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:
parent
05edb97635
commit
96760884d1
@ -7,6 +7,7 @@ endif()
|
||||
set (SOURCE_GROUP_HEADER_FILES
|
||||
${CEE_CURRENT_LIST_DIR}RicWellPathDeleteFeature.h
|
||||
${CEE_CURRENT_LIST_DIR}RicWellPathExportCompletionDataFeature.h
|
||||
${CEE_CURRENT_LIST_DIR}RicWellPathExportPerforationCompdatFeature.h
|
||||
${CEE_CURRENT_LIST_DIR}RicWellPathImportCompletionsFileFeature.h
|
||||
${CEE_CURRENT_LIST_DIR}RicWellPathsImportFileFeature.h
|
||||
${CEE_CURRENT_LIST_DIR}RicWellPathsImportSsihubFeature.h
|
||||
@ -16,6 +17,7 @@ ${CEE_CURRENT_LIST_DIR}RicWellPathViewerEventHandler.h
|
||||
set (SOURCE_GROUP_SOURCE_FILES
|
||||
${CEE_CURRENT_LIST_DIR}RicWellPathDeleteFeature.cpp
|
||||
${CEE_CURRENT_LIST_DIR}RicWellPathExportCompletionDataFeature.cpp
|
||||
${CEE_CURRENT_LIST_DIR}RicWellPathExportPerforationCompdatFeature.cpp
|
||||
${CEE_CURRENT_LIST_DIR}RicWellPathImportCompletionsFileFeature.cpp
|
||||
${CEE_CURRENT_LIST_DIR}RicWellPathsImportFileFeature.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 << "RicWellPathExportCompletionDataFeature";
|
||||
commandIds << "RicWellPathImportCompletionsFileFeature";
|
||||
commandIds << "RicWellPathExportPerforationCompdatFeature";
|
||||
commandIds << "RicFlyToObjectFeature";
|
||||
|
||||
// Work in progress -- End
|
||||
|
@ -38,8 +38,10 @@ public:
|
||||
virtual ~RimPerforationInterval();
|
||||
|
||||
void setStartAndEndMD(double startMD, double endMD);
|
||||
double startMD() { return m_startMD(); }
|
||||
double endMD() { return m_endMD(); }
|
||||
double startMD() const { return m_startMD(); }
|
||||
double endMD() const { return m_endMD(); }
|
||||
double radius() const { return m_radius(); }
|
||||
double skinFactor() const { return m_skinFactor(); }
|
||||
|
||||
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);
|
||||
double wellPathAzimuthAngle(const cvf::Vec3d& position) 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:
|
||||
bool m_hasDatumElevation;
|
||||
|
Loading…
Reference in New Issue
Block a user