#3091 Completion export. Add WELSPECS/WELSPECL to exported file

This commit is contained in:
Bjørn Erik Jensen 2018-08-29 13:36:33 +02:00
parent c4577084dc
commit 6b2359cb39
8 changed files with 444 additions and 57 deletions

View File

@ -128,3 +128,20 @@ QString RiaFilePathTools::commonRootPath(const QStringList& paths)
return paths.front().left(iDir + 1);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::pair<QString, QString> RiaFilePathTools::toFolderAndFileName(const QString& absFileName)
{
auto absFN = toInternalSeparator(absFileName);
int lastSep = absFN.lastIndexOf(SEPARATOR);
if (lastSep > 0)
{
return std::make_pair(absFN.left(lastSep), absFN.mid(lastSep+1));
}
else
{
return std::make_pair("", absFN);
}
}

View File

@ -40,4 +40,5 @@ public:
static bool equalPaths(const QString& path1, const QString& path2);
static QString canonicalPath(const QString& path);
static QString commonRootPath(const QStringList& paths);
static std::pair<QString, QString> toFolderAndFileName(const QString& absFileName);
};

View File

@ -21,6 +21,7 @@
#include "RiaApplication.h"
#include "RiaLogging.h"
#include "RiaPreferences.h"
#include "RiaFilePathTools.h"
#include "RicExportCompletionDataSettingsUi.h"
#include "RicExportFeatureImpl.h"
@ -40,7 +41,8 @@
#include "RigWellLogExtractor.h"
#include "RigWellPath.h"
#include "RigWellPathIntersectionTools.h"
#include "RimFileWellPath.h"
#include "RimFishbonesCollection.h"
#include "RimFishbonesMultipleSubs.h"
#include "RimFractureTemplate.h"
@ -52,6 +54,7 @@
#include "RimWellPathCompletions.h"
#include "RimWellPathFracture.h"
#include "RimWellPathFractureCollection.h"
#include "RimProject.h"
#include "RiuMainWindow.h"
@ -65,6 +68,21 @@
#include "RigVirtualPerforationTransmissibilities.h"
#include <QDir>
//--------------------------------------------------------------------------------------------------
/// Internal functions
//--------------------------------------------------------------------------------------------------
const RimWellPath* findWellPathFromExportName(const QString& wellNameForExport);
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
class OpenFileException
{
public:
OpenFileException(const QString &message) : message(message) {}
QString message;
};
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -895,6 +913,214 @@ RigCompletionData
return resultCompletion;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QFilePtr RicWellPathExportCompletionDataFeatureImpl::openFileForExport(const QString& fullFileName)
{
std::pair<QString, QString> folderAndFileName = RiaFilePathTools::toFolderAndFileName(fullFileName);
return openFileForExport(folderAndFileName.first, folderAndFileName.second);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QFilePtr RicWellPathExportCompletionDataFeatureImpl::openFileForExport(const QString& folderName, const QString& fileName)
{
QDir exportFolder = QDir(folderName);
if (!exportFolder.exists())
{
bool createdPath = exportFolder.mkpath(".");
if (createdPath)
RiaLogging::info("Created export folder " + folderName);
else
{
auto errorMessage = QString("Selected output folder does not exist, and could not be created.");
RiaLogging::error(errorMessage);
throw OpenFileException(errorMessage);
}
}
QString filePath = exportFolder.filePath(fileName);
QFilePtr exportFile(new QFile(filePath));
if (!exportFile->open(QIODevice::WriteOnly))
{
auto errorMessage = QString("Export Completions Data: Could not open the file: %1").arg(filePath);
RiaLogging::error(errorMessage);
throw OpenFileException(errorMessage);
}
return exportFile;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RigCompletionData>
RicWellPathExportCompletionDataFeatureImpl::mainGridCompletions(std::vector<RigCompletionData>& allCompletions)
{
std::vector<RigCompletionData> completions;
for (const auto& completion : allCompletions)
{
QString gridName = completion.completionDataGridCell().lgrName();
if (gridName.isEmpty())
{
completions.push_back(completion);
}
}
return completions;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::map<QString, std::vector<RigCompletionData>>
RicWellPathExportCompletionDataFeatureImpl::subGridsCompletions(std::vector<RigCompletionData>& allCompletions)
{
std::map<QString, std::vector<RigCompletionData>> completions;
for (const auto& completion : allCompletions)
{
QString gridName = completion.completionDataGridCell().lgrName();
if (!gridName.isEmpty())
{
auto it = completions.find(gridName);
if (it == completions.end())
{
completions.insert(
std::pair<QString, std::vector<RigCompletionData>>(gridName, {completion}));
}
else
{
it->second.push_back(completion);
}
}
}
return completions;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicWellPathExportCompletionDataFeatureImpl::exportWelspecsToFile(RimEclipseCase* gridCase,
QFilePtr exportFile,
const std::vector<RigCompletionData>& completions)
{
QTextStream stream(exportFile.get());
RifEclipseDataTableFormatter formatter(stream);
formatter.setColumnSpacing(3);
std::vector<RifEclipseOutputTableColumn> header = {
RifEclipseOutputTableColumn("Well"),
RifEclipseOutputTableColumn("Grp"),
RifEclipseOutputTableColumn("I"),
RifEclipseOutputTableColumn("J"),
RifEclipseOutputTableColumn("RefDpth"),
RifEclipseOutputTableColumn("WellType")
};
formatter.keyword("WELSPEC");
formatter.header(header);
std::set<const RimWellPath*> wellPathSet;
// Build list of unique RimWellPath
for (const auto completion : completions)
{
const auto wellPath = findWellPathFromExportName(completion.wellName());
if (wellPath)
{
wellPathSet.insert(wellPath);
}
}
// Export
for (const auto wellPath : wellPathSet)
{
auto completions = wellPath->completions();
cvf::Vec2i ijIntersection = wellPathUpperGridIntersectionIJ(gridCase, wellPath);
formatter
.add(completions->wellNameForExport())
.add(completions->wellGroupName())
.addOneBasedCellIndex(ijIntersection.x())
.addOneBasedCellIndex(ijIntersection.y())
.add(completions->referenceDepth())
.add(completions->wellTypeName())
.rowCompleted();
}
formatter.tableCompleted();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicWellPathExportCompletionDataFeatureImpl::exportWelspeclToFile(RimEclipseCase* gridCase,
QFilePtr exportFile,
const std::map<QString, std::vector<RigCompletionData>>& completions)
{
QTextStream stream(exportFile.get());
RifEclipseDataTableFormatter formatter(stream);
formatter.setColumnSpacing(3);
std::vector<RifEclipseOutputTableColumn> header = {
RifEclipseOutputTableColumn("Well"),
RifEclipseOutputTableColumn("Grp"),
RifEclipseOutputTableColumn("LGR"),
RifEclipseOutputTableColumn("I"),
RifEclipseOutputTableColumn("J"),
RifEclipseOutputTableColumn("RefDpth"),
RifEclipseOutputTableColumn("WellType")
};
formatter.keyword("WELSPECL");
formatter.header(header);
std::map<QString, std::set<const RimWellPath*>> wellPathMap;
// Build list of unique RimWellPath for each LGR
for (const auto completionsForLgr : completions)
{
wellPathMap.insert(std::make_pair(completionsForLgr.first, std::set<const RimWellPath*>()));
for (const auto completion : completionsForLgr.second)
{
const auto wellPath = findWellPathFromExportName(completion.wellName());
if (wellPath)
{
wellPathMap[completionsForLgr.first].insert(wellPath);
}
}
}
for (const auto wellPathsForLgr : wellPathMap)
{
QString lgrName = wellPathsForLgr.first;
// Export
for (const auto wellPath : wellPathsForLgr.second)
{
auto completions = wellPath->completions();
cvf::Vec2i ijIntersection = wellPathUpperGridIntersectionIJ(gridCase, wellPath, lgrName);
formatter
.add(completions->wellNameForExport())
.add(completions->wellGroupName())
.add(lgrName)
.addOneBasedCellIndex(ijIntersection.x())
.addOneBasedCellIndex(ijIntersection.y())
.add(completions->referenceDepth())
.add(completions->wellTypeName())
.rowCompleted();
}
}
formatter.tableCompleted();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -907,46 +1133,41 @@ void RicWellPathExportCompletionDataFeatureImpl::sortAndExportCompletionsToFile(
RicExportCompletionDataSettingsUi::CompdatExportType exportType)
{
// Sort completions based on grid they belong to
std::vector<RigCompletionData> completionsForMainGrid;
std::map<QString, std::vector<RigCompletionData>> completionsForSubGrids;
for (const auto& completion : completions)
{
QString gridName = completion.completionDataGridCell().lgrName();
if (gridName.isEmpty())
{
completionsForMainGrid.push_back(completion);
}
else
{
auto it = completionsForSubGrids.find(gridName);
if (it == completionsForSubGrids.end())
{
completionsForSubGrids.insert(
std::pair<QString, std::vector<RigCompletionData>>(gridName, std::vector<RigCompletionData>{completion}));
}
else
{
it->second.push_back(completion);
}
}
}
std::vector<RigCompletionData> completionsForMainGrid = mainGridCompletions(completions);
std::map<QString, std::vector<RigCompletionData>> completionsForSubGrids = subGridsCompletions(completions);
if (!completionsForMainGrid.empty())
{
std::map<QString, std::vector<RigCompletionData>> completionsForGrid;
completionsForGrid.insert(std::pair<QString, std::vector<RigCompletionData>>("", completionsForMainGrid));
try
{
QFilePtr exportFile = openFileForExport(folderName, fileName);
exportCompdatAndWpimultTables(
eclipseCase, folderName, fileName, completionsForGrid, wellPathFractureReportItems, exportType);
std::map<QString, std::vector<RigCompletionData>> completionsForGrid;
completionsForGrid.insert(std::pair<QString, std::vector<RigCompletionData>>("", completionsForMainGrid));
exportWelspecsToFile(eclipseCase, exportFile, completionsForMainGrid);
exportCompdatAndWpimultTables(
eclipseCase, exportFile, completionsForGrid, wellPathFractureReportItems, exportType);
}
catch(OpenFileException)
{ }
}
if (!completionsForSubGrids.empty())
{
QString lgrFileName = fileName + "_LGR";
exportCompdatAndWpimultTables(
eclipseCase, folderName, lgrFileName, completionsForSubGrids, wellPathFractureReportItems, exportType);
try
{
QString lgrFileName = fileName + "_LGR";
QFilePtr exportFile = openFileForExport(folderName, lgrFileName);
exportWelspeclToFile(eclipseCase, exportFile, completionsForSubGrids);
exportCompdatAndWpimultTables(
eclipseCase, exportFile, completionsForSubGrids, wellPathFractureReportItems, exportType);
}
catch(OpenFileException)
{ }
}
}
@ -955,33 +1176,14 @@ void RicWellPathExportCompletionDataFeatureImpl::sortAndExportCompletionsToFile(
//--------------------------------------------------------------------------------------------------
void RicWellPathExportCompletionDataFeatureImpl::exportCompdatAndWpimultTables(
RimEclipseCase* sourceCase,
const QString& folderName,
const QString& fileName,
QFilePtr exportFile,
const std::map<QString, std::vector<RigCompletionData>>& completionsPerGrid,
const std::vector<RicWellPathFractureReportItem>& wellPathFractureReportItems,
RicExportCompletionDataSettingsUi::CompdatExportType exportType)
{
if (completionsPerGrid.empty()) return;
QDir exportFolder(folderName);
if (!exportFolder.exists())
{
bool createdPath = exportFolder.mkpath(".");
if (createdPath)
RiaLogging::info("Created export folder " + folderName);
else
RiaLogging::error("Selected output folder does not exist, and could not be created.");
}
QString filePath = exportFolder.filePath(fileName);
QFile exportFile(filePath);
if (!exportFile.open(QIODevice::WriteOnly))
{
RiaLogging::error(QString("Export Completions Data: Could not open the file: %1").arg(filePath));
return;
}
QTextStream stream(&exportFile);
QTextStream stream(exportFile.get());
if (!wellPathFractureReportItems.empty())
{
@ -1032,7 +1234,7 @@ void RicWellPathExportCompletionDataFeatureImpl::exportCompdatAndWpimultTables(
}
}
RiaLogging::info(QString("Successfully exported completion data to %1").arg(filePath));
RiaLogging::info(QString("Successfully exported completion data to %1").arg(exportFile->fileName()));
}
//--------------------------------------------------------------------------------------------------
@ -1904,3 +2106,61 @@ double RicWellPathExportCompletionDataFeatureImpl::calculateTransmissibilityAsEc
return trans;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::Vec2i RicWellPathExportCompletionDataFeatureImpl::wellPathUpperGridIntersectionIJ(const RimEclipseCase* gridCase,
const RimWellPath* wellPath,
const QString& gridName)
{
const RigEclipseCaseData* caseData = gridCase->eclipseCaseData();
const RigMainGrid* mainGrid = caseData->mainGrid();
const RigActiveCellInfo* activeCellInfo = caseData->activeCellInfo(RiaDefines::MATRIX_MODEL);
const RigWellPath* wellPathGeometry = wellPath->wellPathGeometry();
const std::vector<cvf::Vec3d>& coords = wellPathGeometry->wellPathPoints();
const std::vector<double>& mds = wellPathGeometry->measureDepths();
CVF_ASSERT(!coords.empty() && !mds.empty());
std::vector<WellPathCellIntersectionInfo> intersections =
RigWellPathIntersectionTools::findCellIntersectionInfosAlongPath(caseData, coords, mds);
size_t gridId = 0;
if (!gridName.isEmpty())
{
const auto grid = caseData->grid(gridName);
if (grid) gridId = grid->gridId();
}
for (WellPathCellIntersectionInfo intersection : intersections)
{
size_t gridLocalCellIndex = 0;
const RigGridBase* grid = mainGrid->gridAndGridLocalIdxFromGlobalCellIdx(intersection.globCellIndex, &gridLocalCellIndex);
if (grid->gridId() == gridId && activeCellInfo->isActive(intersection.globCellIndex))
{
size_t i, j, k;
if (grid->ijkFromCellIndex(gridLocalCellIndex, &i, &j, &k))
{
return cvf::Vec2i((int)i, (int)j);
}
}
}
return cvf::Vec2i();
}
//--------------------------------------------------------------------------------------------------
/// Internal function
//--------------------------------------------------------------------------------------------------
const RimWellPath* findWellPathFromExportName(const QString& wellNameForExport)
{
auto allWellPaths = RiaApplication::instance()->project()->allWellPaths();
for (const auto wellPath : allWellPaths)
{
if (wellPath->completions()->wellNameForExport() == wellNameForExport) return wellPath;
}
return nullptr;
}

View File

@ -24,10 +24,13 @@
#include "RicMultiSegmentWellExportInfo.h"
#include "RicWellPathFractureReportItem.h"
#include <QFile>
#include "cvfBase.h"
#include "cvfVector3.h"
#include <vector>
#include <memory>
class RigCell;
class RigEclipseCaseData;
@ -40,6 +43,11 @@ class RimWellPathFracture;
class RifEclipseDataTableFormatter;
class RigVirtualPerforationTransmissibilities;
//==================================================================================================
///
//==================================================================================================
typedef std::shared_ptr<QFile> QFilePtr;
//==================================================================================================
///
//==================================================================================================
@ -118,6 +126,23 @@ private:
static RigCompletionData combineEclipseCellCompletions(const std::vector<RigCompletionData>& completions,
const RicExportCompletionDataSettingsUi& settings);
static QFilePtr openFileForExport(const QString& fullFileName);
static QFilePtr openFileForExport(const QString& folderName,
const QString& fileName);
static std::vector<RigCompletionData> mainGridCompletions(std::vector<RigCompletionData>& allCompletions);
static std::map<QString, std::vector<RigCompletionData>> subGridsCompletions(std::vector<RigCompletionData>& allCompletions);
static void exportWelspecsToFile(RimEclipseCase* gridCase,
QFilePtr exportFile,
const std::vector<RigCompletionData>& completions);
static void exportWelspeclToFile(RimEclipseCase* gridCase,
QFilePtr exportFile,
const std::map<QString, std::vector<RigCompletionData>>& completions);
static void sortAndExportCompletionsToFile(RimEclipseCase* eclipseCase,
const QString& exportFolder,
const QString& fileName,
@ -126,8 +151,9 @@ private:
RicExportCompletionDataSettingsUi::CompdatExportType exportType);
static void exportCompdatAndWpimultTables(RimEclipseCase* sourceCase,
const QString& folderName,
const QString& fileName,
QFilePtr exportFile,
//const QString& folderName,
//const QString& fileName,
const std::map<QString, std::vector<RigCompletionData>>& completionsPerGrid,
const std::vector<RicWellPathFractureReportItem>& wellPathFractureReportItems,
RicExportCompletionDataSettingsUi::CompdatExportType exportType);
@ -163,4 +189,6 @@ private:
static void appendCompletionData(std::map<RigCompletionDataGridCell, std::vector<RigCompletionData>>* completionData,
const std::vector<RigCompletionData>& data);
static cvf::Vec2i wellPathUpperGridIntersectionIJ(const RimEclipseCase* gridCase, const RimWellPath* wellPath, const QString& gridName = "");
};

View File

@ -28,6 +28,21 @@
#include "cafPdmUiTreeOrdering.h"
namespace caf {
template<>
void RimWellPathCompletions::WellTypeEnum::setUp()
{
addItem(RimWellPathCompletions::OIL, "OIL", "Oil");
addItem(RimWellPathCompletions::GAS, "GAS", "Gas");
addItem(RimWellPathCompletions::WATER, "WATER", "Water");
addItem(RimWellPathCompletions::LIQUID, "LIQUID", "Liquid");
setDefault(RimWellPathCompletions::OIL);
}
}
CAF_PDM_SOURCE_INIT(RimWellPathCompletions, "WellPathCompletions");
//--------------------------------------------------------------------------------------------------
@ -50,6 +65,12 @@ RimWellPathCompletions::RimWellPathCompletions()
m_fractureCollection.uiCapability()->setUiHidden(true);
CAF_PDM_InitField(&m_wellNameForExport, "WellNameForExport", QString(), "Well Name for Completion Export", "", "", "");
CAF_PDM_InitField(&m_wellGroupName, "WellGroupNameForExport", QString(), "Well Group Name for Completion Export", "", "", "");
CAF_PDM_InitField(&m_referenceDepth, "ReferenceDepthForExport", QString(), "Reference Depth for Completion Export", "", "", "");
CAF_PDM_InitField(&m_wellType, "WellTypeForExport", WellTypeEnum(), "Well Type for Completion Export", "", "", "");
}
//--------------------------------------------------------------------------------------------------
@ -88,6 +109,30 @@ QString RimWellPathCompletions::wellNameForExport() const
return m_wellNameForExport();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimWellPathCompletions::wellGroupName() const
{
return m_wellGroupName;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimWellPathCompletions::referenceDepth() const
{
return m_referenceDepth;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimWellPathCompletions::wellTypeName() const
{
return WellTypeEnum(m_wellType).uiText();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -26,6 +26,7 @@ class RimFishbonesCollection;
class RimPerforationCollection;
class RimWellPathFractureCollection;
//==================================================================================================
///
///
@ -34,6 +35,9 @@ class RimWellPathCompletions : public caf::PdmObject
{
CAF_PDM_HEADER_INIT;
enum WellType {OIL, GAS, WATER, LIQUID};
typedef caf::AppEnum<WellType> WellTypeEnum;
public:
RimWellPathCompletions();
@ -43,6 +47,9 @@ public:
void setWellNameForExport(const QString& name);
QString wellNameForExport() const;
QString wellGroupName() const;
QString referenceDepth() const;
QString wellTypeName() const;
bool hasCompletions() const;
void setUnitSystemSpecificDefaults();
@ -56,4 +63,8 @@ private:
caf::PdmChildField<RimWellPathFractureCollection*> m_fractureCollection;
caf::PdmField<QString> m_wellNameForExport;
caf::PdmField<QString> m_wellGroupName;
caf::PdmField<QString> m_referenceDepth;
caf::PdmField<WellTypeEnum> m_wellType;
};

View File

@ -151,6 +151,30 @@ RigGridBase* RigEclipseCaseData::grid(size_t index)
return m_mainGrid->gridByIndex(index);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const RigGridBase* RigEclipseCaseData::grid(const QString& gridName) const
{
if (m_mainGrid.isNull())
{
return nullptr;
}
if (gridName.isEmpty())
{
return m_mainGrid.p();
}
size_t i;
for (i = 0; i < m_mainGrid->gridCount(); i++)
{
const RigGridBase* grid = m_mainGrid->gridByIndex(i);
if (QString::fromStdString(grid->gridName()) == gridName) return grid;
}
return nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -71,6 +71,7 @@ public:
const RigGridBase* grid(size_t index) const;
RigGridBase* grid(size_t index);
size_t gridCount() const;
const RigGridBase* grid(const QString& gridName) const;
RigCaseCellResultsData* results(RiaDefines::PorosityModelType porosityModel);
const RigCaseCellResultsData* results(RiaDefines::PorosityModelType porosityModel) const;