mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
#2423 Export Completions : Move folder one level up
This commit is contained in:
@@ -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 )
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
};
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
};
|
||||
Reference in New Issue
Block a user