Merge remote-tracking branch 'origin/pre-proto' into dev

This commit is contained in:
Magne Sjaastad 2017-08-22 09:58:39 +02:00
commit 4076c511fa
324 changed files with 90220 additions and 219 deletions

View File

@ -30,6 +30,7 @@
#include "RiaVersionInfo.h"
#include "RigGridManager.h"
#include "RigEclipseCaseData.h"
#include "Rim3dOverlayInfoConfig.h"
#include "RimCaseCollection.h"
@ -50,6 +51,11 @@
#include "RimFlowCharacteristicsPlot.h"
#include "RimFlowPlotCollection.h"
#include "RimFormationNamesCollection.h"
#ifdef USE_PROTOTYPE_FEATURE_FRACTURES
#include "RimFractureTemplateCollection.h"
#endif // USE_PROTOTYPE_FEATURE_FRACTURES
#include "RimGeoMechCase.h"
#include "RimGeoMechCellColors.h"
#include "RimGeoMechModels.h"
@ -74,6 +80,7 @@
#include "RimWellLogPlotCollection.h"
#include "RimWellPath.h"
#include "RimWellPathCollection.h"
#include "RimWellPathFracture.h"
#include "RiuMainPlotWindow.h"
#include "RiuMainWindow.h"
@ -214,13 +221,14 @@ RiaApplication::RiaApplication(int& argc, char** argv)
// instead of using the application font
m_standardFont = new caf::FixedAtlasFont(caf::FixedAtlasFont::POINT_SIZE_8);
m_resViewUpdateTimer = NULL;
m_resViewUpdateTimer = nullptr;
m_recalculateCompletionTypeTimer = nullptr;
m_runningRegressionTests = false;
m_runningWorkerProcess = false;
m_mainPlotWindow = NULL;
m_mainPlotWindow = nullptr;
m_recentFileActionProvider = std::unique_ptr<RiuRecentFileActionProvider>(new RiuRecentFileActionProvider);
}
@ -478,6 +486,21 @@ bool RiaApplication::loadProject(const QString& projectFileName, ProjectLoadActi
}
oilField->summaryCaseCollection()->createSummaryCasesFromRelevantEclipseResultCases();
oilField->summaryCaseCollection()->loadAllSummaryCaseData();
#ifdef USE_PROTOTYPE_FEATURE_FRACTURES
oilField->fractureDefinitionCollection()->loadAndUpdateData();
{
std::vector<RimWellPathFracture*> wellPathFractures;
oilField->wellPathCollection->descendantsIncludingThisOfType(wellPathFractures);
for (auto fracture : wellPathFractures)
{
fracture->loadDataAndUpdate();
}
}
#endif // USE_PROTOTYPE_FEATURE_FRACTURES
}
// If load action is specified to recalculate statistics, do it now.
@ -982,6 +1005,18 @@ bool RiaApplication::openEclipseCase(const QString& caseName, const QString& cas
riv->loadDataAndUpdate();
if (analysisModels->cases.size() > 0)
{
if (rimResultReservoir->eclipseCaseData())
{
#ifdef USE_PROTOTYPE_FEATURE_FRACTURES
project()->activeOilField()->fractureDefinitionCollection->defaultUnitsForFracTemplates = rimResultReservoir->eclipseCaseData()->unitsType();
#endif // USE_PROTOTYPE_FEATURE_FRACTURES
}
}
// Add a corresponding summary case if it exists
{
RimSummaryCaseCollection* sumCaseColl = m_project->activeOilField() ? m_project->activeOilField()->summaryCaseCollection() : NULL;
@ -2763,6 +2798,44 @@ void RiaApplication::scheduleDisplayModelUpdateAndRedraw(RimView* resViewToUpdat
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaApplication::scheduleRecalculateCompletionTypeAndRedrawAllViews()
{
for (RimEclipseCase* eclipseCase : project()->activeOilField()->analysisModels->cases())
{
m_eclipseCasesToRecalculate.push_back(eclipseCase);
}
if (!m_recalculateCompletionTypeTimer)
{
m_recalculateCompletionTypeTimer = new QTimer(this);
m_recalculateCompletionTypeTimer->setSingleShot(true);
connect(m_recalculateCompletionTypeTimer, SIGNAL(timeout()), this, SLOT(slotRecaulculateCompletionType()));
}
m_recalculateCompletionTypeTimer->start(500);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaApplication::scheduleRecalculateCompletionTypeAndRedrawEclipseCase(RimEclipseCase* eclipseCase)
{
m_eclipseCasesToRecalculate.push_back(eclipseCase);
if (!m_recalculateCompletionTypeTimer)
{
m_recalculateCompletionTypeTimer = new QTimer(this);
m_recalculateCompletionTypeTimer->setSingleShot(true);
connect(m_recalculateCompletionTypeTimer, SIGNAL(timeout()), this, SLOT(slotRecaulculateCompletionType()));
}
m_recalculateCompletionTypeTimer->start(500);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -2803,6 +2876,21 @@ void RiaApplication::slotUpdateScheduledDisplayModels()
m_resViewsToUpdate.clear();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaApplication::slotRecaulculateCompletionType()
{
std::set<RimEclipseCase*> uniqueCases(m_eclipseCasesToRecalculate.begin(), m_eclipseCasesToRecalculate.end());
for (RimEclipseCase* eclipseCase : uniqueCases)
{
eclipseCase->recalculateCompletionTypeAndRedrawAllViews();
}
m_eclipseCasesToRecalculate.clear();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -105,6 +105,8 @@ public:
RimViewWindow* activePlotWindow() const;
void scheduleDisplayModelUpdateAndRedraw(RimView* resViewToUpdate);
void scheduleRecalculateCompletionTypeAndRedrawAllViews();
void scheduleRecalculateCompletionTypeAndRedrawEclipseCase(RimEclipseCase* eclipseCase);
RimProject* project();
@ -227,6 +229,7 @@ private:
private slots:
void slotWorkerProcessFinished(int exitCode, QProcess::ExitStatus exitStatus);
void slotUpdateScheduledDisplayModels();
void slotRecaulculateCompletionType();
// Friend classes required to have access to slotUpdateScheduledDisplayModels
// As snapshots are produced fast in sequence, the feature must have access to force redraw
@ -241,6 +244,8 @@ private:
std::vector<caf::PdmPointer<RimView> > m_resViewsToUpdate;
QTimer* m_resViewUpdateTimer;
std::vector<caf::PdmPointer<RimEclipseCase> > m_eclipseCasesToRecalculate;
QTimer* m_recalculateCompletionTypeTimer;
RiaSocketServer* m_socketServer;

View File

@ -64,6 +64,7 @@ namespace caf
addItem(RiaDefines::WELL_PATH, "WELL_PATH", "Well Path");
addItem(RiaDefines::PERFORATION_INTERVAL, "PERFORATION_INTERVAL", "Perforation Interval");
addItem(RiaDefines::FISHBONES, "FISHBONES", "Fishbones");
addItem(RiaDefines::FRACTURE, "FRACTURE", "Fracture");
setDefault(RiaDefines::WELL_PATH);
}

View File

@ -39,7 +39,8 @@ namespace RiaDefines
enum CompletionType {
WELL_PATH,
PERFORATION_INTERVAL,
FISHBONES
FISHBONES,
FRACTURE,
};
bool isPerCellFaceResult(const QString& resultName);

View File

@ -212,6 +212,28 @@ const caf::ColorTable& RiaColorTables::angularPaletteColors()
return colorTable;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const caf::ColorTable& RiaColorTables::stimPlanPaletteColors()
{
static std::vector<cvf::Color3ub> colors{
cvf::Color3ub(220, 220, 220), //Grey
cvf::Color3ub(0, 0, 255), //Blue
cvf::Color3ub(0, 128, 255), //Lighter blue
cvf::Color3ub(80, 240, 60), //Darker green
cvf::Color3ub(0, 255, 0), //Green
cvf::Color3ub(255, 255, 0), //Yellow
cvf::Color3ub(255, 192, 0), //Light orange
cvf::Color3ub(255, 128, 0), //Orange
cvf::Color3ub(255, 64, 0), //Red-orange
cvf::Color3ub(255, 0, 255) //Magenta
};
static caf::ColorTable colorTable = caf::ColorTable(colors);
return colorTable;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -38,6 +38,7 @@ public:
static const caf::ColorTable& redWhiteBluePaletteColors();
static const caf::ColorTable& categoryPaletteColors();
static const caf::ColorTable& angularPaletteColors();
static const caf::ColorTable& stimPlanPaletteColors();
static const caf::ColorTable& faultsPaletteColors();
static const caf::ColorTable& wellsPaletteColors();
static const caf::ColorTable& summaryCurveDefaultPaletteColors();

View File

@ -41,7 +41,7 @@ public:
static double feetToMeter(double feet) { return feet*meterPerFeet();}
static double meterToInch(double meter) { return meter*feetPerMeter()*12; }
static double inchToMeter(double inch) { return (inch / 12)*meterPerFeet(); }
static double inchToFeet(double inch) { return inch / 12.0; }
static double inchToFeet (double inch) { return (inch / 12.0); }
static double darcysConstant(UnitSystem unitSystem);

View File

@ -189,6 +189,11 @@ if (${RESINSIGHT_FOUND_HDF5})
endif()
if (RESINSIGHT_ENABLE_PROTOTYPE_FEATURE_FRACTURES)
add_definitions(-DUSE_PROTOTYPE_FEATURE_FRACTURES)
endif()
#############################################################################
# Qt specifics: Moc, ui, resources
#############################################################################
@ -338,6 +343,11 @@ if(RESINSIGHT_ENABLE_COTIRE)
# mix of cvf and Qt namespaces
ModelVisualization/GridBox/RivGridBoxGenerator.cpp
ModelVisualization/Intersections/RivIntersectionGeometryGenerator.cpp
# exclude file using Eigen
ReservoirDataModel/RigTransmissibilityCondenser.cpp
ReservoirDataModel/RigEclipseToStimPlanCellTransmissibilityCalculator.cpp
ReservoirDataModel/RigCellGeometryTools.cpp
)
foreach (fileToExclude ${COTIRE_EXCLUDE_FILES})

View File

@ -6,6 +6,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RicfComputeCaseGroupStatistics.h
${CMAKE_CURRENT_LIST_DIR}/RicfExportMsw.h
${CMAKE_CURRENT_LIST_DIR}/RicfExportMultiCaseSnapshots.h
${CMAKE_CURRENT_LIST_DIR}/RicfExportProperty.h
${CMAKE_CURRENT_LIST_DIR}/RicfExportSimWellCompletions.h
${CMAKE_CURRENT_LIST_DIR}/RicfExportSnapshots.h
${CMAKE_CURRENT_LIST_DIR}/RicfExportWellPathCompletions.h
${CMAKE_CURRENT_LIST_DIR}/RicfLoadCase.h
@ -26,6 +27,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RicfComputeCaseGroupStatistics.cpp
${CMAKE_CURRENT_LIST_DIR}/RicfExportMsw.cpp
${CMAKE_CURRENT_LIST_DIR}/RicfExportMultiCaseSnapshots.cpp
${CMAKE_CURRENT_LIST_DIR}/RicfExportProperty.cpp
${CMAKE_CURRENT_LIST_DIR}/RicfExportSimWellCompletions.cpp
${CMAKE_CURRENT_LIST_DIR}/RicfExportSnapshots.cpp
${CMAKE_CURRENT_LIST_DIR}/RicfExportWellPathCompletions.cpp
${CMAKE_CURRENT_LIST_DIR}/RicfLoadCase.cpp

View File

@ -0,0 +1,129 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RicfExportSimWellCompletions.h"
#include "RicfCommandFileExecutor.h"
#include "RiaApplication.h"
#include "RiaLogging.h"
#include "RimProject.h"
#include "RimOilField.h"
#include "RimEclipseCaseCollection.h"
#include "RimEclipseCase.h"
#include "RimEclipseWell.h"
#include "RimEclipseView.h"
#include "RimEclipseWellCollection.h"
#include "RimEclipseWell.h"
#include "RimWellPathCollection.h"
#include "RimWellPath.h"
#include "CompletionCommands/RicWellPathExportCompletionDataFeature.h"
CAF_PDM_SOURCE_INIT(RicfExportSimWellCompletions, "exportSimWellCompletions");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RicfExportSimWellCompletions::RicfExportSimWellCompletions()
{
RICF_InitField(&m_caseId, "case", -1, "Case ID", "", "", "");
RICF_InitField(&m_timeStep, "timeStep", -1, "Time Step Index", "", "", "");
RICF_InitField(&m_wellPathNames, "wellPathNames", std::vector<QString>(), "Well Path Names", "", "", "");
RICF_InitField(&m_wellSelection, "wellSelection", RicExportCompletionDataSettingsUi::WellSelectionType(), "Well Selection", "", "", "");
RICF_InitField(&m_fileSplit, "fileSplit", RicExportCompletionDataSettingsUi::ExportSplitType(), "File Split", "", "", "");
RICF_InitField(&m_compdatExport, "compdatExport", RicExportCompletionDataSettingsUi::CompdatExportType(), "Compdat Export", "", "", "");
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicfExportSimWellCompletions::execute()
{
RicExportCompletionDataSettingsUi exportSettings(false);
exportSettings.timeStep = m_timeStep;
exportSettings.wellSelection = m_wellSelection;
exportSettings.fileSplit = m_fileSplit;
exportSettings.compdatExport = m_compdatExport;
{
bool foundCase = false;
for (RimEclipseCase* c : RiaApplication::instance()->project()->activeOilField()->analysisModels->cases())
{
if (c->caseId() == m_caseId())
{
exportSettings.caseToApply = c;
foundCase = true;
break;
}
}
if (!foundCase)
{
RiaLogging::error(QString("exportSimWellCompletions: Could not find case with ID %1").arg(m_caseId()));
return;
}
}
QString exportFolder = RicfCommandFileExecutor::instance()->getExportPath(RicfCommandFileExecutor::COMPLETIONS);
if (exportFolder.isNull())
{
exportFolder = RiaApplication::instance()->createAbsolutePathFromProjectRelativePath("completions");
}
exportSettings.folder = exportFolder;
// FIXME : Select correct view?
RimEclipseView* view;
for (RimView* v : exportSettings.caseToApply->views())
{
view = dynamic_cast<RimEclipseView*>(v);
if (view) break;
}
if (!view)
{
RiaLogging::error(QString("exportSimWellCompletions: Could not find a view for case with ID %1").arg(m_caseId()));
return;
}
std::vector<RimEclipseWell*> simWells;
if (m_wellPathNames().empty())
{
std::copy(view->wellCollection->wells.begin(),
view->wellCollection->wells.end(),
std::back_inserter(simWells));
}
else
{
for (const QString& wellPathName : m_wellPathNames())
{
RimEclipseWell* simWell = view->wellCollection->findWell(wellPathName);
if (simWell)
{
simWells.push_back(simWell);
}
else
{
RiaLogging::warning(QString("exportSimWellCompletions: Could not find well with name %1 on case with ID %2").arg(wellPathName).arg(m_caseId()));
}
}
}
std::vector<RimWellPath*> wellPaths;
RicWellPathExportCompletionDataFeature::exportCompletions(wellPaths, simWells, exportSettings);
}

View File

@ -0,0 +1,50 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RicfCommandObject.h"
#include "CompletionCommands/RicExportCompletionDataSettingsUi.h"
#include "cafAppEnum.h"
#include "cafPdmField.h"
//==================================================================================================
//
//
//
//==================================================================================================
class RicfExportSimWellCompletions : public RicfCommandObject
{
CAF_PDM_HEADER_INIT;
public:
RicfExportSimWellCompletions();
virtual void execute() override;
private:
caf::PdmField<int> m_caseId;
caf::PdmField<int> m_timeStep;
caf::PdmField< std::vector<QString> > m_wellPathNames;
caf::PdmField<RicExportCompletionDataSettingsUi::WellSelectionType> m_wellSelection;
caf::PdmField<RicExportCompletionDataSettingsUi::ExportSplitType> m_fileSplit;
caf::PdmField<RicExportCompletionDataSettingsUi::CompdatExportType> m_compdatExport;
};

View File

@ -105,8 +105,14 @@ void RicfExportWellPathCompletions::execute()
{
wellPaths.push_back(wellPath);
}
else
{
RiaLogging::warning(QString("exportWellPathCompletions: Could not find well path with name %1").arg(wellPathName));
}
}
}
RicWellPathExportCompletionDataFeature::exportCompletions(wellPaths, exportSettings);
std::vector<RimEclipseWell*> simWells;
RicWellPathExportCompletionDataFeature::exportCompletions(wellPaths, simWells, exportSettings);
}

View File

@ -34,6 +34,7 @@ ${CEE_CURRENT_LIST_DIR}RicExportFeatureImpl.h
${CEE_CURRENT_LIST_DIR}RicSelectOrCreateViewFeatureImpl.h
# General delete of any object in a child array field
${CEE_CURRENT_LIST_DIR}RicDeleteItemExec.h
${CEE_CURRENT_LIST_DIR}RicDeleteItemExecData.h
@ -48,6 +49,23 @@ ${CEE_CURRENT_LIST_DIR}RicReloadCaseFeature.h
${CEE_CURRENT_LIST_DIR}RicFlyToObjectFeature.h
)
if (RESINSIGHT_ENABLE_PROTOTYPE_FEATURE_FRACTURES)
list (APPEND SOURCE_GROUP_HEADER_FILES
${CEE_CURRENT_LIST_DIR}RicNewSimWellFractureFeature.h
${CEE_CURRENT_LIST_DIR}RicNewSimWellFractureAtPosFeature.h
${CEE_CURRENT_LIST_DIR}RicNewEllipseFractureTemplateFeature.h
${CEE_CURRENT_LIST_DIR}RicNewStimPlanFractureTemplateFeature.h
${CEE_CURRENT_LIST_DIR}RicNewWellPathFractureFeature.h
${CEE_CURRENT_LIST_DIR}RicNewWellPathFractureAtPosFeature.h
${CEE_CURRENT_LIST_DIR}RicConvertFractureTemplateUnitFeature.h
${CEE_CURRENT_LIST_DIR}RicConvertAllFractureTemplatesToMetricFeature.h
${CEE_CURRENT_LIST_DIR}RicConvertAllFractureTemplatesToFieldFeature.h
${CEE_CURRENT_LIST_DIR}RicFractureNameGenerator.h
)
endif()
set (SOURCE_GROUP_SOURCE_FILES
${CEE_CURRENT_LIST_DIR}RicCloseCaseFeature.cpp
${CEE_CURRENT_LIST_DIR}RicGeoMechPropertyFilterFeatureImpl.cpp
@ -88,6 +106,23 @@ ${CEE_CURRENT_LIST_DIR}RicReloadCaseFeature.cpp
${CEE_CURRENT_LIST_DIR}RicFlyToObjectFeature.cpp
)
if (RESINSIGHT_ENABLE_PROTOTYPE_FEATURE_FRACTURES)
list (APPEND SOURCE_GROUP_SOURCE_FILES
${CEE_CURRENT_LIST_DIR}RicNewSimWellFractureFeature.cpp
${CEE_CURRENT_LIST_DIR}RicNewSimWellFractureAtPosFeature.cpp
${CEE_CURRENT_LIST_DIR}RicNewEllipseFractureTemplateFeature.cpp
${CEE_CURRENT_LIST_DIR}RicNewStimPlanFractureTemplateFeature.cpp
${CEE_CURRENT_LIST_DIR}RicNewWellPathFractureFeature.cpp
${CEE_CURRENT_LIST_DIR}RicNewWellPathFractureAtPosFeature.cpp
${CEE_CURRENT_LIST_DIR}RicConvertFractureTemplateUnitFeature.cpp
${CEE_CURRENT_LIST_DIR}RicConvertAllFractureTemplatesToMetricFeature.cpp
${CEE_CURRENT_LIST_DIR}RicConvertAllFractureTemplatesToFieldFeature.cpp
${CEE_CURRENT_LIST_DIR}RicFractureNameGenerator.cpp
)
endif()
list(APPEND CODE_HEADER_FILES
${SOURCE_GROUP_HEADER_FILES}
)

View File

@ -20,6 +20,13 @@ ${CEE_CURRENT_LIST_DIR}RicWellPathImportPerforationIntervalsFeature.h
${CEE_CURRENT_LIST_DIR}RicFishbonesTransmissibilityCalculationFeatureImp.h
)
if (RESINSIGHT_ENABLE_PROTOTYPE_FEATURE_FRACTURES)
list (APPEND SOURCE_GROUP_HEADER_FILES
${CEE_CURRENT_LIST_DIR}RicExportFractureCompletionsImpl.h
)
endif()
set (SOURCE_GROUP_SOURCE_FILES
${CEE_CURRENT_LIST_DIR}RicCaseAndFileExportSettingsUi.cpp
${CEE_CURRENT_LIST_DIR}RicEditPerforationCollectionFeature.cpp
@ -36,6 +43,13 @@ ${CEE_CURRENT_LIST_DIR}RicWellPathImportPerforationIntervalsFeature.cpp
${CEE_CURRENT_LIST_DIR}RicFishbonesTransmissibilityCalculationFeatureImp.cpp
)
if (RESINSIGHT_ENABLE_PROTOTYPE_FEATURE_FRACTURES)
list (APPEND SOURCE_GROUP_SOURCE_FILES
${CEE_CURRENT_LIST_DIR}RicExportFractureCompletionsImpl.cpp
)
endif()
list(APPEND CODE_HEADER_FILES
${SOURCE_GROUP_HEADER_FILES}
)

View File

@ -42,7 +42,7 @@ namespace caf
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");
addItem(RicExportCompletionDataSettingsUi::WPIMULT_AND_DEFAULT_CONNECTION_FACTORS, "WPIMULT_AND_DEFAULT_CONNECTION_FACTORS", "Default Connection Factors and WPIMULT (Fractures Not Supported)");
setDefault(RicExportCompletionDataSettingsUi::TRANSMISSIBILITIES);
}
}
@ -72,12 +72,53 @@ RicExportCompletionDataSettingsUi::RicExportCompletionDataSettingsUi(bool onlyWe
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;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
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
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -122,7 +163,6 @@ QList<caf::PdmOptionItemInfo> RicExportCompletionDataSettingsUi::calculateValueO
//--------------------------------------------------------------------------------------------------
void RicExportCompletionDataSettingsUi::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering)
{
caf::PdmUiGroup* generalExportSettings = uiOrdering.addNewGroup("General Export Settings");
generalExportSettings->add(&folder);
generalExportSettings->add(&caseToApply);
@ -133,12 +173,34 @@ void RicExportCompletionDataSettingsUi::defineUiOrdering(QString uiConfigName, c
generalExportSettings->add(&fileSplit);
if (!m_displayForSimWell)
{
caf::PdmUiGroup* fishboneGroup = uiOrdering.addNewGroup("Export of Fishbone Completions");
fishboneGroup->add(&includeFishbones);
fishboneGroup->add(&excludeMainBoreForFishbones);
if (!includeFishbones) excludeMainBoreForFishbones.uiCapability()->setUiReadOnly(true);
else excludeMainBoreForFishbones.uiCapability()->setUiReadOnly(false);
caf::PdmUiGroup* perfIntervalGroup = uiOrdering.addNewGroup("Export of Perforation Completions");
perfIntervalGroup->add(&includePerforations);
perfIntervalGroup->add(&timeStep);
if (!includePerforations) timeStep.uiCapability()->setUiReadOnly(true);
else timeStep.uiCapability()->setUiReadOnly(false);
#ifdef USE_PROTOTYPE_FEATURE_FRACTURES
caf::PdmUiGroup* fractureGroup = uiOrdering.addNewGroup("Export of Fracture Completions");
fractureGroup->add(&includeFractures);
if (compdatExport == WPIMULT_AND_DEFAULT_CONNECTION_FACTORS)
{
includeFractures.uiCapability()->setUiReadOnly(true);
}
else if (compdatExport == TRANSMISSIBILITIES)
{
includeFractures.uiCapability()->setUiReadOnly(false);
}
#endif // USE_PROTOTYPE_FEATURE_FRACTURES
}
uiOrdering.skipRemainingFields();
}

View File

@ -64,18 +64,24 @@ public:
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 showForSimWells();
void showForWellPath();
virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override;
protected:
virtual QList<caf::PdmOptionItemInfo> calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool * useOptionsOnly) override;
virtual void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) override;
private:
bool m_onlyWellPathCollectionSelected;
bool m_displayForSimWell;
};

View File

@ -0,0 +1,363 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RimFracture.h"
#include "RimWellPath.h"
#include "RimFractureTemplate.h"
#include "RimEclipseView.h"
#include "RimEclipseWell.h"
#include "RimSimWellFractureCollection.h"
#include "RimStimPlanFractureTemplate.h"
#include "RimSimWellFracture.h"
#include "RimWellPathCompletions.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 "RigSingleWellResultsData.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;
wellPath->descendantsIncludingThisOfType(fracturesAlongWellPath);
return generateCompdatValues(caseToApply,
wellPath->completions()->wellNameForExport(),
wellPath->wellPathGeometry(),
fracturesAlongWellPath,
outputStreamForIntermediateResultsText);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RigCompletionData> RicExportFractureCompletionsImpl::generateCompdatValuesForSimWell(RimEclipseCase* eclipseCase,
const RimEclipseWell* 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 (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)
{
bool useFiniteConductivityInFracture = (fracture->fractureTemplate()->conductivityType() == RimFractureTemplate::FINITE_CONDUCTIVITY);
RimFractureTemplate* fracTemplate = fracture->fractureTemplate();
const RigFractureGrid* fractureGrid = fracTemplate->fractureGrid();
//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);
bool conductivityInFile = false;
for (auto parameterUnit : fracTemplateStimPlan->resultNamesWithUnit())
{
if (parameterUnit.first == "CONDUCTIVITY") conductivityInFile = true;
}
if (!conductivityInFile)
{
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());
bool hasAnyContribEclCellWithinContainment = false;
for ( size_t i = 0; i < fractureCellContributingEclipseCells.size(); i++ )
{
if ( fracture->isEclipseCellWithinContainment(caseToApply->eclipseCaseData()->mainGrid(), fractureCellContributingEclipseCells[i]) )
{
hasAnyContribEclCellWithinContainment = true;
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();
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;
size_t i, j, k;
mainGrid->ijkFromCellIndex(externalCell.m_globalCellIdx, &i, &j, &k);
RigCompletionData compDat(wellPathName, {i,j,k} );
compDat.setFromFracture(trans, fracture->fractureTemplate()->skinFactor());
compDat.addMetadata(fracture->name(), QString::number(trans));
fractureCompletions.push_back(compDat);
}
}
if ( outputStreamForIntermediateResultsText )
{
(*outputStreamForIntermediateResultsText) << "\n" << "\n" << "\n----------- All Transimissibilities " << fracture->name() << " -------------------- \n\n";
(*outputStreamForIntermediateResultsText) << QString::fromStdString(transCondenser.neighborTransDebugOutput(mainGrid, fractureGrid));
(*outputStreamForIntermediateResultsText) << "\n" << "\n" << "\n----------- Condensed Results " << fracture->name() << " -------------------- \n\n";
(*outputStreamForIntermediateResultsText) << QString::fromStdString(transCondenser.condensedTransDebugOutput(mainGrid, fractureGrid));
(*outputStreamForIntermediateResultsText) << "\n" ;
}
}
return fractureCompletions;
}

View File

@ -0,0 +1,48 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2017- Statoil ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
class RimWellPath;
class RicExportCompletionDataSettingsUi;
#include <vector>
#include "RigCompletionData.h"
class QTextStream;
class RigWellPath;
class RimEclipseCase;
class RimEclipseWell;
class RimFracture;
class RicExportFractureCompletionsImpl
{
public:
static std::vector<RigCompletionData> generateCompdatValuesForWellPath(RimWellPath* wellPath,
const RicExportCompletionDataSettingsUi& settings,
QTextStream* outputStreamForIntermediateResultsText);
static std::vector<RigCompletionData> generateCompdatValuesForSimWell(RimEclipseCase* eclipseCase,
const RimEclipseWell* well,
QTextStream* outputStreamForIntermediateResultsText);
private:
static std::vector<RigCompletionData> generateCompdatValues(RimEclipseCase* caseToApply,
const QString& wellPathName,
const RigWellPath* wellPathGeometry,
const std::vector<RimFracture*> fractures,
QTextStream* outputStreamForIntermediateResultsText);
};

View File

