diff --git a/ApplicationLibCode/Commands/GeoMechCommands/RicRunFaultReactModelingFeature.cpp b/ApplicationLibCode/Commands/GeoMechCommands/RicRunFaultReactModelingFeature.cpp index 3c1e718925..596d8d1a6c 100644 --- a/ApplicationLibCode/Commands/GeoMechCommands/RicRunFaultReactModelingFeature.cpp +++ b/ApplicationLibCode/Commands/GeoMechCommands/RicRunFaultReactModelingFeature.cpp @@ -24,6 +24,8 @@ #include "RifFaultReactivationModelExporter.h" #include "RimFaultReactivationModel.h" +#include "RimGeoMechCase.h" +#include "RimGeoMechView.h" #include "RimProcess.h" #include "RimProject.h" @@ -66,9 +68,9 @@ void RicRunFaultReactModelingFeature::onActionTriggered( bool isChecked ) return; } - if ( !model->extractModelData() ) + if ( !model->extractAndExportModelData() ) { - QMessageBox::critical( nullptr, frmTitle, "Unable to get necessary data from the input model." ); + QMessageBox::critical( nullptr, frmTitle, "Unable to get necessary data from the input case." ); return; } @@ -115,6 +117,24 @@ void RicRunFaultReactModelingFeature::onActionTriggered( bool isChecked ) runProgress.incrementProgress(); runProgress.setProgressDescription( "Loading modeling results." ); + for ( auto gCase : RimProject::current()->geoMechCases() ) + { + if ( model->outputOdbFilename() == gCase->gridFileName() ) + { + gCase->reloadDataAndUpdate(); + auto& views = gCase->geoMechViews(); + if ( views.size() > 0 ) + { + Riu3DMainWindowTools::selectAsCurrentItem( views[0] ); + } + else + { + Riu3DMainWindowTools::selectAsCurrentItem( gCase ); + } + return; + } + } + RiaApplication* app = RiaApplication::instance(); if ( !app->openOdbCaseFromFile( model->outputOdbFilename() ) ) { diff --git a/ApplicationLibCode/Commands/SsiHubImportCommands/RiuWellImportWizard.cpp b/ApplicationLibCode/Commands/SsiHubImportCommands/RiuWellImportWizard.cpp index efdaadc126..aa994d946b 100644 --- a/ApplicationLibCode/Commands/SsiHubImportCommands/RiuWellImportWizard.cpp +++ b/ApplicationLibCode/Commands/SsiHubImportCommands/RiuWellImportWizard.cpp @@ -417,9 +417,8 @@ void RiuWellImportWizard::updateFieldsModel() QStringList fields; QStringList edmIds; - ResInsightInternalJson::JsonReader jsonReader; - QMap jsonMap = jsonReader.decodeFile( fileName ); - QVariantList variantList = ResInsightInternalJson::JsonReader::getVariantList( jsonMap ); + QMap jsonMap = ResInsightInternalJson::JsonReader::decodeFile( fileName ); + QVariantList variantList = ResInsightInternalJson::JsonReader::getVariantList( jsonMap ); for ( const auto& listItem : variantList ) { QMap fieldMap = listItem.toMap(); @@ -632,9 +631,8 @@ void RiuWellImportWizard::parseWellsResponse( RimOilFieldEntry* oilFieldEntry ) if ( caf::Utils::fileExists( oilFieldEntry->wellsFilePath ) ) { - ResInsightInternalJson::JsonReader jsonReader; - QMap jsonMap = jsonReader.decodeFile( oilFieldEntry->wellsFilePath ); - QVariantList variantList = ResInsightInternalJson::JsonReader::getVariantList( jsonMap ); + QMap jsonMap = ResInsightInternalJson::JsonReader::decodeFile( oilFieldEntry->wellsFilePath ); + QVariantList variantList = ResInsightInternalJson::JsonReader::getVariantList( jsonMap ); for ( const auto& listItem : variantList ) { QMap rootMap = listItem.toMap(); diff --git a/ApplicationLibCode/FileInterface/RifJsonEncodeDecode.cpp b/ApplicationLibCode/FileInterface/RifJsonEncodeDecode.cpp index 5dede33d8c..2858cbaafe 100644 --- a/ApplicationLibCode/FileInterface/RifJsonEncodeDecode.cpp +++ b/ApplicationLibCode/FileInterface/RifJsonEncodeDecode.cpp @@ -23,6 +23,7 @@ #include #include #include +#include namespace ResInsightInternalJson { @@ -30,10 +31,14 @@ QMap JsonReader::decodeFile( QString filePath ) { QFile file; file.setFileName( filePath ); - file.open( QIODevice::ReadOnly ); - QByteArray byteArray = file.readAll(); - file.close(); - return Json::decode( byteArray ); + if ( file.open( QIODevice::ReadOnly ) ) + { + QByteArray byteArray = file.readAll(); + file.close(); + return Json::decode( byteArray ); + } + + return QMap(); } //-------------------------------------------------------------------------------------------------- @@ -53,6 +58,25 @@ QString JsonReader::rootKeyText() return "root"; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool JsonWriter::encodeFile( QString filePath, QMap map ) +{ + QFile file; + file.setFileName( filePath ); + if ( file.open( QIODevice::ReadWrite | QIODevice::Text ) ) + { + QString content = Json::encode( map, true ); + QTextStream out( &file ); + out << content; + file.close(); + return true; + } + + return false; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/FileInterface/RifJsonEncodeDecode.h b/ApplicationLibCode/FileInterface/RifJsonEncodeDecode.h index 679f0ac710..1a01ca8765 100644 --- a/ApplicationLibCode/FileInterface/RifJsonEncodeDecode.h +++ b/ApplicationLibCode/FileInterface/RifJsonEncodeDecode.h @@ -28,12 +28,24 @@ namespace ResInsightInternalJson class JsonReader { public: - QMap decodeFile( QString filePath ); + static QMap decodeFile( QString filePath ); // Get a variant list from a map static QVariantList getVariantList( const QMap& map ); static QString rootKeyText(); + +private: + JsonReader(){}; +}; + +class JsonWriter +{ +public: + static bool encodeFile( QString filePath, QMap map ); + +private: + JsonWriter(){}; }; class Json diff --git a/ApplicationLibCode/FileInterface/RifWellPathImporter.cpp b/ApplicationLibCode/FileInterface/RifWellPathImporter.cpp index b3fbae0329..a165f3a1df 100644 --- a/ApplicationLibCode/FileInterface/RifWellPathImporter.cpp +++ b/ApplicationLibCode/FileInterface/RifWellPathImporter.cpp @@ -124,9 +124,8 @@ bool RifWellPathImporter::isJsonFile( const QString& filePath ) //-------------------------------------------------------------------------------------------------- RifWellPathImporter::WellMetaData RifWellPathImporter::readJsonWellMetaData( const QString& filePath ) { - ResInsightInternalJson::JsonReader jsonReader; - QMap jsonMap = jsonReader.decodeFile( filePath ); - WellMetaData metadata; + QMap jsonMap = ResInsightInternalJson::JsonReader::decodeFile( filePath ); + WellMetaData metadata; metadata.m_id = jsonMap["id"].toString(); metadata.m_name = jsonMap["name"].toString(); @@ -151,8 +150,7 @@ RifWellPathImporter::WellMetaData RifWellPathImporter::readJsonWellMetaData( con //-------------------------------------------------------------------------------------------------- RifWellPathImporter::WellData RifWellPathImporter::readJsonWellData( const QString& filePath ) { - ResInsightInternalJson::JsonReader jsonReader; - QMap jsonMap = jsonReader.decodeFile( filePath ); + QMap jsonMap = ResInsightInternalJson::JsonReader::decodeFile( filePath ); double datumElevation = jsonMap["datumElevation"].toDouble(); QList pathList = jsonMap["path"].toList(); diff --git a/ApplicationLibCode/ProjectDataModel/Faults/CMakeLists_files.cmake b/ApplicationLibCode/ProjectDataModel/Faults/CMakeLists_files.cmake index f45b12175d..529aed94e8 100644 --- a/ApplicationLibCode/ProjectDataModel/Faults/CMakeLists_files.cmake +++ b/ApplicationLibCode/ProjectDataModel/Faults/CMakeLists_files.cmake @@ -3,6 +3,7 @@ set(SOURCE_GROUP_HEADER_FILES ${CMAKE_CURRENT_LIST_DIR}/RimFaultInViewCollection.h ${CMAKE_CURRENT_LIST_DIR}/RimFaultReactivationModel.h ${CMAKE_CURRENT_LIST_DIR}/RimFaultReactivationModelCollection.h + ${CMAKE_CURRENT_LIST_DIR}/RimFaultReactivationTools.h ) set(SOURCE_GROUP_SOURCE_FILES @@ -10,6 +11,7 @@ set(SOURCE_GROUP_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/RimFaultInViewCollection.cpp ${CMAKE_CURRENT_LIST_DIR}/RimFaultReactivationModel.cpp ${CMAKE_CURRENT_LIST_DIR}/RimFaultReactivationModelCollection.cpp + ${CMAKE_CURRENT_LIST_DIR}/RimFaultReactivationTools.cpp ) list(APPEND CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES}) diff --git a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationModel.cpp b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationModel.cpp index 75e37df7f4..90fd538760 100644 --- a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationModel.cpp +++ b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationModel.cpp @@ -23,6 +23,8 @@ #include "RiaPreferencesGeoMech.h" #include "RiaQDateTimeTools.h" +#include "RifJsonEncodeDecode.h" + #include "RigBasicPlane.h" #include "RigFaultReactivationModel.h" #include "RigPolyLinesData.h" @@ -39,6 +41,7 @@ #include "RimEclipseView.h" #include "RimFaultInView.h" #include "RimFaultInViewCollection.h" +#include "RimFaultReactivationTools.h" #include "RimPolylineTarget.h" #include "RimTimeStepFilter.h" #include "RimTools.h" @@ -52,6 +55,8 @@ #include #include +#include +#include CAF_PDM_SOURCE_INIT( RimFaultReactivationModel, "FaultReactivationModel" ); @@ -364,6 +369,17 @@ bool RimFaultReactivationModel::showModel() const return m_showModelPlane; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::pair RimFaultReactivationModel::localCoordSysNormalsXY() const +{ + cvf::Vec3d yNormal = m_modelPlane->normal(); + cvf::Vec3d xNormal = yNormal ^ cvf::Vec3d::Z_AXIS; + + return std::make_pair( xNormal, yNormal ); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -503,9 +519,7 @@ void RimFaultReactivationModel::updateTimeSteps() { m_availableTimeSteps.clear(); const auto eCase = eclipseCase(); - if ( eCase == nullptr ) return; - - m_availableTimeSteps = eCase->timeStepDates(); + if ( eCase != nullptr ) m_availableTimeSteps = eCase->timeStepDates(); } //-------------------------------------------------------------------------------------------------- @@ -548,6 +562,15 @@ QString RimFaultReactivationModel::inputFilename() const return directory.absoluteFilePath( baseFilename() + ".inp" ); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RimFaultReactivationModel::settingsFilename() const +{ + QDir directory( baseDir() ); + return directory.absoluteFilePath( baseFilename() + ".settings.json" ); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -568,8 +591,32 @@ QString RimFaultReactivationModel::baseFilename() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool RimFaultReactivationModel::extractModelData() +bool RimFaultReactivationModel::exportModelSettings() +{ + if ( m_faultPlane.isNull() ) return false; + + QMap settings; + + auto [topPosition, bottomPosition] = m_faultPlane->intersectTopBottomLine(); + auto faultNormal = m_faultPlane->normal(); + + // make sure we move horizontally + faultNormal.z() = 0.0; + faultNormal.normalize(); + + RimFaultReactivationTools::addSettingsToMap( settings, faultNormal, topPosition, bottomPosition ); + + QDir directory( baseDir() ); + return ResInsightInternalJson::JsonWriter::encodeFile( settingsFilename(), settings ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimFaultReactivationModel::extractAndExportModelData() { + exportModelSettings(); + // TODO - get values from eclipse and geomech models here return true; } diff --git a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationModel.h b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationModel.h index 68e543956c..ed3195b909 100644 --- a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationModel.h +++ b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationModel.h @@ -92,7 +92,9 @@ class RimFaultReactivationModel : public RimCheckableNamedObject, public RimPoly cvf::ref model() const; bool showModel() const; - bool extractModelData(); + std::pair localCoordSysNormalsXY() const; + + bool extractAndExportModelData(); QString baseDir() const; void setBaseDir( QString path ); @@ -100,8 +102,10 @@ class RimFaultReactivationModel : public RimCheckableNamedObject, public RimPoly std::vector selectedTimeSteps() const; QStringList commandParameters() const; - QString outputOdbFilename() const; - QString inputFilename() const; + + QString outputOdbFilename() const; + QString inputFilename() const; + QString settingsFilename() const; void updateTimeSteps(); @@ -119,6 +123,8 @@ class RimFaultReactivationModel : public RimCheckableNamedObject, public RimPoly QString baseFilename() const; + bool exportModelSettings(); + private: std::shared_ptr m_pickTargetsEventHandler; diff --git a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationTools.cpp b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationTools.cpp new file mode 100644 index 0000000000..d94d808964 --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationTools.cpp @@ -0,0 +1,76 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2023 Equinor 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RimFaultReactivationTools.h" + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::Vec3d RimFaultReactivationTools::normalVector( QMap settings ) +{ + double x = settings.value( "faultNormal_X", 0.0 ).toDouble(); + double y = settings.value( "faultNormal_Y", 0.0 ).toDouble(); + double z = settings.value( "faultNormal_Z", 0.0 ).toDouble(); + + return cvf::Vec3d( x, y, z ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::Vec3d RimFaultReactivationTools::topFaultPosition( QMap settings ) +{ + double x = settings.value( "faultTop_X", 0.0 ).toDouble(); + double y = settings.value( "faultTop_Y", 0.0 ).toDouble(); + double z = settings.value( "faultTop_Z", 0.0 ).toDouble(); + + return cvf::Vec3d( x, y, z ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::Vec3d RimFaultReactivationTools::bottomFaultPosition( QMap settings ) +{ + double x = settings.value( "faultBottom_X", 0.0 ).toDouble(); + double y = settings.value( "faultBottom_Y", 0.0 ).toDouble(); + double z = settings.value( "faultBottom_Z", 0.0 ).toDouble(); + + return cvf::Vec3d( x, y, z ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFaultReactivationTools::addSettingsToMap( QMap& map, + cvf::Vec3d normalVector, + cvf::Vec3d topFaultPosition, + cvf::Vec3d bottomFaultPosition ) +{ + map["faultTop_X"] = topFaultPosition.x(); + map["faultTop_Y"] = topFaultPosition.y(); + map["faultTop_Z"] = topFaultPosition.z(); + + map["faultBottom_X"] = bottomFaultPosition.x(); + map["faultBottom_Y"] = bottomFaultPosition.y(); + map["faultBottom_Z"] = bottomFaultPosition.z(); + + map["faultNormal_X"] = normalVector.x(); + map["faultNormal_Y"] = normalVector.y(); + map["faultNormal_Z"] = normalVector.z(); +} diff --git a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationTools.h b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationTools.h new file mode 100644 index 0000000000..ecf683aa34 --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationTools.h @@ -0,0 +1,39 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2023 Equinor 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include +#include +#include + +#include "cvfVector3.h" + +class RimFaultReactivationTools +{ +public: + static cvf::Vec3d normalVector( QMap settings ); + static cvf::Vec3d topFaultPosition( QMap settings ); + static cvf::Vec3d bottomFaultPosition( QMap settings ); + + static void + addSettingsToMap( QMap& map, cvf::Vec3d normalVector, cvf::Vec3d topFaultPosition, cvf::Vec3d bottomFaultPosition ); + +private: + RimFaultReactivationTools(){}; +}; diff --git a/ApplicationLibCode/ProjectDataModel/GeoMech/RimGeoMechFaultReactivationResult.cpp b/ApplicationLibCode/ProjectDataModel/GeoMech/RimGeoMechFaultReactivationResult.cpp index 6ea2bf307a..66707d8ef6 100644 --- a/ApplicationLibCode/ProjectDataModel/GeoMech/RimGeoMechFaultReactivationResult.cpp +++ b/ApplicationLibCode/ProjectDataModel/GeoMech/RimGeoMechFaultReactivationResult.cpp @@ -25,15 +25,17 @@ #include "WellLogCommands/RicNewWellLogPlotFeatureImpl.h" #include "WellLogCommands/RicWellLogPlotCurveFeatureImpl.h" +#include "RifJsonEncodeDecode.h" + #include "RigFemPartCollection.h" #include "RigGeoMechCaseData.h" #include "RigHexIntersectionTools.h" #include "RigReservoirGridTools.h" +#include "RimFaultReactivationTools.h" #include "RimGeoMechCase.h" #include "RimGeoMechView.h" #include "RimGridView.h" -#include "RimIntersectionCollection.h" #include "RimMainPlotCollection.h" #include "RimModeledWellPath.h" #include "RimWellLogCalculatedCurve.h" @@ -55,26 +57,29 @@ #include +#include +#include +#include +#include + CAF_PDM_SOURCE_INIT( RimGeoMechFaultReactivationResult, "RimGeoMechFaultReactivationResult" ); //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimGeoMechFaultReactivationResult::RimGeoMechFaultReactivationResult() + : m_bHaveValidData( false ) { - // TODO: Update icon CAF_PDM_InitObject( "Fault Reactivation Result", ":/GeoMechCase24x24.png" ); - CAF_PDM_InitFieldNoDefault( &m_intersection, "Intersection", "Intersection" ); + CAF_PDM_InitField( &m_distanceFromFault, "DistanceFromFault", 5.0, "Distance From Fault" ); - CAF_PDM_InitField( &m_distanceFromIntersection, - "FaceDistanceFromIntersection", - m_defaultDistanceFromIntersection, - "Face Distance From Intersection" ); - CAF_PDM_InitField( &m_widthOutsideIntersection, "FaceWidthOutsideIntersection", 0.0, "Face Width Outside Intersection" ); + CAF_PDM_InitFieldNoDefault( &m_createFaultReactivationPlot, "CreateReactivationPlot", "" ); + caf::PdmUiPushButtonEditor::configureEditorForField( &m_createFaultReactivationPlot ); - CAF_PDM_InitFieldNoDefault( &m_createFaultReactivationResult, "CreateReactivationResult", "" ); - caf::PdmUiPushButtonEditor::configureEditorForField( &m_createFaultReactivationResult ); + CAF_PDM_InitFieldNoDefault( &m_faultNormal, "FaultNormal", "" ); + CAF_PDM_InitFieldNoDefault( &m_faultTopPosition, "FaultTopPosition", "" ); + CAF_PDM_InitFieldNoDefault( &m_faultBottomPosition, "FaultBottomPosition", "" ); CAF_PDM_InitFieldNoDefault( &m_faceAWellPath, "FaceAWellPath", "Face A Well Path" ); m_faceAWellPath.uiCapability()->setUiHidden( true ); @@ -94,8 +99,6 @@ RimGeoMechFaultReactivationResult::RimGeoMechFaultReactivationResult() //-------------------------------------------------------------------------------------------------- RimGeoMechFaultReactivationResult::~RimGeoMechFaultReactivationResult() { - delete m_faceAWellPath; - delete m_faceBWellPath; } //-------------------------------------------------------------------------------------------------- @@ -103,6 +106,27 @@ RimGeoMechFaultReactivationResult::~RimGeoMechFaultReactivationResult() //-------------------------------------------------------------------------------------------------- void RimGeoMechFaultReactivationResult::onLoadDataAndUpdate() { + auto geomCase = geoMechCase(); + if ( geomCase == nullptr ) return; + + auto filename = geomCase->gridFileName(); + QFileInfo fi( filename ); + auto folder = fi.path(); + auto basename = fi.baseName(); + + QDir workDir( folder ); + auto modelSettingsFilename = workDir.absoluteFilePath( basename + ".settings.json" ); + + auto map = ResInsightInternalJson::JsonReader::decodeFile( modelSettingsFilename ); + if ( !map.isEmpty() ) + { + m_faultNormal = RimFaultReactivationTools::normalVector( map ); + m_faultTopPosition = RimFaultReactivationTools::topFaultPosition( map ); + m_faultBottomPosition = RimFaultReactivationTools::bottomFaultPosition( map ); + + m_bHaveValidData = true; + } + createWellGeometry(); createWellLogCurves(); } @@ -114,22 +138,6 @@ QList RimGeoMechFaultReactivationResult::calculateValueO { QList options; - if ( fieldNeedingOptions == &m_intersection ) - { - RimGridView* activeView = RiaApplication::instance()->activeGridView(); - if ( !activeView || !activeView->intersectionCollection() ) return options; - - for ( auto* intersection : activeView->intersectionCollection()->intersections() ) - { - // Only utilize polyline intersections with two points - if ( intersection && intersection->type() == RimExtrudedCurveIntersection::CrossSectionEnum::CS_POLYLINE && - !intersection->polyLines().empty() && intersection->polyLines()[0].size() == 2 ) - { - options.push_back( caf::PdmOptionItemInfo( intersection->name(), intersection ) ); - } - } - } - return options; } @@ -139,14 +147,10 @@ QList RimGeoMechFaultReactivationResult::calculateValueO void RimGeoMechFaultReactivationResult::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) { caf::PdmUiGroup* group = uiOrdering.addNewGroup( "Fault Reactivation Result" ); - group->add( &m_intersection ); - group->add( &m_distanceFromIntersection ); - group->add( &m_widthOutsideIntersection ); - group->add( &m_createFaultReactivationResult ); - group->add( &m_faceAWellPath ); - group->add( &m_faceBWellPath ); - group->add( &m_faceAWellPathPartIndex ); - group->add( &m_faceBWellPathPartIndex ); + group->add( &m_distanceFromFault ); + group->add( &m_createFaultReactivationPlot ); + + uiOrdering.skipRemainingFields( true ); } //-------------------------------------------------------------------------------------------------- @@ -156,11 +160,11 @@ void RimGeoMechFaultReactivationResult::fieldChangedByUi( const caf::PdmFieldHan const QVariant& oldValue, const QVariant& newValue ) { - if ( changedField == &m_distanceFromIntersection || changedField == &m_widthOutsideIntersection ) + if ( changedField == &m_distanceFromFault ) { createWellGeometry(); } - if ( changedField == &m_createFaultReactivationResult && m_intersection() ) + if ( changedField == &m_createFaultReactivationPlot ) { createWellGeometry(); createWellLogCurves(); @@ -174,7 +178,7 @@ void RimGeoMechFaultReactivationResult::defineEditorAttribute( const caf::PdmFie QString uiConfigName, caf::PdmUiEditorAttribute* attribute ) { - if ( field == &m_createFaultReactivationResult ) + if ( field == &m_createFaultReactivationPlot ) { caf::PdmUiPushButtonEditorAttribute* attrib = dynamic_cast( attribute ); if ( attrib ) @@ -189,14 +193,16 @@ void RimGeoMechFaultReactivationResult::defineEditorAttribute( const caf::PdmFie //-------------------------------------------------------------------------------------------------- void RimGeoMechFaultReactivationResult::createWellGeometry() { - RimGeoMechCase* geomCase = firstAncestorOrThisOfTypeAsserted(); + if ( !m_bHaveValidData ) return; + + auto geomCase = geoMechCase(); if ( !geomCase || !geomCase->geoMechData() ) return; RigFemPartCollection* geoMechPartCollection = geomCase->geoMechData()->femParts(); if ( !geoMechPartCollection ) return; RimWellPathCollection* wellPathCollection = RimProject::current()->activeOilField()->wellPathCollection(); if ( !wellPathCollection ) return; - // Create well paths if not existing collection + // Create well paths if not existing in collection const auto allWellPaths = wellPathCollection->allWellPaths(); if ( !m_faceAWellPath || ( m_faceAWellPath && std::find( allWellPaths.begin(), allWellPaths.end(), m_faceAWellPath ) == allWellPaths.end() ) ) @@ -221,41 +227,14 @@ void RimGeoMechFaultReactivationResult::createWellGeometry() m_faceAWellPath->geometryDefinition()->deleteAllTargets(); m_faceBWellPath->geometryDefinition()->deleteAllTargets(); - // Using first two points from first polyline - const auto polyLines = m_intersection()->polyLines(); - if ( polyLines.size() != 1 || polyLines[0].size() != 2 ) - { - RiaLogging::error( "Polyline intersection for fault face must be defined with only 2 points!" ); - return; - } - const std::vector points = { polyLines[0][0], polyLines[0][1] }; - - // Create vector for well path defined by point a and b - const cvf::Vec3d a = points[0]; - const cvf::Vec3d b = points[1]; - const cvf::Vec3d wellVector = b - a; - - // Cross product of well path vector and z-axis (New vector must be normalized) - const cvf::Vec3d normVector = wellVector ^ cvf::Vector3::Z_AXIS; - const cvf::Vec3d distanceVector = m_distanceFromIntersection() * normVector.getNormalized(); - - // Get normalized vector along well to adjust point a and b outside of defined intersection - const auto normalizedWellVector = wellVector.getNormalized(); - const cvf::Vec3d widthAdjustedA = a - ( normalizedWellVector * m_widthOutsideIntersection() ); - const cvf::Vec3d widthAdjustedB = b + ( normalizedWellVector * m_widthOutsideIntersection() ); - - // Create well points for face A and B - const std::pair faceAWellStartAndEnd = { widthAdjustedA + distanceVector, widthAdjustedB + distanceVector }; - const std::pair faceBWellStartAndEnd = { widthAdjustedA - distanceVector, widthAdjustedB - distanceVector }; - - // Get center point between face well points to detect which part fault faces are in - auto centerpoint = []( const cvf::Vec3d& a, const cvf::Vec3d& b ) -> cvf::Vec3d { return ( a + b ) / 2.0; }; - const cvf::Vec3d faceAWellPathCenter = centerpoint( faceAWellStartAndEnd.first, faceAWellStartAndEnd.second ); - const cvf::Vec3d faceBWellPathCenter = centerpoint( faceBWellStartAndEnd.first, faceBWellStartAndEnd.second ); + cvf::Vec3d partATop = m_faultTopPosition() + m_faultNormal() * m_distanceFromFault; + cvf::Vec3d partABottom = m_faultBottomPosition() + m_faultNormal() * m_distanceFromFault; + cvf::Vec3d partBTop = m_faultTopPosition() - m_faultNormal() * m_distanceFromFault; + cvf::Vec3d partBBottom = m_faultBottomPosition() - m_faultNormal() * m_distanceFromFault; // Update the well path target values - const std::vector faceAWellPoints = { faceAWellStartAndEnd.first, faceAWellPathCenter, faceAWellStartAndEnd.second }; - const std::vector faceBWellPoints = { faceBWellStartAndEnd.first, faceBWellPathCenter, faceBWellStartAndEnd.second }; + const std::vector faceAWellPoints = { partATop, partABottom }; + const std::vector faceBWellPoints = { partBTop, partBBottom }; m_faceAWellPath->geometryDefinition()->createAndInsertTargets( faceAWellPoints ); m_faceBWellPath->geometryDefinition()->createAndInsertTargets( faceBWellPoints ); m_faceAWellPath->geometryDefinition()->setUseAutoGeneratedTargetAtSeaLevel( false ); @@ -264,8 +243,8 @@ void RimGeoMechFaultReactivationResult::createWellGeometry() m_faceBWellPath->createWellPathGeometry(); // Detect which part well path centers are in - m_faceAWellPathPartIndex = getPartIndexFromPoint( geoMechPartCollection, faceAWellPathCenter ); - m_faceBWellPathPartIndex = getPartIndexFromPoint( geoMechPartCollection, faceBWellPathCenter ); + m_faceAWellPathPartIndex = getPartIndexFromPoint( geoMechPartCollection, partATop ); + m_faceBWellPathPartIndex = getPartIndexFromPoint( geoMechPartCollection, partBTop ); // Update UI wellPathCollection->uiCapability()->updateConnectedEditors(); @@ -277,7 +256,9 @@ void RimGeoMechFaultReactivationResult::createWellGeometry() //-------------------------------------------------------------------------------------------------- void RimGeoMechFaultReactivationResult::createWellLogCurves() { - RimGeoMechCase* geomCase = firstAncestorOrThisOfTypeAsserted(); + if ( !m_bHaveValidData ) return; + + auto geomCase = geoMechCase(); if ( !geomCase ) return; Rim3dView* view = RiaApplication::instance()->activeMainOrComparisonGridView(); if ( !view ) return; @@ -375,8 +356,9 @@ RimWellLogExtractionCurve* RimGeoMechFaultReactivationResult::createWellLogExtra RimModeledWellPath* wellPath, int partId ) { - RimGeoMechCase* geomCase = firstAncestorOrThisOfTypeAsserted(); + auto geomCase = geoMechCase(); if ( !geomCase ) return nullptr; + Rim3dView* view = RiaApplication::instance()->activeMainOrComparisonGridView(); if ( !view ) return nullptr; @@ -412,3 +394,11 @@ QString RimGeoMechFaultReactivationResult::plotDescription() const return count == 0 ? plotDescription : QString( "%1 %2" ).arg( plotDescription ).arg( count ); } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimGeoMechCase* RimGeoMechFaultReactivationResult::geoMechCase() const +{ + return firstAncestorOrThisOfTypeAsserted(); +} diff --git a/ApplicationLibCode/ProjectDataModel/GeoMech/RimGeoMechFaultReactivationResult.h b/ApplicationLibCode/ProjectDataModel/GeoMech/RimGeoMechFaultReactivationResult.h index c751276def..945be68ce3 100644 --- a/ApplicationLibCode/ProjectDataModel/GeoMech/RimGeoMechFaultReactivationResult.h +++ b/ApplicationLibCode/ProjectDataModel/GeoMech/RimGeoMechFaultReactivationResult.h @@ -35,6 +35,7 @@ class RigFemResultAddress; class RimModeledWellPath; class RimWellLogTrack; class RimWellLogExtractionCurve; +class RimGeoMechCase; class RimGeoMechFaultReactivationResult : public caf::PdmObject { @@ -44,9 +45,9 @@ class RimGeoMechFaultReactivationResult : public caf::PdmObject RimGeoMechFaultReactivationResult(); ~RimGeoMechFaultReactivationResult() override; -private: void onLoadDataAndUpdate(); +private: QList calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions ) override; void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override; void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override; @@ -64,13 +65,16 @@ class RimGeoMechFaultReactivationResult : public caf::PdmObject QString plotDescription() const; + RimGeoMechCase* geoMechCase() const; + private: - caf::PdmPtrField m_intersection; + caf::PdmField m_createFaultReactivationPlot; - caf::PdmField m_createFaultReactivationResult; + caf::PdmField m_distanceFromFault; - caf::PdmField m_distanceFromIntersection; // To move wells to each side of intersection - caf::PdmField m_widthOutsideIntersection; // To stretch well points outside intersection + caf::PdmField m_faultNormal; + caf::PdmField m_faultTopPosition; + caf::PdmField m_faultBottomPosition; caf::PdmPtrField m_faceAWellPath; caf::PdmPtrField m_faceBWellPath; @@ -78,5 +82,5 @@ class RimGeoMechFaultReactivationResult : public caf::PdmObject caf::PdmField m_faceAWellPathPartIndex; caf::PdmField m_faceBWellPathPartIndex; - const double m_defaultDistanceFromIntersection = 1.0; // [m] Default value from intersection and into each part + bool m_bHaveValidData; }; diff --git a/ApplicationLibCode/ProjectDataModel/GeoMech/RimGeoMechView.cpp b/ApplicationLibCode/ProjectDataModel/GeoMech/RimGeoMechView.cpp index a0cca82523..d2844e600d 100644 --- a/ApplicationLibCode/ProjectDataModel/GeoMech/RimGeoMechView.cpp +++ b/ApplicationLibCode/ProjectDataModel/GeoMech/RimGeoMechView.cpp @@ -201,6 +201,8 @@ void RimGeoMechView::onLoadDataAndUpdate() if ( m_partsCollection ) m_partsCollection->syncWithCase( m_geomechCase ); + if ( m_faultReactivationResult ) m_faultReactivationResult->onLoadDataAndUpdate(); + scheduleCreateDisplayModelAndRedraw(); progress.incrementProgress(); diff --git a/ApplicationLibCode/ReservoirDataModel/RigBasicPlane.cpp b/ApplicationLibCode/ReservoirDataModel/RigBasicPlane.cpp index e87b5b553e..e826d60039 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigBasicPlane.cpp +++ b/ApplicationLibCode/ReservoirDataModel/RigBasicPlane.cpp @@ -67,6 +67,14 @@ void RigBasicPlane::setPlane( cvf::Vec3d anchorPoint, cvf::Vec3d normal ) m_planeNormal = normal; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::Vec3d RigBasicPlane::normal() const +{ + return m_planeNormal; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ReservoirDataModel/RigBasicPlane.h b/ApplicationLibCode/ReservoirDataModel/RigBasicPlane.h index 28e31d639a..15d62861f2 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigBasicPlane.h +++ b/ApplicationLibCode/ReservoirDataModel/RigBasicPlane.h @@ -53,6 +53,7 @@ class RigBasicPlane : public cvf::Object double maxDepth(); std::pair intersectTopBottomLine(); + cvf::Vec3d normal() const; cvf::Vec3dArray rect() const; cvf::ref texture() const; diff --git a/ApplicationLibCode/ReservoirDataModel/RigFaultReactivationModel.cpp b/ApplicationLibCode/ReservoirDataModel/RigFaultReactivationModel.cpp index ff0c24b6b1..6346be0b33 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigFaultReactivationModel.cpp +++ b/ApplicationLibCode/ReservoirDataModel/RigFaultReactivationModel.cpp @@ -270,6 +270,14 @@ void RigFaultReactivationModel::updateRects() generateGrids( points ); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::Vec3d RigFaultReactivationModel::normal() const +{ + return m_planeNormal; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ReservoirDataModel/RigFaultReactivationModel.h b/ApplicationLibCode/ReservoirDataModel/RigFaultReactivationModel.h index 323def2263..f07bbee6d8 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigFaultReactivationModel.h +++ b/ApplicationLibCode/ReservoirDataModel/RigFaultReactivationModel.h @@ -84,6 +84,8 @@ class RigFaultReactivationModel : public cvf::Object void updateRects(); + cvf::Vec3d normal() const; + void setPartColors( cvf::Color3f part1Color, cvf::Color3f part2Color ); std::vector rect( ModelParts part ) const; cvf::ref texture( ModelParts part ) const;