ResInsight/OctavePlugin/riSetGridProperty.cpp
Magne Sjaastad 2372cf86ca Octave: Use long timeout (60 s) for all socket data transfer, as socket
data transfer is dependent on several layers of network optimizations.
2013-09-30 20:54:31 +02:00

247 lines
8.6 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <QtNetwork>
#include <octave/oct.h>
#include "riSettings.h"
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: ") + 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.length(); ++i)
{
if (i == 0) command += " ";
command += QString::number(static_cast<int>(timeStepIndices.elem(i)) - 1); // To make the index 0-based
if (i != timeStepIndices.length() -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;
const double* internalData = propertyFrames.fortran_vec();
int dataWritten = socket.write((const char *)internalData, singleTimeStepByteCount*timeStepCount);
if (dataWritten == singleTimeStepByteCount*timeStepCount)
{
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;
}
else
{
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 << " Data Written: " << dataWritten << " Should have written: " << timeStepCount * cellCount * sizeof(double) << std::endl;
}
while(socket.bytesToWrite() && socket.state() == QAbstractSocket::ConnectedState)
{
// octave_stdout << "Bytes to write: " << socket.bytesToWrite() << std::endl;
socket.waitForBytesWritten(riOctavePlugin::longTimeOutMilliSecs);
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");
}
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"
"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();
if (error_state)
{
error("riSetGridProperty: The supplied first argument is not a valid Matrix");
print_usage();
return octave_value_list ();
}
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()))
{
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.length() > 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.length() != 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", 40001, caseId, gridIndex, propertyName.c_str(), timeStepIndices, porosityModel.c_str());
return octave_value_list ();
}