@ -24,12 +24,15 @@
#include "RicExportCompletionDataSettingsUi.h"
#include "RicExportFeatureImpl.h"
#include "RicFishbonesTransmissibilityCalculationFeatureImp.h"
#include "RicExportFractureCompletionsImpl.h"
#include "RigActiveCellInfo.h"
#include "RigEclipseCaseData.h"
#include "RigMainGrid.h"
#include "RigResultAccessorFactory.h"
#include "RigTransmissibilityEquations.h"
#include "RigWellLogExtractionTools.h"
#include "RigWellPath.h"
#include "RigWellPathIntersectionTools.h"
@ -42,6 +45,8 @@
#include "RimPerforationInterval.h"
#include "RimProject.h"
#include "RimReservoirCellResultsStorage.h"
#include "RimEclipseWell.h"
#include "RimEclipseWellCollection.h"
#include "RimWellPath.h"
#include "RimWellPathCollection.h"
#include "RimWellPathCompletions.h"
@ -65,7 +70,32 @@ CAF_CMD_SOURCE_INIT(RicWellPathExportCompletionDataFeature, "RicWellPathExportCo
//--------------------------------------------------------------------------------------------------
bool RicWellPathExportCompletionDataFeature::isCommandEnabled()
{
return !selectedWellPaths().empty();
std::vector<RimWellPath*> wellPaths = selectedWellPaths();
std::vector<RimEclipseWell*> simWells = selectedSimWells();
if (wellPaths.empty() && simWells.empty())
{
return false;
}
if (!wellPaths.empty() && !simWells.empty())
{
return false;
}
std::set<RimEclipseCase*> eclipseCases;
for (auto simWell : simWells)
{
RimEclipseCase* eclipseCase;
simWell->firstAncestorOrThisOfType(eclipseCase);
eclipseCases.insert(eclipseCase);
}
if (eclipseCases.size() > 1)
{
return false;
}
return true;
}
//--------------------------------------------------------------------------------------------------
@ -74,8 +104,9 @@ bool RicWellPathExportCompletionDataFeature::isCommandEnabled()
void RicWellPathExportCompletionDataFeature::onActionTriggered(bool isChecked)
{
std::vector<RimWellPath*> wellPaths = selectedWellPaths();
std::vector<RimEclipseWell*> simWells = selectedSimWells();
CVF_ASSERT(wellPaths.size() > 0);
CVF_ASSERT(wellPaths.size() > 0 || simWells.size() > 0);
RiaApplication* app = RiaApplication::instance();
@ -83,8 +114,16 @@ void RicWellPathExportCompletionDataFeature::onActionTriggered(bool isChecked)
QString defaultDir = RiaApplication::instance()->lastUsedDialogDirectoryWithFallback("COMPLETIONS", projectFolder);
bool onlyWellPathCollectionSelected = noWellPathsSelectedDirectly();
RicExportCompletionDataSettingsUi exportSettings(onlyWellPathCollectionSelected);
if (wellPaths.empty())
{
exportSettings.showForSimWells();
}
else
{
exportSettings.showForWellPath();
}
std::vector<RimCase*> cases;
app->project()->allCases(cases);
for (auto c : cases)
@ -106,7 +145,7 @@ void RicWellPathExportCompletionDataFeature::onActionTriggered(bool isChecked)
{
RiaApplication::instance()->setLastUsedDialogDirectory("COMPLETIONS", exportSettings.folder);
exportCompletions(wellPaths, exportSettings);
exportCompletions(wellPaths, simWells, exportSettings);
}
}
@ -157,10 +196,36 @@ bool RicWellPathExportCompletionDataFeature::noWellPathsSelectedDirectly()
else return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RimEclipseWell*> RicWellPathExportCompletionDataFeature::selectedSimWells()
{
std::vector<RimEclipseWell*> simWells;
caf::SelectionManager::instance()->objectsByType(&simWells);
std::vector<RimEclipseWellCollection*> simWellCollections;
caf::SelectionManager::instance()->objectsByType(&simWellCollections);
for (auto simWellCollection : simWellCollections)
{
for (auto simWell : simWellCollection->wells())
{
simWells.push_back(simWell);
}
}
std::set<RimEclipseWell*> uniqueSimWells(simWells.begin(), simWells.end());
simWells.assign(uniqueSimWells.begin(), uniqueSimWells.end());
return simWells;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicWellPathExportCompletionDataFeature::exportCompletions(const std::vector<RimWellPath*>& wellPaths,
const std::vector<RimEclipseWell*>& simWells,
const RicExportCompletionDataSettingsUi& exportSettings)
{
@ -197,6 +262,16 @@ void RicWellPathExportCompletionDataFeature::exportCompletions(const std::vector
break;
}
}
for (const RimEclipseWell* simWell : simWells)
{
RimEclipseCase* eclipseCase;
simWell->firstAncestorOrThisOfType(eclipseCase);
if (exportSettings.caseToApply->eclipseCaseData()->unitsType() != eclipseCase->eclipseCaseData()->unitsType())
{
unitSystemMismatch = true;
break;
}
}
if (unitSystemMismatch)
{
RiaLogging::error("Well path unit systems must match unit system of chosen eclipse case.");
@ -205,6 +280,16 @@ void RicWellPathExportCompletionDataFeature::exportCompletions(const std::vector
}
std::map<IJKCellIndex, std::vector<RigCompletionData> > completionsPerEclipseCell;
// FractureTransmissibilityExportInformation
QString fractureTransmisibillityExportInformationPath = QDir(exportSettings.folder).filePath("FractureTransmissibilityExportInformation");
QFile fractureTransmissibilityExportInformationFile(fractureTransmisibillityExportInformationPath);
if (!fractureTransmissibilityExportInformationFile.open(QIODevice::WriteOnly))
{
RiaLogging::error(QString("Export Completions Data: Could not open the file: %1").arg(fractureTransmisibillityExportInformationPath));
return;
}
QTextStream fractureTransmissibilityExportInformationStream(&fractureTransmissibilityExportInformationFile);
for (auto wellPath : usedWellPaths)
{
@ -220,7 +305,26 @@ void RicWellPathExportCompletionDataFeature::exportCompletions(const std::vector
std::vector<RigCompletionData> fishbonesCompletionData = RicFishbonesTransmissibilityCalculationFeatureImp::generateFishboneCompdatValuesUsingAdjustedCellVolume(wellPath, exportSettings);
appendCompletionData(&completionsPerEclipseCell, fishbonesCompletionData);
}
#ifdef USE_PROTOTYPE_FEATURE_FRACTURES
if (exportSettings.includeFractures())
{
std::vector<RigCompletionData> fractureCompletionData = RicExportFractureCompletionsImpl::generateCompdatValuesForWellPath(wellPath, exportSettings, &fractureTransmissibilityExportInformationStream);
appendCompletionData(&completionsPerEclipseCell, fractureCompletionData);
}
#endif // USE_PROTOTYPE_FEATURE_FRACTURES
}
#ifdef USE_PROTOTYPE_FEATURE_FRACTURES
for (auto simWell : simWells)
{
std::vector<RigCompletionData> fractureCompletionData = RicExportFractureCompletionsImpl::generateCompdatValuesForSimWell(exportSettings.caseToApply(),
simWell,
&fractureTransmissibilityExportInformationStream);
appendCompletionData(&completionsPerEclipseCell, fractureCompletionData);
}
#endif // USE_PROTOTYPE_FEATURE_FRACTURES
const QString eclipseCaseName = exportSettings.caseToApply->caseUserDescription();
@ -254,6 +358,8 @@ void RicWellPathExportCompletionDataFeature::exportCompletions(const std::vector
}
}
if (wellCompletions.empty()) continue;
QString fileName = QString("%1_unifiedCompletions_%2").arg(wellPath->name()).arg(eclipseCaseName);
printCompletionsToFile(exportSettings.folder, fileName, wellCompletions, exportSettings.compdatExport);
}
@ -270,15 +376,29 @@ void RicWellPathExportCompletionDataFeature::exportCompletions(const std::vector
}
{
std::vector<RigCompletionData> fishbonesCompletions = getCompletionsForWellAndCompletionType(completions, wellPath->completions()->wellNameForExport(), RigCompletionData::FISHBONES);
if (!fishbonesCompletions.empty())
{
QString fileName = QString("%1_Fishbones_%2").arg(wellPath->name()).arg(eclipseCaseName);
printCompletionsToFile(exportSettings.folder, fileName, fishbonesCompletions, exportSettings.compdatExport);
}
}
{
std::vector<RigCompletionData> perforationCompletions = getCompletionsForWellAndCompletionType(completions, wellPath->completions()->wellNameForExport(), RigCompletionData::PERFORATION);
if (!perforationCompletions.empty())
{
QString fileName = QString("%1_Perforations_%2").arg(wellPath->name()).arg(eclipseCaseName);
printCompletionsToFile(exportSettings.folder, fileName, perforationCompletions, exportSettings.compdatExport);
}
}
{
std::vector<RigCompletionData> fractureCompletions = getCompletionsForWellAndCompletionType(completions, wellPath->completions()->wellNameForExport(), RigCompletionData::FRACTURE);
if (!fractureCompletions.empty())
{
QString fileName = QString("%1_Fractures_%2").arg(wellPath->name()).arg(eclipseCaseName);
printCompletionsToFile(exportSettings.folder, fileName, fractureCompletions, exportSettings.compdatExport);
}
}
}
}
}
@ -319,21 +439,30 @@ RigCompletionData RicWellPathExportCompletionDataFeature::combineEclipseCellComp
for (const RigCompletionData& completion : completions)
{
resultCompletion.m_metadata.reserve(resultCompletion.m_metadata.size() + completion.m_metadata.size());
resultCompletion.m_metadata.insert(resultCompletion.m_metadata.end(), completion.m_metadata.begin(), completion.m_metadata.end());
if (completion.completionType() != completions[0].completionType())
{
RiaLogging::error(QString("Cannot combine completions of different types in same cell [%1, %2, %3]").arg(cellIndexIJK.i).arg(cellIndexIJK.j).arg(cellIndexIJK.k));
QString errorMessage = QString("Cannot combine completions of different types in same cell [%1, %2, %3]").arg(cellIndexIJK.i + 1).arg(cellIndexIJK.j + 1).arg(cellIndexIJK.k + 1);
RiaLogging::error(errorMessage);
resultCompletion.addMetadata("ERROR", errorMessage);
return resultCompletion; //Returning empty completion, should not be exported
}
if (completion.wellName() != completions[0].wellName())
{
RiaLogging::error(QString("Cannot combine completions from different wells in same cell [%1, %2, %3]").arg(cellIndexIJK.i).arg(cellIndexIJK.j).arg(cellIndexIJK.k));
QString errorMessage = QString("Cannot combine completions from different wells in same cell [%1, %2, %3]").arg(cellIndexIJK.i + 1).arg(cellIndexIJK.j + 1).arg(cellIndexIJK.k + 1);
RiaLogging::error(errorMessage);
resultCompletion.addMetadata("ERROR", errorMessage);
return resultCompletion; //Returning empty completion, should not be exported
}
if (completion.transmissibility() == HUGE_VAL)
{
RiaLogging::error(QString("Transmissibility calculation has failed for cell [%1, %2, %3]").arg(cellIndexIJK.i).arg(cellIndexIJK.j).arg(cellIndexIJK.k));
QString errorMessage = QString("Transmissibility calculation has failed for cell [%1, %2, %3]").arg(cellIndexIJK.i + 1).arg(cellIndexIJK.j + 1).arg(cellIndexIJK.k + 1);
RiaLogging::error(errorMessage);
resultCompletion.addMetadata("ERROR", errorMessage);
return resultCompletion; //Returning empty completion, should not be exported
}
@ -343,10 +472,6 @@ RigCompletionData RicWellPathExportCompletionDataFeature::combineEclipseCellComp
}
totalTrans = totalTrans + completion.transmissibility();
resultCompletion.m_metadata.reserve(resultCompletion.m_metadata.size() + completion.m_metadata.size());
resultCompletion.m_metadata.insert(resultCompletion.m_metadata.end(), completion.m_metadata.begin(), completion.m_metadata.end());
}
@ -354,8 +479,7 @@ RigCompletionData RicWellPathExportCompletionDataFeature::combineEclipseCellComp
{
resultCompletion.setCombinedValuesExplicitTrans(totalTrans, completionType);
}
if (settings.compdatExport == RicExportCompletionDataSettingsUi::WPIMULT_AND_DEFAULT_CONNECTION_FACTORS)
else if (settings.compdatExport == RicExportCompletionDataSettingsUi::WPIMULT_AND_DEFAULT_CONNECTION_FACTORS)
{
//calculate trans for main bore - but as Eclipse will do it!
double transmissibilityEclipseCalculation = RicWellPathExportCompletionDataFeature::calculateTransmissibilityAsEclipseDoes(settings.caseToApply(),
@ -378,7 +502,10 @@ RigCompletionData RicWellPathExportCompletionDataFeature::combineEclipseCellComp
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicWellPathExportCompletionDataFeature::printCompletionsToFile(const QString& folderName, const QString& fileName, std::vector<RigCompletionData>& completions, RicExportCompletionDataSettingsUi::CompdatExportType exportType)
void RicWellPathExportCompletionDataFeature::printCompletionsToFile(const QString& folderName,
const QString& fileName,
std::vector<RigCompletionData>& completions,
RicExportCompletionDataSettingsUi::CompdatExportType exportType)
{
//TODO: Check that completion is ready for export
@ -560,7 +687,7 @@ void RicWellPathExportCompletionDataFeature::generateWpimultTable(RifEclipseData
for (auto& completion : completionData)
{
if (completion.wpimult() == 0.0)
if (completion.wpimult() == 0.0 || completion.isDefaultValue(completion.wpimult()))
{
continue;
}

View File

@ -33,6 +33,7 @@
class RimWellPath;
class RimEclipseCase;
class RimEclipseWell;
class RigEclipseCaseData;
class RigMainGrid;
class RigCell;
@ -126,6 +127,8 @@ protected:
virtual void setupActionLook(QAction* actionToSetup) override;
std::vector<RimWellPath*> selectedWellPaths();
std::vector<RimEclipseWell*> selectedSimWells();
bool noWellPathsSelectedDirectly();
public:
@ -150,7 +153,7 @@ public:
double wellRadius,
size_t cellIndex,
CellDirection direction);
static void exportCompletions(const std::vector<RimWellPath*>& wellPaths, const RicExportCompletionDataSettingsUi& exportSettings);
static void exportCompletions(const std::vector<RimWellPath*>& wellPaths, const std::vector<RimEclipseWell*>& simWells, const RicExportCompletionDataSettingsUi& exportSettings);
private:
static RigCompletionData combineEclipseCellCompletions(const std::vector<RigCompletionData>& completions,

View File

@ -35,7 +35,7 @@
#include <QClipboard>
#include <QString>
#include "QAction"
#include <QAction>

View File

@ -0,0 +1,88 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RicConvertAllFractureTemplatesToFieldFeature.h"
#include "RiaApplication.h"
#include "RiaEclipseUnitTools.h"
#include "RimEclipseCase.h"
#include "RimEclipseView.h"
#include "RimEllipseFractureTemplate.h"
#include "RimFracture.h"
#include "RimFractureExportSettings.h"
#include "RimFractureTemplateCollection.h"
#include "RimView.h"
#include "RimWellPathCollection.h"
#include "RiuMainWindow.h"
#include "cafPdmObjectHandle.h"
#include "cafPdmUiPropertyViewDialog.h"
#include "cafSelectionManager.h"
#include "cvfAssert.h"
#include <QAction>
#include <QMessageBox>
#include <QString>
#include <QFileInfo>
CAF_CMD_SOURCE_INIT(RicConvertAllFractureTemplatesToFieldFeature, "RicConvertAllFractureTemplatesToFieldFeature");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicConvertAllFractureTemplatesToFieldFeature::onActionTriggered(bool isChecked)
{
caf::PdmUiItem* pdmUiItem = caf::SelectionManager::instance()->selectedItem();
if (!pdmUiItem) return;
caf::PdmObjectHandle* objHandle = dynamic_cast<caf::PdmObjectHandle*>(pdmUiItem);
if (!objHandle) return;
RimFractureTemplateCollection* fracTempColl = nullptr;
objHandle->firstAncestorOrThisOfType(fracTempColl);
std::vector<RimEllipseFractureTemplate*> ellipseFracTemplates;
fracTempColl->descendantsIncludingThisOfType(ellipseFracTemplates);
for (auto ellipseFracTemplate : ellipseFracTemplates)
{
if (ellipseFracTemplate->fractureTemplateUnit == RiaEclipseUnitTools::UNITS_METRIC)
{
ellipseFracTemplate->changeUnits();
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicConvertAllFractureTemplatesToFieldFeature::setupActionLook(QAction* actionToSetup)
{
actionToSetup->setText("Convert All Ellipse Fracture Templates to Field");
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RicConvertAllFractureTemplatesToFieldFeature::isCommandEnabled()
{
return true;
}

View File

@ -0,0 +1,39 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "cafCmdFeature.h"
#include <vector>
//==================================================================================================
///
//==================================================================================================
class RicConvertAllFractureTemplatesToFieldFeature : public caf::CmdFeature
{
CAF_CMD_HEADER_INIT;
protected:
virtual void onActionTriggered(bool isChecked) override;
virtual void setupActionLook(QAction* actionToSetup) override;
virtual bool isCommandEnabled() override;
};

View File

@ -0,0 +1,90 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RicConvertAllFractureTemplatesToMetricFeature.h"
#include "RiaApplication.h"
#include "RiaEclipseUnitTools.h"
#include "RimEclipseCase.h"
#include "RimEclipseView.h"
#include "RimEllipseFractureTemplate.h"
#include "RimFracture.h"
#include "RimFractureExportSettings.h"
#include "RimFractureTemplateCollection.h"
#include "RimView.h"
#include "RimWellPathCollection.h"
#include "RiuMainWindow.h"
#include "cafPdmObjectHandle.h"
#include "cafPdmUiPropertyViewDialog.h"
#include "cafSelectionManager.h"
#include "cvfAssert.h"
#include <QAction>
#include <QFileInfo>
#include <QMessageBox>
#include <QString>
CAF_CMD_SOURCE_INIT(RicConvertAllFractureTemplatesToMetricFeature, "RicConvertAllFractureTemplatesToMetricFeature");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicConvertAllFractureTemplatesToMetricFeature::onActionTriggered(bool isChecked)
{
caf::PdmUiItem* pdmUiItem = caf::SelectionManager::instance()->selectedItem();
if (!pdmUiItem) return;
caf::PdmObjectHandle* objHandle = dynamic_cast<caf::PdmObjectHandle*>(pdmUiItem);
if (!objHandle) return;
RimFractureTemplateCollection* fracTempColl = nullptr;
objHandle->firstAncestorOrThisOfType(fracTempColl);
std::vector<RimEllipseFractureTemplate*> ellipseFracTemplates;
fracTempColl->descendantsIncludingThisOfType(ellipseFracTemplates);
for (auto ellipseFracTemplate : ellipseFracTemplates)
{
if (ellipseFracTemplate->fractureTemplateUnit == RiaEclipseUnitTools::UNITS_FIELD)
{
ellipseFracTemplate->changeUnits();
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicConvertAllFractureTemplatesToMetricFeature::setupActionLook(QAction* actionToSetup)
{
actionToSetup->setText("Convert All Ellipse Fracture Templates to Metric");
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RicConvertAllFractureTemplatesToMetricFeature::isCommandEnabled()
{
return true;
}

View File

@ -0,0 +1,39 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "cafCmdFeature.h"
#include <vector>
//==================================================================================================
///
//==================================================================================================
class RicConvertAllFractureTemplatesToMetricFeature : public caf::CmdFeature
{
CAF_CMD_HEADER_INIT;
protected:
virtual void onActionTriggered(bool isChecked) override;
virtual void setupActionLook(QAction* actionToSetup) override;
virtual bool isCommandEnabled() override;
};

View File

@ -0,0 +1,102 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RicConvertFractureTemplateUnitFeature.h"
#include "RiaApplication.h"
#include "RiaEclipseUnitTools.h"
#include "RimEclipseCase.h"
#include "RimEclipseView.h"
#include "RimEllipseFractureTemplate.h"
#include "RimFracture.h"
#include "RimFractureExportSettings.h"
#include "RimView.h"
#include "RimWellPathCollection.h"
#include "RiuMainWindow.h"
#include "cafPdmObjectHandle.h"
#include "cafPdmUiPropertyViewDialog.h"
#include "cafSelectionManager.h"
#include "cvfAssert.h"
#include <QAction>
#include <QMessageBox>
#include <QString>
#include <QFileInfo>
CAF_CMD_SOURCE_INIT(RicConvertFractureTemplateUnitFeature, "RicConvertFractureTemplateUnitFeature");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicConvertFractureTemplateUnitFeature::onActionTriggered(bool isChecked)
{
caf::PdmUiItem* pdmUiItem = caf::SelectionManager::instance()->selectedItem();
if (!pdmUiItem) return;
caf::PdmObjectHandle* objHandle = dynamic_cast<caf::PdmObjectHandle*>(pdmUiItem);
if (!objHandle) return;
RimEllipseFractureTemplate* ellipseFractureTemplate = nullptr;
objHandle->firstAncestorOrThisOfType(ellipseFractureTemplate);
ellipseFractureTemplate->changeUnits();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicConvertFractureTemplateUnitFeature::setupActionLook(QAction* actionToSetup)
{
actionToSetup->setIcon(QIcon(":/FractureTemplate16x16.png"));
//TODO: Add unit to text
caf::PdmUiItem* pdmUiItem = caf::SelectionManager::instance()->selectedItem();
if (!pdmUiItem) return;
caf::PdmObjectHandle* objHandle = dynamic_cast<caf::PdmObjectHandle*>(pdmUiItem);
if (!objHandle) return;
RimEllipseFractureTemplate* ellipseFractureTemplate = nullptr;
objHandle->firstAncestorOrThisOfType(ellipseFractureTemplate);
QString text = "Convert Values to ";
if (ellipseFractureTemplate->fractureTemplateUnit == RiaEclipseUnitTools::UNITS_METRIC)
{
text += "Field";
}
else if (ellipseFractureTemplate->fractureTemplateUnit == RiaEclipseUnitTools::UNITS_FIELD)
{
text += "Metric";
}
actionToSetup->setText(text);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RicConvertFractureTemplateUnitFeature::isCommandEnabled()
{
return true;
}

View File

@ -0,0 +1,39 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "cafCmdFeature.h"
#include <vector>
//==================================================================================================
///
//==================================================================================================
class RicConvertFractureTemplateUnitFeature : public caf::CmdFeature
{
CAF_CMD_HEADER_INIT;
protected:
virtual void onActionTriggered(bool isChecked) override;
virtual void setupActionLook(QAction* actionToSetup) override;
virtual bool isCommandEnabled() override;
};

View File

@ -24,7 +24,9 @@
#include "RimCase.h"
#include "RimCellRangeFilterCollection.h"
#include "RimEclipsePropertyFilterCollection.h"
#include "RimEclipseWell.h"
#include "RimFormationNamesCollection.h"
#include "RimFractureTemplateCollection.h"
#include "RimGeoMechPropertyFilterCollection.h"
#include "RimIntersectionCollection.h"
#include "RimProject.h"
@ -33,6 +35,7 @@
#include "RimWellLogPlot.h"
#include "RimWellLogPlotCollection.h"
#include "RimWellLogTrack.h"
#include "RimWellPath.h"
#include "RimWellPathCollection.h"
#include "cafNotificationCenter.h"
@ -118,8 +121,37 @@ void RicDeleteItemExec::redo()
view->scheduleCreateDisplayModelAndRedraw();
}
// SimWell Fractures
RimEclipseWell* eclipseWell;
parentObj->firstAncestorOrThisOfType(eclipseWell);
if (view && eclipseWell)
{
view->scheduleCreateDisplayModelAndRedraw();
}
RimFractureTemplateCollection* fracTemplateColl;
parentObj->firstAncestorOrThisOfType(fracTemplateColl);
if (fracTemplateColl)
{
RimProject* proj = nullptr;
parentObj->firstAncestorOrThisOfType(proj);
if (proj)
{
proj->createDisplayModelAndRedrawAllViews();
}
}
// Well paths
RimWellPath* wellPath;
parentObj->firstAncestorOrThisOfType(wellPath);
if (wellPath)
{
wellPath->updateConnectedEditors();
}
RimWellPathCollection* wellPathColl;
parentObj->firstAncestorOrThisOfType(wellPathColl);

View File

@ -26,6 +26,7 @@
#include "RimEclipsePropertyFilter.h"
#include "RimEclipseView.h"
#include "RimFishbonesMultipleSubs.h"
#include "RimEllipseFractureTemplate.h"
#include "RimFormationNames.h"
#include "RimFormationNamesCollection.h"
#include "RimGeoMechPropertyFilter.h"
@ -34,6 +35,9 @@
#include "RimIdenticalGridCaseGroup.h"
#include "RimIntersection.h"
#include "RimIntersectionBox.h"
#include "RimSimWellFracture.h"
#include "RimSimWellFractureCollection.h"
#include "RimStimPlanFractureTemplate.h"
#include "RimSummaryCurve.h"
#include "RimSummaryCurveFilter.h"
#include "RimSummaryPlot.h"
@ -47,6 +51,8 @@
#include "RimPerforationInterval.h"
#include "RimFlowCharacteristicsPlot.h"
#include "RimAsciiDataCurve.h"
#include "RimWellPathFracture.h"
#include "RimWellPathFractureCollection.h"
#include "cafCmdExecCommandManager.h"
#include "cafCmdSelectionHelper.h"
@ -100,6 +106,13 @@ bool isDeletable(caf::PdmUiItem* uiItem)
if (dynamic_cast<RimFishbonesMultipleSubs*>(uiItem)) return true;
if (dynamic_cast<RimPerforationInterval*>(uiItem)) return true;
if (dynamic_cast<RimAsciiDataCurve*>(uiItem)) return true;
if (dynamic_cast<RimWellPathFractureCollection*>(uiItem)) return true;
if (dynamic_cast<RimWellPathFracture*>(uiItem)) return true;
if (dynamic_cast<RimEllipseFractureTemplate*>(uiItem)) return true;
if (dynamic_cast<RimStimPlanFractureTemplate*>(uiItem)) return true;
if (dynamic_cast<RimSimWellFractureCollection*>(uiItem)) return true;
if (dynamic_cast<RimSimWellFracture*>(uiItem)) return true;
return false;
}

View File

@ -0,0 +1,56 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RicFractureNameGenerator.h"
#include "RiaApplication.h"
#include "RimProject.h"
#include "RimOilField.h"
#include "RimFracture.h"
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RicFractureNameGenerator::nameForNewFracture()
{
std::vector<RimFracture*> oldFractures;
RiaApplication::instance()->project()->activeOilField()->descendantsIncludingThisOfType(oldFractures);
size_t fractureNum = oldFractures.size();
bool found;
QString name;
do {
found = false;
name = QString("Fracture_%1").arg(fractureNum, 2, 10, QChar('0'));
for (RimFracture* fracture : oldFractures)
{
if (fracture->name() == name)
{
found = true;
break;
}
}
fractureNum++;
} while (found);
return name;
}

View File

@ -0,0 +1,30 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 <QString>
//==================================================================================================
///
//==================================================================================================
class RicFractureNameGenerator
{
public:
static QString nameForNewFracture();
};

View File

@ -0,0 +1,80 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2016- 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 "RicNewEllipseFractureTemplateFeature.h"
#include "RiaApplication.h"
#include "RimOilField.h"
#include "RimEllipseFractureTemplate.h"
#include "RimFractureTemplateCollection.h"
#include "RimProject.h"
#include "RiuMainWindow.h"
#include "cafSelectionManager.h"
#include "cvfAssert.h"
#include <QAction>
CAF_CMD_SOURCE_INIT(RicNewEllipseFractureTemplateFeature, "RicNewEllipseFractureTemplateFeature");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicNewEllipseFractureTemplateFeature::onActionTriggered(bool isChecked)
{
RimProject* project = RiaApplication::instance()->project();
CVF_ASSERT(project);
RimOilField* oilfield = project->activeOilField();
if (oilfield == nullptr) return;
RimFractureTemplateCollection* fracDefColl = oilfield->fractureDefinitionCollection();
if (fracDefColl)
{
RimEllipseFractureTemplate* fractureDef = new RimEllipseFractureTemplate();
fracDefColl->fractureDefinitions.push_back(fractureDef);
fractureDef->name = "Ellipse Fracture Template";
fractureDef->fractureTemplateUnit = fracDefColl->defaultUnitsForFracTemplates();
fractureDef->setDefaultWellDiameterFromUnit();
fracDefColl->updateConnectedEditors();
RiuMainWindow::instance()->selectAsCurrentItem(fractureDef);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicNewEllipseFractureTemplateFeature::setupActionLook(QAction* actionToSetup)
{
actionToSetup->setIcon(QIcon(":/FractureTemplate16x16.png"));
actionToSetup->setText("New Ellipse Fracture Template");
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RicNewEllipseFractureTemplateFeature::isCommandEnabled()
{
return true;
}

View File

@ -0,0 +1,39 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2016- 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 "cafCmdFeature.h"
#include <vector>
//==================================================================================================
///
//==================================================================================================
class RicNewEllipseFractureTemplateFeature : public caf::CmdFeature
{
CAF_CMD_HEADER_INIT;
protected:
virtual void onActionTriggered(bool isChecked) override;
virtual void setupActionLook(QAction* actionToSetup) override;
virtual bool isCommandEnabled() override;
};

View File

@ -0,0 +1,142 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2016- 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 "RicNewSimWellFractureAtPosFeature.h"
#include "RiaApplication.h"
#include "RigEclipseCaseData.h"
#include "RimCase.h"
#include "RimEclipseResultCase.h"
#include "RimEclipseWell.h"
#include "RimEllipseFractureTemplate.h"
#include "RimFractureTemplateCollection.h"
#include "RimOilField.h"
#include "RimProject.h"
#include "RimSimWellFracture.h"
#include "RimSimWellFractureCollection.h"
#include "RimView.h"
#include "RiuMainWindow.h"
#include "RiuSelectionManager.h"
#include "RivSimWellPipeSourceInfo.h"
#include "cafSelectionManager.h"
#include "cvfAssert.h"
#include <QAction>
CAF_CMD_SOURCE_INIT(RicNewSimWellFractureAtPosFeature, "RicNewSimWellFractureAtPosFeature");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicNewSimWellFractureAtPosFeature::onActionTriggered(bool isChecked)
{
RimView* activeView = RiaApplication::instance()->activeReservoirView();
if (!activeView) return;
RiuSelectionManager* riuSelManager = RiuSelectionManager::instance();
RiuSelectionItem* selItem = riuSelManager->selectedItem(RiuSelectionManager::RUI_TEMPORARY);
RiuSimWellSelectionItem* simWellItem = nullptr;
if (selItem->type() == RiuSelectionItem::SIMWELL_SELECTION_OBJECT)
{
simWellItem = static_cast<RiuSimWellSelectionItem*>(selItem);
if (!simWellItem) return;
}
RimEclipseWell* simWell = simWellItem->m_simWell;
if (!simWell) return;
RimSimWellFractureCollection* fractureCollection = simWell->simwellFractureCollection();
if (!fractureCollection) return;
RimSimWellFracture* fracture = new RimSimWellFracture();
fractureCollection->simwellFractures.push_back(fracture);
fracture->setClosestWellCoord(simWellItem->m_domainCoord, simWellItem->m_branchIndex);
RimOilField* oilfield = nullptr;
simWell->firstAncestorOrThisOfType(oilfield);
if (!oilfield) return;
std::vector<RimFracture* > oldFractures;
oilfield->descendantsIncludingThisOfType(oldFractures);
QString fracNum = QString("%1").arg(oldFractures.size(), 2, 10, QChar('0'));
fracture->setName(QString("Fracture_") + fracNum);
{
RimEclipseResultCase* eclipseCase = nullptr;
simWell->firstAncestorOrThisOfType(eclipseCase);
fracture->setFractureUnit(eclipseCase->eclipseCaseData()->unitsType());
}
if (oilfield->fractureDefinitionCollection->fractureDefinitions.size() > 0)
{
RimFractureTemplate* fracDef = oilfield->fractureDefinitionCollection->fractureDefinitions[0];
fracture->setFractureTemplate(fracDef);
}
simWell->updateConnectedEditors();
RiuMainWindow::instance()->selectAsCurrentItem(fracture);
activeView->scheduleCreateDisplayModelAndRedraw();
RimEclipseCase* eclipseCase = nullptr;
simWell->firstAncestorOrThisOfType(eclipseCase);
if (eclipseCase)
{
RimProject* project;
eclipseCase->firstAncestorOrThisOfTypeAsserted(project);
project->reloadCompletionTypeResultsForEclipseCase(eclipseCase);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicNewSimWellFractureAtPosFeature::setupActionLook(QAction* actionToSetup)
{
actionToSetup->setIcon(QIcon(":/FractureSymbol16x16.png"));
actionToSetup->setText("New Fracture");
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RicNewSimWellFractureAtPosFeature::isCommandEnabled()
{
caf::PdmUiItem* pdmUiItem = caf::SelectionManager::instance()->selectedItem();
if (!pdmUiItem) return false;
caf::PdmObjectHandle* objHandle = dynamic_cast<caf::PdmObjectHandle*>(pdmUiItem);
if (!objHandle) return false;
RimEclipseWell* eclipseWell = nullptr;
objHandle->firstAncestorOrThisOfType(eclipseWell);
if (eclipseWell)
{
return true;
}
return false;
}

View File

@ -0,0 +1,39 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2016- 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 "cafCmdFeature.h"
#include <vector>
//==================================================================================================
///
//==================================================================================================
class RicNewSimWellFractureAtPosFeature : public caf::CmdFeature
{
CAF_CMD_HEADER_INIT;
protected:
virtual void onActionTriggered(bool isChecked) override;
virtual void setupActionLook(QAction* actionToSetup) override;
virtual bool isCommandEnabled() override;
};

View File

@ -0,0 +1,127 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2016- 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 "RicNewSimWellFractureFeature.h"
#include "RicFractureNameGenerator.h"
#include "RiaApplication.h"
#include "RigEclipseCaseData.h"
#include "RimCase.h"
#include "RimEclipseResultCase.h"
#include "RimEclipseView.h"
#include "RimEclipseWell.h"
#include "RimEllipseFractureTemplate.h"
#include "RimFractureTemplateCollection.h"
#include "RimOilField.h"
#include "RimProject.h"
#include "RimSimWellFracture.h"
#include "RimSimWellFractureCollection.h"
#include "RimEclipseCase.h"
#include "RiuMainWindow.h"
#include "cafSelectionManager.h"
#include "cvfAssert.h"
#include <QAction>
CAF_CMD_SOURCE_INIT(RicNewSimWellFractureFeature, "RicNewSimWellFractureFeature");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicNewSimWellFractureFeature::onActionTriggered(bool isChecked)
{
caf::PdmUiItem* pdmUiItem = caf::SelectionManager::instance()->selectedItem();
if (!pdmUiItem) return;
caf::PdmObjectHandle* objHandle = dynamic_cast<caf::PdmObjectHandle*>(pdmUiItem);
if (!objHandle) return;
RimEclipseWell* eclipseWell = nullptr;
objHandle->firstAncestorOrThisOfType(eclipseWell);
RimSimWellFracture* fracture = new RimSimWellFracture();
eclipseWell->simwellFractureCollection()->simwellFractures.push_back(fracture);
RimOilField* oilfield = nullptr;
objHandle->firstAncestorOrThisOfType(oilfield);
if (!oilfield) return;
fracture->setName(RicFractureNameGenerator::nameForNewFracture());
{
RimEclipseResultCase* eclipseCase = nullptr;
objHandle->firstAncestorOrThisOfType(eclipseCase);
fracture->setFractureUnit(eclipseCase->eclipseCaseData()->unitsType());
}
if (oilfield->fractureDefinitionCollection->fractureDefinitions.size() > 0)
{
RimFractureTemplate* fracDef = oilfield->fractureDefinitionCollection->fractureDefinitions[0];
fracture->setFractureTemplate(fracDef);
}
fracture->updateFracturePositionFromLocation();
eclipseWell->updateConnectedEditors();
RiuMainWindow::instance()->selectAsCurrentItem(fracture);
RimEclipseCase* eclipseCase = nullptr;
objHandle->firstAncestorOrThisOfType(eclipseCase);
if (eclipseCase)
{
RimProject* project;
objHandle->firstAncestorOrThisOfTypeAsserted(project);
project->reloadCompletionTypeResultsForEclipseCase(eclipseCase);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicNewSimWellFractureFeature::setupActionLook(QAction* actionToSetup)
{
actionToSetup->setIcon(QIcon(":/FractureSymbol16x16.png"));
actionToSetup->setText("New Fracture");
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RicNewSimWellFractureFeature::isCommandEnabled()
{
caf::PdmUiItem* pdmUiItem = caf::SelectionManager::instance()->selectedItem();
if (!pdmUiItem) return false;
caf::PdmObjectHandle* objHandle = dynamic_cast<caf::PdmObjectHandle*>(pdmUiItem);
if (!objHandle) return false;
RimEclipseWell* eclipseWell = nullptr;
objHandle->firstAncestorOrThisOfType(eclipseWell);
if (eclipseWell)
{
return true;
}
return false;
}

View File

@ -0,0 +1,39 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2016- 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 "cafCmdFeature.h"
#include <vector>
//==================================================================================================
///
//==================================================================================================
class RicNewSimWellFractureFeature : public caf::CmdFeature
{
CAF_CMD_HEADER_INIT;
protected:
virtual void onActionTriggered(bool isChecked) override;
virtual void setupActionLook(QAction* actionToSetup) override;
virtual bool isCommandEnabled() override;
};

View File

@ -0,0 +1,89 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RicNewStimPlanFractureTemplateFeature.h"
#include "RiaApplication.h"
#include "RimOilField.h"
#include "RimFractureTemplateCollection.h"
#include "RimProject.h"
#include "RimStimPlanFractureTemplate.h"
#include "RiuMainWindow.h"
#include "cafSelectionManager.h"
#include "cvfAssert.h"
#include <QAction>
#include <QFileDialog>
CAF_CMD_SOURCE_INIT(RicNewStimPlanFractureTemplateFeature, "RicNewStimPlanFractureTemplateFeature");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicNewStimPlanFractureTemplateFeature::onActionTriggered(bool isChecked)
{
RiaApplication* app = RiaApplication::instance();
QString defaultDir = app->lastUsedDialogDirectory("BINARY_GRID");
QString fileName = QFileDialog::getOpenFileName(NULL, "Open StimPlan XML File", defaultDir, "StimPlan XML File (*.xml);;All files(*.*)");
if (fileName.isEmpty()) return;
RimProject* project = RiaApplication::instance()->project();
CVF_ASSERT(project);
RimOilField* oilfield = project->activeOilField();
if (oilfield == nullptr) return;
RimFractureTemplateCollection* fracDefColl = oilfield->fractureDefinitionCollection();
if (fracDefColl)
{
RimStimPlanFractureTemplate* fractureDef = new RimStimPlanFractureTemplate();
fracDefColl->fractureDefinitions.push_back(fractureDef);
fractureDef->name = "StimPlan Fracture Template";
fractureDef->setFileName(fileName);
fractureDef->loadDataAndUpdate();
fractureDef->setDefaultsBasedOnXMLfile();
fractureDef->setDefaultWellDiameterFromUnit();
fracDefColl->updateConnectedEditors();
RiuMainWindow::instance()->selectAsCurrentItem(fractureDef);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicNewStimPlanFractureTemplateFeature::setupActionLook(QAction* actionToSetup)
{
actionToSetup->setIcon(QIcon(":/FractureTemplate16x16.png"));
actionToSetup->setText("New StimPlan Fracture Template");
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RicNewStimPlanFractureTemplateFeature::isCommandEnabled()
{
return true;
}

View File

@ -0,0 +1,39 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "cafCmdFeature.h"
#include <vector>
//==================================================================================================
///
//==================================================================================================
class RicNewStimPlanFractureTemplateFeature : public caf::CmdFeature
{
CAF_CMD_HEADER_INIT;
protected:
virtual void onActionTriggered(bool isChecked) override;
virtual void setupActionLook(QAction* actionToSetup) override;
virtual bool isCommandEnabled() override;
};

View File

@ -0,0 +1,65 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2016- 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 "RicNewWellPathFractureAtPosFeature.h"
#include "RiaApplication.h"
#include "RicNewWellPathFractureFeature.h"
#include "RiuSelectionManager.h"
#include <QAction>
CAF_CMD_SOURCE_INIT(RicNewWellPathFractureAtPosFeature, "RicNewWellPathFractureAtPosFeature");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicNewWellPathFractureAtPosFeature::onActionTriggered(bool isChecked)
{
RiuSelectionManager* riuSelManager = RiuSelectionManager::instance();
RiuSelectionItem* selItem = riuSelManager->selectedItem(RiuSelectionManager::RUI_TEMPORARY);
RiuWellPathSelectionItem* wellPathItem = dynamic_cast<RiuWellPathSelectionItem*>(selItem);
if (!wellPathItem) return;
RimWellPath* wellPath = wellPathItem->m_wellpath;
if (!wellPath) return;
RicNewWellPathFractureFeature::addFracture(wellPath, wellPathItem->m_measuredDepth);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicNewWellPathFractureAtPosFeature::setupActionLook(QAction* actionToSetup)
{
actionToSetup->setIcon(QIcon(":/FractureSymbol16x16.png"));
actionToSetup->setText("New Fracture");
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RicNewWellPathFractureAtPosFeature::isCommandEnabled()
{
return true;
}

View File

@ -0,0 +1,37 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2016- 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 "cafCmdFeature.h"
#include <vector>
//==================================================================================================
///
//==================================================================================================
class RicNewWellPathFractureAtPosFeature : public caf::CmdFeature
{
CAF_CMD_HEADER_INIT;
protected:
virtual void onActionTriggered(bool isChecked) override;
virtual void setupActionLook(QAction* actionToSetup) override;
virtual bool isCommandEnabled() override;
};

View File

@ -0,0 +1,157 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2016- 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 "RicNewWellPathFractureFeature.h"
#include "RicFractureNameGenerator.h"
#include "RiaApplication.h"
#include "RigWellPath.h"
#include "RimCase.h"
#include "RimEllipseFractureTemplate.h"
#include "RimFractureTemplateCollection.h"
#include "RimOilField.h"
#include "RimProject.h"
#include "RimWellPath.h"
#include "RimWellPathCollection.h"
#include "RimWellPathFracture.h"
#include "RimWellPathFractureCollection.h"
#include "RiuMainWindow.h"
#include "WellPathCommands/RicWellPathsUnitSystemSettingsImpl.h"
#include "cafSelectionManager.h"
#include "cvfAssert.h"
#include <QAction>
CAF_CMD_SOURCE_INIT(RicNewWellPathFractureFeature, "RicNewWellPathFractureFeature");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicNewWellPathFractureFeature::addFracture(RimWellPath* wellPath, double measuredDepth)
{
CVF_ASSERT(wellPath);
if (!RicWellPathsUnitSystemSettingsImpl::ensureHasUnitSystem(wellPath)) return;
RimWellPathFractureCollection* fractureCollection = wellPath->fractureCollection();
CVF_ASSERT(fractureCollection);
RimWellPathFracture* fracture = new RimWellPathFracture();
fractureCollection->fractures.push_back(fracture);
fracture->setMeasuredDepth(measuredDepth);
fracture->setFractureUnit(wellPath->unitSystem());
RigWellPath* wellPathGeometry = wellPath->wellPathGeometry();
cvf::Vec3d positionAtWellpath = wellPathGeometry->interpolatedPointAlongWellPath(measuredDepth);
fracture->setAnchorPosition(positionAtWellpath);
RimOilField* oilfield = nullptr;
fractureCollection->firstAncestorOrThisOfType(oilfield);
if (!oilfield) return;
fracture->setName(RicFractureNameGenerator::nameForNewFracture());
if (oilfield->fractureDefinitionCollection->fractureDefinitions.size() > 0)
{
RimFractureTemplate* fracDef = oilfield->fractureDefinitionCollection->fractureDefinitions[0];
fracture->setFractureTemplate(fracDef);
}
wellPath->updateConnectedEditors();
RiuMainWindow::instance()->selectAsCurrentItem(fracture);
RimProject* project = nullptr;
fractureCollection->firstAncestorOrThisOfType(project);
if (project)
{
project->reloadCompletionTypeResultsInAllViews();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicNewWellPathFractureFeature::onActionTriggered(bool isChecked)
{
RimWellPathFractureCollection* fractureColl = RicNewWellPathFractureFeature::selectedWellPathFractureCollection();
if (!fractureColl) return;
RimWellPath* wellPath = nullptr;
fractureColl->firstAncestorOrThisOfTypeAsserted(wellPath);
double defaultMeasuredDepth = 0.0f;
RicNewWellPathFractureFeature::addFracture(wellPath, defaultMeasuredDepth);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicNewWellPathFractureFeature::setupActionLook(QAction* actionToSetup)
{
actionToSetup->setIcon(QIcon(":/FractureSymbol16x16.png"));
actionToSetup->setText("New Fracture");
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RicNewWellPathFractureFeature::isCommandEnabled()
{
if (selectedWellPathFractureCollection())
{
return true;
}
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimWellPathFractureCollection* RicNewWellPathFractureFeature::selectedWellPathFractureCollection()
{
RimWellPathFractureCollection* objToFind = nullptr;
caf::PdmUiItem* pdmUiItem = caf::SelectionManager::instance()->selectedItem();
caf::PdmObjectHandle* objHandle = dynamic_cast<caf::PdmObjectHandle*>(pdmUiItem);
if (objHandle)
{
objHandle->firstAncestorOrThisOfType(objToFind);
}
if (objToFind == nullptr)
{
std::vector<RimWellPath*> wellPaths;
caf::SelectionManager::instance()->objectsByType(&wellPaths);
if (!wellPaths.empty())
{
return wellPaths[0]->fractureCollection();
}
}
return objToFind;
}

View File

@ -0,0 +1,45 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2016- 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 "cafCmdFeature.h"
#include <vector>
class RimWellPathFractureCollection;
class RimWellPath;
//==================================================================================================
///
//==================================================================================================
class RicNewWellPathFractureFeature : public caf::CmdFeature
{
CAF_CMD_HEADER_INIT;
public:
static void addFracture(RimWellPath* wellPath, double measuredDepth);
protected:
virtual void onActionTriggered(bool isChecked) override;
virtual void setupActionLook(QAction* actionToSetup) override;
virtual bool isCommandEnabled() override;
private:
static RimWellPathFractureCollection* selectedWellPathFractureCollection();
};

View File

@ -63,6 +63,10 @@ bool RicWellPathViewerEventHandler::handleEvent(cvf::Object* eventObject)
cvf::Vec3d domainCoord = transForm->transformToDomainCoord(uiEvent->globalIntersectionPoint);
double measuredDepth = wellPathSourceInfo->measuredDepth(uiEvent->firstPartTriangleIndex, domainCoord);
// NOTE: This computation was used to find the location for a fracture when clicking on a well path
// It turned out that the computation was a bit inaccurate
// Consider to use code in RigSimulationWellCoordsAndMD instead
cvf::Vec3d trueVerticalDepth = wellPathSourceInfo->trueVerticalDepth(uiEvent->firstPartTriangleIndex, domainCoord);
QString wellPathText;

View File

@ -28,6 +28,12 @@ ${CEE_CURRENT_LIST_DIR}RifHdf5ReaderInterface.h
#${CEE_CURRENT_LIST_DIR}RifHdf5Reader.h
)
if (RESINSIGHT_ENABLE_PROTOTYPE_FEATURE_FRACTURES)
list (APPEND SOURCE_GROUP_HEADER_FILES
${CEE_CURRENT_LIST_DIR}RifStimPlanXmlReader.h
)
endif()
set (SOURCE_GROUP_SOURCE_FILES
${CEE_CURRENT_LIST_DIR}RifEclipseDataTableFormatter.cpp
${CEE_CURRENT_LIST_DIR}RifEclipseInputFileTools.cpp
@ -52,6 +58,12 @@ ${CEE_CURRENT_LIST_DIR}RifHdf5ReaderInterface.cpp
#${CEE_CURRENT_LIST_DIR}RifHdf5Reader.cpp
)
if (RESINSIGHT_ENABLE_PROTOTYPE_FEATURE_FRACTURES)
list (APPEND SOURCE_GROUP_SOURCE_FILES
${CEE_CURRENT_LIST_DIR}RifStimPlanXmlReader.cpp
)
endif()
list(APPEND CODE_HEADER_FILES
${SOURCE_GROUP_HEADER_FILES}
)

View File

@ -0,0 +1,301 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RifStimPlanXmlReader.h"
#include "RiaEclipseUnitTools.h"
#include "RigStimPlanFractureDefinition.h"
#include "RiaLogging.h"
#include <QFile>
#include <QXmlStreamReader>
#include <cmath> // Needed for HUGE_VAL on Linux
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::ref<RigStimPlanFractureDefinition> RifStimPlanXmlReader::readStimPlanXMLFile(const QString& stimPlanFileName,
double conductivityScalingFactor,
QString * errorMessage)
{
RiaLogging::info(QString("Starting to open StimPlan XML file: '%1'").arg(stimPlanFileName));
RiaEclipseUnitTools::UnitSystemType unitSystem = RiaEclipseUnitTools::UNITS_UNKNOWN;
cvf::ref<RigStimPlanFractureDefinition> stimPlanFileData = new RigStimPlanFractureDefinition;
size_t startingNegXsValues = 0;
{
QFile dataFile(stimPlanFileName);
if (!dataFile.open(QFile::ReadOnly))
{
if (errorMessage) (*errorMessage) += "Could not open the File: " + (stimPlanFileName) + "\n";
return nullptr;
}
QXmlStreamReader xmlStream;
xmlStream.setDevice(&dataFile);
xmlStream.readNext();
startingNegXsValues = readStimplanGridAndTimesteps(xmlStream, stimPlanFileData.p(), unitSystem);
stimPlanFileData->setUnitSet(unitSystem);
if (unitSystem != RiaEclipseUnitTools::UNITS_UNKNOWN)
RiaLogging::info(QString("Setting unit system for StimPlan fracture template %1 to %2").arg(stimPlanFileName).arg(unitSystem.uiText()));
else
RiaLogging::error(QString("Found invalid units for %1. Unit system not set.").arg(stimPlanFileName));
if (xmlStream.hasError())
{
RiaLogging::error(QString("Failed to parse file '%1'").arg(dataFile.fileName()));
RiaLogging::error(xmlStream.errorString());
}
dataFile.close();
}
size_t numberOfDepthValues = stimPlanFileData->depthCount();
RiaLogging::debug(QString("Grid size X: %1, Y: %2").arg(QString::number(stimPlanFileData->gridXCount()),
QString::number(numberOfDepthValues)));
size_t numberOfTimeSteps = stimPlanFileData->timeSteps().size();
RiaLogging::debug(QString("Number of time-steps: %1").arg(numberOfTimeSteps));
//Start reading from top:
QFile dataFile(stimPlanFileName);
if (!dataFile.open(QFile::ReadOnly))
{
if (errorMessage) (*errorMessage) += "Could not open the File: " + (stimPlanFileName) + "\n";
return nullptr;
}
QXmlStreamReader xmlStream2;
xmlStream2.setDevice(&dataFile);
QString parameter;
QString unit;
RiaLogging::info(QString("Properties available in file:"));
while (!xmlStream2.atEnd())
{
xmlStream2.readNext();
if (xmlStream2.isStartElement())
{
if (xmlStream2.name() == "property")
{
unit = getAttributeValueString(xmlStream2, "uom");
parameter = getAttributeValueString(xmlStream2, "name");
RiaLogging::info(QString("%1 [%2]").arg(parameter, unit));
}
else if (xmlStream2.name() == "time")
{
double timeStepValue = getAttributeValueDouble(xmlStream2, "value");
std::vector<std::vector<double>> propertyValuesAtTimestep = getAllDepthDataAtTimeStep(xmlStream2, startingNegXsValues);
bool valuesOK = stimPlanFileData->numberOfParameterValuesOK(propertyValuesAtTimestep);
if (!valuesOK)
{
RiaLogging::error(QString("Inconsistency detected in reading XML file: '%1'").arg(dataFile.fileName()));
return nullptr;
}
stimPlanFileData->setDataAtTimeValue(parameter, unit, propertyValuesAtTimestep, timeStepValue, conductivityScalingFactor);
}
}
}
dataFile.close();
if (xmlStream2.hasError())
{
RiaLogging::error(QString("Failed to parse file: '%1'").arg(dataFile.fileName()));
RiaLogging::error(xmlStream2.errorString());
}
else if (dataFile.error() != QFile::NoError)
{
RiaLogging::error(QString("Cannot read file: '%1'").arg(dataFile.fileName()));
RiaLogging::error(dataFile.errorString());
}
else
{
RiaLogging::info(QString("Successfully read XML file: '%1'").arg(stimPlanFileName));
}
return stimPlanFileData;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t RifStimPlanXmlReader::readStimplanGridAndTimesteps(QXmlStreamReader &xmlStream, RigStimPlanFractureDefinition* stimPlanFileData, RiaEclipseUnitTools::UnitSystemType& unit)
{
size_t startNegValuesXs = 0;
size_t startNegValuesYs = 0;
QString gridunit = "unknown";
xmlStream.readNext();
//First, read time steps and grid to establish data structures for putting data into later.
while (!xmlStream.atEnd())
{
xmlStream.readNext();
if (xmlStream.isStartElement())
{
if (xmlStream.name() == "grid")
{
gridunit = getAttributeValueString(xmlStream, "uom");
}
if (xmlStream.name() == "xs")
{
std::vector<double> gridValues;
getGriddingValues(xmlStream, gridValues, startNegValuesXs);
stimPlanFileData->setGridXs(gridValues);
}
else if (xmlStream.name() == "ys")
{
std::vector<double> gridValues;
getGriddingValues(xmlStream, gridValues, startNegValuesYs);
stimPlanFileData->setGridYs(gridValues);
stimPlanFileData->reorderYgridToDepths();
}
else if (xmlStream.name() == "time")
{
double timeStepValue = getAttributeValueDouble(xmlStream, "value");
stimPlanFileData->addTimeStep(timeStepValue);
}
}
}
if (gridunit == "m") unit = RiaEclipseUnitTools::UNITS_METRIC;
else if (gridunit == "ft") unit = RiaEclipseUnitTools::UNITS_FIELD;
else unit = RiaEclipseUnitTools::UNITS_UNKNOWN;
if (startNegValuesYs > 0)
{
RiaLogging::error(QString("Negative depth values detected in XML file"));
}
return startNegValuesXs;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<std::vector<double>> RifStimPlanXmlReader::getAllDepthDataAtTimeStep(QXmlStreamReader &xmlStream, size_t startingNegValuesXs)
{
std::vector<std::vector<double>> propertyValuesAtTimestep;
while (!(xmlStream.isEndElement() && xmlStream.name() == "time"))
{
xmlStream.readNext();
if (xmlStream.name() == "depth")
{
double depth = xmlStream.readElementText().toDouble();
std::vector<double> propertyValuesAtDepth;
xmlStream.readNext(); //read end depth token
xmlStream.readNext(); //read cdata section with values
if (xmlStream.isCDATA())
{
QString depthDataStr = xmlStream.text().toString();
for (int i = 0; i < depthDataStr.split(' ').size(); i++)
{
if (i < static_cast<int>(startingNegValuesXs)) continue;
else
{
QString value = depthDataStr.split(' ')[i];
if ( value != "")
{
propertyValuesAtDepth.push_back(value.toDouble());
}
}
}
}
propertyValuesAtTimestep.push_back(propertyValuesAtDepth);
}
}
return propertyValuesAtTimestep;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RifStimPlanXmlReader::getGriddingValues(QXmlStreamReader &xmlStream, std::vector<double>& gridValues, size_t& startNegValues)
{
QString gridValuesString = xmlStream.readElementText().replace('\n', ' ');
for (QString value : gridValuesString.split(' '))
{
if (value.size() > 0)
{
double gridValue = value.toDouble();
if (gridValue > -1e-5) //tolerance of 1e-5
{
gridValues.push_back(gridValue);
}
else startNegValues++;
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RifStimPlanXmlReader::getAttributeValueDouble(QXmlStreamReader &xmlStream, QString parameterName)
{
double value = HUGE_VAL;
for (const QXmlStreamAttribute &attr : xmlStream.attributes())
{
if (attr.name() == parameterName)
{
value = attr.value().toString().toDouble();
}
}
return value;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RifStimPlanXmlReader::getAttributeValueString(QXmlStreamReader &xmlStream, QString parameterName)
{
QString parameterValue;
for (const QXmlStreamAttribute &attr : xmlStream.attributes())
{
if (attr.name() == parameterName)
{
parameterValue = attr.value().toString();
}
}
return parameterValue;
}

View File

@ -0,0 +1,49 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RiaEclipseUnitTools.h"
#include "cvfBase.h"
#include "cvfObject.h"
#include <QString>
#include <vector>
class RigStimPlanFractureDefinition;
class QXmlStreamReader;
class RifStimPlanXmlReader
{
public:
static cvf::ref<RigStimPlanFractureDefinition> readStimPlanXMLFile(const QString& stimPlanFileName, double conductivityScalingFactor, QString * errorMessage);
private:
static size_t readStimplanGridAndTimesteps(QXmlStreamReader &xmlStream, RigStimPlanFractureDefinition* stimPlanFileData, RiaEclipseUnitTools::UnitSystemType& unit);
static double getAttributeValueDouble(QXmlStreamReader &xmlStream, QString parameterName);
static QString getAttributeValueString(QXmlStreamReader &xmlStream, QString parameterName);
static void getGriddingValues(QXmlStreamReader &xmlStream, std::vector<double>& gridValues, size_t& startNegValues);
static std::vector<std::vector<double>> getAllDepthDataAtTimeStep(QXmlStreamReader &xmlStream, size_t startingNegValuesXs);
};

View File

@ -41,6 +41,13 @@ ${CEE_CURRENT_LIST_DIR}RivWellConnectionsPartMgr.h
${CEE_CURRENT_LIST_DIR}RivFishbonesSubsPartMgr.h
)
if (RESINSIGHT_ENABLE_PROTOTYPE_FEATURE_FRACTURES)
list (APPEND SOURCE_GROUP_HEADER_FILES
${CEE_CURRENT_LIST_DIR}RivWellFracturePartMgr.h
)
endif()
set (SOURCE_GROUP_SOURCE_FILES
${CEE_CURRENT_LIST_DIR}RivCellEdgeEffectGenerator.cpp
${CEE_CURRENT_LIST_DIR}RivFaultPartMgr.cpp
@ -73,6 +80,12 @@ ${CEE_CURRENT_LIST_DIR}RivWellConnectionsPartMgr.cpp
${CEE_CURRENT_LIST_DIR}RivFishbonesSubsPartMgr.cpp
)
if (RESINSIGHT_ENABLE_PROTOTYPE_FEATURE_FRACTURES)
list (APPEND SOURCE_GROUP_SOURCE_FILES
${CEE_CURRENT_LIST_DIR}RivWellFracturePartMgr.cpp
)
endif()
list(APPEND CODE_HEADER_FILES
${SOURCE_GROUP_HEADER_FILES}
)

View File

@ -58,9 +58,10 @@ public:
cvf::ref<cvf::DrawableGeo> createMeshDrawable();
cvf::ref<cvf::DrawableGeo> createOutlineMeshDrawable(double creaseAngle);
private:
static cvf::ref<cvf::UIntArray> lineIndicesFromQuadVertexArray(const cvf::Vec3fArray* vertexArray);
private:
void computeArrays();
private:

View File

@ -21,9 +21,12 @@
#pragma once
#include "cvfBase.h"
#include "cvfObject.h"
#include "cvfArray.h"
#include "cvfPart.h"
#include "cvfColor3.h"
#include "cvfVector3.h"
#include <vector>
namespace cvf {
class DrawableGeo;

View File

@ -19,7 +19,9 @@
#include "RivSimWellPipeSourceInfo.h"
#include "RimEclipseView.h"
#include "RimEclipseWell.h"
#include "RimEclipseWellCollection.h"
//--------------------------------------------------------------------------------------------------
@ -46,3 +48,4 @@ size_t RivSimWellPipeSourceInfo::branchIndex() const
{
return m_branchIndex;
}

View File

@ -167,6 +167,7 @@ RivSimWellPipesPartMgr::RivPipeBranchData* RivSimWellPipesPartMgr::pipeBranchDat
while (i < branchIndex)
{
brIt++;
i++;
}
return &(*brIt);

View File

@ -0,0 +1,682 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RivWellFracturePartMgr.h"
#include "RiaApplication.h"
#include "RigFractureGrid.h"
#include "RigMainGrid.h"
#include "RigHexIntersectionTools.h"
#include "RigCellGeometryTools.h"
#include "RimEclipseView.h"
#include "RimEclipseWell.h"
#include "RimFracture.h"
#include "RimFractureContainment.h"
#include "RimFractureTemplate.h"
#include "RimLegendConfig.h"
#include "RigFractureCell.h"
#include "RimStimPlanColors.h"
#include "RimStimPlanFractureTemplate.h"
#include "RivFaultGeometryGenerator.h"
#include "RivPartPriority.h"
#include "RivObjectSourceInfo.h"
#include "cafDisplayCoordTransform.h"
#include "cafEffectGenerator.h"
#include "cvfDrawableGeo.h"
#include "cvfGeometryTools.h"
#include "cvfModelBasicList.h"
#include "cvfPart.h"
#include "cvfPrimitiveSet.h"
#include "cvfPrimitiveSetDirect.h"
#include "cvfPrimitiveSetIndexedUInt.h"
#include "cvfScalarMapperContinuousLinear.h"
#include "cvfRenderStateDepth.h"
#include <array>
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RivWellFracturePartMgr::RivWellFracturePartMgr(RimFracture* fracture)
: m_rimFracture(fracture)
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RivWellFracturePartMgr::~RivWellFracturePartMgr()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RivWellFracturePartMgr::generateSurfacePart(const caf::DisplayCoordTransform* displayCoordTransform)
{
if (m_surfacePart.notNull()) return;
if (!displayCoordTransform) return;
if (m_rimFracture)
{
std::vector<cvf::Vec3f> nodeCoords;
std::vector<cvf::uint> triangleIndices;
m_rimFracture->triangleGeometry(&triangleIndices, &nodeCoords);
std::vector<cvf::Vec3f> displayCoords;
for (size_t i = 0; i < nodeCoords.size(); i++)
{
cvf::Vec3d nodeCoordsDouble = static_cast<cvf::Vec3d>(nodeCoords[i]);
cvf::Vec3d displayCoordsDouble = displayCoordTransform->transformToDisplayCoord(nodeCoordsDouble);
displayCoords.push_back(static_cast<cvf::Vec3f>(displayCoordsDouble));
}
if (triangleIndices.size() == 0 || displayCoords.size() == 0)
{
return;
}
cvf::ref<cvf::DrawableGeo> geo = buildDrawableGeoFromTriangles(triangleIndices, displayCoords);
CVF_ASSERT(geo.notNull());
m_surfacePart = new cvf::Part(0, "FractureSurfacePart");
m_surfacePart->setDrawable(geo.p());
m_surfacePart->setSourceInfo(new RivObjectSourceInfo(m_rimFracture));
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RivWellFracturePartMgr::generateContainmentMaskPart(const RimEclipseView* activeView)
{
std::vector<cvf::Vec3f> borderPolygonLocalCS = m_rimFracture->fractureTemplate()->fractureBorderPolygon(m_rimFracture->fractureUnit());
cvf::Mat4d frMx = m_rimFracture->transformMatrix();
cvf::BoundingBox frBBox;
std::vector<cvf::Vec3d> borderPolygonGlobCs;
std::vector<cvf::Vec3d> borderPolygonLocalCsd;
for (const auto& pv: borderPolygonLocalCS)
{
cvf::Vec3d pvd(pv);
borderPolygonLocalCsd.push_back(pvd);
pvd.transformPoint(frMx);
borderPolygonGlobCs.push_back(pvd);
frBBox.add(pvd);
}
std::vector<size_t> cellCandidates;
activeView->mainGrid()->findIntersectingCells(frBBox, &cellCandidates);
auto displCoordTrans = activeView->displayCoordTransform();
std::vector<cvf::Vec3f> maskTriangles;
for (size_t resCellIdx : cellCandidates)
{
if (!m_rimFracture->isEclipseCellWithinContainment(activeView->mainGrid(), resCellIdx))
{
// Calculate Eclipse cell intersection with fracture plane
std::array<cvf::Vec3d,8> corners;
activeView->mainGrid()->cellCornerVertices(resCellIdx, corners.data());
std::vector<std::vector<cvf::Vec3d> > eclCellPolygons;
bool hasIntersection = RigHexIntersectionTools::planeHexIntersectionPolygons(corners, frMx, eclCellPolygons);
if (!hasIntersection || eclCellPolygons.empty()) continue;
// Transform eclCell - plane intersection onto fracture
cvf::Mat4d invertedTransformMatrix = frMx.getInverted();
for ( std::vector<cvf::Vec3d>& eclCellPolygon : eclCellPolygons )
{
for ( cvf::Vec3d& v : eclCellPolygon )
{
v.transformPoint(invertedTransformMatrix);
}
}
cvf::Vec3d fractureNormal = cvf::Vec3d(frMx.col(2));
cvf::Vec3d maskOffset = fractureNormal * 0.01 * frBBox.radius();
for (const std::vector<cvf::Vec3d>& eclCellPolygon : eclCellPolygons)
{
// Clip Eclipse cell polygon with fracture border
std::vector< std::vector<cvf::Vec3d> > clippedPolygons = RigCellGeometryTools::intersectPolygons(eclCellPolygon,
borderPolygonLocalCsd);
for (auto& clippedPolygon : clippedPolygons)
{
for (auto& v: clippedPolygon)
{
v.transformPoint(frMx);
}
}
// Create triangles from the clipped polygons
for (auto& clippedPolygon : clippedPolygons)
{
cvf::EarClipTesselator tess;
tess.setNormal(fractureNormal);
cvf::Vec3dArray cvfNodes(clippedPolygon);
tess.setGlobalNodeArray(cvfNodes);
std::vector<size_t> polyIndexes;
for (size_t idx = 0; idx < clippedPolygon.size(); ++idx) polyIndexes.push_back(idx);
tess.setPolygonIndices(polyIndexes);
std::vector<size_t> triangleIndices;
tess.calculateTriangles(&triangleIndices);
for (size_t idx: triangleIndices)
{
maskTriangles.push_back( cvf::Vec3f( displCoordTrans->transformToDisplayCoord(clippedPolygon[idx] + maskOffset)) );
}
for (size_t idx: triangleIndices)
{
maskTriangles.push_back( cvf::Vec3f( displCoordTrans->transformToDisplayCoord(clippedPolygon[idx] - maskOffset)) );
}
}
}
}
}
if ( maskTriangles.size() >= 3 )
{
cvf::ref<cvf::DrawableGeo> maskTriangleGeo = new cvf::DrawableGeo;
maskTriangleGeo->setVertexArray(new cvf::Vec3fArray(maskTriangles));
cvf::ref<cvf::PrimitiveSetDirect> primitives = new cvf::PrimitiveSetDirect(cvf::PT_TRIANGLES);
primitives->setIndexCount(maskTriangles.size());
maskTriangleGeo->addPrimitiveSet(primitives.p());
maskTriangleGeo->computeNormals();
m_containmentMaskPart = new cvf::Part(0, "FractureContainmentMaskPart");
m_containmentMaskPart->setDrawable(maskTriangleGeo.p());
m_containmentMaskPart->setSourceInfo(new RivObjectSourceInfo(m_rimFracture));
cvf::Color4f maskColor = cvf::Color4f(cvf::Color3f(cvf::Color3::GRAY));
caf::SurfaceEffectGenerator surfaceGen(maskColor, caf::PO_NONE);
cvf::ref<cvf::Effect> eff = surfaceGen.generateCachedEffect();
m_containmentMaskPart->setEffect(eff.p());
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RivWellFracturePartMgr::applyFractureUniformColor(const RimEclipseView* activeView)
{
if ( m_surfacePart.notNull() )
{
cvf::Color4f fractureColor = cvf::Color4f(cvf::Color3f(cvf::Color3::BROWN));
if ( activeView )
{
fractureColor = cvf::Color4f(activeView->stimPlanColors->defaultColor());
}
caf::SurfaceEffectGenerator surfaceGen(fractureColor, caf::PO_1);
cvf::ref<cvf::Effect> eff = surfaceGen.generateCachedEffect();
m_surfacePart->setEffect(eff.p());
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RivWellFracturePartMgr::applyResultTextureColor(const RimEclipseView* activeView)
{
if (m_surfacePart.isNull()) return;
if (m_rimFracture)
{
RimLegendConfig* legendConfig = nullptr;
if (activeView && activeView->stimPlanColors())
{
if (activeView->stimPlanColors()->isChecked())
{
legendConfig = activeView->stimPlanColors()->activeLegend();
}
}
RimFractureTemplate* fracTemplate = m_rimFracture->fractureTemplate();
RimStimPlanFractureTemplate* stimPlanFracTemplate = dynamic_cast<RimStimPlanFractureTemplate*>(fracTemplate);
if (!stimPlanFracTemplate)
{
return;
}
float opacityLevel = activeView->stimPlanColors->opacityLevel();
if (legendConfig)
{
cvf::ScalarMapper* scalarMapper = legendConfig->scalarMapper();
cvf::DrawableGeo* geo = dynamic_cast<cvf::DrawableGeo*> (m_surfacePart->drawable());
cvf::ref<cvf::Vec2fArray> textureCoords = new cvf::Vec2fArray;
textureCoords->resize(geo->vertexCount());
int timeStepIndex = stimPlanFracTemplate->activeTimeStepIndex();
std::vector<std::vector<double> > dataToPlot = stimPlanFracTemplate->resultValues(activeView->stimPlanColors->resultName(),
activeView->stimPlanColors->unit(),
timeStepIndex);
int i = 0;
for (const std::vector<double>& depthData : dataToPlot)
{
std::vector<double> mirroredValuesAtDepth = mirrorDataAtSingleDepth(depthData);
for (double gridXdata : mirroredValuesAtDepth)
{
cvf::Vec2f texCoord = scalarMapper->mapToTextureCoord(gridXdata);
if (gridXdata > 1e-7)
{
texCoord[1] = 0; // Set the Y texture coordinate to the opaque line in the texture
}
textureCoords->set(i, texCoord);
i++;
}
}
geo->setTextureCoordArray(textureCoords.p());
caf::ScalarMapperEffectGenerator effGen(scalarMapper, caf::PO_1);
effGen.setOpacityLevel(0.5);
effGen.discardTransparentFragments(true);
if (activeView && activeView->isLightingDisabled())
{
effGen.disableLighting(true);
}
cvf::ref<cvf::Effect> eff = effGen.generateCachedEffect();
m_surfacePart->setEffect(eff.p());
m_surfacePart->setPriority(RivPartPriority::PartType::Transparent);
}
else
{
applyFractureUniformColor(activeView);
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RivWellFracturePartMgr::generateFractureOutlinePolygonPart(const caf::DisplayCoordTransform* displayCoordTransform)
{
m_polygonPart = nullptr;
cvf::ref<cvf::DrawableGeo> polygonGeo = createPolygonDrawable(displayCoordTransform);
if (polygonGeo.notNull())
{
m_polygonPart = new cvf::Part(0, "FractureOutline");
m_polygonPart->setDrawable(polygonGeo.p());
m_polygonPart->updateBoundingBox();
m_polygonPart->setPriority(RivPartPriority::PartType::TransparentMeshLines);
caf::MeshEffectGenerator lineEffGen(cvf::Color3::MAGENTA);
lineEffGen.setLineWidth(3.0f);
cvf::ref<cvf::Effect> eff = lineEffGen.generateCachedEffect();
m_polygonPart->setEffect(eff.p());
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RivWellFracturePartMgr::generateStimPlanMeshPart(const caf::DisplayCoordTransform* displayCoordTransform,
const RimEclipseView* activeView)
{
m_stimPlanMeshPart = nullptr;
if (!m_rimFracture->fractureTemplate()) return;
RimStimPlanFractureTemplate* stimPlanFracTemplate = dynamic_cast<RimStimPlanFractureTemplate*>(m_rimFracture->fractureTemplate());
if (!stimPlanFracTemplate) return;
cvf::ref<cvf::DrawableGeo> stimPlanMeshGeo = createStimPlanMeshDrawable(stimPlanFracTemplate,
displayCoordTransform,
activeView);
if (stimPlanMeshGeo.notNull())
{
m_stimPlanMeshPart = new cvf::Part(0, "StimPlanMesh");
m_stimPlanMeshPart->setDrawable(stimPlanMeshGeo.p());
m_stimPlanMeshPart->updateBoundingBox();
m_stimPlanMeshPart->setPriority(RivPartPriority::PartType::TransparentMeshLines);
caf::MeshEffectGenerator lineEffGen(cvf::Color3::BLACK);
lineEffGen.setLineWidth(1.0f);
cvf::ref<cvf::Effect> eff = lineEffGen.generateCachedEffect();
m_stimPlanMeshPart->setEffect(eff.p());
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::ref<cvf::DrawableGeo> RivWellFracturePartMgr::createStimPlanMeshDrawable(RimStimPlanFractureTemplate* stimPlanFracTemplate,
const caf::DisplayCoordTransform* displayCoordTransform,
const RimEclipseView* activeView)
{
//TODO: This is needed to avoid errors when loading project with stimPlan fractures with multipled timesteps.
//Should probably be moved, since it now is called twice in some cases...
stimPlanFracTemplate->updateFractureGrid();
std::vector<RigFractureCell> stimPlanCells = stimPlanFracTemplate->fractureGrid()->fractureCells();
std::vector<cvf::Vec3f> stimPlanMeshVertices;
QString resultNameFromColors = activeView->stimPlanColors->resultName();
QString resultUnitFromColors = activeView->stimPlanColors->unit();
std::vector<double> prCellResults = stimPlanFracTemplate->fractureGridResults(resultNameFromColors,
resultUnitFromColors,
stimPlanFracTemplate->activeTimeStepIndex());
for ( size_t cIdx = 0; cIdx < stimPlanCells.size() ; ++cIdx)
{
if (prCellResults[cIdx] > 1e-7)
{
const RigFractureCell& stimPlanCell = stimPlanCells[cIdx];
std::vector<cvf::Vec3d> stimPlanCellPolygon = stimPlanCell.getPolygon();
for (cvf::Vec3d cellCorner : stimPlanCellPolygon)
{
stimPlanMeshVertices.push_back(static_cast<cvf::Vec3f>(cellCorner));
}
}
}
if (stimPlanMeshVertices.size() == 0)
{
return nullptr;
}
cvf::Mat4d fractureXf = m_rimFracture->transformMatrix();
std::vector<cvf::Vec3f> stimPlanMeshVerticesDisplayCoords = transfromToFractureDisplayCoords(stimPlanMeshVertices,
fractureXf,
displayCoordTransform);
cvf::Vec3fArray* stimPlanMeshVertexList;
stimPlanMeshVertexList = new cvf::Vec3fArray;
stimPlanMeshVertexList->assign(stimPlanMeshVerticesDisplayCoords);
cvf::ref<cvf::DrawableGeo> stimPlanMeshGeo = new cvf::DrawableGeo;
stimPlanMeshGeo->setVertexArray(stimPlanMeshVertexList);
cvf::ref<cvf::UIntArray> indices = RivFaultGeometryGenerator::lineIndicesFromQuadVertexArray(stimPlanMeshVertexList);
cvf::ref<cvf::PrimitiveSetIndexedUInt> prim = new cvf::PrimitiveSetIndexedUInt(cvf::PT_LINES);
prim->setIndices(indices.p());
stimPlanMeshGeo->addPrimitiveSet(prim.p());
return stimPlanMeshGeo;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RivWellFracturePartMgr::getPolygonBB(float &polygonXmin, float &polygonXmax, float &polygonYmin, float &polygonYmax)
{
std::vector<cvf::Vec3f> polygon = m_rimFracture->fractureTemplate()->fractureBorderPolygon(m_rimFracture->fractureUnit());
if (polygon.size() > 1)
{
polygonXmin = polygon[0].x();
polygonXmax = polygon[0].x();
polygonYmin = polygon[0].y();
polygonYmax = polygon[0].y();
}
for (cvf::Vec3f v : polygon)
{
if (v.x() < polygonXmin) polygonXmin = v.x();
if (v.x() > polygonXmax) polygonXmax = v.x();
if (v.y() < polygonYmin) polygonYmin = v.y();
if (v.y() > polygonYmax) polygonYmax = v.y();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::ref<cvf::DrawableGeo> RivWellFracturePartMgr::createPolygonDrawable(const caf::DisplayCoordTransform* displayCoordTransform)
{
std::vector<cvf::uint> lineIndices;
std::vector<cvf::Vec3f> vertices;
{
std::vector<cvf::Vec3f> polygon = m_rimFracture->fractureTemplate()->fractureBorderPolygon(m_rimFracture->fractureUnit());
cvf::Mat4d m = m_rimFracture->transformMatrix();
std::vector<cvf::Vec3f> polygonDisplayCoords = transfromToFractureDisplayCoords(polygon, m, displayCoordTransform);
for (size_t i = 0; i < polygonDisplayCoords.size(); ++i)
{
vertices.push_back(cvf::Vec3f(polygonDisplayCoords[i]));
if (i < polygonDisplayCoords.size() - 1)
{
lineIndices.push_back(static_cast<cvf::uint>(i));
lineIndices.push_back(static_cast<cvf::uint>(i + 1));
}
}
}
if (vertices.size() == 0) return nullptr;
cvf::ref<cvf::Vec3fArray> vx = new cvf::Vec3fArray;
vx->assign(vertices);
cvf::ref<cvf::UIntArray> idxes = new cvf::UIntArray;
idxes->assign(lineIndices);
cvf::ref<cvf::PrimitiveSetIndexedUInt> prim = new cvf::PrimitiveSetIndexedUInt(cvf::PT_LINES);
prim->setIndices(idxes.p());
cvf::ref<cvf::DrawableGeo> polygonGeo = new cvf::DrawableGeo;
polygonGeo->setVertexArray(vx.p());
polygonGeo->addPrimitiveSet(prim.p());
return polygonGeo;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<cvf::Vec3f> RivWellFracturePartMgr::transfromToFractureDisplayCoords(const std::vector<cvf::Vec3f>& coordinatesVector,
cvf::Mat4d m,
const caf::DisplayCoordTransform* displayCoordTransform)
{
std::vector<cvf::Vec3f> polygonInDisplayCoords;
polygonInDisplayCoords.reserve(coordinatesVector.size());
for (const cvf::Vec3f& v : coordinatesVector)
{
cvf::Vec3d vd(v);
vd.transformPoint(m);
cvf::Vec3d displayCoordsDouble = displayCoordTransform->transformToDisplayCoord(vd);
polygonInDisplayCoords.push_back(cvf::Vec3f(displayCoordsDouble));
}
return polygonInDisplayCoords;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<double> RivWellFracturePartMgr::mirrorDataAtSingleDepth(std::vector<double> depthData)
{
std::vector<double> mirroredValuesAtGivenDepth;
mirroredValuesAtGivenDepth.push_back(depthData[0]);
for (size_t i = 1; i < (depthData.size()); i++) //starting at 1 since we don't want center value twice
{
double valueAtGivenX = depthData[i];
mirroredValuesAtGivenDepth.insert(mirroredValuesAtGivenDepth.begin(), valueAtGivenX);
mirroredValuesAtGivenDepth.push_back(valueAtGivenX);
}
return mirroredValuesAtGivenDepth;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RivWellFracturePartMgr::appendGeometryPartsToModel(cvf::ModelBasicList* model,
const RimEclipseView* eclView)
{
clearGeometryCache();
if (!m_rimFracture->isChecked()) return;
RimStimPlanFractureTemplate* stimPlanFracTemplate = dynamic_cast<RimStimPlanFractureTemplate*>(m_rimFracture->fractureTemplate());
auto displayCoordTransform = eclView->displayCoordTransform();
if (m_surfacePart.isNull())
{
if (m_rimFracture->fractureTemplate())
{
if (stimPlanFracTemplate)
{
generateSurfacePart(displayCoordTransform.p());
generateFractureOutlinePolygonPart(displayCoordTransform.p());
applyResultTextureColor(eclView);
if (stimPlanFracTemplate->showStimPlanMesh())
{
generateStimPlanMeshPart(displayCoordTransform.p(), eclView);
}
}
else // Ellipse
{
generateSurfacePart(displayCoordTransform.p());
applyFractureUniformColor(eclView);
}
if (m_rimFracture->fractureTemplate()->fractureContainment()->isEnabled())
{
generateContainmentMaskPart(eclView);
}
else
{
m_containmentMaskPart = nullptr;
}
}
}
if (m_surfacePart.notNull())
{
model->addPart(m_surfacePart.p());
}
if (m_stimPlanMeshPart.notNull()
&& stimPlanFracTemplate->showStimPlanMesh())
{
model->addPart(m_stimPlanMeshPart.p());
}
if (stimPlanFracTemplate
&& m_rimFracture->showPolygonFractureOutline()
&& m_polygonPart.notNull())
{
model->addPart(m_polygonPart.p());
}
if (m_containmentMaskPart.notNull())
{
model->addPart(m_containmentMaskPart.p());
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RivWellFracturePartMgr::clearGeometryCache()
{
m_surfacePart = nullptr;
m_polygonPart = nullptr;
m_stimPlanMeshPart = nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::ref<cvf::DrawableGeo> RivWellFracturePartMgr::buildDrawableGeoFromTriangles(const std::vector<cvf::uint>& triangleIndices,
const std::vector<cvf::Vec3f>& nodeCoords)
{
CVF_ASSERT(triangleIndices.size() > 0);
CVF_ASSERT(nodeCoords.size() > 0);
cvf::ref<cvf::DrawableGeo> geo = new cvf::DrawableGeo;
cvf::ref<cvf::UIntArray> indices = new cvf::UIntArray(triangleIndices);
cvf::ref<cvf::Vec3fArray> vertices = new cvf::Vec3fArray(nodeCoords);
geo->setVertexArray(vertices.p());
geo->addPrimitiveSet(new cvf::PrimitiveSetIndexedUInt(cvf::PT_TRIANGLES, indices.p()));
geo->computeNormals();
return geo;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RivWellFracturePartMgr::stimPlanCellTouchesPolygon(const std::vector<cvf::Vec3f>& polygon,
double xMin, double xMax, double yMin, double yMax,
float polygonXmin, float polygonXmax, float polygonYmin, float polygonYmax)
{
if (static_cast<float>(xMin) > polygonXmin && static_cast<float>(xMax) < polygonXmax)
{
if (static_cast<float>(yMin) > polygonYmin && static_cast<float>(yMax) < polygonYmax)
{
return true;
}
}
for (cvf::Vec3f v : polygon)
{
if (v.x() > xMin && v.x() < xMax)
{
if (v.y() > yMin && v.y() < yMax)
{
return true;
}
}
}
return false;
}

View File

@ -0,0 +1,106 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "cvfObject.h"
#include "cvfVector3.h"
#include "cafPdmPointer.h"
#include <vector>
namespace cvf
{
class ModelBasicList;
class DrawableGeo;
class Part;
}
namespace caf
{
class DisplayCoordTransform;
}
class RimFracture;
class RimStimPlanFractureTemplate;
class RimEclipseView;
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
class RivWellFracturePartMgr : public cvf::Object
{
public:
RivWellFracturePartMgr(RimFracture* well);
~RivWellFracturePartMgr();
void appendGeometryPartsToModel(cvf::ModelBasicList* model,
const RimEclipseView* eclView);
void clearGeometryCache();
static std::vector<double> mirrorDataAtSingleDepth(std::vector<double> depthData);
private:
void generateSurfacePart(const caf::DisplayCoordTransform* displayCoordTransform);
void generateContainmentMaskPart(const RimEclipseView* activeView);
void applyFractureUniformColor(const RimEclipseView* activeView);
void applyResultTextureColor(const RimEclipseView* activeView);
void generateFractureOutlinePolygonPart(const caf::DisplayCoordTransform* displayCoordTransform);
void generateStimPlanMeshPart(const caf::DisplayCoordTransform* displayCoordTransform,
const RimEclipseView* activeView);
cvf::ref<cvf::DrawableGeo> createPolygonDrawable(const caf::DisplayCoordTransform* displayCoordTransform);
cvf::ref<cvf::DrawableGeo> createStimPlanMeshDrawable(RimStimPlanFractureTemplate* stimPlanFracTemplate,
const caf::DisplayCoordTransform* displayCoordTransform,
const RimEclipseView* activeView);
void getPolygonBB(float &polygonXmin,
float &polygonXmax,
float &polygonYmin,
float &polygonYmax);
std::vector<cvf::Vec3f> transfromToFractureDisplayCoords(const std::vector<cvf::Vec3f>& polygon,
cvf::Mat4d m,
const caf::DisplayCoordTransform* displayCoordTransform);
bool stimPlanCellTouchesPolygon(const std::vector<cvf::Vec3f>& polygon,
double xMin,
double xMax,
double yMin,
double yMax,
float polygonXmin,
float polygonXmax,
float polygonYmin,
float polygonYmax);
static cvf::ref<cvf::DrawableGeo> buildDrawableGeoFromTriangles(const std::vector<cvf::uint>& triangleIndices,
const std::vector<cvf::Vec3f>& nodeCoords);
private:
caf::PdmPointer<RimFracture> m_rimFracture;
cvf::ref<cvf::Part> m_surfacePart;
cvf::ref<cvf::Part> m_containmentMaskPart;
cvf::ref<cvf::Part> m_polygonPart;
cvf::ref<cvf::Part> m_stimPlanMeshPart;
};

View File

@ -37,12 +37,19 @@
#include "RimWellPath.h"
#include "RimWellPathCollection.h"
#include "RimWellPathFractureCollection.h"
#include "RimWellPathFracture.h"
#include "RivFishbonesSubsPartMgr.h"
#include "RivObjectSourceInfo.h"
#include "RivPartPriority.h"
#include "RivPipeGeometryGenerator.h"
#include "RivWellPathSourceInfo.h"
#include "RivPartPriority.h"
#include "RivWellFracturePartMgr.h"
#include "RivWellPathPartMgr.h"
#include "cafDisplayCoordTransform.h"
#include "cafEffectGenerator.h"
#include "cvfDrawableGeo.h"
@ -91,6 +98,23 @@ RivWellPathPartMgr::~RivWellPathPartMgr()
clearAllBranchData();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
#ifdef USE_PROTOTYPE_FEATURE_FRACTURES
void RivWellPathPartMgr::appendStaticFracturePartsToModel(cvf::ModelBasicList* model, const RimEclipseView* eclView)
{
if (!m_rimWellPath || !m_rimWellPath->fractureCollection()->isChecked()) return;
for (RimWellPathFracture* f : m_rimWellPath->fractureCollection()->fractures())
{
CVF_ASSERT(f);
f->fracturePartManager()->appendGeometryPartsToModel(model, eclView);
}
}
#endif // USE_PROTOTYPE_FEATURE_FRACTURES
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -369,8 +393,6 @@ void RivWellPathPartMgr::appendStaticGeometryPartsToModel(cvf::ModelBasicList* m
RimWellPathCollection* wellPathCollection = this->wellPathCollection();
if (!wellPathCollection) return;
if (m_rimWellPath.isNull()) return;
if (wellPathCollection->wellPathVisibility() == RimWellPathCollection::FORCE_ALL_OFF)
return;

View File

@ -34,7 +34,8 @@ namespace cvf
class ScalarMapper;
}
namespace caf {
namespace caf
{
class DisplayCoordTransform;
}
@ -43,6 +44,7 @@ class RimProject;
class RimWellPath;
class RivFishbonesSubsPartMgr;
class RimWellPathCollection;
class RimEclipseView;
class QDateTime;
@ -57,6 +59,11 @@ public:
const cvf::BoundingBox& wellPathClipBoundingBox,
const caf::DisplayCoordTransform* displayCoordTransform);
#ifdef USE_PROTOTYPE_FEATURE_FRACTURES
void appendStaticFracturePartsToModel(cvf::ModelBasicList* model,
const RimEclipseView* eclView);
#endif // USE_PROTOTYPE_FEATURE_FRACTURES
void appendDynamicGeometryPartsToModel(cvf::ModelBasicList* model,
const QDateTime& timeStamp,
double characteristicCellSize,
@ -79,6 +86,7 @@ private:
const caf::DisplayCoordTransform* displayCoordTransform,
double characteristicCellSize);
void buildWellPathParts(const caf::DisplayCoordTransform* displayCoordTransform,
double characteristicCellSize,
const cvf::BoundingBox& wellPathClipBoundingBox);

View File

@ -93,6 +93,13 @@ ${CEE_CURRENT_LIST_DIR}RimDialogData.h
${CEE_CURRENT_LIST_DIR}RimTimeStepFilter.h
)
if (RESINSIGHT_ENABLE_PROTOTYPE_FEATURE_FRACTURES)
list (APPEND SOURCE_GROUP_HEADER_FILES
${CEE_CURRENT_LIST_DIR}RimStimPlanLegendConfig.h
${CEE_CURRENT_LIST_DIR}RimStimPlanColors.h
)
endif()
set (SOURCE_GROUP_SOURCE_FILES
${CEE_CURRENT_LIST_DIR}RimEclipseCaseCollection.cpp
${CEE_CURRENT_LIST_DIR}RimCaseCollection.cpp
@ -182,6 +189,13 @@ ${CEE_CURRENT_LIST_DIR}RimDialogData.cpp
${CEE_CURRENT_LIST_DIR}RimTimeStepFilter.cpp
)
if (RESINSIGHT_ENABLE_PROTOTYPE_FEATURE_FRACTURES)
list (APPEND SOURCE_GROUP_SOURCE_FILES
${CEE_CURRENT_LIST_DIR}RimStimPlanLegendConfig.cpp
${CEE_CURRENT_LIST_DIR}RimStimPlanColors.cpp
)
endif()
list(APPEND CODE_HEADER_FILES
${SOURCE_GROUP_HEADER_FILES}
)

View File

@ -14,12 +14,26 @@ ${CEE_CURRENT_LIST_DIR}RimFishboneWellPathCollection.h
${CEE_CURRENT_LIST_DIR}RimPerforationCollection.h
${CEE_CURRENT_LIST_DIR}RimPerforationInterval.h
${CEE_CURRENT_LIST_DIR}RimWellPathCompletions.h
# Fracture files goes here
)
if (RESINSIGHT_ENABLE_PROTOTYPE_FEATURE_FRACTURES)
list (APPEND SOURCE_GROUP_HEADER_FILES
${CEE_CURRENT_LIST_DIR}RimEllipseFractureTemplate.h
${CEE_CURRENT_LIST_DIR}RimFracture.h
${CEE_CURRENT_LIST_DIR}RimFractureContainment.h
${CEE_CURRENT_LIST_DIR}RimFractureExportSettings.h
${CEE_CURRENT_LIST_DIR}RimFractureTemplate.h
${CEE_CURRENT_LIST_DIR}RimFractureTemplateCollection.h
${CEE_CURRENT_LIST_DIR}RimSimWellFracture.h
${CEE_CURRENT_LIST_DIR}RimSimWellFractureCollection.h
${CEE_CURRENT_LIST_DIR}RimStimPlanFractureTemplate.h
${CEE_CURRENT_LIST_DIR}RimWellPathFracture.h
${CEE_CURRENT_LIST_DIR}RimWellPathFractureCollection.h
)
endif()
set (SOURCE_GROUP_SOURCE_FILES
${CEE_CURRENT_LIST_DIR}RimCompletionCellIntersectionCalc.cpp
${CEE_CURRENT_LIST_DIR}RimFishbonesCollection.cpp
@ -30,12 +44,25 @@ ${CEE_CURRENT_LIST_DIR}RimFishboneWellPathCollection.cpp
${CEE_CURRENT_LIST_DIR}RimPerforationCollection.cpp
${CEE_CURRENT_LIST_DIR}RimPerforationInterval.cpp
${CEE_CURRENT_LIST_DIR}RimWellPathCompletions.cpp
# Fracture files goes here
)
if (RESINSIGHT_ENABLE_PROTOTYPE_FEATURE_FRACTURES)
list (APPEND SOURCE_GROUP_SOURCE_FILES
${CEE_CURRENT_LIST_DIR}RimEllipseFractureTemplate.cpp
${CEE_CURRENT_LIST_DIR}RimFracture.cpp
${CEE_CURRENT_LIST_DIR}RimFractureContainment.cpp
${CEE_CURRENT_LIST_DIR}RimFractureExportSettings.cpp
${CEE_CURRENT_LIST_DIR}RimFractureTemplate.cpp
${CEE_CURRENT_LIST_DIR}RimFractureTemplateCollection.cpp
${CEE_CURRENT_LIST_DIR}RimSimWellFracture.cpp
${CEE_CURRENT_LIST_DIR}RimSimWellFractureCollection.cpp
${CEE_CURRENT_LIST_DIR}RimStimPlanFractureTemplate.cpp
${CEE_CURRENT_LIST_DIR}RimWellPathFracture.cpp
${CEE_CURRENT_LIST_DIR}RimWellPathFractureCollection.cpp
)
endif()
list(APPEND CODE_HEADER_FILES
${SOURCE_GROUP_HEADER_FILES}
)

View File

@ -28,17 +28,34 @@
#include "RimFishbonesMultipleSubs.h"
#include "RimPerforationCollection.h"
#include "RimPerforationInterval.h"
#include "RimEclipseCase.h"
#include "RimEclipseView.h"
#include "RimEclipseWellCollection.h"
#include "RimEclipseWell.h"
#include "RigMainGrid.h"
#include "RigWellPath.h"
#include "RigWellPathIntersectionTools.h"
#include "RigCellGeometryTools.h"
#ifdef USE_PROTOTYPE_FEATURE_FRACTURES
#include "RimFracture.h"
#include "RimWellPathFracture.h"
#include "RimFractureTemplate.h"
#include "RimWellPathFractureCollection.h"
#include "RimSimWellFractureCollection.h"
#include "RimSimWellFracture.h"
#include "RigFractureGrid.h"
#include "RigFractureCell.h"
#endif // USE_PROTOTYPE_FEATURE_FRACTURES
#include <QDateTime>
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimCompletionCellIntersectionCalc::calculateIntersections(const RimProject* project, const RigMainGrid* grid, std::vector<double>& values, const QDateTime& fromDate)
void RimCompletionCellIntersectionCalc::calculateIntersections(const RimProject* project, const RimEclipseCase* eclipseCase, const RigMainGrid* grid, std::vector<double>& values, const QDateTime& fromDate)
{
for (const RimWellPath* wellPath : project->activeOilField()->wellPathCollection->wellPaths)
{
@ -47,6 +64,19 @@ void RimCompletionCellIntersectionCalc::calculateIntersections(const RimProject*
calculateWellPathIntersections(wellPath, grid, values, fromDate);
}
}
#ifdef USE_PROTOTYPE_FEATURE_FRACTURES
for (RimEclipseView* view : eclipseCase->reservoirViews())
{
for (RimEclipseWell* simWell : view->wellCollection()->wells())
{
for (RimSimWellFracture* fracture : simWell->simwellFractureCollection()->simwellFractures())
{
calculateFractureIntersections(grid, fracture, values);
}
}
}
#endif // USE_PROTOTYPE_FEATURE_FRACTURES
}
//--------------------------------------------------------------------------------------------------
@ -61,18 +91,40 @@ void RimCompletionCellIntersectionCalc::calculateWellPathIntersections(const Rim
values[intersection.m_hexIndex] = RiaDefines::WELL_PATH;
}
if (wellPath->fishbonesCollection()->isChecked())
{
for (const RimFishbonesMultipleSubs* fishbones : wellPath->fishbonesCollection()->fishbonesSubs)
{
if (fishbones->isChecked())
{
calculateFishbonesIntersections(fishbones, grid, values);
}
}
}
#ifdef USE_PROTOTYPE_FEATURE_FRACTURES
if (wellPath->fractureCollection()->isChecked())
{
for (const RimWellPathFracture* fracture : wellPath->fractureCollection()->fractures())
{
if (fracture->isChecked())
{
calculateFractureIntersections(grid, fracture, values);
}
}
}
#endif // USE_PROTOTYPE_FEATURE_FRACTURES
if (wellPath->perforationIntervalCollection()->isChecked())
{
for (const RimPerforationInterval* perforationInterval : wellPath->perforationIntervalCollection()->perforations())
{
if (perforationInterval->isActiveOnDate(fromDate))
if (perforationInterval->isChecked() && perforationInterval->isActiveOnDate(fromDate))
{
calculatePerforationIntersections(wellPath, perforationInterval, grid, values);
}
}
}
}
//--------------------------------------------------------------------------------------------------
@ -104,3 +156,76 @@ void RimCompletionCellIntersectionCalc::calculatePerforationIntersections(const
values[intersection.m_hexIndex] = RiaDefines::PERFORATION_INTERVAL;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
#ifdef USE_PROTOTYPE_FEATURE_FRACTURES
void RimCompletionCellIntersectionCalc::calculateFractureIntersections(const RigMainGrid* mainGrid, const RimFracture* fracture, std::vector<double>& values)
{
if (!fracture->fractureTemplate()) return;
for (const RigFractureCell& fractureCell : fracture->fractureTemplate()->fractureGrid()->fractureCells())
{
if (!fractureCell.hasNonZeroConductivity()) continue;
std::vector<cvf::Vec3d> fractureCellTransformed;
for (const auto& v : fractureCell.getPolygon())
{
cvf::Vec3d polygonNode = v;
polygonNode.transformPoint(fracture->transformMatrix());
fractureCellTransformed.push_back(polygonNode);
}
std::vector<size_t> potentialCells;
{
cvf::BoundingBox boundingBox;
for (cvf::Vec3d nodeCoord : fractureCellTransformed)
{
boundingBox.add(nodeCoord);
}
mainGrid->findIntersectingCells(boundingBox, &potentialCells);
}
for (size_t cellIndex : potentialCells)
{
if (!fracture->isEclipseCellWithinContainment(mainGrid, cellIndex)) continue;
std::array<cvf::Vec3d, 8> hexCorners;
mainGrid->cellCornerVertices(cellIndex, hexCorners.data());
std::vector< std::vector<cvf::Vec3d> > planeCellPolygons;
bool isPlaneIntersected = RigHexIntersectionTools::planeHexIntersectionPolygons(hexCorners, fracture->transformMatrix(), planeCellPolygons);
if (!isPlaneIntersected || planeCellPolygons.empty()) continue;
{
cvf::Mat4d invertedTransformMatrix = cvf::Mat4d(fracture->transformMatrix().getInverted());
for (std::vector<cvf::Vec3d>& planeCellPolygon : planeCellPolygons)
{
for (cvf::Vec3d& v : planeCellPolygon)
{
v.transformPoint(invertedTransformMatrix);
}
}
}
for (const std::vector<cvf::Vec3d>& planeCellPolygon : planeCellPolygons)
{
std::vector< std::vector<cvf::Vec3d> > clippedPolygons = RigCellGeometryTools::intersectPolygons(planeCellPolygon, fractureCell.getPolygon());
for (const auto& clippedPolygon : clippedPolygons)
{
if (!clippedPolygon.empty())
{
values[cellIndex] = RiaDefines::FRACTURE;
break;
}
}
}
}
}
}
#endif // USE_PROTOTYPE_FEATURE_FRACTURES

View File

@ -25,6 +25,12 @@ class RimWellPath;
class RimFishbonesMultipleSubs;
class RimPerforationInterval;
#ifdef USE_PROTOTYPE_FEATURE_FRACTURES
class RimFracture;
#endif // USE_PROTOTYPE_FEATURE_FRACTURES
class RimEclipseCase;
class RigMainGrid;
class QDateTime;
@ -35,10 +41,13 @@ class QDateTime;
class RimCompletionCellIntersectionCalc
{
public:
static void calculateIntersections(const RimProject* project, const RigMainGrid* grid, std::vector<double>& values, const QDateTime& fromDate);
static void calculateIntersections(const RimProject* project, const RimEclipseCase* eclipseCase, const RigMainGrid* grid, std::vector<double>& values, const QDateTime& fromDate);
private:
static void calculateWellPathIntersections(const RimWellPath* wellPath, const RigMainGrid* grid, std::vector<double>& values, const QDateTime& fromDate);
static void calculateFishbonesIntersections(const RimFishbonesMultipleSubs* fishbonesSubs, const RigMainGrid* grid, std::vector<double>& values);
static void calculatePerforationIntersections(const RimWellPath* wellPath, const RimPerforationInterval* perforationInterval, const RigMainGrid* grid, std::vector<double>& values);
#ifdef USE_PROTOTYPE_FEATURE_FRACTURES
static void calculateFractureIntersections(const RigMainGrid* mainGrid, const RimFracture* fracture, std::vector<double>& values);
#endif // USE_PROTOTYPE_FEATURE_FRACTURES
};

View File

@ -0,0 +1,354 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2016- 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 "RimEllipseFractureTemplate.h"
#include "RiaEclipseUnitTools.h"
#include "RiaLogging.h"
#include "RigCellGeometryTools.h"
#include "RigFractureCell.h"
#include "RigFractureGrid.h"
#include "RigTesselatorTools.h"
#include "RimFracture.h"
#include "RimFractureContainment.h"
#include "RimFractureTemplate.h"
#include "RimProject.h"
#include "cafPdmObject.h"
#include "cvfVector3.h"
#include "cvfGeometryTools.h"
CAF_PDM_SOURCE_INIT(RimEllipseFractureTemplate, "RimEllipseFractureTemplate");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimEllipseFractureTemplate::RimEllipseFractureTemplate(void)
{
CAF_PDM_InitObject("Fracture Template", ":/FractureTemplate16x16.png", "", "");
CAF_PDM_InitField(&halfLength, "HalfLength", 650.0f, "Halflength X<sub>f</sub>", "", "", "");
CAF_PDM_InitField(&height, "Height", 75.0f, "Height", "", "", "");
CAF_PDM_InitField(&width, "Width", 1.0f, "Width", "", "", "");
CAF_PDM_InitField(&permeability,"Permeability", 22000.f, "Permeability [mD]", "", "", "");
m_fractureGrid = new RigFractureGrid();
setupFractureGridCells();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimEllipseFractureTemplate::~RimEllipseFractureTemplate()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEllipseFractureTemplate::loadDataAndUpdate()
{
setupFractureGridCells();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEllipseFractureTemplate::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue)
{
RimFractureTemplate::fieldChangedByUi(changedField, oldValue, newValue);
if (changedField == &halfLength || changedField == &height)
{
//Changes to one of these parameters should change all fractures with this fracture template attached.
RimProject* proj;
this->firstAncestorOrThisOfType(proj);
if (proj)
{
//Regenerate geometry
std::vector<RimFracture*> fractures;
proj->descendantsIncludingThisOfType(fractures);
for (RimFracture* fracture : fractures)
{
if (fracture->fractureTemplate() == this)
{
fracture->clearDisplayGeometryCache();
}
}
proj->createDisplayModelAndRedrawAllViews();
setupFractureGridCells();
}
}
if (changedField == &width || changedField == &permeability)
{
setupFractureGridCells();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEllipseFractureTemplate::fractureTriangleGeometry(std::vector<cvf::Vec3f>* nodeCoords,
std::vector<cvf::uint>* triangleIndices,
RiaEclipseUnitTools::UnitSystem neededUnit)
{
RigEllipsisTesselator tesselator(20);
float a = cvf::UNDEFINED_FLOAT;
float b = cvf::UNDEFINED_FLOAT;
if (neededUnit == fractureTemplateUnit())
{
a = halfLength;
b = height / 2.0f;
}
else if (fractureTemplateUnit() == RiaEclipseUnitTools::UNITS_METRIC && neededUnit == RiaEclipseUnitTools::UNITS_FIELD)
{
RiaLogging::info(QString("Converting fracture template geometry from metric to field"));
a = RiaEclipseUnitTools::meterToFeet(halfLength);
b = RiaEclipseUnitTools::meterToFeet(height / 2.0f);
}
else if (fractureTemplateUnit() == RiaEclipseUnitTools::UNITS_FIELD && neededUnit == RiaEclipseUnitTools::UNITS_METRIC)
{
RiaLogging::info(QString("Converting fracture template geometry from field to metric"));
a = RiaEclipseUnitTools::feetToMeter(halfLength);
b = RiaEclipseUnitTools::feetToMeter(height / 2.0f);
}
else
{
//Should never get here...
RiaLogging::error(QString("Error: Could not convert units for fracture / fracture template"));
return;
}
tesselator.tesselateEllipsis(a, b, triangleIndices, nodeCoords);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<cvf::Vec3f> RimEllipseFractureTemplate::fractureBorderPolygon(RiaEclipseUnitTools::UnitSystem neededUnit)
{
std::vector<cvf::Vec3f> polygon;
std::vector<cvf::Vec3f> nodeCoords;
std::vector<cvf::uint> triangleIndices;
fractureTriangleGeometry(&nodeCoords, &triangleIndices, neededUnit);
for (size_t i = 1; i < nodeCoords.size(); i++)
{
polygon.push_back(nodeCoords[i]);
}
return polygon;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEllipseFractureTemplate::changeUnits()
{
if (fractureTemplateUnit == RiaEclipseUnitTools::UNITS_METRIC)
{
halfLength = RiaEclipseUnitTools::meterToFeet(halfLength);
height = RiaEclipseUnitTools::meterToFeet(height);
width = RiaEclipseUnitTools::meterToInch(width);
wellDiameter = RiaEclipseUnitTools::meterToInch(wellDiameter);
perforationLength = RiaEclipseUnitTools::meterToFeet(perforationLength);
fractureTemplateUnit = RiaEclipseUnitTools::UNITS_FIELD;
}
else if (fractureTemplateUnit == RiaEclipseUnitTools::UNITS_FIELD)
{
halfLength = RiaEclipseUnitTools::feetToMeter(halfLength);
height = RiaEclipseUnitTools::feetToMeter(height);
width = RiaEclipseUnitTools::inchToMeter(width);
wellDiameter = RiaEclipseUnitTools::inchToMeter(wellDiameter);
perforationLength = RiaEclipseUnitTools::feetToMeter(perforationLength);
fractureTemplateUnit = RiaEclipseUnitTools::UNITS_METRIC;
}
this->updateConnectedEditors();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEllipseFractureTemplate::setupFractureGridCells()
{
std::vector<RigFractureCell> fractureCells;
std::pair<size_t, size_t> wellCenterFractureCellIJ = std::make_pair(0, 0);
bool wellCenterFractureCellFound = false;
int numberOfCellsX = 35;
int numberOfCellsY = 35;
double cellSizeX = (halfLength * 2) / numberOfCellsX;
double cellSizeZ = height / numberOfCellsY;
double cellArea = cellSizeX * cellSizeZ;
double areaTresholdForIncludingCell = 0.5 * cellArea;
for (int i = 0; i < numberOfCellsX; i++)
{
for (int j = 0; j < numberOfCellsX; j++)
{
double X1 = - halfLength + i * cellSizeX;
double X2 = - halfLength + (i+1) * cellSizeX;
double Y1 = - height / 2 + j * cellSizeZ;
double Y2 = - height / 2 + (j+1) * cellSizeZ;
std::vector<cvf::Vec3d> cellPolygon;
cellPolygon.push_back(cvf::Vec3d(X1, Y1, 0.0));
cellPolygon.push_back(cvf::Vec3d(X2, Y1, 0.0));
cellPolygon.push_back(cvf::Vec3d(X2, Y2, 0.0));
cellPolygon.push_back(cvf::Vec3d(X1, Y2, 0.0));
double cond = cvf::UNDEFINED_DOUBLE;
if (fractureTemplateUnit == RiaEclipseUnitTools::UNITS_METRIC)
{
//Conductivity should be md-m, width is in m
cond = permeability * width;
}
else if(fractureTemplateUnit == RiaEclipseUnitTools::UNITS_FIELD)
{
//Conductivity should be md-ft, but width is in inches
cond = permeability * RiaEclipseUnitTools::inchToFeet(width);
}
std::vector<cvf::Vec3f> ellipseFracPolygon = fractureBorderPolygon(fractureTemplateUnit());
std::vector<cvf::Vec3d> ellipseFracPolygonDouble;
for (auto v : ellipseFracPolygon) ellipseFracPolygonDouble.push_back(static_cast<cvf::Vec3d>(v));
std::vector<std::vector<cvf::Vec3d> >clippedFracturePolygons = RigCellGeometryTools::intersectPolygons(cellPolygon, ellipseFracPolygonDouble);
if (clippedFracturePolygons.size() > 0)
{
for (auto clippedFracturePolygon : clippedFracturePolygons)
{
double areaCutPolygon = cvf::GeometryTools::polygonAreaNormal3D(clippedFracturePolygon).length();
if (areaCutPolygon < areaTresholdForIncludingCell) cond = 0.0; //Cell is excluded from calculation, cond is set to zero. Must be included for indexing to be correct
}
}
else cond = 0.0;
RigFractureCell fractureCell(cellPolygon, i, j);
fractureCell.setConductivityValue(cond);
if (cellPolygon[0].x() < 0.0 && cellPolygon[1].x() > 0.0)
{
if (cellPolygon[1].y() < 0.0 && cellPolygon[2].y() > 0.0)
{
wellCenterFractureCellIJ = std::make_pair(fractureCell.getI(), fractureCell.getJ());
RiaLogging::debug(QString("Setting wellCenterFractureCell at cell %1, %2").
arg(QString::number(fractureCell.getI()), QString::number(fractureCell.getJ())));
wellCenterFractureCellFound = true;
}
}
fractureCells.push_back(fractureCell);
}
}
m_fractureGrid->setFractureCells(fractureCells);
m_fractureGrid->setWellCenterFractureCellIJ(wellCenterFractureCellIJ);
m_fractureGrid->setICellCount(numberOfCellsX);
m_fractureGrid->setJCellCount(numberOfCellsY);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const RigFractureGrid* RimEllipseFractureTemplate::fractureGrid() const
{
return m_fractureGrid.p();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEllipseFractureTemplate::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering)
{
RimFractureTemplate::defineUiOrdering(uiConfigName, uiOrdering);
if (fractureTemplateUnit == RiaEclipseUnitTools::UNITS_METRIC)
{
halfLength.uiCapability()->setUiName("Halflenght X<sub>f</sub> [m]");
height.uiCapability()->setUiName("Height [m]");
width.uiCapability()->setUiName("Width [m]");
wellDiameter.uiCapability()->setUiName("Well Diameter [m]");
}
else if (fractureTemplateUnit == RiaEclipseUnitTools::UNITS_FIELD)
{
halfLength.uiCapability()->setUiName("Halflenght X<sub>f</sub> [Ft]");
height.uiCapability()->setUiName("Height [Ft]");
width.uiCapability()->setUiName("Width [inches]");
wellDiameter.uiCapability()->setUiName("Well Diameter [inches]");
}
if (conductivityType == FINITE_CONDUCTIVITY)
{
permeability.uiCapability()->setUiHidden(false);
width.uiCapability()->setUiHidden(false);
}
else if (conductivityType == INFINITE_CONDUCTIVITY)
{
permeability.uiCapability()->setUiHidden(true);
width.uiCapability()->setUiHidden(true);
}
uiOrdering.add(&name);
caf::PdmUiGroup* geometryGroup = uiOrdering.addNewGroup("Geometry");
geometryGroup->add(&halfLength);
geometryGroup->add(&height);
geometryGroup->add(&orientationType);
geometryGroup->add(&azimuthAngle);
caf::PdmUiGroup* trGr = uiOrdering.addNewGroup("Fracture Truncation");
m_fractureContainment()->defineUiOrdering(uiConfigName, *trGr);
caf::PdmUiGroup* propertyGroup = uiOrdering.addNewGroup("Properties");
propertyGroup->add(&conductivityType);
propertyGroup->add(&permeability);
propertyGroup->add(&width);
propertyGroup->add(&skinFactor);
propertyGroup->add(&perforationLength);
propertyGroup->add(&perforationEfficiency);
propertyGroup->add(&wellDiameter);
uiOrdering.add(&fractureTemplateUnit);
uiOrdering.skipRemainingFields(true);
}

View File

@ -0,0 +1,73 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2016- 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 "RimFractureTemplate.h"
#include "cafAppEnum.h"
#include "cafPdmField.h"
#include "cafPdmFieldHandle.h"
#include "cafPdmObject.h"
#include "cafPdmFieldCvfVec3d.h"
#include "cvfBase.h"
#include "cvfObject.h"
#include "cvfVector3.h"
#include <vector>
class RigFractureGrid;
//==================================================================================================
///
///
//==================================================================================================
class RimEllipseFractureTemplate : public RimFractureTemplate
{
CAF_PDM_HEADER_INIT;
public:
RimEllipseFractureTemplate(void);
virtual ~RimEllipseFractureTemplate(void);
caf::PdmField<float> halfLength;
caf::PdmField<float> height;
caf::PdmField<float> width;
caf::PdmField<float> permeability;
void loadDataAndUpdate();
virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override;
void fractureTriangleGeometry(std::vector<cvf::Vec3f>* nodeCoords,
std::vector<cvf::uint>* polygonIndices,
RiaEclipseUnitTools::UnitSystem neededUnit);
std::vector<cvf::Vec3f> fractureBorderPolygon(RiaEclipseUnitTools::UnitSystem neededUnit);
void changeUnits();
const RigFractureGrid* fractureGrid() const;
protected:
virtual void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering);
private:
void setupFractureGridCells();
cvf::ref<RigFractureGrid> m_fractureGrid;
};

View File

@ -104,7 +104,14 @@ void RimFishbonesCollection::fieldChangedByUi(const caf::PdmFieldHandle* changed
RimProject* proj;
this->firstAncestorOrThisOfTypeAsserted(proj);
if (changedField == &m_isChecked)
{
proj->reloadCompletionTypeResultsInAllViews();
}
else
{
proj->createDisplayModelAndRedrawAllViews();
}
}
//--------------------------------------------------------------------------------------------------

View File

@ -0,0 +1,610 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RimFracture.h"
#include "RiaApplication.h"
#include "RiaEclipseUnitTools.h"
#include "RiaLogging.h"
#include "RifReaderInterface.h"
#include "RigActiveCellInfo.h"
#include "RigCaseCellResultsData.h"
#include "RigCell.h"
#include "RigCellGeometryTools.h"
#include "RigEclipseCaseData.h"
#include "RigMainGrid.h"
#include "RigResultAccessor.h"
#include "RigResultAccessorFactory.h"
#include "RigTesselatorTools.h"
#include "RimEclipseCase.h"
#include "RimEclipseCellColors.h"
#include "RimEclipseView.h"
#include "RimEllipseFractureTemplate.h"
#include "RimFractureTemplate.h"
#include "RimFractureTemplateCollection.h"
#include "RimOilField.h"
#include "RimProject.h"
#include "RimReservoirCellResultsStorage.h"
#include "RimStimPlanFractureTemplate.h"
#include "RimView.h"
#include "RivWellFracturePartMgr.h"
#include "cafHexGridIntersectionTools/cafHexGridIntersectionTools.h"
#include "cafPdmUiDoubleSliderEditor.h"
#include "cafPdmUiTreeOrdering.h"
#include "cvfBoundingBox.h"
#include "cvfGeometryTools.h"
#include "cvfMath.h"
#include "cvfMatrix4.h"
#include "cvfPlane.h"
#include "clipper/clipper.hpp"
#include <math.h>
#include <QDebug>
#include <QString>
#include "RigHexIntersectionTools.h"
#include "RimFractureContainment.h"
CAF_PDM_XML_ABSTRACT_SOURCE_INIT(RimFracture, "Fracture");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimFracture::RimFracture(void)
{
CAF_PDM_InitObject("Fracture", "", "", "");
CAF_PDM_InitFieldNoDefault(&m_fractureTemplate, "FractureDef", "Fracture Template", "", "", "");
CAF_PDM_InitFieldNoDefault(&m_anchorPosition, "anchorPosition", "Anchor Position", "", "", "");
m_anchorPosition.uiCapability()->setUiHidden(true);
CAF_PDM_InitFieldNoDefault(&m_uiAnchorPosition, "ui_positionAtWellpath", "Fracture Position", "", "", "");
m_uiAnchorPosition.registerGetMethod(this, &RimFracture::fracturePositionForUi);
m_uiAnchorPosition.uiCapability()->setUiReadOnly(true);
CAF_PDM_InitField(&azimuth, "Azimuth", 0.0, "Azimuth", "", "", "");
azimuth.uiCapability()->setUiEditorTypeName(caf::PdmUiDoubleSliderEditor::uiEditorTypeName());
CAF_PDM_InitField(&perforationLength, "PerforationLength", 1.0, "Perforation Length", "", "", "");
CAF_PDM_InitField(&perforationEfficiency, "perforationEfficiency", 1.0, "perforation Efficiency", "", "", "");
perforationEfficiency.uiCapability()->setUiEditorTypeName(caf::PdmUiDoubleSliderEditor::uiEditorTypeName());
CAF_PDM_InitField(&wellDiameter, "wellDiameter", 0.216, "Well Diameter at Fracture", "", "", "");
CAF_PDM_InitField(&dip, "Dip", 0.0, "Dip", "", "", "");
CAF_PDM_InitField(&tilt, "Tilt", 0.0, "Tilt", "", "", "");
CAF_PDM_InitField(&showPolygonFractureOutline, "showPolygonFractureOutline", false, "Show Polygon Outline", "", "", "");
showPolygonFractureOutline.uiCapability()->setUiHidden(true);
CAF_PDM_InitField(&m_fractureUnit, "fractureUnit", caf::AppEnum<RiaEclipseUnitTools::UnitSystem>(RiaEclipseUnitTools::UNITS_METRIC), "Fracture Unit System", "", "", "");
m_fractureUnit.uiCapability()->setUiReadOnly(true);
CAF_PDM_InitField(&stimPlanTimeIndexToPlot, "timeIndexToPlot", 0, "StimPlan Time Step", "", "", "");
CAF_PDM_InitFieldNoDefault(&m_uiWellPathAzimuth, "WellPathAzimuth", "Well Path Azimuth", "", "", "");
m_uiWellPathAzimuth.registerGetMethod(this, &RimFracture::wellAzimuthAtFracturePositionText);
m_uiWellPathAzimuth.uiCapability()->setUiReadOnly(true);
CAF_PDM_InitFieldNoDefault(&m_uiWellFractureAzimuthDiff, "WellFractureAzimuthDiff", "Azimuth Difference Between Fracture and Well", "", "", "");
m_uiWellFractureAzimuthDiff.registerGetMethod(this, &RimFracture::wellFractureAzimuthDiffText);
m_uiWellFractureAzimuthDiff.uiCapability()->setUiReadOnly(true);
CAF_PDM_InitField(&m_wellFractureAzimuthAngleWarning, "WellFractureAzimithAngleWarning", QString("Difference is below 10 degrees. Consider longitudinal fracture"), "", "", "", "");
m_wellFractureAzimuthAngleWarning.uiCapability()->setUiReadOnly(true);
m_fracturePartMgr = new RivWellFracturePartMgr(this);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimFracture::~RimFracture()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<size_t> RimFracture::getPotentiallyFracturedCells(const RigMainGrid* mainGrid)
{
std::vector<size_t> cellindecies;
if (!mainGrid) return cellindecies;
cvf::BoundingBox fractureBBox = this->boundingBoxInDomainCoords();
mainGrid->findIntersectingCells(fractureBBox, &cellindecies);
return cellindecies;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFracture::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue)
{
if (changedField == &m_fractureTemplate)
{
setFractureTemplate(m_fractureTemplate);
}
if (changedField == &azimuth ||
changedField == &m_fractureTemplate ||
changedField == &stimPlanTimeIndexToPlot ||
changedField == this->objectToggleField() ||
changedField == &showPolygonFractureOutline ||
changedField == &dip ||
changedField == &tilt)
{
clearDisplayGeometryCache();
RimView* rimView = nullptr;
this->firstAncestorOrThisOfType(rimView);
if (rimView)
{
rimView->createDisplayModelAndRedraw();
}
else
{
// Can be triggered from well path, find active view
RimProject* proj;
this->firstAncestorOrThisOfTypeAsserted(proj);
proj->reloadCompletionTypeResultsInAllViews();
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::Vec3d RimFracture::fracturePosition() const
{
return m_anchorPosition;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RimFracture::wellFractureAzimuthDiff() const
{
double wellDifference = abs(wellAzimuthAtFracturePosition() - azimuth);
return wellDifference;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimFracture::wellFractureAzimuthDiffText() const
{
double wellDifference = wellFractureAzimuthDiff();
return QString::number(wellDifference, 'f', 2);
}
QString RimFracture::wellAzimuthAtFracturePositionText() const
{
double wellAzimuth = wellAzimuthAtFracturePosition();
return QString::number(wellAzimuth, 'f', 2);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::BoundingBox RimFracture::boundingBoxInDomainCoords()
{
std::vector<cvf::Vec3f> nodeCoordVec;
std::vector<cvf::uint> triangleIndices;
this->triangleGeometry(&triangleIndices, &nodeCoordVec);
cvf::BoundingBox fractureBBox;
for (cvf::Vec3f nodeCoord : nodeCoordVec) fractureBBox.add(nodeCoord);
return fractureBBox;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RimFracture::wellRadius(RiaEclipseUnitTools::UnitSystem unitSystem) const
{
if (m_fractureUnit == RiaEclipseUnitTools::UNITS_METRIC)
{
if (unitSystem == RiaEclipseUnitTools::UNITS_FIELD)
{
return RiaEclipseUnitTools::meterToFeet(wellDiameter / 2);
}
else
{
return wellDiameter / 2;
}
}
else if (m_fractureUnit == RiaEclipseUnitTools::UNITS_FIELD)
{
if (unitSystem == RiaEclipseUnitTools::UNITS_METRIC)
{
return RiaEclipseUnitTools::inchToMeter(wellDiameter / 2);
}
else
{
return RiaEclipseUnitTools::inchToFeet(wellDiameter / 2);
}
}
return cvf::UNDEFINED_DOUBLE;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::Vec3d RimFracture::anchorPosition() const
{
return m_anchorPosition();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::Mat4d RimFracture::transformMatrix() const
{
cvf::Vec3d center = anchorPosition();
// Dip (in XY plane)
cvf::Mat4d dipRotation = cvf::Mat4d::fromRotation(cvf::Vec3d::Z_AXIS, cvf::Math::toRadians(dip()));
// Dip (out of XY plane)
cvf::Mat4d tiltRotation = cvf::Mat4d::fromRotation(cvf::Vec3d::X_AXIS, cvf::Math::toRadians(tilt()));
// Ellipsis geometry is produced in XY-plane, rotate 90 deg around X to get zero azimuth along Y
cvf::Mat4d rotationFromTesselator = cvf::Mat4d::fromRotation(cvf::Vec3d::X_AXIS, cvf::Math::toRadians(90.0f));
// Azimuth rotation
cvf::Mat4d azimuthRotation = cvf::Mat4d::fromRotation(cvf::Vec3d::Z_AXIS, cvf::Math::toRadians(-azimuth()-90));
cvf::Mat4d m = azimuthRotation * rotationFromTesselator * dipRotation * tiltRotation;
m.setTranslation(center);
return m;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFracture::clearDisplayGeometryCache()
{
m_fracturePartMgr->clearGeometryCache();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFracture::triangleGeometry(std::vector<cvf::uint>* triangleIndices, std::vector<cvf::Vec3f>* nodeCoords)
{
RimFractureTemplate* fractureDef = fractureTemplate();
if (fractureDef )
{
fractureDef->fractureTriangleGeometry(nodeCoords, triangleIndices, fractureUnit());
}
cvf::Mat4d m = transformMatrix();
for (cvf::Vec3f& v : *nodeCoords)
{
cvf::Vec3d vd(v);
vd.transformPoint(m);
v = cvf::Vec3f(vd);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::Vec3d RimFracture::fracturePositionForUi() const
{
cvf::Vec3d v = m_anchorPosition;
v.z() = -v.z();
return v;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QList<caf::PdmOptionItemInfo> RimFracture::calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool * useOptionsOnly)
{
QList<caf::PdmOptionItemInfo> options;
RimProject* proj = RiaApplication::instance()->project();
CVF_ASSERT(proj);
RimOilField* oilField = proj->activeOilField();
if (oilField == nullptr) return options;
if (fieldNeedingOptions == &m_fractureTemplate)
{
RimFractureTemplateCollection* fracDefColl = oilField->fractureDefinitionCollection();
if (fracDefColl == nullptr) return options;
for (RimFractureTemplate* fracDef : fracDefColl->fractureDefinitions())
{
options.push_back(caf::PdmOptionItemInfo(fracDef->name(), fracDef));
}
}
else if (fieldNeedingOptions == &stimPlanTimeIndexToPlot)
{
if (fractureTemplate())
{
RimFractureTemplate* fracTemplate = fractureTemplate();
if (dynamic_cast<RimStimPlanFractureTemplate*>(fracTemplate))
{
RimStimPlanFractureTemplate* fracTemplateStimPlan = dynamic_cast<RimStimPlanFractureTemplate*>(fracTemplate);
std::vector<double> timeValues = fracTemplateStimPlan->timeSteps();
int index = 0;
for (double value : timeValues)
{
options.push_back(caf::PdmOptionItemInfo(QString::number(value), index));
index++;
}
}
}
}
return options;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFracture::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering)
{
if (m_fractureUnit() == RiaEclipseUnitTools::UNITS_METRIC)
{
wellDiameter.uiCapability()->setUiName("Well Diameter [m]");
perforationLength.uiCapability()->setUiName("Perforation Length [m]");
}
else if (m_fractureUnit() == RiaEclipseUnitTools::UNITS_FIELD)
{
wellDiameter.uiCapability()->setUiName("Well Diameter [inches]");
perforationLength.uiCapability()->setUiName("Perforation Length [Ft]");
}
if (fractureTemplate())
{
if (fractureTemplate()->orientationType == RimFractureTemplate::ALONG_WELL_PATH
|| fractureTemplate()->orientationType == RimFractureTemplate::TRANSVERSE_WELL_PATH)
{
m_uiWellPathAzimuth.uiCapability()->setUiHidden(true);
m_uiWellFractureAzimuthDiff.uiCapability()->setUiHidden(true);
m_wellFractureAzimuthAngleWarning.uiCapability()->setUiHidden(true);
}
else if (fractureTemplate()->orientationType == RimFractureTemplate::AZIMUTH)
{
m_uiWellPathAzimuth.uiCapability()->setUiHidden(false);
m_uiWellFractureAzimuthDiff.uiCapability()->setUiHidden(false);
if (wellFractureAzimuthDiff() < 10
|| (wellFractureAzimuthDiff() > 170 && wellFractureAzimuthDiff() < 190 )
|| wellFractureAzimuthDiff() > 350)
{
m_wellFractureAzimuthAngleWarning.uiCapability()->setUiHidden(false);
}
else
{
m_wellFractureAzimuthAngleWarning.uiCapability()->setUiHidden(true);
}
}
if (fractureTemplate()->orientationType == RimFractureTemplate::ALONG_WELL_PATH
|| fractureTemplate()->orientationType == RimFractureTemplate::TRANSVERSE_WELL_PATH)
{
azimuth.uiCapability()->setUiReadOnly(true);
}
else if (fractureTemplate()->orientationType == RimFractureTemplate::AZIMUTH)
{
azimuth.uiCapability()->setUiReadOnly(false);
}
if (fractureTemplate()->orientationType == RimFractureTemplate::ALONG_WELL_PATH)
{
perforationEfficiency.uiCapability()->setUiHidden(false);
perforationLength.uiCapability()->setUiHidden(false);
}
else
{
perforationEfficiency.uiCapability()->setUiHidden(true);
perforationLength.uiCapability()->setUiHidden(true);
}
if (fractureTemplate()->conductivityType == RimFractureTemplate::FINITE_CONDUCTIVITY)
{
wellDiameter.uiCapability()->setUiHidden(false);
}
else if (fractureTemplate()->conductivityType == RimFractureTemplate::INFINITE_CONDUCTIVITY)
{
wellDiameter.uiCapability()->setUiHidden(true);
}
RimFractureTemplate* fracTemplate = fractureTemplate();
if (dynamic_cast<RimStimPlanFractureTemplate*>(fracTemplate))
{
stimPlanTimeIndexToPlot.uiCapability()->setUiHidden(false);
stimPlanTimeIndexToPlot.uiCapability()->setUiReadOnly(true);
}
else
{
stimPlanTimeIndexToPlot.uiCapability()->setUiHidden(true);
}
}
else
{
stimPlanTimeIndexToPlot.uiCapability()->setUiHidden(true);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFracture::defineEditorAttribute(const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute * attribute)
{
if (field == &azimuth)
{
caf::PdmUiDoubleSliderEditorAttribute* myAttr = dynamic_cast<caf::PdmUiDoubleSliderEditorAttribute*>(attribute);
if (myAttr)
{
myAttr->m_minimum = 0;
myAttr->m_maximum = 360;
}
}
if (field == &perforationEfficiency)
{
caf::PdmUiDoubleSliderEditorAttribute* myAttr = dynamic_cast<caf::PdmUiDoubleSliderEditorAttribute*>(attribute);
if (myAttr)
{
myAttr->m_minimum = 0;
myAttr->m_maximum = 1.0;
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFracture::setAnchorPosition(const cvf::Vec3d& pos)
{
m_anchorPosition = pos;
clearDisplayGeometryCache();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiaEclipseUnitTools::UnitSystem RimFracture::fractureUnit() const
{
return m_fractureUnit();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFracture::setFractureUnit(RiaEclipseUnitTools::UnitSystem unitSystem)
{
m_fractureUnit = unitSystem;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimFracture::isEclipseCellWithinContainment(const RigMainGrid* mainGrid, size_t globalCellIndex) const
{
CVF_ASSERT(fractureTemplate());
if (!fractureTemplate()->fractureContainment()->isEnabled()) return true;
size_t anchorEclipseCell = findAnchorEclipseCell(mainGrid);
return fractureTemplate()->fractureContainment()->isEclipseCellWithinContainment(mainGrid, anchorEclipseCell, globalCellIndex);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t RimFracture::findAnchorEclipseCell(const RigMainGrid* mainGrid ) const
{
cvf::BoundingBox pointBBox;
pointBBox.add(m_anchorPosition);
std::vector<size_t> cellIndices;
mainGrid->findIntersectingCells(pointBBox, &cellIndices);
size_t cellContainingAchorPoint = cvf::UNDEFINED_SIZE_T;
for ( size_t cellIndex : cellIndices )
{
auto cornerIndices = mainGrid->globalCellArray()[cellIndex].cornerIndices();
cvf::Vec3d vertices[8];
vertices[0] = (mainGrid->nodes()[cornerIndices[0]]);
vertices[1] = (mainGrid->nodes()[cornerIndices[1]]);
vertices[2] = (mainGrid->nodes()[cornerIndices[2]]);
vertices[3] = (mainGrid->nodes()[cornerIndices[3]]);
vertices[4] = (mainGrid->nodes()[cornerIndices[4]]);
vertices[5] = (mainGrid->nodes()[cornerIndices[5]]);
vertices[6] = (mainGrid->nodes()[cornerIndices[6]]);
vertices[7] = (mainGrid->nodes()[cornerIndices[7]]);
if ( RigHexIntersectionTools::isPointInCell(m_anchorPosition, vertices) )
{
cellContainingAchorPoint = cellIndex;
break;
}
}
return cellContainingAchorPoint;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFracture::setFractureTemplate(RimFractureTemplate* fractureTemplate)
{
m_fractureTemplate = fractureTemplate;
RimStimPlanFractureTemplate* stimPlanFracTemplate = dynamic_cast<RimStimPlanFractureTemplate*>(fractureTemplate);
if (stimPlanFracTemplate)
{
stimPlanTimeIndexToPlot = stimPlanFracTemplate->activeTimeStepIndex();
}
if (fractureTemplate->orientationType == RimFractureTemplate::AZIMUTH)
{
azimuth = fractureTemplate->azimuthAngle;
}
else
{
this->updateAzimuthBasedOnWellAzimuthAngle();
}
this->wellDiameter = fractureTemplate->wellDiameterInFractureUnit(m_fractureUnit());
this->perforationLength = fractureTemplate->perforationLengthInFractureUnit(m_fractureUnit());
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimFractureTemplate* RimFracture::fractureTemplate() const
{
return m_fractureTemplate();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RivWellFracturePartMgr* RimFracture::fracturePartManager()
{
CVF_ASSERT(m_fracturePartMgr.notNull());
return m_fracturePartMgr.p();
}

View File

@ -0,0 +1,130 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RiaEclipseUnitTools.h"
#include "Rim3dPropertiesInterface.h"
#include "RimCheckableNamedObject.h"
#include "cvfBase.h"
#include "cvfObject.h"
#include "cvfVector3.h"
#include "cvfMatrix4.h"
#include "cvfPlane.h"
#include "cafAppEnum.h"
#include "cafPdmChildField.h"
#include "cafPdmFieldCvfVec3d.h"
#include "cafPdmProxyValueField.h"
#include "cafPdmPtrField.h"
class RimEclipseCase;
class RimEllipseFractureTemplate;
class RivWellFracturePartMgr;
class RimFractureTemplate;
class RigFracturedEclipseCellExportData;
class RigMainGrid;
//==================================================================================================
///
///
//==================================================================================================
class RimFracture : public RimCheckableNamedObject, public Rim3dPropertiesInterface
{
CAF_PDM_HEADER_INIT;
public:
RimFracture(void);
virtual ~RimFracture(void);
caf::PdmField<double> azimuth;
caf::PdmField<double> perforationLength;
caf::PdmField<double> perforationEfficiency;
caf::PdmField<double> wellDiameter;
caf::PdmField<double> dip;
caf::PdmField<double> tilt;
caf::PdmField<int> stimPlanTimeIndexToPlot;
caf::PdmField<bool> showPolygonFractureOutline;
double wellRadius(RiaEclipseUnitTools::UnitSystem unitSystem) const;
cvf::Vec3d anchorPosition() const ;
void setAnchorPosition(const cvf::Vec3d& pos);
RiaEclipseUnitTools::UnitSystem fractureUnit() const;
void setFractureUnit(RiaEclipseUnitTools::UnitSystem unitSystem);
bool isEclipseCellWithinContainment(const RigMainGrid* mainGrid,
size_t globalCellIndex) const;
size_t findAnchorEclipseCell(const RigMainGrid* mainGrid) const;
cvf::Mat4d transformMatrix() const;
void setFractureTemplate(RimFractureTemplate* fractureTemplate);
RimFractureTemplate* fractureTemplate() const;
RivWellFracturePartMgr* fracturePartManager();
void clearDisplayGeometryCache();
void triangleGeometry(std::vector<cvf::uint>* triangleIndices, std::vector<cvf::Vec3f>* vxCoords );
std::vector<size_t> getPotentiallyFracturedCells(const RigMainGrid* mainGrid);
virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override;
cvf::Vec3d fracturePosition() const;
virtual void updateAzimuthBasedOnWellAzimuthAngle() = 0;
virtual double wellAzimuthAtFracturePosition() const = 0;
virtual double fractureMD() const = 0;
virtual void loadDataAndUpdate() = 0;
protected:
virtual QList<caf::PdmOptionItemInfo> calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool * useOptionsOnly) override;
virtual void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) override;
virtual void defineEditorAttribute(const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute * attribute) override;
private:
cvf::Vec3d fracturePositionForUi() const;
double wellFractureAzimuthDiff() const;
QString wellFractureAzimuthDiffText() const;
QString wellAzimuthAtFracturePositionText() const;
virtual cvf::BoundingBox boundingBoxInDomainCoords() override;
protected:
caf::PdmPtrField<RimFractureTemplate*> m_fractureTemplate;
caf::PdmProxyValueField<cvf::Vec3d> m_uiAnchorPosition;
caf::PdmField< RiaEclipseUnitTools::UnitSystemType > m_fractureUnit;
caf::PdmProxyValueField<QString> m_uiWellPathAzimuth;
caf::PdmProxyValueField<QString> m_uiWellFractureAzimuthDiff;
caf::PdmField<QString> m_wellFractureAzimuthAngleWarning;
private:
caf::PdmField<cvf::Vec3d> m_anchorPosition;
cvf::ref<RivWellFracturePartMgr> m_fracturePartMgr;
};

View File

@ -0,0 +1,142 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RimFractureContainment.h"
#include "cafPdmUiSliderEditor.h"
#include "RigMainGrid.h"
#include "RimProject.h"
CAF_PDM_SOURCE_INIT(RimFractureContainment, "FractureContainment");
namespace caf
{
template<>
void caf::AppEnum< RimFractureContainment::FaultTruncType>::setUp()
{
addItem(RimFractureContainment::DISABLED, "DISABLED", "Disable");
addItem(RimFractureContainment::TRUNCATE_AT_FAULT, "TRUNCATE_AT_FAULT", "Truncate At Faults");
addItem(RimFractureContainment::CONTINUE_IN_CONTAINMENT_ZONE, "CONTINUE_IN_CONTAINMENT_ZONE", "Continue in Containment Zone");
setDefault(RimFractureContainment::DISABLED);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimFractureContainment::RimFractureContainment()
{
CAF_PDM_InitObject("Fracture Containment", "", "", "");
CAF_PDM_InitField(&m_isUsingFractureContainment, "IsUsingFractureContainment", false, "Fracture Containment", "", "", "");
CAF_PDM_InitField(&m_topKLayer, "TopKLayer", 0, "Top Layer", "", "", "");
//m_topKLayer.uiCapability()->setUiEditorTypeName(caf::PdmUiSliderEditor::uiEditorTypeName());
CAF_PDM_InitField(&m_baseKLayer, "BaseKLayer", 0, "Base Layer", "", "", "");
//m_topKLayer.uiCapability()->setUiEditorTypeName(caf::PdmUiSliderEditor::uiEditorTypeName());
// This field is not active yet.
CAF_PDM_InitFieldNoDefault(&m_faultTruncation, "FaultTruncationType", "Fault Truncation", "", "", "");
m_faultTruncation.uiCapability()->setUiHidden(true);
m_faultTruncation.xmlCapability()->setIOWritable(false); // When in operation, remove
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimFractureContainment::~RimFractureContainment()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QList<caf::PdmOptionItemInfo> RimFractureContainment::calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions,
bool* useOptionsOnly)
{
QList<caf::PdmOptionItemInfo> options;
if (fieldNeedingOptions == &m_faultTruncation)
{
options.push_back(caf::PdmOptionItemInfo(caf::AppEnum< FaultTruncType >::uiText(DISABLED), DISABLED));
options.push_back(caf::PdmOptionItemInfo(caf::AppEnum< FaultTruncType >::uiText(TRUNCATE_AT_FAULT), TRUNCATE_AT_FAULT));
if (m_isUsingFractureContainment())
{
options.push_back(caf::PdmOptionItemInfo(caf::AppEnum< FaultTruncType >::uiText(CONTINUE_IN_CONTAINMENT_ZONE), CONTINUE_IN_CONTAINMENT_ZONE));
}
}
return options;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimFractureContainment::isEclipseCellWithinContainment(const RigMainGrid* mainGrid, size_t anchorEclipseCell, size_t globalCellIndex) const
{
if (!this->m_isUsingFractureContainment()) return true;
CVF_ASSERT(mainGrid);
size_t i, j, k;
if (globalCellIndex >= mainGrid->globalCellArray().size()) return false;
bool ok = mainGrid->ijkFromCellIndex(globalCellIndex, &i, &j, &k);
if (k + 1 < static_cast<size_t>(m_topKLayer()))
{
return false;
}
if (k + 1 > static_cast<size_t>(m_baseKLayer()))
{
return false;
}
// Todo: use fault propagation mode
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFractureContainment::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering)
{
uiOrdering.add(&m_isUsingFractureContainment);
uiOrdering.add(&m_topKLayer);
uiOrdering.add(&m_baseKLayer);
//uiOrdering.add(&m_faultTruncation);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFractureContainment::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue)
{
if (changedField == &m_isUsingFractureContainment
|| m_isUsingFractureContainment())
{
RimProject* proj;
this->firstAncestorOrThisOfType(proj);
if (proj)
{
proj->reloadCompletionTypeResultsInAllViews();
}
}
}

View File

@ -0,0 +1,62 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "cafPdmObject.h"
#include "cafPdmField.h"
#include "cafAppEnum.h"
class RigMainGrid;
class RimFractureContainment : public caf::PdmObject
{
CAF_PDM_HEADER_INIT;
public:
RimFractureContainment();
~RimFractureContainment();
enum FaultTruncType
{
DISABLED,
TRUNCATE_AT_FAULT,
CONTINUE_IN_CONTAINMENT_ZONE
};
bool isEnabled() const { return m_isUsingFractureContainment();}
bool isEclipseCellWithinContainment(const RigMainGrid* mainGrid, size_t anchorEclipseCell, size_t globalCellIndex) const;
virtual void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) override;
protected:
virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override;
virtual QList<caf::PdmOptionItemInfo> calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly) override;
private:
friend caf::AppEnum< FaultTruncType >;
caf::PdmField< caf::AppEnum< FaultTruncType > > m_faultTruncation;
caf::PdmField<bool> m_isUsingFractureContainment;
caf::PdmField<int> m_topKLayer;
caf::PdmField<int> m_baseKLayer;
};

View File

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

View File

@ -0,0 +1,47 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "cafPdmField.h"
#include "cafPdmObject.h"
#include "cafPdmPtrField.h"
#include "cafPdmUiItem.h"
class RimEclipseCase;
//==================================================================================================
///
///
//==================================================================================================
class RimFractureExportSettings : public caf::PdmObject
{
CAF_PDM_HEADER_INIT;
public:
RimFractureExportSettings();
caf::PdmField<QString> fileName;
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);
};

View File

@ -0,0 +1,308 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RimFractureTemplate.h"
#include "RigTesselatorTools.h"
#include "RimFracture.h"
#include "RimProject.h"
#include "cafPdmObject.h"
#include "cafPdmUiDoubleSliderEditor.h"
#include "cvfVector3.h"
#include "RimFractureContainment.h"
namespace caf
{
template<>
void caf::AppEnum< RimFractureTemplate::FracOrientationEnum>::setUp()
{
addItem(RimFractureTemplate::AZIMUTH, "Az", "Azimuth");
addItem(RimFractureTemplate::ALONG_WELL_PATH, "AlongWellPath", "Along Well Path");
addItem(RimFractureTemplate::TRANSVERSE_WELL_PATH, "TransverseWellPath", "Transverse (normal) to Well Path");
setDefault(RimFractureTemplate::TRANSVERSE_WELL_PATH);
}
template<>
void caf::AppEnum< RimFractureTemplate::FracConductivityEnum>::setUp()
{
addItem(RimFractureTemplate::INFINITE_CONDUCTIVITY, "InfiniteConductivity", "Infinite Conductivity");
addItem(RimFractureTemplate::FINITE_CONDUCTIVITY, "FiniteConductivity", "Finite Conductivity");
setDefault(RimFractureTemplate::INFINITE_CONDUCTIVITY);
}
}
CAF_PDM_XML_ABSTRACT_SOURCE_INIT(RimFractureTemplate, "RimFractureTemplate");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimFractureTemplate::RimFractureTemplate(void)
{
CAF_PDM_InitObject("Fracture Template", ":/FractureTemplate16x16.png", "", "");
CAF_PDM_InitField(&name, "UserDescription", QString("Fracture Template"), "Name", "", "", "");
CAF_PDM_InitField(&fractureTemplateUnit, "fractureTemplateUnit", caf::AppEnum<RiaEclipseUnitTools::UnitSystem>(RiaEclipseUnitTools::UNITS_METRIC), "Units System", "", "", "");
fractureTemplateUnit.uiCapability()->setUiReadOnly(true);
CAF_PDM_InitField(&orientationType, "Orientation", caf::AppEnum<FracOrientationEnum>(TRANSVERSE_WELL_PATH), "Fracture Orientation", "", "", "");
CAF_PDM_InitField(&azimuthAngle, "AzimuthAngle", 0.0f, "Azimuth Angle", "", "", ""); //Is this correct description?
CAF_PDM_InitField(&skinFactor, "SkinFactor", 0.0f, "Skin Factor", "", "", "");
CAF_PDM_InitField(&perforationLength, "PerforationLength", 1.0, "Perforation Length", "", "", "");
CAF_PDM_InitField(&perforationEfficiency, "perforationEfficiency", 1.0, "perforation Efficiency", "", "", "");
perforationEfficiency.uiCapability()->setUiEditorTypeName(caf::PdmUiDoubleSliderEditor::uiEditorTypeName());
CAF_PDM_InitField(&wellDiameter, "wellDiameter", 0.216, "Well Diameter at Fracture", "", "", "");
CAF_PDM_InitField(&conductivityType, "FractureCondictivity", caf::AppEnum<FracConductivityEnum>(FINITE_CONDUCTIVITY), "Conductivity in Fracture", "", "", "");
CAF_PDM_InitFieldNoDefault(&m_fractureContainment, "fractureContainmentField", "Fracture Containment", "", "", "");
m_fractureContainment = new RimFractureContainment();
m_fractureContainment.uiCapability()->setUiTreeHidden(true);
m_fractureContainment.uiCapability()->setUiTreeChildrenHidden(true);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimFractureTemplate::~RimFractureTemplate()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
caf::PdmFieldHandle* RimFractureTemplate::userDescriptionField()
{
return &name;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFractureTemplate::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue)
{
if (changedField == &azimuthAngle || changedField == &orientationType)
{
//Changes to one of these parameters should change all fractures with this fracture template attached.
RimProject* proj;
this->firstAncestorOrThisOfType(proj);
if (proj)
{
//Regenerate geometry
std::vector<RimFracture*> fractures;
proj->descendantsIncludingThisOfType(fractures);
for (RimFracture* fracture : fractures)
{
if (fracture->fractureTemplate() == this)
{
if (changedField == &azimuthAngle && (abs(oldValue.toDouble() - fracture->azimuth()) < 1e-5))
{
fracture->azimuth = azimuthAngle;
fracture->clearDisplayGeometryCache();
}
if (changedField == &orientationType)
{
if (newValue == AZIMUTH)
{
fracture->azimuth = azimuthAngle;
}
else fracture->updateAzimuthBasedOnWellAzimuthAngle();
fracture->clearDisplayGeometryCache();
}
}
}
proj->createDisplayModelAndRedrawAllViews();
}
}
if (changedField == &perforationLength || changedField == &perforationEfficiency || changedField == &wellDiameter)
{
RimProject* proj;
this->firstAncestorOrThisOfType(proj);
if (!proj) return;
std::vector<RimFracture*> fractures;
proj->descendantsIncludingThisOfType(fractures);
for (RimFracture* fracture : fractures)
{
if (fracture->fractureTemplate() == this)
{
if (changedField == &perforationLength && (abs(oldValue.toDouble() - fracture->perforationLength()) < 1e-5))
{
fracture->perforationLength = perforationLength;
}
if (changedField == &perforationEfficiency && (abs(oldValue.toDouble() - fracture->perforationEfficiency()) < 1e-5))
{
fracture->perforationEfficiency = perforationEfficiency;
}
if (changedField == &wellDiameter && (abs(oldValue.toDouble() - fracture->wellDiameter()) < 1e-5))
{
fracture->wellDiameter = wellDiameter;
}
}
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFractureTemplate::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering)
{
if (fractureTemplateUnit == RiaEclipseUnitTools::UNITS_METRIC)
{
wellDiameter.uiCapability()->setUiName("Well Diameter [m]");
perforationLength.uiCapability()->setUiName("Perforation Length [m]");
}
else if (fractureTemplateUnit == RiaEclipseUnitTools::UNITS_FIELD)
{
wellDiameter.uiCapability()->setUiName("Well Diameter [inches]");
perforationLength.uiCapability()->setUiName("Perforation Length [Ft]");
}
if (orientationType == RimFractureTemplate::ALONG_WELL_PATH
|| orientationType == RimFractureTemplate::TRANSVERSE_WELL_PATH)
{
azimuthAngle.uiCapability()->setUiHidden(true);
}
else if (orientationType == RimFractureTemplate::AZIMUTH)
{
azimuthAngle.uiCapability()->setUiHidden(false);
}
if (orientationType == RimFractureTemplate::ALONG_WELL_PATH)
{
perforationEfficiency.uiCapability()->setUiHidden(false);
perforationLength.uiCapability()->setUiHidden(false);
}
else
{
perforationEfficiency.uiCapability()->setUiHidden(true);
perforationLength.uiCapability()->setUiHidden(true);
}
if (conductivityType == FINITE_CONDUCTIVITY)
{
wellDiameter.uiCapability()->setUiHidden(false);
}
else if (conductivityType == INFINITE_CONDUCTIVITY)
{
wellDiameter.uiCapability()->setUiHidden(true);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFractureTemplate::defineEditorAttribute(const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute)
{
if (field == &perforationEfficiency)
{
caf::PdmUiDoubleSliderEditorAttribute* myAttr = dynamic_cast<caf::PdmUiDoubleSliderEditorAttribute*>(attribute);
if (myAttr)
{
myAttr->m_minimum = 0;
myAttr->m_maximum = 1.0;
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RimFractureTemplate::wellDiameterInFractureUnit(RiaEclipseUnitTools::UnitSystemType fractureUnit)
{
if (fractureUnit == fractureTemplateUnit())
{
return wellDiameter;
}
else if (fractureTemplateUnit == RiaEclipseUnitTools::UNITS_METRIC
&& fractureUnit == RiaEclipseUnitTools::UNITS_FIELD)
{
return RiaEclipseUnitTools::meterToInch(wellDiameter);
}
else if (fractureTemplateUnit == RiaEclipseUnitTools::UNITS_FIELD
&& fractureUnit == RiaEclipseUnitTools::UNITS_METRIC)
{
return RiaEclipseUnitTools::inchToMeter(wellDiameter);
}
return cvf::UNDEFINED_DOUBLE;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RimFractureTemplate::perforationLengthInFractureUnit(RiaEclipseUnitTools::UnitSystemType fractureUnit)
{
if (fractureUnit == fractureTemplateUnit())
{
return perforationLength;
}
else if (fractureTemplateUnit == RiaEclipseUnitTools::UNITS_METRIC
&& fractureUnit == RiaEclipseUnitTools::UNITS_FIELD)
{
return RiaEclipseUnitTools::meterToFeet(perforationLength);
}
else if (fractureTemplateUnit == RiaEclipseUnitTools::UNITS_FIELD
&& fractureUnit == RiaEclipseUnitTools::UNITS_METRIC)
{
return RiaEclipseUnitTools::feetToMeter(perforationLength);
}
return cvf::UNDEFINED_DOUBLE;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const RimFractureContainment * RimFractureTemplate::fractureContainment()
{
return m_fractureContainment();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFractureTemplate::setDefaultWellDiameterFromUnit()
{
if (fractureTemplateUnit == RiaEclipseUnitTools::UNITS_FIELD)
{
wellDiameter = 8.5;
}
else if (fractureTemplateUnit == RiaEclipseUnitTools::UNITS_METRIC)
{
wellDiameter = 0.216;
}
}

View File

@ -0,0 +1,98 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RiaEclipseUnitTools.h"
#include "cafAppEnum.h"
#include "cafPdmField.h"
#include "cafPdmFieldHandle.h"
#include "cafPdmObject.h"
#include "cafPdmChildField.h"
#include "cafPdmFieldCvfVec3d.h"
#include "cvfBase.h"
#include "cvfVector3.h"
#include <vector>
class RigEclipseCaseData;
class RigFractureGrid;
class RimFractureContainment;
//==================================================================================================
///
///
//==================================================================================================
class RimFractureTemplate : public caf::PdmObject
{
CAF_PDM_HEADER_INIT;
public:
RimFractureTemplate(void);
virtual ~RimFractureTemplate(void);
caf::PdmField<QString> name;
caf::PdmField<float> azimuthAngle;
caf::PdmField<float> skinFactor;
caf::PdmField<double> perforationLength;
caf::PdmField<double> perforationEfficiency;
caf::PdmField<double> wellDiameter;
enum FracOrientationEnum
{
AZIMUTH,
ALONG_WELL_PATH,
TRANSVERSE_WELL_PATH
};
caf::PdmField< caf::AppEnum< FracOrientationEnum > > orientationType;
enum FracConductivityEnum
{
INFINITE_CONDUCTIVITY,
FINITE_CONDUCTIVITY,
};
caf::PdmField< caf::AppEnum< FracConductivityEnum > > conductivityType;
caf::PdmField< RiaEclipseUnitTools::UnitSystemType > fractureTemplateUnit;
void setDefaultWellDiameterFromUnit();
double wellDiameterInFractureUnit(RiaEclipseUnitTools::UnitSystemType fractureUnit);
double perforationLengthInFractureUnit(RiaEclipseUnitTools::UnitSystemType fractureUnit);
virtual void fractureTriangleGeometry(std::vector<cvf::Vec3f>* nodeCoords,
std::vector<cvf::uint>* triangleIndices,
RiaEclipseUnitTools::UnitSystem neededUnit) = 0;
virtual std::vector<cvf::Vec3f> fractureBorderPolygon(RiaEclipseUnitTools::UnitSystem neededUnit) = 0;
virtual const RigFractureGrid* fractureGrid() const = 0;
const RimFractureContainment * fractureContainment();
protected:
caf::PdmChildField<RimFractureContainment*> m_fractureContainment;
virtual caf::PdmFieldHandle* userDescriptionField() override;
virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override;
virtual void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering);
virtual void defineEditorAttribute(const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute) override;
};

View File

@ -0,0 +1,150 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2016- 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 "RimFractureTemplateCollection.h"
#include "RimEllipseFractureTemplate.h"
#include "RimFractureTemplate.h"
#include "RimStimPlanFractureTemplate.h"
#include "cafPdmObject.h"
CAF_PDM_SOURCE_INIT(RimFractureTemplateCollection, "FractureDefinitionCollection");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimFractureTemplateCollection::RimFractureTemplateCollection(void)
{
CAF_PDM_InitObject("Fracture Templates", ":/FractureTemplates16x16.png", "", "");
CAF_PDM_InitField(&defaultUnitsForFracTemplates, "defaultUnitForFracTemplates", caf::AppEnum<RiaEclipseUnitTools::UnitSystem>(RiaEclipseUnitTools::UNITS_METRIC), "Default unit system for fracture templates", "", "", "");
CAF_PDM_InitFieldNoDefault(&fractureDefinitions, "FractureDefinitions", "", "", "", "");
fractureDefinitions.uiCapability()->setUiHidden(true);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimFractureTemplateCollection::~RimFractureTemplateCollection()
{
fractureDefinitions.deleteAllChildObjects();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<std::pair<QString, QString> > RimFractureTemplateCollection::stimPlanResultNamesAndUnits() const
{
std::set<std::pair<QString, QString> > nameSet;
for (const RimFractureTemplate* f : fractureDefinitions())
{
auto stimPlanFracture = dynamic_cast<const RimStimPlanFractureTemplate*>(f);
if (stimPlanFracture)
{
std::vector<std::pair<QString, QString> > namesAndUnits = stimPlanFracture->resultNamesWithUnit();
for (auto nameAndUnit : namesAndUnits)
{
nameSet.insert(nameAndUnit);
}
}
}
std::vector<std::pair<QString, QString>> names(nameSet.begin(), nameSet.end());
return names;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<QString> RimFractureTemplateCollection::stimPlanResultNames() const
{
std::vector<QString> names;
for (auto nameAndUnit : stimPlanResultNamesAndUnits())
{
names.push_back(nameAndUnit.first);
}
return names;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFractureTemplateCollection::computeMinMax(const QString& resultName, const QString& unit, double* minValue, double* maxValue, double* posClosestToZero, double* negClosestToZero) const
{
for (const RimFractureTemplate* f : fractureDefinitions())
{
auto stimPlanFracture = dynamic_cast<const RimStimPlanFractureTemplate*>(f);
if (stimPlanFracture)
{
stimPlanFracture->computeMinMax(resultName, unit, minValue, maxValue, posClosestToZero, negClosestToZero);
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFractureTemplateCollection::deleteFractureDefinitions()
{
fractureDefinitions.deleteAllChildObjects();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFractureTemplateCollection::loadAndUpdateData()
{
for (RimFractureTemplate* f : fractureDefinitions())
{
RimStimPlanFractureTemplate* stimPlanFracture = dynamic_cast<RimStimPlanFractureTemplate*>(f);
if (stimPlanFracture)
{
stimPlanFracture->loadDataAndUpdate();
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFractureTemplateCollection::updateFilePathsFromProjectPath(const QString& newProjectPath, const QString& oldProjectPath)
{
for (RimFractureTemplate* f : fractureDefinitions())
{
RimStimPlanFractureTemplate* stimPlanFracture = dynamic_cast<RimStimPlanFractureTemplate*>(f);
if (stimPlanFracture)
{
stimPlanFracture->updateFilePathsFromProjectPath(newProjectPath, oldProjectPath);
}
RimEllipseFractureTemplate* ellipseFracture = dynamic_cast<RimEllipseFractureTemplate*>(f);
if (ellipseFracture)
{
ellipseFracture->loadDataAndUpdate();
}
}
}

View File

@ -0,0 +1,52 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2016- 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 "RiaEclipseUnitTools.h"
#include "cafPdmField.h"
#include "cafPdmObject.h"
#include "cafPdmChildArrayField.h"
class RimFractureTemplate;
//==================================================================================================
///
///
//==================================================================================================
class RimFractureTemplateCollection : public caf::PdmObject
{
CAF_PDM_HEADER_INIT;
public:
RimFractureTemplateCollection(void);
virtual ~RimFractureTemplateCollection(void);
caf::PdmChildArrayField<RimFractureTemplate*> fractureDefinitions;
caf::PdmField< RiaEclipseUnitTools::UnitSystemType > defaultUnitsForFracTemplates;
std::vector<std::pair<QString, QString> > stimPlanResultNamesAndUnits() const;
std::vector<QString> stimPlanResultNames() const;
void computeMinMax(const QString& resultName, const QString& unit, double* minValue, double* maxValue, double* posClosestToZero, double* negClosestToZero) const;
void deleteFractureDefinitions();
void loadAndUpdateData();
void updateFilePathsFromProjectPath(const QString& newProjectPath, const QString& oldProjectPath);
};

View File

@ -62,7 +62,14 @@ void RimPerforationCollection::fieldChangedByUi(const caf::PdmFieldHandle* chang
{
RimProject* proj;
this->firstAncestorOrThisOfTypeAsserted(proj);
if (changedField == &m_isChecked)
{
proj->reloadCompletionTypeResultsInAllViews();
}
else
{
proj->createDisplayModelAndRedrawAllViews();
}
}
//--------------------------------------------------------------------------------------------------

View File

@ -0,0 +1,344 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2016- 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 "RimSimWellFracture.h"
#include "RigCell.h"
#include "RigMainGrid.h"
#include "RigSingleWellResultsData.h"
#include "RimEclipseView.h"
#include "RimEclipseWell.h"
#include "RimEllipseFractureTemplate.h"
#include "RimFracture.h"
#include "RimFractureTemplate.h"
#include "RimProject.h"
#include "cafPdmUiDoubleSliderEditor.h"
CAF_PDM_SOURCE_INIT(RimSimWellFracture, "SimWellFracture");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSimWellFracture::RimSimWellFracture(void)
{
CAF_PDM_InitObject("SimWellFracture", ":/FractureSymbol16x16.png", "", "");
CAF_PDM_InitField(&m_location, "MeasuredDepth", 0.0f, "Pseudo Length Location", "", "", "");
m_location.uiCapability()->setUiEditorTypeName(caf::PdmUiDoubleSliderEditor::uiEditorTypeName());
CAF_PDM_InitFieldNoDefault(&m_displayIJK, "Cell_IJK", "Cell IJK", "", "", "");
m_displayIJK.registerGetMethod(this, &RimSimWellFracture::createOneBasedIJKText);
m_displayIJK.uiCapability()->setUiReadOnly(true);
CAF_PDM_InitField(&m_branchIndex, "Branch", 0, "Branch", "", "", "");
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSimWellFracture::~RimSimWellFracture()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSimWellFracture::setClosestWellCoord(cvf::Vec3d& position, size_t branchIndex)
{
updateBranchGeometry();
double location = m_branchCenterLines[branchIndex].locationAlongWellCoords(position);
m_branchIndex = static_cast<int>(branchIndex);
m_location = location;
updateFracturePositionFromLocation();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSimWellFracture::updateAzimuthBasedOnWellAzimuthAngle()
{
updateBranchGeometry();
if (!fractureTemplate()) return;
if (fractureTemplate()->orientationType == RimFractureTemplate::ALONG_WELL_PATH
|| fractureTemplate()->orientationType == RimFractureTemplate::TRANSVERSE_WELL_PATH)
{
double simWellAzimuth = wellAzimuthAtFracturePosition();
if (fractureTemplate()->orientationType == RimFractureTemplate::ALONG_WELL_PATH )
{
azimuth = simWellAzimuth;
}
else if (fractureTemplate()->orientationType == RimFractureTemplate::TRANSVERSE_WELL_PATH)
{
if (simWellAzimuth + 90 < 360) azimuth = simWellAzimuth + 90;
else azimuth = simWellAzimuth - 90;
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RimSimWellFracture::wellAzimuthAtFracturePosition() const
{
double simWellAzimuth = m_branchCenterLines[m_branchIndex].simWellAzimuthAngle(fracturePosition());
if (simWellAzimuth < 0) simWellAzimuth += 360;
return simWellAzimuth;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RimSimWellFracture::wellDipAtFracturePosition()
{
updateBranchGeometry();
double simWellDip = m_branchCenterLines[m_branchIndex].simWellDipAngle(fracturePosition());
return simWellDip;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSimWellFracture::loadDataAndUpdate()
{
setBranchGeometry();
updateFracturePositionFromLocation();
updateAzimuthBasedOnWellAzimuthAngle();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSimWellFracture::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue)
{
RimFracture::fieldChangedByUi(changedField, oldValue, newValue);
if ( changedField == &m_location
|| changedField == &m_branchIndex
)
{
updateFracturePositionFromLocation();
RimFractureTemplate::FracOrientationEnum orientation;
if (fractureTemplate()) orientation = fractureTemplate()->orientationType();
else orientation = RimFractureTemplate::AZIMUTH;
if (orientation != RimFractureTemplate::AZIMUTH)
{
updateAzimuthBasedOnWellAzimuthAngle();
}
RimProject* proj;
this->firstAncestorOrThisOfType(proj);
if (proj) proj->reloadCompletionTypeResultsInAllViews();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSimWellFracture::recomputeWellCenterlineCoordinates()
{
m_branchCenterLines.clear();
updateBranchGeometry();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSimWellFracture::updateFracturePositionFromLocation()
{
updateBranchGeometry();
if (m_branchCenterLines.size() > 0)
{
cvf::Vec3d interpolated = m_branchCenterLines[m_branchIndex()].interpolatedPointAlongWellPath(m_location());
this->setAnchorPosition(interpolated);
RimProject* proj;
this->firstAncestorOrThisOfType(proj);
if (proj) proj->createDisplayModelAndRedrawAllViews();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSimWellFracture::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering)
{
RimFracture::defineUiOrdering(uiConfigName, uiOrdering);
uiOrdering.add(nameField());
uiOrdering.add(&showPolygonFractureOutline);
caf::PdmUiGroup* locationGroup = uiOrdering.addNewGroup("Location / Orientation");
locationGroup->add(&m_location);
locationGroup->add(&m_branchIndex);
locationGroup->add(&azimuth);
locationGroup->add(&m_uiWellPathAzimuth);
locationGroup->add(&m_uiWellFractureAzimuthDiff);
locationGroup->add(&m_wellFractureAzimuthAngleWarning);
locationGroup->add(&dip);
locationGroup->add(&tilt);
caf::PdmUiGroup* propertyGroup = uiOrdering.addNewGroup("Properties");
propertyGroup->add(&m_fractureUnit);
propertyGroup->add(&m_fractureTemplate);
propertyGroup->add(&stimPlanTimeIndexToPlot);
propertyGroup->add(&perforationLength);
propertyGroup->add(&perforationEfficiency);
propertyGroup->add(&wellDiameter);
caf::PdmUiGroup* fractureCenterGroup = uiOrdering.addNewGroup("Fracture Center Info");
fractureCenterGroup->add(&m_uiAnchorPosition);
fractureCenterGroup->add(&m_displayIJK);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSimWellFracture::defineEditorAttribute(const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute * attribute)
{
RimFracture::defineEditorAttribute(field, uiConfigName, attribute);
if (field == &m_location)
{
caf::PdmUiDoubleSliderEditorAttribute* myAttr = dynamic_cast<caf::PdmUiDoubleSliderEditorAttribute*>(attribute);
if (myAttr)
{
updateBranchGeometry();
if (m_branchCenterLines.size() > 0)
{
const RigSimulationWellCoordsAndMD& pointAndMd = m_branchCenterLines[m_branchIndex];
myAttr->m_minimum = pointAndMd.measuredDepths().front();
myAttr->m_maximum = pointAndMd.measuredDepths().back();
myAttr->m_sliderTickCount = pointAndMd.measuredDepths().back();
}
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QList<caf::PdmOptionItemInfo> RimSimWellFracture::calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly)
{
QList<caf::PdmOptionItemInfo> options = RimFracture::calculateValueOptions(fieldNeedingOptions, useOptionsOnly);
if (fieldNeedingOptions == &m_branchIndex)
{
if (m_branchCenterLines.size() == 0)
{
updateBranchGeometry();
}
if (m_branchCenterLines.size() > 0)
{
size_t branchCount = m_branchCenterLines.size();
for (size_t bIdx = 0; bIdx < branchCount; ++bIdx)
{
// Use 1-based index in UI
options.push_back(caf::PdmOptionItemInfo(QString::number(bIdx + 1), QVariant::fromValue(bIdx)));
}
}
}
return options;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RigMainGrid* RimSimWellFracture::ownerCaseMainGrid() const
{
RimEclipseView* ownerEclView;
this->firstAncestorOrThisOfType(ownerEclView);
if (ownerEclView)
return ownerEclView->mainGrid();
else
return nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSimWellFracture::updateBranchGeometry()
{
if (m_branchCenterLines.size() == 0)
{
setBranchGeometry();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSimWellFracture::setBranchGeometry()
{
m_branchCenterLines.clear();
RimEclipseWell* rimWell = nullptr;
this->firstAncestorOrThisOfType(rimWell);
CVF_ASSERT(rimWell);
std::vector< std::vector <cvf::Vec3d> > pipeBranchesCLCoords;
std::vector< std::vector <RigWellResultPoint> > pipeBranchesCellIds;
rimWell->calculateWellPipeStaticCenterLine(pipeBranchesCLCoords,
pipeBranchesCellIds);
for (const auto& branch : pipeBranchesCLCoords)
{
RigSimulationWellCoordsAndMD wellPathWithMD(branch);
m_branchCenterLines.push_back(wellPathWithMD);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimSimWellFracture::createOneBasedIJKText() const
{
RigMainGrid* mainGrid = ownerCaseMainGrid();
size_t i,j,k;
size_t anchorCellIdx = findAnchorEclipseCell(mainGrid);
if (anchorCellIdx == cvf::UNDEFINED_SIZE_T) return "";
bool ok = mainGrid->ijkFromCellIndex(anchorCellIdx, &i, &j, &k);
if (!ok) return "";
return QString("[%1, %2, %3]").arg(i + 1).arg(j + 1).arg(k + 1);
}

View File

@ -0,0 +1,74 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2016- 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 "RimFracture.h"
#include "RigSimulationWellCoordsAndMD.h"
#include "RimEllipseFractureTemplate.h"
//==================================================================================================
///
///
//==================================================================================================
class RimSimWellFracture : public RimFracture
{
CAF_PDM_HEADER_INIT;
public:
RimSimWellFracture(void);
virtual ~RimSimWellFracture(void);
void setClosestWellCoord(cvf::Vec3d& position, size_t branchIndex);
virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override;
void recomputeWellCenterlineCoordinates();
void updateFracturePositionFromLocation();
void updateAzimuthBasedOnWellAzimuthAngle() override;
double wellAzimuthAtFracturePosition() const override;
double wellDipAtFracturePosition();
double fractureMD() const override { return m_location; }
int branchIndex() const { return m_branchIndex(); }
virtual void loadDataAndUpdate() override;
protected:
virtual void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) override;
virtual void defineEditorAttribute(const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute) override;
virtual QList<caf::PdmOptionItemInfo> calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly) override;
RigMainGrid* ownerCaseMainGrid() const;
private:
void updateBranchGeometry();
void setBranchGeometry();
private:
caf::PdmField<float> m_location;
caf::PdmField<int> m_branchIndex;
std::vector<RigSimulationWellCoordsAndMD> m_branchCenterLines;
caf::PdmProxyValueField<QString> m_displayIJK;
QString createOneBasedIJKText() const;
};

View File

@ -0,0 +1,55 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2016- 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 "RimSimWellFractureCollection.h"
#include "RimSimWellFracture.h"
#include "cafPdmObject.h"
CAF_PDM_SOURCE_INIT(RimSimWellFractureCollection, "SimWellFractureCollection");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSimWellFractureCollection::RimSimWellFractureCollection(void)
{
CAF_PDM_InitObject("Fractures", ":/FractureLayout16x16.png", "", "");
CAF_PDM_InitFieldNoDefault(&simwellFractures, "Fractures", "", "", "", "");
simwellFractures.uiCapability()->setUiHidden(true);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSimWellFractureCollection::~RimSimWellFractureCollection()
{
simwellFractures.deleteAllChildObjects();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSimWellFractureCollection::deleteFractures()
{
simwellFractures.deleteAllChildObjects();
}

View File

@ -0,0 +1,43 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2016- 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 "cafPdmField.h"
#include "cafPdmObject.h"
#include "cafPdmChildArrayField.h"
class RimSimWellFracture;
//==================================================================================================
///
///
//==================================================================================================
class RimSimWellFractureCollection : public caf::PdmObject
{
CAF_PDM_HEADER_INIT;
public:
RimSimWellFractureCollection(void);
virtual ~RimSimWellFractureCollection(void);
caf::PdmChildArrayField<RimSimWellFracture*> simwellFractures;
void deleteFractures();
};

View File

@ -0,0 +1,513 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RimStimPlanFractureTemplate.h"
#include "RiaApplication.h"
#include "RiaLogging.h"
#include "RifStimPlanXmlReader.h"
#include "RigStimPlanFractureDefinition.h"
#include "RigFractureGrid.h"
#include "RigFractureCell.h"
#include "RimEclipseView.h"
#include "RimFracture.h"
#include "RimFractureContainment.h"
#include "RimProject.h"
#include "RimStimPlanColors.h"
#include "RimStimPlanLegendConfig.h"
#include "RimTools.h"
#include "RivWellFracturePartMgr.h"
#include "cafPdmObject.h"
#include "cafPdmUiDoubleSliderEditor.h"
#include "cafPdmUiFilePathEditor.h"
#include "cvfVector3.h"
#include <QFileInfo>
#include <QMessageBox>
#include <algorithm>
#include <vector>
#include <cmath>
CAF_PDM_SOURCE_INIT(RimStimPlanFractureTemplate, "RimStimPlanFractureTemplate");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimStimPlanFractureTemplate::RimStimPlanFractureTemplate(void)
{
CAF_PDM_InitObject("Fracture Template", ":/FractureTemplate16x16.png", "", "");
CAF_PDM_InitField(&m_stimPlanFileName, "StimPlanFileName", QString(""), "File Name", "", "", "");
m_stimPlanFileName.uiCapability()->setUiEditorTypeName(caf::PdmUiFilePathEditor::uiEditorTypeName());
CAF_PDM_InitField(&m_wellPathDepthAtFracture, "WellPathDepthAtFracture", 0.0, "Well/Fracture Intersection Depth", "", "", "");
m_wellPathDepthAtFracture.uiCapability()->setUiEditorTypeName(caf::PdmUiDoubleSliderEditor::uiEditorTypeName());
CAF_PDM_InitField(&m_borderPolygonResultName, "parameterForPolyton", QString(""), "Parameter", "", "", "");
m_borderPolygonResultName.uiCapability()->setUiHidden(true);
CAF_PDM_InitField(&m_activeTimeStepIndex, "activeTimeStepIndex", 0, "Active TimeStep Index", "", "", "");
CAF_PDM_InitField(&m_showStimPlanMesh, "showStimPlanMesh", true, "Show StimPlan Mesh", "", "", "");
CAF_PDM_InitField(&m_conductivityScalingFactor, "FractureConductivityFactor", 1.0, "Conductivity Scaling Factor", "", "The conductivity values read from file will be scaled with this parameters", "");
m_fractureGrid = new RigFractureGrid();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimStimPlanFractureTemplate::~RimStimPlanFractureTemplate()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimStimPlanFractureTemplate::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue)
{
RimFractureTemplate::fieldChangedByUi(changedField, oldValue, newValue);
if (&m_stimPlanFileName == changedField)
{
updateUiTreeName();
loadDataAndUpdate();
setDefaultsBasedOnXMLfile();
}
if (&m_activeTimeStepIndex == changedField)
{
updateFractureGrid();
//Changes to this parameters should change all fractures with this fracture template attached.
RimProject* proj;
this->firstAncestorOrThisOfType(proj);
if (proj)
{
std::vector<RimFracture*> fractures;
proj->descendantsIncludingThisOfType(fractures);
for (RimFracture* fracture : fractures)
{
if (fracture->fractureTemplate() == this)
{
fracture->stimPlanTimeIndexToPlot = m_activeTimeStepIndex;
fracture->clearDisplayGeometryCache();
}
}
proj->createDisplayModelAndRedrawAllViews();
}
}
if (&m_wellPathDepthAtFracture == changedField
|| &m_borderPolygonResultName == changedField
|| &m_activeTimeStepIndex == changedField
|| &m_showStimPlanMesh == changedField
|| &m_conductivityScalingFactor == changedField)
{
if (&m_conductivityScalingFactor == changedField)
{
loadDataAndUpdate();
}
RimProject* proj;
this->firstAncestorOrThisOfType(proj);
if (proj)
{
//Regenerate geometry
std::vector<RimFracture*> fractures;
proj->descendantsIncludingThisOfType(fractures);
for (RimFracture* fracture : fractures)
{
if (fracture->fractureTemplate() == this)
{
fracture->clearDisplayGeometryCache();
}
}
}
proj->createDisplayModelAndRedrawAllViews();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimStimPlanFractureTemplate::updateUiTreeName()
{
this->uiCapability()->setUiName(fileNameWithOutPath());
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimStimPlanFractureTemplate::setFileName(const QString& fileName)
{
m_stimPlanFileName = fileName;
updateUiTreeName();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const QString& RimStimPlanFractureTemplate::fileName()
{
return m_stimPlanFileName();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimStimPlanFractureTemplate::fileNameWithOutPath()
{
QFileInfo stimplanfileFileInfo(m_stimPlanFileName());
return stimplanfileFileInfo.fileName();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimStimPlanFractureTemplate::updateFilePathsFromProjectPath(const QString& newProjectPath, const QString& oldProjectPath)
{
m_stimPlanFileName = RimTools::relocateFile(m_stimPlanFileName(), newProjectPath, oldProjectPath, nullptr, nullptr);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimStimPlanFractureTemplate::setDefaultsBasedOnXMLfile()
{
setDepthOfWellPathAtFracture();
RiaLogging::info(QString("Setting well/fracture intersection depth at %1").arg(m_wellPathDepthAtFracture));
m_activeTimeStepIndex = static_cast<int>(m_stimPlanFractureDefinitionData->totalNumberTimeSteps() - 1);
bool polygonPropertySet = setBorderPolygonResultNameToDefault();
if (polygonPropertySet) RiaLogging::info(QString("Calculating polygon outline based on %1 at timestep %2").arg(m_borderPolygonResultName).arg(m_stimPlanFractureDefinitionData->timeSteps()[m_activeTimeStepIndex]));
else RiaLogging::info(QString("Property for polygon calculation not set."));
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimStimPlanFractureTemplate::setBorderPolygonResultNameToDefault()
{
//first option: Width
for (std::pair<QString, QString> property : resultNamesWithUnit())
{
if (property.first == "WIDTH")
{
m_borderPolygonResultName = property.first;
return true;
}
}
//if width not found, use conductivity
for (std::pair<QString, QString> property : resultNamesWithUnit())
{
if (property.first == "CONDUCTIVITY")
{
m_borderPolygonResultName = property.first;
return true;
}
}
//else: Set to first property
if (resultNamesWithUnit().size() > 0)
{
m_borderPolygonResultName = resultNamesWithUnit()[0].first;
return true;
}
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimStimPlanFractureTemplate::loadDataAndUpdate()
{
QString errorMessage;
m_stimPlanFractureDefinitionData = RifStimPlanXmlReader::readStimPlanXMLFile( m_stimPlanFileName(), m_conductivityScalingFactor(), &errorMessage);
if (errorMessage.size() > 0) RiaLogging::error(errorMessage);
if (m_stimPlanFractureDefinitionData.notNull())
{
fractureTemplateUnit = m_stimPlanFractureDefinitionData->unitSet();
}
else
{
fractureTemplateUnit = RiaEclipseUnitTools::UNITS_UNKNOWN;
}
updateFractureGrid();
// Todo: Must update all views using this fracture template
RimEclipseView* activeView = dynamic_cast<RimEclipseView*>(RiaApplication::instance()->activeReservoirView());
if (activeView) activeView->stimPlanColors->loadDataAndUpdate();
updateConnectedEditors();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QList<caf::PdmOptionItemInfo> RimStimPlanFractureTemplate::calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly)
{
QList<caf::PdmOptionItemInfo> options;
if (fieldNeedingOptions == &m_borderPolygonResultName)
{
for (std::pair<QString, QString> nameUnit : resultNamesWithUnit())
{
//options.push_back(caf::PdmOptionItemInfo(nameUnit.first + " [" + nameUnit.second + "]", nameUnit.first + " " + nameUnit.second));
options.push_back(caf::PdmOptionItemInfo(nameUnit.first, nameUnit.first));
}
}
else if (fieldNeedingOptions == &m_activeTimeStepIndex)
{
std::vector<double> timeValues = timeSteps();
int index = 0;
for (double value : timeValues)
{
options.push_back(caf::PdmOptionItemInfo(QString::number(value), index));
index++;
}
}
return options;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimStimPlanFractureTemplate::setDepthOfWellPathAtFracture()
{
if (!m_stimPlanFractureDefinitionData.isNull())
{
double firstDepth = m_stimPlanFractureDefinitionData->minDepth();
double lastDepth = m_stimPlanFractureDefinitionData->maxDepth();
double averageDepth = (firstDepth + lastDepth) / 2;
m_wellPathDepthAtFracture = averageDepth;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimStimPlanFractureTemplate::getUnitForStimPlanParameter(QString parameterName)
{
QString unit;
bool found = false;
bool foundMultiple = false;
for (std::pair<QString, QString> nameUnit : resultNamesWithUnit())
{
if (nameUnit.first == parameterName)
{
unit = nameUnit.second;
if (found) foundMultiple = true;
found = true;
}
}
if (foundMultiple) RiaLogging::error(QString("Multiple units found for same parameter"));
if (!found) RiaLogging::error(QString("Requested unit / parameter not found for %1 template").arg(name()));
return unit;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const std::vector<double>& RimStimPlanFractureTemplate::timeSteps()
{
if (m_stimPlanFractureDefinitionData.isNull()) loadDataAndUpdate();
return m_stimPlanFractureDefinitionData->timeSteps();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<std::pair<QString, QString> > RimStimPlanFractureTemplate::resultNamesWithUnit() const
{
std::vector<std::pair<QString, QString> > propertyNamesUnits;
if (m_stimPlanFractureDefinitionData.notNull())
{
propertyNamesUnits = m_stimPlanFractureDefinitionData->getStimPlanPropertyNamesUnits();
}
return propertyNamesUnits;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimStimPlanFractureTemplate::computeMinMax(const QString& resultName, const QString& unitName, double* minValue, double* maxValue, double* posClosestToZero, double* negClosestToZero) const
{
if (m_stimPlanFractureDefinitionData.notNull())
{
m_stimPlanFractureDefinitionData->computeMinMax(resultName, unitName, minValue, maxValue, posClosestToZero, negClosestToZero);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<std::vector<double>> RimStimPlanFractureTemplate::resultValues(const QString& resultName, const QString& unitName, size_t timeStepIndex) const
{
return m_stimPlanFractureDefinitionData->getDataAtTimeIndex(resultName, unitName, timeStepIndex);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<double> RimStimPlanFractureTemplate::fractureGridResults(const QString& resultName, const QString& unitName, size_t timeStepIndex) const
{
return m_stimPlanFractureDefinitionData->fractureGridResults(resultName, unitName, timeStepIndex);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const RigFractureGrid* RimStimPlanFractureTemplate::fractureGrid() const
{
return m_fractureGrid.p();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimStimPlanFractureTemplate::updateFractureGrid()
{
m_fractureGrid = m_stimPlanFractureDefinitionData->createFractureGrid(m_activeTimeStepIndex,
fractureTemplateUnit,
m_wellPathDepthAtFracture);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimStimPlanFractureTemplate::fractureTriangleGeometry(std::vector<cvf::Vec3f>* nodeCoords,
std::vector<cvf::uint>* triangleIndices,
RiaEclipseUnitTools::UnitSystem neededUnit)
{
if (m_stimPlanFractureDefinitionData.isNull())
{
loadDataAndUpdate();
}
m_stimPlanFractureDefinitionData->createFractureTriangleGeometry(m_wellPathDepthAtFracture,
neededUnit,
name,
nodeCoords,
triangleIndices);
return;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<cvf::Vec3f> RimStimPlanFractureTemplate::fractureBorderPolygon(RiaEclipseUnitTools::UnitSystem neededUnit)
{
QString parameterName = m_borderPolygonResultName;
QString parameterUnit = getUnitForStimPlanParameter(parameterName);
return m_stimPlanFractureDefinitionData->createFractureBorderPolygon(parameterName,
parameterUnit,
m_activeTimeStepIndex,
m_wellPathDepthAtFracture,
neededUnit,
name);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimStimPlanFractureTemplate::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering)
{
RimFractureTemplate::defineUiOrdering(uiConfigName, uiOrdering);
uiOrdering.add(&name);
uiOrdering.add(&m_showStimPlanMesh);
caf::PdmUiGroup* fileGroup = uiOrdering.addNewGroup("Input");
fileGroup->add(&m_stimPlanFileName);
fileGroup->add(&m_activeTimeStepIndex);
fileGroup->add(&m_wellPathDepthAtFracture);
caf::PdmUiGroup* geometryGroup = uiOrdering.addNewGroup("Geometry");
geometryGroup->add(&orientationType);
geometryGroup->add(&azimuthAngle);
caf::PdmUiGroup* trGr = uiOrdering.addNewGroup("Fracture Truncation");
m_fractureContainment()->defineUiOrdering(uiConfigName, *trGr);
caf::PdmUiGroup* propertyGroup = uiOrdering.addNewGroup("Properties");
propertyGroup->add(&m_conductivityScalingFactor);
propertyGroup->add(&conductivityType);
propertyGroup->add(&skinFactor);
propertyGroup->add(&perforationLength);
propertyGroup->add(&perforationEfficiency);
propertyGroup->add(&wellDiameter);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimStimPlanFractureTemplate::defineEditorAttribute(const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute * attribute)
{
RimFractureTemplate::defineEditorAttribute(field, uiConfigName, attribute);
if (field == &m_stimPlanFileName)
{
caf::PdmUiFilePathEditorAttribute* myAttr = dynamic_cast<caf::PdmUiFilePathEditorAttribute*>(attribute);
if (myAttr)
{
myAttr->m_fileSelectionFilter = "StimPlan Xml Files(*.xml);;All Files (*.*)";
}
}
if (field == &m_wellPathDepthAtFracture)
{
if ( !m_stimPlanFractureDefinitionData.isNull() && (m_stimPlanFractureDefinitionData->depthCount() > 0) )
{
caf::PdmUiDoubleSliderEditorAttribute* myAttr = dynamic_cast<caf::PdmUiDoubleSliderEditorAttribute*>(attribute);
if ( myAttr )
{
myAttr->m_minimum = m_stimPlanFractureDefinitionData->minDepth();
myAttr->m_maximum = m_stimPlanFractureDefinitionData->maxDepth();
}
}
}
}

View File

@ -0,0 +1,109 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RimFractureTemplate.h"
#include "cafAppEnum.h"
#include "cafPdmChildArrayField.h"
#include "cafPdmField.h"
#include "cafPdmFieldCvfVec3d.h"
#include "cafPdmFieldHandle.h"
#include "cafPdmObject.h"
#include "cafPdmPtrField.h"
#include "cvfBase.h"
#include "cvfObject.h"
#include "cvfVector3.h"
#include <vector>
#include "RigFractureCell.h"
#include "RigFractureGrid.h"
class RigStimPlanFractureDefinition;
class RimStimPlanLegendConfig;
class RigFractureCell;
class RigFractureGrid;
//==================================================================================================
///
///
//==================================================================================================
class RimStimPlanFractureTemplate : public RimFractureTemplate
{
CAF_PDM_HEADER_INIT;
public:
RimStimPlanFractureTemplate(void);
virtual ~RimStimPlanFractureTemplate(void);
int activeTimeStepIndex() { return m_activeTimeStepIndex; }
bool showStimPlanMesh() { return m_showStimPlanMesh;}
void loadDataAndUpdate();
void setDefaultsBasedOnXMLfile();
void setFileName(const QString& fileName);
const QString& fileName();
QString fileNameWithOutPath();
void updateFilePathsFromProjectPath(const QString& newProjectPath, const QString& oldProjectPath);
// Fracture geometry
const RigFractureGrid* fractureGrid() const;
void updateFractureGrid();
void fractureTriangleGeometry(std::vector<cvf::Vec3f>* nodeCoords,
std::vector<cvf::uint>* triangleIndices,
RiaEclipseUnitTools::UnitSystem neededUnit) override;
std::vector<cvf::Vec3f> fractureBorderPolygon(RiaEclipseUnitTools::UnitSystem neededUnit);
// Result Access
const std::vector<double>& timeSteps();
std::vector<std::pair<QString, QString> > resultNamesWithUnit() const;
void computeMinMax(const QString& resultName, const QString& unitName, double* minValue, double* maxValue, double* posClosestToZero, double* negClosestToZero) const;
std::vector<std::vector<double>> resultValues(const QString& resultName, const QString& unitName, size_t timeStepIndex) const;
std::vector<double> fractureGridResults(const QString& resultName, const QString& unitName, size_t timeStepIndex) const;
protected:
virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override;
virtual QList<caf::PdmOptionItemInfo> calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly) override;
virtual void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering);
virtual void defineEditorAttribute(const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute * attribute) override;
private:
void updateUiTreeName();
bool setBorderPolygonResultNameToDefault();
void setDepthOfWellPathAtFracture();
QString getUnitForStimPlanParameter(QString parameterName);
caf::PdmField<int> m_activeTimeStepIndex;
caf::PdmField<bool> m_showStimPlanMesh;
caf::PdmField<double> m_wellPathDepthAtFracture;
caf::PdmField<QString> m_borderPolygonResultName;
caf::PdmField<QString> m_stimPlanFileName;
cvf::ref<RigStimPlanFractureDefinition> m_stimPlanFractureDefinitionData;
caf::PdmField<double> m_conductivityScalingFactor;
cvf::ref<RigFractureGrid> m_fractureGrid;
};

View File

@ -21,6 +21,9 @@
#include "RimFishbonesCollection.h"
#include "RimFishboneWellPathCollection.h"
#include "RimPerforationCollection.h"
#ifdef USE_PROTOTYPE_FEATURE_FRACTURES
#include "RimWellPathFractureCollection.h"
#endif // USE_PROTOTYPE_FEATURE_FRACTURES
#include "cvfAssert.h"
@ -44,6 +47,12 @@ RimWellPathCompletions::RimWellPathCompletions()
m_fishbonesCollection = new RimFishbonesCollection;
m_fishbonesCollection.uiCapability()->setUiHidden(true);
#ifdef USE_PROTOTYPE_FEATURE_FRACTURES
CAF_PDM_InitFieldNoDefault(&m_fractureCollection, "Fractures", "Fractures", "", "", "");
m_fractureCollection = new RimWellPathFractureCollection;
m_fractureCollection.uiCapability()->setUiHidden(true);
#endif // USE_PROTOTYPE_FEATURE_FRACTURES
CAF_PDM_InitField(&m_wellNameForExport, "WellNameForExport", QString(), "Well Name for Completion Export", "", "", "");
}
@ -83,11 +92,30 @@ QString RimWellPathCompletions::wellNameForExport() const
return m_wellNameForExport();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
#ifdef USE_PROTOTYPE_FEATURE_FRACTURES
RimWellPathFractureCollection* RimWellPathCompletions::fractureCollection() const
{
CVF_ASSERT(m_fractureCollection);
return m_fractureCollection;
}
#endif // USE_PROTOTYPE_FEATURE_FRACTURES
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimWellPathCompletions::hasCompletions() const
{
#ifdef USE_PROTOTYPE_FEATURE_FRACTURES
if (!fractureCollection()->fractures().empty())
{
return true;
}
#endif // USE_PROTOTYPE_FEATURE_FRACTURES
return !fishbonesCollection()->fishbonesSubs().empty() ||
!fishbonesCollection()->wellPathCollection()->wellPaths().empty() ||
!perforationCollection()->perforations().empty();
@ -118,4 +146,11 @@ void RimWellPathCompletions::defineUiTreeOrdering(caf::PdmUiTreeOrdering& uiTree
{
uiTreeOrdering.add(&m_fishbonesCollection);
}
#ifdef USE_PROTOTYPE_FEATURE_FRACTURES
if (!fractureCollection()->fractures().empty())
{
uiTreeOrdering.add(&m_fractureCollection);
}
#endif // USE_PROTOTYPE_FEATURE_FRACTURES
}

View File

@ -24,6 +24,9 @@
class RimFishbonesCollection;
class RimPerforationCollection;
#ifdef USE_PROTOTYPE_FEATURE_FRACTURES
class RimWellPathFractureCollection;
#endif // USE_PROTOTYPE_FEATURE_FRACTURES
//==================================================================================================
///
@ -38,6 +41,9 @@ public:
RimFishbonesCollection* fishbonesCollection() const;
RimPerforationCollection* perforationCollection() const;
#ifdef USE_PROTOTYPE_FEATURE_FRACTURES
RimWellPathFractureCollection* fractureCollection() const;
#endif // USE_PROTOTYPE_FEATURE_FRACTURES
void setWellNameForExport(const QString& name);
QString wellNameForExport() const;
@ -51,5 +57,9 @@ protected:
private:
caf::PdmChildField<RimFishbonesCollection*> m_fishbonesCollection;
caf::PdmChildField<RimPerforationCollection*> m_perforationCollection;
#ifdef USE_PROTOTYPE_FEATURE_FRACTURES
caf::PdmChildField<RimWellPathFractureCollection*> m_fractureCollection;
#endif // USE_PROTOTYPE_FEATURE_FRACTURES
caf::PdmField<QString> m_wellNameForExport;
};

View File

@ -0,0 +1,211 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2016- 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 "RimWellPathFracture.h"
#include "RigWellPath.h"
#include "RimEllipseFractureTemplate.h"
#include "RimProject.h"
#include "RimWellPath.h"
#include "cafPdmUiDoubleSliderEditor.h"
CAF_PDM_SOURCE_INIT(RimWellPathFracture, "WellPathFracture");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimWellPathFracture::RimWellPathFracture(void)
{
CAF_PDM_InitObject("Fracture", ":/FractureSymbol16x16.png", "", "");
CAF_PDM_InitField( &m_measuredDepth, "MeasuredDepth", 0.0f, "Measured Depth Location", "", "", "");
m_measuredDepth.uiCapability()->setUiEditorTypeName(caf::PdmUiDoubleSliderEditor::uiEditorTypeName());
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimWellPathFracture::~RimWellPathFracture()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPathFracture::setMeasuredDepth(double mdValue)
{
m_measuredDepth = mdValue;
updatePositionFromMeasuredDepth();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPathFracture::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue)
{
RimFracture::fieldChangedByUi(changedField, oldValue, newValue);
if (changedField == &m_measuredDepth)
{
updatePositionFromMeasuredDepth();
updateAzimuthBasedOnWellAzimuthAngle();
RimProject* proj = nullptr;
this->firstAncestorOrThisOfType(proj);
if (proj) proj->reloadCompletionTypeResultsInAllViews();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPathFracture::updateAzimuthBasedOnWellAzimuthAngle()
{
if (!fractureTemplate()) return;
if (fractureTemplate()->orientationType == RimFractureTemplate::ALONG_WELL_PATH
|| fractureTemplate()->orientationType == RimFractureTemplate::TRANSVERSE_WELL_PATH)
{
double wellPathAzimuth = wellAzimuthAtFracturePosition();
if (fractureTemplate()->orientationType == RimFractureTemplate::ALONG_WELL_PATH)
{
azimuth = wellPathAzimuth;
}
if (fractureTemplate()->orientationType == RimFractureTemplate::TRANSVERSE_WELL_PATH)
{
if (wellPathAzimuth + 90 < 360) azimuth = wellPathAzimuth + 90;
else azimuth = wellPathAzimuth - 90;
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RimWellPathFracture::wellAzimuthAtFracturePosition() const
{
RimWellPath* wellPath = nullptr;
this->firstAncestorOrThisOfType(wellPath);
if (!wellPath) return cvf::UNDEFINED_DOUBLE;
RigWellPath* wellPathGeometry = wellPath->wellPathGeometry();
double wellPathAzimuth = wellPathGeometry->wellPathAzimuthAngle(fracturePosition());
if (wellPathAzimuth < 0) wellPathAzimuth += 360;
return wellPathAzimuth;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPathFracture::loadDataAndUpdate()
{
updatePositionFromMeasuredDepth();
updateAzimuthBasedOnWellAzimuthAngle();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPathFracture::updatePositionFromMeasuredDepth()
{
cvf::Vec3d positionAlongWellpath = cvf::Vec3d::ZERO;
caf::PdmObjectHandle* objHandle = dynamic_cast<caf::PdmObjectHandle*>(this);
if (!objHandle) return;
RimWellPath* wellPath = nullptr;
objHandle->firstAncestorOrThisOfType(wellPath);
if (!wellPath) return;
RigWellPath* wellPathGeometry = wellPath->wellPathGeometry();
positionAlongWellpath = wellPathGeometry->interpolatedPointAlongWellPath(m_measuredDepth());
this->setAnchorPosition(positionAlongWellpath);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPathFracture::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering)
{
RimFracture::defineUiOrdering(uiConfigName, uiOrdering);
uiOrdering.add(nameField());
uiOrdering.add(&showPolygonFractureOutline);
caf::PdmUiGroup* locationGroup = uiOrdering.addNewGroup("Location / Orientation");
locationGroup->add(&m_measuredDepth);
locationGroup->add(&azimuth);
locationGroup->add(&m_uiWellPathAzimuth);
locationGroup->add(&m_uiWellFractureAzimuthDiff);
locationGroup->add(&m_wellFractureAzimuthAngleWarning);
locationGroup->add(&dip);
locationGroup->add(&tilt);
caf::PdmUiGroup* propertyGroup = uiOrdering.addNewGroup("Properties");
propertyGroup->add(&m_fractureUnit);
propertyGroup->add(&m_fractureTemplate);
propertyGroup->add(&stimPlanTimeIndexToPlot);
propertyGroup->add(&perforationLength);
propertyGroup->add(&perforationEfficiency);
propertyGroup->add(&wellDiameter);
caf::PdmUiGroup* fractureCenterGroup = uiOrdering.addNewGroup("Fracture Center Info");
fractureCenterGroup->add(&m_uiAnchorPosition);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPathFracture::defineEditorAttribute(const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute * attribute)
{
RimFracture::defineEditorAttribute(field, uiConfigName, attribute);
if (field == &m_measuredDepth)
{
caf::PdmUiDoubleSliderEditorAttribute* myAttr = dynamic_cast<caf::PdmUiDoubleSliderEditorAttribute*>(attribute);
if (myAttr)
{
RimWellPath* rimWellPath = nullptr;
this->firstAncestorOrThisOfType(rimWellPath);
CVF_ASSERT(rimWellPath);
RigWellPath* wellPathGeo = rimWellPath->wellPathGeometry();
CVF_ASSERT(wellPathGeo);
{
if (wellPathGeo->m_measuredDepths.size() > 2)
{
myAttr->m_minimum = wellPathGeo->m_measuredDepths.front();
myAttr->m_maximum = wellPathGeo->m_measuredDepths.back();
}
}
}
}
}

View File

@ -0,0 +1,59 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2016- 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 "RimFracture.h"
namespace caf {
class PdmFieldHandle;
class PdmUiEditorAttribute;
}
//==================================================================================================
///
///
//==================================================================================================
class RimWellPathFracture : public RimFracture
{
CAF_PDM_HEADER_INIT;
public:
RimWellPathFracture(void);
virtual ~RimWellPathFracture(void);
double fractureMD() const override { return m_measuredDepth; }
void setMeasuredDepth(double mdValue);
virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override;
virtual void updateAzimuthBasedOnWellAzimuthAngle() override;
double wellAzimuthAtFracturePosition() const override;
virtual void loadDataAndUpdate() override;
protected:
virtual void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) override;
virtual void defineEditorAttribute(const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute * attribute) override;
private:
void updatePositionFromMeasuredDepth();
private:
caf::PdmField<float> m_measuredDepth;
};

View File

@ -0,0 +1,75 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2016- 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 "RimWellPathFractureCollection.h"
#include "RimProject.h"
#include "RimWellPathFracture.h"
#include "cafPdmObject.h"
CAF_PDM_SOURCE_INIT(RimWellPathFractureCollection, "WellPathFractureCollection");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimWellPathFractureCollection::RimWellPathFractureCollection(void)
{
CAF_PDM_InitObject("Fractures", ":/FractureLayout16x16.png", "", "");
CAF_PDM_InitFieldNoDefault(&fractures, "Fractures", "", "", "", "");
fractures.uiCapability()->setUiHidden(true);
setName("Fractures");
nameField()->uiCapability()->setUiHidden(true);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimWellPathFractureCollection::~RimWellPathFractureCollection()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPathFractureCollection::deleteFractures()
{
fractures.deleteAllChildObjects();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPathFractureCollection::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue)
{
RimProject* proj;
this->firstAncestorOrThisOfTypeAsserted(proj);
if (changedField == &m_isChecked)
{
proj->reloadCompletionTypeResultsInAllViews();
}
else
{
proj->createDisplayModelAndRedrawAllViews();
}
}

View File

@ -0,0 +1,48 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2016- 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 "RimCheckableNamedObject.h"
#include "cafPdmField.h"
#include "cafPdmObject.h"
#include "cafPdmChildArrayField.h"
class RimWellPathFracture;
//==================================================================================================
///
///
//==================================================================================================
class RimWellPathFractureCollection : public RimCheckableNamedObject
{
CAF_PDM_HEADER_INIT;
public:
RimWellPathFractureCollection(void);
virtual ~RimWellPathFractureCollection(void);
void deleteFractures();
public:
caf::PdmChildArrayField<RimWellPathFracture*> fractures;
private:
virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override;
};

View File

@ -18,6 +18,7 @@
#pragma once
#include "cvfBase.h"
#include "cvfBoundingBox.h"
class Rim3dPropertiesInterface

View File

@ -37,7 +37,7 @@ public:
protected:
virtual caf::PdmFieldHandle* objectToggleField() override;
private:
protected:
caf::PdmField<bool> m_isChecked;
};

View File

@ -33,6 +33,7 @@
#include "RimEclipseStatisticsCase.h"
#include "RimEclipseView.h"
#include "RimEclipseWell.h"
#include "RimEclipseWellCollection.h"
#include "RimFault.h"
#include "RimFlowDiagSolution.h"
#include "RimFlowPlotCollection.h"
@ -64,17 +65,26 @@
#include "RimWellPath.h"
#include "RimWellPathCollection.h"
#ifdef USE_PROTOTYPE_FEATURE_FRACTURES
#include "RimEllipseFractureTemplate.h"
#include "RimStimPlanFractureTemplate.h"
#include "RimFractureTemplateCollection.h"
#include "RimFractureTemplate.h"
#include "RimSimWellFracture.h"
#include "RimWellPathFracture.h"
#include "RimWellPathFractureCollection.h"
#endif // USE_PROTOTYPE_FEATURE_FRACTURES
#include "ToggleCommands/RicToggleItemsFeatureImpl.h"
#include "cafCmdFeature.h"
#include "cafCmdFeatureManager.h"
#include "cafPdmUiItem.h"
#include "cafSelectionManager.h"
#include "cvfAssert.h"
#include "cafCmdFeatureManager.h"
#include "cafCmdFeature.h"
#include <vector>
#include <QMenu>
//--------------------------------------------------------------------------------------------------
@ -203,6 +213,7 @@ QStringList RimContextCommandBuilder::commandsFromSelection()
commandIds << "RicWellPathsImportFileFeature";
commandIds << "RicWellPathsImportSsihubFeature";
commandIds << "RicWellLogsImportFileFeature";
commandIds << "Separator";
}
else if (dynamic_cast<RimWellPath*>(uiItem))
{
@ -366,6 +377,28 @@ QStringList RimContextCommandBuilder::commandsFromSelection()
{
commandIds << "RicShowFlowCharacteristicsPlotFeature";
}
#ifdef USE_PROTOTYPE_FEATURE_FRACTURES
else if (dynamic_cast<RimSimWellFracture*>(uiItem))
{
commandIds << "RicNewSimWellFractureFeature";
}
else if (dynamic_cast<RimFractureTemplateCollection*>(uiItem) ||
dynamic_cast<RimStimPlanFractureTemplate*>(uiItem))
{
commandIds << "RicNewEllipseFractureTemplateFeature";
commandIds << "RicNewStimPlanFractureTemplateFeature";
commandIds << "Separator";
commandIds << "RicConvertAllFractureTemplatesToMetricFeature";
commandIds << "RicConvertAllFractureTemplatesToFieldFeature";
}
else if (dynamic_cast<RimEllipseFractureTemplate*>(uiItem))
{
commandIds << "RicNewEllipseFractureTemplateFeature";
commandIds << "RicNewStimPlanFractureTemplateFeature";
commandIds << "Separator";
commandIds << "RicConvertFractureTemplateUnitFeature";
}
#endif // USE_PROTOTYPE_FEATURE_FRACTURES
if (dynamic_cast<RimView*>(uiItem))
@ -408,6 +441,11 @@ QStringList RimContextCommandBuilder::commandsFromSelection()
commandIds << "RicFlyToObjectFeature";
commandIds << "RicExportCarfin";
// Fracture commands
#ifdef USE_PROTOTYPE_FEATURE_FRACTURES
commandIds << "RicNewWellPathFractureFeature";
#endif // USE_PROTOTYPE_FEATURE_FRACTURES
// Work in progress -- End
caf::PdmUiItem* uiItem = uiItems[0];
@ -459,6 +497,10 @@ QStringList RimContextCommandBuilder::commandsFromSelection()
commandIds << "RicEclipseWellShowSpheresFeature";
commandIds << "RicEclipseWellShowWellCellsFeature";
commandIds << "RicEclipseWellShowWellCellFenceFeature";
#ifdef USE_PROTOTYPE_FEATURE_FRACTURES
commandIds << "Separator";
commandIds << "RicNewSimWellFractureFeature";
#endif // USE_PROTOTYPE_FEATURE_FRACTURES
}
}

View File

@ -255,9 +255,9 @@ RimEclipseView* RimEclipseCase::createCopyAndAddView(const RimEclipseView* sourc
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEclipseCase::removeEclipseResultAndScheduleRedrawAllViews(RiaDefines::ResultCatType type, const QString& resultName)
void RimEclipseCase::recalculateCompletionTypeAndRedrawAllViews()
{
m_matrixModelResults->clearScalarResult(type, resultName);
m_matrixModelResults->clearScalarResult(RiaDefines::DYNAMIC_NATIVE, RiaDefines::completionTypeResultName());
for (RimView* view : views())
{

View File

@ -79,7 +79,7 @@ public:
RimEclipseView* createAndAddReservoirView();
RimEclipseView* createCopyAndAddView(const RimEclipseView* sourceView);
void removeEclipseResultAndScheduleRedrawAllViews(RiaDefines::ResultCatType type, const QString& resultName);
void recalculateCompletionTypeAndRedrawAllViews();
virtual QString locationOnDisc() const { return QString(); }
virtual QString gridFileName() const { return QString(); }

View File

@ -388,10 +388,12 @@ void RimEclipseCellColors::updateLegendData(size_t currentTimeStep)
caf::AppEnum<RiaDefines::CompletionType> wellPath(RiaDefines::WELL_PATH);
caf::AppEnum<RiaDefines::CompletionType> fishbone(RiaDefines::FISHBONES);
caf::AppEnum<RiaDefines::CompletionType> perforationInterval(RiaDefines::PERFORATION_INTERVAL);
caf::AppEnum<RiaDefines::CompletionType> fracture(RiaDefines::FRACTURE);
categories.push_back(std::make_tuple(wellPath.uiText(), static_cast<int>(wellPath.index()), cvf::Color3::RED));
categories.push_back(std::make_tuple(fishbone.uiText(), static_cast<int>(fishbone.index()), cvf::Color3::DARK_GREEN));
categories.push_back(std::make_tuple(perforationInterval.uiText(), static_cast<int>(perforationInterval.index()), cvf::Color3::GREEN));
categories.push_back(std::make_tuple(fracture.uiText(), static_cast<int>(fracture.index()), cvf::Color3::YELLOW_GREEN));
legendConfig()->setCategoryItems(categories);
}

View File

@ -52,6 +52,7 @@
#include "RimOilField.h"
#include "RimProject.h"
#include "RimReservoirCellResultsStorage.h"
#include "RimStimPlanColors.h"
#include "RimTernaryLegendConfig.h"
#include "RimViewController.h"
#include "RimViewLinker.h"
@ -66,6 +67,13 @@
#include "RivSingleCellPartGenerator.h"
#include "RivTernarySaturationOverlayItem.h"
#ifdef USE_PROTOTYPE_FEATURE_FRACTURES
#include "RimFracture.h"
#include "RimSimWellFracture.h"
#include "RivWellFracturePartMgr.h"
#endif // USE_PROTOTYPE_FEATURE_FRACTURES
#include "cafCadNavigation.h"
#include "cafCeetronPlusNavigation.h"
#include "cafDisplayCoordTransform.h"
@ -86,7 +94,6 @@
CAF_PDM_SOURCE_INIT(RimEclipseView, "ReservoirView");
//--------------------------------------------------------------------------------------------------
///
@ -111,6 +118,12 @@ RimEclipseView::RimEclipseView()
faultResultSettings = new RimEclipseFaultColors();
faultResultSettings.uiCapability()->setUiHidden(true);
#ifdef USE_PROTOTYPE_FEATURE_FRACTURES
CAF_PDM_InitFieldNoDefault(&stimPlanColors, "StimPlanColors", "Fracture Colors", "", "", "");
stimPlanColors = new RimStimPlanColors();
stimPlanColors.uiCapability()->setUiHidden(true);
#endif // USE_PROTOTYPE_FEATURE_FRACTURES
CAF_PDM_InitFieldNoDefault(&wellCollection, "WellCollection", "Simulation Wells", "", "", "");
wellCollection = new RimEclipseWellCollection;
wellCollection.uiCapability()->setUiHidden(true);
@ -220,6 +233,9 @@ void RimEclipseView::fieldChangedByUi(const caf::PdmFieldHandle* changedField, c
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEclipseView::updateScaleTransform()
{
cvf::Mat4d scale = cvf::Mat4d::IDENTITY;
@ -228,11 +244,19 @@ void RimEclipseView::updateScaleTransform()
this->scaleTransform()->setLocalTransform(scale);
m_simWellsPartManager->setScaleTransform(this->scaleTransform());
#ifdef USE_PROTOTYPE_FEATURE_FRACTURES
// Regenerate fracture geometry
std::vector<RimFracture*> fractures;
this->descendantsIncludingThisOfType(fractures);
for (RimFracture* fracture : fractures)
{
fracture->clearDisplayGeometryCache();
}
#endif // USE_PROTOTYPE_FEATURE_FRACTURES
if (m_viewer) m_viewer->updateCachedValuesInScene();
}
//--------------------------------------------------------------------------------------------------
/// Create display model,
/// or at least empty scenes as frames that is delivered to the viewer
@ -425,8 +449,19 @@ void RimEclipseView::createDisplayModel()
m_wellPathPipeVizModel->removeAllParts();
// NB! StimPlan legend colors must be updated before well path geometry is added to the model
// as the fracture geometry depends on the StimPlan legend colors
#ifdef USE_PROTOTYPE_FEATURE_FRACTURES
stimPlanColors->updateLegendData();
#endif // USE_PROTOTYPE_FEATURE_FRACTURES
addWellPathsToModel(m_wellPathPipeVizModel.p(), currentActiveCellInfo()->geometryBoundingBox());
#ifdef USE_PROTOTYPE_FEATURE_FRACTURES
wellPathsPartManager()->appendStaticFracturePartsToModel(m_wellPathPipeVizModel.p(), this);
#endif // USE_PROTOTYPE_FEATURE_FRACTURES
m_wellPathPipeVizModel->updateBoundingBoxesRecursive();
m_viewer->addStaticModelOnce(m_wellPathPipeVizModel.p());
// Create Scenes from the frameModels
@ -642,6 +677,40 @@ void RimEclipseView::updateCurrentTimeStep()
frameScene->addModel(wellPathModelBasicList.p());
}
// Sim Well Fractures
#ifdef USE_PROTOTYPE_FEATURE_FRACTURES
{
cvf::String name = "SimWellFracturesModel";
this->removeModelByName(frameScene, name);
cvf::ref<cvf::ModelBasicList> simWellFracturesModelBasicList = new cvf::ModelBasicList;
simWellFracturesModelBasicList->setName(name);
cvf::ref<caf::DisplayCoordTransform> transForm = this->displayCoordTransform();
std::vector<RimFracture*> fractures;
this->descendantsIncludingThisOfType(fractures);
for (RimFracture* f : fractures)
{
RimEclipseWell* eclWell = nullptr;
f->firstAncestorOrThisOfType(eclWell);
if (eclWell)
{
bool isAnyGeometryPresent = eclWell->isWellPipeVisible(m_currentTimeStep) || eclWell->isWellSpheresVisible(m_currentTimeStep);
if (!isAnyGeometryPresent)
{
continue;
}
}
f->fracturePartManager()->appendGeometryPartsToModel(simWellFracturesModelBasicList.p(), this);
}
simWellFracturesModelBasicList->updateBoundingBoxesRecursive();
frameScene->addModel(simWellFracturesModelBasicList.p());
}
#endif // USE_PROTOTYPE_FEATURE_FRACTURES
}
}
@ -678,6 +747,9 @@ void RimEclipseView::loadDataAndUpdate()
this->cellEdgeResult()->loadResult();
this->faultResultSettings()->customFaultResult()->loadResult();
#ifdef USE_PROTOTYPE_FEATURE_FRACTURES
this->stimPlanColors->loadDataAndUpdate();
#endif // USE_PROTOTYPE_FEATURE_FRACTURES
updateMdiWindowVisibility();
@ -691,8 +763,20 @@ void RimEclipseView::loadDataAndUpdate()
syncronizeWellsWithResults();
this->scheduleCreateDisplayModelAndRedraw();
#ifdef USE_PROTOTYPE_FEATURE_FRACTURES
{
// Update simulation well fractures after well cell results are imported
std::vector<RimSimWellFracture*> simFractures;
this->descendantsIncludingThisOfType(simFractures);
for (auto fracture : simFractures)
{
fracture->loadDataAndUpdate();
}
}
#endif // USE_PROTOTYPE_FEATURE_FRACTURES
this->scheduleCreateDisplayModelAndRedraw();
}
@ -971,6 +1055,19 @@ void RimEclipseView::updateLegends()
this->cellEdgeResult()->legendConfig()->setClosestToZeroValues(0, 0, 0, 0);
this->cellEdgeResult()->legendConfig()->setAutomaticRanges(cvf::UNDEFINED_DOUBLE, cvf::UNDEFINED_DOUBLE, cvf::UNDEFINED_DOUBLE, cvf::UNDEFINED_DOUBLE);
}
#ifdef USE_PROTOTYPE_FEATURE_FRACTURES
RimLegendConfig* stimPlanLegend = stimPlanColors()->activeLegend();
if (stimPlanLegend)
{
stimPlanColors->updateLegendData();
if (stimPlanColors()->isChecked() && stimPlanLegend->legend())
{
m_viewer->addColorLegendToBottomLeftCorner(stimPlanLegend->legend());
}
}
#endif // USE_PROTOTYPE_FEATURE_FRACTURES
}
//--------------------------------------------------------------------------------------------------
@ -1313,6 +1410,9 @@ void RimEclipseView::defineUiTreeOrdering(caf::PdmUiTreeOrdering& uiTreeOrdering
uiTreeOrdering.add(cellResult());
uiTreeOrdering.add(cellEdgeResult());
uiTreeOrdering.add(faultResultSettings());
#ifdef USE_PROTOTYPE_FEATURE_FRACTURES
uiTreeOrdering.add(stimPlanColors());
#endif // USE_PROTOTYPE_FEATURE_FRACTURES
uiTreeOrdering.add(wellCollection());
uiTreeOrdering.add(faultCollection());
@ -1437,7 +1537,7 @@ cvf::Transform* RimEclipseView::scaleTransform()
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimCase* RimEclipseView::ownerCase()
RimCase* RimEclipseView::ownerCase() const
{
return eclipseCase();
}

View File

@ -41,18 +41,22 @@ class RigGridBase;
class RigGridCellFaceVisibilityFilter;
class RigMainGrid;
class Rim3dOverlayInfoConfig;
class RimEclipseCase;
class RimCellEdgeColors;
class RimEclipsePropertyFilter;
class RimEclipsePropertyFilterCollection;
class RimCellRangeFilter;
class RimCellRangeFilterCollection;
class RimFaultCollection;
class RimEclipseFaultColors;
class RimReservoirCellResultsStorage;
class RimReservoirCellResultsStorage;
class RimEclipseCase;
class RimEclipseCellColors;
class RimEclipseFaultColors;
class RimEclipsePropertyFilter;
class RimEclipsePropertyFilterCollection;
class RimEclipseWell;
class RimEclipseWellCollection;
class RimFaultCollection;
class RimReservoirCellResultsStorage;
class RimReservoirCellResultsStorage;
#ifdef USE_PROTOTYPE_FEATURE_FRACTURES
class RimStimPlanColors;
#endif // USE_PROTOTYPE_FEATURE_FRACTURES
class RiuViewer;
class RivReservoirSimWellsPartMgr;
class RivIntersectionPartMgr;
@ -90,6 +94,9 @@ public:
caf::PdmChildField<RimEclipseCellColors*> cellResult;
caf::PdmChildField<RimCellEdgeColors*> cellEdgeResult;
caf::PdmChildField<RimEclipseFaultColors*> faultResultSettings;
#ifdef USE_PROTOTYPE_FEATURE_FRACTURES
caf::PdmChildField<RimStimPlanColors*> stimPlanColors;
#endif // USE_PROTOTYPE_FEATURE_FRACTURES
caf::PdmChildField<RimEclipseWellCollection*> wellCollection;
caf::PdmChildField<RimFaultCollection*> faultCollection;
@ -113,7 +120,7 @@ public:
void setEclipseCase(RimEclipseCase* reservoir);
RimEclipseCase* eclipseCase() const;
virtual RimCase* ownerCase();
virtual RimCase* ownerCase() const override;
RigMainGrid* mainGrid() const;

View File

@ -28,10 +28,17 @@
#include "RimEclipseWellCollection.h"
#include "RimIntersectionCollection.h"
#ifdef USE_PROTOTYPE_FEATURE_FRACTURES
#include "RimSimWellFractureCollection.h"
#include "RimSimWellFracture.h"
#endif // USE_PROTOTYPE_FEATURE_FRACTURES
#include "RiuMainWindow.h"
#include "RivReservoirViewPartMgr.h"
#include "cafPdmUiTreeOrdering.h"
#include "cvfMath.h"
#include "RigCell.h"
#include "RimEclipseCase.h"
@ -64,7 +71,18 @@ RimEclipseWell::RimEclipseWell()
CAF_PDM_InitField(&showWellCells, "ShowWellCells", false, "Well Cells", "", "", "");
CAF_PDM_InitField(&showWellCellFence, "ShowWellCellFence", false, "Well Cell Fence", "", "", "");
#ifdef USE_PROTOTYPE_FEATURE_FRACTURES
CAF_PDM_InitFieldNoDefault(&simwellFractureCollection, "FractureCollection", "Fractures", "", "", "");
#endif // USE_PROTOTYPE_FEATURE_FRACTURES
name.uiCapability()->setUiHidden(true);
name.uiCapability()->setUiReadOnly(true);
m_resultWellIndex = cvf::UNDEFINED_SIZE_T;
#ifdef USE_PROTOTYPE_FEATURE_FRACTURES
simwellFractureCollection= new RimSimWellFractureCollection();
#endif // USE_PROTOTYPE_FEATURE_FRACTURES
}
//--------------------------------------------------------------------------------------------------
@ -72,6 +90,9 @@ RimEclipseWell::RimEclipseWell()
//--------------------------------------------------------------------------------------------------
RimEclipseWell::~RimEclipseWell()
{
#ifdef USE_PROTOTYPE_FEATURE_FRACTURES
if (simwellFractureCollection()) delete simwellFractureCollection();
#endif // USE_PROTOTYPE_FEATURE_FRACTURES
}
//--------------------------------------------------------------------------------------------------
@ -155,7 +176,7 @@ void RimEclipseWell::calculateWellPipeStaticCenterLine(std::vector< std::vector
//--------------------------------------------------------------------------------------------------
void RimEclipseWell::calculateWellPipeDynamicCenterLine(size_t timeStepIdx,
std::vector< std::vector <cvf::Vec3d> >& pipeBranchesCLCoords,
std::vector< std::vector <RigWellResultPoint> >& pipeBranchesCellIds)
std::vector< std::vector <RigWellResultPoint> >& pipeBranchesCellIds) const
{
RigSimulationWellCenterLineCalculator::calculateWellPipeDynamicCenterline(this, timeStepIdx, pipeBranchesCLCoords, pipeBranchesCellIds);
}
@ -362,6 +383,14 @@ void RimEclipseWell::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering&
//--------------------------------------------------------------------------------------------------
void RimEclipseWell::defineUiTreeOrdering(caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName /*= ""*/)
{
#ifdef USE_PROTOTYPE_FEATURE_FRACTURES
for (RimSimWellFracture* fracture : simwellFractureCollection()->simwellFractures())
{
uiTreeOrdering.add(fracture);
}
uiTreeOrdering.skipRemainingChildren(true);
#endif // USE_PROTOTYPE_FEATURE_FRACTURES
const RimEclipseView* reservoirView = nullptr;
this->firstAncestorOrThisOfType(reservoirView);
if (!reservoirView) return;

View File

@ -24,6 +24,7 @@
#include "cafPdmObject.h"
#include "cafPdmPointer.h"
#include "cafAppEnum.h"
#include "cafPdmChildField.h"
// Include to make Pdm work for cvf::Color
#include "cafPdmFieldCvfColor.h"
@ -36,6 +37,10 @@ class RigWellResultFrame;
struct RigWellResultPoint;
#ifdef USE_PROTOTYPE_FEATURE_FRACTURES
class RimSimWellFractureCollection;
#endif // USE_PROTOTYPE_FEATURE_FRACTURES
//==================================================================================================
///
///
@ -67,7 +72,7 @@ public:
void calculateWellPipeDynamicCenterLine(size_t timeStepIdx,
std::vector< std::vector <cvf::Vec3d> >& pipeBranchesCLCoords,
std::vector< std::vector <RigWellResultPoint> >& pipeBranchesCellIds);
std::vector< std::vector <RigWellResultPoint> >& pipeBranchesCellIds) const;
void wellHeadTopBottomPosition(size_t frameIndex, cvf::Vec3d* top, cvf::Vec3d* bottom);
double pipeRadius();
@ -88,6 +93,11 @@ public:
caf::PdmField<bool> showWellCells;
caf::PdmField<bool> showWellCellFence;
#ifdef USE_PROTOTYPE_FEATURE_FRACTURES
caf::PdmChildField<RimSimWellFractureCollection*> simwellFractureCollection;
#endif // USE_PROTOTYPE_FEATURE_FRACTURES
protected:
virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override;
virtual void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) override;

View File

@ -32,6 +32,10 @@
#include "RimEclipseWell.h"
#include "RimProject.h"
#include "RimWellAllocationPlot.h"
#ifdef USE_PROTOTYPE_FEATURE_FRACTURES
#include "RimSimWellFracture.h"
#include "RimSimWellFractureCollection.h"
#endif // USE_PROTOTYPE_FEATURE_FRACTURES
#include "RiuMainWindow.h"
@ -456,6 +460,19 @@ void RimEclipseWellCollection::fieldChangedByUi(const caf::PdmFieldHandle* chang
{
if (m_reservoirView) m_reservoirView->scheduleCreateDisplayModelAndRedraw();
}
#ifdef USE_PROTOTYPE_FEATURE_FRACTURES
if (&wellPipeCoordType == changedField)
{
for (RimEclipseWell* w : wells)
{
for (RimSimWellFracture* frac : w->simwellFractureCollection()->simwellFractures())
{
frac->recomputeWellCenterlineCoordinates();
}
}
}
#endif // USE_PROTOTYPE_FEATURE_FRACTURES
}
//--------------------------------------------------------------------------------------------------

View File

@ -507,7 +507,7 @@ void RimGeoMechView::initAfterRead()
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimCase* RimGeoMechView::ownerCase()
RimCase* RimGeoMechView::ownerCase() const
{
return m_geomechCase;
}

View File

@ -61,7 +61,7 @@ public:
void setGeoMechCase(RimGeoMechCase* gmCase);
RimGeoMechCase* geoMechCase();
virtual RimCase* ownerCase();
virtual RimCase* ownerCase() const override;
virtual void loadDataAndUpdate();

View File

@ -27,6 +27,7 @@
#include "RimEclipseCellColors.h"
#include "RimEclipseView.h"
#include "RimGeoMechResultDefinition.h"
#include "RimStimPlanColors.h"
#include "RimViewLinker.h"
#include "cafCategoryLegend.h"
@ -75,6 +76,7 @@ namespace caf {
addItem(RimLegendConfig::BLACK_WHITE, "BLACK_WHITE", "Black to white");
addItem(RimLegendConfig::CATEGORY, "CATEGORY", "Category colors");
addItem(RimLegendConfig::ANGULAR, "ANGULAR", "Full color cyclic");
addItem(RimLegendConfig::STIMPLAN, "STIMPLAN", "StimPlan colors");
setDefault(RimLegendConfig::NORMAL);
}
}
@ -125,8 +127,8 @@ RimLegendConfig::RimLegendConfig()
CAF_PDM_InitField(&m_colorRangeMode, "ColorRangeMode", ColorRangeEnum(NORMAL) , "Colors", "", "", "");
CAF_PDM_InitField(&m_mappingMode, "MappingMode", MappingEnum(LINEAR_CONTINUOUS) , "Mapping", "", "", "");
CAF_PDM_InitField(&m_rangeMode, "RangeType", RangeModeEnum(AUTOMATIC_ALLTIMESTEPS), "Range type", "", "Switches between automatic and user defined range on the legend", "");
CAF_PDM_InitField(&m_userDefinedMaxValue, "UserDefinedMax", 1.0, "Max", "", "Min value of the legend", "");
CAF_PDM_InitField(&m_userDefinedMinValue, "UserDefinedMin", 0.0, "Min", "", "Max value of the legend", "");
CAF_PDM_InitField(&m_userDefinedMaxValue, "UserDefinedMax", 1.0, "Max", "", "Max value of the legend", "");
CAF_PDM_InitField(&m_userDefinedMinValue, "UserDefinedMin", 0.0, "Min", "", "Min value of the legend (if mapping is logarithmic only positive values are valid)", "");
CAF_PDM_InitField(&resultVariableName, "ResultVariableUsage", QString(""), "", "", "", "");
resultVariableName.uiCapability()->setUiHidden(true);
@ -714,6 +716,9 @@ cvf::Color3ubArray RimLegendConfig::colorArrayFromColorType(ColorRangesType colo
case RimLegendConfig::ANGULAR:
return RiaColorTables::angularPaletteColors().color3ubArray();
break;
case RimLegendConfig::STIMPLAN:
return RiaColorTables::stimPlanPaletteColors().color3ubArray();
break;
default:
break;
}
@ -748,6 +753,10 @@ void RimLegendConfig::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering&
//--------------------------------------------------------------------------------------------------
QList<caf::PdmOptionItemInfo> RimLegendConfig::calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly)
{
bool hasStimPlanParent = false;
RimStimPlanColors* stimPlanColors = nullptr;
this->firstAncestorOrThisOfType(stimPlanColors);
if (stimPlanColors) hasStimPlanParent = true;
bool isCategoryResult = false;
{
@ -800,6 +809,7 @@ QList<caf::PdmOptionItemInfo> RimLegendConfig::calculateValueOptions(const caf::
rangeTypes.push_back(WHITE_BLACK);
rangeTypes.push_back(BLACK_WHITE);
rangeTypes.push_back(ANGULAR);
if (hasStimPlanParent) rangeTypes.push_back(STIMPLAN);
if (isCategoryResult)
{
@ -813,10 +823,14 @@ QList<caf::PdmOptionItemInfo> RimLegendConfig::calculateValueOptions(const caf::
}
else if (fieldNeedingOptions == &m_rangeMode)
{
if (!m_isAllTimeStepsRangeDisabled) {
if (!m_isAllTimeStepsRangeDisabled)
{
options.push_back(caf::PdmOptionItemInfo(RangeModeEnum::uiText(RimLegendConfig::AUTOMATIC_ALLTIMESTEPS), RimLegendConfig::AUTOMATIC_ALLTIMESTEPS));
}
if (!hasStimPlanParent)
{
options.push_back(caf::PdmOptionItemInfo(RangeModeEnum::uiText(RimLegendConfig::AUTOMATIC_CURRENT_TIMESTEP), RimLegendConfig::AUTOMATIC_CURRENT_TIMESTEP));
}
options.push_back(caf::PdmOptionItemInfo(RangeModeEnum::uiText(RimLegendConfig::USER_DEFINED), RimLegendConfig::USER_DEFINED));
}

Some files were not shown because too many files have changed in this diff Show More