Rename ApplicationCode to ApplicationLibCode

This commit is contained in:
Gaute Lindkvist
2021-01-06 14:55:29 +01:00
parent 751df1a421
commit 81699db187
3242 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,671 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RiaSocketCommand.h"
#include "RiaPreferences.h"
#include "RiaSocketServer.h"
#include "RiaSocketTools.h"
#include "RigActiveCellInfo.h"
#include "RigCaseCellResultsData.h"
#include "RigEclipseCaseData.h"
#include "RigFemPart.h"
#include "RigFemPartCollection.h"
#include "RigFemPartGrid.h"
#include "RigGeoMechCaseData.h"
#include "RigMainGrid.h"
#include "Rim3dOverlayInfoConfig.h"
#include "RimCellEdgeColors.h"
#include "RimCellRangeFilterCollection.h"
#include "RimEclipseCase.h"
#include "RimEclipseCellColors.h"
#include "RimEclipsePropertyFilterCollection.h"
#include "RimEclipseView.h"
#include "RimGeoMechCase.h"
#include "RimGeoMechView.h"
#include "RimReservoirCellResultsStorage.h"
#include "RimSimWellInViewCollection.h"
#include "Riu3dSelectionManager.h"
#include <QTcpSocket>
#include "RimGeoMechResultDefinition.h"
#include <array>
//--------------------------------------------------------------------------------------------------
/// OBSOLETE, to be deleted
//--------------------------------------------------------------------------------------------------
class RiaGetMainGridDimensions : public RiaSocketCommand
{
public:
static QString commandName() { return QString( "GetMainGridDimensions" ); }
bool interpretCommand( RiaSocketServer* server, const QList<QByteArray>& args, QDataStream& socketStream ) override
{
RimEclipseCase* rimCase = RiaSocketTools::findCaseFromArgs( server, args );
if ( !rimCase ) return true;
// Write data back to octave: I, J, K dimensions
size_t iCount = 0;
size_t jCount = 0;
size_t kCount = 0;
if ( rimCase && rimCase->eclipseCaseData() && rimCase->eclipseCaseData()->mainGrid() )
{
iCount = rimCase->eclipseCaseData()->mainGrid()->cellCountI();
jCount = rimCase->eclipseCaseData()->mainGrid()->cellCountJ();
kCount = rimCase->eclipseCaseData()->mainGrid()->cellCountK();
}
socketStream << (quint64)iCount << (quint64)jCount << (quint64)kCount;
return true;
}
};
static bool RiaGetMainGridDimensions_init = RiaSocketCommandFactory::instance()->registerCreator<RiaGetMainGridDimensions>(
RiaGetMainGridDimensions::commandName() );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
class RiaGetActiveCellInfo : public RiaSocketCommand
{
public:
static QString commandName() { return QString( "GetActiveCellInfo" ); }
bool interpretCommand( RiaSocketServer* server, const QList<QByteArray>& args, QDataStream& socketStream ) override
{
RimEclipseCase* rimCase = RiaSocketTools::findCaseFromArgs( server, args );
if ( !rimCase ) return true;
RiaDefines::PorosityModelType porosityModel = RiaDefines::PorosityModelType::MATRIX_MODEL;
if ( args.size() > 2 )
{
QString prorosityModelString = args[2];
if ( prorosityModelString.toUpper() == "FRACTURE" )
{
porosityModel = RiaDefines::PorosityModelType::FRACTURE_MODEL;
}
}
// Write data back to octave: columnCount, bytesPrTimestep, GridNr I J K ParentGridNr PI PJ PK CoarseBoxIdx
std::array<std::vector<qint32>, 9> activeCellInfo;
if ( !( rimCase && rimCase->eclipseCaseData() && rimCase->eclipseCaseData()->mainGrid() ) )
{
// No data available
socketStream << (quint64)0 << (quint64)0;
return true;
}
calculateMatrixModelActiveCellInfo( rimCase,
porosityModel,
activeCellInfo[0],
activeCellInfo[1],
activeCellInfo[2],
activeCellInfo[3],
activeCellInfo[4],
activeCellInfo[5],
activeCellInfo[6],
activeCellInfo[7],
activeCellInfo[8] );
// First write column count
quint64 columnCount = (quint64)9;
socketStream << columnCount;
// then the byte-size of the size of one column
size_t timestepResultCount = activeCellInfo[0].size();
quint64 timestepByteCount = ( quint64 )( timestepResultCount * sizeof( qint32 ) );
socketStream << timestepByteCount;
for ( size_t tIdx = 0; tIdx < columnCount; ++tIdx )
{
RiaSocketTools::writeBlockData( server,
server->currentClient(),
(const char*)activeCellInfo[tIdx].data(),
timestepByteCount );
}
return true;
}
static void calculateMatrixModelActiveCellInfo( RimEclipseCase* reservoirCase,
RiaDefines::PorosityModelType porosityModel,
std::vector<qint32>& gridNumber,
std::vector<qint32>& cellI,
std::vector<qint32>& cellJ,
std::vector<qint32>& cellK,
std::vector<qint32>& parentGridNumber,
std::vector<qint32>& hostCellI,
std::vector<qint32>& hostCellJ,
std::vector<qint32>& hostCellK,
std::vector<qint32>& globalCoarseningBoxIdx )
{
gridNumber.clear();
cellI.clear();
cellJ.clear();
cellK.clear();
parentGridNumber.clear();
hostCellI.clear();
hostCellJ.clear();
hostCellK.clear();
globalCoarseningBoxIdx.clear();
if ( !reservoirCase || !reservoirCase->eclipseCaseData() || !reservoirCase->eclipseCaseData()->mainGrid() )
{
return;
}
RigActiveCellInfo* actCellInfo = reservoirCase->eclipseCaseData()->activeCellInfo( porosityModel );
size_t numMatrixModelActiveCells = actCellInfo->reservoirActiveCellCount();
gridNumber.reserve( numMatrixModelActiveCells );
cellI.reserve( numMatrixModelActiveCells );
cellJ.reserve( numMatrixModelActiveCells );
cellK.reserve( numMatrixModelActiveCells );
parentGridNumber.reserve( numMatrixModelActiveCells );
hostCellI.reserve( numMatrixModelActiveCells );
hostCellJ.reserve( numMatrixModelActiveCells );
hostCellK.reserve( numMatrixModelActiveCells );
globalCoarseningBoxIdx.reserve( numMatrixModelActiveCells );
const std::vector<RigCell>& reservoirCells = reservoirCase->eclipseCaseData()->mainGrid()->globalCellArray();
std::vector<size_t> globalCoarseningBoxIndexStart;
{
size_t globalCoarseningBoxCount = 0;
for ( size_t gridIdx = 0; gridIdx < reservoirCase->eclipseCaseData()->gridCount(); gridIdx++ )
{
globalCoarseningBoxIndexStart.push_back( globalCoarseningBoxCount );
RigGridBase* grid = reservoirCase->eclipseCaseData()->grid( gridIdx );
size_t localCoarseningBoxCount = grid->coarseningBoxCount();
globalCoarseningBoxCount += localCoarseningBoxCount;
}
}
for ( size_t cIdx = 0; cIdx < reservoirCells.size(); ++cIdx )
{
if ( actCellInfo->isActive( cIdx ) )
{
RigGridBase* grid = reservoirCells[cIdx].hostGrid();
CVF_ASSERT( grid != nullptr );
size_t cellIndex = reservoirCells[cIdx].gridLocalCellIndex();
size_t i, j, k;
grid->ijkFromCellIndex( cellIndex, &i, &j, &k );
size_t pi, pj, pk;
RigGridBase* parentGrid = nullptr;
if ( grid->isMainGrid() )
{
pi = i;
pj = j;
pk = k;
parentGrid = grid;
}
else
{
size_t parentCellIdx = reservoirCells[cIdx].parentCellIndex();
parentGrid = ( static_cast<RigLocalGrid*>( grid ) )->parentGrid();
CVF_ASSERT( parentGrid != nullptr );
parentGrid->ijkFromCellIndex( parentCellIdx, &pi, &pj, &pk );
}
gridNumber.push_back( static_cast<qint32>( grid->gridIndex() ) );
cellI.push_back( static_cast<qint32>( i + 1 ) ); // NB: 1-based index in Octave
cellJ.push_back( static_cast<qint32>( j + 1 ) ); // NB: 1-based index in Octave
cellK.push_back( static_cast<qint32>( k + 1 ) ); // NB: 1-based index in Octave
parentGridNumber.push_back( static_cast<qint32>( parentGrid->gridIndex() ) );
hostCellI.push_back( static_cast<qint32>( pi + 1 ) ); // NB: 1-based index in Octave
hostCellJ.push_back( static_cast<qint32>( pj + 1 ) ); // NB: 1-based index in Octave
hostCellK.push_back( static_cast<qint32>( pk + 1 ) ); // NB: 1-based index in Octave
size_t coarseningIdx = reservoirCells[cIdx].coarseningBoxIndex();
if ( coarseningIdx != cvf::UNDEFINED_SIZE_T )
{
size_t globalCoarseningIdx = globalCoarseningBoxIndexStart[grid->gridIndex()] + coarseningIdx;
globalCoarseningBoxIdx.push_back( static_cast<qint32>( globalCoarseningIdx + 1 ) ); // NB: 1-based
// index in Octave
}
else
{
globalCoarseningBoxIdx.push_back( -1 );
}
}
}
}
};
static bool RiaGetActiveCellInfo_init =
RiaSocketCommandFactory::instance()->registerCreator<RiaGetActiveCellInfo>( RiaGetActiveCellInfo::commandName() );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
class RiaGetCoarseningInfo : public RiaSocketCommand
{
public:
static QString commandName() { return QString( "GetCoarseningInfo" ); }
bool interpretCommand( RiaSocketServer* server, const QList<QByteArray>& args, QDataStream& socketStream ) override
{
int argCaseGroupId = -1;
if ( args.size() == 2 )
{
argCaseGroupId = args[1].toInt();
}
RimEclipseCase* rimCase = server->findReservoir( argCaseGroupId );
if ( !rimCase || !rimCase->eclipseCaseData() || !rimCase->eclipseCaseData()->mainGrid() )
{
quint64 byteCount = 0;
socketStream << byteCount;
return true;
}
// Write data back to octave: I1, I2, J1, J2, K1, K2 for all coarsening boxes
if ( rimCase && rimCase->eclipseCaseData() && rimCase->eclipseCaseData()->mainGrid() )
{
size_t globalCoarseningBoxCount = 0;
for ( size_t gridIdx = 0; gridIdx < rimCase->eclipseCaseData()->gridCount(); gridIdx++ )
{
RigGridBase* grid = rimCase->eclipseCaseData()->grid( gridIdx );
size_t localCoarseningBoxCount = grid->coarseningBoxCount();
globalCoarseningBoxCount += localCoarseningBoxCount;
}
quint64 byteCount = globalCoarseningBoxCount * 6 * sizeof( qint32 );
socketStream << byteCount;
for ( size_t gridIdx = 0; gridIdx < rimCase->eclipseCaseData()->gridCount(); gridIdx++ )
{
RigGridBase* grid = rimCase->eclipseCaseData()->grid( gridIdx );
size_t localCoarseningBoxCount = grid->coarseningBoxCount();
for ( size_t boxIdx = 0; boxIdx < localCoarseningBoxCount; boxIdx++ )
{
size_t i1, i2, j1, j2, k1, k2;
grid->coarseningBox( boxIdx, &i1, &i2, &j1, &j2, &k1, &k2 );
// Write 1-based coordinates for coarsening box
socketStream << static_cast<qint32>( i1 + 1 );
socketStream << static_cast<qint32>( i2 + 1 );
socketStream << static_cast<qint32>( j1 + 1 );
socketStream << static_cast<qint32>( j2 + 1 );
socketStream << static_cast<qint32>( k1 + 1 );
socketStream << static_cast<qint32>( k2 + 1 );
}
}
}
return true;
}
};
static bool RiaGetCoarseningInfo_init =
RiaSocketCommandFactory::instance()->registerCreator<RiaGetCoarseningInfo>( RiaGetCoarseningInfo::commandName() );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
class RiaGetGridDimensions : public RiaSocketCommand
{
public:
static QString commandName() { return QString( "GetGridDimensions" ); }
bool interpretCommand( RiaSocketServer* server, const QList<QByteArray>& args, QDataStream& socketStream ) override
{
int argCaseGroupId = -1;
if ( args.size() == 2 )
{
argCaseGroupId = args[1].toInt();
}
RimEclipseCase* rimCase = server->findReservoir( argCaseGroupId );
if ( !rimCase || !rimCase->eclipseCaseData() || !rimCase->eclipseCaseData()->mainGrid() )
{
quint64 byteCount = 0;
socketStream << byteCount;
return true;
}
// Write data back to octave: I, J, K dimensions
if ( rimCase && rimCase->eclipseCaseData() && rimCase->eclipseCaseData()->mainGrid() )
{
std::vector<RigGridBase*> grids;
rimCase->eclipseCaseData()->allGrids( &grids );
quint64 byteCount = grids.size() * 3 * sizeof( quint64 );
socketStream << byteCount;
for ( size_t i = 0; i < grids.size(); i++ )
{
size_t iCount = 0;
size_t jCount = 0;
size_t kCount = 0;
iCount = grids[i]->cellCountI();
jCount = grids[i]->cellCountJ();
kCount = grids[i]->cellCountK();
socketStream << (quint64)iCount << (quint64)jCount << (quint64)kCount;
}
}
return true;
}
};
static bool RiaGetGridDimensions_init =
RiaSocketCommandFactory::instance()->registerCreator<RiaGetGridDimensions>( RiaGetGridDimensions::commandName() );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
class RiaGetTimeStepDates : public RiaSocketCommand
{
public:
static QString commandName() { return QString( "GetTimeStepDates" ); }
bool interpretCommand( RiaSocketServer* server, const QList<QByteArray>& args, QDataStream& socketStream ) override
{
int argCaseGroupId = -1;
if ( args.size() == 2 )
{
argCaseGroupId = args[1].toInt();
}
RimEclipseCase* rimCase = server->findReservoir( argCaseGroupId );
bool canFetchData = true;
if ( !rimCase || !rimCase->eclipseCaseData() )
{
canFetchData = false;
}
RigEclipseResultAddress addrToMaxTimeStepCountResult;
if ( rimCase && rimCase->eclipseCaseData() )
{
rimCase->eclipseCaseData()
->results( RiaDefines::PorosityModelType::MATRIX_MODEL )
->maxTimeStepCount( &addrToMaxTimeStepCountResult );
if ( !addrToMaxTimeStepCountResult.isValid() )
{
canFetchData = false;
}
}
// Did not find any result to fetch data from, return zero data found
if ( !canFetchData )
{
quint64 timeStepCount = 0;
quint64 byteCount = sizeof( quint64 );
socketStream << byteCount;
socketStream << timeStepCount;
return true;
}
std::vector<QDateTime> timeStepDates =
rimCase->eclipseCaseData()
->results( RiaDefines::PorosityModelType::MATRIX_MODEL )
->timeStepDates( RigEclipseResultAddress( addrToMaxTimeStepCountResult ) );
quint64 timeStepCount = timeStepDates.size();
quint64 byteCount = sizeof( quint64 ) + 6 * timeStepCount * sizeof( qint32 );
socketStream << byteCount;
socketStream << timeStepCount;
for ( size_t i = 0; i < timeStepCount; i++ )
{
qint32 intValue = 0;
intValue = timeStepDates[i].date().year();
socketStream << intValue;
intValue = timeStepDates[i].date().month();
socketStream << intValue;
intValue = timeStepDates[i].date().day();
socketStream << intValue;
intValue = timeStepDates[i].time().hour();
socketStream << intValue;
intValue = timeStepDates[i].time().minute();
socketStream << intValue;
intValue = timeStepDates[i].time().second();
socketStream << intValue;
}
return true;
}
};
static bool RiaGetTimeStepDates_init =
RiaSocketCommandFactory::instance()->registerCreator<RiaGetTimeStepDates>( RiaGetTimeStepDates::commandName() );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
class RiaGetTimeStepDays : public RiaSocketCommand
{
public:
static QString commandName() { return QString( "GetTimeStepDays" ); }
bool interpretCommand( RiaSocketServer* server, const QList<QByteArray>& args, QDataStream& socketStream ) override
{
int argCaseGroupId = -1;
if ( args.size() == 2 )
{
argCaseGroupId = args[1].toInt();
}
RimEclipseCase* rimCase = server->findReservoir( argCaseGroupId );
bool canFetchData = true;
if ( !rimCase || !rimCase->eclipseCaseData() )
{
canFetchData = false;
}
RigEclipseResultAddress addrToMaxTimeStepCountResult;
if ( rimCase && rimCase->eclipseCaseData() )
{
rimCase->eclipseCaseData()
->results( RiaDefines::PorosityModelType::MATRIX_MODEL )
->maxTimeStepCount( &addrToMaxTimeStepCountResult );
if ( !addrToMaxTimeStepCountResult.isValid() )
{
canFetchData = false;
}
}
// Did not find any result to fetch data from, return zero data found
if ( !canFetchData )
{
quint64 timeStepCount = 0;
quint64 byteCount = sizeof( quint64 );
socketStream << byteCount;
socketStream << timeStepCount;
return true;
}
std::vector<double> daysSinceSimulationStart = rimCase->eclipseCaseData()
->results( RiaDefines::PorosityModelType::MATRIX_MODEL )
->daysSinceSimulationStart( addrToMaxTimeStepCountResult );
quint64 timeStepCount = daysSinceSimulationStart.size();
quint64 byteCount = sizeof( quint64 ) + timeStepCount * sizeof( qint32 );
socketStream << byteCount;
socketStream << timeStepCount;
for ( double day : daysSinceSimulationStart )
{
socketStream << day;
}
return true;
}
};
static bool RiaGetTimeStepDays_init =
RiaSocketCommandFactory::instance()->registerCreator<RiaGetTimeStepDays>( RiaGetTimeStepDays::commandName() );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
class RiaGetSelectedCells : public RiaSocketCommand
{
public:
static QString commandName() { return QString( "GetSelectedCells" ); }
bool interpretCommand( RiaSocketServer* server, const QList<QByteArray>& args, QDataStream& socketStream ) override
{
// findCaseFromArgs only returns RimEclipseCase, so geomech cases are not supported because of this.
// The rest of the function supports geomech cases, so using a findCaseFromArgs that supports geomech
// cases is the only change needed to add geomech support.
RimEclipseCase* rimCase = RiaSocketTools::findCaseFromArgs( server, args );
if ( !rimCase ) return true;
// Write data back to octave: column count, bytes per column, caseId, gridNumber, cellI, cellJ, cellK
std::array<std::vector<qint32>, 5> selectedCellInfo;
getSelectedCells( rimCase,
selectedCellInfo[0],
selectedCellInfo[1],
selectedCellInfo[2],
selectedCellInfo[3],
selectedCellInfo[4] );
// First write column count
quint64 columnCount = 5;
socketStream << columnCount;
// then the byte-size of the size of one column
quint64 columnByteCount = ( quint64 )( selectedCellInfo[0].size() * sizeof( qint32 ) );
socketStream << columnByteCount;
// Write back table data
for ( size_t tIdx = 0; tIdx < columnCount; ++tIdx )
{
RiaSocketTools::writeBlockData( server,
server->currentClient(),
(const char*)selectedCellInfo[tIdx].data(),
columnByteCount );
}
return true;
}
static void getSelectedCells( const RimCase* reservoirCase,
std::vector<qint32>& caseNumber,
std::vector<qint32>& gridNumber,
std::vector<qint32>& cellI,
std::vector<qint32>& cellJ,
std::vector<qint32>& cellK )
{
std::vector<RiuSelectionItem*> items;
Riu3dSelectionManager::instance()->selectedItems( items );
for ( const RiuSelectionItem* item : items )
{
size_t i, j, k;
size_t gridIndex;
int caseId;
bool validIndex = true;
if ( item->type() == RiuSelectionItem::ECLIPSE_SELECTION_OBJECT )
{
const RiuEclipseSelectionItem* eclipseItem = static_cast<const RiuEclipseSelectionItem*>( item );
eclipseItem->m_resultDefinition->eclipseCase()
->eclipseCaseData()
->grid( eclipseItem->m_gridIndex )
->ijkFromCellIndex( eclipseItem->m_gridLocalCellIndex, &i, &j, &k );
gridIndex = eclipseItem->m_gridIndex;
caseId = eclipseItem->m_resultDefinition->eclipseCase()->caseId;
}
else if ( item->type() == RiuSelectionItem::GEOMECH_SELECTION_OBJECT )
{
const RiuGeoMechSelectionItem* geomechItem = static_cast<const RiuGeoMechSelectionItem*>( item );
validIndex = geomechItem->m_resultDefinition->ownerCaseData()
->femParts()
->part( geomechItem->m_gridIndex )
->getOrCreateStructGrid()
->ijkFromCellIndex( geomechItem->m_cellIndex, &i, &j, &k );
CVF_ASSERT( validIndex );
gridIndex = geomechItem->m_gridIndex;
caseId = geomechItem->m_resultDefinition->geoMechCase()->caseId;
}
else
{
continue;
}
if ( caseId == reservoirCase->caseId && validIndex )
{
caseNumber.push_back( static_cast<int>( caseId ) );
gridNumber.push_back( static_cast<int>( gridIndex ) );
cellI.push_back( static_cast<int>( i + 1 ) );
cellJ.push_back( static_cast<int>( j + 1 ) );
cellK.push_back( static_cast<int>( k + 1 ) );
}
}
}
};
static bool RiaGetSelectedCells_init =
RiaSocketCommandFactory::instance()->registerCreator<RiaGetSelectedCells>( RiaGetSelectedCells::commandName() );

