Refactor grid export and fault export

This commit is contained in:
Gaute Lindkvist
2019-03-19 13:52:48 +01:00
parent 2166d0834e
commit 88d2ad2c35
9 changed files with 426 additions and 365 deletions

View File

@@ -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 "";
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------