#2423 Export Completions : Move folder one level up

This commit is contained in:
Magne Sjaastad
2018-01-30 17:25:41 +01:00
parent e989b3afc9
commit 20652a0597
31 changed files with 6 additions and 6 deletions

View File

@@ -1,57 +0,0 @@
# Use this workaround until we're on 2.8.3 on all platforms and can use CMAKE_CURRENT_LIST_DIR directly
if (${CMAKE_VERSION} VERSION_GREATER "2.8.2")
set(CEE_CURRENT_LIST_DIR ${CMAKE_CURRENT_LIST_DIR}/)
endif()
set (SOURCE_GROUP_HEADER_FILES
${CEE_CURRENT_LIST_DIR}RicExportCompletionDataSettingsUi.h
${CEE_CURRENT_LIST_DIR}RicWellPathExportCompletionDataFeature.h
${CEE_CURRENT_LIST_DIR}RicFishbonesTransmissibilityCalculationFeatureImp.h
${CEE_CURRENT_LIST_DIR}RigCompletionData.h
${CEE_CURRENT_LIST_DIR}RigCompletionDataGridCell.h
${CEE_CURRENT_LIST_DIR}RicExportFishbonesWellSegmentsFeature.h
${CEE_CURRENT_LIST_DIR}RicCaseAndFileExportSettingsUi.h
)
if (RESINSIGHT_ENABLE_PROTOTYPE_FEATURE_FRACTURES)
list (APPEND SOURCE_GROUP_HEADER_FILES
${CEE_CURRENT_LIST_DIR}RicExportFractureCompletionsImpl.h
${CEE_CURRENT_LIST_DIR}RigEclipseToStimPlanCellTransmissibilityCalculator.h
${CEE_CURRENT_LIST_DIR}RigTransmissibilityCondenser.h
${CEE_CURRENT_LIST_DIR}RigFractureTransmissibilityEquations.h
${CEE_CURRENT_LIST_DIR}RigWellPathStimplanIntersector.h
)
endif()
set (SOURCE_GROUP_SOURCE_FILES
${CEE_CURRENT_LIST_DIR}RicExportCompletionDataSettingsUi.cpp
${CEE_CURRENT_LIST_DIR}RicWellPathExportCompletionDataFeature.cpp
${CEE_CURRENT_LIST_DIR}RicFishbonesTransmissibilityCalculationFeatureImp.cpp
${CEE_CURRENT_LIST_DIR}RigCompletionData.cpp
${CEE_CURRENT_LIST_DIR}RigCompletionDataGridCell.cpp
${CEE_CURRENT_LIST_DIR}RicExportFishbonesWellSegmentsFeature.cpp
${CEE_CURRENT_LIST_DIR}RicCaseAndFileExportSettingsUi.cpp
)
if (RESINSIGHT_ENABLE_PROTOTYPE_FEATURE_FRACTURES)
list (APPEND SOURCE_GROUP_SOURCE_FILES
${CEE_CURRENT_LIST_DIR}RicExportFractureCompletionsImpl.cpp
${CEE_CURRENT_LIST_DIR}RigEclipseToStimPlanCellTransmissibilityCalculator.cpp
${CEE_CURRENT_LIST_DIR}RigTransmissibilityCondenser.cpp
${CEE_CURRENT_LIST_DIR}RigFractureTransmissibilityEquations.cpp
${CEE_CURRENT_LIST_DIR}RigWellPathStimplanIntersector.cpp
)
endif()
list(APPEND CODE_HEADER_FILES
${SOURCE_GROUP_HEADER_FILES}
)
list(APPEND CODE_SOURCE_FILES
${SOURCE_GROUP_SOURCE_FILES}
)
source_group( "CommandFeature\\CompletionExport" FILES ${SOURCE_GROUP_HEADER_FILES} ${SOURCE_GROUP_SOURCE_FILES} ${CEE_CURRENT_LIST_DIR}CMakeLists_files.cmake )

View File

@@ -1,68 +0,0 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RicCaseAndFileExportSettingsUi.h"
#include "RimTools.h"
#include "cafPdmUiFilePathEditor.h"
CAF_PDM_SOURCE_INIT(RicCaseAndFileExportSettingsUi, "RicCaseAndFileExportSettingsUi");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RicCaseAndFileExportSettingsUi::RicCaseAndFileExportSettingsUi()
{
CAF_PDM_InitObject("RimCaseAndFileExportSettings", "", "", "");
CAF_PDM_InitFieldNoDefault(&folder, "Folder", "Export Folder", "", "", "");
folder.uiCapability()->setUiEditorTypeName(caf::PdmUiFilePathEditor::uiEditorTypeName());
CAF_PDM_InitFieldNoDefault(&caseToApply, "CaseToApply", "Case to Apply", "", "", "");
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QList<caf::PdmOptionItemInfo> RicCaseAndFileExportSettingsUi::calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly)
{
QList<caf::PdmOptionItemInfo> options;
if (fieldNeedingOptions == &caseToApply)
{
RimTools::caseOptionItems(&options);
}
return options;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicCaseAndFileExportSettingsUi::defineEditorAttribute(const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute)
{
if (field == &folder)
{
caf::PdmUiFilePathEditorAttribute* myAttr = static_cast<caf::PdmUiFilePathEditorAttribute*>(attribute);
if (myAttr)
{
myAttr->m_selectDirectory = true;
}
}
}

View File

@@ -1,44 +0,0 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RimEclipseCase.h"
#include "cafPdmObject.h"
#include "cafPdmField.h"
#include "cafPdmPtrField.h"
//==================================================================================================
///
///
//==================================================================================================
class RicCaseAndFileExportSettingsUi : public caf::PdmObject
{
CAF_PDM_HEADER_INIT;
public:
RicCaseAndFileExportSettingsUi();
caf::PdmField<QString> folder;
caf::PdmPtrField<RimEclipseCase*> caseToApply;
virtual QList<caf::PdmOptionItemInfo> calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly) override;
protected:
virtual void defineEditorAttribute(const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute) override;
};

View File

