mirror of
https://github.com/OPM/ResInsight.git
synced 2025-01-01 03:37:15 -06:00
282 lines
10 KiB
C++
282 lines
10 KiB
C++
/////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// 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 <http://www.gnu.org/licenses/gpl.html>
|
|
// for more details.
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "RimEmCase.h"
|
|
|
|
#include "RiaDefines.h"
|
|
#include "RiaLogging.h"
|
|
#include "RiaPreferences.h"
|
|
|
|
#include "RigActiveCellInfo.h"
|
|
#include "RigCaseCellResultsData.h"
|
|
#include "RigEclipseCaseData.h"
|
|
#include "RigEclipseResultAddress.h"
|
|
#include "RigMainGrid.h"
|
|
#include "RigReservoirBuilder.h"
|
|
|
|
#ifdef USE_HDF5
|
|
#include "H5Cpp.h"
|
|
#endif
|
|
|
|
#include "cafPdmObjectScriptingCapability.h"
|
|
|
|
#include <QDir>
|
|
#include <QFileInfo>
|
|
|
|
CAF_PDM_SOURCE_INIT( RimEmCase, "RimEmCase" );
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RimEmCase::RimEmCase()
|
|
{
|
|
CAF_PDM_InitScriptableObject( "RimEmCase", ":/EclipseInput48x48.png" );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RimEmCase::~RimEmCase()
|
|
{
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
bool RimEmCase::openEclipseGridFile()
|
|
{
|
|
if ( eclipseCaseData() )
|
|
{
|
|
// Early exit if reservoir data is created
|
|
return true;
|
|
}
|
|
|
|
setReservoirData( new RigEclipseCaseData( this ) );
|
|
|
|
auto emDataFromFile = readDataFromFile();
|
|
|
|
auto emData = emDataFromFile;
|
|
|
|
// Flip X and Y axis
|
|
emData.cellSizes[0] = emDataFromFile.cellSizes[1];
|
|
emData.cellSizes[1] = emDataFromFile.cellSizes[0];
|
|
|
|
emData.ijkNumCells[0] = emDataFromFile.ijkNumCells[1];
|
|
emData.ijkNumCells[1] = emDataFromFile.ijkNumCells[0];
|
|
|
|
emData.originNED[0] = emDataFromFile.originNED[1];
|
|
emData.originNED[1] = emDataFromFile.originNED[0];
|
|
|
|
{
|
|
RigReservoirBuilder builder;
|
|
|
|
builder.setWorldCoordinates( cvf::Vec3d( emData.originNED[0], emData.originNED[1], emData.originNED[2] ),
|
|
cvf::Vec3d( emData.originNED[0] + emData.cellSizes[0] * emData.ijkNumCells[0],
|
|
emData.originNED[1] + emData.cellSizes[1] * emData.ijkNumCells[1],
|
|
-( emData.originNED[2] + emData.cellSizes[2] * emData.ijkNumCells[2] ) ) );
|
|
|
|
builder.setIJKCount( cvf::Vec3st( emData.ijkNumCells[0], emData.ijkNumCells[1], emData.ijkNumCells[2] ) );
|
|
builder.createGridsAndCells( eclipseCaseData() );
|
|
}
|
|
|
|
results( RiaDefines::PorosityModelType::MATRIX_MODEL )->createPlaceholderResultEntries();
|
|
|
|
if ( RiaPreferences::current()->autocomputeDepthRelatedProperties )
|
|
{
|
|
results( RiaDefines::PorosityModelType::MATRIX_MODEL )->computeDepthRelatedResults();
|
|
results( RiaDefines::PorosityModelType::FRACTURE_MODEL )->computeDepthRelatedResults();
|
|
}
|
|
|
|
results( RiaDefines::PorosityModelType::MATRIX_MODEL )->computeCellVolumes();
|
|
|
|
{
|
|
// Compute resistivity as the inverted value for sigmaN and sigmaT
|
|
|
|
std::map<std::string, std::vector<float>> additionalData;
|
|
for ( auto [resultName, resultData] : emData.resultData )
|
|
{
|
|
auto fullResultName = QString::fromStdString( resultName );
|
|
auto resultWords = fullResultName.split( "::" );
|
|
auto lastResultName = resultWords.last();
|
|
resultWords.removeLast();
|
|
auto resultNameSpace = resultWords.join( "::" );
|
|
|
|
std::map<QString, QString> invertedResultNameMap = { { "Sigma", "Resistivity" },
|
|
{ "SigmaN", "ResistivityN" },
|
|
{ "SigmaT", "ResistivityT" } };
|
|
|
|
for ( auto [originalName, invertedName] : invertedResultNameMap )
|
|
{
|
|
if ( lastResultName.compare( originalName, Qt::CaseInsensitive ) == 0 )
|
|
{
|
|
std::vector<float> inverted;
|
|
inverted.resize( resultData.size() );
|
|
std::transform( resultData.begin(), resultData.end(), inverted.begin(), []( float val ) { return 1.0f / val; } );
|
|
additionalData[( resultNameSpace + "::" + invertedName ).toStdString()] = inverted;
|
|
}
|
|
}
|
|
}
|
|
|
|
for ( const auto& obj : additionalData )
|
|
{
|
|
emData.resultData[obj.first] = obj.second;
|
|
}
|
|
}
|
|
|
|
for ( auto [resultName, data] : emData.resultData )
|
|
{
|
|
QString riResultName =
|
|
eclipseCaseData()->results( RiaDefines::PorosityModelType::MATRIX_MODEL )->makeResultNameUnique( QString::fromStdString( resultName ) );
|
|
|
|
RigEclipseResultAddress resAddr( RiaDefines::ResultCatType::STATIC_NATIVE, RiaDefines::ResultDataType::FLOAT, riResultName );
|
|
eclipseCaseData()->results( RiaDefines::PorosityModelType::MATRIX_MODEL )->createResultEntry( resAddr, false );
|
|
|
|
auto newPropertyData =
|
|
eclipseCaseData()->results( RiaDefines::PorosityModelType::MATRIX_MODEL )->modifiableCellScalarResultTimesteps( resAddr );
|
|
|
|
std::vector<double> reorganizedData;
|
|
|
|
// Switch cell size ordering from IJK to KJI to make the data layout fit internal ResInsight result ordering
|
|
auto kjiNumCells = emData.ijkNumCells;
|
|
kjiNumCells[0] = emData.ijkNumCells[2];
|
|
kjiNumCells[2] = emData.ijkNumCells[0];
|
|
|
|
for ( int k = 0; k < kjiNumCells[0]; k++ )
|
|
{
|
|
for ( int i = 0; i < kjiNumCells[2]; i++ )
|
|
{
|
|
for ( int j = 0; j < kjiNumCells[1]; j++ )
|
|
{
|
|
reorganizedData.push_back( data[k + j * kjiNumCells[0] + i * kjiNumCells[0] * kjiNumCells[1]] );
|
|
}
|
|
}
|
|
}
|
|
|
|
newPropertyData->push_back( reorganizedData );
|
|
}
|
|
|
|
computeCachedData();
|
|
|
|
return true;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimEmCase::reloadEclipseGridFile()
|
|
{
|
|
setReservoirData( nullptr );
|
|
openReserviorCase();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimEmCase::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
|
|
{
|
|
uiOrdering.add( &m_caseUserDescription );
|
|
uiOrdering.add( &m_displayNameOption );
|
|
uiOrdering.add( &m_caseId );
|
|
uiOrdering.add( &m_caseFileName );
|
|
|
|
auto group = uiOrdering.addNewGroup( "Case Options" );
|
|
group->add( &m_activeFormationNames );
|
|
group->add( &m_flipXAxis );
|
|
group->add( &m_flipYAxis );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RimEmData RimEmCase::readDataFromFile()
|
|
{
|
|
#ifndef USE_HDF5
|
|
return {};
|
|
#else
|
|
|
|
QString fileName = gridFileName();
|
|
|
|
std::array<double, 3> originNED;
|
|
std::array<double, 3> cellSizes;
|
|
std::array<int, 3> ijkNumCells;
|
|
std::map<std::string, std::vector<float>> resultData;
|
|
|
|
try
|
|
{
|
|
H5::Exception::dontPrint(); // Turn off auto-printing of failures to handle the errors appropriately
|
|
|
|
H5::H5File mainFile( fileName.toStdString().c_str(), H5F_ACC_RDONLY );
|
|
|
|
{
|
|
auto attr = mainFile.openAttribute( "description::OriginNED" );
|
|
H5::DataType type = attr.getDataType();
|
|
attr.read( type, originNED.data() );
|
|
}
|
|
|
|
{
|
|
H5::Group group = mainFile.openGroup( "Mesh" );
|
|
|
|
{
|
|
auto attr = group.openAttribute( "cell_sizes" );
|
|
H5::DataType type = attr.getDataType();
|
|
attr.read( type, cellSizes.data() );
|
|
}
|
|
{
|
|
auto attr = group.openAttribute( "num_cells" );
|
|
H5::DataType type = attr.getDataType();
|
|
attr.read( type, ijkNumCells.data() );
|
|
}
|
|
}
|
|
|
|
H5::Group group = mainFile.openGroup( "Data" );
|
|
auto numObj = group.getNumObjs();
|
|
for ( size_t i = 0; i < numObj; i++ )
|
|
{
|
|
auto resultName = group.getObjnameByIdx( i );
|
|
|
|
std::vector<float> resultValues;
|
|
H5::DataSet dataset = H5::DataSet( group.openDataSet( resultName ) );
|
|
|
|
hsize_t dims[3];
|
|
H5::DataSpace dataspace = dataset.getSpace();
|
|
dataspace.getSimpleExtentDims( dims, nullptr );
|
|
|
|
resultValues.resize( dims[0] * dims[1] * dims[2] );
|
|
dataset.read( resultValues.data(), H5::PredType::NATIVE_FLOAT );
|
|
|
|
resultData[resultName] = resultValues;
|
|
}
|
|
}
|
|
catch ( ... )
|
|
{
|
|
}
|
|
|
|
return { originNED, cellSizes, ijkNumCells, resultData };
|
|
#endif
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
QString RimEmCase::locationOnDisc() const
|
|
{
|
|
if ( gridFileName().isEmpty() ) return QString();
|
|
|
|
QFileInfo fi( gridFileName() );
|
|
return fi.absolutePath();
|
|
}
|