Make it possible to build Octave plugins independent to main build

The building of Octave plugins within main ResInsight build on RHEL8 cause the build to use gcc-12, and gcc-12 is extremely slow when building opm-common.

Adjust the CMake configuration so it is possible to build the Octave plugins as an independent build job. The plugin binaries can then be uploaded to an external server. The main ResInsight build  can download the binaries and include them in the install package for ResInsight.

Use the flag RESINSIGHT_USE_EXTERNAL_OCTAVE_PLUGINS to download external Octave plugin binaries.
This commit is contained in:
Magne Sjaastad
2024-06-04 07:42:50 +02:00
committed by GitHub
parent 1c899df063
commit b050cac1d2
47 changed files with 566 additions and 271 deletions

33
Octave/CMakeLists.txt Normal file
View File

@@ -0,0 +1,33 @@
cmake_minimum_required(VERSION 3.15)
project(OctavePlugins)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
find_package(Octave)
if(CEE_USE_QT6)
find_package(
Qt6
COMPONENTS
REQUIRED Core Gui OpenGL Widgets Network
)
set(QT_LIBRARIES Qt6::Core Qt6::Gui Qt6::OpenGL Qt6::Widgets Qt6::Network)
qt_standard_project_setup()
else()
find_package(
Qt5
COMPONENTS
REQUIRED Core Gui OpenGL Widgets Network
)
set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::OpenGL Qt5::Widgets Qt5::Network)
endif()
add_subdirectory(OctavePlugin)
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
set(CPACK_GENERATOR TGZ)
elseif(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
set(CPACK_GENERATOR ZIP)
endif()
include(CPack)

View File

@@ -0,0 +1,278 @@
# Some of the functionality in this CMakeLists.txt might be easier to maintain
# if we use a CMake macro to find configuration info for Octave This file is
# currently (2.8.12) not part of default CMake installation See
# http://www.cmake.org/Wiki/CMakeUserFindOctave
set(CPP_SOURCES
riGetActiveCellProperty.cpp
riSetActiveCellProperty.cpp
riGetActiveCellInfo.cpp
riGetMainGridDimensions.cpp
riGetNNCConnections.cpp
riGetNNCPropertyNames.cpp
riGetCurrentCase.cpp
riGetCaseGroups.cpp
riGetDynamicNNCValues.cpp
riGetStaticNNCValues.cpp
riGetSelectedCases.cpp
riGetSelectedCells.cpp
riGetCases.cpp
riGetTimeStepDates.cpp
riGetTimeStepDays.cpp
riGetGridDimensions.cpp
riGetCoarseningInfo.cpp
riGetCellCenters.cpp
riGetActiveCellCenters.cpp
riGetCellCorners.cpp
riGetActiveCellCorners.cpp
riGetGridProperty.cpp
riSetGridProperty.cpp
riGetGridPropertyForSelectedCells.cpp
riGetPropertyNames.cpp
riGetWellNames.cpp
riGetWellStatus.cpp
riGetWellCells.cpp
riSetNNCProperty.cpp
)
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
# since the compiler passes the option to the linker, double quoting is
# necessary
set(RPATH_COMMAND "-Wl,-rpath,'\\$$ORIGIN'")
endif()
# recreate the magic that CMake does for MacOS X frameworks in the include list
# when we call mkoctfile as a custom command
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
set(QT_INCLUDES)
set(QT_FRAMEWORKS)
# QT_INCLUDE_DIR contains two items; the first is the directory containing
# header files, the second is the framework. This setup is specially processed
# in include_directories (); CMake will add -F before the frameworks. We will
# have to replicate that setup here when we want to pass it directly to a
# command see <http://www.cmake.org/Bug/print_bug_page.php?bug_id=10632>
foreach(item IN ITEMS ${QT_QTNETWORK_INCLUDE_DIR} ${QT_QTCORE_INCLUDE_DIR}
${QT_INCLUDE_DIR}
)
if("${item}" MATCHES ".framework$")
get_filename_component(frmwrk_path ${item} PATH)
get_filename_component(frmwrk_name ${item} NAME_WE)
# mkoctfile doesn't support arbitrary compiler command, so we must wrap in
# -Wl, to pass to the linker
list(APPEND QT_FRAMEWORKS "-Wl,-F${frmwrk_path}")
list(APPEND QT_FRAMEWORKS "-Wl,-framework,${frmwrk_name}")
else()
list(APPEND QT_INCLUDES "-I${item}")
endif()
endforeach(item)
if(QT_INCLUDES)
list(REMOVE_DUPLICATES QT_INCLUDES)
endif()
if(QT_FRAMEWORKS)
list(REMOVE_DUPLICATES QT_FRAMEWORKS)
endif()
endif()
message(STATUS "Compiling Octave plugins using : ${OCTAVE_MKOCTFILE}")
if(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
option(RESINSIGHT_OCTAVE_PLUGIN_QT
"Compile Octave plugin using Qt located insided Octave root folder" ON
)
endif(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
if(RESINSIGHT_OCTAVE_PLUGIN_QT)
message(
STATUS
"Compiling Octave plugins using custom Qt located at ${OCTAVE_ROOT_DIR}"
)
if(EXISTS ${OCTAVE_ROOT_DIR}/qt5)
set(OCTAVE_QT_INCLUDE_DIR ${OCTAVE_ROOT_DIR}/qt5/include)
set(OCTAVE_QT_QTCORE_INCLUDE_DIR ${OCTAVE_ROOT_DIR}/qt5/include/QtCore)
set(OCTAVE_QT_QTNETWORK_INCLUDE_DIR
${OCTAVE_ROOT_DIR}/qt5/include/QtNetwork
)
set(OCTAVE_QT_LIBRARY_DIR ${OCTAVE_ROOT_DIR}/qt5/lib)
set(OCTAVE_QT_QTCORE_LIB Qt5Core)
set(OCTAVE_QT_QTNETWORK_LIB Qt5Network)
else()
set(OCTAVE_QT_INCLUDE_DIR ${OCTAVE_ROOT_DIR}/include)
set(OCTAVE_QT_QTCORE_INCLUDE_DIR ${OCTAVE_ROOT_DIR}/include/QtCore)
set(OCTAVE_QT_QTNETWORK_INCLUDE_DIR ${OCTAVE_ROOT_DIR}/include/QtNetwork)
set(OCTAVE_QT_LIBRARY_DIR ${OCTAVE_ROOT_DIR}/lib)
set(OCTAVE_QT_QTCORE_LIB QtCore4)
set(OCTAVE_QT_QTNETWORK_LIB QtNetwork4)
endif(EXISTS ${OCTAVE_ROOT_DIR}/qt5)
else()
if(Qt5Core_FOUND)
message(STATUS "Compiling Octave plugins using system Qt5")
set(OCTAVE_QT_QTCORE_INCLUDE_DIR ${Qt5Core_INCLUDE_DIRS})
set(OCTAVE_QT_QTNETWORK_INCLUDE_DIR ${Qt5Network_INCLUDE_DIRS})
set(OCTAVE_QT_LIBRARY_DIR ${QT_LIBRARY_DIR})
set(OCTAVE_QT_QTCORE_LIB Qt5Core)
set(OCTAVE_QT_QTNETWORK_LIB Qt5Network)
endif(Qt5Core_FOUND)
endif(RESINSIGHT_OCTAVE_PLUGIN_QT)
list(APPEND MKOCTFILE_INCLUDE_DIRS ${OCTAVE_QT_INCLUDE_DIR})
list(APPEND MKOCTFILE_INCLUDE_DIRS ${OCTAVE_QT_QTCORE_INCLUDE_DIR})
list(APPEND MKOCTFILE_INCLUDE_DIRS ${OCTAVE_QT_QTNETWORK_INCLUDE_DIR})
# Add socket interface source code folder
list(APPEND MKOCTFILE_INCLUDE_DIRS
${CMAKE_CURRENT_SOURCE_DIR}/../../ApplicationLibCode/SocketInterface
)
list(REMOVE_DUPLICATES MKOCTFILE_INCLUDE_DIRS)
foreach(item ${MKOCTFILE_INCLUDE_DIRS})
list(APPEND MKOCTFILE_INCLUDE_TEMP -I${item})
endforeach(item)
string(REPLACE ";" " " MKOCTFILE_INCLUDE_TEMP "${MKOCTFILE_INCLUDE_TEMP}")
# Use special command to avoid double quoting in add_custom_command()
separate_arguments(
MKOCTFILE_INCLUDE_COMMAND_STRING WINDOWS_COMMAND "${MKOCTFILE_INCLUDE_TEMP}"
)
# Clear the list of binary oct files to be produced
set(OCTAVE_BINARY_OCT_FILES)
if(OCTAVE_MKOCTFILE)
foreach(srcFileName IN LISTS CPP_SOURCES)
if(NOT IS_ABSOLUTE "${srcFileName}")
set(srcFileName "${CMAKE_CURRENT_SOURCE_DIR}/${srcFileName}")
endif()
get_filename_component(baseFilename "${srcFileName}" NAME_WE)
set(octFileName "${CMAKE_CURRENT_BINARY_DIR}/${baseFilename}.oct")
if(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
add_custom_command(
OUTPUT "${octFileName}"
COMMAND set "OCTAVE_HOME=${OCTAVE_ROOT_DIR}"
COMMAND set "PATH=%OCTAVE_HOME%\\bin;%PATH%"
COMMAND
${OCTAVE_MKOCTFILE} ${MKOCTFILE_INCLUDE_COMMAND_STRING}
${RPATH_COMMAND} -L${OCTAVE_QT_LIBRARY_DIR} -l${OCTAVE_QT_QTCORE_LIB}
-l${OCTAVE_QT_QTNETWORK_LIB} -o "${octFileName}" "${srcFileName}"
DEPENDS "${srcFileName}"
COMMENT "===> Generating ${octFileName}"
)
elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
add_custom_command(
OUTPUT "${octFileName}"
COMMAND
${OCTAVE_MKOCTFILE} ${QT_INCLUDES} ${QT_FRAMEWORKS}
-I${ResInsight_SOURCE_DIR}/ApplicationLibCode/SocketInterface
${RPATH_COMMAND} -L${QT_LIBRARY_DIR} -Wl,-framework,QtCore
-Wl,-framework,QtNetwork -o "${octFileName}" "${srcFileName}"
DEPENDS "${srcFileName}"
COMMENT "===> Generating ${octFileName}"
)
else()
add_custom_command(
OUTPUT "${octFileName}"
COMMAND
OCTAVE_HOME=${OCTAVE_ROOT_DIR} ${OCTAVE_MKOCTFILE}
${MKOCTFILE_INCLUDE_COMMAND_STRING} ${RPATH_COMMAND}
-L${OCTAVE_QT_LIBRARY_DIR} -l${OCTAVE_QT_QTCORE_LIB}
-l${OCTAVE_QT_QTNETWORK_LIB} -o "${octFileName}" "${srcFileName}"
DEPENDS "${srcFileName}"
COMMENT "===> Generating ${octFileName}"
)
endif()
list(APPEND OCTAVE_BINARY_OCT_FILES "${octFileName}")
endforeach()
# Create depencedy string represeting the full path to all generated oct-files
foreach(item ${CPP_SOURCES})
string(REPLACE ".cpp" ".oct" item ${item})
list(APPEND DEPENDENCY_STRING ${CMAKE_CURRENT_BINARY_DIR}/${item})
endforeach(item)
# message("DEPENDENCY_STRING : ${DEPENDENCY_STRING}")
add_custom_target(
octave_plugins ALL
DEPENDS ${DEPENDENCY_STRING}
SOURCES ${CPP_SOURCES} riSettings.h
)
# Copy Octave generated *.oct files to application folder, will make it
# possible to use Octave functions directly from the location of the
# ResInsight binaries
if(TARGET ResInsight)
message(
STATUS
"Target ResInsight exists, add copy of Octave plugins to ApplicationExeCode folder"
)
# Make ResInsight dependant on Octave, makes it easiser to debug Octave
# functionality by compiling ResInsight
add_dependencies(ResInsight octave_plugins)
foreach(oct_bin ${OCTAVE_BINARY_OCT_FILES})
get_filename_component(Filename "${oct_bin}" NAME)
if(MSVC)
add_custom_command(
TARGET octave_plugins
POST_BUILD
COMMAND
${CMAKE_COMMAND} -E copy_if_different "${oct_bin}"
"${CMAKE_CURRENT_BINARY_DIR}/../../ApplicationExeCode/$<CONFIGURATION>/${Filename}"
)
else()
add_custom_command(
TARGET octave_plugins
POST_BUILD
COMMAND
${CMAKE_COMMAND} -E copy_if_different "${oct_bin}"
"${CMAKE_CURRENT_BINARY_DIR}/../../ApplicationExeCode/${Filename}"
)
endif(MSVC)
endforeach(oct_bin)
if(RESINSIGHT_PRIVATE_INSTALL)
install(FILES ${OCTAVE_BINARY_OCT_FILES}
DESTINATION ${RESINSIGHT_INSTALL_FOLDER}
)
else(RESINSIGHT_PRIVATE_INSTALL)
# probe for site location of .oct files
if(NOT OCTAVE_SITE_OCT_DIR)
find_program(
OCTAVE_CONFIG_COMMAND octave-config
DOC "Path to Octave component and library information retrieval"
)
exec_program(
${OCTAVE_CONFIG_COMMAND} ARGS
--oct-site-dir
OUTPUT_VARIABLE OCTAVE_SITE_OCT_DIR
)
set(OCTAVE_SITE_OCT_DIR
"${OCTAVE_SITE_OCT_DIR}"
CACHE LOCATION "Octave plugin directory"
)
endif(NOT OCTAVE_SITE_OCT_DIR)
install(FILES ${OCTAVE_BINARY_OCT_FILES}
DESTINATION ${OCTAVE_SITE_OCT_DIR}
)
endif(RESINSIGHT_PRIVATE_INSTALL)
else()
install(FILES ${OCTAVE_BINARY_OCT_FILES} DESTINATION .)
endif(TARGET ResInsight)
endif(OCTAVE_MKOCTFILE)

View File

@@ -0,0 +1,17 @@
Build configuration MinGW
==================================
http://wiki.octave.org/Windows_Installer
To be able to build with 64-bit indexing, run the following
./configure --enable-64
// To get changes from server
hg pull
hg update
http://hgbook.red-bean.com/read/a-tour-of-mercurial-the-basics.html

View File

@@ -0,0 +1,73 @@
#### Matrix[numSelectedCells][5] riGetSelectedCells([CaseId])
This function returns a two dimensional matrix containing the cell info for each selected cell in the case with `CaseId`.
The columns contain the following information:
[CaseId, GridIdx, I, J, K]
CaseId # The ID of the case the cell resides in.
GridIdx # The index of the grid the cell resides in.
# Main grid has index 0
I, J, K # 1-based index of the cell in the grid.
If the CaseId is not defined, ResInsight's Current Case is used.
#### Matrix[numSelectedCells][numTimestepsRequested] riGetGridPropertyForSelectedCells([CaseId], PropertyName, [RequestedTimeSteps], [PorosityModel = "Matrix"|"Fracture"] )
This function returns a two dimensional matrix: [numSelectedCells][numTimestepsRequested] containing the requested property data from the case with CaseId.
If the CaseId is not defined, ResInsight's Current Case is used.
The RequestedTimeSteps must contain a list of 1-based indices to the requested time steps. If not defined, all the time steps are returned.
#### Vector[PropertyInfo] riGetNNCPropertyNames([CaseId])
This function returns the name and type of all NNC properties in the case as a vector of structures.
The structure is defined as:
PropertyInfo {
PropName = string # Name of the property as received from
# the analysis tool
PropType = string # The type of the property: "StaticNative",
# "DynamicNative", "Generated"
}
If the CaseId is not defined, ResInsight's Current Case is used.
#### Matrix[numNNCConnections][2] riGetNNCConnections([CaseId])
This function returns a two dimensional matrix containing grid and IJK information about each NNC connection.
Each row contains a from and to cell for the connection.
The cells are specified in a structure defined as:
CellInfo = {
GridIndex = int # Index of the grid the cell resides in.
# Main grid has index 0.
I, J, K = int # 1-based index address of the cell in the grid.
}
#### Matrix[numConnections][numTimestepsRequested] riGetDynamicNNCValues([CaseId], PropertyName, [RequestedTimeSteps])
This function returns a two dimensional matrix: [Num Connections][Num Time Steps Requested] containing the value of the requested property from the case with CaseId. The order of connections is the same as the order from `riGetNNCConnectio
If the CaseId is not defined, ResInsight's Current Case is used.
The RequestedTimeSteps must contain a list of indices to the requested time steps. If not defined, all the timesteps are returned.
#### Vector[numConnections] riGetStaticNNCValues([CaseId], PropertyName)
This function returns a vector of values for the requested static property for each NNC connection. The order of connections is the same as the order from `riGetNNCConnections`.
If the CaseId is not defined, ResInsight's Current Case is used.
#### riSetNNCProperty(Matrix[numNNCConnections][numTimeSteps], [CaseId], PropertyName, [TimeStepIndices])
Interprets the supplied matrix as a property set defined for the NNC connections in the case, and puts the data into ResInsight as a "Generated" property with the name "PropertyName".
The "TimeStepIndices" argument is used to "label" all the steps present in the supplied data matrix and must thus be complete.
The time step data will then be put into ResInsight at the time steps requested.
If the CaseId is not defined, ResInsight's Current Case is used.

View File

@@ -0,0 +1,13 @@
addpath("/home/builder/Projects/ResInsightBuildDir/OctavePlugin");
tic();
PORO = riGetActiveCellProperty("PORO");
PERMX = riGetActiveCellProperty("PERMX");
IJK = riGetMainGridDimensions();
GENERATED = PORO .* PERMX;
riSetActiveCellProperty(GENERATED, "PORO*PERMX");
elapsed_time = toc();
disp("Elapsed time: "), disp(elapsed_time)

View File

@@ -0,0 +1,14 @@
# Keep the values in the first LGR only
CInfo = riGetActiveCellInfo();
SOIL = riGetActiveCellProperty("SOIL");
Mask = (CInfo(:,1) != 1);
LGRSOIL = SOIL;
i = 0;
for i = (1:columns(LGRSOIL))
LGRSOIL(Mask,i) = nan;
endfor
riSetActiveCellProperty(LGRSOIL, "LGRSOIL");

View File

@@ -0,0 +1,10 @@
SATNUM = riGetActiveCellProperty("SATNUM");
SOIL = riGetActiveCellProperty( "SOIL");
# Set all SOIL data to 0.0 for all cells with SATNUM different
# from 7 for timestep 1
GENERATED = (SATNUM == 7) .* SOIL(:, 1);
riSetActiveCellProperty(GENERATED, "SOIL_IN_SATNUM_Eq_7");

View File

@@ -0,0 +1,12 @@
addpath("C:/cmake_build/ResInsightQt5/OctavePlugin");
tic();
timeSteps = riGetTimeStepDates(0)
disp("Number of time steps: "), disp(size(timeSteps))
for i = 1:size(timeSteps)
SOIL = riGetActiveCellProperty(0, "SOIL", i);
avg = mean(SOIL)
endfor
elapsed_time = toc();
disp("Elapsed time: "), disp(elapsed_time)

View File

@@ -0,0 +1,17 @@
SOIL = riGetActiveCellProperty("SOIL");
SOILDIFF = SOIL;
# Calculate change of oil saturation from timestep to timestep
i = 0;
for timestep = SOIL
if (i > 0)
SOILDIFF(:,i) = timestep - SOIL(:,i);
endif
i++;
endfor
SOILDIFF(:,i) = 0;
riSetActiveCellProperty(SOILDIFF, "SOILDIFF");

View File

@@ -0,0 +1,24 @@
CInfo = riGetActiveCellInfo();
SOIL = riGetActiveCellProperty("SOIL");
SOIL_KAverage = SOIL;
SOIL_KAverage(:) = nan;
mini = min(CInfo(:,2))
maxi = max(CInfo(:,2))
minj = min(CInfo(:,3))
maxj = max(CInfo(:,3))
for i = mini:maxi
for j = minj:maxj
Mask = (CInfo(:,1) == 0) & (CInfo(:,2) == i) & (CInfo(:,3) == j) ;
for ts = (1:columns(SOIL))
SOIL_KAverage(Mask, ts) = mean(SOIL(Mask, ts));
endfor
endfor
endfor
riSetActiveCellProperty(SOIL_KAverage, "SOIL_KAverage");

View File

@@ -0,0 +1,13 @@
# Set all values to "Undefined" exept k-layers from 17 to 20
CInfo = riGetActiveCellInfo();
SOIL = riGetActiveCellProperty("SOIL");
Mask = (CInfo(:,4) < 17) | (CInfo(:,4) > 20)
LGRSOIL = SOIL;
i = 0;
for i = (1:columns(LGRSOIL))
LGRSOIL(Mask,i) = nan;
endfor
riSetActiveCellProperty(LGRSOIL, "KSlice");

View File

@@ -0,0 +1,147 @@
Considerations
==================================
This function interface towards ResInsight is currently a Draft,
and not addressing some issues. The known issues are :
1. How do we address Cases in the future when we have Case Groups ?
Where do we write/store the generated data ?
2. Users wants to run octave operations on several cases/groups.
There are two ways (at least) of doing that. Either from ResInsight:
1 Command to call a specified Octave Script for each selected Case
2 Creating Scripts that loops over all selections in ResInsight
Option 2 is needed if users wants to do cross-case operations
Option 1 seems intuitive for one case operations
How does these two relate ?
3. Do we need functions to retreive the selected/active cases/groups ?
4. Do we need functions to retreive info on what Parent cells an LGR occupies ?
Project Information
==================================
Vector[Casenames] riGetCaseNames()
Returns a vector of all the case names in the current ResInsight project
Use this to determine the number of cases as well
This probably needs some additions related to Case Groups
Retreiving Grid Metadata
==================================
Matrix[ActiveCells][8] riGetActiveCellInfo( [CaseName/CaseIndex])
Returns a two dimensional matrix: [ActiveCells][8]
Containing grid and ijk information about the cells from the Eclipse Case defined.
The columns contain the following information:
1: GridIndex: The index of the grid the cell resides in. (Main grid has index 0)
2, 3, 4: I, J, K: 1-based index address of the cell in the grid.
5: ParentGridIndex. The index to the grid that this cell's grid is residing in.
6, 7, 8: PI, PJ, PK address of the parent grid cell that this cell is a part of.
If the Eclipse Case is not defined, the active View in ResInsight is used.
Matrix[g0I, g0J, g0K; ... ; gnI, gnJ, gnK] riGetGridDimensions ( [CaseName/CaseIndex])
Returns a matrix: [NuberOfGrids][3]
containing the I, J, K dimensions of the main grid and all the LGR's
# Unnecessary ? # Vector(3)[ICount, JCount, KCount] riGetMainGridDimensions( [CaseName/CaseIndex])
# Unnecessary ? #
# Unnecessary ? # Returns a vector of size 3: [ICount, JCount, KCount]
# Unnecessary ? # Containing the dimensions of the main grid in the requested case.
# Unnecessary ? # If the Eclipse Case is not defined, the active View in ResInsight is used."
# Unnecessary ? #
# Unnecessary ? # NumberOfGrids riGetNumLGRs([Casename/CaseIndex])
# Unnecessary ? #
# Unnecessary ? # Returns an integer telling the number of LGRS in this case
Vector[Dates] riGetTimestepDates([Casename/CaseIndex])
Returns a vector of all the timesteps in a case as dates YYYY.MM.DD
Vector[Days] riGetTimestepDays([Casename/CaseIndex])
Returns a vector of all the timesteps in a case as days from start
Retreiving property data
==================================
Matrix[ActiveCells][Timesteps] riGetActiveCellProperty( [CaseName/CaseIndex], PropertyName )
Returns a two dimentional matrix: [ActiveCells][Timesteps]
Containing the requested property data from the Eclipse Case defined.
If the Eclipse Case is not defined, the active View in ResInsight is used.
Matrix[numI][numJ][numK][timeSteps] riGetGridProperty( [Casename/CaseIndex], GridIndex , PropertyName )
Matrix[numI][numJ][numK] riGetGridProperty( [Casename/CaseIndex], GridIndex , PropertyName, TimeStep )
Returns a 4D or 3D matrix of the requested property data for all the gridcells in the requested grid.
Grids are indexed from 0 - main grid to Max num LGR's
Writing Back to ResInsight
==================================
riSetActiveCellProperty( Matrix(nActiveCells, nTimesteps), [CaseName/CaseIndex], PropertyName )
Interprets the supplied matrix as an eclipse property set, and puts the data into
ResInsight as a "Generated" property with the name "PropertyName". The property
is added to the active case if no case specification is given, or to the Eclipse Case
named "CaseName" or to the case number "CaseIndex". "
riSetGridProperty( Matrix[numI][numJ][numK][timeSteps] , [CaseName/CaseIndex], GridIndex, PropertyName )
riSetGridProperty( Matrix[numI][numJ][numK], [CaseName/CaseIndex], GridIndex, PropertyName , TimeStep)
Interprets the supplied matrix as an eclipse property set defined for all cells in one of the grids in a case,
and puts the data into ResInsight as a "Generated" property with the name "PropertyName". The property
is added to the active case if no case specification is given, or to the Eclipse Case
named "CaseName" or to the case number "CaseIndex". "
Cell geometry functions:
=================================
Matrix[numI*Vector(3)][numJ*Vec(3)] [numK*Vec(3)] riGetCellCenters( [Casename/CaseIndex], GridIndex )
Returns the UTM coordinates (X, Y, Z) for centerpoint of all cells
Matrix[numI*8*Vector(3)][numJ*8*Vec(3)] [numK*8*Vec(3)] riGetCellCorners( [Casename/CaseIndex], GridIndex )
Returns the UTM coordinates of the each cells 8 corners
Well data functions
=================================
Vector[WellNames] riGetWellNames([Casename/CaseIndex])
Returns the names of all the wells in the case
Vector[ I, J, K, GridNr] riGetWellCells([Casename/CaseIndex], WellName/WellIndex, TimeStep, Producing/Injecting/Any)
Returns the cells that has the requested production status for the given well and timestep
Comments to remember/consider
=================================
<EFBFBD>Execute for all cases within group<75> in script-tree
Well trajectories (alternative trajectory like Planned / Drilled /Real Time/ Project ahead?)
riGetTrajectories(well, case) ? MD, Inc, Az, Norht(X), East(Y), TVD(Z),DLS,BUR,TR,prop/log/connections?
Operator to restrict operation to be carried out inside a given polygon object
riInside(polygon)
Set Octave function Case ID as a function parameter (enable for loops)
Write grid data to file on .grdecl format (and read & append?)

View File

@@ -0,0 +1,150 @@
#include <QtNetwork>
#include <QStringList>
#include <octave/oct.h>
#include "riSettings.h"
#include "RiaSocketDataTransfer.cpp" // NB! Include cpp-file to avoid linking of additional file in oct-compile configuration
void getActiveCellCenters(NDArray& cellCenterValues, const QString &hostName, quint16 port, const qint32& caseId, const QString& porosityModel)
{
QString serverName = hostName;
quint16 serverPort = port;
QTcpSocket socket;
socket.connectToHost(serverName, serverPort);
if (!socket.waitForConnected(riOctavePlugin::connectTimeOutMilliSecs))
{
error("Connection: %s",socket.errorString().toLatin1().data());
return;
}
// Create command and send it:
QString command = QString("GetActiveCellCenters %1 %2").arg(caseId).arg(porosityModel);
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)(2 * sizeof(quint64)))
{
if (!socket.waitForReadyRead(riOctavePlugin::longTimeOutMilliSecs))
{
error("Waiting for header: %s",socket.errorString().toLatin1().data());
return;
}
}
// Read timestep count and blocksize
quint64 activeCellCount;
quint64 byteCount;
socketStream >> activeCellCount;
socketStream >> byteCount;
if (!(byteCount && activeCellCount))
{
error ("Could not find the requested data in ResInsight");
return;
}
dim_vector dv;
dv.resize(2);
dv(0) = activeCellCount;
dv(1) = 3;
cellCenterValues.resize(dv);
double* internalMatrixData = cellCenterValues.fortran_vec();
QStringList errorMessages;
if (!RiaSocketDataTransfer::readBlockDataFromSocket(&socket, (char*)(internalMatrixData), byteCount, errorMessages))
{
for (int i = 0; i < errorMessages.size(); i++)
{
error("%s",errorMessages[i].toLatin1().data());
}
OCTAVE_QUIT;
}
return;
}
DEFUN_DLD (riGetActiveCellCenters, args, nargout,
"Usage:\n"
"\n"
" riGetActiveCellCenters([CaseId], [PorosityModel = <20>Matrix<69>|<7C>Fracture<72>] )\n"
"\n"
"This function returns the UTM coordinates (X, Y, Z) of the center point of all the cells in the grid.\n"
"If the CaseId is not defined, ResInsight<68>s Current Case is used.\n"
)
{
if (nargout < 1)
{
error("riGetActiveCellCenters: Missing output argument.\n");
print_usage();
return octave_value_list ();
}
int nargin = args.length ();
if (nargin > 2)
{
error("riGetActiveCellCenters: Too many arguments.\n");
print_usage();
return octave_value_list ();
}
qint32 caseId = -1;
std::string porosityModel = "Matrix";
if (nargin == 1)
{
if (riOctavePlugin::isOctaveValueNumeric(args(0)))
{
caseId = args(0).uint_value();
}
else
{
porosityModel = args(0).string_value();
}
}
else if (nargin == 2)
{
if (riOctavePlugin::isOctaveValueNumeric(args(0)))
{
caseId = args(0).uint_value();
porosityModel = args(1).string_value();
}
else
{
caseId = args(1).uint_value();
porosityModel = args(0).string_value();
}
}
if (porosityModel != "Matrix" && porosityModel != "Fracture")
{
error("riGetActiveCellProperty: The value for \"PorosityModel\" is unknown. Please use either \"Matrix\" or \"Fracture\"\n");
print_usage();
return octave_value_list ();
}
NDArray cellCenterValues;
getActiveCellCenters(cellCenterValues, "127.0.0.1", riOctavePlugin::portNumber(), caseId, porosityModel.c_str());
return octave_value(cellCenterValues);
}

View File

@@ -0,0 +1,150 @@
#include <QtNetwork>
#include <QStringList>
#include <octave/oct.h>
#include "riSettings.h"
#include "RiaSocketDataTransfer.cpp" // NB! Include cpp-file to avoid linking of additional file in oct-compile configuration
void getActiveCellCorners(NDArray& cellCornerValues, const QString &hostName, quint16 port, const qint32& caseId, const QString& porosityModel)
{
QString serverName = hostName;
quint16 serverPort = port;
QTcpSocket socket;
socket.connectToHost(serverName, serverPort);
if (!socket.waitForConnected(riOctavePlugin::connectTimeOutMilliSecs))
{
error("Connection: %s",socket.errorString().toLatin1().data());
return;
}
// Create command and send it:
QString command = QString("GetActiveCellCorners %1 %2").arg(caseId).arg(porosityModel);
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)(2 * sizeof(quint64)))
{
if (!socket.waitForReadyRead(riOctavePlugin::longTimeOutMilliSecs))
{
error("Waiting for header: %s",socket.errorString().toLatin1().data());
return;
}
}
// Read timestep count and blocksize
quint64 activeCellCount;
quint64 byteCount;
socketStream >> activeCellCount;
socketStream >> byteCount;
if (!(byteCount && activeCellCount))
{
error ("Could not find the requested data in ResInsight");
return;
}
dim_vector dv;
dv.resize(3);
dv(0) = activeCellCount;
dv(1) = 8;
dv(2) = 3;
cellCornerValues.resize(dv);
double* internalMatrixData = cellCornerValues.fortran_vec();
QStringList errorMessages;
if (!RiaSocketDataTransfer::readBlockDataFromSocket(&socket, (char*)(internalMatrixData), byteCount, errorMessages))
{
for (int i = 0; i < errorMessages.size(); i++)
{
error("%s",errorMessages[i].toLatin1().data());
}
OCTAVE_QUIT;
}
return;
}
DEFUN_DLD (riGetActiveCellCorners, args, nargout,
"Usage:\n"
"\n"
" riGetActiveCellCorners([CaseId], [PorosityModel = <20>Matrix<69>|<7C>Fracture<72>] )\n"
"\n"
"This function returns the UTM coordinates (X, Y, Z) of the 8 corners of each of the active cells.\n"
"If the CaseId is not defined, ResInsight<68>s Current Case is used.\n"
)
{
if (nargout < 1)
{
error("riGetActiveCellCorners: Missing output argument.\n");
print_usage();
return octave_value_list ();
}
int nargin = args.length ();
if (nargin > 2)
{
error("riGetActiveCellCorners: Too many arguments.\n");
print_usage();
return octave_value_list ();
}
qint32 caseId = -1;
std::string porosityModel = "Matrix";
if (nargin == 1)
{
if (riOctavePlugin::isOctaveValueNumeric(args(0)))
{
caseId = args(0).uint_value();
}
else
{
porosityModel = args(0).string_value();
}
}
else if (nargin == 2)
{
if (riOctavePlugin::isOctaveValueNumeric(args(0)))
{
caseId = args(0).uint_value();
porosityModel = args(1).string_value();
}
else
{
caseId = args(1).uint_value();
porosityModel = args(0).string_value();
}
}
if (porosityModel != "Matrix" && porosityModel != "Fracture")
{
error("riGetActiveCellProperty: The value for \"PorosityModel\" is unknown. Please use either \"Matrix\" or \"Fracture\"\n");
print_usage();
return octave_value_list ();
}
NDArray cellCornerValues;
getActiveCellCorners(cellCornerValues, "127.0.0.1", riOctavePlugin::portNumber(), caseId, porosityModel.c_str());
return octave_value(cellCornerValues);
}

View File

@@ -0,0 +1,168 @@
#include <QtNetwork>
#include <QStringList>
#include <octave/oct.h>
#include "riSettings.h"
#include "RiaSocketDataTransfer.cpp" // NB! Include cpp-file to avoid linking of additional file in oct-compile configuration
void getActiveCellInfo(int32NDArray& activeCellInfo, const QString &hostName, quint16 port, const qint64& caseId, const QString& porosityModel)
{
QString serverName = hostName;
quint16 serverPort = port;
QTcpSocket socket;
socket.connectToHost(serverName, serverPort);
if (!socket.waitForConnected(riOctavePlugin::connectTimeOutMilliSecs))
{
error("Connection: %s",socket.errorString().toLatin1().data());
return;
}
// Create command and send it:
QString command = QString("GetActiveCellInfo %1 %2").arg(caseId).arg(porosityModel);
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)(2*sizeof(quint64)))
{
if (!socket.waitForReadyRead(riOctavePlugin::longTimeOutMilliSecs))
{
error("Waiting for header: %s",socket.errorString().toLatin1().data());
return;
}
}
// Read timestep count and blocksize
quint64 columnCount;
quint64 byteCountForOneTimestep;
size_t activeCellCount;
socketStream >> columnCount;
socketStream >> byteCountForOneTimestep;
activeCellCount = byteCountForOneTimestep / sizeof(qint32);
dim_vector dv (2, 1);
dv(0) = activeCellCount;
dv(1) = columnCount;
activeCellInfo.resize(dv);
if (!(byteCountForOneTimestep && columnCount))
{
error ("Could not find the requested data in ResInsight");
return;
}
#if OCTAVE_MAJOR_VERSION > 6
auto internalMatrixData = (qint32*)activeCellInfo.fortran_vec();
#else
qint32* internalMatrixData = (qint32*)activeCellInfo.fortran_vec()->mex_get_data();
#endif
QStringList errorMessages;
if (!RiaSocketDataTransfer::readBlockDataFromSocket(&socket, (char*)(internalMatrixData), columnCount * byteCountForOneTimestep, errorMessages))
{
for (int i = 0; i < errorMessages.size(); i++)
{
error("%s",errorMessages[i].toLatin1().data());
}
OCTAVE_QUIT;
}
QString tmp = QString("riGetActiveCellInfo : Read active cell info");
if (caseId < 0)
{
tmp += QString(" from current case.");
}
else
{
tmp += QString(" from caseID: %1.").arg(caseId);
}
octave_stdout << tmp.toStdString() << " Active cells: " << activeCellCount << ", Columns: " << columnCount << std::endl;
return;
}
DEFUN_DLD (riGetActiveCellInfo, args, nargout,
"Usage:\n"
"\n"
" riGetActiveCellInfo([CaseId], [PorosityModel = <20>Matrix<69>|<7C>Fracture<72>] )\n"
"\n"
"This function returns a two dimensional matrix containing grid and IJK information\n"
"for each of the active cells in the requested case.\n"
"The columns contain the following information:\n"
"[GridIdx, I, J, K, ParentGridIdx, PI, PJ, PK, CoarseBoxIdx]\n"
" GridIdx : The index of the grid the cell resides in. (Main grid has index 0)\n"
" I, J, K : 1-based index address of the cell in the grid.\n"
" ParentGridIdx : The index to the grid that this cell's grid is residing in.\n"
" PI, PJ, PK : 1-based address of the parent grid cell that this cell is a part of.\n"
" CoarseBoxIdx : Coarsening box index, -1 if none.\n"
"If the CaseId is not defined, ResInsight<68>s Current Case is used. If PorosityModel is not defined, <20>Matrix<69> is used.\n"
)
{
int nargin = args.length ();
if (nargin > 2)
{
error("riGetActiveCellInfo: Too many arguments. CaseId and PorosityModel are optional input arguments.\n");
print_usage();
}
else if (nargout < 1)
{
error("riGetActiveCellInfo: Missing output argument.\n");
print_usage();
}
else
{
int32NDArray propertyFrames;
qint64 caseId = -1;
QString porosityModel = "Matrix";
if (nargin > 0)
{
if (riOctavePlugin::isOctaveValueNumeric(args(0)))
{
unsigned int argCaseId = args(0).uint_value();
caseId = argCaseId;
}
else
{
porosityModel = args(0).char_matrix_value().row_as_string(0).c_str();
}
}
if (nargin > 1)
{
if (riOctavePlugin::isOctaveValueNumeric(args(1)))
{
unsigned int argCaseId = args(1).uint_value();
caseId = argCaseId;
}
else
{
porosityModel = args(1).char_matrix_value().row_as_string(0).c_str();
}
}
getActiveCellInfo(propertyFrames, "127.0.0.1", riOctavePlugin::portNumber(), caseId, porosityModel);
return octave_value(propertyFrames);
}
return octave_value();
}

View File

@@ -0,0 +1,199 @@
#include <QtNetwork>
#include <QStringList>
#include <octave/oct.h>
#include "riSettings.h"
#include "RiaSocketDataTransfer.cpp" // NB! Include cpp-file to avoid linking of additional file in oct-compile configuration
void getActiveCellProperty(Matrix& propertyFrames, const QString &serverName, quint16 serverPort,
const qint64& caseId, QString propertyName, const int32NDArray& requestedTimeSteps, QString porosityModel)
{
QTcpSocket socket;
socket.connectToHost(serverName, serverPort);
if (!socket.waitForConnected(riOctavePlugin::connectTimeOutMilliSecs))
{
error("Connection: %s",socket.errorString().toLatin1().data());
return;
}
QDataStream socketStream(&socket);
socketStream.setVersion(riOctavePlugin::qtDataStreamVersion);
// Create command as a string with arguments , and send it:
QString command;
command += "GetActiveCellProperty " + QString::number(caseId) + " " + propertyName + " " + porosityModel;
for (int i = 0; i < requestedTimeSteps.numel(); ++i)
{
if (i == 0) command += " ";
command += QString::number(static_cast<int>(requestedTimeSteps.elem(i)) - 1); // To make the index 0-based
if (i != requestedTimeSteps.numel() -1) command += " ";
}
QByteArray cmdBytes = command.toLatin1();
socketStream << (qint64)(cmdBytes.size());
socket.write(cmdBytes);
// Get response. First wait for the header
while (socket.bytesAvailable() < (int)(2*sizeof(quint64)))
{
if (!socket.waitForReadyRead(riOctavePlugin::longTimeOutMilliSecs))
{
error("Waiting for header: %s",socket.errorString().toLatin1().data());
return;
}
}
// Read timestep count and blocksize
quint64 timestepCount;
quint64 byteCount;
size_t activeCellCount;
socketStream >> timestepCount;
socketStream >> byteCount;
activeCellCount = byteCount / sizeof(double);
propertyFrames.resize(activeCellCount, timestepCount);
if (!(byteCount && timestepCount))
{
error ("Could not find the requested data in ResInsight");
return;
}
quint64 totalByteCount = byteCount * timestepCount;
double* internalMatrixData = propertyFrames.fortran_vec();
QStringList errorMessages;
if (!RiaSocketDataTransfer::readBlockDataFromSocket(&socket, (char*)(internalMatrixData), totalByteCount, errorMessages))
{
for (int i = 0; i < errorMessages.size(); i++)
{
error("%s",errorMessages[i].toLatin1().data());
}
return;
}
QString tmp = QString("riGetActiveCellProperty : Read %1").arg(propertyName);
if (caseId < 0)
{
tmp += QString(" from current case.");
}
else
{
tmp += QString(" from case with Id: %1.").arg(caseId);
}
octave_stdout << tmp.toStdString() << " Active cells : " << activeCellCount << ", Timesteps : " << timestepCount << std::endl;
return;
}
DEFUN_DLD (riGetActiveCellProperty, args, nargout,
"Usage:\n"
"\n"
"Matrix[numActiveCells][numTimestepsRequested] riGetActiveCellProperty([CaseId], PropertyName, [RequestedTimeSteps], [PorosityModel = \"Matrix\"|\"Fracture\"] )"
"\n"
"This function returns a two dimensional matrix: [ActiveCells][Num TimestepsRequested] containing the requested property data from the case with CaseId."
"If the case contains coarse-cells, the results are expanded onto the active cells."
"If the CaseId is not defined, ResInsights Current Case is used."
"The RequestedTimeSteps must contain a list of 1-based indices to the requested timesteps. If not defined, all the timesteps are returned."
)
{
if (nargout < 1)
{
error("riGetActiveCellProperty: Missing output argument.\n");
print_usage();
return octave_value_list ();
}
int nargin = args.length ();
if (nargin < 1)
{
error("riGetActiveCellProperty: Too few arguments. The name of the property requested is neccesary.\n");
print_usage();
return octave_value_list ();
}
if (nargin > 4)
{
error("riGetActiveCellProperty: Too many arguments.\n");
print_usage();
return octave_value_list ();
}
std::vector<int> argIndices;
argIndices.push_back(0);
argIndices.push_back(1);
argIndices.push_back(2);
argIndices.push_back(3);
// Check if we have a CaseId:
if (!riOctavePlugin::isOctaveValueNumeric(args(argIndices[0])))
{
argIndices[0] = -1;
for (size_t aIdx = 1; aIdx < argIndices.size(); ++aIdx)
--argIndices[aIdx];
}
// Check if we have a Requested TimeSteps
if (!(nargin > argIndices[2] && (args(argIndices[2]).is_matrix_type() || riOctavePlugin::isOctaveValueNumeric(args(argIndices[2]))) && !args(argIndices[2]).is_string()))
{
argIndices[2] = -1;
for (size_t aIdx = 3; aIdx < argIndices.size(); ++aIdx)
--argIndices[aIdx];
}
// Check if we have a PorosityModel
int lastArgumentIndex = argIndices[3] ;
if (!(nargin > argIndices[3] && args(argIndices[3]).is_string()))
{
argIndices[3] = -1;
for (size_t aIdx = 4; aIdx < argIndices.size(); ++aIdx)
--argIndices[aIdx];
}
// Check if we have more arguments than we should
if (nargin > lastArgumentIndex + 1)
{
error("riGetActiveCellProperty: Unexpected argument after the PorosityModel.\n");
print_usage();
return octave_value_list ();
}
// Setup the argument list
Matrix propertyFrames;
int caseId = -1;
std::string propertyName = "UNDEFINED";
int32NDArray requestedTimeSteps;
std::string porosityModel = "Matrix";
if (argIndices[0] >= 0) caseId = args(argIndices[0]).int_value();
if (argIndices[1] >= 0) propertyName = args(argIndices[1]).char_matrix_value().row_as_string(0);
if (argIndices[2] >= 0) requestedTimeSteps = args(argIndices[2]).int32_array_value();
if (argIndices[3] >= 0) porosityModel = args(argIndices[3]).string_value();
if (porosityModel != "Matrix" && porosityModel != "Fracture")
{
error("riGetActiveCellProperty: The value for \"PorosityModel\" is unknown. Please use either \"Matrix\" or \"Fracture\"\n");
print_usage();
return octave_value_list ();
}
getActiveCellProperty(propertyFrames, "127.0.0.1", riOctavePlugin::portNumber(), caseId, propertyName.c_str(), requestedTimeSteps, porosityModel.c_str());
return octave_value(propertyFrames);
}

View File

@@ -0,0 +1,140 @@
#include <QtNetwork>
#include <octave/oct.h>
#include <octave/oct-map.h>
#include "riSettings.h"
void getCaseGroups(std::vector<QString>& groupNames, std::vector<int>& groupIds, const QString &hostName, quint16 port)
{
QString serverName = hostName;
quint16 serverPort = port;
QTcpSocket socket;
socket.connectToHost(serverName, serverPort);
if (!socket.waitForConnected(riOctavePlugin::connectTimeOutMilliSecs))
{
error("Connection: %s",socket.errorString().toLatin1().data());
return;
}
// Create command and send it:
QString command("GetCaseGroups");
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)(2*sizeof(quint64)))
{
if (!socket.waitForReadyRead(riOctavePlugin::longTimeOutMilliSecs))
{
error("Waiting for data: %s",socket.errorString().toLatin1().data());
return;
}
OCTAVE_QUIT;
}
quint64 byteCount;
socketStream >> byteCount;
quint64 groupCount;
socketStream >> groupCount;
// Get response. Read all data for command
while (socket.bytesAvailable() < (int)byteCount)
{
if (!socket.waitForReadyRead(riOctavePlugin::longTimeOutMilliSecs))
{
error("Waiting for data: %s",socket.errorString().toLatin1().data());
return;
}
OCTAVE_QUIT;
}
quint64 group = 0;
while (group < groupCount)
{
QString caseGroupName;
qint64 caseGroupId;
socketStream >> caseGroupName;
socketStream >> caseGroupId;
groupNames.push_back(caseGroupName);
groupIds.push_back(caseGroupId);
group++;
}
return;
}
DEFUN_DLD (riGetCaseGroups, args, nargout,
"Usage:\n"
"\n"
" riGetCaseGroups()\n"
"\n"
"This function returns a CaseGroupInfo Structure for each of the case groups in the current ResInsight project.\n"
"CaseGroupInfo = {\n"
" CaseGroupId = int # A project-unique integer used to address this particular CaseGroup\n"
" CaseGroupName = string # The name assigned to the CaseGroup in ResInsight\n"
"}\n"
)
{
int nargin = args.length ();
if (nargin > 0)
{
error("riGetCaseGroups: Too many arguments, this function does not take any arguments.\n");
print_usage();
}
else if (nargout != 1)
{
error("riGetCaseGroups: Wrong number of output arguments, expects one output argument.\n");
print_usage();
}
else
{
std::vector<QString> groupNames;
std::vector<int> groupIds;
getCaseGroups(groupNames, groupIds, "127.0.0.1", riOctavePlugin::portNumber());
size_t groupCount = groupNames.size();
if (groupCount != groupIds.size())
{
error("riGetCurrentCase: Inconsistent data received from ResInsight.\n");
}
else
{
// Create cells with N items for each field in the data structure
Cell cellValuesA(groupCount, 1);
Cell cellValuesB(groupCount, 1);
for (size_t i = 0; i < groupCount; i++)
{
cellValuesA(i) = groupIds[i];
cellValuesB(i) = groupNames[i].toLatin1().data();
}
// Build a map between the field name and field cell values
octave_map m;
m.assign(riOctavePlugin::caseGroupInfo_CaseGroupId, cellValuesA);
m.assign(riOctavePlugin::caseGroupInfo_CaseGroupName, cellValuesB);
return octave_value(m);
}
}
return octave_value();
}

View File

@@ -0,0 +1,160 @@
#include <QtNetwork>
#include <octave/oct.h>
#include <octave/oct-map.h>
#include "riSettings.h"
void getCases(std::vector<qint64>& caseIds, std::vector<QString>& caseNames, std::vector<QString>& caseTypes, std::vector<qint64>& caseGroupIds, const qint64& caseGroupId, const QString &hostName, quint16 port)
{
QString serverName = hostName;
quint16 serverPort = port;
QTcpSocket socket;
socket.connectToHost(serverName, serverPort);
if (!socket.waitForConnected(riOctavePlugin::connectTimeOutMilliSecs))
{
error("Connection: %s",socket.errorString().toLatin1().data());
return;
}
// Create command and send it:
QString command = QString("GetCases %1").arg(caseGroupId);
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: %s",socket.errorString().toLatin1().data());
return;
}
}
quint64 byteCount;
socketStream >> byteCount;
while (socket.bytesAvailable() < (int)(byteCount))
{
if (!socket.waitForReadyRead(riOctavePlugin::longTimeOutMilliSecs))
{
error("Waiting for data: %s",socket.errorString().toLatin1().data());
return;
}
OCTAVE_QUIT;
}
quint64 caseCount;
socketStream >> caseCount;
qint64 caseId = -1;
QString caseName;
QString caseType;
qint64 caseGroupIdFromSocket = -1;
for (size_t i = 0; i < caseCount; i++)
{
socketStream >> caseId;
socketStream >> caseName;
socketStream >> caseType;
socketStream >> caseGroupIdFromSocket;
caseIds.push_back(caseId);
caseNames.push_back(caseName);
caseTypes.push_back(caseType);
caseGroupIds.push_back(caseGroupIdFromSocket);
}
return;
}
DEFUN_DLD (riGetCases, args, nargout,
"Usage:\n"
"\n"
" riGetCases([CaseGroupId])\n"
"\n"
"This function returns a CaseInfo Structure for all the cases in the current ResInsight project,\n"
"including the Statistics cases and Source cases in a Grid Case Group.\n"
"If a CaseGroupId is provided, only the cases in that Case Group will be returned.\n"
)
{
int nargin = args.length ();
if (nargin > 1)
{
error("riGetCases: Too many arguments, this function takes one optional argument.\n");
print_usage();
}
else if (nargout != 1)
{
error("riGetCases: Wrong number of output arguments, this function requires one output argument.\n");
print_usage();
}
else
{
std::vector<qint64> caseIds;
std::vector<QString> caseNames;
std::vector<QString> caseTypes;
std::vector<qint64> caseGroupIds;
qint64 caseGroupId = -1;
if (nargin == 1)
{
unsigned int argCaseId = args(0).uint_value();
caseGroupId = argCaseId;
}
getCases(caseIds, caseNames, caseTypes, caseGroupIds, caseGroupId, "127.0.0.1", riOctavePlugin::portNumber());
size_t caseCount = caseIds.size();
if (caseCount != caseNames.size() ||
caseCount != caseTypes.size() ||
caseCount != caseGroupIds.size())
{
error("riGetCases: Inconsistent data received from ResInsight.\n");
}
else
{
// Create cells with N items for each field in the data structure
Cell cellValuesA(caseCount, 1);
Cell cellValuesB(caseCount, 1);
Cell cellValuesC(caseCount, 1);
Cell cellValuesD(caseCount, 1);
for (size_t i = 0; i < caseCount; i++)
{
cellValuesA(i) = caseIds[i];
cellValuesB(i) = caseNames[i].toLatin1().data();
cellValuesC(i) = caseTypes[i].toLatin1().data();
cellValuesD(i) = caseGroupIds[i];
}
// Build a map between the field name and field cell values
octave_map m;
m.assign(riOctavePlugin::caseInfo_CaseId, cellValuesA);
m.assign(riOctavePlugin::caseInfo_CaseName, cellValuesB);
m.assign(riOctavePlugin::caseInfo_CaseType, cellValuesC);
m.assign(riOctavePlugin::caseInfo_CaseGroupId, cellValuesD);
return octave_value(m);
}
}
return octave_value();
}

View File

@@ -0,0 +1,136 @@
#include <QtNetwork>
#include <QStringList>
#include <octave/oct.h>
#include "riSettings.h"
#include "RiaSocketDataTransfer.cpp" // NB! Include cpp-file to avoid linking of additional file in oct-compile configuration
void getCellCenters(NDArray& cellCenterValues, const QString &hostName, quint16 port, const qint32& caseId, const quint32& gridIndex)
{
QString serverName = hostName;
quint16 serverPort = port;
QTcpSocket socket;
socket.connectToHost(serverName, serverPort);
if (!socket.waitForConnected(riOctavePlugin::connectTimeOutMilliSecs))
{
error("Connection: %s",socket.errorString().toLatin1().data());
return;
}
// Create command and send it:
QString command = QString("GetCellCenters %1 %2").arg(caseId).arg(gridIndex);
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)(5 * sizeof(quint64)))
{
if (!socket.waitForReadyRead(riOctavePlugin::longTimeOutMilliSecs))
{
error("Waiting for header: %s",socket.errorString().toLatin1().data());
return;
}
}
quint64 cellCountI;
quint64 cellCountJ;
quint64 cellCountK;
quint64 cellCount;
quint64 byteCount;
socketStream >> cellCount;
socketStream >> cellCountI;
socketStream >> cellCountJ;
socketStream >> cellCountK;
socketStream >> byteCount;
if (!(byteCount && cellCount))
{
error ("Could not find the requested data in ResInsight");
return;
}
dim_vector dv;
dv.resize(4);
dv(0) = cellCountI;
dv(1) = cellCountJ;
dv(2) = cellCountK;
dv(3) = 3;
cellCenterValues.resize(dv);
double* internalMatrixData = cellCenterValues.fortran_vec();
QStringList errorMessages;
if (!RiaSocketDataTransfer::readBlockDataFromSocket(&socket, (char*)(internalMatrixData), byteCount, errorMessages))
{
for (int i = 0; i < errorMessages.size(); i++)
{
error("%s",errorMessages[i].toLatin1().data());
}
OCTAVE_QUIT;
}
return;
}
DEFUN_DLD (riGetCellCenters, args, nargout,
"Usage:\n"
"\n"
" riGetCellCenters([CaseId], GridIndex )\n"
"\n"
"This function returns the UTM coordinates (X, Y, Z) of the center point of all the cells in the grid.\n"
"If the CaseId is not defined, ResInsight<68>s Current Case is used.\n"
)
{
int nargin = args.length ();
if (nargin > 2)
{
error("riGetCellCenters: Too many arguments. CaseId is optional input argument.\n");
print_usage();
}
else if (nargout < 1)
{
error("riGetCellCenters: Missing output argument.\n");
print_usage();
}
else
{
NDArray cellCenterValues;
qint32 caseId = -1;
quint32 gridIndex = 0;
if (nargin == 1)
{
gridIndex = args(0).uint_value();
}
else if (nargin == 2)
{
unsigned int argCaseId = args(0).uint_value();
caseId = argCaseId;
gridIndex = args(1).uint_value();
}
getCellCenters(cellCenterValues, "127.0.0.1", riOctavePlugin::portNumber(), caseId, gridIndex);
return octave_value(cellCenterValues);
}
return octave_value();
}

View File

@@ -0,0 +1,138 @@
#include <QtNetwork>
#include <QStringList>
#include <octave/oct.h>
#include "riSettings.h"
#include "RiaSocketDataTransfer.cpp" // NB! Include cpp-file to avoid linking of additional file in oct-compile configuration
void getCellCorners(NDArray& cellCornerValues, const QString &hostName, quint16 port, const qint32& caseId, const quint32& gridIndex)
{
QString serverName = hostName;
quint16 serverPort = port;
QTcpSocket socket;
socket.connectToHost(serverName, serverPort);
if (!socket.waitForConnected(riOctavePlugin::connectTimeOutMilliSecs))
{
error("Connection: %s",socket.errorString().toLatin1().data());
return;
}
// Create command and send it:
QString command = QString("GetCellCorners %1 %2").arg(caseId).arg(gridIndex);
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)(5 * sizeof(quint64)))
{
if (!socket.waitForReadyRead(riOctavePlugin::longTimeOutMilliSecs))
{
error("Waiting for header: %s",socket.errorString().toLatin1().data());
return;
}
}
quint64 cellCountI;
quint64 cellCountJ;
quint64 cellCountK;
quint64 cellCount;
quint64 byteCount;
socketStream >> cellCount;
socketStream >> cellCountI;
socketStream >> cellCountJ;
socketStream >> cellCountK;
socketStream >> byteCount;
if (!(byteCount && cellCount))
{
error ("Could not find the requested data in ResInsight");
return;
}
dim_vector dv;
dv.resize(5);
dv(0) = cellCountI;
dv(1) = cellCountJ;
dv(2) = cellCountK;
dv(3) = 8;
dv(4) = 3;
cellCornerValues.resize(dv);
double* internalMatrixData = cellCornerValues.fortran_vec();
QStringList errorMessages;
if (!RiaSocketDataTransfer::readBlockDataFromSocket(&socket, (char*)(internalMatrixData), byteCount, errorMessages))
{
for (int i = 0; i < errorMessages.size(); i++)
{
error("%s",errorMessages[i].toLatin1().data());
}
OCTAVE_QUIT;
}
return;
}
DEFUN_DLD (riGetCellCorners, args, nargout,
"Usage:\n"
"\n"
" riGetCellCorners([CaseId], GridIndex )\n"
"\n"
"This function returns the UTM coordinates (X, Y, Z) of the 8 corners of all the cells in the grid.\n"
"If the CaseId is not defined, ResInsight<68>s Current Case is used.\n"
)
{
int nargin = args.length ();
if (nargin > 2)
{
error("riGetCellCorners: Too many arguments. CaseId is optional input argument.\n");
print_usage();
}
else if (nargout < 1)
{
error("riGetCellCorners: Missing output argument.\n");
print_usage();
}
else
{
NDArray cellCornerValues;
qint32 caseId = -1;
quint32 gridIndex = 0;
if (nargin == 1)
{
gridIndex = args(0).uint_value();
}
else if (nargin == 2)
{
unsigned int argCaseId = args(0).uint_value();
caseId = argCaseId;
gridIndex = args(1).uint_value();
}
getCellCorners(cellCornerValues, "127.0.0.1", riOctavePlugin::portNumber(), caseId, gridIndex);
return octave_value(cellCornerValues);
}
return octave_value();
}

View File

@@ -0,0 +1,125 @@
#include <QtNetwork>
#include <octave/oct.h>
#include "riSettings.h"
void getCoarseningInfo(int32NDArray& coarseningInfo, 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: %s",socket.errorString().toLatin1().data());
return;
}
// Create command and send it:
QString command = QString("GetCoarseningInfo %1").arg(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: %s",socket.errorString().toLatin1().data());
return;
}
}
quint64 byteCount;
socketStream >> byteCount;
quint64 boxCount = byteCount / (6 * sizeof(qint32));
dim_vector dv (1, 1);
dv(0) = boxCount;
dv(1) = 6;
coarseningInfo.resize(dv);
for (size_t i = 0; i < boxCount; i++)
{
qint32 i1;
qint32 i2;
qint32 j1;
qint32 j2;
qint32 k1;
qint32 k2;
socketStream >> i1;
socketStream >> i2;
socketStream >> j1;
socketStream >> j2;
socketStream >> k1;
socketStream >> k2;
coarseningInfo(i, 0) = i1;
coarseningInfo(i, 1) = i2;
coarseningInfo(i, 2) = j1;
coarseningInfo(i, 3) = j2;
coarseningInfo(i, 4) = k1;
coarseningInfo(i, 5) = k2;
}
return;
}
DEFUN_DLD (riGetCoarseningInfo, args, nargout,
"Usage:\n"
"\n"
" riGetCoarseningInfo([CaseId])\n"
"\n"
"This function returns all the coarse box definitions used in the grid.\n"
"The columns contain the following information:\n"
"[I1, I2, J1, J2, K1, K2]: 1-based index addresses of the min and max corners of the coarsening box.\n"
"If the CaseId is not defined, ResInsight<68>s Current Case is used.\n"
)
{
int nargin = args.length ();
if (nargin > 1)
{
error("riGetCoarseningInfo: Too many arguments. Only the name or index of the case is valid input.\n");
print_usage();
}
else if (nargout < 1)
{
error("riGetCoarseningInfo: Missing output argument.\n");
print_usage();
}
else
{
qint64 caseId = -1;
if (nargin > 0)
{
if (riOctavePlugin::isOctaveValueNumeric(args(0)))
{
unsigned int argCaseId = args(0).uint_value();
caseId = argCaseId;
}
}
int32NDArray coarseningInfo;
getCoarseningInfo(coarseningInfo, "127.0.0.1", riOctavePlugin::portNumber(), caseId);
return octave_value(coarseningInfo);
}
return octave_value_list ();
}

View File

@@ -0,0 +1,110 @@
#include <QtNetwork>
#include <octave/oct.h>
#include <octave/oct-map.h>
#include "riSettings.h"
void getCurrentCase(qint64& caseId, QString& caseName, QString& caseType, qint64& caseGroupId, const QString &hostName, quint16 port)
{
QString serverName = hostName;
quint16 serverPort = port;
QTcpSocket socket;
socket.connectToHost(serverName, serverPort);
if (!socket.waitForConnected(riOctavePlugin::connectTimeOutMilliSecs))
{
error("Connection: %s",socket.errorString().toLatin1().data());
return;
}
// Create command and send it:
QString command("GetCurrentCase");
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: %s",socket.errorString().toLatin1().data());
return;
}
}
quint64 byteCount;
socketStream >> byteCount;
while (socket.bytesAvailable() < (int)(byteCount))
{
if (!socket.waitForReadyRead(riOctavePlugin::longTimeOutMilliSecs))
{
error("Waiting for data: %s",socket.errorString().toLatin1().data());
return;
}
OCTAVE_QUIT;
}
socketStream >> caseId;
socketStream >> caseName;
socketStream >> caseType;
socketStream >> caseGroupId;
return;
}
DEFUN_DLD (riGetCurrentCase, args, nargout,
"Usage:\n"
"\n"
" riGetCurrentCase()\n"
"\n"
"This function returns a CaseInfo Structure for the Case considered being the 'Current Case' by ResInsight.\n"
"When ResInsigt loops over a selection of cases and executes an Octave script for each of them,\n"
"this function returns the CaseInfo for that particular Case.\n"
)
{
octave_value retval;
int nargin = args.length ();
if (nargin > 0)
{
error("riGetCurrentCase: Too many input arguments, this function does not take any input arguments.\n");
print_usage();
}
else if (nargout != 1)
{
error("riGetCurrentCase: Wrong number of output arguments, this function requires one output argument.\n");
print_usage();
}
else
{
qint64 caseId = -1;
QString caseName;
QString caseType;
qint64 caseGroupId = -1;
getCurrentCase(caseId, caseName, caseType, caseGroupId, "127.0.0.1", riOctavePlugin::portNumber());
octave_map fieldMap;
fieldMap.assign(riOctavePlugin::caseInfo_CaseId, Cell(caseId));
fieldMap.assign(riOctavePlugin::caseInfo_CaseName, Cell(std::string(caseName.toLatin1().data()), true));
fieldMap.assign(riOctavePlugin::caseInfo_CaseType, Cell(std::string(caseType.toLatin1().data()), true));
fieldMap.assign(riOctavePlugin::caseInfo_CaseGroupId, Cell(caseGroupId));
retval = octave_value(fieldMap);
}
return retval;
}

View File

@@ -0,0 +1,161 @@
#include <QtNetwork>
#include <QStringList>
#include <octave/oct.h>
#include "riSettings.h"
#include "RiaSocketDataTransfer.cpp" // NB! Include cpp-file to avoid linking of additional file in oct-compile configuration
void getDynamicNNCValues(Matrix& propertyFrames, const QString &serverName, quint16 serverPort,
const qint64& caseId, QString propertyName, const int32NDArray& requestedTimeSteps)
{
QTcpSocket socket;
socket.connectToHost(serverName, serverPort);
if (!socket.waitForConnected(riOctavePlugin::connectTimeOutMilliSecs))
{
error("Connection: %s",socket.errorString().toLatin1().data());
return;
}
QDataStream socketStream(&socket);
socketStream.setVersion(riOctavePlugin::qtDataStreamVersion);
// Create command as a string with arguments , and send it:
QString command;
command += "GetDynamicNNCValues " + QString::number(caseId) + " " + propertyName;
for (int i = 0; i < requestedTimeSteps.numel(); ++i)
{
if (i == 0) command += " ";
command += QString::number(static_cast<int>(requestedTimeSteps.elem(i)) - 1); // To make the index 0-based
if (i != requestedTimeSteps.numel() -1) command += " ";
}
QByteArray cmdBytes = command.toLatin1();
socketStream << (qint64)(cmdBytes.size());
socket.write(cmdBytes);
// Get response. First wait for the header
while (socket.bytesAvailable() < (int)(2*sizeof(quint64)))
{
if (!socket.waitForReadyRead(riOctavePlugin::longTimeOutMilliSecs))
{
error("Waiting for header: %s",socket.errorString().toLatin1().data());
return;
}
}
// Read connection count and timestep count
quint64 connectionCount;
quint64 timestepCount;
socketStream >> connectionCount;
socketStream >> timestepCount;
propertyFrames.resize(connectionCount, timestepCount);
if (!(connectionCount && timestepCount))
{
error ("Could not find the requested data in ResInsight");
return;
}
quint64 totalByteCount = timestepCount * connectionCount * sizeof(double);
double* internalMatrixData = propertyFrames.fortran_vec();
QStringList errorMessages;
if (!RiaSocketDataTransfer::readBlockDataFromSocket(&socket, (char*)(internalMatrixData), totalByteCount, errorMessages))
{
for (int i = 0; i < errorMessages.size(); i++)
{
error("%s",errorMessages[i].toLatin1().data());
}
return;
}
QString tmp = QString("riGetDynamicNNCValues : Read %1").arg(propertyName);
if (caseId < 0)
{
tmp += QString(" from current case.");
}
else
{
tmp += QString(" from case with Id: %1.").arg(caseId);
}
octave_stdout << tmp.toStdString() << " Connections: " << connectionCount << ", Time steps : " << timestepCount << std::endl;
return;
}
DEFUN_DLD (riGetDynamicNNCValues, args, nargout,
"Usage:\n"
"\n"
" riGetDynamicNNCValues([CaseId], PropertyName, [RequestedTimeSteps])\n"
"\n"
"This function returns a matrix with the dynamic NNC values for each connection for the requested time steps.\n"
"The matrix has a number of rows equal to the number of NNC connections and a number of columns equal to the requested time steps.\n"
"\n"
"See riGetNNCConnections for information about each individual connection.\n"
"If the CaseId is not defined, ResInsight's Current Case is used.\n"
"If RequestedTimeSteps are left empty, values for all time steps will be returned.\n"
)
{
int nargin = args.length ();
if (nargin < 1)
{
error("riGetDynamicNNCValues: Too few arguments. The name of the property requested is necessary.\n");
print_usage();
return octave_value_list();
}
else if (nargin > 3)
{
error("riGetDynamicNNCValues: Too many arguments.\n");
print_usage();
return octave_value_list();
}
else if (nargout < 1)
{
error("riGetDynamicNNCValues: Missing output argument.\n");
print_usage();
return octave_value_list();
}
std::vector<int> argIndices;
argIndices.push_back(0);
argIndices.push_back(1);
argIndices.push_back(2);
// Check if we have a CaseId:
if (!riOctavePlugin::isOctaveValueNumeric(args(argIndices[0])))
{
argIndices[0] = -1;
for (size_t aIdx = 1; aIdx < argIndices.size(); ++aIdx)
--argIndices[aIdx];
}
// Check if we have a Requested TimeSteps
if (!(nargin > argIndices[2] && args(argIndices[2]).is_matrix_type()))
{
argIndices[2] = -1;
}
Matrix propertyFrames;
qint32 caseId = -1;
int32NDArray requestedTimeSteps;
std::string propertyName;
if (argIndices[0] >= 0) caseId = args(argIndices[0]).int_value();
if (argIndices[1] >= 0) propertyName = args(argIndices[1]).char_matrix_value().row_as_string(0);
if (argIndices[2] >= 0) requestedTimeSteps = args(argIndices[2]).int32_array_value();
getDynamicNNCValues(propertyFrames, "127.0.0.1", riOctavePlugin::portNumber(), caseId, propertyName.c_str(), requestedTimeSteps);
return octave_value(propertyFrames);
}

View File

@@ -0,0 +1,129 @@
#include <QtNetwork>
#include <octave/oct.h>
#include "riSettings.h"
void getGridDimensions(int32NDArray& gridDimensions, 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: %s",socket.errorString().toLatin1().data());
return;
}
// Create command and send it:
QString command = QString("GetGridDimensions %1").arg(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: %s",socket.errorString().toLatin1().data());
return;
}
}
quint64 byteCount;
socketStream >> byteCount;
quint64 gridCount = byteCount / (3 * sizeof(quint64));
dim_vector dv (1, 1);
dv(0) = gridCount;
dv(1) = 3;
gridDimensions.resize(dv);
for (size_t i = 0; i < gridCount; i++)
{
quint64 iCount;
quint64 jCount;
quint64 kCount;
socketStream >> iCount;
socketStream >> jCount;
socketStream >> kCount;
gridDimensions(i, 0) = iCount;
gridDimensions(i, 1) = jCount;
gridDimensions(i, 2) = kCount;
}
QString tmp = QString("riGetGridDimensions : Read grid dimensions");
if (caseId < 0)
{
tmp += QString(" from current case.");
}
else
{
tmp += QString(" from caseID: %1.").arg(caseId);
}
octave_stdout << tmp.toStdString() << std::endl;
return;
}
DEFUN_DLD (riGetGridDimensions, args, nargout,
"Usage:\n"
"\n"
" riGetGridDimensions([CaseId])\n"
"\n"
"This function returns a two dimensional matrix: One row for each grid, starting with the main grid.\n"
"NOTE: This means that the <20>normal<61> GridIndices where 0 means Main Grid does not work directly with this matrix. You have to add 1.\n"
"The columns contain the following information:\n"
"[NI, NJ, NK]: I, J, K dimensions of the grid.\n"
"If the CaseId is not defined, ResInsight<68>s Current Case is used.\n"
)
{
int nargin = args.length ();
if (nargin > 1)
{
error("riGetGridDimensions: Too many arguments. Only the name or index of the case is valid input.\n");
print_usage();
}
else if (nargout < 1)
{
error("riGetGridDimensions: Missing output argument.\n");
print_usage();
}
else
{
qint64 caseId = -1;
if (nargin > 0)
{
if (riOctavePlugin::isOctaveValueNumeric(args(0)))
{
unsigned int argCaseId = args(0).uint_value();
caseId = argCaseId;
}
}
int32NDArray gridDimensions;
getGridDimensions(gridDimensions, "127.0.0.1", riOctavePlugin::portNumber(), caseId);
return octave_value(gridDimensions);
}
return octave_value_list ();
}

View File

@@ -0,0 +1,217 @@
#include <QtNetwork>
#include <QStringList>
#include <octave/oct.h>
#include "riSettings.h"
#include "RiaSocketDataTransfer.cpp" // NB! Include cpp-file to avoid linking of additional file in oct-compile configuration
void getGridProperty(NDArray& propertyFrames, const QString &serverName, quint16 serverPort,
const int& caseId, int gridIdx, QString propertyName, const int32NDArray& requestedTimeSteps, QString porosityModel)
{
QTcpSocket socket;
socket.connectToHost(serverName, serverPort);
if (!socket.waitForConnected(riOctavePlugin::connectTimeOutMilliSecs))
{
error("Connection: %s",socket.errorString().toLatin1().data());
return;
}
QDataStream socketStream(&socket);
socketStream.setVersion(riOctavePlugin::qtDataStreamVersion);
// Create command as a string with arguments , and send it:
QString command;
command += "GetGridProperty " + QString::number(caseId) + " " + QString::number(gridIdx) + " " + propertyName + " " + porosityModel;
for (qint64 i = 0; i < requestedTimeSteps.numel(); ++i)
{
if (i == 0) command += " ";
command += QString::number(static_cast<int>(requestedTimeSteps.elem(i)) - 1); // To make the index 0-based
if (i != requestedTimeSteps.numel() -1) command += " ";
}
QByteArray cmdBytes = command.toLatin1();
socketStream << (qint64)(cmdBytes.size());
socket.write(cmdBytes);
// Get response. First wait for the header
while (socket.bytesAvailable() < (qint64)(4*sizeof(quint64)))
{
if (!socket.waitForReadyRead(riOctavePlugin::longTimeOutMilliSecs))
{
error("Waiting for header: %s",socket.errorString().toLatin1().data());
return;
}
}
// Read sizes
quint64 totalByteCount;
quint64 cellCountI;
quint64 cellCountJ;
quint64 cellCountK;
quint64 timestepCount;
socketStream >> cellCountI;
socketStream >> cellCountJ;
socketStream >> cellCountK;
socketStream >> timestepCount;
totalByteCount = cellCountI*cellCountJ*cellCountK*timestepCount*sizeof(double);
if (!(totalByteCount))
{
error ("Could not find the requested data in ResInsight");
return;
}
dim_vector dv;
dv.resize(4);
dv(0) = cellCountI;
dv(1) = cellCountJ;
dv(2) = cellCountK;
dv(3) = timestepCount;
propertyFrames.resize(dv);
double* internalMatrixData = propertyFrames.fortran_vec();
QStringList errorMessages;
if (!RiaSocketDataTransfer::readBlockDataFromSocket(&socket, (char*)(internalMatrixData), totalByteCount, errorMessages))
{
for (int i = 0; i < errorMessages.size(); i++)
{
error("%s",errorMessages[i].toLatin1().data());
}
return;
}
QString tmp = QString("riGetGridProperty : Read %1").arg(propertyName);
if (caseId < 0)
{
tmp += QString(" from current case,");
}
else
{
tmp += QString(" from case with Id: %1,").arg(caseId);
}
tmp += QString(" grid index: %1, ").arg(gridIdx);
octave_stdout << tmp.toStdString() << " I, J, K " << cellCountI << ", " << cellCountJ << ", " << cellCountK << ", Timesteps : " << timestepCount << std::endl;
return;
}
DEFUN_DLD (riGetGridProperty, args, nargout,
"Usage:\n"
"\n"
"Matrix[numI][numJ][numK][numTimestepsRequested] riGetGridProperty([CaseId], GridIndex , PropertyName, [RequestedTimeSteps], [PorosityModel = \"Matrix\"|\"Fracture\"])"
"\n"
"This function returns a matrix of the requested property data for all the grid cells in the requested grid for each requested time step.\n"
"Grids are indexed from 0 (main grid) to max number of LGR's.\n"
"If the CaseId is not defined, ResInsights Current Case is used.\n"
"The RequestedTimeSteps must contain a list of indices to the requested time steps. If not defined, all the time steps are returned.\n"
)
{
if (nargout < 1)
{
error("riGetGridProperty: Missing output argument.\n");
print_usage();
return octave_value_list ();
}
int nargin = args.length ();
if (nargin < 2)
{
error("riGetGridProperty: Too few arguments. The name of the property and index of the grid requested is neccesary.\n");
print_usage();
return octave_value_list ();
}
if (nargin > 5)
{
error("riGetGridProperty: Too many arguments.\n");
print_usage();
return octave_value_list ();
}
std::vector<int> argIndices;
argIndices.push_back(0); // caseId
argIndices.push_back(1); // GridIndex
argIndices.push_back(2); // PropertyName
argIndices.push_back(3); // TimeSteps
argIndices.push_back(4); // PorosityModel
// Check if we do not have a CaseId:
if (args(argIndices[1]).is_string()) // Check if second argument is a text. If it is, the caseid is missing
{
argIndices[0] = -1;
for (size_t aIdx = 1; aIdx < argIndices.size(); ++aIdx)
--argIndices[aIdx];
}
// Check if we have a Requested TimeSteps
if (!(nargin > argIndices[3] && (args(argIndices[3]).is_matrix_type() || riOctavePlugin::isOctaveValueNumeric(args(argIndices[3]))) && !args(argIndices[3]).is_string()))
{
argIndices[3] = -1;
for (size_t aIdx = 3; aIdx < argIndices.size(); ++aIdx)
--argIndices[aIdx];
}
// Check if we have a PorosityModel
int lastArgumentIndex = argIndices[4] ;
if (!(nargin > argIndices[4] && args(argIndices[4]).is_string()))
{
argIndices[4] = -1;
for (size_t aIdx = 5; aIdx < argIndices.size(); ++aIdx)
--argIndices[aIdx];
}
// Check if we have more arguments than we should
if (nargin > lastArgumentIndex + 1)
{
error("riGetGridProperty: Unexpected argument after the PorosityModel.\n");
print_usage();
return octave_value_list ();
}
// Setup the argument list
NDArray propertyFrames;
int caseId = -1;
int gridIdx = 0;
std::string propertyName = "UNDEFINED";
int32NDArray requestedTimeSteps;
std::string porosityModel = "Matrix";
if (argIndices[0] >= 0) caseId = args(argIndices[0]).int_value();
if (argIndices[1] >= 0) gridIdx = args(argIndices[1]).int_value();
if (argIndices[2] >= 0) propertyName = args(argIndices[2]).char_matrix_value().row_as_string(0);
if (argIndices[3] >= 0) requestedTimeSteps = args(argIndices[3]).int32_array_value();
if (argIndices[4] >= 0) porosityModel = args(argIndices[4]).string_value();
if (porosityModel != "Matrix" && porosityModel != "Fracture")
{
error("riGetGridProperty: The value for \"PorosityModel\" is unknown. Please use either \"Matrix\" or \"Fracture\"\n");
print_usage();
return octave_value_list ();
}
getGridProperty(propertyFrames, "127.0.0.1", riOctavePlugin::portNumber(), caseId, gridIdx, propertyName.c_str(), requestedTimeSteps, porosityModel.c_str());
return octave_value(propertyFrames);
}

View File

@@ -0,0 +1,199 @@
#include <QtNetwork>
#include <QStringList>
#include <octave/oct.h>
#include "riSettings.h"
#include "RiaSocketDataTransfer.cpp" // NB! Include cpp-file to avoid linking of additional file in oct-compile configuration
void getGridPropertyForSelectedCells(Matrix& propertyFrames, const QString &serverName, quint16 serverPort,
const qint64& caseId, QString propertyName, const int32NDArray& requestedTimeSteps, QString porosityModel)
{
QTcpSocket socket;
socket.connectToHost(serverName, serverPort);
if (!socket.waitForConnected(riOctavePlugin::connectTimeOutMilliSecs))
{
error("Connection: %s",socket.errorString().toLatin1().data());
return;
}
QDataStream socketStream(&socket);
socketStream.setVersion(riOctavePlugin::qtDataStreamVersion);
// Create command as a string with arguments , and send it:
QString command;
command += "GetGridPropertyForSelectedCells " + QString::number(caseId) + " " + propertyName + " " + porosityModel;
for (int i = 0; i < requestedTimeSteps.numel(); ++i)
{
if (i == 0) command += " ";
command += QString::number(static_cast<int>(requestedTimeSteps.elem(i)) - 1); // To make the index 0-based
if (i != requestedTimeSteps.numel() - 1) command += " ";
}
QByteArray cmdBytes = command.toLatin1();
socketStream << (qint64)(cmdBytes.size());
socket.write(cmdBytes);
// Get response. First wait for the header
while (socket.bytesAvailable() < (int)(2*sizeof(quint64)))
{
if (!socket.waitForReadyRead(riOctavePlugin::longTimeOutMilliSecs))
{
error("Waiting for header: %s",socket.errorString().toLatin1().data());
return;
}
}
// Read timestep count and blocksize
quint64 timestepCount;
quint64 byteCount;
size_t selectedCellCount;
socketStream >> timestepCount;
socketStream >> byteCount;
selectedCellCount = byteCount / sizeof(double);
propertyFrames.resize(selectedCellCount, timestepCount);
if (!(byteCount && timestepCount))
{
error ("Could not find the requested data in ResInsight");
return;
}
quint64 totalByteCount = byteCount * timestepCount;
double* internalMatrixData = propertyFrames.fortran_vec();
QStringList errorMessages;
if (!RiaSocketDataTransfer::readBlockDataFromSocket(&socket, (char*)(internalMatrixData), totalByteCount, errorMessages))
{
for (int i = 0; i < errorMessages.size(); i++)
{
error("%s",errorMessages[i].toLatin1().data());
}
return;
}
QString tmp = QString("riGetGridPropertyForSelectedCells : Read %1").arg(propertyName);
if (caseId < 0)
{
tmp += QString(" from current case.");
}
else
{
tmp += QString(" from case with Id: %1.").arg(caseId);
}
octave_stdout << tmp.toStdString() << " Selected cells cells : " << selectedCellCount << ", Time steps : " << timestepCount << std::endl;
return;
}
DEFUN_DLD (riGetGridPropertyForSelectedCells, args, nargout,
"Usage:\n"
"\n"
"Matrix[numSelectedCells][numTimestepsRequested]\n"
" riGetGridPropertyForSelectedCells([CaseId], PropertyName, [RequestedTimeSteps], [PorosityModel = \"Matrix\"|\"Fracture\"] )\n"
"\n"
"This function returns a two dimensional matrix: [numSelectedCells][numTimestepsRequested] containing the requested property data from the case with CaseId.\n"
"If the CaseId is not defined, ResInsight's Current Case is used.\n"
"The RequestedTimeSteps must contain a list of 1-based indices to the requested time steps. If not defined, all the time steps are returned.\n"
)
{
if (nargout < 1)
{
error("riGetGridPropertyForSelectedCells: Missing output argument.\n");
print_usage();
return octave_value_list ();
}
int nargin = args.length ();
if (nargin < 1)
{
error("riGetGridPropertyForSelectedCells: Too few arguments. The name of the property requested is necessary.\n");
print_usage();
return octave_value_list ();
}
if (nargin > 4)
{
error("riGetGridPropertyForSelectedCells: Too many arguments.\n");
print_usage();
return octave_value_list ();
}
std::vector<int> argIndices;
argIndices.push_back(0);
argIndices.push_back(1);
argIndices.push_back(2);
argIndices.push_back(3);
// Check if we have a CaseId:
if (!riOctavePlugin::isOctaveValueNumeric(args(argIndices[0])))
{
argIndices[0] = -1;
for (size_t aIdx = 1; aIdx < argIndices.size(); ++aIdx)
--argIndices[aIdx];
}
// Check if we have a Requested TimeSteps
if (!(nargin > argIndices[2] && (args(argIndices[2]).is_matrix_type() || riOctavePlugin::isOctaveValueNumeric(args(argIndices[2]))) && !args(argIndices[2]).is_string()))
{
argIndices[2] = -1;
for (size_t aIdx = 3; aIdx < argIndices.size(); ++aIdx)
--argIndices[aIdx];
}
// Check if we have a PorosityModel
int lastArgumentIndex = argIndices[3] ;
if (!(nargin > argIndices[3] && args(argIndices[3]).is_string()))
{
argIndices[3] = -1;
for (size_t aIdx = 4; aIdx < argIndices.size(); ++aIdx)
--argIndices[aIdx];
}
// Check if we have more arguments than we should
if (nargin > lastArgumentIndex + 1)
{
error("riGetGridPropertyForSelectedCells: Unexpected argument after the PorosityModel.\n");
print_usage();
return octave_value_list ();
}
// Setup the argument list
Matrix propertyFrames;
int caseId = -1;
std::string propertyName = "UNDEFINED";
int32NDArray requestedTimeSteps;
std::string porosityModel = "Matrix";
if (argIndices[0] >= 0) caseId = args(argIndices[0]).int_value();
if (argIndices[1] >= 0) propertyName = args(argIndices[1]).char_matrix_value().row_as_string(0);
if (argIndices[2] >= 0) requestedTimeSteps = args(argIndices[2]).int32_array_value();
if (argIndices[3] >= 0) porosityModel = args(argIndices[3]).string_value();
if (porosityModel != "Matrix" && porosityModel != "Fracture")
{
error("riGetGridPropertyForSelectedCells: The value for \"PorosityModel\" is unknown. Please use either \"Matrix\" or \"Fracture\"\n");
print_usage();
return octave_value_list ();
}
getGridPropertyForSelectedCells(propertyFrames, "127.0.0.1", riOctavePlugin::portNumber(), caseId, propertyName.c_str(), requestedTimeSteps, porosityModel.c_str());
return octave_value(propertyFrames);
}

View File

@@ -0,0 +1,113 @@
#include <QtNetwork>
#include <octave/oct.h>
#include "riSettings.h"
void getMainGridDimensions(int32NDArray& gridDimensions, const QString &hostName, quint16 port, QString caseName)
{
QString serverName = hostName;
quint16 serverPort = port;
QTcpSocket socket;
socket.connectToHost(serverName, serverPort);
if (!socket.waitForConnected(riOctavePlugin::connectTimeOutMilliSecs))
{
error("Connection: %s",socket.errorString().toLatin1().data());
return;
}
// Create command and send it:
QString command("GetMainGridDimensions ");
command += caseName;
QByteArray cmdBytes = command.toLatin1();
QDataStream socketStream(&socket);
socketStream.setVersion(QDataStream::Qt_4_0);
socketStream << (qint64)(cmdBytes.size());
socket.write(cmdBytes);
// Get response. First wait for the header
while (socket.bytesAvailable() < (int)(3*sizeof(quint64)))
{
if (!socket.waitForReadyRead(riOctavePlugin::longTimeOutMilliSecs))
{
error("Waiting for header: %s",socket.errorString().toLatin1().data());
return;
}
}
// Read timestep count and blocksize
quint64 iCount;
quint64 jCount;
quint64 kCount;
socketStream >> iCount;
socketStream >> jCount;
socketStream >> kCount;
dim_vector dv (1, 1);
dv(0) = 3;
gridDimensions.resize(dv);
gridDimensions(0) = iCount;
gridDimensions(1) = jCount;
gridDimensions(2) = kCount;
QString tmp = QString("riGetMainGridDimensions : Read main grid dimensions");
if (caseName.isEmpty())
{
tmp += QString(" from active case.");
}
else
{
tmp += QString(" from %1.").arg(caseName);
}
octave_stdout << tmp.toStdString() << " Dimensions: " << iCount << ", " << jCount << ", " << kCount << std::endl;
return;
}
DEFUN_DLD (riGetMainGridDimensions, args, nargout,
"Usage:\n"
"\n"
" riGetMainGridDimensions( [CaseName/CaseIndex])\n"
"\n"
"Returns a vector of size 3: [ICount, JCount, KCount] \n"
"Containing the dimensions of the main grid in the requested case.\n"
"If the Eclipse Case is not defined, the active View in ResInsight is used."
)
{
int nargin = args.length ();
if (nargin > 1)
{
error("riGetActiveCellInfo: Too many arguments. Only the name or index of the case is valid input.\n");
print_usage();
}
else if (nargout < 1)
{
error("riGetActiveCellInfo: Missing output argument.\n");
print_usage();
}
else
{
int32NDArray propertyFrames;
if (nargin > 0)
getMainGridDimensions(propertyFrames, "127.0.0.1", riOctavePlugin::portNumber(), args(0).char_matrix_value().row_as_string(0).c_str());
else
getMainGridDimensions(propertyFrames, "127.0.0.1", riOctavePlugin::portNumber(), "");
return octave_value(propertyFrames);
}
return octave_value_list ();
}

View File

@@ -0,0 +1,158 @@
#include <QtNetwork>
#include <octave/oct.h>
#include <octave/oct-map.h>
#include "riSettings.h"
#include "RiaSocketDataTransfer.cpp" // NB! Include cpp-file to avoid linking of additional file in oct-compile configuration
struct GridLocalCell
{
int gridIndex;
int i;
int j;
int k;
};
struct Connection
{
GridLocalCell fromCell;
GridLocalCell toCell;
};
void getNNCConnections(std::vector<Connection>& connections, 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: %s",socket.errorString().toLatin1().data());
return;
}
QString command = QString("GetNNCConnections %1").arg(caseId);
QByteArray cmdBytes = command.toLatin1();
QDataStream socketStream(&socket);
socketStream.setVersion(riOctavePlugin::qtDataStreamVersion);
socketStream << (qint64)(cmdBytes.size());
socket.write(cmdBytes);
while (socket.bytesAvailable() < (int)sizeof(quint64))
{
if (!socket.waitForReadyRead(riOctavePlugin::longTimeOutMilliSecs))
{
error("Waiting for header: %s",socket.errorString().toLatin1().data());
return;
}
OCTAVE_QUIT;
}
quint64 connectionCount;
quint64 byteCount;
quint64 rowByteSize = sizeof(qint32) * 4 * 2;
socketStream >> connectionCount;
byteCount = connectionCount * rowByteSize;
while (socket.bytesAvailable() < (int)byteCount)
{
if (!socket.waitForReadyRead(riOctavePlugin::longTimeOutMilliSecs))
{
error("Waiting for data: %s",socket.errorString().toLatin1().data());
return;
}
OCTAVE_QUIT;
}
connections.resize(connectionCount);
for (size_t i = 0; i < connectionCount; ++i)
{
socketStream >> connections[i].fromCell.gridIndex;
socketStream >> connections[i].fromCell.i >> connections[i].fromCell.j >> connections[i].fromCell.k;
socketStream >> connections[i].toCell.gridIndex;
socketStream >> connections[i].toCell.i >> connections[i].toCell.j >> connections[i].toCell.k;
}
return;
}
DEFUN_DLD(riGetNNCConnections, args, nargout,
"Usage:\n"
"\n"
" riGetNNCConnections([CaseId])\n"
"\n"
"This function returns a two dimensional matrix containing grid and IJK information for each NNC in the requested case.\n"
"The columns contain the following information:\n"
"[GridIdx, I, J, K]:\n"
" GridIdx : The index of the grid the cell resides in. (Main grid has index 0)\n"
" I, J, K : 1-based index address of the cell in the grid.\n"
"\n"
"If the CaseId is not defined, ResInsight's Current Case is used.\n"
)
{
int nargin = args.length();
if (nargin > 1)
{
error("riGetNNCConnections: Too many arguments, CaseId are optional input arguments.\n");
print_usage();
}
else if (nargout < 1)
{
error("riGetNNCConnections: Missing output argument.\n");
print_usage();
}
else
{
std::vector<Connection> connections;
qint64 caseId = -1;
if (nargin > 0)
{
if (riOctavePlugin::isOctaveValueNumeric(args(0)))
{
unsigned int argCaseId = args(0).uint_value();
caseId = argCaseId;
}
}
getNNCConnections(connections, "127.0.0.1", riOctavePlugin::portNumber(), caseId);
Cell cellValuesGridIndex(connections.size(), 2);
Cell cellValuesI(connections.size(), 2);
Cell cellValuesJ(connections.size(), 2);
Cell cellValuesK(connections.size(), 2);
for (size_t i = 0; i < connections.size(); ++i)
{
cellValuesGridIndex(i, 0) = connections[i].fromCell.gridIndex;
cellValuesGridIndex(i, 1) = connections[i].toCell.gridIndex;
cellValuesI(i, 0) = connections[i].fromCell.i;
cellValuesI(i, 1) = connections[i].toCell.i;
cellValuesJ(i, 0) = connections[i].fromCell.j;
cellValuesJ(i, 1) = connections[i].toCell.j;
cellValuesK(i, 0) = connections[i].fromCell.k;
cellValuesK(i, 1) = connections[i].toCell.k;
}
octave_map m;
m.assign(riOctavePlugin::cellIndex_gridIndex, cellValuesGridIndex);
m.assign(riOctavePlugin::cellIndex_I, cellValuesI);
m.assign(riOctavePlugin::cellIndex_J, cellValuesJ);
m.assign(riOctavePlugin::cellIndex_K, cellValuesK);
return octave_value(m);
}
return octave_value();
}

View File

@@ -0,0 +1,152 @@
#include <QtNetwork>
#include <octave/oct.h>
#include <octave/oct-map.h>
#include "riSettings.h"
void getNNCPropertyNames(std::vector<QString>& propNames, std::vector<QString>& 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: %s",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: %s",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: %s",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<QString> propertyNames;
std::vector<QString> propertyTypes;
getNNCPropertyNames(propertyNames, propertyTypes, "127.0.0.1", riOctavePlugin::portNumber(), 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();
}

View File

@@ -0,0 +1,172 @@
#include <QtNetwork>
#include <octave/oct.h>
#include <octave/oct-map.h>
#include "riSettings.h"
void getPropertyNames(std::vector<QString>& propNames, std::vector<QString>& propTypes, const QString &hostName, quint16 port,
const qint64& caseId, QString porosityModel)
{
QString serverName = hostName;
quint16 serverPort = port;
QTcpSocket socket;
socket.connectToHost(serverName, serverPort);
if (!socket.waitForConnected(riOctavePlugin::connectTimeOutMilliSecs))
{
error("Connection: %s",socket.errorString().toLatin1().data());
return;
}
// Create command and send it:
QString command;
command += QString("GetPropertyNames") + " " + QString::number(caseId) + " " + porosityModel;
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: %s",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: %s",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 (riGetPropertyNames, args, nargout,
"Usage:\n"
"\n"
" riGetPropertyNames([CaseId]), [PorosityModel = \"Matrix\"|\"Fracture\"] \n"
"\n"
"This function returns the name and type of all the properties in the case as a Vector of Structures.\n"
"The Structure is defined as: \n"
"PropertyInfo {\n"
" PropName = string # Name of the property as received from the analysis tool \n"
" PropType = string # The type of the property: \"StaticNative\", \"DynamicNative\", \"Input\", \"Generated\" \n"
"} \n"
"If the CaseId is not defined, ResInsights Current Case is used.\n"
)
{
int nargin = args.length ();
if (nargin > 2)
{
error("riGetPropertyNames: Too many arguments, this function takes two optional arguments.\n");
print_usage();
}
else if (nargout != 1)
{
error("riGetPropertyNames: Wrong number of output arguments, this function requires one output argument.\n");
print_usage();
}
else
{
qint64 argCaseId = -1;
QString porosityModel = "Matrix";
if (nargin == 1)
{
if (args(0).is_string())
{
porosityModel = args(0).char_matrix_value().row_as_string(0).c_str();
}
else
{
argCaseId = args(0).uint_value();
}
}
else if (nargin == 2)
{
argCaseId = args(0).uint_value();
porosityModel = args(1).char_matrix_value().row_as_string(0).c_str();
}
if (porosityModel != "Matrix" && porosityModel != "Fracture")
{
error("riGetPropertyNames: The value for \"PorosityModel\" is unknown. Please use either \"Matrix\" or \"Fracture\"\n");
print_usage();
return octave_value_list ();
}
std::vector<QString> propertyNames;
std::vector<QString> propertyTypes;
getPropertyNames(propertyNames, propertyTypes, "127.0.0.1", riOctavePlugin::portNumber(), argCaseId, porosityModel);
size_t caseCount = propertyNames.size();
if (propertyNames.size() != propertyTypes.size() )
{
error("riGetPropertyNames: 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();
}

View File

@@ -0,0 +1,150 @@
#include <QtNetwork>
#include <octave/oct.h>
#include <octave/oct-map.h>
#include "riSettings.h"
void getSelectedCases(std::vector<qint64>& caseIds, std::vector<QString>& caseNames, std::vector<QString>& caseTypes, std::vector<qint64>& caseGroupIds, const QString &hostName, quint16 port)
{
QString serverName = hostName;
quint16 serverPort = port;
QTcpSocket socket;
socket.connectToHost(serverName, serverPort);
if (!socket.waitForConnected(riOctavePlugin::connectTimeOutMilliSecs))
{
error("Connection: %s",socket.errorString().toLatin1().data());
return;
}
// Create command and send it:
QString command("GetSelectedCases");
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: %s",socket.errorString().toLatin1().data());
return;
}
}
quint64 byteCount;
socketStream >> byteCount;
while (socket.bytesAvailable() < (int)(byteCount))
{
if (!socket.waitForReadyRead(riOctavePlugin::longTimeOutMilliSecs))
{
error("Waiting for data: %s",socket.errorString().toLatin1().data());
return;
}
OCTAVE_QUIT;
}
quint64 selectionCount;
socketStream >> selectionCount;
qint64 caseId = -1;
QString caseName;
QString caseType;
qint64 caseGroupId = -1;
for (size_t i = 0; i < selectionCount; i++)
{
socketStream >> caseId;
socketStream >> caseName;
socketStream >> caseType;
socketStream >> caseGroupId;
caseIds.push_back(caseId);
caseNames.push_back(caseName);
caseTypes.push_back(caseType);
caseGroupIds.push_back(caseGroupId);
}
return;
}
DEFUN_DLD (riGetSelectedCases, args, nargout,
"Usage:\n"
"\n"
" riGetSelectedCases()\n"
"\n"
"This function returns a CaseInfo Structure for each of the cases selected in ResInsight at the time when the script was launched.\n"
)
{
int nargin = args.length ();
if (nargin > 0)
{
error("riGetSelectedCases: Too many arguments, this function does not take any arguments.\n");
print_usage();
}
else if (nargout != 1)
{
error("riGetSelectedCases: Wrong number of output arguments, this function requires one output argument.\n");
print_usage();
}
else
{
std::vector<qint64> caseIds;
std::vector<QString> caseNames;
std::vector<QString> caseTypes;
std::vector<qint64> caseGroupIds;
getSelectedCases(caseIds, caseNames, caseTypes, caseGroupIds, "127.0.0.1", riOctavePlugin::portNumber());
size_t caseCount = caseIds.size();
if (caseCount != caseNames.size() ||
caseCount != caseTypes.size() ||
caseCount != caseGroupIds.size())
{
error("riGetSelectedCases: Inconsistent data received from ResInsight.\n");
}
else
{
// Create cells with N items for each field in the data structure
Cell cellValuesA(caseCount, 1);
Cell cellValuesB(caseCount, 1);
Cell cellValuesC(caseCount, 1);
Cell cellValuesD(caseCount, 1);
for (size_t i = 0; i < caseCount; i++)
{
cellValuesA(i) = caseIds[i];
cellValuesB(i) = caseNames[i].toLatin1().data();
cellValuesC(i) = caseTypes[i].toLatin1().data();
cellValuesD(i) = caseGroupIds[i];
}
// Build a map between the field name and field cell values
octave_map m;
m.assign(riOctavePlugin::caseInfo_CaseId, cellValuesA);
m.assign(riOctavePlugin::caseInfo_CaseName, cellValuesB);
m.assign(riOctavePlugin::caseInfo_CaseType, cellValuesC);
m.assign(riOctavePlugin::caseInfo_CaseGroupId, cellValuesD);
return octave_value(m);
}
}
return octave_value();
}

View File

@@ -0,0 +1,135 @@
#include <QtNetwork>
#include <QStringList>
#include <octave/oct.h>
#include "riSettings.h"
#include "RiaSocketDataTransfer.cpp" // NB! Include cpp-file to avoid linking of additional file in oct-compile configuration
void getSelectedCells(int32NDArray& selectedCellInfo, 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: %s",socket.errorString().toLatin1().data());
return;
}
// Create command and send it:
QString command = QString("GetSelectedCells %1").arg(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)(2*sizeof(quint64)))
{
if (!socket.waitForReadyRead(riOctavePlugin::longTimeOutMilliSecs))
{
error("Waiting for header: %s",socket.errorString().toLatin1().data());
return;
}
}
// Read timestep count and blocksize
quint64 columnCount;
quint64 byteCountForOneTimestep;
size_t selectedCellCount;
socketStream >> columnCount;
socketStream >> byteCountForOneTimestep;
selectedCellCount = byteCountForOneTimestep / sizeof(qint32);
dim_vector dv (2, 1);
dv(0) = selectedCellCount;
dv(1) = columnCount;
selectedCellInfo.resize(dv);
if (!(byteCountForOneTimestep && columnCount))
{
error ("No selected cells found in ResInsight");
return;
}
#if OCTAVE_MAJOR_VERSION > 6
auto internalMatrixData = (qint32*)selectedCellInfo.fortran_vec();
#else
qint32* internalMatrixData = (qint32*)selectedCellInfo.fortran_vec()->mex_get_data();
#endif
QStringList errorMessages;
if (!RiaSocketDataTransfer::readBlockDataFromSocket(&socket, (char*)(internalMatrixData), columnCount * byteCountForOneTimestep, errorMessages))
{
for (int i = 0; i < errorMessages.size(); i++)
{
error("%s",errorMessages[i].toLatin1().data());
}
OCTAVE_QUIT;
}
QString tmp = QString("riGetSelectedCells : Read selected cell info");
octave_stdout << tmp.toStdString() << " Selected cells: " << selectedCellCount << ", Columns: " << columnCount << std::endl;
return;
}
DEFUN_DLD (riGetSelectedCells, args, nargout,
"Usage:\n"
"\n"
" Matrix[numSelectedCells][5] riGetSelectedCells([CaseId])\n"
"\n"
"This function returns a two dimensional matrix containing cell info for each selected cell.\n"
"The columns contain the following information:\n"
"[CaseId, GridIdx, I, J, K]\n"
" CaseId : The ID of the case the cell resides in.\n"
" GridIdx : The index of the grid the cell resides in. (Main grid has index 0)\n"
" I, J, K : 1-based index address of the cell in the grid.\n"
)
{
int nargin = args.length ();
if (nargin > 1)
{
error("riGetSelectedCells: Too many arguments.\n");
print_usage();
}
else if (nargout < 1)
{
error("riGetSelectedCells: Missing output argument.\n");
print_usage();
}
else
{
qint64 caseId = -1;
if (nargin > 0)
{
unsigned int argCaseId = args(0).uint_value();
caseId = argCaseId;
}
int32NDArray propertyFrames;
getSelectedCells(propertyFrames, "127.0.0.1", riOctavePlugin::portNumber(), caseId);
return octave_value(propertyFrames);
}
return octave_value();
}

View File

@@ -0,0 +1,144 @@
#include <QtNetwork>
#include <QStringList>
#include <octave/oct.h>
#include "riSettings.h"
#include "RiaSocketDataTransfer.cpp" // NB! Include cpp-file to avoid linking of additional file in oct-compile configuration
void getStaticNNCValues(std::vector<double>& propertyValues, const QString &serverName, quint16 serverPort,
const qint64& caseId, QString propertyName)
{
QTcpSocket socket;
socket.connectToHost(serverName, serverPort);
if (!socket.waitForConnected(riOctavePlugin::connectTimeOutMilliSecs))
{
error("Connection: %s",socket.errorString().toLatin1().data());
return;
}
QDataStream socketStream(&socket);
socketStream.setVersion(riOctavePlugin::qtDataStreamVersion);
// Create command as a string with arguments , and send it:
QString command;
command += "GetStaticNNCValues " + QString::number(caseId) + " " + propertyName;
QByteArray cmdBytes = command.toLatin1();
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: %s",socket.errorString().toLatin1().data());
return;
}
}
// Read connection count and timestep count
quint64 connectionCount;
socketStream >> connectionCount;
if (!(connectionCount))
{
error ("Could not find the requested data in ResInsight");
return;
}
propertyValues.reserve(connectionCount);
for (size_t i = 0; i < connectionCount; ++i)
{
double val;
socketStream >> val;
propertyValues.push_back(val);
}
QString tmp = QString("riGetStaticNNCValues : Read %1").arg(propertyName);
if (caseId < 0)
{
tmp += QString(" from current case.");
}
else
{
tmp += QString(" from case with Id: %1.").arg(caseId);
}
octave_stdout << tmp.toStdString() << " Connections: " << connectionCount << std::endl;
return;
}
DEFUN_DLD (riGetStaticNNCValues, args, nargout,
"Usage:\n"
"\n"
" riGetStaticNNCValues([CaseId], PropertyName)\n"
"\n"
"This function returns a vector with the static NNC values for each connection.\n"
"\n"
"See riGetNNCConnections for information about each individual connection.\n"
"If the CaseId is not defined, ResInsight's Current Case is used.\n"
)
{
int nargin = args.length ();
if (nargin < 1)
{
error("riGetStaticNNCValues: Too few arguments. The name of the property requested is necessary.\n");
print_usage();
return octave_value();
}
else if (nargin > 2)
{
error("riGetStaticNNCValues: Too many arguments.\n");
print_usage();
return octave_value();
}
else if (nargout < 1)
{
error("riGetStaticNNCValues: Missing output argument.\n");
print_usage();
return octave_value();
}
std::vector<int> argIndices;
argIndices.push_back(0);
argIndices.push_back(1);
// Check if we have a CaseId:
if (!riOctavePlugin::isOctaveValueNumeric(args(argIndices[0])))
{
argIndices[0] = -1;
for (size_t aIdx = 1; aIdx < argIndices.size(); ++aIdx)
--argIndices[aIdx];
}
std::vector<double> propertyValues;
qint32 caseId = -1;
std::string propertyName;
if (argIndices[0] >= 0) caseId = args(argIndices[0]).int_value();
if (argIndices[1] >= 0) propertyName = args(argIndices[1]).char_matrix_value().row_as_string(0);
getStaticNNCValues(propertyValues, "127.0.0.1", riOctavePlugin::portNumber(), caseId, propertyName.c_str());
dim_vector dv(2, 1);
dv(0) = propertyValues.size();
dv(1) = 1;
NDArray oct_propertyValues(dv);
for (size_t i = 0; i < propertyValues.size(); ++i)
{
oct_propertyValues(i) = propertyValues[i];
}
return octave_value(oct_propertyValues);
}

View File

@@ -0,0 +1,182 @@
#include <QtNetwork>
#include <octave/oct.h>
#include <octave/oct-map.h>
#include "riSettings.h"
void getTimeStepDates( std::vector<qint32>& yearValues,
std::vector<qint32>& monthValues,
std::vector<qint32>& dayValues,
std::vector<qint32>& hourValues,
std::vector<qint32>& minuteValues,
std::vector<qint32>& secondValues,
const qint64& caseId,
const QString& hostName,
quint16 port)
{
QString serverName = hostName;
quint16 serverPort = port;
QTcpSocket socket;
socket.connectToHost(serverName, serverPort);
if (!socket.waitForConnected(riOctavePlugin::connectTimeOutMilliSecs))
{
error("Connection: %s",socket.errorString().toLatin1().data());
return;
}
// Create command and send it:
QString command = QString("GetTimeStepDates %1").arg(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: %s",socket.errorString().toLatin1().data());
return;
}
}
quint64 byteCount;
socketStream >> byteCount;
while (socket.bytesAvailable() < (int)(byteCount))
{
if (!socket.waitForReadyRead(riOctavePlugin::longTimeOutMilliSecs))
{
error("Waiting for data: %s",socket.errorString().toLatin1().data());
return;
}
OCTAVE_QUIT;
}
quint64 timeStepCount;
socketStream >> timeStepCount;
for (size_t i = 0; i < timeStepCount; i++)
{
qint32 intValue;
socketStream >> intValue;
yearValues.push_back(intValue);
socketStream >> intValue;
monthValues.push_back(intValue);
socketStream >> intValue;
dayValues.push_back(intValue);
socketStream >> intValue;
hourValues.push_back(intValue);
socketStream >> intValue;
minuteValues.push_back(intValue);
socketStream >> intValue;
secondValues.push_back(intValue);
}
return;
}
DEFUN_DLD (riGetTimeStepDates, args, nargout,
"Usage:\n"
"\n"
" riGetTimeStepDates()\n"
"\n"
"This function returns the date information for each of the time steps in the case as a Vector of Structures.\n"
"The Structure is defined as:\n"
"TimeStepDate = {\n"
" Year = int # The year eg. 2013\n"
" Month = int # The month. Eg. 12\n"
" Day = int # The day in the month. Eg. 24\n"
" Hour = int # The hour of the day. Eg. 17\n"
" Minute = int # The minute in the hour. Eg. 55\n"
" Second = int # The second within the minute. Eg. 30\n"
"}\n"
"If the CaseId is not defined, ResInsight<68>s Current Case is used.\n"
)
{
int nargin = args.length ();
if (nargin > 1)
{
error("riGetTimeStepDates: Too many arguments, this function takes one optional argument.\n");
print_usage();
}
else if (nargout != 1)
{
error("riGetTimeStepDates: Wrong number of output arguments, this function requires one output argument.\n");
print_usage();
}
else
{
qint64 caseId = -1;
if (nargin > 0)
{
if (riOctavePlugin::isOctaveValueNumeric(args(0)))
{
unsigned int argCaseId = args(0).uint_value();
caseId = argCaseId;
}
}
std::vector<qint32> yearValues;
std::vector<qint32> monthValues;
std::vector<qint32> dayValues;
std::vector<qint32> hourValues;
std::vector<qint32> minuteValues;
std::vector<qint32> secondValues;
getTimeStepDates(yearValues, monthValues, dayValues, hourValues, minuteValues, secondValues, caseId, "127.0.0.1", riOctavePlugin::portNumber());
size_t timeStepDateCount = yearValues.size();
// Create cells with N items for each field in the data structure
Cell cellValuesA(timeStepDateCount, 1);
Cell cellValuesB(timeStepDateCount, 1);
Cell cellValuesC(timeStepDateCount, 1);
Cell cellValuesD(timeStepDateCount, 1);
Cell cellValuesE(timeStepDateCount, 1);
Cell cellValuesF(timeStepDateCount, 1);
for (size_t i = 0; i < timeStepDateCount; i++)
{
cellValuesA(i) = yearValues[i];
cellValuesB(i) = monthValues[i];
cellValuesC(i) = dayValues[i];
cellValuesD(i) = hourValues[i];
cellValuesE(i) = minuteValues[i];
cellValuesF(i) = secondValues[i];
}
// Build a map between the field name and field cell values
octave_map m;
m.assign(riOctavePlugin::timeStepDate_Year, cellValuesA);
m.assign(riOctavePlugin::timeStepDate_Month, cellValuesB);
m.assign(riOctavePlugin::timeStepDate_Day, cellValuesC);
m.assign(riOctavePlugin::timeStepDate_Hour, cellValuesD);
m.assign(riOctavePlugin::timeStepDate_Minute, cellValuesE);
m.assign(riOctavePlugin::timeStepDate_Second, cellValuesF);
return octave_value(m);
}
return octave_value();
}

View File

@@ -0,0 +1,128 @@
#include <QtNetwork>
#include <octave/oct.h>
#include "riSettings.h"
void getTimeStepDates( std::vector<double>& decimalDays,
const qint64& caseId,
const QString& hostName,
quint16 port)
{
QString serverName = hostName;
quint16 serverPort = port;
QTcpSocket socket;
socket.connectToHost(serverName, serverPort);
if (!socket.waitForConnected(riOctavePlugin::connectTimeOutMilliSecs))
{
error("Connection: %s",socket.errorString().toLatin1().data());
return;
}
// Create command and send it:
QString command = QString("GetTimeStepDays %1").arg(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: %s",socket.errorString().toLatin1().data());
return;
}
}
quint64 byteCount;
socketStream >> byteCount;
while (socket.bytesAvailable() < (int)(byteCount))
{
if (!socket.waitForReadyRead(riOctavePlugin::longTimeOutMilliSecs))
{
error("Waiting for data: %s",socket.errorString().toLatin1().data());
return;
}
OCTAVE_QUIT;
}
quint64 timeStepCount;
socketStream >> timeStepCount;
octave_stdout << "byte count: " << byteCount << ", Timesteps: " << timeStepCount << std::endl;
for (size_t i = 0; i < timeStepCount; i++)
{
double doubleValue;
socketStream >> doubleValue;
decimalDays.push_back(doubleValue);
}
return;
}
DEFUN_DLD (riGetTimeStepDays, args, nargout,
"Usage:\n"
"\n"
" riGetTimeStepDays()\n"
"\n"
"This function returns the time from the simulation start\n"
"as decimal days for all the time steps as a Vector of doubles.\n"
"If the CaseId is not defined, ResInsight<68>s Current Case is used.\n"
)
{
int nargin = args.length ();
if (nargin > 1)
{
error("riGetTimeStepDays: Too many arguments, this function takes one optional argument.\n");
print_usage();
}
else if (nargout != 1)
{
error("riGetTimeStepDays: Wrong number of output arguments, this function requires one output argument.\n");
print_usage();
}
else
{
qint64 caseId = -1;
if (nargin > 0)
{
if (riOctavePlugin::isOctaveValueNumeric(args(0)))
{
unsigned int argCaseId = args(0).uint_value();
caseId = argCaseId;
}
}
std::vector<double> decimalDays;
getTimeStepDates(decimalDays, caseId, "127.0.0.1", riOctavePlugin::portNumber());
dim_vector dv(2, 1);
dv(0) = decimalDays.size();
dv(1) = 1;
NDArray oct_decimalDays(dv);
for (size_t i = 0; i < decimalDays.size(); i++)
{
oct_decimalDays(i) = decimalDays[i];
}
return octave_value(oct_decimalDays);
}
return octave_value();
}

View File

@@ -0,0 +1,265 @@
#include <QtNetwork>
#include <octave/oct.h>
#include <octave/oct-map.h>
#include "riSettings.h"
void getWellCells( std::vector<int>& cellIs,
std::vector<int>& cellJs,
std::vector<int>& cellKs,
std::vector<int>& gridIndices,
std::vector<int>& cellStatuses,
std::vector<int>& branchIds,
std::vector<int>& segmentIds,
const QString &hostName, quint16 port,
const qint64& caseId, const QString& wellName, int requestedTimeStep)
{
QString serverName = hostName;
quint16 serverPort = port;
QTcpSocket socket;
socket.connectToHost(serverName, serverPort);
if (!socket.waitForConnected(riOctavePlugin::connectTimeOutMilliSecs))
{
error("Connection: %s",socket.errorString().toLatin1().data());
return;
}
// Create command and send it:
QString command;
command += QString("GetWellCells") + " " + QString::number(caseId) + " " + wellName + " " + QString::number(requestedTimeStep) ;
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: %s",socket.errorString().toLatin1().data());
return;
}
}
quint64 byteCount;
socketStream >> byteCount;
if (byteCount == 0)
{
return;
}
while (socket.bytesAvailable() < (int)(byteCount))
{
if (!socket.waitForReadyRead(riOctavePlugin::longTimeOutMilliSecs))
{
error("Waiting for data: %s",socket.errorString().toLatin1().data());
return;
}
OCTAVE_QUIT;
}
quint64 cellCount;
socketStream >> cellCount;
octave_stdout << "riGetWellCells: Number of cells in well " << wellName.toLatin1().data() << " : " << cellCount << std::endl;
cellIs .reserve(cellCount);
cellJs .reserve(cellCount);
cellKs .reserve(cellCount);
gridIndices .reserve(cellCount);
cellStatuses .reserve(cellCount);
branchIds .reserve(cellCount);
segmentIds .reserve(cellCount);
qint32 i, j, k, gIdx, cStat, bId, sId;
for (size_t cIdx = 0; cIdx < cellCount; cIdx++)
{
socketStream >> i;
socketStream >> j;
socketStream >> k;
socketStream >> gIdx;
socketStream >> cStat;
socketStream >> bId;
socketStream >> sId;
cellIs.push_back (i);
cellJs.push_back (j);
cellKs.push_back (k);
gridIndices.push_back (gIdx);
cellStatuses.push_back(cStat);
branchIds.push_back (bId);
segmentIds.push_back (sId);
}
return;
}
DEFUN_DLD (riGetWellCells, args, nargout,
"Usage:\n"
"\n"
" riGetWellCells ([CaseId], WellName, TimeStep) \n"
"\n"
"This function returns the cells defined in the specified well for the time step requested \n"
"as a vector of Structures. \n"
"The Structure is defined as:\n"
"WellCellInfo { \n"
" I, J, K = int # Index to the cell in the grid\n"
" GridIndex = int # the index of the grid. Main grid has index 0.\n"
" CellStatus = int # is either 0 or 1, meaning the cell is closed or open respectively\n"
" BranchId = int # Branch id of the branch intersecting the cell\n"
" SegmentId = int # Branch segment id of the branch intersecting the cell\n"
"}\n"
"If the CaseId is not defined, ResInsights Current Case is used.\n"
)
{
if (nargout != 1)
{
error("riGetWellCells: Wrong number of output arguments, this function requires one output argument.\n");
print_usage();
return octave_value();
}
int nargin = args.length ();
if (nargin < 2)
{
error("riGetWellCells: Too few arguments, this function needs at least the well name and a timestep as input.\n");
print_usage();
return octave_value();
}
if (nargin > 3)
{
error("riGetWellCells: Too many arguments, this function takes at most three arguments.\n");
print_usage();
return octave_value();
}
std::vector<int> argIndices;
argIndices.push_back(0); // caseId
argIndices.push_back(1); // WellName
argIndices.push_back(2); // TimeStep
// Check if we do not have a CaseId:
if (args(argIndices[0]).is_string()) // Check if first argument is a text. If it is, the caseId is missing
{
argIndices[0] = -1;
for (size_t aIdx = 1; aIdx < argIndices.size(); ++aIdx)
--argIndices[aIdx];
}
if (!args(argIndices[1]).is_string()) // Check if the WellName argument is actually a string
{
error("riGetWellCells: Missing Well Name. this function needs at least the well name and a timestep as input.\n");
print_usage();
return octave_value();
}
if (!riOctavePlugin::isOctaveValueNumeric(args(argIndices[2]))) // Check if the TimeStep argument is actually a number
{
error("riGetWellCells: The last argument must be a timestep index.\n");
print_usage();
return octave_value();
}
// Setup the argument list
int caseId = -1;
std::string wellName = "UNDEFINED";
int requestedTimeStep = -1;
if (argIndices[0] >= 0) caseId = args(argIndices[0]).int_value();
if (argIndices[1] >= 0) wellName = args(argIndices[1]).char_matrix_value().row_as_string(0);
if (argIndices[2] >= 0) requestedTimeStep = args(argIndices[2]).int_value();
if (wellName == "UNDEFINED")
{
error("riGetWellCells: The argument must be a text containing the well name.\n");
print_usage();
return octave_value();
}
if (requestedTimeStep == -1)
{
error("riGetWellCells: The last argument must be a timestep index (1 - timestepCount).\n");
print_usage();
return octave_value();
}
std::vector<int> cellIs, cellJs, cellKs;
std::vector<int> gridIndices;
std::vector<int> cellStatuses;
std::vector<int> branchIds;
std::vector<int> segmentIds;
getWellCells( cellIs, cellJs, cellKs,
gridIndices,
cellStatuses,
branchIds,
segmentIds,
"127.0.0.1", riOctavePlugin::portNumber(),
caseId, QString::fromStdString(wellName), requestedTimeStep);
size_t cellCount = cellIs.size();
if (cellJs.size() != cellCount
|| cellKs.size() != cellCount
|| gridIndices.size() != cellCount
|| cellStatuses.size() != cellCount
|| branchIds.size() != cellCount
|| segmentIds.size() != cellCount )
{
error("riGetWellCells: Inconsistent data received from ResInsight.\n");
return octave_value();
}
// Create cells with N items for each field in the data structure
Cell cellIscv (cellCount, 1);
Cell cellJscv (cellCount, 1);
Cell cellKscv (cellCount, 1);
Cell gridIndicescv (cellCount, 1);
Cell cellStatusescv (cellCount, 1);
Cell branchIdscv (cellCount, 1);
Cell segmentIdscv (cellCount, 1);
for (size_t i = 0; i < cellCount; i++)
{
cellIscv (i) = cellIs [i];
cellJscv (i) = cellJs [i];
cellKscv (i) = cellKs [i];
gridIndicescv (i) = gridIndices [i];
cellStatusescv (i) = cellStatuses[i];
branchIdscv (i) = branchIds [i];
segmentIdscv (i) = segmentIds [i];
}
// Build a map between the field name and field cell values
octave_map m;
m.assign(riOctavePlugin::wellCellInfo_I, cellIscv );
m.assign(riOctavePlugin::wellCellInfo_J, cellJscv );
m.assign(riOctavePlugin::wellCellInfo_K, cellKscv );
m.assign(riOctavePlugin::wellCellInfo_GridIndex , gridIndicescv );
m.assign(riOctavePlugin::wellCellInfo_CellStatus, cellStatusescv);
m.assign(riOctavePlugin::wellCellInfo_BranchId, branchIdscv );
m.assign(riOctavePlugin::wellCellInfo_SegmentId, segmentIdscv );
return octave_value(m);
}

View File

@@ -0,0 +1,126 @@
#include <QtNetwork>
#include <octave/oct.h>
#include <octave/oct-map.h>
#include "riSettings.h"
void getWellNames(std::vector<QString>& wellNames, 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: %s",socket.errorString().toLatin1().data());
return;
}
// Create command and send it:
QString command;
command += QString("GetWellNames") + " " + 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: %s",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: %s",socket.errorString().toLatin1().data());
return;
}
OCTAVE_QUIT;
}
quint64 wellCount;
socketStream >> wellCount;
QString wellName;
for (size_t i = 0; i < wellCount; i++)
{
socketStream >> wellName;
wellNames.push_back(wellName);
}
return;
}
DEFUN_DLD (riGetWellNames, args, nargout,
"Usage:\n"
"\n"
" riGetWellNames([CaseId]) \n"
"\n"
"This function returns the names of all the wells in the case as a Vector of strings.\n"
"If the CaseId is not defined, ResInsights Current Case is used.\n"
)
{
int nargin = args.length ();
if (nargin > 1)
{
error("riGetWellNames: Too many arguments, this function takes one optional arguments.\n");
print_usage();
}
else if (nargout != 1)
{
error("riGetWellNames: 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<QString> wellNames;
getWellNames(wellNames, "127.0.0.1", riOctavePlugin::portNumber(), argCaseId);
size_t caseCount = wellNames.size();
// Create cells with N items for each field in the data structure
string_vector octaveWellNames;
for (size_t i = 0; i < caseCount; i++)
{
octaveWellNames.append(wellNames[i].toStdString());
}
return octave_value(Cell(octaveWellNames));
}
return octave_value();
}

View File

@@ -0,0 +1,206 @@
#include <QtNetwork>
#include <octave/oct.h>
#include <octave/oct-map.h>
#include "riSettings.h"
void getWellStatus(std::vector<QString>& wellTypes, std::vector<int>& wellStatuses, const QString &hostName, quint16 port,
const qint64& caseId, const QString& wellName, const int32NDArray& requestedTimeSteps)
{
QString serverName = hostName;
quint16 serverPort = port;
QTcpSocket socket;
socket.connectToHost(serverName, serverPort);
if (!socket.waitForConnected(riOctavePlugin::connectTimeOutMilliSecs))
{
error("Connection: %s",socket.errorString().toLatin1().data());
return;
}
// Create command and send it:
QString command;
command += QString("GetWellStatus") + " " + QString::number(caseId) + " " + wellName;
for (int i = 0; i < requestedTimeSteps.numel(); ++i)
{
if (i == 0) command += " ";
command += QString::number(static_cast<int>(requestedTimeSteps.elem(i)) - 1); // To make the index 0-based
if (i != requestedTimeSteps.numel() -1) command += " ";
}
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: %s",socket.errorString().toLatin1().data());
return;
}
}
quint64 byteCount;
socketStream >> byteCount;
while (socket.bytesAvailable() < (int)(byteCount))
{
if (!socket.waitForReadyRead(riOctavePlugin::longTimeOutMilliSecs))
{
error("Waiting for data: %s",socket.errorString().toLatin1().data());
return;
}
OCTAVE_QUIT;
}
quint64 timeStepCount;
socketStream >> timeStepCount;
QString wellType;
qint32 wellStatus;
for (size_t i = 0; i < timeStepCount; i++)
{
socketStream >> wellType;
socketStream >> wellStatus;
wellTypes.push_back(wellType);
wellStatuses.push_back(wellStatus);
}
return;
}
DEFUN_DLD (riGetWellStatus, args, nargout,
"Usage:\n"
"\n"
" riGetWellStatus ([CaseId], WellName, [RequestedTimeSteps]) \n"
"\n"
"This function returns the status information for a specified well for each\n"
"requested time step as a vector of Structures. \n"
"The Structure is defined as:\n"
"WellStatus { \n"
" WellType = string # \"Producer\", \"OilInjector\", \"WaterInjector\", \"GasInjector\", \"NotDefined\" \n"
" WellStatus = int # is either 0 or 1, meaning the well is shut or open respectively.\n"
"}\n"
"If the CaseId is not defined, ResInsights Current Case is used.\n"
)
{
if (nargout != 1)
{
error("riGetWellStatus: Wrong number of output arguments, this function requires one output argument.\n");
print_usage();
return octave_value();
}
int nargin = args.length ();
if (nargin < 1)
{
error("riGetWellStatus: Too few arguments, this function needs at least the well name as input.\n");
print_usage();
return octave_value();
}
if (nargin > 3)
{
error("riGetWellStatus: Too many arguments, this function takes at most three arguments.\n");
print_usage();
return octave_value();
}
std::vector<int> argIndices;
argIndices.push_back(0); // caseId
argIndices.push_back(1); // WellName
argIndices.push_back(2); // TimeSteps
// Check if we do not have a CaseId:
if (args(argIndices[0]).is_string()) // Check if first argument is a text. If it is, the caseId is missing
{
argIndices[0] = -1;
for (size_t aIdx = 1; aIdx < argIndices.size(); ++aIdx)
--argIndices[aIdx];
}
// Check if we have a Requested TimeSteps
int lastArgumentIndex = argIndices[2] ;
if (!(nargin > argIndices[2] && (args(argIndices[2]).is_matrix_type() || riOctavePlugin::isOctaveValueNumeric(args(argIndices[2])))))
{
argIndices[2] = -1;
}
// Check if we have more arguments than we should
if (nargin > lastArgumentIndex + 1)
{
error("riGetWellStatus: Unexpected argument at the end.\n");
print_usage();
return octave_value_list ();
}
// Setup the argument list
NDArray propertyFrames;
int caseId = -1;
std::string wellName = "UNDEFINED";
int32NDArray requestedTimeSteps;
if (argIndices[0] >= 0) caseId = args(argIndices[0]).int_value();
if (argIndices[1] >= 0) wellName = args(argIndices[1]).char_matrix_value().row_as_string(0);
if (argIndices[2] >= 0) requestedTimeSteps = args(argIndices[2]).int32_array_value();
if (wellName == "UNDEFINED")
{
error("riGetWellStatus: The argument must be a text containing the well name.\n");
print_usage();
return octave_value();
}
std::vector<QString> wellType;
std::vector<int> wellStatus;
getWellStatus(wellType, wellStatus, "127.0.0.1", riOctavePlugin::portNumber(), caseId, QString::fromStdString(wellName), requestedTimeSteps);
size_t caseCount = wellType.size();
if (wellType.size() != wellStatus.size() )
{
error("riGetWellStatus: Inconsistent data received from ResInsight.\n");
return octave_value();
}
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) = wellType[i].toLatin1().data();
cellValuesC(i) = wellStatus[i];
}
// Build a map between the field name and field cell values
octave_map m;
m.assign(riOctavePlugin::wellStatus_WellType, cellValuesB);
m.assign(riOctavePlugin::wellStatus_WellStatus, cellValuesC);
return octave_value(m);
}
}

View File

@@ -0,0 +1,226 @@
#include <QtNetwork>
#include <QStringList>
#include <octave/oct.h>
#include "riSettings.h"
#include "RiaSocketDataTransfer.cpp" // NB! Include cpp-file to avoid linking of additional file in oct-compile configuration
#ifdef WIN32
#include <Windows.h>
#endif //WIN32
void setEclipseProperty(const Matrix& propertyFrames, const QString &hostName, quint16 port,
const qint64& caseId, QString propertyName, const int32NDArray& requestedTimeSteps, QString porosityModel)
{
QTcpSocket socket;
socket.connectToHost(hostName, port);
if (!socket.waitForConnected(riOctavePlugin::connectTimeOutMilliSecs))
{
error("Connection: %s",socket.errorString().toLatin1().data());
return;
}
QDataStream socketStream(&socket);
socketStream.setVersion(riOctavePlugin::qtDataStreamVersion);
// Create command as a string with arguments , and send it:
QString command;
command += "SetActiveCellProperty " + QString::number(caseId) + " " + propertyName + " " + porosityModel;
for (int i = 0; i < requestedTimeSteps.numel(); ++i)
{
if (i == 0) command += " ";
command += QString::number(static_cast<int>(requestedTimeSteps.elem(i)) - 1); // To make the index 0-based
if (i != requestedTimeSteps.numel() -1) command += " ";
}
QByteArray cmdBytes = command.toLatin1();
socketStream << (qint64)(cmdBytes.size());
socket.write(cmdBytes);
// Write property data header
dim_vector mxDims = propertyFrames.dims();
qint64 cellCount = mxDims.elem(0);
qint64 timeStepCount = mxDims.elem(1);
qint64 timeStepByteCount = cellCount * sizeof(double);
socketStream << (qint64)(timeStepCount);
socketStream << (qint64)timeStepByteCount;
#if OCTAVE_MAJOR_VERSION > 6
auto internalData = propertyFrames.data();
#else
const double* internalData = propertyFrames.fortran_vec();
#endif
QStringList errorMessages;
if (!RiaSocketDataTransfer::writeBlockDataToSocket(&socket, (const char *)internalData, timeStepByteCount*timeStepCount, errorMessages))
{
for (int i = 0; i < errorMessages.size(); i++)
{
octave_stdout << errorMessages[i].toStdString();
}
return;
}
QString tmp = QString("riSetActiveCellProperty : Wrote %1").arg(propertyName);
if (caseId == -1)
{
tmp += QString(" to current case.");
}
else
{
tmp += QString(" to case with Id = %1.").arg(caseId);
}
octave_stdout << tmp.toStdString() << " Active Cells : " << cellCount << " Time steps : " << timeStepCount << std::endl;
while(socket.bytesToWrite() && socket.state() == QAbstractSocket::ConnectedState)
{
// octave_stdout << "Bytes to write: " << socket.bytesToWrite() << std::endl;
socket.waitForBytesWritten(riOctavePlugin::shortTimeOutMilliSecs);
OCTAVE_QUIT;
}
//octave_stdout << " Socket write completed" << std::endl;
if (socket.bytesToWrite() && socket.state() != QAbstractSocket::ConnectedState)
{
error("riSetActiveCellProperty : ResInsight refused to accept the data. Maybe the dimensions or porosity model is wrong");
}
#ifdef WIN32
// TODO: Due to synchronization issues seen on Windows 10, it is required to do a sleep here to be able to catch disconnect
// signals from the socket. No sleep causes the server to hang.
Sleep(100);
#endif //WIN32
return;
}
DEFUN_DLD (riSetActiveCellProperty, args, nargout,
"Usage:\n"
"\n"
"\triSetActiveCellProperty( Matrix[numActiveCells][numTimeSteps], [CaseId], PropertyName, [TimeStepIndices], [PorosityModel = \"Matrix\"|\"Fracture\"] ) \n"
"\n"
"Interprets the supplied matrix as a property set defined for the active cells in the case, "
"and puts the data into ResInsight as a \"Generated\" property with the name \"PropertyName\"."
"The \"TimeStepIndices\" argument is used to \"label\" all the time steps present in the supplied data matrix,"
"and must thus be complete. The time step data will then be put into ResInsight at the time steps requested."
"If the CaseId is not defined, ResInsights Current Case is used."
)
{
int nargin = args.length ();
if (nargin < 2)
{
error("riSetActiveCellProperty: Too few arguments. The data matrix and the name of the property requested is neccesary\n");
print_usage();
return octave_value_list ();
}
if (nargin > 5)
{
error("riSetActiveCellProperty: Too many arguments.\n");
print_usage();
return octave_value_list ();
}
Matrix propertyFrames = args(0).matrix_value();
dim_vector mxDims = propertyFrames.dims();
if (mxDims.length() != 2)
{
error("riSetActiveCellProperty: The supplied Data Matrix must have two dimensions: NumActiveCells*numTimesteps");
print_usage();
return octave_value_list ();
}
std::vector<int> argIndices;
argIndices.push_back(0);
argIndices.push_back(1);
argIndices.push_back(2);
argIndices.push_back(3);
argIndices.push_back(4);
// Check if we have a CaseId:
if (!riOctavePlugin::isOctaveValueNumeric(args(argIndices[1])))
{
argIndices[1] = -1;
for (size_t aIdx = 2; aIdx < argIndices.size(); ++aIdx)
--argIndices[aIdx];
}
// Check if we have a Requested TimeSteps
if (!(nargin > argIndices[3] && args(argIndices[3]).is_matrix_type() && !args(argIndices[3]).is_string()))
{
argIndices[3] = -1;
for (size_t aIdx = 4; aIdx < argIndices.size(); ++aIdx)
--argIndices[aIdx];
}
// Check if we have a PorosityModel
int lastArgumentIndex = argIndices[4] ;
if (!(nargin > argIndices[4] && args(argIndices[4]).is_string()))
{
argIndices[4] = -1;
for (size_t aIdx = 5; aIdx < argIndices.size(); ++aIdx)
--argIndices[aIdx];
}
// Check if we have more arguments than we should
if (nargin > lastArgumentIndex + 1)
{
error("riSetActiveCellProperty: Unexpected argument after the PorosityModel.\n");
print_usage();
return octave_value_list ();
}
int caseId = -1;
std::string propertyName = "UNDEFINED";
int32NDArray requestedTimeSteps;
std::string porosityModel = "Matrix";
if (argIndices[1] >= 0) caseId = args(argIndices[1]).int_value();
if (argIndices[2] >= 0) propertyName = args(argIndices[2]).char_matrix_value().row_as_string(0);
if (argIndices[3] >= 0) requestedTimeSteps = args(argIndices[3]).int32_array_value();
if (argIndices[4] >= 0) porosityModel = args(argIndices[4]).string_value();
if (requestedTimeSteps.numel())
{
int timeStepCount = mxDims.elem(1);
if (requestedTimeSteps.numel() != timeStepCount)
{
error("riSetActiveCellProperty: The number of timesteps in the input matrix must match the number of timesteps in the TimeStepIndices array.");
print_usage();
return octave_value_list ();
}
}
if (porosityModel != "Matrix" && porosityModel != "Fracture")
{
error("riSetActiveCellProperty: The value for \"PorosityModel\" is unknown. Please use either \"Matrix\" or \"Fracture\"\n");
print_usage();
return octave_value_list ();
}
setEclipseProperty(propertyFrames, "127.0.0.1", riOctavePlugin::portNumber(), caseId, propertyName.c_str(), requestedTimeSteps, porosityModel.c_str());
return octave_value_list ();
}

View File

@@ -0,0 +1,265 @@
#include <QtNetwork>
#include <QStringList>
#include <octave/oct.h>
#include "riSettings.h"
#include "RiaSocketDataTransfer.cpp" // NB! Include cpp-file to avoid linking of additional file in oct-compile configuration
#ifdef WIN32
#include <Windows.h>
#endif //WIN32
void setEclipseProperty(const NDArray& propertyFrames, const QString &hostName, quint16 port,
const qint64& caseId, const qint64& gridIndex, QString propertyName, const int32NDArray& timeStepIndices, QString porosityModel)
{
QTcpSocket socket;
socket.connectToHost(hostName, port);
if (!socket.waitForConnected(riOctavePlugin::connectTimeOutMilliSecs))
{
error("Connection: %s",socket.errorString().toLatin1().data());
return;
}
QDataStream socketStream(&socket);
socketStream.setVersion(riOctavePlugin::qtDataStreamVersion);
// Create command as a string with arguments , and send it:
QString command = QString("SetGridProperty %1 %2 %3 %4").arg(caseId).arg(gridIndex).arg(propertyName).arg(porosityModel);
for (int i = 0; i < timeStepIndices.numel(); ++i)
{
if (i == 0) command += " ";
command += QString::number(static_cast<int>(timeStepIndices.elem(i)) - 1); // To make the index 0-based
if (i != timeStepIndices.numel() -1) command += " ";
}
QByteArray cmdBytes = command.toLatin1();
socketStream << (qint64)(cmdBytes.size());
socket.write(cmdBytes);
// Write property data header
dim_vector mxDims = propertyFrames.dims();
qint64 cellCountI = mxDims.elem(0);
qint64 cellCountJ = mxDims.elem(1);
qint64 cellCountK = mxDims.elem(2);
qint64 timeStepCount = 0;
if (mxDims.length() > 3)
{
timeStepCount = mxDims.elem(3);
}
else
{
timeStepCount = 1;
}
qint64 singleTimeStepByteCount = cellCountI * cellCountJ * cellCountK * sizeof(double);
//octave_stdout << " Cell count I: " << cellCountI << " Cell count J: " << cellCountJ << " Cell count K: " << cellCountK << std::endl;
//octave_stdout << " Time step count: " << timeStepCount << std::endl;
socketStream << (qint64)(cellCountI);
socketStream << (qint64)(cellCountJ);
socketStream << (qint64)(cellCountK);
socketStream << (qint64)(timeStepCount);
socketStream << (qint64)singleTimeStepByteCount;
#if OCTAVE_MAJOR_VERSION > 6
auto internalData = propertyFrames.data();
#else
const double* internalData = propertyFrames.fortran_vec();
#endif
QStringList errorMessages;
if (!RiaSocketDataTransfer::writeBlockDataToSocket(&socket, (const char *)internalData, timeStepCount*singleTimeStepByteCount, errorMessages))
{
for (int i = 0; i < errorMessages.size(); i++)
{
octave_stdout << errorMessages[i].toStdString();
}
size_t cellCount = cellCountI * cellCountJ * cellCountK;
error("riSetGridProperty : Was not able to write the proper amount of data to ResInsight:");
octave_stdout << " Cell count : " << cellCount << "Time steps : " << timeStepCount << std::endl;
return;
}
QString tmp = QString("riSetGridProperty : Wrote %1").arg(propertyName);
if (caseId == -1)
{
tmp += QString(" to current case,");
}
else
{
tmp += QString(" to case with Id = %1,").arg(caseId);
}
tmp += QString(" grid index: %1, ").arg(gridIndex);
octave_stdout << tmp.toStdString() << " Time steps : " << timeStepCount << std::endl;
while(socket.bytesToWrite() && socket.state() == QAbstractSocket::ConnectedState)
{
// octave_stdout << "Bytes to write: " << socket.bytesToWrite() << std::endl << std::flush;
socket.waitForBytesWritten(riOctavePlugin::shortTimeOutMilliSecs);
OCTAVE_QUIT;
}
if (socket.bytesToWrite() && socket.state() != QAbstractSocket::ConnectedState)
{
error("riSetGridProperty : ResInsight refused to accept the data. Maybe the dimensions or porosity model is wrong.\n");
}
#ifdef WIN32
// TODO: Due to synchronization issues seen on Windows 10, it is required to do a sleep here to be able to catch disconnect
// signals from the socket. No sleep causes the server to hang.
Sleep(100);
#endif //WIN32
return;
}
DEFUN_DLD (riSetGridProperty, args, nargout,
"Usage:\n"
"\n"
"\triSetGridProperty( Matrix[numI][numJ][numK][numTimeSteps], [CaseId], GridIndex, PropertyName, [TimeStepIndices], [PorosityModel = \"Matrix\"|\"Fracture\"] ) \n"
"\n"
"Interprets the supplied matrix as a property set defined for all cells in one of the grids in a case, and puts the data into ResInsight as a \"Generated\" property with the name \"PropertyName\".\n"
"The \"TimeStepIndices\" argument is used to \"label\" all the time steps present in the supplied data matrix, and must thus be complete. The time step data will then be put into ResInsight at the time steps requested."
"If the CaseId is not defined, ResInsights Current Case is used.\n"
)
{
int nargin = args.length ();
if (nargin < 2)
{
error("riSetGridProperty: Too few arguments, required input parameters are the data matrix, grid index and property name.\n");
print_usage();
return octave_value_list ();
}
if (nargin > 6)
{
error("riSetGridProperty: Too many arguments.\n");
print_usage();
return octave_value_list ();
}
NDArray propertyFrames = args(0).array_value();
dim_vector mxDims = propertyFrames.dims();
if (!(mxDims.length() == 3 || mxDims.length() == 4))
{
error("riSetGridProperty: The supplied Data Matrix must have three dimensions (numI*numJ*numK*1) or four dimensions (numI*numJ*numK*numTimeSteps)");
print_usage();
return octave_value_list ();
}
std::vector<int> argIndices;
argIndices.push_back(0); // Array data
argIndices.push_back(1); // Case Id
argIndices.push_back(2); // GridIndex
argIndices.push_back(3); // Property name
argIndices.push_back(4); // Time step indices
argIndices.push_back(5); // Porosity model
// Check that the second argument is an integer
if (!args(argIndices[1]).is_real_scalar()) // Check if second argument is an int. If it is
{
error("riSetGridProperty: The GridIndex argument is missing");
print_usage();
return octave_value_list ();
}
// Check if we do not have a CaseId:
if (args(argIndices[2]).is_string()) // Check if second argument is a text. If it is, the caseid is missing
{
argIndices[1] = -1;
for (size_t aIdx = 2; aIdx < argIndices.size(); ++aIdx)
--argIndices[aIdx];
}
// Check if we have a Requested TimeSteps
if (!(nargin > argIndices[4] && args(argIndices[4]).is_matrix_type() && !args(argIndices[4]).is_string()))
{
argIndices[4] = -1;
for (size_t aIdx = 5; aIdx < argIndices.size(); ++aIdx)
--argIndices[aIdx];
}
// Check if we have a PorosityModel
int lastArgumentIndex = argIndices[5] ;
if (!(nargin > argIndices[5] && args(argIndices[5]).is_string()))
{
argIndices[5] = -1;
for (size_t aIdx = 6; aIdx < argIndices.size(); ++aIdx)
--argIndices[aIdx];
}
// Check if we have more arguments than we should
if (nargin > lastArgumentIndex + 1)
{
error("riSetGridProperty: Unexpected argument after the PorosityModel.\n");
print_usage();
return octave_value_list ();
}
int caseId = -1;
int gridIndex = 0;
std::string propertyName = "UNDEFINED";
int32NDArray timeStepIndices;
std::string porosityModel = "Matrix";
if (argIndices[1] >= 0) caseId = args(argIndices[1]).int_value();
if (argIndices[2] >= 0) gridIndex = args(argIndices[2]).int_value();
if (argIndices[3] >= 0) propertyName = args(argIndices[3]).char_matrix_value().row_as_string(0);
if (argIndices[4] >= 0) timeStepIndices = args(argIndices[4]).int32_array_value();
if (argIndices[5] >= 0) porosityModel = args(argIndices[5]).string_value();
if (timeStepIndices.numel() > 1)
{
if (mxDims.length() == 3)
{
error("riSetGridProperty: The input matrix has three dimensions, but there are more than one time step in [TimeStepIndices]. If more than one time step is defined, the data matrix must be 4D.");
print_usage();
return octave_value_list ();
}
int timeStepCount = mxDims.elem(3);
if (timeStepIndices.numel() != timeStepCount)
{
error("riSetGridProperty: The number of time steps in the input matrix must match the number of time steps in the TimeStepIndices array.");
print_usage();
return octave_value_list ();
}
}
if (porosityModel != "Matrix" && porosityModel != "Fracture")
{
error("riSetGridProperty: The value for \"PorosityModel\" is unknown. Please use either \"Matrix\" or \"Fracture\"\n");
print_usage();
return octave_value_list ();
}
setEclipseProperty(propertyFrames, "127.0.0.1", riOctavePlugin::portNumber(), caseId, gridIndex, propertyName.c_str(), timeStepIndices, porosityModel.c_str());
return octave_value_list ();
}

View File

@@ -0,0 +1,193 @@
#include <QtNetwork>
#include <QStringList>
#include <octave/oct.h>
#include "riSettings.h"
#include "RiaSocketDataTransfer.cpp" // NB! Include cpp-file to avoid linking of additional file in oct-compile configuration
#ifdef WIN32
#include <Windows.h>
#endif //WIN32
void setNNCProperty(const Matrix& propertyFrames, const QString &hostName, quint16 port,
const qint64& caseId, QString propertyName, const int32NDArray& requestedTimeSteps)
{
QTcpSocket socket;
socket.connectToHost(hostName, port);
if (!socket.waitForConnected(riOctavePlugin::connectTimeOutMilliSecs))
{
error("Connection: %s",socket.errorString().toLatin1().data());
return;
}
QDataStream socketStream(&socket);
socketStream.setVersion(riOctavePlugin::qtDataStreamVersion);
// Create command as a string with arguments , and send it:
QString command;
command += "SetNNCProperty " + QString::number(caseId) + " " + propertyName;
for (int i = 0; i < requestedTimeSteps.numel(); ++i)
{
if (i == 0) command += " ";
command += QString::number(static_cast<int>(requestedTimeSteps.elem(i)) - 1); // To make the index 0-based
if (i != requestedTimeSteps.numel() -1) command += " ";
}
QByteArray cmdBytes = command.toLatin1();
socketStream << (qint64)(cmdBytes.size());
socket.write(cmdBytes);
// Write property data header
dim_vector mxDims = propertyFrames.dims();
qint64 connectionCount = mxDims.elem(0);
qint64 timeStepCount = mxDims.elem(1);
qint64 timeStepByteCount = connectionCount * sizeof(double);
socketStream << (qint64)(timeStepCount);
socketStream << (qint64)timeStepByteCount;
const double* internalData = propertyFrames.fortran_vec();
QStringList errorMessages;
if (!RiaSocketDataTransfer::writeBlockDataToSocket(&socket, (const char *)internalData, timeStepByteCount*timeStepCount, errorMessages))
{
for (int i = 0; i < errorMessages.size(); i++)
{
octave_stdout << errorMessages[i].toStdString();
}
return;
}
QString tmp = QString("riSetNNCProperty : Wrote %1").arg(propertyName);
if (caseId == -1)
{
tmp += QString(" to current case.");
}
else
{
tmp += QString(" to case with Id = %1.").arg(caseId);
}
octave_stdout << tmp.toStdString() << " NNC Connections : " << connectionCount << " Time steps : " << timeStepCount << std::endl;
while(socket.bytesToWrite() && socket.state() == QAbstractSocket::ConnectedState)
{
// octave_stdout << "Bytes to write: " << socket.bytesToWrite() << std::endl;
socket.waitForBytesWritten(riOctavePlugin::shortTimeOutMilliSecs);
OCTAVE_QUIT;
}
//octave_stdout << " Socket write completed" << std::endl;
if (socket.bytesToWrite() && socket.state() != QAbstractSocket::ConnectedState)
{
error("riSetNNCProperty : ResInsight refused to accept the data. Maybe the dimensions or porosity model is wrong");
}
#ifdef WIN32
// TODO: Due to synchronization issues seen on Windows 10, it is required to do a sleep here to be able to catch disconnect
// signals from the socket. No sleep causes the server to hang.
Sleep(100);
#endif //WIN32
return;
}
DEFUN_DLD (riSetNNCProperty, args, nargout,
"Usage:\n"
"\n"
"\triSetNNCProperty(Matrix[numNNCConnections][numTimeSteps], [CaseId], PropertyName, [TimeStepIndices]) \n"
"\n"
"Interprets the supplied matrix as a property set defined for the NNC connections in the case, "
"and puts the data into ResInsight as a \"Generated\" property with the name \"PropertyName\"."
"The \"TimeStepIndices\" argument is used to \"label\" all the time steps present in the supplied data matrix "
"and must thus be complete. The time step data will then be put into ResInsight at the time steps requested.\n"
"If the CaseId is not defined, ResInsight's Current Case is used."
)
{
int nargin = args.length ();
if (nargin < 2)
{
error("riSetNNCProperty: Too few arguments. The data matrix and the name of the property requested is necessary\n");
print_usage();
return octave_value_list ();
}
if (nargin > 4)
{
error("riSetNNCProperty: Too many arguments.\n");
print_usage();
return octave_value_list ();
}
Matrix propertyFrames = args(0).matrix_value();
dim_vector mxDims = propertyFrames.dims();
if (mxDims.length() != 2)
{
error("riSetNNCProperty: The supplied Data Matrix must have two dimensions: numNNCConnections*numTimesteps");
print_usage();
return octave_value_list ();
}
std::vector<int> argIndices;
argIndices.push_back(0);
argIndices.push_back(1);
argIndices.push_back(2);
argIndices.push_back(3);
// Check if we have a CaseId:
if (!riOctavePlugin::isOctaveValueNumeric(args(argIndices[1])))
{
argIndices[1] = -1;
for (size_t aIdx = 2; aIdx < argIndices.size(); ++aIdx)
--argIndices[aIdx];
}
// Check if we have a Requested TimeSteps
if (!(nargin > argIndices[3] && args(argIndices[3]).is_matrix_type() && !args(argIndices[3]).is_string()))
{
argIndices[3] = -1;
for (size_t aIdx = 4; aIdx < argIndices.size(); ++aIdx)
--argIndices[aIdx];
}
int caseId = -1;
std::string propertyName = "UNDEFINED";
int32NDArray requestedTimeSteps;
if (argIndices[1] >= 0) caseId = args(argIndices[1]).int_value();
if (argIndices[2] >= 0) propertyName = args(argIndices[2]).char_matrix_value().row_as_string(0);
if (argIndices[3] >= 0) requestedTimeSteps = args(argIndices[3]).int32_array_value();
if (requestedTimeSteps.numel())
{
int timeStepCount = mxDims.elem(1);
if (requestedTimeSteps.numel() != timeStepCount)
{
error("riSetNNCProperty: The number of time steps in the input matrix must match the number of time steps in the TimeStepIndices array.");
print_usage();
return octave_value_list ();
}
}
setNNCProperty(propertyFrames, "127.0.0.1", riOctavePlugin::portNumber(), caseId, propertyName.c_str(), requestedTimeSteps);
return octave_value_list ();
}

View File

@@ -0,0 +1,91 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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.
//
/////////////////////////////////////////////////////////////////////////////////
#include "../../ApplicationLibCode/SocketInterface/RiaSocketServerDefines.h"
namespace riOctavePlugin
{
const int connectTimeOutMilliSecs = 5000;
const int shortTimeOutMilliSecs = 1000;
const int longTimeOutMilliSecs = 6000000;
const int socketMaxByteCount = 100000;
// Octave data structure : CaseInfo
char caseInfo_CaseId[] = "CaseId";
char caseInfo_CaseName[] = "CaseName";
char caseInfo_CaseType[] = "CaseType";
char caseInfo_CaseGroupId[] = "CaseGroupId";
// Octave data structure: PropertyInfo
char propertyInfo_PropName[] = "PropName";
char propertyInfo_PropType[] = "PropType";
// Octave data structure: WellStatus
char wellStatus_WellType[] = "WellType";
char wellStatus_WellStatus[] = "WellStatus";
// Octave data structure : CaseGroupInfo
char caseGroupInfo_CaseGroupId[] = "CaseGroupId";
char caseGroupInfo_CaseGroupName[] = "CaseGroupName";
// Octave data structure : WellCellInfo
char wellCellInfo_I[] = "I";
char wellCellInfo_J[] = "J";
char wellCellInfo_K[] = "K";
char wellCellInfo_GridIndex [] = "GridIndex";
char wellCellInfo_CellStatus[] = "CellStatus";
char wellCellInfo_BranchId[] = "BranchId";
char wellCellInfo_SegmentId[] = "SegmentId";
// Octave data structure : TimeStepDate
char timeStepDate_Year[] = "Year";
char timeStepDate_Month[] = "Month";
char timeStepDate_Day[] = "Day";
char timeStepDate_Hour[] = "Hour";
char timeStepDate_Minute[] = "Minute";
char timeStepDate_Second[] = "Second";
// Octave data structure : CellIndex
char cellIndex_gridIndex[] = "GridIndex";
char cellIndex_I[] = "I";
char cellIndex_J[] = "J";
char cellIndex_K[] = "K";
bool isOctaveValueNumeric(const octave_value& value)
{
#if (OCTAVE_MAJOR_VERSION > 4 || (OCTAVE_MAJOR_VERSION == 4 && OCTAVE_MINOR_VERSION >= 4))
return value.isnumeric();
#else
return value.is_numeric_type();
#endif
}
int portNumber()
{
QString portStr = getenv(riOctavePlugin::portNumberKey().data());
if (!portStr.isEmpty())
{
return portStr.toInt();
}
return riOctavePlugin::defaultPortNumber;
}
}

View File

@@ -0,0 +1,205 @@
# - Find Octave
# GNU Octave is a high-level interpreted language, primarily intended for numerical computations.
# available at http://www.gnu.org/software/octave/
#
# This module defines:
# OCTAVE_EXECUTABLE - octave interpreter
# OCTAVE_INCLUDE_DIRS - include path for mex.h, mexproto.h
# OCTAVE_LIBRARIES - required libraries: octinterp, octave, cruft
# OCTAVE_OCTINTERP_LIBRARY - path to the library octinterp
# OCTAVE_OCTAVE_LIBRARY - path to the library octave
# OCTAVE_CRUFT_LIBRARY - path to the library cruft
# OCTAVE_VERSION_STRING - octave version string
# OCTAVE_MAJOR_VERSION - major version
# OCTAVE_MINOR_VERSION - minor version
# OCTAVE_PATCH_VERSION - patch version
# OCTAVE_OCT_FILE_DIR - object files that will be dynamically loaded
# OCTAVE_OCT_LIB_DIR - oct libraries
# OCTAVE_ROOT_DIR - octave prefix
# OCTAVE_M_SITE_DIR - .m files site dir
# OCTAVE_OCT_SITE_DIR - .oct files site dir
#
# The macro octave_add_oct allows to create compiled modules.
# octave_add_oct (target_name
# [SOURCES] source1 [source2 ...]
# [LINK_LIBRARIES lib1 [lib2 ...]]
# [EXTENSION ext]
#)
#
# To install it, you can the use the variable OCTAVE_OCT_FILE_DIR as follow:
# file (RELATIVE_PATH PKG_OCTAVE_OCT_SITE_DIR ${OCTAVE_ROOT_DIR} ${OCTAVE_OCT_SITE_DIR})
# install (
# TARGETS target_name
# DESTINATION ${PKG_OCTAVE_OCT_SITE_DIR}
#)
#=============================================================================
# Copyright 2013, Julien Schueller
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# The views and conclusions contained in the software and documentation are those
# of the authors and should not be interpreted as representing official policies,
# either expressed or implied, of the FreeBSD Project.
#=============================================================================
find_program(OCTAVE_CONFIG_EXECUTABLE
NAMES octave-config
)
if (OCTAVE_CONFIG_EXECUTABLE)
execute_process (COMMAND ${OCTAVE_CONFIG_EXECUTABLE} -p OCTAVE_HOME
OUTPUT_VARIABLE OCTAVE_ROOT_DIR
OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process (COMMAND ${OCTAVE_CONFIG_EXECUTABLE} --m-site-dir
OUTPUT_VARIABLE OCTAVE_M_SITE_DIR
OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process (COMMAND ${OCTAVE_CONFIG_EXECUTABLE} --oct-site-dir
OUTPUT_VARIABLE OCTAVE_OCT_SITE_DIR
OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process (COMMAND ${OCTAVE_CONFIG_EXECUTABLE} -p BINDIR
OUTPUT_VARIABLE OCTAVE_BIN_PATHS
OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process (COMMAND ${OCTAVE_CONFIG_EXECUTABLE} -p OCTINCLUDEDIR
OUTPUT_VARIABLE OCTAVE_INCLUDE_PATHS
OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process (COMMAND ${OCTAVE_CONFIG_EXECUTABLE} -p OCTLIBDIR
OUTPUT_VARIABLE OCTAVE_LIBRARIES_PATHS
OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process (COMMAND ${OCTAVE_CONFIG_EXECUTABLE} -p OCTFILEDIR
OUTPUT_VARIABLE OCTAVE_OCT_FILE_DIR
OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process (COMMAND ${OCTAVE_CONFIG_EXECUTABLE} -p OCTLIBDIR
OUTPUT_VARIABLE OCTAVE_OCT_LIB_DIR
OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process (COMMAND ${OCTAVE_CONFIG_EXECUTABLE} -v
OUTPUT_VARIABLE OCTAVE_VERSION_STRING
OUTPUT_STRIP_TRAILING_WHITESPACE)
if (OCTAVE_VERSION_STRING)
string (REGEX REPLACE "([0-9]+)\\..*" "\\1" OCTAVE_MAJOR_VERSION ${OCTAVE_VERSION_STRING})
string (REGEX REPLACE "[0-9]+\\.([0-9]+).*" "\\1" OCTAVE_MINOR_VERSION ${OCTAVE_VERSION_STRING})
string (REGEX REPLACE "[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" OCTAVE_PATCH_VERSION ${OCTAVE_VERSION_STRING})
endif ()
endif ()
find_program(OCTAVE_EXECUTABLE
HINTS ${OCTAVE_BIN_PATHS}
NAMES octave
)
find_program(OCTAVE_MKOCTFILE
HINTS ${OCTAVE_BIN_PATHS}
NAMES mkoctfile
)
find_library(OCTAVE_OCTINTERP_LIBRARY
NAMES octinterp liboctinterp
HINTS ${OCTAVE_LIBRARIES_PATHS}
)
find_library(OCTAVE_OCTAVE_LIBRARY
NAMES octave liboctave
HINTS ${OCTAVE_LIBRARIES_PATHS}
)
find_library(OCTAVE_CRUFT_LIBRARY
NAMES cruft libcruft
HINTS ${OCTAVE_LIBRARIES_PATHS}
)
set (OCTAVE_LIBRARIES ${OCTAVE_OCTINTERP_LIBRARY})
list (APPEND OCTAVE_LIBRARIES ${OCTAVE_OCTAVE_LIBRARY})
if (OCTAVE_CRUFT_LIBRARY)
list (APPEND OCTAVE_LIBRARIES ${OCTAVE_CRUFT_LIBRARY})
endif ()
find_path (OCTAVE_INCLUDE_DIR
NAMES octave/oct.h
PATHS "${OCTAVE_INCLUDE_PATHS}/.."
)
set (OCTAVE_INCLUDE_DIRS ${OCTAVE_INCLUDE_DIR} ${OCTAVE_INCLUDE_DIR}/octave)
macro (octave_add_oct FUNCTIONNAME)
set (_CMD SOURCES)
set (_SOURCES)
set (_LINK_LIBRARIES)
set (_EXTENSION)
set (_OCT_EXTENSION oct)
foreach (_ARG ${ARGN})
if (${_ARG} MATCHES SOURCES)
set (_CMD SOURCES)
elseif (${_ARG} MATCHES LINK_LIBRARIES)
set (_CMD LINK_LIBRARIES)
elseif (${_ARG} MATCHES EXTENSION)
set (_CMD EXTENSION)
else ()
if (${_CMD} MATCHES SOURCES)
list (APPEND _SOURCES "${_ARG}")
elseif (${_CMD} MATCHES LINK_LIBRARIES)
list (APPEND _LINK_LIBRARIES "${_ARG}")
elseif (${_CMD} MATCHES EXTENSION)
set (_OCT_EXTENSION ${_ARG})
endif ()
endif ()
endforeach ()
add_library (${FUNCTIONNAME} SHARED ${_SOURCES})
target_link_libraries (${FUNCTIONNAME} ${OCTAVE_LIBRARIES} ${_LINK_LIBRARIES})
set_target_properties (${FUNCTIONNAME} PROPERTIES
PREFIX ""
SUFFIX ".${_OCT_EXTENSION}"
)
endmacro ()
# handle REQUIRED and QUIET options
include (FindPackageHandleStandardArgs)
find_package_handle_standard_args (Octave REQUIRED_VARS OCTAVE_EXECUTABLE OCTAVE_ROOT_DIR OCTAVE_INCLUDE_DIRS OCTAVE_LIBRARIES VERSION_VAR OCTAVE_VERSION_STRING)
mark_as_advanced (
OCTAVE_OCT_FILE_DIR
OCTAVE_OCT_LIB_DIR
OCTAVE_OCTINTERP_LIBRARY
OCTAVE_OCTAVE_LIBRARY
OCTAVE_CRUFT_LIBRARY
OCTAVE_LIBRARIES
OCTAVE_INCLUDE_DIR
OCTAVE_INCLUDE_DIRS
OCTAVE_ROOT_DIR
OCTAVE_VERSION_STRING
OCTAVE_MAJOR_VERSION
OCTAVE_MINOR_VERSION
OCTAVE_PATCH_VERSION
)

View File

@@ -0,0 +1,20 @@
# -----------------------------
# Options effecting formatting.
# See: https://github.com/cheshirekow/cmake_format
# -----------------------------
with section("format"):
# How wide to allow formatted cmake files
line_width = 80
# How many spaces to tab for indent
tab_size = 2
# If true, separate flow control names from their parentheses with a space
separate_ctrl_name_with_space = False
# If true, separate function names from parentheses with a space
separate_fn_name_with_space = False
# If a statement is wrapped to more than one line, than dangle the closing
# parenthesis on its own line.
dangle_parens = True