///////////////////////////////////////////////////////////////////////////////// // // 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 "RimEclipseInputCase.h" #include "RiaFieldHandleTools.h" #include "RiaLogging.h" #include "RiaPreferences.h" #include "RifEclipseInputFileTools.h" #include "RifReaderEclipseInput.h" #include "RifReaderInterface.h" #include "RifReaderMockModel.h" #include "RifReaderSettings.h" #include "RigActiveCellInfo.h" #include "RigCaseCellResultsData.h" #include "RigEclipseCaseData.h" #include "RigMainGrid.h" #include "RiaDefines.h" #include "RimEclipseInputProperty.h" #include "RimEclipseInputPropertyCollection.h" #include "RimReservoirCellResultsStorage.h" #include "RimTools.h" #include "cafPdmUiTreeOrdering.h" #include "cafProgressInfo.h" #include #include CAF_PDM_SOURCE_INIT( RimEclipseInputCase, "RimInputReservoir" ); //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimEclipseInputCase::RimEclipseInputCase() : RimEclipseCase() { CAF_PDM_InitObject( "RimInputCase", ":/EclipseInput48x48.png", "", "" ); CAF_PDM_InitField( &m_gridFileName, "GridFileName", QString(), "Case File Name", "", "", "" ); m_gridFileName.uiCapability()->setUiReadOnly( true ); CAF_PDM_InitFieldNoDefault( &m_inputPropertyCollection, "InputPropertyCollection", "", "", "", "" ); m_inputPropertyCollection = new RimEclipseInputPropertyCollection; m_inputPropertyCollection->parentField()->uiCapability()->setUiHidden( true ); CAF_PDM_InitFieldNoDefault( &m_additionalFiles, "AdditionalFileNamesProxy", "Additional Files", "", "", "" ); m_additionalFiles.registerGetMethod( this, &RimEclipseInputCase::additionalFiles ); m_additionalFiles.uiCapability()->setUiReadOnly( true ); m_additionalFiles.xmlCapability()->setIOWritable( false ); CAF_PDM_InitFieldNoDefault( &m_additionalFilenames_OBSOLETE, "AdditionalFileNames", "Additional Files", "", "", "" ); m_additionalFilenames_OBSOLETE.uiCapability()->setUiReadOnly( true ); RiaFieldhandleTools::disableWriteAndSetFieldHidden( &m_additionalFilenames_OBSOLETE ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimEclipseInputCase::~RimEclipseInputCase() { delete m_inputPropertyCollection; } //-------------------------------------------------------------------------------------------------- /// Open the supplied file set. If no grid data has been read, it will first find the possible /// grid data among the files then read all supported properties from the files matching the grid //-------------------------------------------------------------------------------------------------- bool RimEclipseInputCase::openDataFileSet( const QStringList& fileNames ) { if ( fileNames.contains( RiaDefines::mockModelBasicInputCase() ) ) { cvf::ref readerInterface = this->createMockModel( fileNames[0] ); results( RiaDefines::MATRIX_MODEL )->setReaderInterface( readerInterface.p() ); results( RiaDefines::FRACTURE_MODEL )->setReaderInterface( readerInterface.p() ); eclipseCaseData()->activeCellInfo( RiaDefines::MATRIX_MODEL )->computeDerivedData(); eclipseCaseData()->activeCellInfo( RiaDefines::FRACTURE_MODEL )->computeDerivedData(); QFileInfo gridFileName( fileNames[0] ); QString caseName = gridFileName.completeBaseName(); this->caseUserDescription = caseName; computeCachedData(); return true; } if ( this->eclipseCaseData() == nullptr ) { this->setReservoirData( new RigEclipseCaseData( this ) ); } bool importFaults = RiaApplication::instance()->preferences()->readerSettings()->importFaults(); std::vector allErrorMessages; // First find and read the grid data if ( this->eclipseCaseData()->mainGrid()->gridPointDimensions() == cvf::Vec3st( 0, 0, 0 ) ) { for ( int i = 0; i < fileNames.size(); i++ ) { QString errorMessages; if ( RifEclipseInputFileTools::openGridFile( fileNames[i], this->eclipseCaseData(), importFaults, &errorMessages ) ) { m_gridFileName = fileNames[i]; QFileInfo gridFileName( fileNames[i] ); QString caseName = gridFileName.completeBaseName(); this->caseUserDescription = caseName; this->eclipseCaseData()->mainGrid()->setFlipAxis( m_flipXAxis, m_flipYAxis ); computeCachedData(); break; } else { allErrorMessages.push_back( errorMessages ); } } } if ( this->eclipseCaseData()->mainGrid()->gridPointDimensions() == cvf::Vec3st( 0, 0, 0 ) ) { if ( !allErrorMessages.empty() ) { for ( QString errorMessages : allErrorMessages ) { RiaLogging::error( errorMessages ); } } return false; // No grid present } std::vector filesToRead; for ( const QString& filename : fileNames ) { bool exists = false; for ( const QString& currentFileName : additionalFiles() ) { if ( filename == currentFileName ) { exists = true; break; } } if ( !exists ) { filesToRead.push_back( filename ); } } for ( const QString& propertyFileName : filesToRead ) { std::map readProperties = RifEclipseInputFileTools::readProperties( propertyFileName, this->eclipseCaseData() ); std::map::iterator it; for ( it = readProperties.begin(); it != readProperties.end(); ++it ) { RimEclipseInputProperty* inputProperty = new RimEclipseInputProperty; inputProperty->resultName = it->first; inputProperty->eclipseKeyword = it->second; inputProperty->fileName = propertyFileName; inputProperty->resolvedState = RimEclipseInputProperty::RESOLVED; m_inputPropertyCollection->inputProperties.push_back( inputProperty ); } if ( importFaults ) { cvf::Collection faultCollection; RifEclipseInputFileTools::parseAndReadFaults( propertyFileName, &faultCollection ); if ( !faultCollection.empty() ) { this->eclipseCaseData()->mainGrid()->setFaults( faultCollection ); } } } return true; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- bool RimEclipseInputCase::openEclipseGridFile() { // Early exit if reservoir data is created if ( this->eclipseCaseData() == nullptr ) { cvf::ref readerInterface; if ( m_gridFileName().contains( RiaDefines::mockModelBasicInputCase() ) ) { readerInterface = this->createMockModel( this->m_gridFileName() ); } else { readerInterface = new RifReaderEclipseInput; cvf::ref eclipseCase = new RigEclipseCaseData( this ); if ( !readerInterface->open( m_gridFileName, eclipseCase.p() ) ) { return false; } this->setReservoirData( eclipseCase.p() ); } CVF_ASSERT( this->eclipseCaseData() ); CVF_ASSERT( readerInterface.notNull() ); results( RiaDefines::MATRIX_MODEL )->setReaderInterface( readerInterface.p() ); results( RiaDefines::FRACTURE_MODEL )->setReaderInterface( readerInterface.p() ); this->eclipseCaseData()->mainGrid()->setFlipAxis( m_flipXAxis, m_flipYAxis ); computeCachedData(); loadAndSyncronizeInputProperties(); } RiaApplication* app = RiaApplication::instance(); if ( app->preferences()->autocomputeDepthRelatedProperties ) { results( RiaDefines::MATRIX_MODEL )->computeDepthRelatedResults(); results( RiaDefines::FRACTURE_MODEL )->computeDepthRelatedResults(); } results( RiaDefines::MATRIX_MODEL )->computeCellVolumes(); return true; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimEclipseInputCase::reloadEclipseGridFile() { setReservoirData( nullptr ); openReserviorCase(); } #define for_all( stdVector, indexName ) for ( size_t indexName = 0; indexName < stdVector.size(); ++indexName ) //-------------------------------------------------------------------------------------------------- /// Loads input property data from the gridFile and additional files /// Creates new InputProperties if necessary, and flags the unused ones as obsolete //-------------------------------------------------------------------------------------------------- void RimEclipseInputCase::loadAndSyncronizeInputProperties() { // Make sure we actually have reservoir data CVF_ASSERT( this->eclipseCaseData() ); CVF_ASSERT( this->eclipseCaseData()->mainGrid()->gridPointDimensions() != cvf::Vec3st( 0, 0, 0 ) ); // Then read the properties from all the files referenced by the InputReservoir std::vector filenames; for ( const QString& fileName : additionalFiles() ) { filenames.push_back( fileName ); } filenames.push_back( m_gridFileName ); size_t inputPropCount = this->m_inputPropertyCollection()->inputProperties.size(); caf::ProgressInfo progInfo( static_cast( filenames.size() * inputPropCount ), "Reading Input properties" ); for_all( filenames, i ) { int progress = static_cast( i * inputPropCount ); // Find all the keywords present on the file progInfo.setProgressDescription( filenames[i] ); QFileInfo fileNameInfo( filenames[i] ); bool isExistingFile = fileNameInfo.exists(); std::set fileKeywordSet; if ( isExistingFile ) { std::vector fileKeywords; RifEclipseInputFileTools::findKeywordsOnFile( filenames[i], &fileKeywords ); for_all( fileKeywords, fkIt ) fileKeywordSet.insert( fileKeywords[fkIt].keyword ); } // Find the input property objects referring to the file std::vector ipsUsingThisFile = this->m_inputPropertyCollection()->findInputProperties( filenames[i] ); // Read property data for each inputProperty for_all( ipsUsingThisFile, ipIdx ) { if ( !isExistingFile ) { ipsUsingThisFile[ipIdx]->resolvedState = RimEclipseInputProperty::FILE_MISSING; } else { QString kw = ipsUsingThisFile[ipIdx]->eclipseKeyword(); ipsUsingThisFile[ipIdx]->resolvedState = RimEclipseInputProperty::KEYWORD_NOT_IN_FILE; if ( fileKeywordSet.count( kw ) ) { if ( RifEclipseInputFileTools::readProperty( filenames[i], this->eclipseCaseData(), kw, ipsUsingThisFile[ipIdx]->resultName ) ) { ipsUsingThisFile[ipIdx]->resolvedState = RimEclipseInputProperty::RESOLVED; } } fileKeywordSet.erase( kw ); } progInfo.setProgress( static_cast( progress + ipIdx ) ); } progInfo.setProgress( static_cast( progress + inputPropCount ) ); // Check if there are more known property keywords left on file. If it is, read them and create inputProperty objects for ( const QString& fileKeyword : fileKeywordSet ) { { QString resultName = this->eclipseCaseData()->results( RiaDefines::MATRIX_MODEL )->makeResultNameUnique( fileKeyword ); if ( RifEclipseInputFileTools::readProperty( filenames[i], this->eclipseCaseData(), fileKeyword, resultName ) ) { RimEclipseInputProperty* inputProperty = new RimEclipseInputProperty; inputProperty->resultName = resultName; inputProperty->eclipseKeyword = fileKeyword; inputProperty->fileName = filenames[i]; inputProperty->resolvedState = RimEclipseInputProperty::RESOLVED; m_inputPropertyCollection->inputProperties.push_back( inputProperty ); } } progInfo.setProgress( static_cast( progress + inputPropCount ) ); } } for_all( m_inputPropertyCollection->inputProperties, i ) { if ( m_inputPropertyCollection->inputProperties[i]->resolvedState() == RimEclipseInputProperty::UNKNOWN ) { m_inputPropertyCollection->inputProperties[i]->resolvedState = RimEclipseInputProperty::FILE_MISSING; } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimEclipseInputPropertyCollection* RimEclipseInputCase::inputPropertyCollection() { return m_inputPropertyCollection(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- cvf::ref RimEclipseInputCase::createMockModel( QString modelName ) { cvf::ref reservoir = new RigEclipseCaseData( this ); cvf::ref mockFileInterface = new RifReaderMockModel; if ( modelName == RiaDefines::mockModelBasicInputCase() ) { m_gridFileName = modelName; // Create the mock file interface and and RigSerervoir and set them up. mockFileInterface->setWorldCoordinates( cvf::Vec3d( 10, 10, 10 ), cvf::Vec3d( 20, 20, 20 ) ); mockFileInterface->setGridPointDimensions( cvf::Vec3st( 4, 5, 6 ) ); mockFileInterface->addLocalGridRefinement( cvf::Vec3st( 0, 2, 2 ), cvf::Vec3st( 0, 2, 2 ), cvf::Vec3st( 3, 3, 3 ) ); mockFileInterface->setResultInfo( 3, 10 ); mockFileInterface->open( "", reservoir.p() ); { // size_t idx = reservoir->mainGrid()->cellIndexFromIJK(1, 3, 4); // TODO: Rewrite active cell info in mock models // reservoir->mainGrid()->cell(idx).setActiveIndexInMatrixModel(cvf::UNDEFINED_SIZE_T); } { // size_t idx = reservoir->mainGrid()->cellIndexFromIJK(2, 2, 3); // TODO: Rewrite active cell info in mock models // reservoir->mainGrid()->cell(idx).setActiveIndexInMatrixModel(cvf::UNDEFINED_SIZE_T); } // Add a property RimEclipseInputProperty* inputProperty = new RimEclipseInputProperty; inputProperty->resultName = "PORO"; inputProperty->eclipseKeyword = "PORO"; inputProperty->fileName = "PORO.prop"; m_inputPropertyCollection->inputProperties.push_back( inputProperty ); } this->setReservoirData( reservoir.p() ); return mockFileInterface.p(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimEclipseInputCase::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) { uiOrdering.add( &caseUserDescription ); uiOrdering.add( &caseId ); uiOrdering.add( &m_gridFileName ); uiOrdering.add( &m_additionalFiles ); auto group = uiOrdering.addNewGroup( "Case Options" ); group->add( &activeFormationNames ); group->add( &m_flipXAxis ); group->add( &m_flipYAxis ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimEclipseInputCase::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName /*= ""*/ ) { uiTreeOrdering.add( &m_inputPropertyCollection ); RimEclipseCase::defineUiTreeOrdering( uiTreeOrdering, uiConfigName ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QString RimEclipseInputCase::locationOnDisc() const { if ( m_gridFileName().isEmpty() ) return QString(); QFileInfo fi( m_gridFileName ); return fi.absolutePath(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimEclipseInputCase::updateFilePathsFromProjectPath( const QString& newProjectPath, const QString& oldProjectPath ) { bool foundFile = false; std::vector searchedPaths; m_gridFileName = RimTools::relocateFile( m_gridFileName(), newProjectPath, oldProjectPath, &foundFile, &searchedPaths ); for ( RimEclipseInputProperty* inputProperty : m_inputPropertyCollection()->inputProperties() ) { inputProperty->fileName = RimTools::relocateFile( inputProperty->fileName, newProjectPath, oldProjectPath, &foundFile, &searchedPaths ); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimEclipseInputCase::updateAdditionalFileFolder( const QString& newFolder ) { QDir newDir( newFolder ); for ( RimEclipseInputProperty* inputProperty : m_inputPropertyCollection()->inputProperties() ) { if ( inputProperty->fileName == m_gridFileName ) continue; QFileInfo oldFilePath( inputProperty->fileName ); QFileInfo newFilePath( newDir, oldFilePath.fileName() ); inputProperty->fileName = newFilePath.absoluteFilePath(); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector RimEclipseInputCase::additionalFiles() const { std::vector additionalFiles; for ( const RimEclipseInputProperty* inputProperty : m_inputPropertyCollection()->inputProperties() ) { if ( inputProperty->fileName == m_gridFileName ) continue; additionalFiles.push_back( inputProperty->fileName ); } return additionalFiles; }