///////////////////////////////////////////////////////////////////////////////// // // 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 "RigWellPathFormations.h" #include "QStringList" //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RigWellPathFormations::RigWellPathFormations( const std::vector& formations, const QString& filePath, const QString& key ) { m_filePath = filePath; m_keyInFile = key; for ( const RigWellPathFormation& formation : formations ) { if ( isFluid( formation.formationName ) ) { m_fluids.push_back( formation ); } else { FormationLevel level = detectLevel( formation.formationName ); m_formationsLevelsPresent[level] = true; m_formations.push_back( std::pair( formation, level ) ); } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RigWellPathFormations::depthAndFormationNamesWithoutDuplicatesOnDepth( std::vector* names, std::vector* measuredDepths, RimWellLogPlot::DepthTypeEnum depthType ) const { std::map tempMakeVectorUniqueOnMeasuredDepth; if ( depthType == RiaDefines::DepthTypeEnum::MEASURED_DEPTH ) { for ( const std::pair& formation : m_formations ) { if ( !tempMakeVectorUniqueOnMeasuredDepth.count( formation.first.mdTop ) ) { measuredDepths->push_back( formation.first.mdTop ); names->push_back( formation.first.formationName + " Top" ); tempMakeVectorUniqueOnMeasuredDepth[formation.first.mdTop] = true; } } for ( const std::pair& formation : m_formations ) { if ( !tempMakeVectorUniqueOnMeasuredDepth.count( formation.first.mdBase ) ) { measuredDepths->push_back( formation.first.mdBase ); names->push_back( formation.first.formationName + " Base" ); tempMakeVectorUniqueOnMeasuredDepth[formation.first.mdBase] = true; } } } else if ( depthType == RiaDefines::DepthTypeEnum::TRUE_VERTICAL_DEPTH ) { for ( const std::pair& formation : m_formations ) { if ( !tempMakeVectorUniqueOnMeasuredDepth.count( formation.first.tvdTop ) ) { measuredDepths->push_back( formation.first.tvdTop ); names->push_back( formation.first.formationName + " Top" ); tempMakeVectorUniqueOnMeasuredDepth[formation.first.tvdTop] = true; } } for ( const std::pair& formation : m_formations ) { if ( !tempMakeVectorUniqueOnMeasuredDepth.count( formation.first.tvdBase ) ) { measuredDepths->push_back( formation.first.tvdBase ); names->push_back( formation.first.formationName + " Base" ); tempMakeVectorUniqueOnMeasuredDepth[formation.first.tvdBase] = true; } } } /* for (const std::pair& formation : m_formations) { if (!tempMakeVectorUniqueOnMeasuredDepth.count(formation.first.mdTop)) { double depth; if (depthType == RiaDefines::MEASURED_DEPTH) { depth = formation.first.mdTop; } else if (depthType == RiaDefines::TRUE_VERTICAL_DEPTH) { depth = formation.first.tvdTop; } else return; measuredDepths->push_back(depth); names->push_back(formation.first.formationName + " Top"); tempMakeVectorUniqueOnMeasuredDepth[depth] = true; } } for (const std::pair& formation : m_formations) { double depth; if (depthType == RiaDefines::MEASURED_DEPTH) { depth = formation.first.mdBase; } else if (depthType == RiaDefines::TRUE_VERTICAL_DEPTH) { depth = formation.first.tvdBase; } else return; if (!tempMakeVectorUniqueOnMeasuredDepth.count(formation.first.mdBase)) { measuredDepths->push_back(depth); names->push_back(formation.first.formationName + " Base"); tempMakeVectorUniqueOnMeasuredDepth[depth] = true; } }*/ } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RigWellPathFormations::evaluateFormationsForOnePosition( const std::vector>& formations, const FormationLevel& maxLevel, const PickPosition& position, std::map* uniqueListMaker, RimWellLogPlot::DepthTypeEnum depthType ) const { QString postFix; if ( position == TOP ) { postFix = " Top"; } else { postFix = " Base"; } for ( const std::pair& formation : formations ) { double depth; if ( depthType == RiaDefines::DepthTypeEnum::MEASURED_DEPTH ) { if ( position == TOP ) { depth = formation.first.mdTop; } else { depth = formation.first.mdBase; } } else if ( depthType == RiaDefines::DepthTypeEnum::TRUE_VERTICAL_DEPTH ) { if ( position == TOP ) { depth = formation.first.tvdTop; } else { depth = formation.first.tvdBase; } } else return; if ( formation.second > maxLevel ) continue; if ( !uniqueListMaker->count( depth ) || uniqueListMaker->at( depth ).level < formation.second ) { ( *uniqueListMaker )[depth] = LevelAndName( formation.second, formation.first.formationName + postFix ); } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RigWellPathFormations::evaluateFormations( const std::vector>& formations, const FormationLevel& maxLevel, std::vector* names, std::vector* depths, RimWellLogPlot::DepthTypeEnum depthType ) const { std::map tempMakeVectorUniqueOnDepth; evaluateFormationsForOnePosition( formations, maxLevel, PickPosition::TOP, &tempMakeVectorUniqueOnDepth, depthType ); evaluateFormationsForOnePosition( formations, maxLevel, PickPosition::BASE, &tempMakeVectorUniqueOnDepth, depthType ); for ( const std::pair& uniqueDepth : tempMakeVectorUniqueOnDepth ) { depths->push_back( uniqueDepth.first ); names->push_back( uniqueDepth.second.name ); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RigWellPathFormations::evaluateFluids( const std::vector& fluidFormations, std::vector* names, std::vector* depths, RimWellLogPlot::DepthTypeEnum depthType ) const { std::map uniqueListMaker; for ( const RigWellPathFormation& formation : fluidFormations ) { double depthBase; if ( depthType == RiaDefines::DepthTypeEnum::MEASURED_DEPTH ) { depthBase = formation.mdBase; } else if ( depthType == RiaDefines::DepthTypeEnum::TRUE_VERTICAL_DEPTH ) { depthBase = formation.tvdBase; } else return; uniqueListMaker[depthBase] = formation.formationName + " Base"; } for ( const RigWellPathFormation& formation : fluidFormations ) { double depthTop; if ( depthType == RiaDefines::DepthTypeEnum::MEASURED_DEPTH ) { depthTop = formation.mdTop; } else if ( depthType == RiaDefines::DepthTypeEnum::TRUE_VERTICAL_DEPTH ) { depthTop = formation.tvdTop; } else return; uniqueListMaker[depthTop] = formation.formationName + " Top"; } for ( const std::pair& depthAndFormation : uniqueListMaker ) { depths->push_back( depthAndFormation.first ); names->push_back( depthAndFormation.second ); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RigWellPathFormations::depthAndFormationNamesUpToLevel( FormationLevel level, std::vector* names, std::vector* depths, bool includeFluids, RimWellLogPlot::DepthTypeEnum depthType ) const { names->clear(); depths->clear(); if ( includeFluids ) { evaluateFluids( m_fluids, names, depths, depthType ); } if ( level == RigWellPathFormations::NONE ) { return; } else if ( level == RigWellPathFormations::ALL ) { depthAndFormationNamesWithoutDuplicatesOnDepth( names, depths, depthType ); } else { evaluateFormations( m_formations, level, names, depths, depthType ); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector RigWellPathFormations::formationsLevelsPresent() const { std::vector formationLevels; for ( const std::pair& formationLevel : m_formationsLevelsPresent ) { formationLevels.push_back( formationLevel.first ); } return formationLevels; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QString RigWellPathFormations::filePath() const { return m_filePath; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QString RigWellPathFormations::keyInFile() const { return m_keyInFile; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- size_t RigWellPathFormations::formationNamesCount() const { return m_formations.size() + m_fluids.size(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- bool RigWellPathFormations::isFluid( QString formationName ) { formationName = formationName.trimmed(); if ( formationName == "OIL" || formationName == "GAS" || formationName == "WATER" ) { return true; } return false; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RigWellPathFormations::FormationLevel RigWellPathFormations::detectLevel( QString formationName ) { formationName = formationName.trimmed(); bool isGroupName = true; for ( QChar c : formationName ) { if ( c.isLower() ) { isGroupName = false; break; } } if ( isGroupName ) { return RigWellPathFormations::GROUP; } QStringList formationNameSplitted = formationName.split( " " ); std::vector levelDesctiptorCandidates; for ( QString word : formationNameSplitted ) { for ( const QChar& c : word ) { if ( c.isDigit() ) { levelDesctiptorCandidates.push_back( word ); break; } } } if ( levelDesctiptorCandidates.empty() ) { return RigWellPathFormations::LEVEL0; } if ( levelDesctiptorCandidates.size() > 1 ) { for ( auto it = levelDesctiptorCandidates.begin(); it != levelDesctiptorCandidates.end(); it++ ) { for ( const QChar& c : *it ) { if ( c.isLetter() ) { levelDesctiptorCandidates.erase( it ); } } } } if ( levelDesctiptorCandidates.size() != 1 ) return RigWellPathFormations::UNKNOWN; QString levelDescriptor = levelDesctiptorCandidates[0]; QStringList joinedLevel = levelDescriptor.split( '+' ); if ( joinedLevel.size() > 1 ) { levelDescriptor = joinedLevel[0]; } int dotCount = levelDescriptor.count( '.' ); switch ( dotCount ) { case 0: return RigWellPathFormations::LEVEL1; case 1: return RigWellPathFormations::LEVEL2; case 2: return RigWellPathFormations::LEVEL3; case 3: return RigWellPathFormations::LEVEL4; case 4: return RigWellPathFormations::LEVEL5; case 5: return RigWellPathFormations::LEVEL6; case 6: return RigWellPathFormations::LEVEL7; case 7: return RigWellPathFormations::LEVEL8; case 8: return RigWellPathFormations::LEVEL9; case 9: return RigWellPathFormations::LEVEL10; default: break; } return RigWellPathFormations::UNKNOWN; }