View File

@@ -0,0 +1,411 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RiaSocketCommand.h"
#include "RiaPreferences.h"
#include "RiaSocketServer.h"
#include "RiaSocketTools.h"
#include "RigActiveCellInfo.h"
#include "RigCaseCellResultsData.h"
#include "RigEclipseCaseData.h"
#include "RigMainGrid.h"
#include "Rim3dOverlayInfoConfig.h"
#include "RimCellEdgeColors.h"
#include "RimCellRangeFilterCollection.h"
#include "RimEclipseCase.h"
#include "RimEclipseCellColors.h"
#include "RimEclipsePropertyFilterCollection.h"
#include "RimEclipseView.h"
#include "RimReservoirCellResultsStorage.h"
#include "RimSimWellInViewCollection.h"
#include <QTcpSocket>
//--------------------------------------------------------------------------------------------------
/// Convert internal ResInsight representation of cells with negative depth to positive depth.
//--------------------------------------------------------------------------------------------------
static inline void convertVec3dToPositiveDepth( cvf::Vec3d* vec )
{
double& z = vec->z();
z *= -1;
}
//--------------------------------------------------------------------------------------------------
/// Retrieve a cell corner where the depth is represented as negative converted to positive depth.
//--------------------------------------------------------------------------------------------------
static inline double getCellCornerWithPositiveDepth( const cvf::Vec3d* cornerVerts, size_t cornerIndexMapping, int coordIdx )
{
if ( coordIdx == 2 )
{
// Z-value aka depth
return -1 * cornerVerts[cornerIndexMapping][coordIdx];
}
else
{
return cornerVerts[cornerIndexMapping][coordIdx];
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
class RiaGetCellCenters : public RiaSocketCommand
{
public:
static QString commandName() { return QString( "GetCellCenters" ); }
bool interpretCommand( RiaSocketServer* server, const QList<QByteArray>& args, QDataStream& socketStream ) override
{
RimEclipseCase* rimCase = RiaSocketTools::findCaseFromArgs( server, args );
size_t argGridIndex = args[2].toUInt();
if ( !rimCase || !rimCase->eclipseCaseData() || ( argGridIndex >= rimCase->eclipseCaseData()->gridCount() ) )
{
// No data available
socketStream << (quint64)0 << (quint64)0 << (quint64)0 << (quint64)0 << (quint64)0;
return true;
}
RigGridBase* rigGrid = rimCase->eclipseCaseData()->grid( argGridIndex );
quint64 cellCount = (quint64)rigGrid->cellCount();
quint64 cellCountI = (quint64)rigGrid->cellCountI();
quint64 cellCountJ = (quint64)rigGrid->cellCountJ();
quint64 cellCountK = (quint64)rigGrid->cellCountK();
socketStream << cellCount;
socketStream << cellCountI;
socketStream << cellCountJ;
socketStream << cellCountK;
size_t doubleValueCount = cellCount * 3;
quint64 byteCount = doubleValueCount * sizeof( double );
socketStream << byteCount;
// This structure is supposed to be received by Octave using a NDArray. The ordering of this loop is
// defined by the ordering of the receiving NDArray
//
// See riGetCellCenters
//
// dim_vector dv;
// dv.resize(4);
// dv(0) = cellCountI;
// dv(1) = cellCountJ;
// dv(2) = cellCountK;
// dv(3) = 3;
size_t blockByteCount = cellCount * sizeof( double );
std::vector<double> doubleValues( blockByteCount );
for ( int coordIdx = 0; coordIdx < 3; coordIdx++ )
{
quint64 valueIndex = 0;
for ( size_t k = 0; k < cellCountK; k++ )
{
for ( size_t j = 0; j < cellCountJ; j++ )
{
for ( size_t i = 0; i < cellCountI; i++ )
{
size_t gridLocalCellIndex = rigGrid->cellIndexFromIJK( i, j, k );
cvf::Vec3d center = rigGrid->cell( gridLocalCellIndex ).center();
convertVec3dToPositiveDepth( &center );
doubleValues[valueIndex++] = center[coordIdx];
}
}
}
CVF_ASSERT( valueIndex == cellCount );
RiaSocketTools::writeBlockData( server, server->currentClient(), (const char*)doubleValues.data(), blockByteCount );
}
return true;
}
};
static bool RiaGetCellCenters_init =
RiaSocketCommandFactory::instance()->registerCreator<RiaGetCellCenters>( RiaGetCellCenters::commandName() );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
class RiaGetActiveCellCenters : public RiaSocketCommand
{
public:
static QString commandName() { return QString( "GetActiveCellCenters" ); }
bool interpretCommand( RiaSocketServer* server, const QList<QByteArray>& args, QDataStream& socketStream ) override
{
RimEclipseCase* rimCase = RiaSocketTools::findCaseFromArgs( server, args );
QString porosityModelName;
porosityModelName = args[2];
RiaDefines::PorosityModelType porosityModelEnum = RiaDefines::PorosityModelType::MATRIX_MODEL;
if ( porosityModelName.toUpper() == "FRACTURE" )
{
porosityModelEnum = RiaDefines::PorosityModelType::FRACTURE_MODEL;
}
if ( !rimCase || !rimCase->eclipseCaseData() )
{
// No data available
socketStream << (quint64)0 << (quint64)0;
return true;
}
RigActiveCellInfo* actCellInfo = rimCase->eclipseCaseData()->activeCellInfo( porosityModelEnum );
RigMainGrid* mainGrid = rimCase->eclipseCaseData()->mainGrid();
size_t activeCellCount = actCellInfo->reservoirActiveCellCount();
size_t doubleValueCount = activeCellCount * 3;
socketStream << (quint64)activeCellCount;
quint64 byteCount = doubleValueCount * sizeof( double );
socketStream << byteCount;
// This structure is supposed to be received by Octave using a NDArray. The ordering of this loop is
// defined by the ordering of the receiving NDArray
//
// See riGetActiveCellCenters
//
// dim_vector dv;
// dv.resize(2);
// dv(0) = coordCount;
// dv(1) = 3;
size_t blockByteCount = activeCellCount * sizeof( double );
std::vector<double> doubleValues( blockByteCount );
for ( int coordIdx = 0; coordIdx < 3; coordIdx++ )
{
quint64 valueIndex = 0;
for ( size_t reservoirCellIndex = 0; reservoirCellIndex < mainGrid->globalCellArray().size();
reservoirCellIndex++ )
{
if ( !actCellInfo->isActive( reservoirCellIndex ) ) continue;
cvf::Vec3d center = mainGrid->globalCellArray()[reservoirCellIndex].center();
convertVec3dToPositiveDepth( &center );
doubleValues[valueIndex++] = center[coordIdx];
}
CVF_ASSERT( valueIndex == activeCellCount );
RiaSocketTools::writeBlockData( server, server->currentClient(), (const char*)doubleValues.data(), blockByteCount );
}
return true;
}
};
static bool RiaGetActiveCellCenters_init = RiaSocketCommandFactory::instance()->registerCreator<RiaGetActiveCellCenters>(
RiaGetActiveCellCenters::commandName() );
// NB: Match this mapping with the mapping in RifReaderEclipseOutput.cpp
static const size_t cellCornerMappingEclipse[8] = { 0, 1, 3, 2, 4, 5, 7, 6 };
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
class RiaGetCellCorners : public RiaSocketCommand
{
public:
static QString commandName() { return QString( "GetCellCorners" ); }
bool interpretCommand( RiaSocketServer* server, const QList<QByteArray>& args, QDataStream& socketStream ) override
{
RimEclipseCase* rimCase = RiaSocketTools::findCaseFromArgs( server, args );
size_t argGridIndex = args[2].toUInt();
if ( !rimCase || !rimCase->eclipseCaseData() || ( argGridIndex >= rimCase->eclipseCaseData()->gridCount() ) )
{
// No data available
socketStream << (quint64)0 << (quint64)0 << (quint64)0 << (quint64)0 << (quint64)0;
return true;
}
RigGridBase* rigGrid = rimCase->eclipseCaseData()->grid( argGridIndex );
quint64 cellCount = (quint64)rigGrid->cellCount();
quint64 cellCountI = (quint64)rigGrid->cellCountI();
quint64 cellCountJ = (quint64)rigGrid->cellCountJ();
quint64 cellCountK = (quint64)rigGrid->cellCountK();
size_t doubleValueCount = cellCount * 3 * 8;
quint64 byteCount = doubleValueCount * sizeof( double );
socketStream << cellCount;
socketStream << cellCountI;
socketStream << cellCountJ;
socketStream << cellCountK;
socketStream << byteCount;
// This structure is supposed to be received by Octave using a NDArray. The ordering of this loop is
// defined by the ordering of the receiving NDArray
//
// See riGetCellCorners
//
// dim_vector dv;
// dv.resize(5);
// dv(0) = cellCountI;
// dv(1) = cellCountJ;
// dv(2) = cellCountK;
// dv(3) = 8;
// dv(4) = 3;
cvf::Vec3d cornerVerts[8];
size_t blockByteCount = cellCount * sizeof( double );
std::vector<double> doubleValues( blockByteCount );
for ( int coordIdx = 0; coordIdx < 3; coordIdx++ )
{
for ( size_t cornerIdx = 0; cornerIdx < 8; cornerIdx++ )
{
size_t cornerIndexMapping = cellCornerMappingEclipse[cornerIdx];
quint64 valueIndex = 0;
for ( size_t k = 0; k < cellCountK; k++ )
{
for ( size_t j = 0; j < cellCountJ; j++ )
{
for ( size_t i = 0; i < cellCountI; i++ )
{
size_t gridLocalCellIndex = rigGrid->cellIndexFromIJK( i, j, k );
rigGrid->cellCornerVertices( gridLocalCellIndex, cornerVerts );
doubleValues[valueIndex++] =
getCellCornerWithPositiveDepth( cornerVerts, cornerIndexMapping, coordIdx );
}
}
}
CVF_ASSERT( valueIndex == cellCount );
RiaSocketTools::writeBlockData( server,
server->currentClient(),
(const char*)doubleValues.data(),
blockByteCount );
}
}
return true;
}
};
static bool RiaGetCellCorners_init =
RiaSocketCommandFactory::instance()->registerCreator<RiaGetCellCorners>( RiaGetCellCorners::commandName() );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
class RiaGetActiveCellCorners : public RiaSocketCommand
{
public:
static QString commandName() { return QString( "GetActiveCellCorners" ); }
bool interpretCommand( RiaSocketServer* server, const QList<QByteArray>& args, QDataStream& socketStream ) override
{
RimEclipseCase* rimCase = RiaSocketTools::findCaseFromArgs( server, args );
QString porosityModelName;
porosityModelName = args[2];
RiaDefines::PorosityModelType porosityModelEnum = RiaDefines::PorosityModelType::MATRIX_MODEL;
if ( porosityModelName.toUpper() == "FRACTURE" )
{
porosityModelEnum = RiaDefines::PorosityModelType::FRACTURE_MODEL;
}
if ( !rimCase || !rimCase->eclipseCaseData() )
{
// No data available
socketStream << (quint64)0 << (quint64)0;
return true;
}
RigActiveCellInfo* actCellInfo = rimCase->eclipseCaseData()->activeCellInfo( porosityModelEnum );
RigMainGrid* mainGrid = rimCase->eclipseCaseData()->mainGrid();
size_t activeCellCount = actCellInfo->reservoirActiveCellCount();
size_t doubleValueCount = activeCellCount * 3 * 8;
socketStream << (quint64)activeCellCount;
quint64 byteCount = doubleValueCount * sizeof( double );
socketStream << byteCount;
// This structure is supposed to be received by Octave using a NDArray. The ordering of this loop is
// defined by the ordering of the receiving NDArray
//
// See riGetCellCorners
//
// dim_vector dv;
// dv.resize(3);
// dv(0) = coordCount;
// dv(1) = 8;
// dv(2) = 3;
cvf::Vec3d cornerVerts[8];
size_t blockByteCount = activeCellCount * sizeof( double );
std::vector<double> doubleValues( blockByteCount );
for ( int coordIdx = 0; coordIdx < 3; coordIdx++ )
{
for ( size_t cornerIdx = 0; cornerIdx < 8; cornerIdx++ )
{
size_t cornerIndexMapping = cellCornerMappingEclipse[cornerIdx];
quint64 valueIndex = 0;
for ( size_t reservoirCellIndex = 0; reservoirCellIndex < mainGrid->globalCellArray().size();
reservoirCellIndex++ )
{
if ( !actCellInfo->isActive( reservoirCellIndex ) ) continue;
mainGrid->cellCornerVertices( reservoirCellIndex, cornerVerts );
doubleValues[valueIndex++] =
getCellCornerWithPositiveDepth( cornerVerts, cornerIndexMapping, coordIdx );
}
CVF_ASSERT( valueIndex == activeCellCount );
RiaSocketTools::writeBlockData( server,
server->currentClient(),
(const char*)doubleValues.data(),
blockByteCount );
}
}
return true;
}
};
static bool RiaGetActiveCellCorners_init = RiaSocketCommandFactory::instance()->registerCreator<RiaGetActiveCellCorners>(
RiaGetActiveCellCorners::commandName() );

View File

@@ -0,0 +1,611 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RiaSocketCommand.h"
#include "RiaPreferences.h"
#include "RiaSocketDataTransfer.h"
#include "RiaSocketServer.h"
#include "RiaSocketTools.h"
#include "RigActiveCellInfo.h"
#include "RigCaseCellResultsData.h"
#include "RigEclipseCaseData.h"
#include "RigMainGrid.h"
#include "Rim3dOverlayInfoConfig.h"
#include "RimCellEdgeColors.h"
#include "RimCellRangeFilterCollection.h"
#include "RimEclipseCase.h"
#include "RimEclipseCellColors.h"
#include "RimEclipseInputCase.h"
#include "RimEclipseInputProperty.h"
#include "RimEclipseInputPropertyCollection.h"
#include "RimEclipsePropertyFilterCollection.h"
#include "RimEclipseView.h"
#include "RimIntersectionCollection.h"
#include "RimReservoirCellResultsStorage.h"
#include "RimSimWellInViewCollection.h"
#include <QTcpSocket>
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
class RiaGetNNCConnections : public RiaSocketCommand
{
public:
static QString commandName() { return QString( "GetNNCConnections" ); }
bool interpretCommand( RiaSocketServer* server, const QList<QByteArray>& args, QDataStream& socketStream ) override
{
RimEclipseCase* rimCase = RiaSocketTools::findCaseFromArgs( server, args );
// Write data back to octave: columnCount, GridNr I J K GridNr I J K
if ( !( rimCase && rimCase->eclipseCaseData() && rimCase->eclipseCaseData()->mainGrid() ) )
{
// No data available
socketStream << (quint64)0;
return true;
}
RigMainGrid* mainGrid = rimCase->eclipseCaseData()->mainGrid();
size_t connectionCount = mainGrid->nncData()->connections().size();
socketStream << (quint64)connectionCount;
for ( size_t i = 0; i < mainGrid->nncData()->connections().size(); ++i )
{
RigConnection connection = mainGrid->nncData()->connections()[i];
const RigCell& cell1 = mainGrid->globalCellArray()[connection.c1GlobIdx()];
const RigCell& cell2 = mainGrid->globalCellArray()[connection.c2GlobIdx()];
sendCellInfo( socketStream, cell1 );
sendCellInfo( socketStream, cell2 );
}
return true;
}
static void sendCellInfo( QDataStream& socketStream, const RigCell& cell )
{
RigGridBase* hostGrid = cell.hostGrid();
size_t gridLocalCellIndex = cell.gridLocalCellIndex();
size_t i, j, k;
hostGrid->ijkFromCellIndex( gridLocalCellIndex, &i, &j, &k );
socketStream << (qint32)hostGrid->gridIndex();
socketStream << ( qint32 )( i + 1 ) << ( qint32 )( j + 1 ) << ( qint32 )( k + 1 );
}
};
static bool RiaGetNNCConnections_init =
RiaSocketCommandFactory::instance()->registerCreator<RiaGetNNCConnections>( RiaGetNNCConnections::commandName() );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
class RiaGetDynamicNNCValues : public RiaSocketCommand
{
public:
static QString commandName() { return QString( "GetDynamicNNCValues" ); }
bool interpretCommand( RiaSocketServer* server, const QList<QByteArray>& args, QDataStream& socketStream ) override
{
RimEclipseCase* rimCase = RiaSocketTools::findCaseFromArgs( server, args );
// Write data back to octave: connectionCount, timeStepCount, property values
if ( !( rimCase && rimCase->eclipseCaseData() && rimCase->eclipseCaseData()->mainGrid() ) )
{
// No data available
socketStream << (quint64)0 << (quint64)0;
return true;
}
QString propertyName = args[2];
RigMainGrid* mainGrid = rimCase->eclipseCaseData()->mainGrid();
const std::vector<std::vector<double>>* nncValues =
mainGrid->nncData()->dynamicConnectionScalarResultByName( propertyName );
if ( nncValues == nullptr )
{
socketStream << (quint64)0 << (quint64)0;
return true;
}
std::vector<size_t> requestedTimeSteps;
if ( args.size() > 3 )
{
bool timeStepReadError = false;
for ( int argIdx = 3; argIdx < args.size(); ++argIdx )
{
bool conversionOk = false;
int tsIdx = args[argIdx].toInt( &conversionOk );
if ( conversionOk )
{
requestedTimeSteps.push_back( tsIdx );
}
else
{
timeStepReadError = true;
}
}
if ( timeStepReadError )
{
server->showErrorMessage(
RiaSocketServer::tr( "ResInsight SocketServer: riGetDynamicNNCValues : \n" ) +
RiaSocketServer::tr( "An error occurred while interpreting the requested time steps." ) );
}
}
else
{
for ( size_t timeStep = 0; timeStep < nncValues->size(); ++timeStep )
{
requestedTimeSteps.push_back( timeStep );
}
}
// then the connection count and time step count.
size_t connectionCount = mainGrid->nncData()->connections().size();
size_t timeStepCount = requestedTimeSteps.size();
socketStream << (quint64)connectionCount;
socketStream << (quint64)timeStepCount;
for ( size_t timeStep : requestedTimeSteps )
{
const std::vector<double>& timeStepValues = nncValues->at( timeStep );
RiaSocketTools::writeBlockData( server,
server->currentClient(),
(const char*)timeStepValues.data(),
sizeof( double ) * timeStepValues.size() );
}
return true;
}
};
static bool RiaGetDynamicNNCValues_init =
RiaSocketCommandFactory::instance()->registerCreator<RiaGetDynamicNNCValues>( RiaGetDynamicNNCValues::commandName() );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
class RiaGetStaticNNCValues : public RiaSocketCommand
{
public:
static QString commandName() { return QString( "GetStaticNNCValues" ); }
bool interpretCommand( RiaSocketServer* server, const QList<QByteArray>& args, QDataStream& socketStream ) override
{
RimEclipseCase* rimCase = RiaSocketTools::findCaseFromArgs( server, args );
QString propertyName = args[2];
// Write data back to octave: connectionCount, property values
if ( !( rimCase && rimCase->eclipseCaseData() && rimCase->eclipseCaseData()->mainGrid() ) )
{
// No data available
socketStream << (quint64)0;
return true;
}
RigMainGrid* mainGrid = rimCase->eclipseCaseData()->mainGrid();
const std::vector<double>* nncValues = mainGrid->nncData()->staticConnectionScalarResultByName( propertyName );
if ( nncValues == nullptr )
{
socketStream << (quint64)0;
return true;
}
// connection count
size_t connectionCount = mainGrid->nncData()->connections().size();
socketStream << (quint64)connectionCount;
RiaSocketTools::writeBlockData( server,
server->currentClient(),
(const char*)nncValues->data(),
sizeof( double ) * nncValues->size() );
return true;
}
};
static bool RiaGetStaticNNCValues_init =
RiaSocketCommandFactory::instance()->registerCreator<RiaGetStaticNNCValues>( RiaGetStaticNNCValues::commandName() );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
class RiaGetNNCPropertyNames : public RiaSocketCommand
{
public:
static QString commandName() { return QString( "GetNNCPropertyNames" ); }
bool interpretCommand( RiaSocketServer* server, const QList<QByteArray>& args, QDataStream& socketStream ) override
{
RimEclipseCase* rimCase = RiaSocketTools::findCaseFromArgs( server, args );
if ( !( rimCase && rimCase->eclipseCaseData() && rimCase->eclipseCaseData()->mainGrid() ) )
{
// No data available
socketStream << (quint64)0;
return true;
}
RigNNCData* nncData = rimCase->eclipseCaseData()->mainGrid()->nncData();
std::vector<QString> propertyTypes;
std::vector<QString> propertyNames;
std::vector<RigNNCData::NNCResultType> resultTypes;
std::vector<QString> resultTypeNames;
resultTypes.push_back( RigNNCData::NNC_DYNAMIC );
resultTypeNames.push_back( "DynamicNative" );
resultTypes.push_back( RigNNCData::NNC_STATIC );
resultTypeNames.push_back( "StaticNative" );
resultTypes.push_back( RigNNCData::NNC_GENERATED );
resultTypeNames.push_back( "Generated" );
for ( size_t rtIdx = 0; rtIdx < resultTypes.size(); ++rtIdx )
{
std::vector<QString> availableParameters = nncData->availableProperties( resultTypes[rtIdx] );
for ( const QString& parameter : availableParameters )
{
propertyNames.push_back( parameter );
propertyTypes.push_back( resultTypeNames[rtIdx] );
}
}
qint64 byteCount = 0;
for ( size_t ptIdx = 0; ptIdx < propertyNames.size(); ++ptIdx )
{
byteCount += propertyNames[ptIdx].size() * sizeof( QChar );
byteCount += propertyTypes[ptIdx].size() * sizeof( QChar );
}
// Byte count
socketStream << byteCount;
// Parameter count
socketStream << (quint64)propertyNames.size();
for ( size_t ptIdx = 0; ptIdx < propertyNames.size(); ++ptIdx )
{
socketStream << propertyNames[ptIdx];
socketStream << propertyTypes[ptIdx];
}
return true;
}
};
static bool RiaGetNNCPropertyNames_init =
RiaSocketCommandFactory::instance()->registerCreator<RiaGetNNCPropertyNames>( RiaGetNNCPropertyNames::commandName() );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
class RiaSetNNCProperty : public RiaSocketCommand
{
public:
RiaSetNNCProperty()
: m_currentReservoir( nullptr )
, m_currentEclResultAddress()
, m_timeStepCountToRead( 0 )
, m_bytesPerTimeStepToRead( 0 )
, m_currentTimeStepNumberToRead( 0 )
, m_invalidConnectionCountDetected( false )
, m_porosityModelEnum( RiaDefines::PorosityModelType::MATRIX_MODEL )
{
}
static QString commandName() { return QString( "SetNNCProperty" ); }
bool interpretCommand( RiaSocketServer* server, const QList<QByteArray>& args, QDataStream& socketStream ) override
{
RimEclipseCase* rimCase = RiaSocketTools::findCaseFromArgs( server, args );
QString propertyName = args[2];
// Find the requested data, or create a set if we are setting data and it is not found
if ( !( rimCase && rimCase->eclipseCaseData() && rimCase->eclipseCaseData()->mainGrid() ) )
{
QString caseId = args[1];
server->showErrorMessage( RiaSocketServer::tr( "ResInsight SocketServer: \n" ) +
RiaSocketServer::tr( "Could not find case with id %1" ).arg( caseId ) );
return true;
}
// If we have not read the header and there are data enough: Read it.
// Do nothing if we have not enough data
if ( m_timeStepCountToRead == 0 || m_bytesPerTimeStepToRead == 0 )
{
if ( server->currentClient()->bytesAvailable() < (int)sizeof( quint64 ) * 2 ) return true;
socketStream >> m_timeStepCountToRead;
socketStream >> m_bytesPerTimeStepToRead;
}
RigNNCData* nncData = rimCase->eclipseCaseData()->mainGrid()->nncData();
auto nncResults = nncData->generatedConnectionScalarResultByName( propertyName );
if ( nncResults == nullptr )
{
nncData->makeGeneratedConnectionScalarResult( propertyName, m_timeStepCountToRead );
}
if ( rimCase && rimCase->results( m_porosityModelEnum ) )
{
bool ok = createIJKCellResults( rimCase->results( m_porosityModelEnum ), propertyName );
if ( !ok )
{
server->showErrorMessage(
RiaSocketServer::tr( "ResInsight SocketServer: \n" ) +
RiaSocketServer::tr( "Could not find the property named: \"%2\"" ).arg( propertyName ) );
return true;
}
RigEclipseResultAddress resAddr( QString( "%1IJK" ).arg( propertyName ) );
rimCase->results( m_porosityModelEnum )->ensureKnownResultLoaded( resAddr );
nncData->setEclResultAddress( propertyName, resAddr );
}
// Create a list of all the requested time steps
m_requestedTimesteps.clear();
if ( args.size() <= 4 )
{
// Select all
for ( size_t tsIdx = 0; tsIdx < m_timeStepCountToRead; ++tsIdx )
{
m_requestedTimesteps.push_back( tsIdx );
}
}
else
{
bool timeStepReadError = false;
for ( int argIdx = 4; argIdx < args.size(); ++argIdx )
{
bool conversionOk = false;
int tsIdx = args[argIdx].toInt( &conversionOk );
if ( conversionOk )
{
m_requestedTimesteps.push_back( tsIdx );
}
else
{
timeStepReadError = true;
}
}
if ( timeStepReadError )
{
server->showErrorMessage(
RiaSocketServer::tr( "ResInsight SocketServer: riSetNNCProperty : \n" ) +
RiaSocketServer::tr( "An error occurred while interpreting the requested time steps." ) );
}
}
if ( !m_requestedTimesteps.size() )
{
server->showErrorMessage( RiaSocketServer::tr( "ResInsight SocketServer: \n" ) +
RiaSocketServer::tr( "No time steps specified" ) );
return true;
}
m_currentReservoir = rimCase;
m_currentPropertyName = propertyName;
if ( server->currentClient()->bytesAvailable() )
{
return this->interpretMore( server, server->currentClient() );
}
return false;
}
private:
static bool createIJKCellResults( RigCaseCellResultsData* results, QString propertyName )
{
bool ok;
ok = scalarResultExistsOrCreate( results, QString( "%1IJK" ).arg( propertyName ) );
if ( !ok ) return false;
ok = scalarResultExistsOrCreate( results, QString( "%1I" ).arg( propertyName ) );
if ( !ok ) return false;
ok = scalarResultExistsOrCreate( results, QString( "%1J" ).arg( propertyName ) );
if ( !ok ) return false;
ok = scalarResultExistsOrCreate( results, QString( "%1K" ).arg( propertyName ) );
return ok;
}
static bool scalarResultExistsOrCreate( RigCaseCellResultsData* results, QString propertyName )
{
RigEclipseResultAddress resAddr( RiaDefines::ResultCatType::GENERATED, propertyName );
if ( !results->ensureKnownResultLoaded( resAddr ) )
{
results->createResultEntry( resAddr, true );
}
std::vector<std::vector<double>>* scalarResultFrames = results->modifiableCellScalarResultTimesteps( resAddr );
size_t timeStepCount = results->maxTimeStepCount();
scalarResultFrames->resize( timeStepCount );
return true;
}
public:
bool interpretMore( RiaSocketServer* server, QTcpSocket* currentClient ) override
{
if ( m_invalidConnectionCountDetected ) return true;
// If nothing should be read, or we already have read everything, do nothing
if ( ( m_timeStepCountToRead == 0 ) || ( m_currentTimeStepNumberToRead >= m_timeStepCountToRead ) ) return true;
if ( !currentClient->bytesAvailable() ) return false;
if ( m_timeStepCountToRead != m_requestedTimesteps.size() )
{
CVF_ASSERT( false );
}
// Check if a complete timestep is available, return and whait for readyRead() if not
if ( currentClient->bytesAvailable() < (int)m_bytesPerTimeStepToRead ) return false;
RigNNCData* nncData = m_currentReservoir->eclipseCaseData()->mainGrid()->nncData();
size_t connectionCountFromOctave = m_bytesPerTimeStepToRead / sizeof( double );
size_t connectionCount = nncData->connections().size();
std::vector<std::vector<double>>* resultsToAdd =
nncData->generatedConnectionScalarResultByName( m_currentPropertyName );
if ( connectionCountFromOctave != connectionCount )
{
server->showErrorMessage( RiaSocketServer::tr( "ResInsight SocketServer: \n" ) +
RiaSocketServer::tr( "The number of connections in the data coming from octave "
"does not match the case: '%1'\n" )
.arg( m_currentReservoir->caseUserDescription() ) +
RiaSocketServer::tr( " Octave: %1\n" ).arg( connectionCountFromOctave ) +
RiaSocketServer::tr( " %1: Connection count: %2" )
.arg( m_currentReservoir->caseUserDescription() )
.arg( connectionCount ) );
connectionCountFromOctave = 0;
m_invalidConnectionCountDetected = true;
currentClient->abort();
return true;
}
for ( size_t tIdx = 0; tIdx < m_timeStepCountToRead; ++tIdx )
{
size_t tsId = m_requestedTimesteps[tIdx];
resultsToAdd->at( tsId ).resize( connectionCount, HUGE_VAL );
}
double* internalMatrixData = nullptr;
QDataStream socketStream( currentClient );
socketStream.setVersion( riOctavePlugin::qtDataStreamVersion );
// Read available complete time step data
while ( ( currentClient->bytesAvailable() >= (int)m_bytesPerTimeStepToRead ) &&
( m_currentTimeStepNumberToRead < m_timeStepCountToRead ) )
{
internalMatrixData = resultsToAdd->at( m_requestedTimesteps[m_currentTimeStepNumberToRead] ).data();
QStringList errorMessages;
if ( !RiaSocketDataTransfer::readBlockDataFromSocket( currentClient,
(char*)( internalMatrixData ),
m_bytesPerTimeStepToRead,
errorMessages ) )
{
for ( int i = 0; i < errorMessages.size(); i++ )
{
server->showErrorMessage( errorMessages[i] );
}
currentClient->abort();
return true;
}
++m_currentTimeStepNumberToRead;
}
// If we have read all the data, refresh the views
if ( m_currentTimeStepNumberToRead == m_timeStepCountToRead )
{
if ( m_currentReservoir != nullptr )
{
// Create a new input property if we have an input reservoir
RimEclipseInputCase* inputRes = dynamic_cast<RimEclipseInputCase*>( m_currentReservoir );
if ( inputRes )
{
RimEclipseInputProperty* inputProperty =
inputRes->inputPropertyCollection()->findInputProperty( m_currentPropertyName );
if ( !inputProperty )
{
inputProperty = new RimEclipseInputProperty;
inputProperty->resultName = m_currentPropertyName;
inputProperty->eclipseKeyword = "";
inputProperty->fileName = QString( "" );
inputRes->inputPropertyCollection()->inputProperties.push_back( inputProperty );
inputRes->inputPropertyCollection()->updateConnectedEditors();
}
inputProperty->resolvedState = RimEclipseInputProperty::RESOLVED_NOT_SAVED;
}
if ( m_currentEclResultAddress.isValid() && // Will never be valid because it is never set. What is
// correct behaviour ?
m_currentReservoir->eclipseCaseData() &&
m_currentReservoir->eclipseCaseData()->results( m_porosityModelEnum ) )
{
m_currentReservoir->eclipseCaseData()
->results( m_porosityModelEnum )
->recalculateStatistics( m_currentEclResultAddress );
}
for ( size_t i = 0; i < m_currentReservoir->reservoirViews.size(); ++i )
{
if ( m_currentReservoir->reservoirViews[i] )
{
// As new result might have been introduced, update all editors connected
m_currentReservoir->reservoirViews[i]->cellResult()->updateConnectedEditors();
// It is usually not needed to create new display model, but if any derived geometry based on
// generated data (from Octave) a full display model rebuild is required
m_currentReservoir->reservoirViews[i]->scheduleCreateDisplayModelAndRedraw();
m_currentReservoir->reservoirViews[i]
->intersectionCollection()
->scheduleCreateDisplayModelAndRedraw2dIntersectionViews();
}
}
}
return true;
}
return false;
}
private:
RimEclipseCase* m_currentReservoir;
RigEclipseResultAddress m_currentEclResultAddress;
QString m_currentPropertyName;
std::vector<size_t> m_requestedTimesteps;
RiaDefines::PorosityModelType m_porosityModelEnum;
quint64 m_timeStepCountToRead;
quint64 m_bytesPerTimeStepToRead;
size_t m_currentTimeStepNumberToRead;
bool m_invalidConnectionCountDetected;
};
static bool RiaSetNNCProperty_init =
RiaSocketCommandFactory::instance()->registerCreator<RiaSetNNCProperty>( RiaSetNNCProperty::commandName() );

View File

@@ -0,0 +1,305 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RiaSocketCommand.h"
#include "RiaApplication.h"
#include "RiaSocketServer.h"
#include "RiaSocketTools.h"
#include "Rim3dOverlayInfoConfig.h"
#include "RimCaseCollection.h"
#include "RimCellEdgeColors.h"
#include "RimCellRangeFilterCollection.h"
#include "RimEclipseCase.h"
#include "RimEclipseCaseCollection.h"
#include "RimEclipseCellColors.h"
#include "RimEclipsePropertyFilterCollection.h"
#include "RimEclipseView.h"
#include "RimIdenticalGridCaseGroup.h"
#include "RimOilField.h"
#include "RimProject.h"
#include "RimReservoirCellResultsStorage.h"
#include "RimScriptCollection.h"
#include "RimSimWellInViewCollection.h"
#include "RiuMainWindow.h"
#include "cafSelectionManager.h"
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void getCaseInfoFromCases( std::vector<RimCase*>& cases,
std::vector<qint64>& caseIds,
std::vector<QString>& caseNames,
std::vector<QString>& caseTypes,
std::vector<qint64>& caseGroupIds )
{
for ( size_t i = 0; i < cases.size(); i++ )
{
RimCase* rimCase = cases[i];
qint64 caseId = -1;
QString caseName;
QString caseType;
qint64 caseGroupId = -1;
RiaSocketTools::getCaseInfoFromCase( rimCase, caseId, caseName, caseType, caseGroupId );
caseIds.push_back( rimCase->caseId );
caseNames.push_back( rimCase->caseUserDescription );
caseTypes.push_back( caseType );
caseGroupIds.push_back( caseGroupId );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
class RiaGetCurrentCase : public RiaSocketCommand
{
public:
static QString commandName() { return QString( "GetCurrentCase" ); }
bool interpretCommand( RiaSocketServer* server, const QList<QByteArray>& args, QDataStream& socketStream ) override
{
qint64 caseId = RiaApplication::instance()->currentScriptCaseId();
QString caseName;
QString caseType;
qint64 caseGroupId = -1;
RimEclipseCase* rimCase = server->findReservoir( caseId );
if ( rimCase )
{
RiaSocketTools::getCaseInfoFromCase( rimCase, caseId, caseName, caseType, caseGroupId );
}
quint64 byteCount = 2 * sizeof( qint64 );
byteCount += caseName.size() * sizeof( QChar );
byteCount += caseType.size() * sizeof( QChar );
socketStream << byteCount;
socketStream << caseId;
socketStream << caseName;
socketStream << caseType;
socketStream << caseGroupId;
return true;
}
};
static bool RiaGetCurrentCase_init =
RiaSocketCommandFactory::instance()->registerCreator<RiaGetCurrentCase>( RiaGetCurrentCase::commandName() );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
class RiaGetSelectedCases : public RiaSocketCommand
{
public:
static QString commandName() { return QString( "GetSelectedCases" ); }
bool interpretCommand( RiaSocketServer* server, const QList<QByteArray>& args, QDataStream& socketStream ) override
{
{
std::vector<RimCase*> cases;
caf::SelectionManager::instance()->objectsByType( &cases );
std::vector<qint64> caseIds;
std::vector<QString> caseNames;
std::vector<QString> caseTypes;
std::vector<qint64> caseGroupIds;
getCaseInfoFromCases( cases, caseIds, caseNames, caseTypes, caseGroupIds );
quint64 byteCount = sizeof( quint64 );
quint64 selectionCount = caseIds.size();
for ( size_t i = 0; i < selectionCount; i++ )
{
byteCount += 2 * sizeof( qint64 );
byteCount += caseNames[i].size() * sizeof( QChar );
byteCount += caseTypes[i].size() * sizeof( QChar );
}
socketStream << byteCount;
socketStream << selectionCount;
for ( size_t i = 0; i < selectionCount; i++ )
{
socketStream << caseIds[i];
socketStream << caseNames[i];
socketStream << caseTypes[i];
socketStream << caseGroupIds[i];
}
}
return true;
}
};
static bool RiaGetSelectedCases_init =
RiaSocketCommandFactory::instance()->registerCreator<RiaGetSelectedCases>( RiaGetSelectedCases::commandName() );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
class RiaGetCaseGroups : public RiaSocketCommand
{
public:
static QString commandName() { return QString( "GetCaseGroups" ); }
bool interpretCommand( RiaSocketServer* server, const QList<QByteArray>& args, QDataStream& socketStream ) override
{
RimProject* proj = RimProject::current();
RimEclipseCaseCollection* analysisModels =
( proj && proj->activeOilField() ) ? proj->activeOilField()->analysisModels() : nullptr;
if ( analysisModels )
{
std::vector<QString> groupNames;
std::vector<qint64> groupIds;
size_t caseGroupCount = analysisModels->caseGroups().size();
quint64 byteCount = 0;
for ( size_t i = 0; i < caseGroupCount; i++ )
{
RimIdenticalGridCaseGroup* cg = analysisModels->caseGroups()[i];
QString caseGroupName = cg->name;
qint64 caseGroupId = cg->groupId;
byteCount += caseGroupName.size() * sizeof( QChar );
byteCount += sizeof( qint64 );
groupNames.push_back( caseGroupName );
groupIds.push_back( caseGroupId );
}
socketStream << (quint64)byteCount;
socketStream << (quint64)caseGroupCount;
for ( size_t i = 0; i < caseGroupCount; i++ )
{
socketStream << groupNames[i];
socketStream << groupIds[i];
}
}
else
{
// ERROR
}
return true;
}
};
static bool RiaGetCaseGroups_init =
RiaSocketCommandFactory::instance()->registerCreator<RiaGetCaseGroups>( RiaGetCaseGroups::commandName() );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
class RiaGetCases : public RiaSocketCommand
{
public:
static QString commandName() { return QString( "GetCases" ); }
bool interpretCommand( RiaSocketServer* server, const QList<QByteArray>& args, QDataStream& socketStream ) override
{
int argCaseGroupId = -1;
if ( args.size() == 2 )
{
argCaseGroupId = args[1].toInt();
}
RimProject* proj = RimProject::current();
RimEclipseCaseCollection* analysisModels =
( proj && proj->activeOilField() ) ? proj->activeOilField()->analysisModels() : nullptr;
if ( analysisModels )
{
std::vector<RimCase*> cases;
if ( argCaseGroupId == -1 )
{
proj->allCases( cases );
}
else
{
RimIdenticalGridCaseGroup* caseGroup = nullptr;
for ( size_t i = 0; i < analysisModels->caseGroups().size(); i++ )
{
RimIdenticalGridCaseGroup* cg = analysisModels->caseGroups()[i];
if ( argCaseGroupId == cg->groupId() )
{
caseGroup = cg;
}
}
if ( caseGroup )
{
for ( size_t i = 0; i < caseGroup->statisticsCaseCollection()->reservoirs.size(); i++ )
{
cases.push_back( caseGroup->statisticsCaseCollection()->reservoirs[i] );
}
for ( size_t i = 0; i < caseGroup->caseCollection()->reservoirs.size(); i++ )
{
cases.push_back( caseGroup->caseCollection()->reservoirs[i] );
}
}
}
std::vector<qint64> caseIds;
std::vector<QString> caseNames;
std::vector<QString> caseTypes;
std::vector<qint64> caseGroupIds;
getCaseInfoFromCases( cases, caseIds, caseNames, caseTypes, caseGroupIds );
quint64 byteCount = sizeof( quint64 );
quint64 caseCount = caseIds.size();
for ( size_t i = 0; i < caseCount; i++ )
{
byteCount += 2 * sizeof( qint64 );
byteCount += caseNames[i].size() * sizeof( QChar );
byteCount += caseTypes[i].size() * sizeof( QChar );
}
socketStream << byteCount;
socketStream << caseCount;
for ( size_t i = 0; i < caseCount; i++ )
{
socketStream << caseIds[i];
socketStream << caseNames[i];
socketStream << caseTypes[i];
socketStream << caseGroupIds[i];
}
}
return true;
}
};
static bool RiaGetCases_init =
RiaSocketCommandFactory::instance()->registerCreator<RiaGetCases>( RiaGetCases::commandName() );

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,54 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2011-2012 Statoil ASA, 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
//////////////////////////////////////////////////////////////////////////
/// The base class for classes interpreting commands sent via socket.
/// Works in close connection with RiaSocketServer
//////////////////////////////////////////////////////////////////////////
class RiaSocketServer;
class QTcpSocket;
class QDataStream;
class QByteArray;
#include <QList>
class RiaSocketCommand
{
public:
virtual ~RiaSocketCommand() {}
/// This method is supposed to interpret the commands received from the calling socket connection and
/// read the data currently available.
/// If it read all the data and completed the command, it is supposed to return true. If it did not read all the
/// data, it is supposed to return false. The socket server will then assume that the command is not completely
/// interpreted, and will continue to call interpretMore() until that method returns true.
virtual bool interpretCommand( RiaSocketServer* server, const QList<QByteArray>& args, QDataStream& socketStream ) = 0;
/// This method is supposed to read whatever more data that is available on the socket connection, and return true
/// if it was able to read all the data. If not all the data was available, it must return false, so that the
/// RiaSocketServer will call this method again when more data becomes available.
virtual bool interpretMore( RiaSocketServer* server, QTcpSocket* currentClient ) { return true; }
};
#include "cafFactory.h"
typedef caf::Factory<RiaSocketCommand, QString> RiaSocketCommandFactory;

View File

@@ -0,0 +1,110 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RiaSocketDataTransfer.h"
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RiaSocketDataTransfer::writeBlockDataToSocket( QTcpSocket* socket,
const char* data,
quint64 bytesToWrite,
QStringList& errorMessages )
{
quint64 bytesWritten = 0;
quint64 maxBlockSize = maximumValueCountInBlock() * sizeof( double );
while ( bytesWritten < bytesToWrite )
{
quint64 byteCountToWrite = qMin( bytesToWrite - bytesWritten, maxBlockSize );
qint64 actuallyBytesWritten = socket->write( data + bytesWritten, byteCountToWrite );
if ( actuallyBytesWritten < 0 )
{
errorMessages.push_back( "Error detected when writing data, error string from socket" );
errorMessages.push_back( socket->errorString() );
return false;
}
bytesWritten += actuallyBytesWritten;
}
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RiaSocketDataTransfer::readBlockDataFromSocket( QTcpSocket* socket, char* data, quint64 bytesToRead, QStringList& errorMessages )
{
quint64 bytesRead = 0;
quint64 maxBlockSize = maximumValueCountInBlock() * sizeof( double );
while ( bytesRead < bytesToRead )
{
if ( socket->bytesAvailable() )
{
quint64 byteCountToRead = bytesToRead - bytesRead;
byteCountToRead = qMin( byteCountToRead, maxBlockSize );
qint64 actuallyBytesRead = socket->read( data + bytesRead, byteCountToRead );
if ( actuallyBytesRead < 0 )
{
errorMessages.push_back( "Error detected when reading data, error string from socket" );
errorMessages.push_back( socket->errorString() );
return false;
}
bytesRead += actuallyBytesRead;
#ifdef octave_oct_h
// octave_stdout << "Byte read " << bytesRead << " of a total of "<< bytesToRead << "\n";
#endif
}
else
{
if ( !socket->waitForReadyRead() )
{
errorMessages.push_back( "Waited for data for %1 milli seconds." );
errorMessages.push_back( socket->errorString() );
return false;
}
}
// Allow Octave process to end a long running Octave function
#ifdef octave_oct_h
OCTAVE_QUIT;
#endif
}
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t RiaSocketDataTransfer::maximumValueCountInBlock()
{
return 20000;
}

View File

@@ -0,0 +1,40 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include <QStringList>
#include <QTcpSocket>
//==================================================================================================
/// Utility class used for transfer of data using QTcpSocket
///
/// As the compile configuration for octave plugins is quite complex,
// the octave plugins includes the cpp-file to be able to compile only one file per plugin
//==================================================================================================
class RiaSocketDataTransfer
{
public:
static size_t maximumValueCountInBlock();
public:
static bool
writeBlockDataToSocket( QTcpSocket* socket, const char* data, quint64 bytesToWrite, QStringList& errorMessages );
static bool readBlockDataFromSocket( QTcpSocket* socket, char* data, quint64 bytesToRead, QStringList& errorMessages );
};

View File

@@ -0,0 +1,357 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RiaSocketServer.h"
#include "RiaSocketCommand.h"
#include "RiaApplication.h"
#include "RiaLogging.h"
#include "RiaPreferences.h"
#include "RimCase.h"
#include "RimEclipseCase.h"
#include "RimEclipseView.h"
#include "RimProject.h"
#include "RiuMainWindow.h"
#include "RiuViewer.h"
#include "cafFactory.h"
#include <QtNetwork>
#include <QtWidgets/QMdiSubWindow>
#include <cstdlib>
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiaSocketServer::RiaSocketServer( QObject* parent )
: QObject( parent )
, m_tcpServer( nullptr )
, m_currentClient( nullptr )
, m_currentCommandSize( 0 )
, m_currentCommand( nullptr )
{
m_tcpServer = new QTcpServer( this );
m_nextPendingConnectionTimer = new QTimer( this );
m_nextPendingConnectionTimer->setInterval( 100 );
m_nextPendingConnectionTimer->setSingleShot( true );
if ( !m_tcpServer->listen( QHostAddress::LocalHost, 40001 ) )
{
QString txt = "Disabled communication with Octave due to another ResInsight process running.";
RiaLogging::warning( txt );
return;
}
connect( m_nextPendingConnectionTimer, SIGNAL( timeout() ), this, SLOT( slotNewClientConnection() ) );
connect( m_tcpServer, SIGNAL( newConnection() ), this, SLOT( slotNewClientConnection() ) );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiaSocketServer::~RiaSocketServer()
{
assert( m_currentCommand == nullptr );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
unsigned short RiaSocketServer::serverPort()
{
if ( m_tcpServer )
return m_tcpServer->serverPort();
else
return 0;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaSocketServer::slotNewClientConnection()
{
// If we are currently handling a connection, just ignore the new one until the current one is disconnected.
if ( m_currentClient && ( m_currentClient->state() != QAbstractSocket::UnconnectedState ) )
{
// PMonLog("Starting Timer");
m_nextPendingConnectionTimer->start(); // Reset and start again
return;
}
// Read pending data from socket
if ( m_currentClient && m_currentCommand )
{
bool isFinshed = m_currentCommand->interpretMore( this, m_currentClient );
if ( !isFinshed )
{
QString txt;
txt = "ResInsight SocketServer : The command did not finish up correctly at the presence of a new one.";
RiaLogging::error( txt );
}
}
handleNextPendingConnection();
}
//--------------------------------------------------------------------------------------------------
/// Find the requested reservoir by caseId
//--------------------------------------------------------------------------------------------------
RimEclipseCase* RiaSocketServer::findReservoir( int caseId )
{
int currCaseId = caseId;
if ( caseId < 0 )
{
currCaseId = RiaApplication::instance()->currentScriptCaseId();
}
if ( currCaseId < 0 )
{
RimEclipseView* eclipseView = dynamic_cast<RimEclipseView*>( RiaApplication::instance()->activeReservoirView() );
if ( eclipseView )
{
return eclipseView->eclipseCase();
}
// If the active mdi window is different from an Eclipse view, search through available mdi windows to find the
// last activated Eclipse view. The sub windows are returned with the most recent activated window at the back.
QList<QMdiSubWindow*> subWindows = RiuMainWindow::instance()->subWindowList( QMdiArea::ActivationHistoryOrder );
for ( int i = subWindows.size() - 1; i > -1; i-- )
{
RiuViewer* viewer = subWindows[i]->widget()->findChild<RiuViewer*>();
if ( viewer )
{
RimEclipseView* riv = dynamic_cast<RimEclipseView*>( viewer->ownerReservoirView() );
if ( riv )
{
return riv->eclipseCase();
}
}
}
}
else
{
RimProject* project = RimProject::current();
if ( !project ) return nullptr;
std::vector<RimCase*> cases;
project->allCases( cases );
for ( size_t i = 0; i < cases.size(); i++ )
{
if ( cases[i]->caseId == currCaseId )
{
return dynamic_cast<RimEclipseCase*>( cases[i] );
}
}
}
return nullptr;
}
//--------------------------------------------------------------------------------------------------
/// Reads the command name size, the command string and creates a new command object based on the string read.
/// Tries to interpret the command as well.
/// Returns whether the command actually was completely finished in one go.
//--------------------------------------------------------------------------------------------------
bool RiaSocketServer::readCommandFromOctave()
{
QDataStream socketStream( m_currentClient );
socketStream.setVersion( riOctavePlugin::qtDataStreamVersion );
// If we have not read the currentCommandSize
// read the size of the command if all the data is available
if ( m_currentCommandSize == 0 )
{
if ( m_currentClient->bytesAvailable() < (int)sizeof( qint64 ) ) return false;
socketStream >> m_currentCommandSize;
}
// Check if the complete command is available, return and whait for readyRead() if not
if ( m_currentClient->bytesAvailable() < m_currentCommandSize ) return false;
// Now we can read the command name
QByteArray command = m_currentClient->read( m_currentCommandSize );
QTextStream commandStream( command );
QList<QByteArray> args;
while ( !commandStream.atEnd() )
{
QByteArray arg;
commandStream >> arg;
args.push_back( arg );
}
CVF_ASSERT( args.size() > 0 );
// Create the actual RiaSocketCommand object that will interpret the socket data
m_currentCommand = RiaSocketCommandFactory::instance()->create( args[0] );
if ( m_currentCommand )
{
bool finished = m_currentCommand->interpretCommand( this, args, socketStream );
return finished;
}
else
{
QString txt;
txt = QString( "ResInsight SocketServer: Unknown command: %1" ).arg( args[0].data() );
RiaLogging::error( txt );
return true;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaSocketServer::slotCurrentClientDisconnected()
{
if ( m_currentCommand )
{
// Make sure we read what can be read.
bool isFinished = m_currentCommand->interpretMore( this, m_currentClient );
if ( !isFinished )
{
QString txt;
txt = QString( "ResInsight SocketServer: The command was interrupted and did not finish because the "
"connection to octave disconnected." );
RiaLogging::error( txt );
}
}
handleNextPendingConnection();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaSocketServer::slotReadyRead()
{
if ( m_currentCommand )
{
bool isFinished = m_currentCommand->interpretMore( this, m_currentClient );
if ( isFinished )
{
handleNextPendingConnection();
}
}
else
{
bool isFinished = readCommandFromOctave();
if ( isFinished )
{
handleNextPendingConnection();
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaSocketServer::showErrorMessage( const QString& message ) const
{
RiaLogging::error( message );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaSocketServer::terminateCurrentConnection()
{
if ( m_currentClient )
{
m_currentClient->disconnect( SIGNAL( disconnected() ) );
m_currentClient->disconnect( SIGNAL( readyRead() ) );
m_currentClient->deleteLater();
m_currentClient = nullptr;
}
// Clean up more state:
if ( m_currentCommand )
{
delete m_currentCommand;
m_currentCommand = nullptr;
}
m_currentCommandSize = 0;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaSocketServer::handleNextPendingConnection()
{
if ( m_currentClient && ( m_currentClient->state() != QAbstractSocket::UnconnectedState ) )
{
// PMonLog("Starting Timer");
m_nextPendingConnectionTimer->start(); // Reset and start again
return;
}
// Stop timer
if ( m_nextPendingConnectionTimer->isActive() )
{
// PMonLog("Stopping Timer");
m_nextPendingConnectionTimer->stop();
}
terminateCurrentConnection();
QTcpSocket* clientToHandle = m_tcpServer->nextPendingConnection();
if ( clientToHandle )
{
CVF_ASSERT( m_currentClient == nullptr );
CVF_ASSERT( m_currentCommand == nullptr );
m_currentClient = clientToHandle;
m_currentCommandSize = 0;
connect( m_currentClient, SIGNAL( disconnected() ), this, SLOT( slotCurrentClientDisconnected() ) );
connect( m_currentClient, SIGNAL( readyRead() ), this, SLOT( slotReadyRead() ) );
if ( m_currentClient->bytesAvailable() )
{
bool isFinished = this->readCommandFromOctave();
if ( isFinished )
{
// Call ourselves recursively until there are none left, or until it can not be processed in one go.
this->handleNextPendingConnection();
}
}
}
}

View File

@@ -0,0 +1,81 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "RiaSocketServerDefines.h"
#include <QDataStream>
#include <QObject>
#include <vector>
class QLabel;
class QPushButton;
class QTcpServer;
class QTcpSocket;
class QNetworkSession;
class QTimer;
class RimEclipseCase;
class RiaSocketCommand;
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
class RiaSocketServer : public QObject
{
Q_OBJECT
public:
enum ReadState
{
ReadingCommand,
ReadingPropertyData
};
public:
explicit RiaSocketServer( QObject* parent = nullptr );
~RiaSocketServer() override;
unsigned short serverPort();
RimEclipseCase* findReservoir( int caseId );
QTcpSocket* currentClient() { return m_currentClient; }
void showErrorMessage( const QString& message ) const;
private slots:
void slotNewClientConnection();
void slotCurrentClientDisconnected();
void slotReadyRead();
private:
void handleNextPendingConnection();
void terminateCurrentConnection();
bool readCommandFromOctave();
private:
QTcpServer* m_tcpServer;
QTcpSocket* m_currentClient;
qint64 m_currentCommandSize; ///< The size in bytes of the command we are currently reading.
RiaSocketCommand* m_currentCommand;
QTimer* m_nextPendingConnectionTimer;
};

View File

@@ -0,0 +1,24 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2018- Equinor 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include <QDataStream>
namespace riOctavePlugin
{
const int qtDataStreamVersion = QDataStream::Qt_4_0;
}

View File

@@ -0,0 +1,137 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RiaSocketTools.h"
#include "RiaPreferences.h"
#include "RiaSocketDataTransfer.h"
#include "RiaSocketServer.h"
#include "Rim3dOverlayInfoConfig.h"
#include "RimCaseCollection.h"
#include "RimCellEdgeColors.h"
#include "RimCellRangeFilterCollection.h"
#include "RimEclipseCase.h"
#include "RimEclipseCellColors.h"
#include "RimEclipseInputCase.h"
#include "RimEclipseInputPropertyCollection.h"
#include "RimEclipsePropertyFilterCollection.h"
#include "RimEclipseView.h"
#include "RimIdenticalGridCaseGroup.h"
#include "RimReservoirCellResultsStorage.h"
#include "RimSimWellInViewCollection.h"
#include "cvfTimer.h"
#include <QTcpSocket>
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimEclipseCase* RiaSocketTools::findCaseFromArgs( RiaSocketServer* server, const QList<QByteArray>& args )
{
RimEclipseCase* rimCase = nullptr;
int caseId = -1;
if ( args.size() > 1 )
{
caseId = args[1].toInt();
}
rimCase = server->findReservoir( caseId );
if ( rimCase == nullptr )
{
// TODO: Display error message a different place to avoid socket comm to be halted.
// server->showMessage(RiaSocketServer::tr("ResInsight SocketServer: \n") + RiaSocketServer::tr("Could not find
// the Case with CaseId : \"%1\"").arg(caseId));
}
return rimCase;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaSocketTools::getCaseInfoFromCase( RimCase* rimCase, qint64& caseId, QString& caseName, QString& caseType, qint64& caseGroupId )
{
CVF_ASSERT( rimCase );
caseId = rimCase->caseId;
caseName = rimCase->caseUserDescription;
RimEclipseCase* eclCase = dynamic_cast<RimEclipseCase*>( rimCase );
RimCaseCollection* caseCollection = nullptr;
if ( eclCase )
{
caseCollection = eclCase->parentCaseCollection();
}
if ( caseCollection )
{
caseGroupId = caseCollection->parentCaseGroup()->groupId;
if ( RimIdenticalGridCaseGroup::isStatisticsCaseCollection( caseCollection ) )
{
caseType = "StatisticsCase";
}
else
{
caseType = "SourceCase";
}
}
else
{
caseGroupId = -1;
if ( dynamic_cast<RimEclipseInputCase*>( rimCase ) )
{
caseType = "InputCase";
}
else if ( eclCase )
{
caseType = "ResultCase";
}
else
{
caseType = "GeoMechCase";
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RiaSocketTools::writeBlockData( RiaSocketServer* server, QTcpSocket* socket, const char* data, quint64 bytesToWrite )
{
cvf::Timer timer;
QStringList errorMessages;
bool writeSucceded = RiaSocketDataTransfer::writeBlockDataToSocket( socket, data, bytesToWrite, errorMessages );
if ( server )
{
for ( int i = 0; i < errorMessages.size(); i++ )
{
server->showErrorMessage( errorMessages[i] );
}
}
return writeSucceded;
}

View File

@@ -0,0 +1,41 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
class RimCase;
class RiaSocketServer;
class RimEclipseCase;
class QTcpSocket;
#include <QByteArray>
#include <QList>
#define PMonLog( MessageString ) RiuMainWindow::instance()->processMonitor()->addStringToLog( MessageString );
class RiaSocketTools
{
public:
static RimEclipseCase* findCaseFromArgs( RiaSocketServer* server, const QList<QByteArray>& args );
static void
getCaseInfoFromCase( RimCase* rimCase, qint64& caseId, QString& caseName, QString& caseType, qint64& caseGroupId );
static bool writeBlockData( RiaSocketServer* server, QTcpSocket* socket, const char* data, quint64 bytesToWrite );
};

View File

@@ -0,0 +1,342 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RiaSocketCommand.h"
#include "RiaSocketServer.h"
#include "RiaSocketTools.h"
#include "RigEclipseCaseData.h"
#include "RigGridBase.h"
#include "RigSimWellData.h"
#include "RimEclipseCase.h"
#include "cvfCollection.h"
#include <QTcpSocket>
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
class RiaGetWellNames : public RiaSocketCommand
{
public:
static QString commandName() { return QString( "GetWellNames" ); }
bool interpretCommand( RiaSocketServer* server, const QList<QByteArray>& args, QDataStream& socketStream ) override
{
int caseId = args[1].toInt();
RimEclipseCase* rimCase = server->findReservoir( caseId );
if ( !rimCase )
{
server->showErrorMessage( RiaSocketServer::tr( "ResInsight SocketServer: \n" ) +
RiaSocketServer::tr( "Could not find the case with ID : \"%1\"" ).arg( caseId ) );
return true;
}
std::vector<QString> wellNames;
const cvf::Collection<RigSimWellData>& wells = rimCase->eclipseCaseData()->wellResults();
for ( size_t wIdx = 0; wIdx < wells.size(); ++wIdx )
{
wellNames.push_back( wells[wIdx]->m_wellName );
}
quint64 byteCount = sizeof( quint64 );
quint64 wellCount = wellNames.size();
for ( size_t wIdx = 0; wIdx < wellCount; wIdx++ )
{
byteCount += wellNames[wIdx].size() * sizeof( QChar );
}
socketStream << byteCount;
socketStream << wellCount;
for ( size_t wIdx = 0; wIdx < wellCount; wIdx++ )
{
socketStream << wellNames[wIdx];
}
return true;
}
};
static bool RiaGetWellNames_init =
RiaSocketCommandFactory::instance()->registerCreator<RiaGetWellNames>( RiaGetWellNames::commandName() );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
class RiaGetWellStatus : public RiaSocketCommand
{
public:
static QString commandName() { return QString( "GetWellStatus" ); }
bool interpretCommand( RiaSocketServer* server, const QList<QByteArray>& args, QDataStream& socketStream ) override
{
int caseId = args[1].toInt();
QString wellName = args[2];
RimEclipseCase* rimCase = server->findReservoir( caseId );
if ( !rimCase )
{
server->showErrorMessage( RiaSocketServer::tr( "ResInsight SocketServer: \n" ) +
RiaSocketServer::tr( "Could not find the case with ID : \"%1\"" ).arg( caseId ) );
return true;
}
// Create a list of all the requested time steps
std::vector<size_t> requestedTimesteps;
// First find the well result for the correct well
const cvf::Collection<RigSimWellData>& allWellRes = rimCase->eclipseCaseData()->wellResults();
cvf::ref<RigSimWellData> currentWellResult;
for ( size_t tsIdx = 0; tsIdx < allWellRes.size(); ++tsIdx )
{
if ( allWellRes[tsIdx]->m_wellName == wellName )
{
currentWellResult = allWellRes[tsIdx];
break;
}
}
if ( currentWellResult.isNull() )
{
server->showErrorMessage( RiaSocketServer::tr( "ResInsight SocketServer: \n" ) +
RiaSocketServer::tr( "Could not find the well with name : \"%1\"" ).arg( wellName ) );
return true;
}
if ( args.size() <= 3 )
{
// Select all timesteps.
for ( size_t tsIdx = 0; tsIdx < currentWellResult->m_resultTimeStepIndexToWellTimeStepIndex.size(); ++tsIdx )
{
requestedTimesteps.push_back( tsIdx );
}
}
else
{
bool timeStepReadError = false;
for ( int argIdx = 3; argIdx < args.size(); ++argIdx )
{
bool conversionOk = false;
int tsIdx = args[argIdx].toInt( &conversionOk );
if ( conversionOk )
{
requestedTimesteps.push_back( tsIdx );
}
else
{
timeStepReadError = true;
}
}
if ( timeStepReadError )
{
server->showErrorMessage(
RiaSocketServer::tr( "ResInsight SocketServer: riGetGridProperty : \n" ) +
RiaSocketServer::tr( "An error occurred while interpreting the requested timesteps." ) );
}
}
std::vector<QString> wellTypes;
std::vector<qint32> wellStatuses;
for ( size_t tsIdx = 0; tsIdx < requestedTimesteps.size(); ++tsIdx )
{
QString wellType = "NotDefined";
qint32 wellStatus = 0;
if ( currentWellResult->hasWellResult( tsIdx ) )
{
switch ( currentWellResult->wellResultFrame( tsIdx ).m_productionType )
{
case RigWellResultFrame::PRODUCER:
wellType = "Producer";
break;
case RigWellResultFrame::OIL_INJECTOR:
wellType = "OilInjector";
break;
case RigWellResultFrame::WATER_INJECTOR:
wellType = "WaterInjector";
break;
case RigWellResultFrame::GAS_INJECTOR:
wellType = "GasInjector";
break;
}
wellStatus = currentWellResult->wellResultFrame( tsIdx ).m_isOpen ? 1 : 0;
}
wellTypes.push_back( wellType );
wellStatuses.push_back( wellStatus );
}
quint64 byteCount = sizeof( quint64 );
quint64 timeStepCount = wellTypes.size();
for ( size_t tsIdx = 0; tsIdx < timeStepCount; tsIdx++ )
{
byteCount += wellTypes[tsIdx].size() * sizeof( QChar );
byteCount += sizeof( qint32 );
}
socketStream << byteCount;
socketStream << timeStepCount;
for ( size_t tsIdx = 0; tsIdx < timeStepCount; tsIdx++ )
{
socketStream << wellTypes[tsIdx];
socketStream << wellStatuses[tsIdx];
}
return true;
}
};
static bool RiaGetWellStatus_init =
RiaSocketCommandFactory::instance()->registerCreator<RiaGetWellStatus>( RiaGetWellStatus::commandName() );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
class RiaGetWellCells : public RiaSocketCommand
{
public:
static QString commandName() { return QString( "GetWellCells" ); }
bool interpretCommand( RiaSocketServer* server, const QList<QByteArray>& args, QDataStream& socketStream ) override
{
int caseId = args[1].toInt();
QString wellName = args[2];
size_t timeStepIdx = args[3].toInt() - 1; // Interpret timeStepIdx from octave as 1-based
RimEclipseCase* rimCase = server->findReservoir( caseId );
if ( !rimCase )
{
server->showErrorMessage( RiaSocketServer::tr( "ResInsight SocketServer: \n" ) +
RiaSocketServer::tr( "Could not find the case with ID : \"%1\"" ).arg( caseId ) );
socketStream << (quint64)0;
return true;
}
const cvf::Collection<RigSimWellData>& allWellRes = rimCase->eclipseCaseData()->wellResults();
cvf::ref<RigSimWellData> currentWellResult;
for ( size_t cIdx = 0; cIdx < allWellRes.size(); ++cIdx )
{
if ( allWellRes[cIdx]->m_wellName == wellName )
{
currentWellResult = allWellRes[cIdx];
break;
}
}
if ( currentWellResult.isNull() )
{
server->showErrorMessage( RiaSocketServer::tr( "ResInsight SocketServer: \n" ) +
RiaSocketServer::tr( "Could not find the well with name : \"%1\"" ).arg( wellName ) );
socketStream << (quint64)0;
return true;
}
if ( !currentWellResult->hasWellResult( timeStepIdx ) )
{
socketStream << (quint64)0;
return true;
}
std::vector<qint32> cellIs;
std::vector<qint32> cellJs;
std::vector<qint32> cellKs;
std::vector<qint32> gridIndices;
std::vector<qint32> cellStatuses;
std::vector<qint32> branchIds;
std::vector<qint32> segmentIds;
// Fetch results
const RigWellResultFrame& wellResFrame = currentWellResult->wellResultFrame( timeStepIdx );
std::vector<RigGridBase*> grids;
rimCase->eclipseCaseData()->allGrids( &grids );
for ( size_t bIdx = 0; bIdx < wellResFrame.m_wellResultBranches.size(); ++bIdx )
{
const std::vector<RigWellResultPoint>& branchResPoints =
wellResFrame.m_wellResultBranches[bIdx].m_branchResultPoints;
for ( size_t rpIdx = 0; rpIdx < branchResPoints.size(); ++rpIdx )
{
const RigWellResultPoint& resPoint = branchResPoints[rpIdx];
if ( resPoint.isCell() )
{
size_t i;
size_t j;
size_t k;
size_t gridIdx = resPoint.m_gridIndex;
grids[gridIdx]->ijkFromCellIndex( resPoint.m_gridCellIndex, &i, &j, &k );
bool isOpen = resPoint.m_isOpen;
int branchId = resPoint.m_ertBranchId;
int segmentId = resPoint.m_ertSegmentId;
cellIs.push_back( static_cast<qint32>( i + 1 ) ); // NB: 1-based index in Octave
cellJs.push_back( static_cast<qint32>( j + 1 ) ); // NB: 1-based index in Octave
cellKs.push_back( static_cast<qint32>( k + 1 ) ); // NB: 1-based index in Octave
gridIndices.push_back( static_cast<qint32>( gridIdx ) );
cellStatuses.push_back( static_cast<qint32>( isOpen ) );
branchIds.push_back( branchId );
segmentIds.push_back( segmentId );
}
}
}
quint64 byteCount = sizeof( quint64 );
quint64 cellCount = cellIs.size();
byteCount += cellCount * ( 7 * sizeof( qint32 ) );
socketStream << byteCount;
socketStream << cellCount;
for ( size_t cIdx = 0; cIdx < cellCount; cIdx++ )
{
socketStream << cellIs[cIdx];
socketStream << cellJs[cIdx];
socketStream << cellKs[cIdx];
socketStream << gridIndices[cIdx];
socketStream << cellStatuses[cIdx];
socketStream << branchIds[cIdx];
socketStream << segmentIds[cIdx];
}
return true;
}
};
static bool RiaGetWellCells_init =
RiaSocketCommandFactory::instance()->registerCreator<RiaGetWellCells>( RiaGetWellCells::commandName() );