@@ -1,229 +0,0 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RicExportCompletionDataSettingsUi.h"
namespace caf
{
template<>
void RicExportCompletionDataSettingsUi::ExportSplitType::setUp()
{
addItem(RicExportCompletionDataSettingsUi::UNIFIED_FILE, "UNIFIED_FILE", "Unified File");
addItem(RicExportCompletionDataSettingsUi::SPLIT_ON_WELL, "SPLIT_ON_WELL", "Split on Well");
addItem(RicExportCompletionDataSettingsUi::SPLIT_ON_WELL_AND_COMPLETION_TYPE, "SPLIT_ON_WELL_AND_COMPLETION_TYPE", "Split on Well and Completion Type");
setDefault(RicExportCompletionDataSettingsUi::UNIFIED_FILE);
}
template<>
void RicExportCompletionDataSettingsUi::WellSelectionType::setUp()
{
addItem(RicExportCompletionDataSettingsUi::ALL_WELLS, "ALL_WELLS", "All Wells");
addItem(RicExportCompletionDataSettingsUi::CHECKED_WELLS, "CHECKED_WELLS", "Checked Wells");
addItem(RicExportCompletionDataSettingsUi::SELECTED_WELLS, "SELECTED_WELLS", "Selected Wells");
setDefault(RicExportCompletionDataSettingsUi::ALL_WELLS);
}
template<>
void RicExportCompletionDataSettingsUi::CompdatExportType::setUp()
{
addItem(RicExportCompletionDataSettingsUi::TRANSMISSIBILITIES, "TRANSMISSIBILITIES", "Calculated Transmissibilities");
addItem(RicExportCompletionDataSettingsUi::WPIMULT_AND_DEFAULT_CONNECTION_FACTORS, "WPIMULT_AND_DEFAULT_CONNECTION_FACTORS", "Default Connection Factors and WPIMULT (Fractures Not Supported)");
setDefault(RicExportCompletionDataSettingsUi::TRANSMISSIBILITIES);
}
}
CAF_PDM_SOURCE_INIT(RicExportCompletionDataSettingsUi, "RicExportCompletionDataSettingsUi");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RicExportCompletionDataSettingsUi::RicExportCompletionDataSettingsUi()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RicExportCompletionDataSettingsUi::RicExportCompletionDataSettingsUi(bool onlyWellPathCollectionSelected)
{
CAF_PDM_InitObject("RimExportCompletionDataSettings", "", "", "");
CAF_PDM_InitFieldNoDefault(&fileSplit, "FileSplit", "File Split", "", "", "");
CAF_PDM_InitFieldNoDefault(&wellSelection, "WellSelection", "Well Selection", "", "", "");
wellSelection.uiCapability()->setAutoAddingOptionFromValue(false);
CAF_PDM_InitFieldNoDefault(&compdatExport, "compdatExport", "Export", "", " ", "");
CAF_PDM_InitField(&timeStep, "TimeStepIndex", 0, "Time Step", "", "", "");
CAF_PDM_InitField(&useLateralNTG, "UseLateralNTG", false, "Use NTG Horizontally", "", "", "");
CAF_PDM_InitField(&includePerforations, "IncludePerforations", true, "Include Perforations", "", "", "");
CAF_PDM_InitField(&includeFishbones, "IncludeFishbones", true, "Include Fishbones", "", "", "");
#ifdef USE_PROTOTYPE_FEATURE_FRACTURES
CAF_PDM_InitField(&includeFractures, "IncludeFractures", true, "Include Fractures", "", "", "");
#endif // USE_PROTOTYPE_FEATURE_FRACTURES
CAF_PDM_InitField(&excludeMainBoreForFishbones, "ExcludeMainBoreForFishbones", false, "Exclude Main Bore Transmissibility For Fishbones", "", "", "");
m_onlyWellPathCollectionSelected = onlyWellPathCollectionSelected;
m_displayForSimWell = true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicExportCompletionDataSettingsUi::setOnlyWellPathCollectionSelected(bool onlyWellPathCollectionSelected)
{
m_onlyWellPathCollectionSelected = onlyWellPathCollectionSelected;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicExportCompletionDataSettingsUi::showForSimWells()
{
m_displayForSimWell = true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicExportCompletionDataSettingsUi::showForWellPath()
{
m_displayForSimWell = false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicExportCompletionDataSettingsUi::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue)
{
#ifdef USE_PROTOTYPE_FEATURE_FRACTURES
if (changedField == &compdatExport)
{
if (compdatExport == WPIMULT_AND_DEFAULT_CONNECTION_FACTORS)
{
includeFractures = false;
includeFractures.uiCapability()->setUiReadOnly(true);
}
else if (compdatExport == TRANSMISSIBILITIES)
{
includeFractures = true;
includeFractures.uiCapability()->setUiReadOnly(false);
}
}
#endif // USE_PROTOTYPE_FEATURE_FRACTURES
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QList<caf::PdmOptionItemInfo> RicExportCompletionDataSettingsUi::calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly)
{
QList<caf::PdmOptionItemInfo> options;
if (fieldNeedingOptions == &timeStep)
{
QStringList timeStepNames;
if (caseToApply)
{
timeStepNames = caseToApply->timeStepStrings();
}
for (int i = 0; i < timeStepNames.size(); i++)
{
options.push_back(caf::PdmOptionItemInfo(timeStepNames[i], i));
}
}
else if (fieldNeedingOptions == &wellSelection)
{
if (m_onlyWellPathCollectionSelected)
{
options.push_back(caf::PdmOptionItemInfo("All Wells", ALL_WELLS));
options.push_back(caf::PdmOptionItemInfo("Checked Wells", CHECKED_WELLS));
}
else
{
options.push_back(caf::PdmOptionItemInfo("Selected Wells", SELECTED_WELLS));
}
}
else
{
options = RicCaseAndFileExportSettingsUi::calculateValueOptions(fieldNeedingOptions, useOptionsOnly);
}
return options;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicExportCompletionDataSettingsUi::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering)
{
caf::PdmUiGroup* generalExportSettings = uiOrdering.addNewGroup("General Export Settings");
generalExportSettings->add(&folder);
generalExportSettings->add(&caseToApply);
generalExportSettings->add(&compdatExport);
generalExportSettings->add(&useLateralNTG);
generalExportSettings->add(&wellSelection);
if (!m_onlyWellPathCollectionSelected)
{
wellSelection.setValue(SELECTED_WELLS);
}
else
{
if (wellSelection() != ALL_WELLS && wellSelection() != CHECKED_WELLS)
{
wellSelection.setValue(CHECKED_WELLS);
}
}
generalExportSettings->add(&fileSplit);
if (!m_displayForSimWell)
{
caf::PdmUiGroup* fishboneGroup = uiOrdering.addNewGroup("Export of Fishbone Completions");
fishboneGroup->add(&includeFishbones);
fishboneGroup->add(&excludeMainBoreForFishbones);
if (!includeFishbones) excludeMainBoreForFishbones.uiCapability()->setUiReadOnly(true);
else excludeMainBoreForFishbones.uiCapability()->setUiReadOnly(false);
caf::PdmUiGroup* perfIntervalGroup = uiOrdering.addNewGroup("Export of Perforation Completions");
perfIntervalGroup->add(&includePerforations);
perfIntervalGroup->add(&timeStep);
if (!includePerforations) timeStep.uiCapability()->setUiReadOnly(true);
else timeStep.uiCapability()->setUiReadOnly(false);
#ifdef USE_PROTOTYPE_FEATURE_FRACTURES
caf::PdmUiGroup* fractureGroup = uiOrdering.addNewGroup("Export of Fracture Completions");
fractureGroup->add(&includeFractures);
if (compdatExport == WPIMULT_AND_DEFAULT_CONNECTION_FACTORS)
{
includeFractures.uiCapability()->setUiReadOnly(true);
}
else if (compdatExport == TRANSMISSIBILITIES)
{
includeFractures.uiCapability()->setUiReadOnly(false);
}
#endif // USE_PROTOTYPE_FEATURE_FRACTURES
}
uiOrdering.skipRemainingFields();
}

View File

@@ -1,88 +0,0 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RicCaseAndFileExportSettingsUi.h"
#include "cafPdmField.h"
#include "cafAppEnum.h"
//==================================================================================================
///
///
//==================================================================================================
class RicExportCompletionDataSettingsUi : public RicCaseAndFileExportSettingsUi
{
CAF_PDM_HEADER_INIT;
public:
enum ExportSplit {
UNIFIED_FILE,
SPLIT_ON_WELL,
SPLIT_ON_WELL_AND_COMPLETION_TYPE,
};
typedef caf::AppEnum<ExportSplit> ExportSplitType;
enum WellSelection {
ALL_WELLS,
CHECKED_WELLS,
SELECTED_WELLS,
};
typedef caf::AppEnum<WellSelection> WellSelectionType;
enum CompdatExport {
TRANSMISSIBILITIES,
WPIMULT_AND_DEFAULT_CONNECTION_FACTORS,
};
typedef caf::AppEnum<CompdatExport> CompdatExportType;
RicExportCompletionDataSettingsUi();
RicExportCompletionDataSettingsUi(bool onlyWellPathCollectionSelected);
caf::PdmField<ExportSplitType> fileSplit;
caf::PdmField<WellSelectionType> wellSelection;
caf::PdmField<CompdatExportType> compdatExport;
caf::PdmField<bool> useLateralNTG;
caf::PdmField<bool> includePerforations;
caf::PdmField<bool> includeFishbones;
#ifdef USE_PROTOTYPE_FEATURE_FRACTURES
caf::PdmField<bool> includeFractures;
#endif // USE_PROTOTYPE_FEATURE_FRACTURES
caf::PdmField<bool> excludeMainBoreForFishbones;
caf::PdmField<int> timeStep;
void setOnlyWellPathCollectionSelected(bool onlyWellPathCollectionSelected);
void showForSimWells();
void showForWellPath();
virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override;
protected:
virtual QList<caf::PdmOptionItemInfo> calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool * useOptionsOnly) override;
virtual void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) override;
private:
bool m_onlyWellPathCollectionSelected;
bool m_displayForSimWell;
};

View File

@@ -1,434 +0,0 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RicExportFishbonesWellSegmentsFeature.h"
#include "RiaApplication.h"
#include "RiaLogging.h"
#include "RicExportFeatureImpl.h"
#include "RimProject.h"
#include "RimFishboneWellPathCollection.h"
#include "RimFishbonesCollection.h"
#include "RimFishbonesMultipleSubs.h"
#include "RimWellPath.h"
#include "RimEclipseCase.h"
#include "RigMainGrid.h"
#include "RigEclipseCaseData.h"
#include "RigWellPath.h"
#include "RiuMainWindow.h"
#include "cafSelectionManager.h"
#include "cafPdmUiPropertyViewDialog.h"
#include "cafUtils.h"
#include "cvfMath.h"
#include <QAction>
#include <QMessageBox>
#include <QDir>
CAF_CMD_SOURCE_INIT(RicExportFishbonesWellSegmentsFeature, "RicExportFishbonesWellSegmentsFeature");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicExportFishbonesWellSegmentsFeature::onActionTriggered(bool isChecked)
{
RimFishbonesCollection* fishbonesCollection = selectedFishbonesCollection();
RimWellPath* wellPath = selectedWellPath();
CVF_ASSERT(fishbonesCollection);
CVF_ASSERT(wellPath);
RiaApplication* app = RiaApplication::instance();
QString projectFolder = app->currentProjectPath();
QString defaultDir = RiaApplication::instance()->lastUsedDialogDirectoryWithFallback("COMPLETIONS", projectFolder);
RicCaseAndFileExportSettingsUi 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.folder = defaultDir;
caf::PdmUiPropertyViewDialog propertyDialog(RiuMainWindow::instance(), &exportSettings, "Export Well Segments", "");
RicExportFeatureImpl::configureForExport(&propertyDialog);
if (propertyDialog.exec() == QDialog::Accepted)
{
RiaApplication::instance()->setLastUsedDialogDirectory("COMPLETIONS", QFileInfo(exportSettings.folder).absolutePath());
std::vector<RimFishbonesMultipleSubs*> fishbonesSubs;
for (RimFishbonesMultipleSubs* subs : fishbonesCollection->fishbonesSubs)
{
fishbonesSubs.push_back(subs);
}
exportWellSegments(wellPath, fishbonesSubs, exportSettings);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimFishbonesCollection* RicExportFishbonesWellSegmentsFeature::selectedFishbonesCollection()
{
RimFishbonesCollection* objToFind = nullptr;
caf::PdmUiItem* pdmUiItem = caf::SelectionManager::instance()->selectedItem();
caf::PdmObjectHandle* objHandle = dynamic_cast<caf::PdmObjectHandle*>(pdmUiItem);
if (objHandle)
{
objHandle->firstAncestorOrThisOfType(objToFind);
}
return objToFind;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimWellPath* RicExportFishbonesWellSegmentsFeature::selectedWellPath()
{
RimWellPath* objToFind = nullptr;
caf::PdmUiItem* pdmUiItem = caf::SelectionManager::instance()->selectedItem();
caf::PdmObjectHandle* objHandle = dynamic_cast<caf::PdmObjectHandle*>(pdmUiItem);
if (objHandle)
{
objHandle->firstAncestorOrThisOfType(objToFind);
}
return objToFind;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicExportFishbonesWellSegmentsFeature::setupActionLook(QAction* actionToSetup)
{
actionToSetup->setText("Export Well Segments");
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RicExportFishbonesWellSegmentsFeature::isCommandEnabled()
{
if (selectedFishbonesCollection())
{
return true;
}
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicExportFishbonesWellSegmentsFeature::exportWellSegments(const RimWellPath* wellPath, const std::vector<RimFishbonesMultipleSubs*>& fishbonesSubs, const RicCaseAndFileExportSettingsUi& settings)
{
if (settings.caseToApply() == nullptr)
{
RiaLogging::error("Export Well Segments: Cannot export completions data without specified eclipse case");
return;
}
QString fileName = QString("%1-Welsegs").arg(settings.caseToApply()->caseUserDescription());
fileName = caf::Utils::makeValidFileBasename(fileName);
QString filePath = QDir(settings.folder()).filePath(fileName);
QFile exportFile(filePath);
if (!exportFile.open(QIODevice::WriteOnly))
{
RiaLogging::error(QString("Export Well Segments: Could not open the file: %1").arg(filePath));
return;
}
std::vector<WellSegmentLocation> locations = RicWellPathExportCompletionDataFeature::findWellSegmentLocations(settings.caseToApply, wellPath, fishbonesSubs);
QTextStream stream(&exportFile);
RifEclipseDataTableFormatter formatter(stream);
generateWelsegsTable(formatter, wellPath, settings, locations);
generateCompsegsTable(formatter, wellPath, settings, locations);
generateWsegvalvTable(formatter, wellPath, settings, locations);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicExportFishbonesWellSegmentsFeature::generateWelsegsTable(RifEclipseDataTableFormatter& formatter,
const RimWellPath* wellPath,
const RicCaseAndFileExportSettingsUi& settings,
const std::vector<WellSegmentLocation>& locations)
{
RiaEclipseUnitTools::UnitSystem unitSystem = settings.caseToApply->eclipseCaseData()->unitsType();
formatter.keyword("WELSEGS");
double startMD = wellPath->fishbonesCollection()->startMD();
double startTVD = -wellPath->wellPathGeometry()->interpolatedPointAlongWellPath(startMD).z();
{
std::vector<RifEclipseOutputTableColumn> header = {
RifEclipseOutputTableColumn("Name"),
RifEclipseOutputTableColumn("Dep 1"),
RifEclipseOutputTableColumn("Tlen 1"),
RifEclipseOutputTableColumn("Vol 1"),
RifEclipseOutputTableColumn("Len&Dep"),
RifEclipseOutputTableColumn("PresDrop"),
};
formatter.header(header);
formatter.add(wellPath->name());
formatter.add(startTVD);
formatter.add(startMD);
formatter.add("1*");
formatter.add(wellPath->fishbonesCollection()->lengthAndDepth().text());
formatter.add(wellPath->fishbonesCollection()->pressureDrop().text());
formatter.rowCompleted();
}
{
std::vector<RifEclipseOutputTableColumn> header = {
RifEclipseOutputTableColumn("First Seg"),
RifEclipseOutputTableColumn("Last Seg"),
RifEclipseOutputTableColumn("Branch Num"),
RifEclipseOutputTableColumn("Outlet Seg"),
RifEclipseOutputTableColumn("Length"),
RifEclipseOutputTableColumn("Depth Change"),
RifEclipseOutputTableColumn("Diam"),
RifEclipseOutputTableColumn("Rough"),
};
formatter.header(header);
}
{
formatter.comment("Main stem");
double depth = 0;
double length = 0;
double previousMD = startMD;
double previousTVD = startTVD;
for (const WellSegmentLocation& location : locations)
{
if (wellPath->fishbonesCollection()->lengthAndDepth() == RimFishbonesCollection::INC)
{
depth = location.trueVerticalDepth - previousTVD;
length = location.fishbonesSubs->measuredDepth(location.subIndex) - previousMD;
}
else
{
depth += location.trueVerticalDepth - previousTVD;
length += location.fishbonesSubs->measuredDepth(location.subIndex) - previousMD;
}
formatter.comment(QString("Segment for sub %1").arg(location.subIndex));
formatter.add(location.segmentNumber).add(location.segmentNumber);
formatter.add(1); // All segments on main stem are branch 1
formatter.add(location.segmentNumber - 1); // All main stem segments are connected to the segment below them
formatter.add(length);
formatter.add(depth);
formatter.add(wellPath->fishbonesCollection()->linerDiameter(unitSystem));
formatter.add(wellPath->fishbonesCollection()->roughnessFactor(unitSystem));
formatter.rowCompleted();
previousMD = location.measuredDepth;
previousTVD = location.trueVerticalDepth;
}
}
{
formatter.comment("Laterals");
formatter.comment("Diam: MSW - Tubing Radius");
formatter.comment("Rough: MSW - Open Hole Roughness Factor");
for (const WellSegmentLocation& location : locations)
{
formatter.comment("ICD");
formatter.add(location.icdSegmentNumber).add(location.icdSegmentNumber);
formatter.add(location.icdBranchNumber);
formatter.add(location.segmentNumber);
formatter.add(0.1); // ICDs have 0.1 length
formatter.add(0); // Depth change
formatter.add(wellPath->fishbonesCollection()->linerDiameter(unitSystem));
formatter.add(wellPath->fishbonesCollection()->roughnessFactor(unitSystem));
formatter.rowCompleted();
for (const WellSegmentLateral& lateral : location.laterals)
{
formatter.comment(QString("%1 : Sub index %2 - Lateral %3").arg(location.fishbonesSubs->generatedName()).arg(location.subIndex).arg(lateral.lateralIndex));
double depth = 0;
double length = 0;
for (const WellSegmentLateralIntersection& intersection : lateral.intersections)
{
if (wellPath->fishbonesCollection()->lengthAndDepth() == RimFishbonesCollection::INC)
{
depth = intersection.tvdChangeFromPreviousIntersection;
length = intersection.mdFromPreviousIntersection;
}
else
{
depth += intersection.tvdChangeFromPreviousIntersection;
length += intersection.mdFromPreviousIntersection;
}
double diameter = computeEffectiveDiameter(location.fishbonesSubs->tubingDiameter(unitSystem), location.fishbonesSubs->holeDiameter(unitSystem));
formatter.add(intersection.segmentNumber);
formatter.add(intersection.segmentNumber);
formatter.add(lateral.branchNumber);
formatter.add(intersection.attachedSegmentNumber);
formatter.add(length);
formatter.add(depth);
formatter.add(diameter);
formatter.add(location.fishbonesSubs->openHoleRoughnessFactor(unitSystem));
formatter.rowCompleted();
}
}
}
}
formatter.tableCompleted();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicExportFishbonesWellSegmentsFeature::generateCompsegsTable(RifEclipseDataTableFormatter& formatter,
const RimWellPath* wellPath,
const RicCaseAndFileExportSettingsUi& settings,
const std::vector<WellSegmentLocation>& locations)
{
RigMainGrid* grid = settings.caseToApply->eclipseCaseData()->mainGrid();
formatter.keyword("COMPSEGS");
{
std::vector<RifEclipseOutputTableColumn> header = {
RifEclipseOutputTableColumn("Name")
};
formatter.header(header);
formatter.add(wellPath->name());
formatter.rowCompleted();
}
{
std::vector<RifEclipseOutputTableColumn> header = {
RifEclipseOutputTableColumn("I"),
RifEclipseOutputTableColumn("J"),
RifEclipseOutputTableColumn("K"),
RifEclipseOutputTableColumn("Branch no"),
RifEclipseOutputTableColumn("Start Length"),
RifEclipseOutputTableColumn("End Length"),
RifEclipseOutputTableColumn("Dir Pen"),
RifEclipseOutputTableColumn("End Range"),
RifEclipseOutputTableColumn("Connection Depth")
};
formatter.header(header);
}
for (const WellSegmentLocation& location : locations)
{
for (const WellSegmentLateral& lateral : location.laterals)
{
double aggregatedLength = 0;
for (const WellSegmentLateralIntersection& intersection : lateral.intersections)
{
size_t i, j, k;
grid->ijkFromCellIndex(intersection.globalCellIndex, &i, &j, &k);
formatter.addZeroBasedCellIndex(i).addZeroBasedCellIndex(j).addZeroBasedCellIndex(k);
formatter.add(lateral.branchNumber);
formatter.add(aggregatedLength);
formatter.add(aggregatedLength + intersection.mdFromPreviousIntersection);
formatter.rowCompleted();
aggregatedLength += intersection.mdFromPreviousIntersection;
}
}
}
formatter.tableCompleted();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicExportFishbonesWellSegmentsFeature::generateWsegvalvTable(RifEclipseDataTableFormatter& formatter,
const RimWellPath* wellPath,
const RicCaseAndFileExportSettingsUi& settings,
const std::vector<WellSegmentLocation>& locations)
{
RiaEclipseUnitTools::UnitSystem unitSystem = settings.caseToApply->eclipseCaseData()->unitsType();
{
formatter.keyword("WSEGVALV");
std::vector<RifEclipseOutputTableColumn> header = {
RifEclipseOutputTableColumn("Well Name"),
RifEclipseOutputTableColumn("Seg No"),
RifEclipseOutputTableColumn("Cv"),
RifEclipseOutputTableColumn("Ac"),
};
formatter.header(header);
}
for (const WellSegmentLocation& location : locations)
{
formatter.add(wellPath->name());
formatter.add(location.icdSegmentNumber);
formatter.add(location.fishbonesSubs->icdFlowCoefficient());
double icdOrificeRadius = location.fishbonesSubs->icdOrificeDiameter(unitSystem) / 2;
double icdArea = icdOrificeRadius * icdOrificeRadius * cvf::PI_D;
formatter.add(icdArea * static_cast<double>(location.fishbonesSubs->icdCount()));
formatter.rowCompleted();
}
formatter.tableCompleted();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RicExportFishbonesWellSegmentsFeature::computeEffectiveDiameter(double innerDiameter, double outerDiameter)
{
double innerRadius = innerDiameter / 2;
double innerArea = cvf::PI_D * innerRadius * innerRadius;
double outerRadius = outerDiameter / 2;
double outerArea = cvf::PI_D * outerRadius * outerRadius;
double effectiveArea = outerArea - innerArea;
double effectiveRadius = cvf::Math::sqrt(effectiveArea / cvf::PI_D);
return effectiveRadius * 2;
}

View File

@@ -1,57 +0,0 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RifEclipseDataTableFormatter.h"
#include "RicCaseAndFileExportSettingsUi.h"
#include "RicWellPathExportCompletionDataFeature.h"
#include "cafCmdFeature.h"
class RimFishbonesCollection;
class RimFishbonesMultipleSubs;
class RimWellPath;
//==================================================================================================
///
//==================================================================================================
class RicExportFishbonesWellSegmentsFeature : public caf::CmdFeature
{
CAF_CMD_HEADER_INIT;
protected:
virtual void onActionTriggered(bool isChecked) override;
virtual void setupActionLook(QAction* actionToSetup) override;
virtual bool isCommandEnabled() override;
public:
static void exportWellSegments(const RimWellPath* wellPath, const std::vector<RimFishbonesMultipleSubs*>& fishbonesSubs, const RicCaseAndFileExportSettingsUi& settings);
private:
static RimFishbonesCollection* selectedFishbonesCollection();
static RimWellPath* selectedWellPath();
static void generateWelsegsTable(RifEclipseDataTableFormatter& formatter, const RimWellPath* wellPath, const RicCaseAndFileExportSettingsUi& settings, const std::vector<WellSegmentLocation>& locations);
static void generateCompsegsTable(RifEclipseDataTableFormatter& formatter, const RimWellPath* wellPath, const RicCaseAndFileExportSettingsUi& settings, const std::vector<WellSegmentLocation>& locations);
static void generateWsegvalvTable(RifEclipseDataTableFormatter& formatter, const RimWellPath* wellPath, const RicCaseAndFileExportSettingsUi& settings, const std::vector<WellSegmentLocation>& locations);
static double computeEffectiveDiameter(double innerDiameter, double outerDiameter);
};

View File

@@ -1,370 +0,0 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RicExportFractureCompletionsImpl.h"
#include "RiaLogging.h"
#include "RicExportCompletionDataSettingsUi.h"
#include "RimEclipseCase.h"
#include "RimEclipseView.h"
#include "RimFracture.h"
#include "RimFractureTemplate.h"
#include "RimSimWellFracture.h"
#include "RimSimWellFractureCollection.h"
#include "RimSimWellInView.h"
#include "RimStimPlanFractureTemplate.h"
#include "RimWellPath.h"
#include "RimWellPathCompletions.h"
#include "RimWellPathFracture.h"
#include "RimWellPathFractureCollection.h"
#include "RigEclipseCaseData.h"
#include "RigTransmissibilityCondenser.h"
#include "RigFractureCell.h"
#include "RigFractureGrid.h"
#include "RigEclipseToStimPlanCellTransmissibilityCalculator.h"
#include "RigFractureTransmissibilityEquations.h"
#include "RigWellPathStimplanIntersector.h"
#include "RigMainGrid.h"
#include "RigSimWellData.h"
#include "RigSimulationWellCoordsAndMD.h"
#include "RigWellPath.h"
#include <vector>
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RigCompletionData> RicExportFractureCompletionsImpl::generateCompdatValuesForWellPath(RimWellPath* wellPath,
const RicExportCompletionDataSettingsUi& settings,
QTextStream* outputStreamForIntermediateResultsText)
{
RimEclipseCase* caseToApply = settings.caseToApply();
std::vector<RimFracture*> fracturesAlongWellPath;
if (wellPath->fractureCollection()->isChecked())
{
for (const auto& frac : wellPath->fractureCollection()->fractures)
{
if (frac->isChecked())
{
fracturesAlongWellPath.push_back(frac);
}
}
}
return generateCompdatValues(caseToApply,
wellPath->completions()->wellNameForExport(),
wellPath->wellPathGeometry(),
fracturesAlongWellPath,
outputStreamForIntermediateResultsText);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RigCompletionData> RicExportFractureCompletionsImpl::generateCompdatValuesForSimWell(RimEclipseCase* eclipseCase,
const RimSimWellInView* well,
QTextStream* outputStreamForIntermediateResultsText)
{
std::vector<RigCompletionData> completionData;
std::vector< std::vector <cvf::Vec3d> > pipeBranchesCLCoords;
std::vector< std::vector <RigWellResultPoint> > pipeBranchesCellIds;
RimEclipseView* view = nullptr;
well->firstAncestorOrThisOfTypeAsserted(view);
size_t timeStep = view->currentTimeStep();
well->calculateWellPipeDynamicCenterLine(timeStep, pipeBranchesCLCoords, pipeBranchesCellIds);
for (size_t branchIndex = 0; branchIndex < pipeBranchesCLCoords.size(); ++branchIndex)
{
RigSimulationWellCoordsAndMD coordsAndMD(pipeBranchesCLCoords[branchIndex]);
RigWellPath wellPathGeometry;
wellPathGeometry.m_wellPathPoints = coordsAndMD.wellPathPoints();
wellPathGeometry.m_measuredDepths = coordsAndMD.measuredDepths();
std::vector<RimFracture*> fractures;
for (RimSimWellFracture* fracture : well->simwellFractureCollection->simwellFractures())
{
if (fracture->isChecked() && static_cast<size_t>(fracture->branchIndex()) == branchIndex)
{
fractures.push_back(fracture);
}
}
std::vector<RigCompletionData> branchCompletions = generateCompdatValues(eclipseCase, well->name(), &wellPathGeometry, fractures, outputStreamForIntermediateResultsText);
completionData.insert(completionData.end(), branchCompletions.begin(), branchCompletions.end());
}
return completionData;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RigCompletionData> RicExportFractureCompletionsImpl::generateCompdatValues(RimEclipseCase* caseToApply,
const QString& wellPathName,
const RigWellPath* wellPathGeometry,
const std::vector<RimFracture*>& fractures,
QTextStream* outputStreamForIntermediateResultsText)
{
double cDarcyInCorrectUnit = RiaEclipseUnitTools::darcysConstant(caseToApply->eclipseCaseData()->unitsType());
const RigMainGrid* mainGrid = caseToApply->eclipseCaseData()->mainGrid();
// To handle several fractures in the same eclipse cell we need to keep track of the transmissibility
// to the well from each fracture intersecting the cell and sum these transmissibilities at the end.
// std::map <eclipseCellIndex ,map< fracture, trans> >
std::map <size_t, std::map<RimFracture*, double> > eclCellIdxToTransPrFractureMap;
std::vector<RigCompletionData> fractureCompletions;
for (RimFracture* fracture : fractures)
{
RimFractureTemplate* fracTemplate = fracture->fractureTemplate();
if (!fracTemplate) continue;
const RigFractureGrid* fractureGrid = fracTemplate->fractureGrid();
if (!fractureGrid) continue;
bool useFiniteConductivityInFracture = (fracTemplate->conductivityType() == RimFractureTemplate::FINITE_CONDUCTIVITY);
//If finite cond chosen and conductivity not present in stimplan file, do not calculate trans for this fracture
if (useFiniteConductivityInFracture)
{
if (dynamic_cast<RimStimPlanFractureTemplate*>(fracTemplate))
{
RimStimPlanFractureTemplate* fracTemplateStimPlan = dynamic_cast<RimStimPlanFractureTemplate*>(fracTemplate);
if (!fracTemplateStimPlan->hasConductivity())
{
RiaLogging::error("Trying to export completion data for stimPlan fracture without conductivity data for " + fracture->name());
RiaLogging::error("No transmissibilities will be calculated for " + fracture->name());
continue;
}
}
}
using CellIdxSpace = RigTransmissibilityCondenser::CellAddress;
RigTransmissibilityCondenser transCondenser;
//////
// Calculate Matrix To Fracture Trans
const std::vector<RigFractureCell>& fractureCells = fractureGrid->fractureCells();
for (const RigFractureCell& fractureCell : fractureCells)
{
if (!fractureCell.hasNonZeroConductivity()) continue;
RigEclipseToStimPlanCellTransmissibilityCalculator eclToFractureTransCalc(caseToApply,
fracture->transformMatrix(),
fracture->fractureTemplate()->skinFactor,
cDarcyInCorrectUnit,
fractureCell);
const std::vector<size_t>& fractureCellContributingEclipseCells = eclToFractureTransCalc.globalIndeciesToContributingEclipseCells();
const std::vector<double>& fractureCellContributingEclipseCellTransmissibilities = eclToFractureTransCalc.contributingEclipseCellTransmissibilities();
size_t stimPlanCellIndex = fractureGrid->getGlobalIndexFromIJ(fractureCell.getI(), fractureCell.getJ());
for ( size_t i = 0; i < fractureCellContributingEclipseCells.size(); i++ )
{
if ( fracture->isEclipseCellWithinContainment(caseToApply->eclipseCaseData()->mainGrid(), fractureCellContributingEclipseCells[i]) )
{
if ( useFiniteConductivityInFracture )
{
transCondenser.addNeighborTransmissibility({ true, CellIdxSpace::ECLIPSE, fractureCellContributingEclipseCells[i] },
{ false, CellIdxSpace::STIMPLAN, stimPlanCellIndex },
fractureCellContributingEclipseCellTransmissibilities[i]);
}
else
{
transCondenser.addNeighborTransmissibility({ true, CellIdxSpace::ECLIPSE, fractureCellContributingEclipseCells[i] },
{ true, CellIdxSpace::WELL, 1 },
fractureCellContributingEclipseCellTransmissibilities[i]);
}
}
}
}
//////
// Calculate Transmissibility in the fracture: From one StimPlan Cell to the other
if (useFiniteConductivityInFracture)
{
for (size_t i = 0; i < fractureGrid->iCellCount(); i++)
{
for (size_t j = 0; j < fractureGrid->jCellCount(); j++)
{
size_t fractureCellIndex = fractureGrid->getGlobalIndexFromIJ(i, j);
const RigFractureCell& fractureCell = fractureGrid->cellFromIndex(fractureCellIndex);
if (!fractureCell.hasNonZeroConductivity()) continue;
if ( i < fractureGrid->iCellCount() - 1 )
{
size_t fractureCellNeighbourXIndex = fractureGrid->getGlobalIndexFromIJ(i + 1, j);
const RigFractureCell& fractureCellNeighbourX = fractureGrid->cellFromIndex(fractureCellNeighbourXIndex);
double horizontalTransToXneigbour =
RigFractureTransmissibilityEquations::centerToCenterFractureCellTrans(fractureCell.getConductivtyValue(),
fractureCell.cellSizeX(),
fractureCell.cellSizeZ(),
fractureCellNeighbourX.getConductivtyValue(),
fractureCellNeighbourX.cellSizeX(),
fractureCellNeighbourX.cellSizeZ(),
cDarcyInCorrectUnit);
transCondenser.addNeighborTransmissibility({ false, RigTransmissibilityCondenser::CellAddress::STIMPLAN, fractureCellIndex },
{ false, RigTransmissibilityCondenser::CellAddress::STIMPLAN, fractureCellNeighbourXIndex },
horizontalTransToXneigbour);
}
if ( j < fractureGrid->jCellCount() - 1 )
{
size_t fractureCellNeighbourZIndex = fractureGrid->getGlobalIndexFromIJ(i, j + 1);
const RigFractureCell& fractureCellNeighbourZ = fractureGrid->cellFromIndex(fractureCellNeighbourZIndex);
double verticalTransToZneigbour =
RigFractureTransmissibilityEquations::centerToCenterFractureCellTrans(fractureCell.getConductivtyValue(),
fractureCell.cellSizeZ(),
fractureCell.cellSizeX(),
fractureCellNeighbourZ.getConductivtyValue(),
fractureCellNeighbourZ.cellSizeZ(),
fractureCellNeighbourZ.cellSizeX(),
cDarcyInCorrectUnit);
transCondenser.addNeighborTransmissibility({ false, RigTransmissibilityCondenser::CellAddress::STIMPLAN, fractureCellIndex },
{ false, RigTransmissibilityCondenser::CellAddress::STIMPLAN, fractureCellNeighbourZIndex },
verticalTransToZneigbour);
}
}
}
}
/////
// Calculate transmissibility into the well
if (useFiniteConductivityInFracture)
{
////
//If fracture has orientation Azimuth or Transverse, assume only radial inflow
if ( fracture->fractureTemplate()->orientationType() == RimFractureTemplate::AZIMUTH
|| fracture->fractureTemplate()->orientationType() == RimFractureTemplate::TRANSVERSE_WELL_PATH)
{
const RigFractureGrid* fracGrid = fracture->fractureTemplate()->fractureGrid();
if (fracGrid)
{
std::pair<size_t, size_t> wellCellIJ = fracGrid->fractureCellAtWellCenter();
size_t wellCellIndex = fracGrid->getGlobalIndexFromIJ(wellCellIJ.first, wellCellIJ.second);
const RigFractureCell& wellCell = fractureGrid->cellFromIndex(wellCellIndex);
double radialTrans = RigFractureTransmissibilityEquations::fractureCellToWellRadialTrans(wellCell.getConductivtyValue(),
wellCell.cellSizeX(),
wellCell.cellSizeZ(),
fracture->wellRadius(caseToApply->eclipseCaseData()->unitsType()),
fracTemplate->skinFactor(),
cDarcyInCorrectUnit);
transCondenser.addNeighborTransmissibility({ true, RigTransmissibilityCondenser::CellAddress::WELL, 1 },
{ false, RigTransmissibilityCondenser::CellAddress::STIMPLAN, wellCellIndex },
radialTrans);
}
}
else if (fracture->fractureTemplate()->orientationType() == RimFractureTemplate::ALONG_WELL_PATH)
{
////
//If fracture has orientation along well, linear inflow along well and radial flow at endpoints
RigWellPathStimplanIntersector wellFractureIntersector(wellPathGeometry, fracture);
const std::map<size_t, RigWellPathStimplanIntersector::WellCellIntersection >& fractureWellCells = wellFractureIntersector.intersections();
for (const auto& fracCellIdxIsectDataPair : fractureWellCells)
{
size_t fracWellCellIdx = fracCellIdxIsectDataPair.first;
RigWellPathStimplanIntersector::WellCellIntersection intersection = fracCellIdxIsectDataPair.second;
const RigFractureCell& fractureWellCell = fractureGrid->cellFromIndex(fracWellCellIdx);
double linearTrans = 0.0;
if (intersection.hlength > 0.0 || intersection.vlength > 0.0)
{
linearTrans = RigFractureTransmissibilityEquations::fractureCellToWellLinearTrans(fractureWellCell.getConductivtyValue(),
fractureWellCell.cellSizeX(),
fractureWellCell.cellSizeZ(),
intersection.vlength,
intersection.hlength,
fracture->perforationEfficiency(),
fracTemplate->skinFactor(),
cDarcyInCorrectUnit);
}
transCondenser.addNeighborTransmissibility({ true, RigTransmissibilityCondenser::CellAddress::WELL, 1 },
{ false, RigTransmissibilityCondenser::CellAddress::STIMPLAN, fracWellCellIdx },
linearTrans);
}
}
}
/////
// Insert total transmissibility from eclipse-cell to well for this fracture into the map
std::set<RigTransmissibilityCondenser::CellAddress> externalCells = transCondenser.externalCells();
for (RigTransmissibilityCondenser::CellAddress externalCell : externalCells)
{
if (externalCell.m_cellIndexSpace == RigTransmissibilityCondenser::CellAddress::ECLIPSE)
{
double trans = transCondenser.condensedTransmissibility(externalCell, { true, RigTransmissibilityCondenser::CellAddress::WELL, 1 });
eclCellIdxToTransPrFractureMap[externalCell.m_globalCellIdx][fracture] = trans;
RigCompletionData compDat(wellPathName, RigCompletionDataGridCell(externalCell.m_globalCellIdx, caseToApply->mainGrid()));
compDat.setFromFracture(trans, fracture->fractureTemplate()->skinFactor());
compDat.addMetadata(fracture->name(), QString::number(trans));
fractureCompletions.push_back(compDat);
}
}
if ( outputStreamForIntermediateResultsText )
{
(*outputStreamForIntermediateResultsText) << "\n" << "\n" << "\n----------- All Transimissibilities " << fracture->name() << " -------------------- \n\n";
(*outputStreamForIntermediateResultsText) << QString::fromStdString(transCondenser.neighborTransDebugOutput(mainGrid, fractureGrid));
(*outputStreamForIntermediateResultsText) << "\n" << "\n" << "\n----------- Condensed Results " << fracture->name() << " -------------------- \n\n";
(*outputStreamForIntermediateResultsText) << QString::fromStdString(transCondenser.condensedTransDebugOutput(mainGrid, fractureGrid));
(*outputStreamForIntermediateResultsText) << "\n" ;
}
}
return fractureCompletions;
}

View File

@@ -1,55 +0,0 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RigCompletionData.h"
#include <vector>
class RimWellPath;
class RicExportCompletionDataSettingsUi;
class QTextStream;
class RigWellPath;
class RimEclipseCase;
class RimFracture;
class RimSimWellInView;
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
class RicExportFractureCompletionsImpl
{
public:
static std::vector<RigCompletionData> generateCompdatValuesForWellPath(RimWellPath* wellPath,
const RicExportCompletionDataSettingsUi& settings,
QTextStream* outputStreamForIntermediateResultsText);
static std::vector<RigCompletionData> generateCompdatValuesForSimWell(RimEclipseCase* eclipseCase,
const RimSimWellInView* well,
QTextStream* outputStreamForIntermediateResultsText);
private:
static std::vector<RigCompletionData> generateCompdatValues(RimEclipseCase* caseToApply,
const QString& wellPathName,
const RigWellPath* wellPathGeometry,
const std::vector<RimFracture*>& fractures,
QTextStream* outputStreamForIntermediateResultsText);
};

View File

@@ -1,236 +0,0 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RicFishbonesTransmissibilityCalculationFeatureImp.h"
#include "RicExportCompletionDataSettingsUi.h"
#include "RicWellPathExportCompletionDataFeature.h"
#include "RigActiveCellInfo.h"
#include "RigCompletionData.h"
#include "RigEclipseCaseData.h"
#include "RigMainGrid.h"
#include "RigWellPath.h"
#include "RimFishboneWellPath.h"
#include "RimFishboneWellPathCollection.h"
#include "RimFishbonesCollection.h"
#include "RimFishbonesMultipleSubs.h"
#include "RimWellPath.h"
#include "RimWellPathCompletions.h"
#include "RigWellLogExtractor.h"
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicFishbonesTransmissibilityCalculationFeatureImp::findFishboneLateralsWellBoreParts(std::map<size_t, std::vector<WellBorePartForTransCalc> >& wellBorePartsInCells,
const RimWellPath* wellPath,
const RicExportCompletionDataSettingsUi& settings)
{
// Generate data
const RigEclipseCaseData* caseData = settings.caseToApply()->eclipseCaseData();
std::vector<WellSegmentLocation> locations = RicWellPathExportCompletionDataFeature::findWellSegmentLocations(settings.caseToApply, wellPath);
RiaEclipseUnitTools::UnitSystem unitSystem = caseData->unitsType();
bool isMainBore = false;
for (const WellSegmentLocation& location : locations)
{
for (const WellSegmentLateral& lateral : location.laterals)
{
for (const WellSegmentLateralIntersection& intersection : lateral.intersections)
{
double diameter = location.fishbonesSubs->holeDiameter(unitSystem);
QString completionMetaData = (location.fishbonesSubs->generatedName() + QString(": Sub: %1 Lateral: %2").arg(location.subIndex).arg(lateral.lateralIndex));
WellBorePartForTransCalc wellBorePart = WellBorePartForTransCalc(intersection.lengthsInCell,
diameter / 2,
location.fishbonesSubs->skinFactor(),
isMainBore,
completionMetaData);
wellBorePartsInCells[intersection.globalCellIndex].push_back(wellBorePart);
}
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RigCompletionData> RicFishbonesTransmissibilityCalculationFeatureImp::generateFishboneCompdatValuesUsingAdjustedCellVolume(const RimWellPath* wellPath,
const RicExportCompletionDataSettingsUi& settings)
{
std::map<size_t, std::vector<WellBorePartForTransCalc> > wellBorePartsInCells; //wellBore = main bore or fishbone lateral
findFishboneLateralsWellBoreParts(wellBorePartsInCells, wellPath, settings);
findFishboneImportedLateralsWellBoreParts(wellBorePartsInCells, wellPath, settings);
if (!wellBorePartsInCells.empty())
{
findMainWellBoreParts(wellBorePartsInCells, wellPath, settings);
}
std::vector<RigCompletionData> completionData;
const RigActiveCellInfo* activeCellInfo = settings.caseToApply->eclipseCaseData()->activeCellInfo(RiaDefines::MATRIX_MODEL);
for (const auto& cellAndWellBoreParts : wellBorePartsInCells)
{
size_t globalCellIndex = cellAndWellBoreParts.first;
const std::vector<WellBorePartForTransCalc>& wellBoreParts = cellAndWellBoreParts.second;
bool cellIsActive = activeCellInfo->isActive(globalCellIndex);
if (!cellIsActive) continue;
// Find main bore and number of laterals
size_t numberOfLaterals = 0;
CellDirection mainBoreDirection = DIR_I;
for (const auto& wellBorePart : wellBoreParts)
{
if (!wellBorePart.isMainBore)
{
numberOfLaterals++;
}
else
{
mainBoreDirection = RicWellPathExportCompletionDataFeature::calculateDirectionInCell(settings.caseToApply,
globalCellIndex,
wellBorePart.lengthsInCell);
}
}
for (WellBorePartForTransCalc wellBorePart : wellBoreParts)
{
RigCompletionData completion(wellPath->completions()->wellNameForExport(), RigCompletionDataGridCell(globalCellIndex, settings.caseToApply->mainGrid()));
double transmissibility = 0.0;
if (wellBorePart.isMainBore)
{
//No change in transmissibility for main bore
transmissibility = RicWellPathExportCompletionDataFeature::calculateTransmissibility(settings.caseToApply,
wellPath,
wellBorePart.lengthsInCell,
wellBorePart.skinFactor,
wellBorePart.wellRadius,
globalCellIndex,
settings.useLateralNTG);
}
else
{
//Adjust transmissibility for fishbone laterals
transmissibility = RicWellPathExportCompletionDataFeature::calculateTransmissibility(settings.caseToApply,
wellPath,
wellBorePart.lengthsInCell,
wellBorePart.skinFactor,
wellBorePart.wellRadius,
globalCellIndex,
settings.useLateralNTG,
numberOfLaterals,
mainBoreDirection);
}
CellDirection direction = RicWellPathExportCompletionDataFeature::calculateDirectionInCell(settings.caseToApply,
globalCellIndex,
wellBorePart.lengthsInCell);
completion.setTransAndWPImultBackgroundDataFromFishbone(transmissibility,
wellBorePart.skinFactor,
wellBorePart.wellRadius *2,
direction,
wellBorePart.isMainBore);
completion.addMetadata(wellBorePart.metaData, QString::number(transmissibility));
completionData.push_back(completion);
}
}
return completionData;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicFishbonesTransmissibilityCalculationFeatureImp::findFishboneImportedLateralsWellBoreParts(std::map<size_t, std::vector<WellBorePartForTransCalc> >& wellBorePartsInCells,
const RimWellPath* wellPath,
const RicExportCompletionDataSettingsUi& settings)
{
RiaEclipseUnitTools::UnitSystem unitSystem = settings.caseToApply->eclipseCaseData()->unitsType();
std::set<size_t> wellPathCells = RicWellPathExportCompletionDataFeature::findIntersectedCells(settings.caseToApply()->eclipseCaseData(),
wellPath->wellPathGeometry()->m_wellPathPoints);
bool isMainBore = false;
double diameter = wellPath->fishbonesCollection()->wellPathCollection()->holeDiameter(unitSystem);
for (const RimFishboneWellPath* fishbonesPath : wellPath->fishbonesCollection()->wellPathCollection()->wellPaths())
{
std::vector<WellPathCellIntersectionInfo> intersectedCells = RigWellPathIntersectionTools::findCellIntersectionInfosAlongPath(settings.caseToApply->eclipseCaseData(),
fishbonesPath->coordinates(),
fishbonesPath->measuredDepths());
for (auto& cell : intersectedCells)
{
if (wellPathCells.count(cell.globCellIndex) ) continue;
double skinFactor = wellPath->fishbonesCollection()->wellPathCollection()->skinFactor();
QString completionMetaData = fishbonesPath->name();
WellBorePartForTransCalc wellBorePart = WellBorePartForTransCalc(cell.intersectionLengthsInCellCS,
diameter / 2,
skinFactor,
isMainBore,
completionMetaData);
wellBorePartsInCells[cell.globCellIndex].push_back(wellBorePart);
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicFishbonesTransmissibilityCalculationFeatureImp::findMainWellBoreParts(std::map<size_t, std::vector<WellBorePartForTransCalc>>& wellBorePartsInCells,
const RimWellPath* wellPath,
const RicExportCompletionDataSettingsUi& settings)
{
RiaEclipseUnitTools::UnitSystem unitSystem = settings.caseToApply->eclipseCaseData()->unitsType();
bool isMainBore = true;
double holeDiameter = wellPath->fishbonesCollection()->mainBoreDiameter(unitSystem);
std::vector<double> wellPathMD = wellPath->wellPathGeometry()->m_measuredDepths;
double wellPathEndMD = 0.0;
if (wellPathMD.size() > 1) wellPathEndMD = wellPathMD.back();
std::pair< std::vector<cvf::Vec3d>, std::vector<double> > fishbonePerfWellPathCoords = wellPath->wellPathGeometry()->clippedPointSubset(wellPath->fishbonesCollection()->startMD(),
wellPathEndMD);
std::vector<WellPathCellIntersectionInfo> intersectedCellsIntersectionInfo = RigWellPathIntersectionTools::findCellIntersectionInfosAlongPath(settings.caseToApply->eclipseCaseData(),
fishbonePerfWellPathCoords.first,
fishbonePerfWellPathCoords.second);
for (auto& cell : intersectedCellsIntersectionInfo)
{
double skinFactor = wellPath->fishbonesCollection()->mainBoreSkinFactor();
QString completionMetaData = wellPath->name() + " main bore";
WellBorePartForTransCalc wellBorePart = WellBorePartForTransCalc(cell.intersectionLengthsInCellCS,
holeDiameter / 2,
skinFactor,
isMainBore,
completionMetaData);
wellBorePartsInCells[cell.globCellIndex].push_back(wellBorePart);
}
}

View File

@@ -1,78 +0,0 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "cvfBase.h"
#include "cvfVector3.h"
#include <vector>
#include <map>
#include <QString>
class RigCompletionData;
class RimWellPath;
class RicExportCompletionDataSettingsUi;
//==================================================================================================
///
//==================================================================================================
struct WellBorePartForTransCalc {
WellBorePartForTransCalc(cvf::Vec3d lengthsInCell,
double wellRadius,
double skinFactor,
bool isMainBore,
QString metaData)
: lengthsInCell(lengthsInCell),
wellRadius(wellRadius),
skinFactor(skinFactor),
isMainBore(isMainBore),
metaData(metaData)
{}
cvf::Vec3d lengthsInCell;
double wellRadius;
double skinFactor;
QString metaData;
bool isMainBore;
};
//==================================================================================================
///
//==================================================================================================
class RicFishbonesTransmissibilityCalculationFeatureImp
{
public:
static std::vector<RigCompletionData> generateFishboneCompdatValuesUsingAdjustedCellVolume(const RimWellPath* wellPath,
const RicExportCompletionDataSettingsUi& settings);
private:
static void findFishboneLateralsWellBoreParts(std::map<size_t, std::vector<WellBorePartForTransCalc> >& wellBorePartsInCells,
const RimWellPath* wellPath,
const RicExportCompletionDataSettingsUi& settings);
static void findFishboneImportedLateralsWellBoreParts(std::map<size_t, std::vector<WellBorePartForTransCalc> >& wellBorePartsInCells,
const RimWellPath* wellPath,
const RicExportCompletionDataSettingsUi& settings);
static void findMainWellBoreParts(std::map<size_t, std::vector<WellBorePartForTransCalc>>& wellBorePartsInCells,
const RimWellPath* wellPath,
const RicExportCompletionDataSettingsUi& settings);
};

View File

@@ -1,177 +0,0 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RifEclipseDataTableFormatter.h"
#include "RigWellLogExtractionTools.h"
#include "RigWellPathIntersectionTools.h"
#include "RigCompletionData.h"
#include "RicExportCompletionDataSettingsUi.h"
#include "cafCmdFeature.h"
#include "cvfBoundingBox.h"
class RigCell;
class RigEclipseCaseData;
class RigMainGrid;
class RimEclipseCase;
class RimFishbonesMultipleSubs;
class RimSimWellInView;
class RimWellPath;
//==================================================================================================
///
//==================================================================================================
struct WellSegmentLateralIntersection {
WellSegmentLateralIntersection(int segmentNumber,
int attachedSegmentNumber,
size_t globalCellIndex,
double length,
double depth,
const cvf::Vec3d& lengthsInCell)
: segmentNumber(segmentNumber),
attachedSegmentNumber(attachedSegmentNumber),
globalCellIndex(globalCellIndex),
mdFromPreviousIntersection(length),
tvdChangeFromPreviousIntersection(depth),
lengthsInCell(lengthsInCell),
mainBoreCell(false)
{}
int segmentNumber;
int attachedSegmentNumber;
size_t globalCellIndex;
bool mainBoreCell;
double mdFromPreviousIntersection;
double tvdChangeFromPreviousIntersection;
cvf::Vec3d lengthsInCell;
};
//==================================================================================================
///
//==================================================================================================
struct WellSegmentLateral {
WellSegmentLateral(size_t lateralIndex)
: lateralIndex(lateralIndex),
branchNumber(0)
{}
size_t lateralIndex;
int branchNumber;
std::vector<WellSegmentLateralIntersection> intersections;
};
//==================================================================================================
///
//==================================================================================================
struct WellSegmentLocation {
WellSegmentLocation(const RimFishbonesMultipleSubs* subs, double measuredDepth, double trueVerticalDepth, size_t subIndex, int segmentNumber = -1)
: fishbonesSubs(subs),
measuredDepth(measuredDepth),
trueVerticalDepth(trueVerticalDepth),
subIndex(subIndex),
segmentNumber(segmentNumber),
icdBranchNumber(-1),
icdSegmentNumber(-1)
{
}
const RimFishbonesMultipleSubs* fishbonesSubs;
double measuredDepth;
double trueVerticalDepth;
size_t subIndex;
int segmentNumber;
int icdBranchNumber;
int icdSegmentNumber;
std::vector<WellSegmentLateral> laterals;
};
//==================================================================================================
///
//==================================================================================================
class RicWellPathExportCompletionDataFeature : 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;
std::vector<RimWellPath*> selectedWellPaths();
std::vector<RimSimWellInView*> selectedSimWells();
bool noWellPathsSelectedDirectly();
public:
static std::vector<WellSegmentLocation> findWellSegmentLocations(const RimEclipseCase* caseToApply, const RimWellPath* wellPath);
static std::vector<WellSegmentLocation> findWellSegmentLocations(const RimEclipseCase* caseToApply, const RimWellPath* wellPath, const std::vector<RimFishbonesMultipleSubs*>& fishbonesSubs);
//functions also used by RicFishbonesTransmissibilityCalculationFeatureImp
static std::set<size_t> findIntersectedCells(const RigEclipseCaseData* grid, const std::vector<cvf::Vec3d>& coords);
static void markWellPathCells(const std::vector<size_t>& wellPathCells, std::vector<WellSegmentLocation>* locations);
static CellDirection calculateDirectionInCell(RimEclipseCase* eclipseCase, size_t globalCellIndex, const cvf::Vec3d& lengthsInCell);
static double calculateTransmissibility(RimEclipseCase* eclipseCase,
const RimWellPath* wellPath,
const cvf::Vec3d& internalCellLengths,
double skinFactor,
double wellRadius,
size_t globalCellIndex,
bool useLateralNTG,
size_t volumeScaleConstant = 1,
CellDirection directionForVolumeScaling = CellDirection::DIR_I);
static double calculateTransmissibilityAsEclipseDoes(RimEclipseCase* eclipseCase,
double skinFactor,
double wellRadius,
size_t globalCellIndex,
CellDirection direction);
static void exportCompletions(const std::vector<RimWellPath*>& wellPaths, const std::vector<RimSimWellInView*>& simWells, const RicExportCompletionDataSettingsUi& exportSettings);
private:
static RigCompletionData combineEclipseCellCompletions(const std::vector<RigCompletionData>& completions,
const RicExportCompletionDataSettingsUi& settings);
static void printCompletionsToFiles(const QString& exportFolder, const QString& fileName, std::vector<RigCompletionData>& completions, RicExportCompletionDataSettingsUi::CompdatExportType exportType);
static void printCompletionsToFile(const QString& folderName, const QString& fileName, const std::map<QString, std::vector<RigCompletionData>>& completionsPerGrid, RicExportCompletionDataSettingsUi::CompdatExportType exportType);
static std::vector<RigCompletionData> getCompletionsForWellAndCompletionType(const std::vector<RigCompletionData>& completions, const QString& wellName, RigCompletionData::CompletionType completionType);
static std::map<RigCompletionDataGridCell, std::vector<RigCompletionData> > getCompletionsForWell(const std::map<RigCompletionDataGridCell, std::vector<RigCompletionData>>& cellToCompletionMap, const QString& wellName);
static void generateCompdatTable(RifEclipseDataTableFormatter& formatter, const QString& gridName, const std::vector<RigCompletionData>& completionData);
static void generateWpimultTable(RifEclipseDataTableFormatter& formatter, const QString& gridName, const std::vector<RigCompletionData>& completionData);
static std::vector<RigCompletionData> generatePerforationsCompdatValues(const RimWellPath* wellPath, const RicExportCompletionDataSettingsUi& settings);
static bool wellSegmentLocationOrdering(const WellSegmentLocation& first, const WellSegmentLocation& second);
static bool isPointBetween(const cvf::Vec3d& pointA, const cvf::Vec3d& pointB, const cvf::Vec3d& needle);
static void assignLateralIntersections(const RimEclipseCase* caseToApply, WellSegmentLocation* location, int* branchNum, int* segmentNum);
static void assignLateralIntersectionsAndBranchAndSegmentNumbers(const RimEclipseCase* caseToApply, std::vector<WellSegmentLocation>* locations);
static void appendCompletionData(std::map<RigCompletionDataGridCell, std::vector<RigCompletionData> >* completionData, const std::vector<RigCompletionData>& data);
};

View File

@@ -1,393 +0,0 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RigCompletionData.h"
#include "RiaLogging.h"
#include "cvfAssert.h"
#include <QString>
#include <cmath> // Needed for HUGE_VAL on Linux
//==================================================================================================
///
//==================================================================================================
RigCompletionData::RigCompletionData(const QString wellName, const RigCompletionDataGridCell& cellIndex)
: m_wellName(wellName),
m_cellIndex(cellIndex),
m_saturation(HUGE_VAL),
m_transmissibility(HUGE_VAL),
m_diameter(HUGE_VAL),
m_kh(HUGE_VAL),
m_skinFactor(HUGE_VAL),
m_dFactor(HUGE_VAL),
m_direction(DIR_UNDEF),
m_connectionState(OPEN),
m_count(1),
m_wpimult(HUGE_VAL),
m_isMainBore(false),
m_readyForExport(false),
m_completionType(CT_UNDEFINED)
{
}
//==================================================================================================
///
//==================================================================================================
RigCompletionData::~RigCompletionData()
{
}
//==================================================================================================
///
//==================================================================================================
RigCompletionData::RigCompletionData(const RigCompletionData& other)
{
copy(*this, other);
}
//==================================================================================================
///
//==================================================================================================
RigCompletionData RigCompletionData::combine(const std::vector<RigCompletionData>& completions)
{
CVF_ASSERT(!completions.empty());
auto it = completions.cbegin();
RigCompletionData result(*it);
++it;
for (; it != completions.cend(); ++it)
{
if (it->completionType() != result.completionType())
{
RiaLogging::error(QString("Cannot combine completions of different types in same cell [%1, %2, %3]").arg(result.m_cellIndex.localCellIndexI()).arg(result.m_cellIndex.localCellIndexJ()).arg(result.m_cellIndex.localCellIndexK()));
continue;
}
if (onlyOneIsDefaulted(result.m_transmissibility, it->m_transmissibility))
{
RiaLogging::error("Transmissibility defaulted in one but not both, will produce erroneous result");
}
else
{
result.m_transmissibility += it->m_transmissibility;
}
result.m_metadata.reserve(result.m_metadata.size() + it->m_metadata.size());
result.m_metadata.insert(result.m_metadata.end(), it->m_metadata.begin(), it->m_metadata.end());
result.m_count += it->m_count;
}
return result;
}
//==================================================================================================
///
//==================================================================================================
bool RigCompletionData::operator<(const RigCompletionData& other) const
{
if (m_wellName != other.m_wellName)
{
return (m_wellName < other.m_wellName);
}
return m_cellIndex < other.m_cellIndex;
}
//==================================================================================================
///
//==================================================================================================
RigCompletionData& RigCompletionData::operator=(const RigCompletionData& other)
{
if (this != &other)
{
copy(*this, other);
}
return *this;
}
//==================================================================================================
///
//==================================================================================================
void RigCompletionData::setFromFracture(double transmissibility, double skinFactor)
{
m_completionType = FRACTURE;
m_transmissibility = transmissibility;
m_skinFactor = skinFactor;
}
//==================================================================================================
///
//==================================================================================================
void RigCompletionData::setTransAndWPImultBackgroundDataFromFishbone(double transmissibility,
double skinFactor,
double diameter,
CellDirection direction,
bool isMainBore)
{
m_completionType = FISHBONES;
m_transmissibility = transmissibility;
m_skinFactor = skinFactor;
m_diameter = diameter;
m_direction = direction;
m_isMainBore = isMainBore;
}
//==================================================================================================
///
//==================================================================================================
void RigCompletionData::setTransAndWPImultBackgroundDataFromPerforation(double transmissibility,
double skinFactor,
double diameter,
CellDirection direction)
{
m_completionType = PERFORATION;
m_transmissibility = transmissibility;
m_skinFactor = skinFactor;
m_diameter = diameter;
m_direction = direction;
m_isMainBore = true;
}
//==================================================================================================
///
//==================================================================================================
void RigCompletionData::setCombinedValuesExplicitTrans(double transmissibility,
CompletionType completionType)
{
m_completionType = completionType;
m_transmissibility = transmissibility;
m_readyForExport = true;
}
//==================================================================================================
///
//==================================================================================================
void RigCompletionData::setCombinedValuesImplicitTransWPImult(double wpimult,
CellDirection celldirection,
double skinFactor,
double wellDiameter,
CompletionType completionType)
{
m_wpimult = wpimult;
m_direction = celldirection;
m_completionType = completionType;
m_skinFactor = skinFactor;
m_diameter = wellDiameter;
m_readyForExport = true;
}
//==================================================================================================
///
//==================================================================================================
void RigCompletionData::addMetadata(const QString& name, const QString& comment)
{
m_metadata.push_back(RigCompletionMetaData(name, comment));
}
//==================================================================================================
///
//==================================================================================================
bool RigCompletionData::isDefaultValue(double val)
{
return val == HUGE_VAL;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const std::vector<RigCompletionMetaData>& RigCompletionData::metadata() const
{
return m_metadata;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const QString& RigCompletionData::wellName() const
{
return m_wellName;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const RigCompletionDataGridCell& RigCompletionData::completionDataGridCell() const
{
return m_cellIndex;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
WellConnectionState RigCompletionData::connectionState() const
{
return m_connectionState;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RigCompletionData::saturation() const
{
return m_saturation;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RigCompletionData::transmissibility() const
{
return m_transmissibility;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RigCompletionData::diameter() const
{
return m_diameter;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RigCompletionData::kh() const
{
return m_kh;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RigCompletionData::skinFactor() const
{
return m_skinFactor;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RigCompletionData::dFactor() const
{
return m_dFactor;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
CellDirection RigCompletionData::direction() const
{
return m_direction;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t RigCompletionData::count() const
{
return m_count;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RigCompletionData::wpimult() const
{
return m_wpimult;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RigCompletionData::CompletionType RigCompletionData::completionType() const
{
return m_completionType;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RigCompletionData::isMainBore() const
{
return m_isMainBore;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RigCompletionData::readyForExport() const
{
return m_readyForExport;
}
//==================================================================================================
///
//==================================================================================================
bool RigCompletionData::onlyOneIsDefaulted(double first, double second)
{
if (first == HUGE_VAL)
{
if (second == HUGE_VAL)
{
// Both have default values
return false;
}
else
{
// First has default value, second does not
return true;
}
}
if (second == HUGE_VAL)
{
// Second has default value, first does not
return true;
}
// Neither has default values
return false;
}
//==================================================================================================
///
//==================================================================================================
void RigCompletionData::copy(RigCompletionData& target, const RigCompletionData& from)
{
target.m_metadata = from.m_metadata;
target.m_wellName = from.m_wellName;
target.m_cellIndex = from.m_cellIndex;
target.m_connectionState = from.m_connectionState;
target.m_saturation = from.m_saturation;
target.m_transmissibility = from.m_transmissibility;
target.m_diameter = from.m_diameter;
target.m_kh = from.m_kh;
target.m_skinFactor = from.m_skinFactor;
target.m_dFactor = from.m_dFactor;
target.m_direction = from.m_direction;
target.m_isMainBore = from.m_isMainBore;
target.m_readyForExport = from.m_readyForExport;
target.m_count = from.m_count;
target.m_wpimult = from.m_wpimult;
target.m_completionType = from.m_completionType;
}

View File

@@ -1,146 +0,0 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RigCompletionDataGridCell.h"
#include <QString>
#include <vector>
class RimEclipseCase;
//==================================================================================================
///
//==================================================================================================
enum WellConnectionState {
OPEN,
SHUT,
AUTO,
};
//==================================================================================================
///
//==================================================================================================
enum CellDirection {
DIR_I,
DIR_J,
DIR_K,
DIR_UNDEF,
};
//==================================================================================================
///
//==================================================================================================
struct RigCompletionMetaData {
RigCompletionMetaData(const QString& name, const QString& comment) : name(name), comment(comment) {}
QString name;
QString comment;
};
//==================================================================================================
///
//==================================================================================================
class RigCompletionData
{
public:
enum CompletionType {
FISHBONES,
FRACTURE,
PERFORATION,
CT_UNDEFINED
};
RigCompletionData(const QString wellName, const RigCompletionDataGridCell& cellIndex);
~RigCompletionData();
RigCompletionData(const RigCompletionData& other);
static RigCompletionData combine(const std::vector<RigCompletionData>& completions);
bool operator<(const RigCompletionData& other) const;
RigCompletionData& operator=(const RigCompletionData& other);
void setFromFracture(double transmissibility, double skinFactor);
void setTransAndWPImultBackgroundDataFromFishbone(double transmissibility,
double skinFactor,
double diameter,
CellDirection direction,
bool isMainBore);
void setTransAndWPImultBackgroundDataFromPerforation(double transmissibility,
double skinFactor,
double diameter,
CellDirection direction);
void setCombinedValuesExplicitTrans(double transmissibility, CompletionType completionType);
void setCombinedValuesImplicitTransWPImult(double wpimult,
CellDirection celldirection,
double skinFactor,
double wellDiameter,
CompletionType completionType);
void addMetadata(const QString& name, const QString& comment);
static bool isDefaultValue(double val);
const std::vector<RigCompletionMetaData>& metadata() const;
const QString& wellName() const;
const RigCompletionDataGridCell& completionDataGridCell() const;
WellConnectionState connectionState() const;
double saturation() const;
double transmissibility() const;
double diameter() const; //TODO: should be ft or m
double kh() const;
double skinFactor() const;
double dFactor() const;
CellDirection direction() const;
size_t count() const;
double wpimult() const;
CompletionType completionType() const;
bool isMainBore() const;
bool readyForExport() const;
std::vector<RigCompletionMetaData> m_metadata;
private:
QString m_wellName;
RigCompletionDataGridCell m_cellIndex;
WellConnectionState m_connectionState;
double m_saturation; //TODO: remove, always use default in Eclipse?
double m_transmissibility;
double m_diameter;
double m_kh; //TODO: Remove, always use default in Eclipse?
double m_skinFactor;
double m_dFactor; //TODO: Remove, always use default in Eclipse?
CellDirection m_direction;
bool m_isMainBore; //to use mainbore for Eclipse calculation
bool m_readyForExport;
size_t m_count; //TODO: Remove, usage replaced by WPImult
double m_wpimult;
CompletionType m_completionType;
private:
static bool onlyOneIsDefaulted(double first, double second);
static void copy(RigCompletionData& target, const RigCompletionData& from);
};

View File

@@ -1,127 +0,0 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2018 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 "RigCompletionDataGridCell.h"
#include "RigMainGrid.h"
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RigCompletionDataGridCell::RigCompletionDataGridCell() {}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RigCompletionDataGridCell::RigCompletionDataGridCell(size_t globalCellIndex, const RigMainGrid* mainGrid)
: m_globalCellIndex(globalCellIndex)
{
if (mainGrid)
{
const RigCell& cell = mainGrid->globalCellArray()[globalCellIndex];
RigGridBase* grid = cell.hostGrid();
if (grid)
{
size_t gridLocalCellIndex = cell.gridLocalCellIndex();
size_t i = 0;
size_t j = 0;
size_t k = 0;
grid->ijkFromCellIndex(gridLocalCellIndex, &i, &j, &k);
m_localCellIndexI = i;
m_localCellIndexJ = j;
m_localCellIndexK = k;
if (grid != mainGrid)
{
m_lgrName = QString::fromStdString(grid->gridName());
}
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RigCompletionDataGridCell::operator==(const RigCompletionDataGridCell& other) const
{
return m_globalCellIndex == other.m_globalCellIndex;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RigCompletionDataGridCell::operator<(const RigCompletionDataGridCell& other) const
{
if (m_localCellIndexI != other.m_localCellIndexI) return m_localCellIndexI < other.m_localCellIndexI;
if (m_localCellIndexJ != other.m_localCellIndexJ) return m_localCellIndexJ < other.m_localCellIndexJ;
if (m_localCellIndexK != other.m_localCellIndexK) return m_localCellIndexK < other.m_localCellIndexK;
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t RigCompletionDataGridCell::globalCellIndex() const
{
return m_globalCellIndex;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t RigCompletionDataGridCell::localCellIndexI() const
{
return m_localCellIndexI;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t RigCompletionDataGridCell::localCellIndexJ() const
{
return m_localCellIndexJ;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t RigCompletionDataGridCell::localCellIndexK() const
{
return m_localCellIndexK;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RigCompletionDataGridCell::oneBasedLocalCellIndexString() const
{
QString text = QString("[%1, %2, %3]").arg(m_localCellIndexI + 1).arg(m_localCellIndexJ + 1).arg(m_localCellIndexK + 1);
return text;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RigCompletionDataGridCell::lgrName() const
{
return m_lgrName;
}

View File

@@ -1,56 +0,0 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2018 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 <QString>
class RigMainGrid;
//==================================================================================================
///
//==================================================================================================
class RigCompletionDataGridCell
{
public:
RigCompletionDataGridCell();
RigCompletionDataGridCell(size_t globalCellIndex, const RigMainGrid* mainGrid);
bool operator==(const RigCompletionDataGridCell& other) const;
bool operator<(const RigCompletionDataGridCell& other) const;
size_t globalCellIndex() const;
size_t localCellIndexI() const;
size_t localCellIndexJ() const;
size_t localCellIndexK() const;
QString oneBasedLocalCellIndexString() const;
QString lgrName() const;
private:
size_t m_globalCellIndex;
QString m_lgrName;
size_t m_localCellIndexI;
size_t m_localCellIndexJ;
size_t m_localCellIndexK;
};

View File

@@ -1,247 +0,0 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RigEclipseToStimPlanCellTransmissibilityCalculator.h"
#include "RigActiveCellInfo.h"
#include "RigCaseCellResultsData.h"
#include "RigCellGeometryTools.h"
#include "RigEclipseCaseData.h"
#include "RigFractureCell.h"
#include "RigFractureTransmissibilityEquations.h"
#include "RigMainGrid.h"
#include "RigResultAccessorFactory.h"
#include "RigHexIntersectionTools.h"
#include "RimEclipseCase.h"
#include "cvfGeometryTools.h"
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RigEclipseToStimPlanCellTransmissibilityCalculator::RigEclipseToStimPlanCellTransmissibilityCalculator(RimEclipseCase* caseToApply,
cvf::Mat4d fractureTransform,
double skinFactor,
double cDarcy,
const RigFractureCell& stimPlanCell)
: m_case(caseToApply),
m_fractureTransform(fractureTransform),
m_fractureSkinFactor(skinFactor),
m_cDarcy(cDarcy),
m_stimPlanCell(stimPlanCell)
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const std::vector<size_t>& RigEclipseToStimPlanCellTransmissibilityCalculator::globalIndeciesToContributingEclipseCells()
{
if (m_globalIndeciesToContributingEclipseCells.size() < 1)
{
calculateStimPlanCellsMatrixTransmissibility();
}
return m_globalIndeciesToContributingEclipseCells;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const std::vector<double>& RigEclipseToStimPlanCellTransmissibilityCalculator::contributingEclipseCellTransmissibilities()
{
if (m_globalIndeciesToContributingEclipseCells.size() < 1)
{
calculateStimPlanCellsMatrixTransmissibility();
}
return m_contributingEclipseCellTransmissibilities;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigEclipseToStimPlanCellTransmissibilityCalculator::calculateStimPlanCellsMatrixTransmissibility()
{
// Not calculating flow into fracture if stimPlan cell cond value is 0 (assumed to be outside the fracture):
if (m_stimPlanCell.getConductivtyValue() < 1e-7) return;
const RigEclipseCaseData* eclipseCaseData = m_case->eclipseCaseData();
RiaDefines::PorosityModelType porosityModel = RiaDefines::MATRIX_MODEL;
cvf::ref<RigResultAccessor> dataAccessObjectDx = loadResultAndCreateResultAccessor(m_case, porosityModel, "DX");
cvf::ref<RigResultAccessor> dataAccessObjectDy = loadResultAndCreateResultAccessor(m_case, porosityModel, "DY");
cvf::ref<RigResultAccessor> dataAccessObjectDz = loadResultAndCreateResultAccessor(m_case, porosityModel, "DZ");
cvf::ref<RigResultAccessor> dataAccessObjectPermX = loadResultAndCreateResultAccessor(m_case, porosityModel, "PERMX");
cvf::ref<RigResultAccessor> dataAccessObjectPermY = loadResultAndCreateResultAccessor(m_case, porosityModel, "PERMY");
cvf::ref<RigResultAccessor> dataAccessObjectPermZ = loadResultAndCreateResultAccessor(m_case, porosityModel, "PERMZ");
cvf::ref<RigResultAccessor> dataAccessObjectNTG = loadResultAndCreateResultAccessor(m_case, porosityModel, "NTG");
const RigActiveCellInfo* activeCellInfo = eclipseCaseData->activeCellInfo(porosityModel);
std::vector<cvf::Vec3d> stimPlanPolygonTransformed;
for (cvf::Vec3d v : m_stimPlanCell.getPolygon())
{
v.transformPoint(m_fractureTransform);
stimPlanPolygonTransformed.push_back(v);
}
std::vector<size_t> fracCells = getPotentiallyFracturedCellsForPolygon(stimPlanPolygonTransformed);
for (size_t fracCell : fracCells)
{
bool cellIsActive = activeCellInfo->isActive(fracCell);
if (!cellIsActive) continue;
double permX = dataAccessObjectPermX->cellScalarGlobIdx(fracCell);
double permY = dataAccessObjectPermY->cellScalarGlobIdx(fracCell);
double permZ = dataAccessObjectPermZ->cellScalarGlobIdx(fracCell);
double dx = dataAccessObjectDx->cellScalarGlobIdx(fracCell);
double dy = dataAccessObjectDy->cellScalarGlobIdx(fracCell);
double dz = dataAccessObjectDz->cellScalarGlobIdx(fracCell);
double NTG = 1.0;
if (dataAccessObjectNTG.notNull())
{
NTG = dataAccessObjectNTG->cellScalarGlobIdx(fracCell);
}
const RigMainGrid* mainGrid = m_case->eclipseCaseData()->mainGrid();
std::array<cvf::Vec3d, 8> hexCorners;
mainGrid->cellCornerVertices(fracCell, hexCorners.data());
std::vector<std::vector<cvf::Vec3d> > planeCellPolygons;
bool isPlanIntersected = RigHexIntersectionTools::planeHexIntersectionPolygons(hexCorners, m_fractureTransform, planeCellPolygons);
if (!isPlanIntersected || planeCellPolygons.size() == 0) continue;
cvf::Vec3d localX;
cvf::Vec3d localY;
cvf::Vec3d localZ;
RigCellGeometryTools::findCellLocalXYZ(hexCorners, localX, localY, localZ);
//Transform planCell polygon(s) and averageZdirection to x/y coordinate system (where fracturePolygon already is located)
cvf::Mat4d invertedTransMatrix = m_fractureTransform.getInverted();
for (std::vector<cvf::Vec3d> & planeCellPolygon : planeCellPolygons)
{
for (cvf::Vec3d& v : planeCellPolygon)
{
v.transformPoint(invertedTransMatrix);
}
}
std::vector<std::vector<cvf::Vec3d> > polygonsForStimPlanCellInEclipseCell;
cvf::Vec3d areaVector;
std::vector<cvf::Vec3d> stimPlanPolygon = m_stimPlanCell.getPolygon();
for (std::vector<cvf::Vec3d> planeCellPolygon : planeCellPolygons)
{
std::vector<std::vector<cvf::Vec3d> >clippedPolygons = RigCellGeometryTools::intersectPolygons(planeCellPolygon, stimPlanPolygon);
for (std::vector<cvf::Vec3d> clippedPolygon : clippedPolygons)
{
polygonsForStimPlanCellInEclipseCell.push_back(clippedPolygon);
}
}
if (polygonsForStimPlanCellInEclipseCell.size() == 0) continue;
double area;
std::vector<double> areaOfFractureParts;
double length;
std::vector<double> lengthXareaOfFractureParts;
double Ax = 0.0, Ay = 0.0, Az = 0.0;
for (std::vector<cvf::Vec3d> fracturePartPolygon : polygonsForStimPlanCellInEclipseCell)
{
areaVector = cvf::GeometryTools::polygonAreaNormal3D(fracturePartPolygon);
area = areaVector.length();
areaOfFractureParts.push_back(area);
length = RigCellGeometryTools::polygonLengthInLocalXdirWeightedByArea(fracturePartPolygon);
lengthXareaOfFractureParts.push_back(length * area);
cvf::Plane fracturePlane;
fracturePlane.setFromPointAndNormal(static_cast<cvf::Vec3d>(m_fractureTransform.translation()),
static_cast<cvf::Vec3d>(m_fractureTransform.col(2)));
Ax += fabs(area*(fracturePlane.normal().dot(localY)));
Ay += fabs(area*(fracturePlane.normal().dot(localX)));
Az += fabs(area*(fracturePlane.normal().dot(localZ)));
}
double fractureArea = 0.0;
for (double area : areaOfFractureParts) fractureArea += area;
double totalAreaXLength = 0.0;
for (double lengtXarea : lengthXareaOfFractureParts) totalAreaXLength += lengtXarea;
double fractureAreaWeightedlength = totalAreaXLength / fractureArea;
double transmissibility_X = RigFractureTransmissibilityEquations::matrixToFractureTrans(permY, NTG, Ay, dx, m_fractureSkinFactor, fractureAreaWeightedlength, m_cDarcy);
double transmissibility_Y = RigFractureTransmissibilityEquations::matrixToFractureTrans(permX, NTG, Ax, dy, m_fractureSkinFactor, fractureAreaWeightedlength, m_cDarcy);
double transmissibility_Z = RigFractureTransmissibilityEquations::matrixToFractureTrans(permZ, 1.0, Az, dz, m_fractureSkinFactor, fractureAreaWeightedlength, m_cDarcy);
double transmissibility = sqrt(transmissibility_X * transmissibility_X
+ transmissibility_Y * transmissibility_Y
+ transmissibility_Z * transmissibility_Z);
m_globalIndeciesToContributingEclipseCells.push_back(fracCell);
m_contributingEclipseCellTransmissibilities.push_back(transmissibility);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<size_t> RigEclipseToStimPlanCellTransmissibilityCalculator::getPotentiallyFracturedCellsForPolygon(std::vector<cvf::Vec3d> polygon)
{
std::vector<size_t> cellIndices;
const RigMainGrid* mainGrid = m_case->eclipseCaseData()->mainGrid();
if (!mainGrid) return cellIndices;
cvf::BoundingBox polygonBBox;
for (cvf::Vec3d nodeCoord : polygon) polygonBBox.add(nodeCoord);
mainGrid->findIntersectingCells(polygonBBox, &cellIndices);
return cellIndices;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::ref<RigResultAccessor> RigEclipseToStimPlanCellTransmissibilityCalculator::loadResultAndCreateResultAccessor(
RimEclipseCase* eclipseCase,
RiaDefines::PorosityModelType porosityModel,
const QString& uiResultName)
{
CVF_ASSERT(eclipseCase);
RigCaseCellResultsData* gridCellResults = eclipseCase->results(porosityModel);
// Calling this function will force loading of result from file
gridCellResults->findOrLoadScalarResult(RiaDefines::STATIC_NATIVE, uiResultName);
const RigEclipseCaseData* eclipseCaseData = eclipseCase->eclipseCaseData();
// Create result accessor object for main grid at time step zero (static result date is always at first time step
return RigResultAccessorFactory::createFromUiResultName(eclipseCaseData, 0, porosityModel, 0, uiResultName);
}

View File

@@ -1,71 +0,0 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RiaPorosityModel.h"
#include "cvfBase.h"
#include "cvfObject.h"
#include "cvfMatrix4.h"
#include <vector>
class QString;
class RimEclipseCase;
class RigFractureCell;
class RigEclipseCaseData;
class RigResultAccessor;
//==================================================================================================
///
//==================================================================================================
class RigEclipseToStimPlanCellTransmissibilityCalculator
{
public:
explicit RigEclipseToStimPlanCellTransmissibilityCalculator(RimEclipseCase* caseToApply,
cvf::Mat4d fractureTransform,
double skinFactor,
double cDarcy,
const RigFractureCell& stimPlanCell);
const std::vector<size_t>& globalIndeciesToContributingEclipseCells();
const std::vector<double>& contributingEclipseCellTransmissibilities();
private:
void calculateStimPlanCellsMatrixTransmissibility();
std::vector<size_t> getPotentiallyFracturedCellsForPolygon(std::vector<cvf::Vec3d> polygon);
static cvf::ref<RigResultAccessor>
loadResultAndCreateResultAccessor(RimEclipseCase* eclipseCase,
RiaDefines::PorosityModelType porosityModel,
const QString& uiResultName);
private:
RimEclipseCase* m_case;
double m_cDarcy;
double m_fractureSkinFactor;
cvf::Mat4d m_fractureTransform;
const RigFractureCell& m_stimPlanCell;
std::vector<size_t> m_globalIndeciesToContributingEclipseCells;
std::vector<double> m_contributingEclipseCellTransmissibilities;
};

View File

@@ -1,132 +0,0 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RigFractureTransmissibilityEquations.h"
#include "cvfBase.h"
#include "cvfMath.h"
#include <cmath>
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RigFractureTransmissibilityEquations::centerToEdgeFractureCellTrans(double conductivity,
double sideLengthParallellTrans,
double sideLengthNormalTrans,
double cDarcyForRelevantUnit)
{
double transmissibility = cDarcyForRelevantUnit * conductivity * sideLengthNormalTrans / (sideLengthParallellTrans / 2);
return transmissibility;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RigFractureTransmissibilityEquations::centerToCenterFractureCellTrans(double conductivityCell1,
double sideLengthParallellTransCell1,
double sideLengthNormalTransCell1,
double conductivityCell2,
double sideLengthParallellTransCell2,
double sideLengthNormalTransCell2,
double cDarcyForRelevantUnit)
{
double transCell1 = centerToEdgeFractureCellTrans(conductivityCell1, sideLengthParallellTransCell1, sideLengthNormalTransCell1, cDarcyForRelevantUnit);
double transCell2 = centerToEdgeFractureCellTrans(conductivityCell2, sideLengthParallellTransCell2, sideLengthNormalTransCell2, cDarcyForRelevantUnit);
double totalTrans = 1 / ( (1 / transCell1) + (1 / transCell2));
return totalTrans;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RigFractureTransmissibilityEquations::fractureCellToWellRadialTrans(double fractureCellConductivity,
double fractureCellSizeX,
double fractureCellSizeZ,
double wellRadius,
double skinFactor,
double cDarcyForRelevantUnit)
{
double ro = 0.14 * cvf::Math::sqrt(
pow(fractureCellSizeX, 2.0) + pow(fractureCellSizeZ, 2));
if (ro < (wellRadius * 1.01))
{
ro = wellRadius * 1.01;
}
double Tc = 2 * cvf::PI_D * cDarcyForRelevantUnit * fractureCellConductivity /
(log(ro / wellRadius) + skinFactor );
CVF_TIGHT_ASSERT(Tc > 0);
return Tc;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RigFractureTransmissibilityEquations::fractureCellToWellLinearTrans(double fractureCellConductivity,
double fractureCellSizeX,
double fractureCellSizeZ,
double perforationLengthVertical,
double perforationLengthHorizontal,
double perforationEfficiency,
double skinfactor,
double cDarcyForRelevantUnit)
{
double TcPrefix = 8 * cDarcyForRelevantUnit * fractureCellConductivity;
double DzPerf = perforationLengthVertical * perforationEfficiency;
double DxPerf = perforationLengthHorizontal * perforationEfficiency;
double TcZ = TcPrefix * DzPerf /
(fractureCellSizeX + skinfactor * DzPerf / cvf::PI_D);
double TcX = TcPrefix * DxPerf /
(fractureCellSizeZ + skinfactor* DxPerf / cvf::PI_D);
double Tc = cvf::Math::sqrt(pow(TcX, 2) + pow(TcZ, 2));
return Tc;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RigFractureTransmissibilityEquations::matrixToFractureTrans(double perm,
double NTG,
double A,
double cellSizeLength,
double skinfactor,
double fractureAreaWeightedlength,
double cDarcy)
{
double transmissibility;
double slDivPi = 0.0;
if ( cvf::Math::abs(skinfactor) > 1e-9)
{
slDivPi = (skinfactor * fractureAreaWeightedlength) / cvf::PI_D;
}
transmissibility = 8 * cDarcy * (perm * NTG) * A / (cellSizeLength + slDivPi);
CVF_ASSERT(transmissibility == transmissibility);
return transmissibility;
}

View File

@@ -1,63 +0,0 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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
class RigFractureTransmissibilityEquations
{
public:
static double centerToEdgeFractureCellTrans(double conductivity,
double sideLengthParallellTrans,
double sideLengthNormalTrans,
double cDarcyForRelevantUnit);
static double centerToCenterFractureCellTrans(double conductivityCell1,
double sideLengthParallellTransCell1,
double sideLengthNormalTransCell1,
double conductivityCell2,
double sideLengthParallellTransCell2,
double sideLengthNormalTransCell2,
double cDarcyForRelevantUnit);
static double fractureCellToWellRadialTrans(double fractureCellConductivity,
double fractureCellSizeX,
double fractureCellSizeZ,
double wellRadius,
double skinFactor,
double cDarcyForRelevantUnit);
static double fractureCellToWellLinearTrans(double fractureConductivity,
double fractureCellSizeX,
double fractureCellSizeZ,
double perforationLengthVertical,
double perforationLengthHorizontal,
double perforationEfficiency,
double skinfactor,
double cDarcyForRelevantUnit);
static double matrixToFractureTrans(double permX,
double NTG,
double Ay,
double dx,
double skinfactor,
double fractureAreaWeightedlength,
double cDarcy);
};

View File

@@ -1,271 +0,0 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RigTransmissibilityCondenser.h"
#include "RiaLogging.h"
#include <Eigen/Core>
#include <Eigen/LU>
#include <iomanip>
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigTransmissibilityCondenser::addNeighborTransmissibility(CellAddress cell1, CellAddress cell2, double transmissibility)
{
if (transmissibility < 1e-9) return;
m_condensedTransmissibilities.clear();
m_externalCellAddrSet.clear();
if ( cell1 < cell2 )
m_neighborTransmissibilities[cell1][cell2] += transmissibility;
else
m_neighborTransmissibilities[cell2][cell1] += transmissibility;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<RigTransmissibilityCondenser::CellAddress> RigTransmissibilityCondenser::externalCells()
{
calculateCondensedTransmissibilitiesIfNeeded();
return m_externalCellAddrSet;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RigTransmissibilityCondenser::condensedTransmissibility(CellAddress externalCell1, CellAddress externalCell2)
{
CAF_ASSERT(!(externalCell1 == externalCell2));
calculateCondensedTransmissibilitiesIfNeeded();
if ( externalCell2 < externalCell1 ) std::swap(externalCell1, externalCell2);
const auto& adrToAdrTransMapPair = m_condensedTransmissibilities.find(externalCell1);
if ( adrToAdrTransMapPair != m_condensedTransmissibilities.end() )
{
const auto& adrTransPair = adrToAdrTransMapPair->second.find(externalCell2);
if ( adrTransPair != adrToAdrTransMapPair->second.end() )
{
return adrTransPair->second;
}
}
return 0.0;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigTransmissibilityCondenser::calculateCondensedTransmissibilitiesIfNeeded()
{
if (m_condensedTransmissibilities.size()) return;
// Find all equations, and their total ordering
union
{
int idxToFirstExternalEquation;
int internalEquationCount;
};
idxToFirstExternalEquation = -1;
int totalEquationCount = -1;
std::map<CellAddress, int> cellAddressToEqIdxMap;
std::vector<CellAddress> eqIdxToCellAddressMapping;
{
for ( const auto& adrEqIdxPair : m_neighborTransmissibilities )
{
cellAddressToEqIdxMap.insert({ adrEqIdxPair.first, -1 });
for ( const auto& adrTranspair : adrEqIdxPair.second )
{
cellAddressToEqIdxMap.insert({ adrTranspair.first, -1 });
}
}
int currentEqIdx = 0;
for ( auto& adrEqIdxPair : cellAddressToEqIdxMap)
{
adrEqIdxPair.second = currentEqIdx;
eqIdxToCellAddressMapping.push_back(adrEqIdxPair.first);
if ( idxToFirstExternalEquation == -1 && adrEqIdxPair.first.m_isExternal )
{
idxToFirstExternalEquation = currentEqIdx;
}
++currentEqIdx;
}
totalEquationCount = currentEqIdx;
}
CAF_ASSERT(idxToFirstExternalEquation != -1);
using namespace Eigen;
MatrixXd totalSystem = MatrixXd::Zero(totalEquationCount, totalEquationCount);
for (const auto& adrToAdrTransMapPair : m_neighborTransmissibilities)
{
CAF_ASSERT(cellAddressToEqIdxMap.count(adrToAdrTransMapPair.first)); // Remove when stabilized
int c1EquationIdx = cellAddressToEqIdxMap[adrToAdrTransMapPair.first];
for (const auto& adrTranspair : adrToAdrTransMapPair.second)
{
CAF_ASSERT(cellAddressToEqIdxMap.count(adrTranspair.first)); // Remove when stabilized
int c2EquationIdx = cellAddressToEqIdxMap[adrTranspair.first];
totalSystem(c1EquationIdx, c2EquationIdx) += adrTranspair.second;
totalSystem(c2EquationIdx, c1EquationIdx) += adrTranspair.second;
totalSystem(c1EquationIdx, c1EquationIdx) -= adrTranspair.second;
totalSystem(c2EquationIdx, c2EquationIdx) -= adrTranspair.second;
}
++c1EquationIdx;
}
// std::cout << "T = " << std::endl << totalSystem << std::endl;
int externalEquationCount = totalEquationCount - internalEquationCount;
MatrixXd condensedSystem = totalSystem.bottomRightCorner(externalEquationCount, externalEquationCount)
- totalSystem.bottomLeftCorner(externalEquationCount, internalEquationCount)
* totalSystem.topLeftCorner(internalEquationCount, internalEquationCount).inverse()
* totalSystem.topRightCorner(internalEquationCount, externalEquationCount );
// std::cout << "Te = " << std::endl << condensedSystem << std::endl << std::endl;
for (int exEqIdx = 0; exEqIdx < externalEquationCount; ++exEqIdx)
{
for (int exColIdx = exEqIdx +1; exColIdx < externalEquationCount; ++exColIdx)
{
double T = condensedSystem(exEqIdx, exColIdx);
//if (T != 0.0)
{
CellAddress cell1 = eqIdxToCellAddressMapping[exEqIdx + internalEquationCount];
CellAddress cell2 = eqIdxToCellAddressMapping[exColIdx + internalEquationCount];
if (cell1 < cell2) m_condensedTransmissibilities[cell1][cell2] = T;
else m_condensedTransmissibilities[cell2][cell1] = T;
m_externalCellAddrSet.insert(cell1);
m_externalCellAddrSet.insert(cell2);
}
}
}
}
#include "RimStimPlanFractureTemplate.h"
#include "RigMainGrid.h"
#include "RigFractureCell.h"
void printCellAddress(std::stringstream& str,
const RigMainGrid* mainGrid,
const RigFractureGrid* fractureGrid,
RigTransmissibilityCondenser::CellAddress cellAddr)
{
using CellAddress = RigTransmissibilityCondenser::CellAddress;
str << (cellAddr.m_isExternal ? "E " : "I ");
switch (cellAddr.m_cellIndexSpace) {
case CellAddress::ECLIPSE:
{
if (cellAddr.m_globalCellIdx > mainGrid->cellCount())
{
str << "ECL - LGR CELL ";
}
else
{
str << "ECL ";
size_t i, j, k;
mainGrid->ijkFromCellIndex(cellAddr.m_globalCellIdx, &i, &j, &k);
str << std::setw(5) << i+1 << std::setw(5) << j+1 << std::setw(5) << k+1;
}
}
break;
case CellAddress::STIMPLAN:
{
str << "STP ";
const RigFractureCell& stpCell = fractureGrid->cellFromIndex(cellAddr.m_globalCellIdx);
str << std::setw(5) << stpCell.getI()+1 << std::setw(5) << stpCell.getJ()+1 << std::setw(5) << " ";
}
break;
case CellAddress::WELL:
{
str << "WEL ";
str << std::setw(5) << cellAddr.m_globalCellIdx << std::setw(5) << " " << std::setw(5) << " ";
}
break;
}
str << " ";
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::string RigTransmissibilityCondenser::neighborTransDebugOutput(const RigMainGrid* mainGrid, const RigFractureGrid* fractureGrid)
{
std::stringstream debugText;
for ( const auto& adrEqIdxPair : m_neighborTransmissibilities )
{
for (const auto& adrTransPair :adrEqIdxPair.second)
{
debugText << "-- ";
printCellAddress(debugText, mainGrid, fractureGrid, adrEqIdxPair.first);
printCellAddress(debugText, mainGrid, fractureGrid, adrTransPair.first);
debugText << " Trans: " << std::setprecision(10) << std::fixed << adrTransPair.second;
debugText << std::endl;
}
}
return debugText.str();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::string RigTransmissibilityCondenser::condensedTransDebugOutput(const RigMainGrid* mainGrid, const RigFractureGrid* fractureGrid)
{
std::stringstream debugText;
for ( const auto& adrEqIdxPair : m_condensedTransmissibilities )
{
for (const auto& adrTransPair :adrEqIdxPair.second)
{
debugText << "-- ";
printCellAddress(debugText, mainGrid, fractureGrid, adrEqIdxPair.first);
printCellAddress(debugText, mainGrid, fractureGrid, adrTransPair.first);
debugText << " Trans: " << std::setprecision(10) << std::fixed << adrTransPair.second;
debugText << std::endl;
}
}
return debugText.str();
}

View File

@@ -1,87 +0,0 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "cafAssert.h"
#include <map>
#include <vector>
#include <set>
class RigMainGrid;
class RimStimPlanFractureTemplate;
class RigFractureGrid;
class RigTransmissibilityCondenser
{
public:
class CellAddress
{
public:
enum CellIndexSpace { ECLIPSE, STIMPLAN, WELL};
CellAddress(): m_isExternal(false),
m_cellIndexSpace(STIMPLAN),
m_globalCellIdx(-1)
{}
CellAddress(bool isExternal,
CellIndexSpace cellType,
size_t globalCellIdx)
: m_isExternal(isExternal),
m_cellIndexSpace(cellType),
m_globalCellIdx(globalCellIdx)
{}
bool m_isExternal;
CellIndexSpace m_cellIndexSpace;
size_t m_globalCellIdx;
bool operator==(const CellAddress& o)
{
return (m_isExternal == o.m_isExternal) && (m_cellIndexSpace == o.m_cellIndexSpace) && (m_globalCellIdx == o.m_globalCellIdx);
}
// Ordering external after internal is important for the matrix order internally
bool operator<(const CellAddress& other) const
{
if (m_isExternal != other.m_isExternal) return !m_isExternal; // Internal cells < External cells
if (m_cellIndexSpace != other.m_cellIndexSpace)return m_cellIndexSpace < other.m_cellIndexSpace; // Eclipse < StimPlan
if (m_globalCellIdx != other.m_globalCellIdx) return m_globalCellIdx < other.m_globalCellIdx;
return false;
}
};
void addNeighborTransmissibility(CellAddress cell1, CellAddress cell2, double transmissibility);
std::set<CellAddress> externalCells();
double condensedTransmissibility( CellAddress externalCell1, CellAddress externalCell2);
std::string neighborTransDebugOutput(const RigMainGrid* mainGrid, const RigFractureGrid* fractureGrid);
std::string condensedTransDebugOutput(const RigMainGrid* mainGrid, const RigFractureGrid* fractureGrid);
private:
void calculateCondensedTransmissibilitiesIfNeeded();
std::map<CellAddress, std::map<CellAddress, double> > m_neighborTransmissibilities;
std::map<CellAddress, std::map<CellAddress, double> > m_condensedTransmissibilities;
std::set<CellAddress> m_externalCellAddrSet;
};

View File

@@ -1,226 +0,0 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RigWellPathStimplanIntersector.h"
#include "RigCellGeometryTools.h"
#include "RigFractureCell.h"
#include "RigFractureGrid.h"
#include "RigWellPath.h"
#include "RimFracture.h"
#include "RimFractureTemplate.h"
#include "RimSimWellFracture.h"
#include "RimStimPlanFractureTemplate.h"
#include "cvfBase.h"
#include "cvfMath.h"
#include "cvfMatrix4.h"
#include <cmath>
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RigWellPathStimplanIntersector::RigWellPathStimplanIntersector(const RigWellPath* wellpathGeom, const RimFracture* rimFracture)
{
std::vector<cvf::Vec3d> wellPathPoints = wellpathGeom->wellPathPointsIncludingInterpolatedIntersectionPoint(rimFracture->fractureMD());
cvf::Mat4d fractureXf = rimFracture->transformMatrix();
double wellRadius = rimFracture->wellRadius(rimFracture->fractureUnit());
std::vector<std::vector<cvf::Vec3d> > stpCellPolygons;
{
RimFractureTemplate* fractureTemplate = rimFracture->fractureTemplate();
if(fractureTemplate)
{
const std::vector<RigFractureCell>& stpCells = fractureTemplate->fractureGrid()->fractureCells();
for ( const auto& stpCell: stpCells ) stpCellPolygons.push_back(stpCell.getPolygon());
}
}
double perforationLength = rimFracture->perforationLength();
calculate(fractureXf, wellPathPoints, wellRadius, perforationLength, stpCellPolygons, m_stimPlanCellIdxToIntersectionInfoMap);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const std::map<size_t, RigWellPathStimplanIntersector::RigWellPathStimplanIntersector::WellCellIntersection >& RigWellPathStimplanIntersector::intersections() const
{
return m_stimPlanCellIdxToIntersectionInfoMap;
}
//--------------------------------------------------------------------------------------------------
/// Todo: Use only the perforated parts of the well path
//--------------------------------------------------------------------------------------------------
void RigWellPathStimplanIntersector::calculate(const cvf::Mat4d &fractureXf,
const std::vector<cvf::Vec3d>& wellPathPointsOrg,
double wellRadius,
double perforationLength,
const std::vector<std::vector<cvf::Vec3d> >& stpCellPolygons,
std::map<size_t, WellCellIntersection>& m_stimPlanCellIdxToIntersectionInfoMap)
{
cvf::Mat4d toFractureXf = fractureXf.getInverted();
std::vector<cvf::Vec3d> perforationLengthBoundingBoxPolygon;
double cicleRadius = perforationLength / 2;
int pointsInCirclePolygon = 20;
for (int i = 0; i < pointsInCirclePolygon; i++)
{
double x = cicleRadius * cvf::Math::cos(i * (2 * cvf::PI_D / pointsInCirclePolygon));
double y = cicleRadius * cvf::Math::sin(i * (2 * cvf::PI_D / pointsInCirclePolygon));
perforationLengthBoundingBoxPolygon.push_back(cvf::Vec3d(x, y, 0));
}
// Convert well path to fracture template system
std::vector<cvf::Vec3d> fractureRelativeWellPathPoints;
for ( auto & wellPPoint : wellPathPointsOrg ) fractureRelativeWellPathPoints.push_back(wellPPoint.getTransformedPoint( toFractureXf));
// Clip well path to fracture domain
std::vector<std::vector<cvf::Vec3d> > wellPathPartsWithinFracture =
RigCellGeometryTools::clipPolylineByPolygon(fractureRelativeWellPathPoints,
perforationLengthBoundingBoxPolygon,
RigCellGeometryTools::INTERPOLATE_LINE_Z);
// Remove the part of the well path that is more than well radius away from the fracture plane
std::vector< std::vector< cvf::Vec3d > > intersectingWellPathParts;
for ( const auto& part : wellPathPartsWithinFracture )
{
std::vector< cvf::Vec3d > currentIntersectingWpPart;
for ( size_t vxIdx = 0; vxIdx < part.size() -1; ++vxIdx )
{
double thisAbsZ = fabs(part[vxIdx].z());
double nextAbsZ = fabs(part[vxIdx + 1].z());
double thisZ = part[vxIdx].z();
double nextZ = part[vxIdx + 1].z();
if ( thisAbsZ >= wellRadius && nextAbsZ >= wellRadius )
{
if ( (thisZ >= 0 && nextZ >= 0)
|| (thisZ <= 0 && nextZ <= 0 ) )
{
continue; // Outside
}
else // In and out
{
{
double wellRadiusDistFromPlane = thisZ > 0 ? wellRadius: -wellRadius;
double fraction = (wellRadiusDistFromPlane - thisZ)/ (nextZ - thisZ);
cvf::Vec3d intersectPoint = part[vxIdx] + fraction * (part[vxIdx+1] - part[vxIdx]);
currentIntersectingWpPart.push_back(intersectPoint);
}
{
double wellRadiusDistFromPlane = nextZ > 0 ? wellRadius: -wellRadius;
double fraction = (wellRadiusDistFromPlane - thisZ)/ (nextZ - thisZ);
cvf::Vec3d intersectPoint = part[vxIdx] + fraction * (part[vxIdx+1] - part[vxIdx]);
currentIntersectingWpPart.push_back(intersectPoint);
intersectingWellPathParts.push_back(currentIntersectingWpPart);
currentIntersectingWpPart.clear();
}
continue;
}
}
if ( thisAbsZ < wellRadius && nextAbsZ < wellRadius ) // Inside
{
currentIntersectingWpPart.push_back(part[vxIdx]);
continue;
}
if ( thisAbsZ < wellRadius && nextAbsZ >= wellRadius ) // Going out
{
currentIntersectingWpPart.push_back(part[vxIdx]);
double wellRadiusDistFromPlane = nextZ > 0 ? wellRadius: -wellRadius;
double fraction = (wellRadiusDistFromPlane - thisZ)/ (nextZ - thisZ);
cvf::Vec3d intersectPoint = part[vxIdx] + fraction * (part[vxIdx+1] - part[vxIdx]);
currentIntersectingWpPart.push_back(intersectPoint);
intersectingWellPathParts.push_back(currentIntersectingWpPart);
currentIntersectingWpPart.clear();
continue;
}
if ( thisAbsZ >= wellRadius && nextAbsZ < wellRadius ) // Going in
{
double wellRadiusDistFromPlane = thisZ > 0 ? wellRadius: -wellRadius;
double fraction = (wellRadiusDistFromPlane - thisZ)/ (nextZ - thisZ);
cvf::Vec3d intersectPoint = part[vxIdx] + fraction * (part[vxIdx+1] - part[vxIdx]);
currentIntersectingWpPart.push_back(intersectPoint);
continue;
}
}
// Add last point if it is within the radius
if (part.size() > 1 && fabs(part.back().z()) < wellRadius)
{
currentIntersectingWpPart.push_back(part.back());
}
if ( !currentIntersectingWpPart.empty() )
{
intersectingWellPathParts.push_back(currentIntersectingWpPart);
}
}
// Find the StimPlan cells touched by the intersecting well path parts
for ( size_t cIdx = 0; cIdx < stpCellPolygons.size(); ++ cIdx )
{
const std::vector<cvf::Vec3d>& cellPolygon = stpCellPolygons[cIdx];
for ( const auto& wellpathPart :intersectingWellPathParts )
{
std::vector<std::vector<cvf::Vec3d> > wellPathPartsInPolygon =
RigCellGeometryTools::clipPolylineByPolygon(wellpathPart,
cellPolygon,
RigCellGeometryTools::USE_HUGEVAL);
for ( const auto& wellPathPartInCell: wellPathPartsInPolygon )
{
if ( !wellPathPartInCell.empty() )
{
int endpointCount = 0;
if ( wellPathPartInCell.front().z() != HUGE_VAL ) ++endpointCount;
if ( wellPathPartInCell.back().z() != HUGE_VAL ) ++endpointCount;
cvf::Vec3d intersectionLength = (wellPathPartInCell.back() - wellPathPartInCell.front());
double xLengthInCell = fabs(intersectionLength.x());
double yLengthInCell = fabs(intersectionLength.y());
m_stimPlanCellIdxToIntersectionInfoMap[cIdx].endpointCount += endpointCount;
m_stimPlanCellIdxToIntersectionInfoMap[cIdx].hlength += xLengthInCell;
m_stimPlanCellIdxToIntersectionInfoMap[cIdx].vlength += yLengthInCell;
}
}
}
}
}

View File

@@ -1,79 +0,0 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "cvfBase.h"
#include "cvfMatrix4.h"
#include <map>
#include <vector>
class RigWellPath;
class RimFracture;
class RigWellPathStimplanIntersectorTester;
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
class RigWellPathStimplanIntersector
{
public:
struct WellCellIntersection
{
WellCellIntersection():hlength(0.0), vlength(0.0), endpointCount(0) {}
double hlength;
double vlength;
int endpointCount;
};
RigWellPathStimplanIntersector(const RigWellPath* wellpathGeom, const RimFracture* rimFracture);
const std::map<size_t, WellCellIntersection >& intersections() const;
private:
friend class RigWellPathStimplanIntersectorTester;
static void calculate(const cvf::Mat4d& fractureXf,
const std::vector<cvf::Vec3d>& wellPathPoints,
double wellRadius,
double perforationLength,
const std::vector<std::vector<cvf::Vec3d> >& stpCellPolygons,
std::map<size_t, WellCellIntersection>& stimPlanCellIdxToIntersectionInfoMap);
std::map<size_t, WellCellIntersection > m_stimPlanCellIdxToIntersectionInfoMap;
};
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
class RigWellPathStimplanIntersectorTester
{
public:
static void testCalculate(const cvf::Mat4d& fractureXf,
const std::vector<cvf::Vec3d>& wellPathPoints,
double wellRadius,
double perforationLength,
const std::vector<std::vector<cvf::Vec3d> >& stpCellPolygons,
std::map<size_t, RigWellPathStimplanIntersector::WellCellIntersection>& stimPlanCellIdxToIntersectionInfoMap)
{
RigWellPathStimplanIntersector::calculate(fractureXf, wellPathPoints, wellRadius, perforationLength, stpCellPolygons, stimPlanCellIdxToIntersectionInfoMap);
}
};