mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
#1519 Export COMPDAT for all perforation intervals
This commit is contained in:
@@ -7,6 +7,7 @@ endif()
|
|||||||
set (SOURCE_GROUP_HEADER_FILES
|
set (SOURCE_GROUP_HEADER_FILES
|
||||||
${CEE_CURRENT_LIST_DIR}RicWellPathDeleteFeature.h
|
${CEE_CURRENT_LIST_DIR}RicWellPathDeleteFeature.h
|
||||||
${CEE_CURRENT_LIST_DIR}RicWellPathExportCompletionDataFeature.h
|
${CEE_CURRENT_LIST_DIR}RicWellPathExportCompletionDataFeature.h
|
||||||
|
${CEE_CURRENT_LIST_DIR}RicWellPathExportPerforationCompdatFeature.h
|
||||||
${CEE_CURRENT_LIST_DIR}RicWellPathImportCompletionsFileFeature.h
|
${CEE_CURRENT_LIST_DIR}RicWellPathImportCompletionsFileFeature.h
|
||||||
${CEE_CURRENT_LIST_DIR}RicWellPathsImportFileFeature.h
|
${CEE_CURRENT_LIST_DIR}RicWellPathsImportFileFeature.h
|
||||||
${CEE_CURRENT_LIST_DIR}RicWellPathsImportSsihubFeature.h
|
${CEE_CURRENT_LIST_DIR}RicWellPathsImportSsihubFeature.h
|
||||||
@@ -16,6 +17,7 @@ ${CEE_CURRENT_LIST_DIR}RicWellPathViewerEventHandler.h
|
|||||||
set (SOURCE_GROUP_SOURCE_FILES
|
set (SOURCE_GROUP_SOURCE_FILES
|
||||||
${CEE_CURRENT_LIST_DIR}RicWellPathDeleteFeature.cpp
|
${CEE_CURRENT_LIST_DIR}RicWellPathDeleteFeature.cpp
|
||||||
${CEE_CURRENT_LIST_DIR}RicWellPathExportCompletionDataFeature.cpp
|
${CEE_CURRENT_LIST_DIR}RicWellPathExportCompletionDataFeature.cpp
|
||||||
|
${CEE_CURRENT_LIST_DIR}RicWellPathExportPerforationCompdatFeature.cpp
|
||||||
${CEE_CURRENT_LIST_DIR}RicWellPathImportCompletionsFileFeature.cpp
|
${CEE_CURRENT_LIST_DIR}RicWellPathImportCompletionsFileFeature.cpp
|
||||||
${CEE_CURRENT_LIST_DIR}RicWellPathsImportFileFeature.cpp
|
${CEE_CURRENT_LIST_DIR}RicWellPathsImportFileFeature.cpp
|
||||||
${CEE_CURRENT_LIST_DIR}RicWellPathsImportSsihubFeature.cpp
|
${CEE_CURRENT_LIST_DIR}RicWellPathsImportSsihubFeature.cpp
|
||||||
|
|||||||
@@ -0,0 +1,201 @@
|
|||||||
|
/////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Copyright (C) 2017 Statoil ASA
|
||||||
|
//
|
||||||
|
// 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 "RicWellPathExportPerforationCompdatFeature.h"
|
||||||
|
|
||||||
|
#include "RiaApplication.h"
|
||||||
|
#include "RiaLogging.h"
|
||||||
|
|
||||||
|
#include "RimProject.h"
|
||||||
|
#include "RimWellPath.h"
|
||||||
|
#include "RimPerforationCollection.h"
|
||||||
|
#include "RimPerforationInterval.h"
|
||||||
|
|
||||||
|
#include "RiuMainWindow.h"
|
||||||
|
|
||||||
|
#include "RigWellLogExtractionTools.h"
|
||||||
|
#include "RigEclipseCaseData.h"
|
||||||
|
#include "RigMainGrid.h"
|
||||||
|
#include "RigWellPath.h"
|
||||||
|
#include "RigWellPathIntersectionTools.h"
|
||||||
|
|
||||||
|
#include "cafSelectionManager.h"
|
||||||
|
#include "cafPdmUiPropertyViewDialog.h"
|
||||||
|
|
||||||
|
#include "cvfPlane.h"
|
||||||
|
|
||||||
|
#include <QAction>
|
||||||
|
#include <QFileDialog>
|
||||||
|
#include <QMessageBox>
|
||||||
|
|
||||||
|
CAF_CMD_SOURCE_INIT(RicWellPathExportPerforationCompdatFeature, "RicWellPathExportPerforationCompdatFeature");
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
bool RicWellPathExportPerforationCompdatFeature::isCommandEnabled()
|
||||||
|
{
|
||||||
|
std::vector<RimWellPath*> objects;
|
||||||
|
caf::SelectionManager::instance()->objectsByType(&objects);
|
||||||
|
|
||||||
|
if (objects.size() == 1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
void RicWellPathExportPerforationCompdatFeature::onActionTriggered(bool isChecked)
|
||||||
|
{
|
||||||
|
std::vector<RimWellPath*> objects;
|
||||||
|
caf::SelectionManager::instance()->objectsByType(&objects);
|
||||||
|
|
||||||
|
CVF_ASSERT(objects.size() == 1);
|
||||||
|
|
||||||
|
RiaApplication* app = RiaApplication::instance();
|
||||||
|
|
||||||
|
QString projectFolder = app->currentProjectPath();
|
||||||
|
QString defaultDir = RiaApplication::instance()->lastUsedDialogDirectoryWithFallback("COMPLETIONS", projectFolder);
|
||||||
|
|
||||||
|
RimCaseAndFileExportSettings exportSettings;
|
||||||
|
std::vector<RimCase*> cases;
|
||||||
|
app->project()->allCases(cases);
|
||||||
|
for (auto c : cases)
|
||||||
|
{
|
||||||
|
RimEclipseCase* eclipseCase = dynamic_cast<RimEclipseCase*>(c);
|
||||||
|
if (eclipseCase != nullptr)
|
||||||
|
{
|
||||||
|
exportSettings.caseToApply = eclipseCase;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exportSettings.fileName = QDir(defaultDir).filePath("Perforations");
|
||||||
|
|
||||||
|
caf::PdmUiPropertyViewDialog propertyDialog(RiuMainWindow::instance(), &exportSettings, "Export Completion Data", "");
|
||||||
|
if (propertyDialog.exec() == QDialog::Accepted)
|
||||||
|
{
|
||||||
|
RiaApplication::instance()->setLastUsedDialogDirectory("COMPLETIONS", QFileInfo(exportSettings.fileName).absolutePath());
|
||||||
|
|
||||||
|
exportCompdat(objects[0], exportSettings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
void RicWellPathExportPerforationCompdatFeature::setupActionLook(QAction* actionToSetup)
|
||||||
|
{
|
||||||
|
actionToSetup->setText("Export Perforation Completion Data");
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
void RicWellPathExportPerforationCompdatFeature::exportCompdat(RimWellPath* wellPath, const RimCaseAndFileExportSettings& exportSettings)
|
||||||
|
{
|
||||||
|
QFile exportFile(exportSettings.fileName());
|
||||||
|
|
||||||
|
if (exportSettings.caseToApply() == nullptr)
|
||||||
|
{
|
||||||
|
RiaLogging::error("Export Completions Data: Cannot export completions data without specified eclipse case");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!exportFile.open(QIODevice::WriteOnly))
|
||||||
|
{
|
||||||
|
RiaLogging::error(QString("Export Completions Data: Could not open the file: %1").arg(exportSettings.fileName()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate data
|
||||||
|
const RigEclipseCaseData* caseData = exportSettings.caseToApply()->eclipseCaseData();
|
||||||
|
const RigMainGrid* grid = caseData->mainGrid();
|
||||||
|
|
||||||
|
|
||||||
|
QTextStream stream(&exportFile);
|
||||||
|
RifEclipseOutputTableFormatter formatter(stream);
|
||||||
|
|
||||||
|
std::vector<RifEclipseOutputTableColumn> header = {
|
||||||
|
RifEclipseOutputTableColumn("Well"),
|
||||||
|
RifEclipseOutputTableColumn("I"),
|
||||||
|
RifEclipseOutputTableColumn("J"),
|
||||||
|
RifEclipseOutputTableColumn("K1"),
|
||||||
|
RifEclipseOutputTableColumn("K2"),
|
||||||
|
RifEclipseOutputTableColumn("Status"),
|
||||||
|
RifEclipseOutputTableColumn("SAT"),
|
||||||
|
RifEclipseOutputTableColumn("TR"),
|
||||||
|
RifEclipseOutputTableColumn("DIAM"),
|
||||||
|
RifEclipseOutputTableColumn("KH"),
|
||||||
|
RifEclipseOutputTableColumn("S"),
|
||||||
|
RifEclipseOutputTableColumn("Df"),
|
||||||
|
RifEclipseOutputTableColumn("DIR"),
|
||||||
|
RifEclipseOutputTableColumn("r0")
|
||||||
|
};
|
||||||
|
|
||||||
|
formatter.keyword("COMPDAT");
|
||||||
|
formatter.header(header);
|
||||||
|
|
||||||
|
for (const RimPerforationInterval* interval : wellPath->perforationIntervalCollection()->m_perforations())
|
||||||
|
{
|
||||||
|
generateCompdatForPerforation(formatter, caseData, wellPath, interval);
|
||||||
|
}
|
||||||
|
|
||||||
|
formatter.tableCompleted();
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
void RicWellPathExportPerforationCompdatFeature::generateCompdatForPerforation(RifEclipseOutputTableFormatter& formatter, const RigEclipseCaseData* caseData, RimWellPath* wellPath, const RimPerforationInterval* interval)
|
||||||
|
{
|
||||||
|
std::vector<cvf::Vec3d> perforationPoints = wellPath->wellPathGeometry()->clippedPointSubset(interval->startMD(), interval->endMD());
|
||||||
|
std::vector<WellPathCellIntersectionInfo> intersectedCells = RigWellPathIntersectionTools::findCellsIntersectedByPath(caseData, perforationPoints);
|
||||||
|
|
||||||
|
formatter.comment(QString("Perforation interval from %1 to %2").arg(interval->startMD()).arg(interval->endMD()));
|
||||||
|
for (auto& cell : intersectedCells)
|
||||||
|
{
|
||||||
|
size_t i, j, k;
|
||||||
|
caseData->mainGrid()->ijkFromCellIndex(cell.cellIndex, &i, &j, &k);
|
||||||
|
formatter.add(wellPath->name());
|
||||||
|
formatter.addZeroBasedCellIndex(i).addZeroBasedCellIndex(j).addZeroBasedCellIndex(k).addZeroBasedCellIndex(k);
|
||||||
|
formatter.add("'OPEN'").add("1*").add("1*");
|
||||||
|
formatter.add(interval->radius());
|
||||||
|
formatter.add("1*").add("1*").add("1*");
|
||||||
|
switch (cell.direction)
|
||||||
|
{
|
||||||
|
case POS_I:
|
||||||
|
case NEG_I:
|
||||||
|
formatter.add("'X'");
|
||||||
|
break;
|
||||||
|
case POS_J:
|
||||||
|
case NEG_J:
|
||||||
|
formatter.add("'Y'");
|
||||||
|
break;
|
||||||
|
case POS_K:
|
||||||
|
case NEG_K:
|
||||||
|
formatter.add("'Z'");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
formatter.add("1*");
|
||||||
|
formatter.rowCompleted();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
/////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Copyright (C) 2017 Statoil ASA
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "RimCaseAndFileExportSettings.h"
|
||||||
|
|
||||||
|
#include "RifEclipseOutputTableFormatter.h"
|
||||||
|
|
||||||
|
#include "cafCmdFeature.h"
|
||||||
|
|
||||||
|
class RimPerforationInterval;
|
||||||
|
class RimWellPath;
|
||||||
|
|
||||||
|
class RigEclipseCaseData;
|
||||||
|
|
||||||
|
//==================================================================================================
|
||||||
|
///
|
||||||
|
//==================================================================================================
|
||||||
|
class RicWellPathExportPerforationCompdatFeature : public caf::CmdFeature
|
||||||
|
{
|
||||||
|
CAF_CMD_HEADER_INIT;
|
||||||
|
protected:
|
||||||
|
|
||||||
|
// Overrides
|
||||||
|
virtual bool isCommandEnabled() override;
|
||||||
|
virtual void onActionTriggered(bool isChecked) override;
|
||||||
|
virtual void setupActionLook(QAction* actionToSetup) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void exportCompdat(RimWellPath* wellPath, const RimCaseAndFileExportSettings& exportSettings);
|
||||||
|
static void generateCompdatForPerforation(RifEclipseOutputTableFormatter& formatter, const RigEclipseCaseData* caseData, RimWellPath* wellPath, const RimPerforationInterval* interval);
|
||||||
|
};
|
||||||
@@ -401,6 +401,7 @@ QStringList RimContextCommandBuilder::commandsFromSelection()
|
|||||||
commandIds << "RicExportFishbonesLateralsFeature";
|
commandIds << "RicExportFishbonesLateralsFeature";
|
||||||
commandIds << "RicWellPathExportCompletionDataFeature";
|
commandIds << "RicWellPathExportCompletionDataFeature";
|
||||||
commandIds << "RicWellPathImportCompletionsFileFeature";
|
commandIds << "RicWellPathImportCompletionsFileFeature";
|
||||||
|
commandIds << "RicWellPathExportPerforationCompdatFeature";
|
||||||
commandIds << "RicFlyToObjectFeature";
|
commandIds << "RicFlyToObjectFeature";
|
||||||
|
|
||||||
// Work in progress -- End
|
// Work in progress -- End
|
||||||
|
|||||||
@@ -38,8 +38,10 @@ public:
|
|||||||
virtual ~RimPerforationInterval();
|
virtual ~RimPerforationInterval();
|
||||||
|
|
||||||
void setStartAndEndMD(double startMD, double endMD);
|
void setStartAndEndMD(double startMD, double endMD);
|
||||||
double startMD() { return m_startMD(); }
|
double startMD() const { return m_startMD(); }
|
||||||
double endMD() { return m_endMD(); }
|
double endMD() const { return m_endMD(); }
|
||||||
|
double radius() const { return m_radius(); }
|
||||||
|
double skinFactor() const { return m_skinFactor(); }
|
||||||
|
|
||||||
virtual cvf::BoundingBox boundingBoxInDomainCoords() override;
|
virtual cvf::BoundingBox boundingBoxInDomainCoords() override;
|
||||||
|
|
||||||
|
|||||||
@@ -157,3 +157,42 @@ void RigWellPath::twoClosestPoints(const cvf::Vec3d& position, cvf::Vec3d* p1, c
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
std::vector<cvf::Vec3d> RigWellPath::clippedPointSubset(double startMD, double endMD) const
|
||||||
|
{
|
||||||
|
std::vector<cvf::Vec3d> points;
|
||||||
|
if (m_measuredDepths.empty()) return points;
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
// Skip points below startMD
|
||||||
|
while (i < m_measuredDepths.size() && m_measuredDepths[i] < startMD) ++i;
|
||||||
|
|
||||||
|
if (i == 0)
|
||||||
|
{
|
||||||
|
// If startMD is at or below the starting MD, use that point
|
||||||
|
points.push_back(m_wellPathPoints[0]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
double stepsize = (startMD - m_measuredDepths[i - 1]) / (m_measuredDepths[i] - m_measuredDepths[i - 1]);
|
||||||
|
points.push_back(m_wellPathPoints[i - 1] + stepsize * (m_wellPathPoints[i] - m_wellPathPoints[i - 1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
while (i < m_measuredDepths.size() && m_measuredDepths[i] < endMD)
|
||||||
|
{
|
||||||
|
// Add all points between startMD and endMD
|
||||||
|
points.push_back(m_wellPathPoints[i]);
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i < m_measuredDepths.size() && m_measuredDepths[i] > endMD)
|
||||||
|
{
|
||||||
|
double stepsize = (endMD - m_measuredDepths[i - 1]) / (m_measuredDepths[i] - m_measuredDepths[i - 1]);
|
||||||
|
points.push_back(m_wellPathPoints[i - 1] + stepsize * (m_wellPathPoints[i] - m_wellPathPoints[i - 1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
return points;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ public:
|
|||||||
cvf::Vec3d interpolatedPointAlongWellPath(double measuredDepth);
|
cvf::Vec3d interpolatedPointAlongWellPath(double measuredDepth);
|
||||||
double wellPathAzimuthAngle(const cvf::Vec3d& position) const;
|
double wellPathAzimuthAngle(const cvf::Vec3d& position) const;
|
||||||
void twoClosestPoints(const cvf::Vec3d& position, cvf::Vec3d* p1, cvf::Vec3d* p2) const;
|
void twoClosestPoints(const cvf::Vec3d& position, cvf::Vec3d* p1, cvf::Vec3d* p2) const;
|
||||||
|
std::vector<cvf::Vec3d> clippedPointSubset(double startMD, double endMD) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_hasDatumElevation;
|
bool m_hasDatumElevation;
|
||||||
|
|||||||
Reference in New Issue
Block a user