mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
Refactor grid export and fault export
This commit is contained in:
@@ -24,6 +24,7 @@
|
||||
#include "RicExportFeatureImpl.h"
|
||||
#include "RicExportEclipseInputGridUi.h"
|
||||
|
||||
#include "RifEclipseInputFileTools.h"
|
||||
#include "RifReaderEclipseOutput.h"
|
||||
|
||||
#include "RimEclipseCase.h"
|
||||
@@ -85,7 +86,7 @@ void RicExportEclipseInputGridFeature::executeCommand(RimEclipseView* view,
|
||||
if (exportSettings.exportGrid())
|
||||
{
|
||||
auto task = progress.task("Export Input Grid", gridProgressPercentage);
|
||||
bool worked = RifReaderEclipseOutput::saveEclipseGrid(exportSettings.exportGridFilename(), view->eclipseCase()->eclipseCaseData(), min, max, refinement);
|
||||
bool worked = RifEclipseInputFileTools::exportGrid(exportSettings.exportGridFilename(), view->eclipseCase()->eclipseCaseData(), min, max, refinement);
|
||||
if (!worked)
|
||||
{
|
||||
RiaLogging::error(
|
||||
@@ -106,7 +107,7 @@ void RicExportEclipseInputGridFeature::executeCommand(RimEclipseView* view,
|
||||
for (QString keyword : keywords)
|
||||
{
|
||||
QString fileName = dirPath.absoluteFilePath(keyword + ".GRDECL");
|
||||
bool worked = RifReaderEclipseOutput::saveEclipseResults(fileName,
|
||||
bool worked = RifEclipseInputFileTools::exportKeywords(fileName,
|
||||
view->eclipseCase()->eclipseCaseData(),
|
||||
{keyword},
|
||||
fileWriteMode,
|
||||
@@ -129,7 +130,7 @@ void RicExportEclipseInputGridFeature::executeCommand(RimEclipseView* view,
|
||||
fileName = exportSettings.exportGridFilename();
|
||||
}
|
||||
|
||||
bool worked = RifReaderEclipseOutput::saveEclipseResults(fileName,
|
||||
bool worked = RifEclipseInputFileTools::exportKeywords(fileName,
|
||||
view->eclipseCase()->eclipseCaseData(),
|
||||
keywords,
|
||||
fileWriteMode,
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
#include "RigFault.h"
|
||||
#include "RigMainGrid.h"
|
||||
|
||||
#include "RifEclipseInputFileTools.h"
|
||||
|
||||
#include "RimEclipseCase.h"
|
||||
#include "RimFaultInView.h"
|
||||
|
||||
@@ -91,7 +93,7 @@ void RicExportFaultsFeature::onActionTriggered(bool isChecked)
|
||||
|
||||
QString completeFilename = selectedDir + "/" + baseFilename + ".grdecl";
|
||||
|
||||
RicExportFaultsFeature::saveFault(
|
||||
RifEclipseInputFileTools::saveFault(
|
||||
completeFilename, eclCase->eclipseCaseData()->mainGrid(), rimFault->faultGeometry()->faultFaces(), faultName);
|
||||
}
|
||||
}
|
||||
@@ -110,145 +112,3 @@ void RicExportFaultsFeature::setupActionLook(QAction* actionToSetup)
|
||||
actionToSetup->setText("Export Faults ...");
|
||||
actionToSetup->setIcon(QIcon(":/Save.png"));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Order FaultCellAndFace by i, j, face then k.
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RicExportFaultsFeature::faultOrdering(FaultCellAndFace first, FaultCellAndFace second)
|
||||
{
|
||||
size_t i1, i2, j1, j2, k1, k2;
|
||||
cvf::StructGridInterface::FaceType f1, f2;
|
||||
std::tie(i1, j1, k1, f1) = first;
|
||||
std::tie(i2, j2, k2, f2) = second;
|
||||
if (i1 == i2)
|
||||
{
|
||||
if (j1 == j2)
|
||||
{
|
||||
if (f1 == f2)
|
||||
{
|
||||
return k1 < k2;
|
||||
}
|
||||
else
|
||||
{
|
||||
return f1 < f2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return j1 < j2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return i1 < i2;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RicExportFaultsFeature::faceText(cvf::StructGridInterface::FaceType faceType)
|
||||
{
|
||||
switch (faceType)
|
||||
{
|
||||
case cvf::StructGridInterface::POS_I: return QString(" I");
|
||||
case cvf::StructGridInterface::NEG_I: return QString("-I");
|
||||
case cvf::StructGridInterface::POS_J: return QString(" J");
|
||||
case cvf::StructGridInterface::NEG_J: return QString("-J");
|
||||
case cvf::StructGridInterface::POS_K: return QString(" K");
|
||||
case cvf::StructGridInterface::NEG_K: return QString("-K");
|
||||
default: CVF_ASSERT(false);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RicExportFaultsFeature::writeLine(QTextStream & stream, QString faultName, size_t i, size_t j, size_t startK, size_t endK, cvf::StructGridInterface::FaceType faceType)
|
||||
{
|
||||
// Convert indices to eclipse format
|
||||
i++;
|
||||
j++;
|
||||
startK++;
|
||||
endK++;
|
||||
|
||||
stream << "'" << faultName << "'" << " " << i << " " << i
|
||||
<< " " << j << " " << j
|
||||
<< " " << startK << " " << endK
|
||||
<< " " << RicExportFaultsFeature::faceText(faceType) << " / ";
|
||||
stream << endl;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
void RicExportFaultsFeature::saveFault(QString completeFilename, const RigMainGrid* mainGrid, const std::vector<RigFault::FaultFace>& faultFaces, QString faultName)
|
||||
{
|
||||
QFile exportFile(completeFilename);
|
||||
|
||||
if (!exportFile.open(QIODevice::WriteOnly | QIODevice::Text) )
|
||||
{
|
||||
RiaLogging::error("Could not open the file : " + completeFilename);
|
||||
}
|
||||
|
||||
QTextStream stream(&exportFile);
|
||||
|
||||
stream << "FAULTS" << endl;
|
||||
|
||||
stream << "-- Name I1 I2 J1 J2 K1 K2 Face ( I/J/K )" << endl;
|
||||
|
||||
// 'NAME' 1 1 1 1 1 2 J /
|
||||
|
||||
std::vector<FaultCellAndFace> faultCellAndFaces;
|
||||
|
||||
for (const RigFault::FaultFace& faultCellAndFace : faultFaces)
|
||||
{
|
||||
size_t i, j, k;
|
||||
bool ok = mainGrid->ijkFromCellIndex(faultCellAndFace.m_nativeReservoirCellIndex, &i, &j, &k);
|
||||
if (!ok) continue;
|
||||
|
||||
faultCellAndFaces.push_back(std::make_tuple(i, j, k, faultCellAndFace.m_nativeFace));
|
||||
}
|
||||
|
||||
// Sort order: i, j, face then k.
|
||||
std::sort(faultCellAndFaces.begin(), faultCellAndFaces.end(), RicExportFaultsFeature::faultOrdering);
|
||||
|
||||
size_t lastI = std::numeric_limits<size_t>::max();
|
||||
size_t lastJ = std::numeric_limits<size_t>::max();
|
||||
size_t lastK = std::numeric_limits<size_t>::max();
|
||||
size_t startK = std::numeric_limits<size_t>::max();
|
||||
cvf::StructGridInterface::FaceType lastFaceType = cvf::StructGridInterface::FaceType::NO_FACE;
|
||||
|
||||
for (const FaultCellAndFace &faultCellAndFace : faultCellAndFaces)
|
||||
{
|
||||
size_t i, j, k;
|
||||
cvf::StructGridInterface::FaceType faceType;
|
||||
std::tie(i, j, k, faceType) = faultCellAndFace;
|
||||
|
||||
if (i != lastI || j != lastJ || lastFaceType != faceType || k != lastK+1)
|
||||
{
|
||||
// No fault should have no face
|
||||
if (lastFaceType != cvf::StructGridInterface::FaceType::NO_FACE)
|
||||
{
|
||||
RicExportFaultsFeature::writeLine(stream, faultName, lastI, lastJ, startK, lastK, lastFaceType);
|
||||
}
|
||||
lastI = i;
|
||||
lastJ = j;
|
||||
lastK = k;
|
||||
lastFaceType = faceType;
|
||||
startK = k;
|
||||
}
|
||||
else
|
||||
{
|
||||
lastK = k;
|
||||
}
|
||||
}
|
||||
// No fault should have no face
|
||||
if (lastFaceType != cvf::StructGridInterface::FaceType::NO_FACE)
|
||||
{
|
||||
RicExportFaultsFeature::writeLine(stream, faultName, lastI, lastJ, startK, lastK, lastFaceType);
|
||||
}
|
||||
stream << "/" << endl;
|
||||
}
|
||||
|
||||
@@ -20,13 +20,13 @@
|
||||
|
||||
#include "cafCmdFeature.h"
|
||||
|
||||
#include "RigFault.h"
|
||||
|
||||
#include <QString>
|
||||
#include <vector>
|
||||
#include "RigFault.h"
|
||||
|
||||
class RigMainGrid;
|
||||
|
||||
typedef std::tuple<size_t, size_t, size_t, cvf::StructGridInterface::FaceType> FaultCellAndFace;
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
@@ -40,11 +40,5 @@ protected:
|
||||
bool isCommandEnabled() override;
|
||||
void onActionTriggered( bool isChecked ) override;
|
||||
void setupActionLook( QAction* actionToSetup ) override;
|
||||
|
||||
private:
|
||||
static void saveFault(QString completeFilename, const RigMainGrid* mainGrid, const std::vector<RigFault::FaultFace>& faultFaces, QString faultName);
|
||||
static bool faultOrdering(FaultCellAndFace first, FaultCellAndFace second);
|
||||
static QString faceText(cvf::StructGridInterface::FaceType faceType);
|
||||
static void writeLine(QTextStream &stream, QString faultName, size_t i, size_t j, size_t startK, size_t endK, cvf::StructGridInterface::FaceType faceType);
|
||||
};
|
||||
|
||||
|
||||
@@ -20,7 +20,9 @@
|
||||
|
||||
#include "RifEclipseInputFileTools.h"
|
||||
|
||||
#include "RiaCellDividingTools.h"
|
||||
#include "RiaLogging.h"
|
||||
#include "RiaStringEncodingTools.h"
|
||||
|
||||
#include "RifReaderEclipseOutput.h"
|
||||
|
||||
@@ -208,6 +210,290 @@ bool RifEclipseInputFileTools::openGridFile(const QString& fileName, RigEclipseC
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RifEclipseInputFileTools::exportGrid(const QString& fileName,
|
||||
RigEclipseCaseData* eclipseCase,
|
||||
const cvf::Vec3st& min,
|
||||
const cvf::Vec3st& max,
|
||||
const cvf::Vec3st& refinement)
|
||||
{
|
||||
if (!eclipseCase)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const RigActiveCellInfo* activeCellInfo = eclipseCase->activeCellInfo(RiaDefines::MATRIX_MODEL);
|
||||
const RigActiveCellInfo* fractureActiveCellInfo = eclipseCase->activeCellInfo(RiaDefines::FRACTURE_MODEL);
|
||||
|
||||
CVF_ASSERT(activeCellInfo && fractureActiveCellInfo);
|
||||
|
||||
const RigMainGrid* mainGrid = eclipseCase->mainGrid();
|
||||
|
||||
int ecl_nx = static_cast<int>((max.x() - min.x()) * refinement.x() + 1);
|
||||
int ecl_ny = static_cast<int>((max.y() - min.y()) * refinement.y() + 1);
|
||||
int ecl_nz = static_cast<int>((max.z() - min.z()) * refinement.z() + 1);
|
||||
|
||||
size_t cellsPerOriginal = refinement.x() * refinement.y() * refinement.z();
|
||||
|
||||
caf::ProgressInfo progress(mainGrid->cellCount() * 2, "Save Eclipse Grid");
|
||||
int cellProgressInterval = 1000;
|
||||
|
||||
std::vector<float*> ecl_corners;
|
||||
ecl_corners.reserve(mainGrid->cellCount() * cellsPerOriginal);
|
||||
std::vector<int*> ecl_coords;
|
||||
ecl_coords.reserve(mainGrid->cellCount() * cellsPerOriginal);
|
||||
|
||||
const size_t* cellMappingECLRi = RifReaderEclipseOutput::eclipseCellIndexMapping();
|
||||
|
||||
int incrementalIndex = 0;
|
||||
for (size_t k = min.z() * refinement.z(); k <= max.z() * refinement.z(); ++k)
|
||||
{
|
||||
size_t mainK = k / refinement.z();
|
||||
size_t k0 = k - min.z() * refinement.z();
|
||||
for (size_t j = min.y() * refinement.y(); j <= max.y() * refinement.y(); ++j)
|
||||
{
|
||||
size_t mainJ = j / refinement.y();
|
||||
size_t j0 = j - min.y() * refinement.y();
|
||||
for (size_t i = min.x() * refinement.x(); i <= max.x() * refinement.x(); ++i)
|
||||
{
|
||||
size_t mainI = i / refinement.x();
|
||||
size_t i0 = i - min.x() * refinement.x();
|
||||
|
||||
size_t mainIndex = mainGrid->cellIndexFromIJK(mainI, mainJ, mainK);
|
||||
|
||||
int active = activeCellInfo->isActive(mainIndex) ? 1 : 0;
|
||||
|
||||
int* ecl_cell_coords = new int[5];
|
||||
ecl_cell_coords[0] = (int)(i0 + 1);
|
||||
ecl_cell_coords[1] = (int)(j0 + 1);
|
||||
ecl_cell_coords[2] = (int)(k0 + 1);
|
||||
ecl_cell_coords[3] = incrementalIndex++;
|
||||
ecl_cell_coords[4] = active;
|
||||
ecl_coords.push_back(ecl_cell_coords);
|
||||
|
||||
std::array<cvf::Vec3d, 8> cellCorners;
|
||||
mainGrid->cellCornerVertices(mainIndex, cellCorners.data());
|
||||
|
||||
auto refinedCoords =
|
||||
RiaCellDividingTools::createHexCornerCoords(cellCorners, refinement.x(), refinement.y(), refinement.z());
|
||||
|
||||
size_t subI = i % refinement.x();
|
||||
size_t subJ = j % refinement.y();
|
||||
size_t subK = k % refinement.z();
|
||||
size_t subIndex = subI + subJ * refinement.x() + subK * refinement.x() * refinement.y();
|
||||
|
||||
float* ecl_cell_corners = new float[24];
|
||||
for (size_t cIdx = 0; cIdx < 8; ++cIdx)
|
||||
{
|
||||
cvf::Vec3d cellCorner = refinedCoords[subIndex * 8 + cIdx];
|
||||
ecl_cell_corners[cellMappingECLRi[cIdx] * 3] = cellCorner[0];
|
||||
ecl_cell_corners[cellMappingECLRi[cIdx] * 3 + 1] = cellCorner[1];
|
||||
ecl_cell_corners[cellMappingECLRi[cIdx] * 3 + 2] = -cellCorner[2];
|
||||
}
|
||||
ecl_corners.push_back(ecl_cell_corners);
|
||||
}
|
||||
}
|
||||
if (incrementalIndex % cellProgressInterval == 0)
|
||||
{
|
||||
progress.setProgress(incrementalIndex);
|
||||
}
|
||||
}
|
||||
|
||||
ecl_grid_type* mainEclGrid =
|
||||
ecl_grid_alloc_GRID_data((int)ecl_coords.size(), ecl_nx, ecl_ny, ecl_nz, 5, &ecl_coords[0], &ecl_corners[0], false, NULL);
|
||||
progress.setProgress(mainGrid->cellCount());
|
||||
|
||||
for (float* floatArray : ecl_corners)
|
||||
{
|
||||
delete floatArray;
|
||||
}
|
||||
|
||||
for (int* intArray : ecl_coords)
|
||||
{
|
||||
delete intArray;
|
||||
}
|
||||
|
||||
FILE* filePtr = util_fopen(RiaStringEncodingTools::toNativeEncoded(fileName).data(), "w");
|
||||
|
||||
if (!filePtr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ecl_grid_fprintf_grdecl(mainEclGrid, filePtr);
|
||||
ecl_grid_free(mainEclGrid);
|
||||
fclose(filePtr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RifEclipseInputFileTools::exportKeywords(const QString& resultFileName,
|
||||
RigEclipseCaseData* eclipseCase,
|
||||
const std::vector<QString>& keywords,
|
||||
const QString& fileWriteMode,
|
||||
const cvf::Vec3st& min,
|
||||
const cvf::Vec3st& max,
|
||||
const cvf::Vec3st& refinement)
|
||||
{
|
||||
FILE* filePtr = util_fopen(RiaStringEncodingTools::toNativeEncoded(resultFileName).data(),
|
||||
RiaStringEncodingTools::toNativeEncoded(fileWriteMode).data());
|
||||
if (!filePtr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
RigCaseCellResultsData* cellResultsData = eclipseCase->results(RiaDefines::MATRIX_MODEL);
|
||||
RigActiveCellInfo* activeCells = cellResultsData->activeCellInfo();
|
||||
RigMainGrid* mainGrid = eclipseCase->mainGrid();
|
||||
|
||||
caf::ProgressInfo progress(keywords.size(), "Saving Keywords");
|
||||
|
||||
for (const QString& keyword : keywords)
|
||||
{
|
||||
std::vector<double> resultValues;
|
||||
|
||||
RigEclipseResultAddress resAddr(RiaDefines::STATIC_NATIVE, keyword);
|
||||
cellResultsData->ensureKnownResultLoaded(resAddr);
|
||||
resultValues = cellResultsData->cellScalarResults(resAddr)[0];
|
||||
CVF_ASSERT(!resultValues.empty());
|
||||
|
||||
std::vector<double> filteredResults;
|
||||
filteredResults.reserve(resultValues.size());
|
||||
|
||||
for (size_t k = min.z() * refinement.z(); k <= max.z() * refinement.z(); ++k)
|
||||
{
|
||||
size_t mainK = k / refinement.z();
|
||||
for (size_t j = min.y() * refinement.y(); j <= max.y() * refinement.y(); ++j)
|
||||
{
|
||||
size_t mainJ = j / refinement.y();
|
||||
for (size_t i = min.x() * refinement.x(); i <= max.x() * refinement.x(); ++i)
|
||||
{
|
||||
size_t mainI = i / refinement.x();
|
||||
|
||||
size_t mainIndex = mainGrid->cellIndexFromIJK(mainI, mainJ, mainK);
|
||||
|
||||
size_t resIndex = activeCells->cellResultIndex(mainIndex);
|
||||
if (resIndex != cvf::UNDEFINED_SIZE_T)
|
||||
{
|
||||
filteredResults.push_back(resultValues[resIndex]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ecl_kw_type* ecl_kw = nullptr;
|
||||
|
||||
if (keyword.endsWith("NUM"))
|
||||
{
|
||||
std::vector<int> resultValuesInt;
|
||||
resultValuesInt.reserve(filteredResults.size());
|
||||
for (double val : filteredResults)
|
||||
{
|
||||
resultValuesInt.push_back(static_cast<int>(val));
|
||||
}
|
||||
ecl_kw = ecl_kw_alloc_new(keyword.toLatin1().data(), (int)resultValuesInt.size(), ECL_INT, resultValuesInt.data());
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<float> resultValuesFloat;
|
||||
resultValuesFloat.reserve(filteredResults.size());
|
||||
for (double val : filteredResults)
|
||||
{
|
||||
resultValuesFloat.push_back(static_cast<float>(val));
|
||||
}
|
||||
ecl_kw =
|
||||
ecl_kw_alloc_new(keyword.toLatin1().data(), (int)resultValuesFloat.size(), ECL_FLOAT, resultValuesFloat.data());
|
||||
}
|
||||
|
||||
ecl_kw_fprintf_grdecl(ecl_kw, filePtr);
|
||||
ecl_kw_free(ecl_kw);
|
||||
progress.incrementProgress();
|
||||
}
|
||||
|
||||
fclose(filePtr);
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RifEclipseInputFileTools::saveFault(QString completeFilename,
|
||||
const RigMainGrid* mainGrid,
|
||||
const std::vector<RigFault::FaultFace>& faultFaces,
|
||||
QString faultName)
|
||||
{
|
||||
QFile exportFile(completeFilename);
|
||||
|
||||
if (!exportFile.open(QIODevice::WriteOnly | QIODevice::Text))
|
||||
{
|
||||
RiaLogging::error("Could not open the file : " + completeFilename);
|
||||
}
|
||||
|
||||
QTextStream stream(&exportFile);
|
||||
|
||||
stream << "FAULTS" << endl;
|
||||
|
||||
stream << "-- Name I1 I2 J1 J2 K1 K2 Face ( I/J/K )" << endl;
|
||||
|
||||
// 'NAME' 1 1 1 1 1 2 J /
|
||||
|
||||
std::vector<RigFault::FaultCellAndFace> faultCellAndFaces;
|
||||
|
||||
for (const RigFault::FaultFace& faultCellAndFace : faultFaces)
|
||||
{
|
||||
size_t i, j, k;
|
||||
bool ok = mainGrid->ijkFromCellIndex(faultCellAndFace.m_nativeReservoirCellIndex, &i, &j, &k);
|
||||
if (!ok) continue;
|
||||
|
||||
faultCellAndFaces.push_back(std::make_tuple(i, j, k, faultCellAndFace.m_nativeFace));
|
||||
}
|
||||
|
||||
// Sort order: i, j, face then k.
|
||||
std::sort(faultCellAndFaces.begin(), faultCellAndFaces.end(), RigFault::faultOrdering);
|
||||
|
||||
size_t lastI = std::numeric_limits<size_t>::max();
|
||||
size_t lastJ = std::numeric_limits<size_t>::max();
|
||||
size_t lastK = std::numeric_limits<size_t>::max();
|
||||
size_t startK = std::numeric_limits<size_t>::max();
|
||||
cvf::StructGridInterface::FaceType lastFaceType = cvf::StructGridInterface::FaceType::NO_FACE;
|
||||
|
||||
for (const RigFault::FaultCellAndFace& faultCellAndFace : faultCellAndFaces)
|
||||
{
|
||||
size_t i, j, k;
|
||||
cvf::StructGridInterface::FaceType faceType;
|
||||
std::tie(i, j, k, faceType) = faultCellAndFace;
|
||||
|
||||
if (i != lastI || j != lastJ || lastFaceType != faceType || k != lastK + 1)
|
||||
{
|
||||
// No fault should have no face
|
||||
if (lastFaceType != cvf::StructGridInterface::FaceType::NO_FACE)
|
||||
{
|
||||
writeFaultLine(stream, faultName, lastI, lastJ, startK, lastK, lastFaceType);
|
||||
}
|
||||
lastI = i;
|
||||
lastJ = j;
|
||||
lastK = k;
|
||||
lastFaceType = faceType;
|
||||
startK = k;
|
||||
}
|
||||
else
|
||||
{
|
||||
lastK = k;
|
||||
}
|
||||
}
|
||||
// No fault should have no face
|
||||
if (lastFaceType != cvf::StructGridInterface::FaceType::NO_FACE)
|
||||
{
|
||||
writeFaultLine(stream, faultName, lastI, lastJ, startK, lastK, lastFaceType);
|
||||
}
|
||||
stream << "/" << endl;
|
||||
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Read known properties from the input file
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -659,6 +945,54 @@ bool RifEclipseInputFileTools::isValidDataKeyword(const QString& keyword)
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RifEclipseInputFileTools::writeFaultLine(QTextStream& stream,
|
||||
QString faultName,
|
||||
size_t i,
|
||||
size_t j,
|
||||
size_t startK,
|
||||
size_t endK,
|
||||
cvf::StructGridInterface::FaceType faceType)
|
||||
{
|
||||
// Convert indices to eclipse format
|
||||
i++;
|
||||
j++;
|
||||
startK++;
|
||||
endK++;
|
||||
|
||||
stream << "'" << faultName << "'"
|
||||
<< " " << i << " " << i << " " << j << " " << j << " " << startK << " " << endK << " "
|
||||
<< faultFaceText(faceType) << " / ";
|
||||
stream << endl;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RifEclipseInputFileTools::faultFaceText(cvf::StructGridInterface::FaceType faceType)
|
||||
{
|
||||
switch (faceType)
|
||||
{
|
||||
case cvf::StructGridInterface::POS_I:
|
||||
return QString(" I");
|
||||
case cvf::StructGridInterface::NEG_I:
|
||||
return QString("-I");
|
||||
case cvf::StructGridInterface::POS_J:
|
||||
return QString(" J");
|
||||
case cvf::StructGridInterface::NEG_J:
|
||||
return QString("-J");
|
||||
case cvf::StructGridInterface::POS_K:
|
||||
return QString(" K");
|
||||
case cvf::StructGridInterface::NEG_K:
|
||||
return QString("-K");
|
||||
default:
|
||||
CVF_ASSERT(false);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -60,6 +60,25 @@ public:
|
||||
|
||||
static bool openGridFile(const QString& fileName, RigEclipseCaseData* eclipseCase, bool readFaultData);
|
||||
|
||||
static bool exportGrid(const QString& gridFileName,
|
||||
RigEclipseCaseData* eclipseCase,
|
||||
const cvf::Vec3st& min,
|
||||
const cvf::Vec3st& max,
|
||||
const cvf::Vec3st& refinement);
|
||||
|
||||
static bool exportKeywords(const QString& resultFileName,
|
||||
RigEclipseCaseData* eclipseCase,
|
||||
const std::vector<QString>& keywords,
|
||||
const QString& fileWriteMode,
|
||||
const cvf::Vec3st& min,
|
||||
const cvf::Vec3st& max,
|
||||
const cvf::Vec3st& refinement);
|
||||
|
||||
static void saveFault(QString completeFilename,
|
||||
const RigMainGrid* mainGrid,
|
||||
const std::vector<RigFault::FaultFace>& faultFaces,
|
||||
QString faultName);
|
||||
|
||||
// Returns map of assigned resultName and Eclipse Keyword.
|
||||
static std::map<QString, QString> readProperties(const QString& fileName, RigEclipseCaseData* eclipseCase);
|
||||
static bool readProperty (const QString& fileName, RigEclipseCaseData* eclipseCase, const QString& eclipseKeyWord, const QString& resultName );
|
||||
@@ -108,6 +127,16 @@ private:
|
||||
|
||||
static qint64 findKeyword(const QString& keyword, QFile& file, qint64 startPos);
|
||||
static bool isValidDataKeyword(const QString& keyword);
|
||||
|
||||
static void writeFaultLine(QTextStream& stream,
|
||||
QString faultName,
|
||||
size_t i,
|
||||
size_t j,
|
||||
size_t startK,
|
||||
size_t endK,
|
||||
cvf::StructGridInterface::FaceType faceType);
|
||||
|
||||
static QString faultFaceText(cvf::StructGridInterface::FaceType faceType);
|
||||
|
||||
private:
|
||||
static const std::vector<QString>& invalidPropertyDataKeywords();
|
||||
|
||||
@@ -353,203 +353,6 @@ bool RifReaderEclipseOutput::transferGeometry(const ecl_grid_type* mainEclGrid,
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RifReaderEclipseOutput::saveEclipseGrid(const QString& fileName, RigEclipseCaseData* eclipseCase, const cvf::Vec3st& min, const cvf::Vec3st& max, const cvf::Vec3st& refinement)
|
||||
{
|
||||
if (!eclipseCase)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const RigActiveCellInfo* activeCellInfo = eclipseCase->activeCellInfo(RiaDefines::MATRIX_MODEL);
|
||||
const RigActiveCellInfo* fractureActiveCellInfo = eclipseCase->activeCellInfo(RiaDefines::FRACTURE_MODEL);
|
||||
|
||||
CVF_ASSERT(activeCellInfo && fractureActiveCellInfo);
|
||||
|
||||
const RigMainGrid* mainGrid = eclipseCase->mainGrid();
|
||||
|
||||
int ecl_nx = static_cast<int>((max.x() - min.x()) * refinement.x() + 1);
|
||||
int ecl_ny = static_cast<int>((max.y() - min.y()) * refinement.y() + 1);
|
||||
int ecl_nz = static_cast<int>((max.z() - min.z()) * refinement.z() + 1);
|
||||
|
||||
|
||||
size_t cellsPerOriginal = refinement.x() * refinement.y() * refinement.z();
|
||||
|
||||
caf::ProgressInfo progress(mainGrid->cellCount() * 2, "Save Eclipse Grid");
|
||||
int cellProgressInterval = 1000;
|
||||
|
||||
std::vector<float*> ecl_corners; ecl_corners.reserve(mainGrid->cellCount() * cellsPerOriginal);
|
||||
std::vector<int*> ecl_coords; ecl_coords.reserve(mainGrid->cellCount() * cellsPerOriginal);
|
||||
|
||||
int incrementalIndex = 0;
|
||||
for (size_t k = min.z() * refinement.z(); k <= max.z() * refinement.z(); ++k)
|
||||
{
|
||||
size_t mainK = k / refinement.z();
|
||||
size_t k0 = k - min.z() * refinement.z();
|
||||
for (size_t j = min.y() * refinement.y(); j <= max.y() * refinement.y(); ++j)
|
||||
{
|
||||
size_t mainJ = j / refinement.y();
|
||||
size_t j0 = j - min.y() * refinement.y();
|
||||
for (size_t i = min.x() * refinement.x(); i <= max.x() * refinement.x(); ++i)
|
||||
{
|
||||
size_t mainI = i / refinement.x();
|
||||
size_t i0 = i - min.x() * refinement.x();
|
||||
|
||||
size_t mainIndex = mainGrid->cellIndexFromIJK(mainI, mainJ, mainK);
|
||||
|
||||
int active = activeCellInfo->isActive(mainIndex) ? 1 : 0;
|
||||
|
||||
int* ecl_cell_coords = new int[5];
|
||||
ecl_cell_coords[0] = (int)(i0 + 1);
|
||||
ecl_cell_coords[1] = (int)(j0 + 1);
|
||||
ecl_cell_coords[2] = (int)(k0 + 1);
|
||||
ecl_cell_coords[3] = incrementalIndex++;
|
||||
ecl_cell_coords[4] = active;
|
||||
ecl_coords.push_back(ecl_cell_coords);
|
||||
|
||||
std::array<cvf::Vec3d, 8> cellCorners;
|
||||
mainGrid->cellCornerVertices(mainIndex, cellCorners.data());
|
||||
|
||||
auto refinedCoords = RiaCellDividingTools::createHexCornerCoords(
|
||||
cellCorners, refinement.x(), refinement.y(), refinement.z());
|
||||
|
||||
size_t subI = i % refinement.x();
|
||||
size_t subJ = j % refinement.y();
|
||||
size_t subK = k % refinement.z();
|
||||
size_t subIndex = subI + subJ * refinement.x() + subK * refinement.x() * refinement.y();
|
||||
|
||||
float* ecl_cell_corners = new float[24];
|
||||
for (size_t cIdx = 0; cIdx < 8; ++cIdx)
|
||||
{
|
||||
cvf::Vec3d cellCorner = refinedCoords[subIndex * 8 + cIdx];
|
||||
ecl_cell_corners[cellMappingECLRi[cIdx] * 3] = cellCorner[0];
|
||||
ecl_cell_corners[cellMappingECLRi[cIdx] * 3 + 1] = cellCorner[1];
|
||||
ecl_cell_corners[cellMappingECLRi[cIdx] * 3 + 2] = -cellCorner[2];
|
||||
}
|
||||
ecl_corners.push_back(ecl_cell_corners);
|
||||
}
|
||||
}
|
||||
if (incrementalIndex % cellProgressInterval == 0)
|
||||
{
|
||||
progress.setProgress(incrementalIndex);
|
||||
}
|
||||
}
|
||||
|
||||
ecl_grid_type* mainEclGrid = ecl_grid_alloc_GRID_data((int) ecl_coords.size(), ecl_nx, ecl_ny, ecl_nz, 5, &ecl_coords[0], &ecl_corners[0], false, NULL);
|
||||
progress.setProgress(mainGrid->cellCount());
|
||||
|
||||
for (float* floatArray : ecl_corners)
|
||||
{
|
||||
delete floatArray;
|
||||
}
|
||||
|
||||
for (int* intArray : ecl_coords)
|
||||
{
|
||||
delete intArray;
|
||||
}
|
||||
|
||||
FILE* filePtr = RifEclipseOutputFileTools::fopen(fileName, "w");
|
||||
|
||||
if (!filePtr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ecl_grid_fprintf_grdecl(mainEclGrid, filePtr);
|
||||
ecl_grid_free(mainEclGrid);
|
||||
fclose(filePtr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RifReaderEclipseOutput::saveEclipseResults(const QString& resultFileName,
|
||||
RigEclipseCaseData* eclipseCase,
|
||||
const std::vector<QString>& keywords,
|
||||
const QString& fileWriteMode,
|
||||
const cvf::Vec3st& min,
|
||||
const cvf::Vec3st& max,
|
||||
const cvf::Vec3st& refinement)
|
||||
{
|
||||
FILE* filePtr = RifEclipseOutputFileTools::fopen(resultFileName, fileWriteMode);
|
||||
if (!filePtr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
RigCaseCellResultsData* cellResultsData = eclipseCase->results(RiaDefines::MATRIX_MODEL);
|
||||
RigActiveCellInfo* activeCells = cellResultsData->activeCellInfo();
|
||||
RigMainGrid* mainGrid = eclipseCase->mainGrid();
|
||||
|
||||
caf::ProgressInfo progress(keywords.size(), "Saving Keywords");
|
||||
|
||||
for (const QString& keyword : keywords)
|
||||
{
|
||||
std::vector<double> resultValues;
|
||||
|
||||
RigEclipseResultAddress resAddr(RiaDefines::STATIC_NATIVE, keyword);
|
||||
cellResultsData->ensureKnownResultLoaded(resAddr);
|
||||
resultValues = cellResultsData->cellScalarResults(resAddr)[0];
|
||||
CVF_ASSERT(!resultValues.empty());
|
||||
|
||||
std::vector<double> filteredResults;
|
||||
filteredResults.reserve(resultValues.size());
|
||||
|
||||
for (size_t k = min.z() * refinement.z(); k <= max.z() * refinement.z(); ++k)
|
||||
{
|
||||
size_t mainK = k / refinement.z();
|
||||
for (size_t j = min.y() * refinement.y(); j <= max.y() * refinement.y(); ++j)
|
||||
{
|
||||
size_t mainJ = j / refinement.y();
|
||||
for (size_t i = min.x() * refinement.x(); i <= max.x() * refinement.x(); ++i)
|
||||
{
|
||||
size_t mainI = i / refinement.x();
|
||||
|
||||
size_t mainIndex = mainGrid->cellIndexFromIJK(mainI, mainJ, mainK);
|
||||
|
||||
size_t resIndex = activeCells->cellResultIndex(mainIndex);
|
||||
if (resIndex != cvf::UNDEFINED_SIZE_T)
|
||||
{
|
||||
filteredResults.push_back(resultValues[resIndex]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ecl_kw_type* ecl_kw = nullptr;
|
||||
|
||||
if (keyword.endsWith("NUM"))
|
||||
{
|
||||
std::vector<int> resultValuesInt; resultValuesInt.reserve(filteredResults.size());
|
||||
for (double val : filteredResults)
|
||||
{
|
||||
resultValuesInt.push_back(static_cast<int>(val));
|
||||
}
|
||||
ecl_kw = ecl_kw_alloc_new(keyword.toLatin1().data(), (int) resultValuesInt.size(), ECL_INT, resultValuesInt.data());
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<float> resultValuesFloat;
|
||||
resultValuesFloat.reserve(filteredResults.size());
|
||||
for (double val : filteredResults)
|
||||
{
|
||||
resultValuesFloat.push_back(static_cast<float>(val));
|
||||
}
|
||||
ecl_kw = ecl_kw_alloc_new(keyword.toLatin1().data(), (int) resultValuesFloat.size(), ECL_FLOAT, resultValuesFloat.data());
|
||||
}
|
||||
|
||||
ecl_kw_fprintf_grdecl(ecl_kw, filePtr);
|
||||
ecl_kw_free(ecl_kw);
|
||||
progress.incrementProgress();
|
||||
}
|
||||
|
||||
fclose(filePtr);
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Open file and read geometry into given reservoir object
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -794,6 +597,14 @@ void RifReaderEclipseOutput::setFileDataAccess(RifEclipseRestartDataAccess* rest
|
||||
m_dynamicResultsAccess = restartDataAccess;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const size_t* RifReaderEclipseOutput::eclipseCellIndexMapping()
|
||||
{
|
||||
return cellMappingECLRi;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -58,6 +58,8 @@ public:
|
||||
void setHdf5FileName(const QString& fileName);
|
||||
void setFileDataAccess(RifEclipseRestartDataAccess* restartDataAccess);
|
||||
|
||||
static const size_t* eclipseCellIndexMapping();
|
||||
|
||||
virtual bool openAndReadActiveCellData(const QString& fileName, const std::vector<QDateTime>& mainCaseTimeSteps, RigEclipseCaseData* eclipseCase);
|
||||
|
||||
bool staticResult(const QString& result, RiaDefines::PorosityModelType matrixOrFracture, std::vector<double>* values) override;
|
||||
@@ -67,18 +69,11 @@ public:
|
||||
std::vector<QDateTime> allTimeSteps() const;
|
||||
|
||||
static bool transferGeometry(const ecl_grid_type* mainEclGrid, RigEclipseCaseData* eclipseCase);
|
||||
static bool saveEclipseGrid(const QString& gridFileName,
|
||||
RigEclipseCaseData* eclipseCase,
|
||||
const cvf::Vec3st& min,
|
||||
const cvf::Vec3st& max,
|
||||
const cvf::Vec3st& refinement);
|
||||
static bool saveEclipseResults(const QString& resultFileName,
|
||||
RigEclipseCaseData* eclipseCase,
|
||||
const std::vector<QString>& keywords,
|
||||
const QString& fileWriteMode,
|
||||
const cvf::Vec3st& min,
|
||||
const cvf::Vec3st& max,
|
||||
const cvf::Vec3st& refinement);
|
||||
static bool exportGrid(const QString& gridFileName,
|
||||
RigEclipseCaseData* eclipseCase,
|
||||
const cvf::Vec3st& min,
|
||||
const cvf::Vec3st& max,
|
||||
const cvf::Vec3st& refinement);
|
||||
|
||||
static void transferCoarseningInfo(const ecl_grid_type* eclGrid, RigGridBase* grid);
|
||||
|
||||
|
||||
@@ -87,6 +87,39 @@ const std::vector<size_t>& RigFault::connectionIndices() const
|
||||
return m_connectionIndices;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Order FaultCellAndFace by i, j, face then k.
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RigFault::faultOrdering(FaultCellAndFace first, FaultCellAndFace second)
|
||||
{
|
||||
size_t i1, i2, j1, j2, k1, k2;
|
||||
cvf::StructGridInterface::FaceType f1, f2;
|
||||
std::tie(i1, j1, k1, f1) = first;
|
||||
std::tie(i2, j2, k2, f2) = second;
|
||||
if (i1 == i2)
|
||||
{
|
||||
if (j1 == j2)
|
||||
{
|
||||
if (f1 == f2)
|
||||
{
|
||||
return k1 < k2;
|
||||
}
|
||||
else
|
||||
{
|
||||
return f1 < f2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return j1 < j2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return i1 < i2;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -28,8 +28,9 @@
|
||||
|
||||
#include <QString>
|
||||
|
||||
#include <vector>
|
||||
#include <array>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
class RigMainGrid;
|
||||
|
||||
@@ -75,7 +76,8 @@ private:
|
||||
class RigFault : public cvf::Object
|
||||
{
|
||||
public:
|
||||
|
||||
typedef std::tuple<size_t, size_t, size_t, cvf::StructGridInterface::FaceType> FaultCellAndFace;
|
||||
|
||||
struct FaultFace
|
||||
{
|
||||
FaultFace(size_t nativeReservoirCellIndex, cvf::StructGridInterface::FaceType nativeFace, size_t oppositeReservoirCellIndex) :
|
||||
@@ -106,6 +108,8 @@ public:
|
||||
std::vector<size_t>& connectionIndices();
|
||||
const std::vector<size_t>& connectionIndices() const;
|
||||
|
||||
static bool faultOrdering(RigFault::FaultCellAndFace first, RigFault::FaultCellAndFace second);
|
||||
|
||||
private:
|
||||
QString m_name;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user