#1519 Export COMPDAT for all perforation intervals

This commit is contained in:
Bjørnar Grip Fjær 2017-05-26 12:37:01 +02:00
parent 05edb97635
commit 96760884d1
7 changed files with 296 additions and 2 deletions

View File

@ -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

View File

@ -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();
}
}

View File

@ -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);
};

View File

@ -401,6 +401,7 @@ QStringList RimContextCommandBuilder::commandsFromSelection()
commandIds << "RicExportFishbonesLateralsFeature";
commandIds << "RicWellPathExportCompletionDataFeature";
commandIds << "RicWellPathImportCompletionsFileFeature";
commandIds << "RicWellPathExportPerforationCompdatFeature";
commandIds << "RicFlyToObjectFeature";
// Work in progress -- End

View File

@ -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;

View File

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

View File

@ -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;