diff --git a/ApplicationCode/ReservoirDataModel/RigNNCData.cpp b/ApplicationCode/ReservoirDataModel/RigNNCData.cpp index 939a5ec967..7d66310b0d 100644 --- a/ApplicationCode/ReservoirDataModel/RigNNCData.cpp +++ b/ApplicationCode/ReservoirDataModel/RigNNCData.cpp @@ -293,6 +293,28 @@ const std::vector* RigNNCData::dynamicConnectionScalarResultByName(const return nullptr; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RigNNCData::availableProperties(NNCResultType resultType) const +{ + std::vector properties; + + for (auto it : m_connectionResults) + { + if (resultType == NNC_STATIC && it.second.size() == 1 && it.second[0].size() > 0) + { + properties.push_back(it.first); + } + else if (resultType == NNC_DYNAMIC && it.second.size() > 1 && it.second[0].size() > 0) + { + properties.push_back(it.first); + } + } + + return properties; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ReservoirDataModel/RigNNCData.h b/ApplicationCode/ReservoirDataModel/RigNNCData.h index c7fe6f3dc3..b9548614a1 100644 --- a/ApplicationCode/ReservoirDataModel/RigNNCData.h +++ b/ApplicationCode/ReservoirDataModel/RigNNCData.h @@ -58,6 +58,13 @@ public: class RigNNCData : public cvf::Object { public: + enum NNCResultType + { + NNC_DYNAMIC, + NNC_STATIC, + NNC_GENERATED + }; + static QString propertyNameFluxWat() { return "FLRWAT"; } static QString propertyNameFluxOil() { return "FLROIL"; } static QString propertyNameFluxGas() { return "FLRGAS"; } @@ -82,6 +89,8 @@ public: const std::vector< std::vector >* dynamicConnectionScalarResultByName(const QString& nncDataType) const; const std::vector* dynamicConnectionScalarResultByName(const QString& nncDataType, size_t timeStep) const; + std::vector availableProperties(NNCResultType resultType) const; + void setScalarResultIndex(const QString& nncDataType, size_t scalarResultIndex); bool hasScalarValues(size_t scalarResultIndex); diff --git a/ApplicationCode/SocketInterface/RiaNNCCommands.cpp b/ApplicationCode/SocketInterface/RiaNNCCommands.cpp index 01d8bd3bd8..226327011a 100644 --- a/ApplicationCode/SocketInterface/RiaNNCCommands.cpp +++ b/ApplicationCode/SocketInterface/RiaNNCCommands.cpp @@ -214,3 +214,74 @@ public: }; static bool RiaGetStaticNNCValues_init = RiaSocketCommandFactory::instance()->registerCreator(RiaGetStaticNNCValues::commandName()); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +class RiaGetNNCPropertyNames: public RiaSocketCommand +{ +public: + static QString commandName () { return QString("GetNNCPropertyNames"); } + + virtual bool interpretCommand(RiaSocketServer* server, const QList& args, QDataStream& socketStream) + { + 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 propertyTypes; + std::vector propertyNames; + + std::vector resultTypes; + std::vector 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 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::commandName()); diff --git a/OctavePlugin/CMakeLists.txt b/OctavePlugin/CMakeLists.txt index c0a3436b28..642d82387d 100644 --- a/OctavePlugin/CMakeLists.txt +++ b/OctavePlugin/CMakeLists.txt @@ -9,6 +9,7 @@ set(CPP_SOURCES riGetActiveCellInfo.cpp riGetMainGridDimensions.cpp riGetNNCConnections.cpp + riGetNNCPropertyNames.cpp riGetCurrentCase.cpp riGetCaseGroups.cpp riGetDynamicNNCValues.cpp @@ -178,6 +179,7 @@ if (RESINSIGHT_OCTAVE_PLUGIN_QMAKE AND RESINSIGHT_OCTAVE_PLUGIN_MKOCTFILE) "${CMAKE_CURRENT_BINARY_DIR}/riGetActiveCellInfo.oct" "${CMAKE_CURRENT_BINARY_DIR}/riGetMainGridDimensions.oct" "${CMAKE_CURRENT_BINARY_DIR}/riGetNNCConnections.oct" + "${CMAKE_CURRENT_BINARY_DIR}/riGetNNCPropertyNames.oct" "${CMAKE_CURRENT_BINARY_DIR}/riGetDynamicNNCValues.oct" "${CMAKE_CURRENT_BINARY_DIR}/riGetStaticNNCValues.oct" "${CMAKE_CURRENT_BINARY_DIR}/riGetCurrentCase.oct" diff --git a/OctavePlugin/riGetNNCPropertyNames.cpp b/OctavePlugin/riGetNNCPropertyNames.cpp new file mode 100644 index 0000000000..5223f8d49c --- /dev/null +++ b/OctavePlugin/riGetNNCPropertyNames.cpp @@ -0,0 +1,152 @@ +#include +#include +#include + +#include "riSettings.h" + +void getNNCPropertyNames(std::vector& propNames, std::vector& propTypes, const QString &hostName, quint16 port, + const qint64& caseId) +{ + QString serverName = hostName; + quint16 serverPort = port; + + QTcpSocket socket; + socket.connectToHost(serverName, serverPort); + + if (!socket.waitForConnected(riOctavePlugin::connectTimeOutMilliSecs)) + { + error((("Connection: ") + socket.errorString()).toLatin1().data()); + return; + } + + // Create command and send it: + + QString command; + command += QString("GetNNCPropertyNames") + " " + QString::number(caseId); + QByteArray cmdBytes = command.toLatin1(); + + QDataStream socketStream(&socket); + socketStream.setVersion(riOctavePlugin::qtDataStreamVersion); + + socketStream << (qint64)(cmdBytes.size()); + socket.write(cmdBytes); + + // Get response. First wait for the header + + while (socket.bytesAvailable() < (int)(sizeof(quint64))) + { + if (!socket.waitForReadyRead(riOctavePlugin::longTimeOutMilliSecs)) + { + error((("Waiting for header: ") + socket.errorString()).toLatin1().data()); + return; + } + } + + quint64 byteCount; + socketStream >> byteCount; + QString byteCountString = QString::number(byteCount); + + //error(byteCountString.toLatin1().data()); + + while (socket.bytesAvailable() < (int)(byteCount)) + { + if (!socket.waitForReadyRead(riOctavePlugin::longTimeOutMilliSecs)) + { + error((("Waiting for data: ") + socket.errorString()).toLatin1().data()); + return; + } + OCTAVE_QUIT; + } + + quint64 propCount; + socketStream >> propCount; + + QString propName; + QString propType; + + for (size_t i = 0; i < propCount; i++) + { + socketStream >> propName; + socketStream >> propType; + + propNames.push_back(propName); + propTypes.push_back(propType); + } + + return; +} + + + +DEFUN_DLD (riGetNNCPropertyNames, args, nargout, + "Usage:\n" + "\n" + " riGetNNCPropertyNames([CaseId])\n" + "\n" + "This function returns the name and type of all the NNC properties in the case as a Vector of Structures.\n" + "The Structure is defined as: \n" + "PropertyInfo {\n" + " PropName = string # Name of the NNC property as received from the analysis tool \n" + " PropType = string # The type of the property: \"StaticNative\", \"DynamicNative\", \"Generated\" \n" + "} \n" + "If the CaseId is not defined, ResInsight's Current Case is used.\n" + ) +{ + int nargin = args.length (); + if (nargin > 1) + { + error("riGetNNCPropertyNames: Too many arguments, this function takes one optional argument.\n"); + print_usage(); + } + else if (nargout != 1) + { + error("riGetNNCPropertyNames: Wrong number of output arguments, this function requires one output argument.\n"); + print_usage(); + } + else + { + qint64 argCaseId = -1; + + if (nargin == 1) + { + argCaseId = args(0).uint_value(); + } + + std::vector propertyNames; + std::vector propertyTypes; + + getNNCPropertyNames(propertyNames, propertyTypes, "127.0.0.1", 40001, argCaseId); + + size_t caseCount = propertyNames.size(); + + if (propertyNames.size() != propertyTypes.size() ) + { + error("riGetNNCPropertyNames: Inconsistent data received from ResInsight.\n"); + } + else + { + // Create cells with N items for each field in the data structure + + Cell cellValuesB(caseCount, 1); + Cell cellValuesC(caseCount, 1); + + for (size_t i = 0; i < caseCount; i++) + { + cellValuesB(i) = propertyNames[i].toLatin1().data(); + cellValuesC(i) = propertyTypes[i].toLatin1().data(); + } + + // Build a map between the field name and field cell values + + octave_map m; + + m.assign(riOctavePlugin::propertyInfo_PropName, cellValuesB); + m.assign(riOctavePlugin::propertyInfo_PropType, cellValuesC); + + return octave_value(m); + } + } + + return octave_value(); +} +