diff --git a/.github/workflows/ResInsightWithCache.yml b/.github/workflows/ResInsightWithCache.yml index 5d2bb583c7..4d2be6dd14 100644 --- a/.github/workflows/ResInsightWithCache.yml +++ b/.github/workflows/ResInsightWithCache.yml @@ -129,7 +129,7 @@ jobs: uses: actions/cache@v3 with: path: ${{ env.BUILDCACHE_DIR }} - key: ${{ matrix.config.os }}-${{ matrix.config.cc }}-cache-v02-${{ steps.current-time.outputs.formattedTime }} + key: ${{ matrix.config.os }}-${{ matrix.config.cc }}-cache-v03-${{ steps.current-time.outputs.formattedTime }} - name: Create Folder for buildcache run: New-Item ${{ env.BUILDCACHE_DIR }} -ItemType "directory" -Force shell: pwsh diff --git a/.gitmodules b/.gitmodules index 7b1c4f9349..da885ca10b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -22,3 +22,6 @@ [submodule "ThirdParty/regression-analysis"] path = ThirdParty/regression-analysis url = https://github.com/CeetronSolutions/regression-analysis.git +[submodule "ThirdParty/tomlplusplus"] + path = ThirdParty/tomlplusplus + url = https://github.com/marzer/tomlplusplus.git diff --git a/ApplicationExeCode/CMakeLists.txt b/ApplicationExeCode/CMakeLists.txt index cac83accf8..be6d00179e 100644 --- a/ApplicationExeCode/CMakeLists.txt +++ b/ApplicationExeCode/CMakeLists.txt @@ -367,11 +367,11 @@ else() set(OPENVDS_LIB_NAMES libopenvds.so libopenvds.so.3 - libopenvds.so.3.2.3 - libopenvds-968eeb36.so.3.2.3 + libopenvds.so.3.2.7 + libopenvds-e1541338.so.3.2.7 libsegyutils.so libsegyutils.so.3 - libsegyutils.so.3.2.3 + libsegyutils.so.3.2.7 ) foreach(OPENVDS_LIB_NAME ${OPENVDS_LIB_NAMES}) list(APPEND RI_FILENAMES @@ -380,15 +380,33 @@ else() endforeach(OPENVDS_LIB_NAME) endif(MSVC) -# Copy dependencies to make it possible to run ResInsight from the build folder -foreach(FILE_TO_COPY ${RI_FILENAMES}) - add_custom_command( - TARGET ResInsight - POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_if_different ${FILE_TO_COPY} - $ +# create an empty library target that will be used to copy files to the build +# folder +add_library(ResInsightDummyTarget EXCLUDE_FROM_ALL empty.cpp) +set_property(TARGET ResInsightDummyTarget PROPERTY FOLDER "FileCopyTargets") + +# create a custom target that copies the files to the build folder +foreach(riFileName ${RI_FILENAMES}) + list( + APPEND + copyCommands + COMMAND + ${CMAKE_COMMAND} + -E + copy_if_different + ${riFileName} + $ ) endforeach() +add_custom_target( + PreBuildFileCopy + COMMENT "PreBuildFileCopy step: copy runtime files into build folder" + ${copyCommands} +) +set_property(TARGET PreBuildFileCopy PROPERTY FOLDER "FileCopyTargets") + +# Make ResInsight depend on the prebuild target. +add_dependencies(ResInsight PreBuildFileCopy) # Generate Python code in a target that is part of ALL_BUILD and depends on # ResInsight @@ -715,10 +733,10 @@ if(RESINSIGHT_BUNDLE_OPENSSL) string(REPLACE "include" "bin" OPENSSL_BIN_DIR ${OPENSSL_BIN_DIR}) message("OpenSSL binary dir: ${OPENSSL_BIN_DIR}") - install(FILES ${OPENSSL_BIN_DIR}/libcrypto-1_1-x64.dll + install(FILES ${OPENSSL_BIN_DIR}/libcrypto-3-x64.dll DESTINATION ${RESINSIGHT_INSTALL_FOLDER} ) - install(FILES ${OPENSSL_BIN_DIR}/libssl-1_1-x64.dll + install(FILES ${OPENSSL_BIN_DIR}/libssl-3-x64.dll DESTINATION ${RESINSIGHT_INSTALL_FOLDER} ) endif(OPENSSL_FOUND) @@ -733,13 +751,13 @@ if(RESINSIGHT_BUNDLE_OPENSSL) install(FILES ${OPENSSL_BIN_DIR}/libcrypto.so DESTINATION ${RESINSIGHT_INSTALL_FOLDER} ) - install(FILES ${OPENSSL_BIN_DIR}/libcrypto.so.1.1 + install(FILES ${OPENSSL_BIN_DIR}/libcrypto.so.3 DESTINATION ${RESINSIGHT_INSTALL_FOLDER} ) install(FILES ${OPENSSL_BIN_DIR}/libssl.so DESTINATION ${RESINSIGHT_INSTALL_FOLDER} ) - install(FILES ${OPENSSL_BIN_DIR}/libssl.so.1.1 + install(FILES ${OPENSSL_BIN_DIR}/libssl.so.3 DESTINATION ${RESINSIGHT_INSTALL_FOLDER} ) endif() diff --git a/ApplicationExeCode/empty.cpp b/ApplicationExeCode/empty.cpp new file mode 100644 index 0000000000..580fdff75d --- /dev/null +++ b/ApplicationExeCode/empty.cpp @@ -0,0 +1,10 @@ +// +// This empty file is used by ResInsightDummyTarget +// +// Creating a dummy target with an empty file is used to have a different target than ResInsight. +// This target is used to find the full path to the build folder. +// +// $ +// +// If we use the ResInsight target ($), we get a circular dependency. +// diff --git a/ApplicationLibCode/Adm/LicenseInformation.txt b/ApplicationLibCode/Adm/LicenseInformation.txt index b9258bb3cd..828794e6f4 100644 --- a/ApplicationLibCode/Adm/LicenseInformation.txt +++ b/ApplicationLibCode/Adm/LicenseInformation.txt @@ -488,7 +488,7 @@ CRAVA is a software package for seismic inversion and conditioning of =============================================================================== - Notice for the mio library + Notice for mio =============================================================================== Copyright 2017 https://github.com/mandreyel @@ -512,7 +512,7 @@ OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. =============================================================================== - Notice for the fast_float library + Notice for fast_float =============================================================================== https://github.com/fastfloat/fast_float @@ -542,7 +542,7 @@ IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. =============================================================================== - Notice for the Qt-Advanced-Docking-System library + Notice for Qt-Advanced-Docking-System =============================================================================== https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System @@ -561,7 +561,7 @@ https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/blob/master/LICEN the version number 2.1.] =============================================================================== - Notice for the fmtlib library + Notice for fmtlib =============================================================================== https://github.com/fmtlib/fmt @@ -596,7 +596,7 @@ source code, you may redistribute such embedded portions in such object form without including the above copyright and permission notices. =============================================================================== - Notice for the roffcpp library + Notice for roffcpp =============================================================================== https://github.com/CeetronSolutions/roffcpp @@ -617,7 +617,7 @@ See the GNU General Public License at for more details. =============================================================================== - Notice for the open-vds library + Notice for open-vds =============================================================================== https://community.opengroup.org/osdu/platform/domain-data-mgmt-services/seismic/open-vds/-/blob/master/LICENSE @@ -629,7 +629,7 @@ https://community.opengroup.org/osdu/platform/domain-data-mgmt-services/seismic/ =============================================================================== - Notice for the open-zgy library + Notice for open-zgy =============================================================================== https://community.opengroup.org/osdu/platform/domain-data-mgmt-services/seismic/open-zgy/-/blob/master/LICENSE.txt @@ -641,7 +641,7 @@ https://community.opengroup.org/osdu/platform/domain-data-mgmt-services/seismic/ =============================================================================== - Notice for the regression-analysis library + Notice for regression-analysis =============================================================================== https://github.com/CeetronSolutions/regression-analysis @@ -660,3 +660,26 @@ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License at for more details. + +=============================================================================== + Notice for tomlplusplus +=============================================================================== + +https://github.com/marzer/tomlplusplus/blob/master/LICENSE + +MIT License + +Copyright (c) Mark Gillard + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/ApplicationLibCode/Adm/projectfilekeywords/2023.12/ri-fieldKeywords.txt b/ApplicationLibCode/Adm/projectfilekeywords/2023.12/ri-fieldKeywords.txt new file mode 100644 index 0000000000..c976ff0d4f --- /dev/null +++ b/ApplicationLibCode/Adm/projectfilekeywords/2023.12/ri-fieldKeywords.txt @@ -0,0 +1,5596 @@ +// ResInsight version string : 2023.12.0-RC_03 +// Report generated : Mon Dec 11 13:16:58 2023 +// +// + +AnalysisPlot - class RimAnalysisPlot + WindowController + ShowWindow + WindowGeometry + Id + (A)ViewId + ShowPlotTitle + ShowTrackLegends + TrackLegendsHorizontal + LegendItemsClickable + TitleFontSize + LegendDeltaFontSize + LegendPosition + RowSpan + ColSpan + AnalysisPlotData + TimeStepFilter + TimeSteps + ReferenceCase + IsUsingAutoName + PlotDescription + BarOrientation + MajorGroupType + MediumGroupType + MinorGroupType + ValueSortOperation + groupForColors + UseTopBarsFilter + MaxBarCount + UseBarText + UseCaseInBarText + UseEnsembleInBarText + UseSummaryItemInBarText + UseTimeStepInBarText + UseQuantityInBarText + BarTextFontSize + ValueAxisProperties + PlotDataFilterCollection + +AnalysisPlotCollection - class RimAnalysisPlotCollection + AnalysisPlots + +AnalysisPlotDataEntry - class RimAnalysisPlotDataEntry + SummaryCase + Ensemble + SummaryAddress + IsEnsembleCurve + +Annotations - class RimAnnotationInViewCollection + IsActive + TextAnnotations + AnnotationPlaneDepth + SnapAnnotations + TextAnnotationsInView + ReachCircleAnnotationsInView + UserDefinedPolylinesAnnotationsInView + PolylinesFromFileAnnotationsInView + AnnotationFontSize + +AsciiDataCurve - class RimAsciiDataCurve + Show + AutoCheckStateBasedOnCurveData + CurveName + TemplateText + CurveNamingMethod + LegendDescription + AutoName + ShowLegend + ShowErrorBars + Color + FillColor + Thickness + CurveInterpolation + LineStyle + FillStyle + PointSymbol + SymbolEdgeColor + SymbolSkipPxDist + SymbolLabel + SymbolSize + SymbolLabelPosition + PlotCurveAppearance + AdditionalDataSources + RectAnnotation + PlotAxis + TimeSteps + Values + Title + +CalcScript - class RimCalcScript + AbsolutePath + +CellEdgeResultSlot - class RimCellEdgeColors + EnableCellEdgeColors + propertyType + CellEdgeVariable + UseXVariable + UseYVariable + UseZVariable + LegendDefinition + SelectedProperties + ShowTextValuesIfItemIsUnchecked + SingleVarEdgeResult + +CellFilterCollection - class RimCellFilterCollection + Active + CellFilters + RangeFilters + +CellIndexFilter - class RimCellIndexFilter + UserDescription + Active + Case + FilterType + GridIndex + PropagateToSubGrids + ElementSetId + +CellPropertyFilter - class RimEclipsePropertyFilter + UserDescription + Active + Case + FilterType + GridIndex + PropagateToSubGrids + SelectedValues + ResultDefinition + LowerBound + UpperBound + CategorySelection + IsDuplicatedFromLinkedView + +CellPropertyFilters - class RimEclipsePropertyFilterCollection + Active + PropertyFilters + +CellRangeFilter - class RimCellRangeFilter + UserDescription + Active + Case + FilterType + GridIndex + PropagateToSubGrids + StartIndexI + CellCountI + StartIndexJ + CellCountJ + StartIndexK + CellCountK + +CellRangeFilterCollection - class RimCellFilterCollection + Active + CellFilters + RangeFilters + +ChangeDataSourceFeatureUi - class RimWellLogCurveCommonDataSource + CurveCase + SummaryCase + TrajectoryType + CurveWellPath + SimulationWellName + BranchDetection + Allow3DSelectionLink + Branch + CurveTimeStep + WBSSmoothing + WBSSmoothingThreshold + MaximumCurvePointInterval + RftTimeStep + RftWellName + SegmentBranchIndex + SegmentBranchType + +CmdAddItemExecData - class caf::CmdAddItemExecData + PathToField + indexAfter + createdItemIndex + +CmdDeleteItemExecData - class caf::CmdDeleteItemExecData + PathToField + indexToObject + deletedObjectAsXml + +CmdSelectionChangeExecData - class caf::CmdSelectionChangeExecData + selectionLevel + previousSelection + newSelection + +ColorLegend - class RimColorLegend + ColorLegendName + ColorLegendItems + +ColorLegendCollection - class RimColorLegendCollection + CustomColorLegends + +ColorLegendItem - class RimColorLegendItem + Color + CategoryValue + CategoryName + +CompletionTemplateCollection - class RimCompletionTemplateCollection + FractureTemplates + StimPlanModelTemplates + ValveTemplates + FractureGroupStatisticsCollection + +CorrelationMatrixPlot - class RimCorrelationMatrixPlot + WindowController + ShowWindow + WindowGeometry + Id + (A)ViewId + ShowPlotTitle + ShowTrackLegends + TrackLegendsHorizontal + LegendItemsClickable + TitleFontSize + LegendDeltaFontSize + LegendPosition + RowSpan + ColSpan + AnalysisPlotData + TimeStepFilter + TimeStep + AutoTitle + PlotTitle + LabelFontSize + AxisTitleFontSize + AxisValueFontSize + UseCaseFilter + CurveSetForFiltering + EditCaseFilter + CorrelationAbsValues + CorrelationSorting + CorrelationAbsSorting + ExcludeParamsWithoutVariation + ShowOnlyTopNCorrelations + TopNFilterCount + LegendConfig + SelectedParameters + +CorrelationPlot - class RimCorrelationPlot + WindowController + ShowWindow + WindowGeometry + Id + (A)ViewId + ShowPlotTitle + ShowTrackLegends + TrackLegendsHorizontal + LegendItemsClickable + TitleFontSize + LegendDeltaFontSize + LegendPosition + RowSpan + ColSpan + AnalysisPlotData + TimeStepFilter + TimeStep + AutoTitle + PlotTitle + LabelFontSize + AxisTitleFontSize + AxisValueFontSize + UseCaseFilter + CurveSetForFiltering + EditCaseFilter + CorrelationAbsValues + CorrelationAbsSorting + ExcludeParamsWithoutVariation + ShowOnlyTopNCorrelations + TopNFilterCount + SelectedParameters + BarColor + +CorrelationPlotCollection - class RimCorrelationPlotCollection + CorrelationPlots + CorrelationReports + +CorrelationReportPlot - class RimCorrelationReportPlot + WindowController + ShowWindow + WindowGeometry + Id + (A)ViewId + ShowPlotTitle + ShowTrackLegends + TrackLegendsHorizontal + LegendItemsClickable + TitleFontSize + LegendDeltaFontSize + LegendPosition + PlotWindowTitle + MatrixPlot + CorrelationPlot + CrossPlot + SubTitleFontSize + LabelFontSize + AxisTitleFontSize + AxisValueFontSize + +CrossSection - class RimExtrudedCurveIntersection + Active + ShowInactiveCells + UseSeparateIntersectionDataSource + SeparateIntersectionDataSource + UserDescription + Type + Direction + WellPath + SimulationWell + Points + PointsUi + AzimuthAngle + DipAngle + CustomExtrusionPoints + TwoAzimuthPoints + Branch + ExtentLength + lengthUp + lengthDown + SurfaceIntersections + UpperThreshold + LowerThreshold + DepthFilter + CollectionUpperThreshold + CollectionLowerThreshold + ThresholdOverridden + CollectionDepthFilterType + EnableKFilter + KRangeFilter + KFilterCollectionOverride + KRangeCollectionFilter + +CrossSectionCollection - class RimIntersectionCollection + CrossSections + IntersectionBoxes + Active + UpperDepthThreshold + LowerDepthThreshold + DepthFilterOverride + CollectionDepthFilterType + OverrideKFilter + KRangeFilter + ApplyCellFilters + +CsvSummaryCase - class RimCsvSummaryCase + ShortName + NameSetting + ShowSubNodesInTree + AutoShortyName + SummaryHeaderFilename + Id + (A)CaseId + FileType + StartDate + +CurveIntersection - class RimExtrudedCurveIntersection + Active + ShowInactiveCells + UseSeparateIntersectionDataSource + SeparateIntersectionDataSource + UserDescription + Type + Direction + WellPath + SimulationWell + Points + PointsUi + AzimuthAngle + DipAngle + CustomExtrusionPoints + TwoAzimuthPoints + Branch + ExtentLength + lengthUp + lengthDown + SurfaceIntersections + UpperThreshold + LowerThreshold + DepthFilter + CollectionUpperThreshold + CollectionLowerThreshold + ThresholdOverridden + CollectionDepthFilterType + EnableKFilter + KRangeFilter + KFilterCollectionOverride + KRangeCollectionFilter + +DataContainerFloat - class RimcDataContainerDouble + values + +DataContainerString - class RimcDataContainerString + values + +DataContainerTime - class RimcDataContainerTime + values + +DeclineCurve - class RimSummaryDeclineCurve + Show + AutoCheckStateBasedOnCurveData + CurveName + TemplateText + CurveNamingMethod + LegendDescription + AutoName + ShowLegend + ShowErrorBars + Color + FillColor + Thickness + CurveInterpolation + LineStyle + FillStyle + PointSymbol + SymbolEdgeColor + SymbolSkipPxDist + SymbolLabel + SymbolSize + SymbolLabelPosition + PlotCurveAppearance + AdditionalDataSources + RectAnnotation + StackCurve + StackPhaseColors + SummaryCase + SummaryAddress + Resampling + HorizontalAxisType + SummaryCaseX + SummaryAddressX + IsEnsembleCurve + PlotAxis + Axis + XAxis + SummaryCurveNameConfig + isTopZWithinCategory + DeclineCurveType + PredictionYears + HyperbolicDeclineConstant + MinTimeSliderPosition + MaxTimeSliderPosition + ShowTimeSelectionInPlot + +DepthTrackPlot - class RimDepthTrackPlot + WindowController + ShowWindow + WindowGeometry + Id + (A)ViewId + ShowPlotTitle + ShowTrackLegends + TrackLegendsHorizontal + LegendItemsClickable + TitleFontSize + LegendDeltaFontSize + LegendPosition + PlotDescription + TemplateText + PlotNamingMethod + DepthType + DepthUnit + MinimumDepth + MaximumDepth + ShowDepthGridLines + AutoScaleDepthEnabled + DepthAxisVisibility + ShowDepthMarkerLine + AutoZoomMinDepthFactor + AutoZoomMaxDepthFactor + DepthAnnotations + SubTitleFontSize + AxisTitleFontSize + AxisValueFontSize + NameConfig + FilterEnsembleCurveSet + DepthEqualization + Tracks + DepthOrientation + +DoubleParameter - class RimDoubleParameter + Name + Label + Description + Advanced + Valid + Value + +Eclipse2dViewCollection - class RimEclipseContourMapViewCollection + EclipseViews + +EclipseCase - class RimEclipseResultCase + Name + (A)CaseUserDescription + NameSetting + Id + (A)CaseId + FilePath + (A)CaseFileName + (A)GridFileName + DefaultFormationNames + TimeStepFilter + IntersectionViewCollection + ReservoirViews + MatrixModelResults + FractureModelResults + FlipXAxis + FlipYAxis + ContourMaps + InputPropertyCollection + gridModelReader + UnitSystem + FlowDiagSolutions + SourSimFileName + +EclipseGeometrySelectionItem - class RimEclipseGeometrySelectionItem + EclipseCase + GridIndex + CellIndex + LocalIntersectionPoint + +EclipseResultAddress - class RimEclipseResultAddress + ResultName + ResultType + EclipseCase + +ElasticProperties - class RimElasticProperties + FilePath + ShowScaledProperties + PropertyScalingCollection + +ElasticPropertyScaling - class RimElasticPropertyScaling + Name + IsChecked + Formation + Facies + Property + Scale + +ElasticPropertyScalingCollection - class RimElasticPropertyScalingCollection + ElasticPropertyScalings + +EnsembleFractureStatistics - class RimEnsembleFractureStatistics + Name + FilePaths + ExcludeZeroWidthFractures + MeshAlignmentType + MeshType + NumberOfSamplesX + NumberOfSamplesY + AdaptiveMeanType + AdaptiveNumLayersType + AdaptiveNumLayers + SelectedStatisticsType + ComputeStatistics + +EnsembleFractureStatisticsPlot - class RimEnsembleFractureStatisticsPlot + WindowController + ShowWindow + WindowGeometry + Id + (A)ViewId + ShowPlotTitle + ShowTrackLegends + TrackLegendsHorizontal + LegendItemsClickable + TitleFontSize + LegendDeltaFontSize + LegendPosition + PlotDescription + NumHistogramBins + HistogramBarColor + HistogramGapWidth + HistogramFrequencyType + Precision + TickNumberFormat + GraphType + AxisValueFontSize + AxisTitleFontSize + EnsembleFractureStatistics + Property + +EnsembleFractureStatisticsPlotCollection - class RimEnsembleFractureStatisticsPlotCollection + EnsembleFractureStatisticsPlots + +EnsembleStatisticsSurface - class RimEnsembleStatisticsSurface + SurfaceUserDecription + SurfaceColor + DepthOffset + StatisticsType + +EnsembleSurface - class RimEnsembleSurface + SurfaceUserDecription + SubCollections + SurfacesField + FilterEnsembleCurveSet + +EnsembleWellLogStatisticsCurve - class RimEnsembleWellLogStatisticsCurve + Show + AutoCheckStateBasedOnCurveData + CurveName + TemplateText + CurveNamingMethod + LegendDescription + AutoName + ShowLegend + ShowErrorBars + Color + FillColor + Thickness + CurveInterpolation + LineStyle + FillStyle + PointSymbol + SymbolEdgeColor + SymbolSkipPxDist + SymbolLabel + SymbolSize + SymbolLabelPosition + PlotCurveAppearance + AdditionalDataSources + RectAnnotation + StackCurve + StackPhaseColors + TrajectoryType + CurveWellPath + ReferenceWellPath + SimulationWellName + BranchDetection + Branch + CurveCase + CurveEclipseResult + CurveGeomechResult + CurveTimeStep + GeomPartId + AddCaseNameToCurveName + AddPropertyToCurveName + AddWellNameToCurveName + AddTimestepToCurveName + AddDateToCurveName + EnsembleWellLogCurveSet + StatisticsType + +EnsembleWellLogs - class RimEnsembleWellLogs + Name + WellLogFiles + +EnsembleWellLogsCollection - class RimEnsembleWellLogsCollection + EnsembleWellLogsCollection + +FaciesInitialPressureConfig - class RimFaciesInitialPressureConfig + IsChecked + FaciesName + FaciesValue + Fraction + +FaciesProperties - class RimFaciesProperties + FilePath + FaciesDefinition + ColorLegend + +Fault - class RimFaultInView + FaultName + ShowFault + Color + +FaultReactivationModel - class RimFaultReactivationModel + Name + IsChecked + UserDescription + GeoMechCase + BaseDirectory + ModelThickness + ModelExtentFromAnchor + ModelMinZ + ModelBelowSize + StartCellIndex + StartCellFace + FaultExtendUpwards + FaultExtendDownwards + ShowModelPlane + Fault + ModelPart1Color + ModelPart2Color + MaxReservoirCellHeight + CellHeightGrowFactor + MinReservoirCellWidth + CellWidthGrowFactor + UseLocalCoordinates + TimeStepFilter + TimeSteps + UseGridPorePressure + UseGridVoidRatio + UseGridTemperature + UseGridDensity + UseGridElasticProperties + UseGridStress + WaterDensity + Targets + MaterialParameters + +FaultReactivationModelCollection - class RimFaultReactivationModelCollection + Name + IsChecked + UserDescription + FaultReactivationModels + +Faults - class RimFaultInViewCollection + Active + ShowFaultFaces + ShowOppositeFaultFaces + ApplyCellFilters + OnlyShowWithDefNeighbor + FaultFaceCulling + ShowFaultLabel + FaultLabelColor + ShowNNCs + HideNncsWhenNoResultIsAvailable + Faults + ShowFaultsOutsideFilters + +FileSummaryCase - class RimFileSummaryCase + ShortName + NameSetting + ShowSubNodesInTree + AutoShortyName + SummaryHeaderFilename + Id + (A)CaseId + IncludeRestartFiles + AdditionalSummaryFilePath + RftCase + +FileSurface - class RimFileSurface + SurfaceUserDecription + SurfaceColor + DepthOffset + SurfaceFilePath + +FishbonesCollection - class RimFishbonesCollection + Name + IsChecked + FishbonesSubs + StartMD + MainBoreDiameter + MainBoreSkinFactor + +FishbonesMultipleSubs - class RimFishbones + Active + Name + Color + LateralCountPerSub + LateralLength + LateralExitAngle + LateralBuildAngle + LateralTubingDiameter + LateralOpenHoleRoghnessFactor + LateralTubingRoghnessFactor + LateralInstallSuccessFraction + IcdCount + IcdOrificeDiameter + IcdFlowCoefficient + SubsLocationMode + RangeStart + RangeEnd + RangeSubSpacing + RangeSubCount + LocationOfSubs + ValveLocations + SubsOrientationMode + InstallationRotationAngles + FixedInstallationRotationAngle + PipeProperties + +FishbonesPipeProperties - class RimFishbonesPipeProperties + LateralHoleDiameter + SkinFactor + +FlowCharacteristicsPlot - class RimFlowCharacteristicsPlot + WindowController + ShowWindow + WindowGeometry + FlowCase + FlowDiagSolution + TimeSelectionType + SelectedTimeSteps + SelectedTimeStepsUi + CellPVThreshold + ShowLegend + CellFilter + CellFilterView + TracerFilter + SelectedTracerNames + MinCommunication + MaxTof + +FlowDiagSolution - class RimFlowDiagSolution + UserDescription + +FlowPlotCollection - class RimFlowPlotCollection + FlowCharacteristicsPlot + DefaultWellConnectivityTable + DefaultWellAllocationOverTimePlot + DefaultWellAllocationPlot + WellDistributionPlotCollection + StoredWellAllocationPlots + StoredFlowCharacteristicsPlots + +FormationNames - class RimFormationNames + FormationNamesFileName + +FormationNamesCollectionObject - class RimFormationNamesCollection + FormationNamesList + +FractureContainment - class RimFractureContainment + IsUsingFractureContainment + TopKLayer + BaseKLayer + TruncateAtFaults + FaultThrowValue + +FractureDefinitionCollection - class RimFractureTemplateCollection + DefaultUnitForTemplates + FractureDefinitions + NextValidFractureTemplateId + +FractureGroupStatisticsCollection - class RimEnsembleFractureStatisticsCollection + FractureGroupStatistics + +FractureTemplateCollection - class RimFractureTemplateCollection + DefaultUnitForTemplates + FractureDefinitions + NextValidFractureTemplateId + +GeoMech2dViewCollection - class RimGeoMechContourMapViewCollection + GeoMechViews + +GeoMechGeometrySelectionItem - class RimGeoMechGeometrySelectionItem + GeoMechCase + m_gridIndex + m_cellIndex + m_elementFace + m_hasIntersectionTriangle + m_intersectionTriangle_0 + m_intersectionTriangle_1 + m_intersectionTriangle_2 + m_localIntersectionPoint + +GeoMechPart - class RimGeoMechPart + Name + IsChecked + PartId + +GeoMechPartCollection - class RimGeoMechPartCollection + Parts + +GeoMechPropertyFilter - class RimGeoMechPropertyFilter + UserDescription + Active + Case + FilterType + GridIndex + PropagateToSubGrids + SelectedValues + ResultDefinition + LowerBound + UpperBound + +GeoMechPropertyFilters - class RimGeoMechPropertyFilterCollection + Active + PropertyFilters + +GeoMechResultDefinition - class RimGeoMechResultDefinition + IsChecked + ResultPositionType + ResultFieldName + ResultComponentName + TimeLapseBaseTimeStep + ReferenceTimeStep + CompactionRefLayer + NormalizeByHSP + NormalizationAirGap + +GeoMechResultSlot - class RimGeoMechCellColors + IsChecked + ResultPositionType + ResultFieldName + ResultComponentName + TimeLapseBaseTimeStep + ReferenceTimeStep + CompactionRefLayer + NormalizeByHSP + NormalizationAirGap + LegendDefinition + +GeoMechView - class RimGeoMechView + WindowController + ShowWindow + WindowGeometry + Id + (A)ViewId + NameConfig + CameraPosition + CameraPointOfInterest + PerspectiveProjection + GridZScale + BackgroundColor + (A)ViewBackgroundColor + MaximumFrameRate + CurrentTimeStep + MeshMode + SurfaceMode + ShowGridBox + DisableLighting + ShowZScale + ComparisonView + FontSize + AnnotationStrategy + AnnotationCountHint + UseCustomAnnotationStrategy + CrossSections + IntersectionResultDefColl + ReservoirSurfaceResultDefColl + GridCollection + OverlayInfoConfig + WellMeasurements + SurfaceInViewCollection + SeismicSectionCollection + RangeFilters + GridCellResult + TensorResults + FaultReactivationResult + PropertyFilters + Parts + ShowDisplacement + DisplacementScaling + +GridCaseSurface - class RimGridCaseSurface + SurfaceUserDecription + SurfaceColor + DepthOffset + SourceCase + SliceIndex + Watertight + IncludeInactiveCells + +GridCollection - class RimGridCollection + IsActive + MainGrid + PersistentLgrs + +GridCrossPlotCurve - class RimGridCrossPlotCurve + Show + AutoCheckStateBasedOnCurveData + CurveName + TemplateText + CurveNamingMethod + LegendDescription + AutoName + ShowLegend + ShowErrorBars + Color + FillColor + Thickness + CurveInterpolation + LineStyle + FillStyle + PointSymbol + SymbolEdgeColor + SymbolSkipPxDist + SymbolLabel + SymbolSize + SymbolLabelPosition + PlotCurveAppearance + AdditionalDataSources + RectAnnotation + +GridCrossPlotCurveSet - class RimGridCrossPlotDataSet + Name + IsChecked + Case + TimeStep + VisibleCellView + Grouping + XAxisProperty + YAxisProperty + GroupingProperty + NameConfig + CrossPlotCurves + CrossPlotRegressionCurves + UseCustomColor + CustomColor + PlotCellFilterCollection + +GridCrossPlotRegressionCurve - class RimGridCrossPlotRegressionCurve + Show + AutoCheckStateBasedOnCurveData + CurveName + TemplateText + CurveNamingMethod + LegendDescription + AutoName + ShowLegend + ShowErrorBars + Color + FillColor + Thickness + CurveInterpolation + LineStyle + FillStyle + PointSymbol + SymbolEdgeColor + SymbolSkipPxDist + SymbolLabel + SymbolSize + SymbolLabelPosition + PlotCurveAppearance + AdditionalDataSources + RectAnnotation + RegressionType + MinExtrapolationRangeX + MaxExtrapolationRangeX + PolynomialDegree + MinRangeX + MaxRangeX + MinRangeY + MaxRangeY + ShowDataSelectionInPlot + +GridInfo - class RimGridInfo + IsActive + GridName + GridIndex + +GridInfoCollection - class RimGridInfoCollection + IsActive + GridInfos + +GridStatisticsPlot - class RimGridStatisticsPlot + WindowController + ShowWindow + WindowGeometry + Id + (A)ViewId + ShowPlotTitle + ShowTrackLegends + TrackLegendsHorizontal + LegendItemsClickable + TitleFontSize + LegendDeltaFontSize + LegendPosition + PlotDescription + NumHistogramBins + HistogramBarColor + HistogramGapWidth + HistogramFrequencyType + Precision + TickNumberFormat + GraphType + AxisValueFontSize + AxisTitleFontSize + Case + TimeStep + VisibleCellView + Property + +GridStatisticsPlotCollection - class RimGridStatisticsPlotCollection + GridStatisticsPlots + +GridSummaryCase - class RimGridSummaryCase_obsolete + ShortName + NameSetting + ShowSubNodesInTree + AutoShortyName + SummaryHeaderFilename + Id + (A)CaseId + Associated3DCase + CachedCasename + Associated3DCaseGridFileName + IncludeRestartFiles + +GridTimeHistoryCurve - class RimGridTimeHistoryCurve + Show + AutoCheckStateBasedOnCurveData + CurveName + TemplateText + CurveNamingMethod + LegendDescription + AutoName + ShowLegend + ShowErrorBars + Color + FillColor + Thickness + CurveInterpolation + LineStyle + FillStyle + PointSymbol + SymbolEdgeColor + SymbolSkipPxDist + SymbolLabel + SymbolSize + SymbolLabelPosition + PlotCurveAppearance + AdditionalDataSources + RectAnnotation + GeometrySelectionText + EclipseResultDefinition + GeoMechResultDefinition + GeometrySelectionItem + PlotAxis + +IntegerParameter - class RimIntegerParameter + Name + Label + Description + Advanced + Valid + Value + +Intersection2dView - class Rim2dIntersectionView + WindowController + ShowWindow + WindowGeometry + Id + (A)ViewId + NameConfig + CameraPosition + CameraPointOfInterest + PerspectiveProjection + GridZScale + BackgroundColor + (A)ViewBackgroundColor + MaximumFrameRate + CurrentTimeStep + MeshMode + SurfaceMode + ShowGridBox + DisableLighting + ShowZScale + ComparisonView + FontSize + AnnotationStrategy + AnnotationCountHint + UseCustomAnnotationStrategy + Intersection + ShowDefiningPoints + ShowAxisLines + +Intersection2dViewCollection - class Rim2dIntersectionViewCollection + IntersectionViews + +IntersectionBox - class RimBoxIntersection + Active + ShowInactiveCells + UseSeparateIntersectionDataSource + SeparateIntersectionDataSource + UserDescription + singlePlaneState + MinXCoord + MaxXCoord + MinYCoord + MaxYCoord + MinDepth + MaxDepth + xySliderStepSize + DepthSliderStepSize + +IntersectionCollection - class RimIntersectionCollection + CrossSections + IntersectionBoxes + Active + UpperDepthThreshold + LowerDepthThreshold + DepthFilterOverride + CollectionDepthFilterType + OverrideKFilter + KRangeFilter + ApplyCellFilters + +IntersectionResultDefinition - class RimIntersectionResultDefinition + IsActive + Case + TimeStep + IntersectionResultDefinitionDescription + EclipseResultDef + GeoMechResultDef + LegendConfig + TernaryLegendConfig + +Legend - class RimRegularLegendConfig + ShowLegend + NumberOfLevels + Precision + TickNumberFormat + ColorRangeMode + ColorLegend + MappingMode + RangeType + UserDefinedMax + UserDefinedMin + CategoryColorMode + ResultVariableUsage + ResetDefaultValues + CenterLegendAroundZero + +ListParameter - class RimListParameter + Name + Label + Description + Advanced + Valid + Value + +MainPlotCollection - class RimMainPlotCollection + Show + WellLogPlotCollection + RftPlotCollection + PltPlotCollection + SummaryMultiPlotCollection + AnalysisPlotCollection + CorrelationPlotCollection + SummaryCrossPlotCollection + SummaryTableCollection + FlowPlotCollection + Rim3dCrossPlotCollection + RimSaturationPressurePlotCollection + RimMultiPlotCollection + StimPlanModelPlotCollection + VfpPlotCollection + GridStatisticsPlotCollection + EnsembleFractureStatisticsPlotCollection + SummaryPlotCollection + +MdiWindowController - class RimMdiWindowController + MainWindowID + xPos + yPos + Width + Height + IsMaximized + +MockModelSettings - class RimMockModelSettings + CellCountX + CellCountY + CellCountZ + TotalCellCount + ResultCount + TimeStepCount + +ModeledWellPath - class RimModeledWellPath + Name + (A)WellPathName + AirGap + DatumElevation + UnitSystem + SimWellName + SimBranchIndex + ShowWellPathLabel + MeasuredDepthLabelInterval + ShowWellPath + WellPathRadiusScale + WellPathColor + Completions + CompletionSettings + WellLogFiles + CollectionOf3dWellLogCurves + WellPathFormationKeyInFile + WellPathFormationFilePath + WellPathAttributes + WellPathTieIn + WellIASettings + WellPathGeometryDef + +MultiPlot - class RimMultiPlot + WindowController + ShowWindow + WindowGeometry + Id + (A)ViewId + ShowPlotTitle + ShowTrackLegends + TrackLegendsHorizontal + LegendItemsClickable + TitleFontSize + LegendDeltaFontSize + LegendPosition + ProjectFileVersionString + ShowTitleInPlot + PlotDescription + Plots + NumberOfColumns + RowsPerPage + ShowPlotTitles + MajorTickmarkCount + SubTitleFontSize + PagePreviewMode + +MultiSnapshotDefinition - class RimAdvancedSnapshotExportDefinition + IsActive + View + EclipseResultType + SelectedEclipseResults + TimeStepStart + TimeStepEnd + SnapShotDirection + RangeFilterStart + RangeFilterEnd + AdditionalCases + +MultiSummaryPlot - class RimSummaryMultiPlot + WindowController + ShowWindow + WindowGeometry + Id + (A)ViewId + ShowPlotTitle + ShowTrackLegends + TrackLegendsHorizontal + LegendItemsClickable + TitleFontSize + LegendDeltaFontSize + LegendPosition + ProjectFileVersionString + ShowTitleInPlot + PlotDescription + Plots + NumberOfColumns + RowsPerPage + ShowPlotTitles + MajorTickmarkCount + SubTitleFontSize + PagePreviewMode + AutoPlotTitle + AutoSubPlotTitle + LinkSubPlotAxes + LinkTimeAxis + AutoAdjustAppearance + Allow3DSelectionLink + AxisRangeAggregation + PlotFilterYAxisThreshold + DefaultStepDimension + +NonNetLayers - class RimNonNetLayers + IsChecked + Cutoff + Facies + FaciesDefinition + +ObservedDataCollection - class RimObservedDataCollection + ObservedDataArray + ObservedFmuRftDataArray + PressureDepthDataArray + +ObservedFmuRftData - class RimObservedFmuRftData + Name + Directory + +ObservedPressureDepthData - class RimPressureDepthData + Name + File + +ParameterGroup - class RimParameterGroup + Parameters + Name + Label + Comment + Expanded + ParameterLists + +ParameterList - class RimParameterList + ParameterNames + Name + Label + +ParameterResultCrossPlot - class RimParameterResultCrossPlot + WindowController + ShowWindow + WindowGeometry + Id + (A)ViewId + ShowPlotTitle + ShowTrackLegends + TrackLegendsHorizontal + LegendItemsClickable + TitleFontSize + LegendDeltaFontSize + LegendPosition + RowSpan + ColSpan + AnalysisPlotData + TimeStepFilter + TimeStep + AutoTitle + PlotTitle + LabelFontSize + AxisTitleFontSize + AxisValueFontSize + UseCaseFilter + CurveSetForFiltering + EditCaseFilter + EnsembleParameter + +PdmDocument - class caf::PdmDocument + DocumentFileName + +PdmObjectCollection - class caf::PdmObjectCollection + PdmObjects + +PdmObjectGroup - class caf::PdmObjectGroup + +Perforation - class RimPerforationInterval + Name + IsChecked + StartMeasuredDepth + EndMeasuredDepth + Diameter + SkinFactor + StartOfHistory + UseCustomStartDate + StartDate + UseCustomEndDate + EndDate + Valves + +PerforationCollection - class RimPerforationCollection + Name + IsChecked + Perforations + NonDarcyParameters + +PlotDataFilterCollection - class RimPlotDataFilterCollection + IsActive + PlotDataFiltersField + +PlotDataFilterItem - class RimPlotDataFilterItem + IsActive + FilterTarget + FilterAddressField + QuantityText + FilterOperation + MinTopN + Max + Min + EnsembleParameterValueCategories + ConsideredTimestepsType + ExplicitlySelectedTimeSteps + +PlotTemplateCollection - class RimPlotTemplateFolderItem + FolderName + FileNames + SubFolders + +PlotTemplateFileItem - class RimPlotTemplateFileItem + AbsolutePath + +PolyLineFilter - class RimPolygonFilter + UserDescription + Active + Case + FilterType + GridIndex + PropagateToSubGrids + PolygonFilterType + PolyIncludeType + Targets + ShowLines + ShowSpheres + LineThickness + SphereRadiusFactor + LineColor + SphereColor + EnableFiltering + EnableKFilter + KRangeFilter + PolygonPlaneDepth + LockPolygon + +PolygonFilter - class RimPolygonFilter + UserDescription + Active + Case + FilterType + GridIndex + PropagateToSubGrids + PolygonFilterType + PolyIncludeType + Targets + ShowLines + ShowSpheres + LineThickness + SphereRadiusFactor + LineColor + SphereColor + EnableFiltering + EnableKFilter + KRangeFilter + PolygonPlaneDepth + LockPolygon + +PolylineTarget - class RimPolylineTarget + IsEnabled + TargetPointXyd + +PolylinesFromFileAnnotation - class RimPolylinesFromFileAnnotation + IsActive + ClosePolyline + ShowLines + ShowSpheres + Appearance + PolyLineFilePath + PolyLineDescription + +PressureTable - class RimPressureTable + Items + PressureDate + +PressureTableItem - class RimPressureTableItem + Depth + InitialPressure + Pressure + +PropertyFilter - class RimPropertyFilter + UserDescription + Active + Case + FilterType + GridIndex + PropagateToSubGrids + SelectedValues + +RegressionAnalysisCurve - class RimSummaryRegressionAnalysisCurve + Show + AutoCheckStateBasedOnCurveData + CurveName + TemplateText + CurveNamingMethod + LegendDescription + AutoName + ShowLegend + ShowErrorBars + Color + FillColor + Thickness + CurveInterpolation + LineStyle + FillStyle + PointSymbol + SymbolEdgeColor + SymbolSkipPxDist + SymbolLabel + SymbolSize + SymbolLabelPosition + PlotCurveAppearance + AdditionalDataSources + RectAnnotation + StackCurve + StackPhaseColors + SummaryCase + SummaryAddress + Resampling + HorizontalAxisType + SummaryCaseX + SummaryAddressX + IsEnsembleCurve + PlotAxis + Axis + XAxis + SummaryCurveNameConfig + isTopZWithinCategory + DataSourceForRegression + SourceCurveSet + EnsembleStatisticsType + RegressionType + ForecastForward + ForecastBackward + ForecastUnit + PolynomialDegree + TimeRangeSelection + MinTimeSliderPosition + MaxTimeSliderPosition + ShowTimeSelectionInPlot + XRangeSelection + ValueRangeX + YRangeSelection + ValueRangeY + +ResInsightAnalysisModels - class RimEclipseCaseCollection + Reservoirs + CaseGroups + +ResInsightGeoMechCase - class RimGeoMechCase + Name + (A)CaseUserDescription + NameSetting + Id + (A)CaseId + FilePath + (A)CaseFileName + (A)GridFileName + DefaultFormationNames + TimeStepFilter + IntersectionViewCollection + GeoMechViews + CaseCohesion + FrctionAngleDeg + ElementPropertyFileNames + BiotCoefficientType + BiotFixedCoefficient + BiotResultAddress + InitialPermeabilityType + InitialPermeabilityFixed + InitialPermeabilityAddress + PermeabilityExponent + WaterDensityShearSlipIndicator + ContourMaps + MudWeightWindowParameters + +ResInsightGeoMechModels - class RimGeoMechModels + Cases + +ResInsightOilField - class RimOilField + AnalysisModels + GeoMechModels + WellPathCollection + CompletionTemplateCollection + SummaryCaseCollection + FormationNamesCollection + ObservedDataCollection + AnnotationCollection + EnsembleWellLogsCollection + FractureDefinitionCollection + SurfaceCollection + SeismicCollection + SeismicViewCollection + +ResInsightProject - class RimProject + DocumentFileName + ProjectFileVersionString + ReferencedExternalFiles + OilFields + ColorLegendCollection + WellPathImport + MainPlotCollection + LinkedViews + CalculationCollection + GridCalculationCollection + CommandObjects + MultiSnapshotDefinitions + TreeViewStates + TreeViewCurrentModelIndexPaths + PlotWindowTreeViewStates + PlotWindowTreeViewCurrentModelIndexPaths + show3DWindow + showPlotWindow + showPlotWindowOnTopOf3DWindow + tiled3DWindow + tiledPlotWindow + DialogData + Reservoirs + CaseGroups + TileMode3DWindow + TileModePlotWindow + +ResampleData - class RimcSummaryResampleData + TimeSteps + Values + +ReservoirCellResultStorage - class RimReservoirCellResultsStorage + ResultCacheFileName + ResultCacheEntries + +ReservoirView - class RimEclipseView + WindowController + ShowWindow + WindowGeometry + Id + (A)ViewId + NameConfig + CameraPosition + CameraPointOfInterest + PerspectiveProjection + GridZScale + BackgroundColor + (A)ViewBackgroundColor + MaximumFrameRate + CurrentTimeStep + MeshMode + SurfaceMode + ShowGridBox + DisableLighting + ShowZScale + ComparisonView + FontSize + AnnotationStrategy + AnnotationCountHint + UseCustomAnnotationStrategy + CrossSections + IntersectionResultDefColl + ReservoirSurfaceResultDefColl + GridCollection + OverlayInfoConfig + WellMeasurements + SurfaceInViewCollection + SeismicSectionCollection + RangeFilters + CustomEclipseCase + GridCellResult + GridCellEdgeResult + ElementVectorResult + FaultResultSettings + StimPlanColors + VirtualPerforationResult + WellCollection + FaultCollection + FaultReactivationModelCollection + AnnotationCollection + StreamlineCollection + PropertyFilters + ShowInactiveCells + ShowInvalidCells + AdditionalResultsForResultInfo + +ResultDefinition - class RimEclipseResultDefinition + IsChecked + ResultType + PorosityModelType + ResultVariable + FlowDiagSolution + TimeLapseBaseTimeStep + DifferenceCase + DivideByCellFaceArea + SelectedInjectorTracers + SelectedProducerTracers + SelectedSouringTracers + FlowTracerSelectionMode + PhaseSelection + ShowOnlyVisibleCategoriesInLegend + MSyncSelectedInjProd + MSyncSelectedProdInj + +ResultSlot - class RimEclipseCellColors + IsChecked + ResultType + PorosityModelType + ResultVariable + FlowDiagSolution + TimeLapseBaseTimeStep + DifferenceCase + DivideByCellFaceArea + SelectedInjectorTracers + SelectedProducerTracers + SelectedSouringTracers + FlowTracerSelectionMode + PhaseSelection + ShowOnlyVisibleCategoriesInLegend + MSyncSelectedInjProd + MSyncSelectedProdInj + LegendDefinition + ResultVarLegendDefinitionList + TernaryLegendDefinition + LegendDefinitionPtrField + +ResultStorageEntryInfo - class RimReservoirCellResultsStorageEntryInfo + ResultType + ResultName + TimeSteps + DaysSinceSimulationStart + FilePositionDataStart + +RftAddress - class RimDataSourceForRftPlt + SourceType + EclipseCase + SummaryCase + Ensemble + WellLogFile + ObservedFmuRftData + PressureDepthData + +RiaMemoryCleanup - class RiaMemoryCleanup + DataCase + ResultsToDelete + +RiaPreferences - class RiaPreferences + navigationPolicy + enableGrpcServer + defaultGrpcPort + scriptDirectory + scriptEditorExecutable + MaxScriptFoldersDepth + octaveExecutable + octaveShowHeaderInfoWhenExecutingScripts + pythonExecutable + pythonDebugInfo + ssihubAddress + defaultMeshModeType + defaultGridLineColors + defaultFaultGridLineColors + defaultWellLableColor + defaultViewerBackgroundColor + defaultScaleFactorZ + defaultSceneFontSizePt + defaultAnnotationFontSizePt + defaultWellLabelFontSizePt + defaultPlotFontSizePt + showLegendBackground + enableFaultsByDefault + showInfoBox + showGridBox + lastUsedProjectFileName + autocomputeDepth + loadAndShowSoil + holoLensDisableCertificateVerification + csvTextExportFieldSeparator + gridModelReader + readerSettings + dateFormat + timeFormat + useUndoRedo + plotTemplateFolders + MaxPlotTemplateFoldersDepth + defaultPlotTemplate + pageSize + pageOrientation + pageLeftMargin + pageTopMargin + pageRightMargin + pageBottomMargin + openExportedPdfInViewer + writeEchoInGrdeclFiles + useQtChartsPlotByDefault + gridCalculationExpressionFolder + summaryCalculationExpressionFolder + SurfaceImportResamplingDistance + MultiLateralWellPattern + guiTheme + summaryPreferences + geoMechPreferences + systemPreferences + +RiaPreferencesGeoMech - class RiaPreferencesGeoMech + geomechWIADefaultXML + geomechWIACommand + geomechFRMDefaultXML + geomechFRMCommand + keepTemporaryFile + waitForInputFileEdit + +RiaPreferencesSummary - class RiaPreferencesSummary + summaryRestartFilesShowImportDialog + summaryImportMode + gridImportMode + summaryEnsembleImportMode + defaultSummaryHistoryCurveStyle + defaultSummaryCurvesTextFilter + defaultSummaryPlot + CrossPlotAddressCombinations + defaultSummaryTemplates + createEnhancedSummaryDataFile_v01 + useEnhancedSummaryDataFile + createH5SummaryDataFile_v01 + createH5SummaryFileThreadCount + summaryReaderType_v01 + showSummaryTimeAsLongString + useMultipleThreadsWhenLoadingSummaryCases + DefaultNumberOfColumns + DefaultRowsPerPage + curveColorByPhase + appendHistoryVectorForDragDrop + historyCurveContrastColor + +RiaPreferencesSystem - class RiaPreferencesSystem + useShaders + showHud + appendClassNameToUiText + appendFieldKeywordToToolTipText + showViewIdInTree + showTestToolbar + includeFractureDebugInfoFile + holoLensExportFolder + showProjectChangedDialog + showProgressBar + showPdfExportDialog + gtestFilter + exportScalingFactor + eclipseReaderMode + +RiaRegressionTest - class RiaRegressionTest + workingFolder + folderContainingDiffTool + folderContainingGitTool + regressionTestFolder + showInteractiveDiffImages + useOpenMPForGeometryCreation + openReportInBrowser + testFilter + appendTestsAfterTestFilter + invalidateExternalFilePaths + forcePlotEngine + exportSnapshots3dViews + exportSnapshotsPlots + +RicCaseAndFileExportSettingsUi - class RicCaseAndFileExportSettingsUi + Folder + CaseToApply + +RicCellRangeUi - class RicCellRangeUi + Case + GridIndex + StartIndexI + StartIndexJ + StartIndexK + CellCountI + CellCountJ + CellCountK + +RicCreateDepthAdjustedLasFilesUi - class RicCreateDepthAdjustedLasFilesUi + ExportFolder + SelectedCase + SourceWell + WellLogFile + SelectedResultProperties + DestinationWells + +RicCreateEnsembleSurfaceUi - class RicCreateEnsembleSurfaceUi + Layers + AutoCreateEnsembleSurfaces + MinLayer + MaxLayer + +RicCreateEnsembleWellLogUi - class RicCreateEnsembleWellLogUi + AutoCreateEnsembleWellLogs + TimeStep + WellPathSource + WellPath + WellFilePath + SelectedProperties + +RicCreateMultipleWellPathLateralsUi - class RicCreateMultipleWellPathLateralsUi + SourceLaterals + TopLevelWellPath + Locations + +RicCreateRftPlotsFeatureUi - class RicCreateRftPlotsFeatureUi + SelectedWellNames + +RicDeleteItemExecData - class RicDeleteItemExecData + PathToField + Description + indexToObject + deletedObjectAsXml + +RicExportCarfinUi - class RicExportCarfinUi + CellRange + ExportFileName + CaseToApply + CellCountI + CellCountJ + CellCountK + MaxWellCount + +RicExportCompletionDataSettingsUi - class RicExportCompletionDataSettingsUi + Folder + CaseToApply + FileSplit + compdatExport + TimeStepIndex + IncludeMSW + UseLateralNTG + IncludePerforations + IncludeFishbones + IncludeFractures + TransScalingType + TransScalingTimeStep + TransScalingWBHPSource + TransScalingWBHP + ExcludeMainBoreForFishbones + ReportCompletionTypesSeparately + ExportDataSourceAsComment + ExportWelspec + CompletionWelspecAfterMainBore + UseCustomFileName + CustomFileName + +RicExportContourMapToTextUi - class RicExportContourMapToTextUi + ExportFileName + ExportLocalCoordinates + UndefinedValueLabel + ExcludeUndefinedValues + +RicExportEclipseInputGridUi - class RicExportEclipseSectorModelUi + ExportGrid + ExportGridFilename + ExportInLocalCoords + InvisibleCellActnum + GridBoxSelection + MinI + MinJ + MinK + MaxI + MaxJ + MaxK + ExportFaults + ExportFaultsFilename + RefinementCountI + RefinementCountJ + RefinementCountK + ExportParams + ExportParamsFilename + ExportMainKeywords + WriteEchoInGrdeclFiles + ExportFolder + +RicExportLgrUi - class RicExportLgrUi + ExportFolder + CaseToApply + TimeStepIndex + IncludePerforations + IncludeFractures + IncludeFishbones + CellCountI + CellCountJ + CellCountK + SplitType + +RicExportToLasFileObj - class RicExportToLasFileObj + tvdrkbOffset + +RicExportToLasFileResampleUi - class RicExportToLasFileResampleUi + ExportFolder + FilePrefix + CapitalizeFileName + CurveUnitConversion + ActivateResample + ResampleInterval + ExportTvdrkb + tvdrkbOffsets + +RicExportWellPathsUi - class RicExportWellPathsUi + ExportFolder + MdStepSize + +RicGridCalculator - class RicGridCalculatorUi + CurrentCalculation + NewCalculation + DeleteCalculation + ImportCalculations + ExportCalculations + +RicHoloLensCreateSessionUi - class RicHoloLensCreateSessionUi + SessionName + SessionPinCode + ServerSettings + +RicHoloLensExportToFolderUi - class RicHoloLensExportToFolderUi + ViewForExport + ExportFolder + +RicHoloLensServerSettings - class RicHoloLensServerSettings + ServerAddress + +RicLinkVisibleViewsFeatureUi - class RicLinkVisibleViewsFeatureUi + MasterView + +RicPasteAsciiDataToSummaryPlotFeatureUi - class RicPasteAsciiDataToSummaryPlotFeatureUi + PlotTitle + CurvePrefix + DecimalSeparator + DateFormat + TimeFormat + UseCustomDateFormat + CustomDateTimeFormat + LineStyle + Symbol + SymbolSkipDinstance + CellSeparator + TimeColumnName + +RicSaturationPressureUi - class RicSaturationPressureUi + CaseToApply + TimeStep + +RicSaveEclipseInputVisibleCellsUi - class RicSaveEclipseInputVisibleCellsUi + ExportFilename + ExportKeyword + VisibleActiveCellsValue + HiddenActiveCellsValue + InactiveCellsValue + WriteEchoInGrdeclFiles + +RicSaveMultiPlotTemplateFeatureSettings - class RicSaveMultiPlotTemplateFeatureSettings + FilePath + Name + PersistObjectNameWells + PersistObjectNameGroups + PersistObjectNameRegions + +RicSelectCaseOrEnsembleUi - class RicSelectCaseOrEnsembleUi + SelectedSummaryCase + SelectedEnsemble + +RicSelectPlotTemplateUi - class RicSelectPlotTemplateUi + SelectedPlotTemplates + +RicSelectSummaryPlotUI - class RicSelectSummaryPlotUI + SelectedSummaryPlot + CreateNewPlot + NewViewName + +RicSelectViewUI - class RicSelectViewUI + MasterView + CreateNewView + NewViewName + +RicSummaryAddressSelection - class RiuSummaryVectorSelectionUi + SummaryCases + CurrentSummaryCategory + SelectedSummaryCategories + FieldVectors + FieldCalculationIds + Aquifers + AquiferVectors + AquifierCalculationIds + NetworkNames + NetworkVectors + NetworkCalculationIds + MiscVectors + MiscCalculationIds + Regions + RegionsVectors + RegionCalculationIds + Region2RegionRegions + Region2RegionVectors + Region2RegionCalculationIds + WellGroupWellGroupNames + WellGroupVectors + WellGroupCalculationIds + WellWellName + WellVectors + WellCalculationIds + WellCompletionWellName + WellCompletionIjk + WellCompletionVectors + WellCompletionCalculationIds + WellCompletionLgrLgrName + WellCompletionLgrWellName + WellCompletionLgrIjk + WellCompletionLgrVectors + WellCompletionLgrCalculationIds + WellLgrLgrName + WellLgrWellName + WellLgrVectors + WellLgrCalculationIds + WellSegmentWellName + WellSegmentNumber + WellSegmentVectors + WellSegmentCalculationIds + BlockIjk + BlockVectors + BlockCalculationIds + BlockLgrLgrName + BlockLgrIjk + BlockLgrVectors + BlockLgrCalculationIds + ImportedVectors + ImportedCalculationIds + +RicSummaryCurveCalculator - class RicSummaryCurveCalculatorUi + CurrentCalculation + NewCalculation + DeleteCalculation + ImportCalculations + ExportCalculations + +RicSummaryCurveCreator - class RicSummaryPlotEditorUi + TargetPlot + UseAutoAppearanceAssignment + AppearanceApplyButton + CaseAppearanceType + VariableAppearanceType + WellAppearanceType + GroupAppearanceType + RegionAppearanceType + ApplySelection + Close + OK + SummaryCurveNameConfig + +RicWellPathsUnitSystemSettingsUi - class RicWellPathsUnitSystemSettingsUi + UnitSystem + +RifReaderSettings - class RifReaderSettings + importFaults + importSimulationNNCs + includeInactiveCellsInFaultGeometry + importAdvancedMswData + useResultIndexFile + skipWellData + includeFileAbsolutePathPrefix + importSummaryData + +Rim3dWellLogCurveCollection - class Rim3dWellLogCurveCollection + Show3dWellLogCurves + PlaneWidthScaling + Show3dWellLogGrid + Show3dWellLogBackground + ArrayOf3dWellLogCurves + +Rim3dWellLogExtractionCurve - class Rim3dWellLogExtractionCurve + Show3dWellLogCurve + MinCurveValue + MaxCurveValue + DrawPlane + CurveColor + CurveCase + CurveTimeStep + GeomPartId + CurveEclipseResult + CurveGeomechResult + NameConfig + +Rim3dWellLogFileCurve - class Rim3dWellLogFileCurve + Show3dWellLogCurve + MinCurveValue + MaxCurveValue + DrawPlane + CurveColor + CurveWellLogChannel + WellLogFile + NameConfig + +Rim3dWellLogRftCurve - class Rim3dWellLogRftCurve + Show3dWellLogCurve + MinCurveValue + MaxCurveValue + DrawPlane + CurveColor + eclipseResultCase + timeStep + wellLogChannelName + NameConfig + +RimAnnotationCollection - class RimAnnotationCollection + IsActive + TextAnnotations + ReachCircleAnnotations + UserDefinedPolylineAnnotations + PolylineFromFileAnnotations + +RimAnnotationCollectionBase - class RimAnnotationCollectionBase + IsActive + TextAnnotations + +RimAnnotationGroupCollection - class RimAnnotationGroupCollection + IsActive + Annotations + +RimAnnotationLineAppearance - class RimAnnotationLineAppearance + LineFieldsHidden + Color + Thickness + +RimAnnotationTextAppearance - class RimAnnotationTextAppearance + FontSize + FontColor + BackgroundColor + AnchorLineColor + +RimBinaryExportSettings - class RimBinaryExportSettings + Filename + EclipseKeyword + UndefinedValue + WriteEchoInGrdeclFiles + +RimCaseCollection - class RimCaseCollection + Reservoirs + +RimCellFilterCollection - class RimCellFilterCollection + Active + CellFilters + RangeFilters + +RimCommandExecuteScript - class RimCommandExecuteScript + Name + ScriptText + IsEnabled + +RimCommandIssueFieldChanged - class RimCommandIssueFieldChanged + CommandName + ObjectName + FieldName + FieldValueToApply + +RimCommandObject - class RimCommandObject + +RimCommandRouter - class RimCommandRouter + +RimContourMapView - class RimEclipseContourMapView + WindowController + ShowWindow + WindowGeometry + Id + (A)ViewId + NameConfig + CameraPosition + CameraPointOfInterest + PerspectiveProjection + GridZScale + BackgroundColor + (A)ViewBackgroundColor + MaximumFrameRate + CurrentTimeStep + MeshMode + SurfaceMode + ShowGridBox + DisableLighting + ShowZScale + ComparisonView + FontSize + AnnotationStrategy + AnnotationCountHint + UseCustomAnnotationStrategy + CrossSections + IntersectionResultDefColl + ReservoirSurfaceResultDefColl + GridCollection + OverlayInfoConfig + WellMeasurements + SurfaceInViewCollection + SeismicSectionCollection + RangeFilters + CustomEclipseCase + GridCellResult + GridCellEdgeResult + ElementVectorResult + FaultResultSettings + StimPlanColors + VirtualPerforationResult + WellCollection + FaultCollection + FaultReactivationModelCollection + AnnotationCollection + StreamlineCollection + PropertyFilters + ShowInactiveCells + ShowInvalidCells + AdditionalResultsForResultInfo + ContourMapProjection + ShowAxisLines + ShowScaleLegend + +RimCsvUserData - class RimCsvUserData + ShortName + NameSetting + ShowSubNodesInTree + AutoShortyName + SummaryHeaderFilename + Id + (A)CaseId + UseCustomIdentifier + SummaryType + IdentifierName + ParseOptions + +RimCustomObjectiveFunction - class RimCustomObjectiveFunction + FunctionTitle + CustomFunctionTitle + Weights + ObjectiveFunctions + +RimCustomObjectiveFunctionCollection - class RimCustomObjectiveFunctionCollection + ObjectiveFunctions + +RimCustomObjectiveFunctionWeight - class RimCustomObjectiveFunctionWeight + WeightTitle + ObjectiveSummaryAddress + WeightValue + ObjectiveFunction + +RimDerivedEnsembleCase - class RimDerivedSummaryCase + ShortName + NameSetting + ShowSubNodesInTree + AutoShortyName + SummaryHeaderFilename + Id + (A)CaseId + SummaryCase1 + Operator + SummaryCase2 + UseFixedTimeStep + FixedTimeStepIndex + InUse + +RimDerivedEnsembleCaseCollection - class RimDerivedEnsembleCaseCollection + SummaryCases + SummaryCollectionName + CreateAutoName + NameCount + IsEnsemble + Id + (A)EnsembleId + Ensemble1 + Ensemble2 + Operator + CaseCount + MatchOnParameters + UseFixedTimeStep + FixedTimeStepIndex + +RimDialogData - class RimDialogData + ExportCarfin + ExportCompletionData + MultipleFractionsData + HoloLenseExportToFolderData + ExportwellPathsData + ExportLgr + ExportSectorModel + MockModelSettings + CreateEnsembleSurfaceUi + CreateEnsembleWellLogUi + +RimEclipseContourMapProjection - class RimEclipseContourMapProjection + Name + IsChecked + SampleSpacing + ResultAggregation + ContourLines + ContourLabels + SmoothContourLines + WeightByParameter + WeightingResult + +RimEclipseResultAddressCollection - class RimEclipseResultAddressCollection + Name + Addresses + ResultType + +RimElementVectorResult - class RimElementVectorResult + LegendDefinition + ShowOil + ShowGas + ShowWater + ShowResult + VectorView + VectorSurfaceCrossingLocation + ShowVectorI + ShowVectorJ + ShowVectorK + ShowNncData + Threshold + VectorColor + UniformVectorColor + SizeScale + +RimEllipseFractureTemplate - class RimEllipseFractureTemplate + Id + UserDescription + UnitSystem + Orientation + UserDefinedPerforationLength + AzimuthAngle + SkinFactor + PerforationLength + PerforationEfficiency + WellDiameter + ConductivityType + WellPathDepthAtFracture + FractureContainmentField + NonDarcyFlowType + UserDefinedDFactor + FractureWidthType + FractureWidth + BetaFactorType + InertialCoefficient + PermeabilityType + RelativePermeability + EffectivePermeability + RelativeGasDensity + GasViscosity + HeightScaleFactor + WidthScaleFactor + DFactorScaleFactor + ConductivityFactor + HalfLength + Height + Width + Permeability + +RimEnsembleCurveFilter - class RimEnsembleCurveFilter + FilterTitle + Active + FilterMode + EnsembleParameter + ObjectiveSummaryAddress + ObjectiveFunction + CustomObjectiveFunction + MinValue + MaxValue + Categories + +RimEnsembleCurveFilterCollection - class RimEnsembleCurveFilterCollection + Active + CurveFilters + NewEnsembleFilter + +RimEnsembleCurveSet - class RimEnsembleCurveSet + EnsembleCurveSet + IsActive + SummaryGroup + SummaryAddress + Resampling + HorizontalAxisType + XAddressSelector + ColorMode + Color + MainEnsembleColor + ColorTransparency + EnsembleParameter + EnsembleParameterSorting + UseCustomAppearance + LineStyle + PointSymbol + SymbolSize + StatisticsUseCustomAppearance + StatisticsLineStyle + StatisticsPointSymbol + StatisticsSymbolSize + ObjectiveSummaryAddress + CustomObjectiveFunction + ShowObjectiveFunctionFormula + MinDateRange + MinTimeSliderPosition + MaxDateRange + MaxTimeSliderPosition + TimeStepFilter + TimeSteps + PlotAxis + Axis + LegendConfig + CurveFilters + CustomObjectiveFunctions + ObjectiveFunction + Statistics + UserDefinedName + AutoName + SummaryAddressNameTools + +RimEnsembleCurveSetCollection - class RimEnsembleCurveSetCollection + EnsembleCurveSets + IsActive + +RimEnsembleStatistics - class RimEnsembleStatistics + Active + ShowStatisticsCurveLegends + HideEnsembleCurves + ShowEnsembleCurves + BasedOnFilteredCases + ShowP10Curve + ShowP50Curve + ShowP90Curve + ShowMeanCurve + ShowCurveLabels + IncludeIncompleteCurves + CrossPlotCurvesBinCount + CrossPlotCurvesStatisticsRealizationCountThresholdPerBin + Color + +RimEnsembleWellLogCurveSet - class RimEnsembleWellLogCurveSet + EnsembleCurveSet + IsActive + EnsembleWellLogs + WellLogChannelName + FilterEnsembleCurveSet + DepthEqualization + ColorMode + Color + Statistics + UserDefinedName + AutoName + PlotCurveAppearance + +RimEquilibriumAxisAnnotation - class RimEquilibriumAxisAnnotation + Active + Name + Value + RangeStart + RangeEnd + PenStyle + AnnotationType + Associated3DCase + m_equilNum + +RimExportInputSettings - class RimExportInputSettings + Filename + Keyword + WriteEchoInGrdeclFiles + +RimFaultResultSlot - class RimEclipseFaultColors + ShowCustomFaultResult + CustomResultSlot + +RimFractureExportSettings - class RimFractureExportSettings + Filename + CaseToApply + +RimGeoMechContourMapProjection - class RimGeoMechContourMapProjection + Name + IsChecked + SampleSpacing + ResultAggregation + ContourLines + ContourLabels + SmoothContourLines + LimitToPorRegion + VerticalLimit + PaddingAroundPorRegion + +RimGeoMechContourMapView - class RimGeoMechContourMapView + WindowController + ShowWindow + WindowGeometry + Id + (A)ViewId + NameConfig + CameraPosition + CameraPointOfInterest + PerspectiveProjection + GridZScale + BackgroundColor + (A)ViewBackgroundColor + MaximumFrameRate + CurrentTimeStep + MeshMode + SurfaceMode + ShowGridBox + DisableLighting + ShowZScale + ComparisonView + FontSize + AnnotationStrategy + AnnotationCountHint + UseCustomAnnotationStrategy + CrossSections + IntersectionResultDefColl + ReservoirSurfaceResultDefColl + GridCollection + OverlayInfoConfig + WellMeasurements + SurfaceInViewCollection + SeismicSectionCollection + RangeFilters + GridCellResult + TensorResults + FaultReactivationResult + PropertyFilters + Parts + ShowDisplacement + DisplacementScaling + ContourMapProjection + ShowAxisLines + ShowScaleLegend + +RimGeoMechFaultReactivationResult - class RimGeoMechFaultReactivationResult + DistanceFromFault + FaultNormal + FaultTopPosition + FaultBottomPosition + FaceAWellPath + FaceBWellPath + FaceAWellPathPartIndex + FaceBWellPathPartIndex + +RimGridCalculation - class RimGridCalculation + Description + Expression + Unit + Variables + Id + VisibleCellView + DefaultValueType + DefaultValue + DestinationCase + AllDestinationCase + DefaultPropertyVariableName + SelectedTimeSteps + +RimGridCalculationCollection - class RimGridCalculationCollection + Calculations + +RimGridCalculationVariable - class RimGridCalculationVariable + VariableName + ResultType + ResultVariable + EclipseGridCase + TimeStep + +RimGridCrossPlot - class RimGridCrossPlot + WindowController + ShowWindow + WindowGeometry + Id + (A)ViewId + ShowPlotTitle + ShowTrackLegends + TrackLegendsHorizontal + LegendItemsClickable + TitleFontSize + LegendDeltaFontSize + LegendPosition + RowSpan + ColSpan + ShowInfoBox + NameConfig + xAxisProperties + yAxisProperties + CrossPlotCurve + +RimGridCrossPlotCollection - class RimGridCrossPlotCollection + GridCrossPlots + +RimGridCrossPlotCurveSetNameConfig - class RimGridCrossPlotDataSetNameConfig + CustomCurveName + AddCaseName + AddAxisVariables + AddTimeStep + AddGrouping + +RimGridCrossPlotNameConfig - class RimGridCrossPlotNameConfig + CustomCurveName + AddDataSetNames + +RimIdenticalGridCaseGroup - class RimIdenticalGridCaseGroup + UserDescription + GroupId + StatisticsCaseCollection + CaseCollection + +RimInputProperty - class RimEclipseInputProperty + ResultName + EclipseKeyword + FileName + +RimInputPropertyCollection - class RimEclipseInputPropertyCollection + InputProperties + +RimInputReservoir - class RimEclipseInputCase + Name + (A)CaseUserDescription + NameSetting + Id + (A)CaseId + FilePath + (A)CaseFileName + (A)GridFileName + DefaultFormationNames + TimeStepFilter + IntersectionViewCollection + ReservoirViews + MatrixModelResults + FractureModelResults + FlipXAxis + FlipYAxis + ContourMaps + InputPropertyCollection + AdditionalFileNamesProxy + +RimIntersectionResultsDefinitionCollection - class RimIntersectionResultsDefinitionCollection + isActive + IntersectionResultDefinitions + +RimMeasurement - class RimMeasurement + +RimMswCompletionParameters - class RimMswCompletionParameters + RefMDType + RefMD + CustomValuesForLateral + LinerDiameter + RoughnessFactor + PressureDrop + LengthAndDepth + EnforceMaxSegmentLength + MaxSegmentLength + +RimMudWeightWindowParameters - class RimMudWeightWindowParameters + WellDeviationSourceType + WellDeviationFixed + WellDeviationAddress + WellAzimuthSourceType + WellAzimuthFixed + WellAzimuthAddress + UCSSourceType + UCSFixed + UCSAddress + PoissonsRatioSourceType + PoissonsRatioFixed + PoissonsRatioAddress + K0_FGSourceType + K0_FGFixed + K0_FGAddress + obg0SourceType + obg0Fixed + obg0Address + AirGap + SHMultiplier + UpperLimitType + LowerLimitType + FractureGradientCalculationType + PorePressureNonReservoirSource + UserPPNonReservoir + PPNonReservoirAddress + ReferenceLayer + +RimMultiPlotCollection - class RimMultiPlotCollection + MultiPlots + +RimMultipleEclipseResults - class RimMultipleEclipseResults + IsChecked + showCenterCoordinates + showCornerCoordinates + SelectedProperties + +RimMultipleLocations - class RimMultipleLocations + LocationMode + RangeStart + RangeEnd + Spacing + RangeValveCount + Locations + +RimMultipleValveLocations - class RimMultipleValveLocations + LocationMode + RangeStart + RangeEnd + ValveSpacing + RangeValveCount + LocationOfValves + +RimNonDarcyPerforationParameters - class RimNonDarcyPerforationParameters + NonDarcyFlowType + UserDefinedDFactor + GridPermeabilityScalingFactor + WellRadius + RelativeGasDensity + GasViscosity + InertialCoefficientBeta0 + PermeabilityScalingFactor + PorosityScalingFactor + +RimObjectiveFunction - class RimObjectiveFunction + FunctionType + NormalizeByNumberOfObservations + NormalizeByNumberOfVectors + ErrorEstimatePercentage + UseSquaredError + +RimObservedEclipseUserData - class RimObservedEclipseUserData + ShortName + NameSetting + ShowSubNodesInTree + AutoShortyName + SummaryHeaderFilename + Id + (A)CaseId + UseCustomIdentifier + SummaryType + IdentifierName + +RimOilFieldEntry - class RimOilFieldEntry + OilFieldName + EdmId + Selected + wellsFilePath + Wells + +RimOilRegionEntry - class RimOilRegionEntry + OilRegionEntry + Fields + Selected + +RimPlotAxisAnnotation - class RimPlotAxisAnnotation + Active + Name + Value + RangeStart + RangeEnd + PenStyle + +RimPlotCellFilterCollection - class RimPlotCellFilterCollection + Name + IsChecked + FilterMode + CellFilters + +RimPlotCellPropertyFilter - class RimPlotCellPropertyFilter + Name + IsChecked + FilterMode + ResultDefinition + LowerBound + UpperBound + +RimPlotRectAnnotation - class RimPlotRectAnnotation + Name + IsChecked + MinX + MaxX + MinY + MaxY + Color + Transparency + Text + +RimPolylineAppearance - class RimPolylineAppearance + LineFieldsHidden + Color + Thickness + SphereFieldsHidden + SphereColor + SphereRadiusFactor + +RimPolylinesAnnotationInView - class RimPolylinesAnnotationInView + IsActive + SourceAnnotation + +RimPolylinesFromFileAnnotationInView - class RimPolylinesFromFileAnnotationInView + IsActive + SourceAnnotation + +RimProcess - class RimProcess + Command + Description + ID + +RimReachCircleAnnotation - class RimReachCircleAnnotation + IsActive + CenterPointXyd + Radius + Name + Appearance + +RimReachCircleAnnotationInView - class RimReachCircleAnnotationInView + IsActive + SourceAnnotation + +RimResultSelectionUi - class RimResultSelectionUi + Case + Result + +RimRftCase - class RimRftCase + RftFilePath + DataDeckFilePath + +RimRftTopologyCurve - class RimRftTopologyCurve + Show + AutoCheckStateBasedOnCurveData + CurveName + TemplateText + CurveNamingMethod + LegendDescription + AutoName + ShowLegend + ShowErrorBars + Color + FillColor + Thickness + CurveInterpolation + LineStyle + FillStyle + PointSymbol + SymbolEdgeColor + SymbolSkipPxDist + SymbolLabel + SymbolSize + SymbolLabelPosition + PlotCurveAppearance + AdditionalDataSources + RectAnnotation + StackCurve + StackPhaseColors + SummaryCase + TimeStep + WellName + SegmentBranchIndex + SegmentBranchType + CurveType + +RimRoffCase - class RimRoffCase + Name + (A)CaseUserDescription + NameSetting + Id + (A)CaseId + FilePath + (A)CaseFileName + (A)GridFileName + DefaultFormationNames + TimeStepFilter + IntersectionViewCollection + ReservoirViews + MatrixModelResults + FractureModelResults + FlipXAxis + FlipYAxis + ContourMaps + InputPropertyCollection + +RimSEGYConvertOptions - class RimSEGYConvertOptions + InputFilename + OutputFilename + SampleStartOverride + SampleUnit + HeaderFilename + +RimSaturationPressurePlot - class RimSaturationPressurePlot + WindowController + ShowWindow + WindowGeometry + Id + (A)ViewId + ShowPlotTitle + ShowTrackLegends + TrackLegendsHorizontal + LegendItemsClickable + TitleFontSize + LegendDeltaFontSize + LegendPosition + RowSpan + ColSpan + ShowInfoBox + NameConfig + xAxisProperties + yAxisProperties + CrossPlotCurve + +RimSaturationPressurePlotCollection - class RimSaturationPressurePlotCollection + SaturationPressurePlots + +RimSeismicView - class RimSeismicView + WindowController + ShowWindow + WindowGeometry + Id + (A)ViewId + NameConfig + CameraPosition + CameraPointOfInterest + PerspectiveProjection + GridZScale + BackgroundColor + (A)ViewBackgroundColor + MaximumFrameRate + CurrentTimeStep + MeshMode + SurfaceMode + ShowGridBox + DisableLighting + ShowZScale + ComparisonView + FontSize + AnnotationStrategy + AnnotationCountHint + UseCustomAnnotationStrategy + SeismicData + SurfaceInViewCollection + SeismicSectionCollection + AnnotationCollection + OverlayInfoConfig + +RimStatisticalCalculation - class RimEclipseStatisticsCase + Name + (A)CaseUserDescription + NameSetting + Id + (A)CaseId + FilePath + (A)CaseFileName + (A)GridFileName + DefaultFormationNames + TimeStepFilter + IntersectionViewCollection + ReservoirViews + MatrixModelResults + FractureModelResults + FlipXAxis + FlipYAxis + ContourMaps + InputPropertyCollection + DataSourceForStatistics + GridCalculation + GridCalculationFilterView + SelectedTimeSteps + ResultType + PorosityModel + DynamicPropertiesToCalculate + StaticPropertiesToCalculate + GeneratedPropertiesToCalculate + InputPropertiesToCalculate + FractureDynamicPropertiesToCalculate + FractureStaticPropertiesToCalculate + FractureGeneratedPropertiesToCalculate + FractureInputPropertiesToCalculate + CalculatePercentiles + PercentileCalculationType + LowPercentile + MidPercentile + HighPercentile + WellDataSourceCase + UseZeroAsInactiveCellValue + +RimStatisticalCollection - class RimEclipseStatisticsCaseCollection + Reservoirs + +RimStimPlanColors - class RimStimPlanColors + IsChecked + ResultName + DefaultColor + LegendConfigurations + ShowStimPlanMesh + StimPlanCellVizMode + +RimStimPlanFractureTemplate - class RimStimPlanFractureTemplate + Id + UserDescription + UnitSystem + Orientation + UserDefinedPerforationLength + AzimuthAngle + SkinFactor + PerforationLength + PerforationEfficiency + WellDiameter + ConductivityType + WellPathDepthAtFracture + FractureContainmentField + NonDarcyFlowType + UserDefinedDFactor + FractureWidthType + FractureWidth + BetaFactorType + InertialCoefficient + PermeabilityType + RelativePermeability + EffectivePermeability + RelativeGasDensity + GasViscosity + HeightScaleFactor + WidthScaleFactor + DFactorScaleFactor + ConductivityFactor + StimPlanFileName + UserDefinedWellPathDepthAtFracture + BorderPolygonResultName + ActiveTimeStepIndex + ConductivityResultName + ShowStimPlanMesh + +RimStimPlanLegendConfig - class RimStimPlanLegendConfig + Name + Legend + +RimSummaryAddressCollection - class RimSummaryAddressCollection + Name + ContentsType + SummaryAddresses + AddressSubfolders + CaseId + EnsembleId + +RimSummaryAddressSelector - class RimSummaryAddressSelector + SummaryCase + SummaryCaseCollection + SummaryAddress + PlotAxisProperties + Resampling + +RimSummaryCalculation - class RimSummaryCalculation + Description + Expression + Unit + Variables + Id + DistributeToOtherItems + DistributeToAllCases + +RimSummaryCalculationCollection - class RimSummaryCalculationCollection + Calculations + +RimSummaryCalculationVariable - class RimSummaryCalculationVariable + VariableName + SummaryCase + SummaryAddress + +RimSummaryCurveCollection - class RimSummaryCurveCollection + CollectionCurves + IsActive + +RimSummaryCurveCollectionModifier - class RimSummaryPlotSourceStepping + StepDimension + CurveCase + IncludeEnsembleCasesForCaseStepping + WellName + GroupName + NetworkName + Region + VectorName + CellBlock + Segment + Completion + Aquifer + Ensemble + Placeholder + AutoUpdateAppearance + +RimSummaryMultiPlotCollection - class RimSummaryMultiPlotCollection + MultiSummaryPlots + +RimSummaryPlotManager - class RimSummaryPlotManager + SummaryPlot + FilterText + AddressCandidates + SelectedDataSources + IncludeDiffCurves + PushButtonReplace + PushButtonNewPlot + PushButtonAppend + IndividualPlotPerObject + IndividualPlotPerVector + IndividualPlotPerDataSource + CreateMultiPlot + +RimSummaryTable - class RimSummaryTable + WindowController + ShowWindow + WindowGeometry + Id + (A)ViewId + ShowPlotTitle + ShowTrackLegends + TrackLegendsHorizontal + LegendItemsClickable + TitleFontSize + LegendDeltaFontSize + LegendPosition + TableName + AutomaticTableName + SummaryCase + Vector + Categories + ResamplingSelection + ThresholdValue + ExcludedTableRows + ShowValueLabels + MaxTimeLabelCount + AxisTitleFontSize + AxisLabelFontSize + ValueLabelFontSize + LegendConfig + MappingType + RangeType + +RimSummaryTableCollection - class RimSummaryTableCollection + SummaryTables + +RimSurfaceIntersectionBand - class RimSurfaceIntersectionBand + IsChecked + LineAppearance + BandColor + BandOpacity + BandPolygonOffsetUnit + Surfaces + NameProxy + +RimSurfaceIntersectionCollection - class RimSurfaceIntersectionCollection + IsChecked + IntersectionBands + IntersectionCurves + +RimSurfaceIntersectionCurve - class RimSurfaceIntersectionCurve + IsChecked + LineAppearance + Surface1 + NameProxy + +RimTensorResults - class RimTensorResults + LegendDefinition + ResultVariable + ShowTensors + Principal1 + Principal2 + Principal3 + Threshold + VectorColor + ScaleMethod + SizeScale + RangeType + +RimTernaryLegendConfig - class RimTernaryLegendConfig + ShowTernaryLegend + Precision + RangeType + ternaryRangeSummary + UserDefinedMaxSoil + UserDefinedMinSoil + UserDefinedMaxSgas + UserDefinedMinSgas + UserDefinedMaxSwat + UserDefinedMinSwat + +RimTextAnnotation - class RimTextAnnotation + AnchorPointXyd + LabelPointXyd + Text + IsActive + TextAppearance + +RimTextAnnotationInView - class RimTextAnnotationInView + IsActive + SourceAnnotation + +RimThermalFractureTemplate - class RimThermalFractureTemplate + Id + UserDescription + UnitSystem + Orientation + UserDefinedPerforationLength + AzimuthAngle + SkinFactor + PerforationLength + PerforationEfficiency + WellDiameter + ConductivityType + WellPathDepthAtFracture + FractureContainmentField + NonDarcyFlowType + UserDefinedDFactor + FractureWidthType + FractureWidth + BetaFactorType + InertialCoefficient + PermeabilityType + RelativePermeability + EffectivePermeability + RelativeGasDensity + GasViscosity + HeightScaleFactor + WidthScaleFactor + DFactorScaleFactor + ConductivityFactor + StimPlanFileName + UserDefinedWellPathDepthAtFracture + BorderPolygonResultName + ActiveTimeStepIndex + ConductivityResultName + FilterCakePressureDrop + +RimTimeAxisAnnotation - class RimTimeAxisAnnotation + Active + Name + Value + RangeStart + RangeEnd + PenStyle + Color + +RimTimeStepFilter - class RimTimeStepFilter + FilterType + FirstTimeStep + LastTimeStep + Interval + DateFormat + TimeStepIndicesToImport + OnlyLastFrame + +RimUserDefinedIndexFilter - class RimUserDefinedIndexFilter + UserDescription + Active + Case + FilterType + GridIndex + PropagateToSubGrids + IndividualCellIndexes + +RimUserDefinedPolylinesAnnotationInView - class RimUserDefinedPolylinesAnnotationInView + IsActive + SourceAnnotation + +RimVfpPlotCollection - class RimVfpPlotCollection + VfpPlots + +RimViewLinkerCollection - class RimViewLinkerCollection + Active + ViewLinkers + +RimViewNameConfig - class RimViewNameConfig + CustomCurveName + AddCaseName + AddAggregationType + AddProperty + AddSampleSpacing + +RimVirtualPerforationResults - class RimVirtualPerforationResults + ShowConnectionFactors + ShowClosedConnections + GeometryScaleFactor + LegendDefinition + +RimWellAllocationOverTimePlot - class RimWellAllocationOverTimePlot + WindowController + ShowWindow + WindowGeometry + Id + (A)ViewId + ShowPlotTitle + ShowTrackLegends + TrackLegendsHorizontal + LegendItemsClickable + TitleFontSize + LegendDeltaFontSize + LegendPosition + RowSpan + ColSpan + PlotDescription + CurveCase + WellName + FromTimeStep + ToTimeStep + TimeStepRangeFilterMode + TimeStepCount + ExcludeTimeSteps + FlowDiagSolution + FlowValueType + GroupSmallContributions + SmallContributionsThreshold + AxisTitleFontSize + AxisValueFontSize + +RimWellConnectivityTable - class RimWellConnectivityTable + WindowController + ShowWindow + WindowGeometry + Id + (A)ViewId + ShowPlotTitle + ShowTrackLegends + TrackLegendsHorizontal + LegendItemsClickable + TitleFontSize + LegendDeltaFontSize + LegendPosition + CurveCase + VisibleCellView + ViewFilterType + FlowDiagSolution + TimeStepSelectopn + SelectProducersAndInjectorsForTimeSteps + ThresholdValue + TimeSampleValueType + TimeStep + TimeRangeValueType + FromTimeStep + ToTimeStep + TimeStepRangeFilterMode + TimeStepCount + ExcludeTimeSteps + SelectedProducerTracers + SelectedInjectorTracers + SyncSelectedProdInj + SyncSelectedInjProd + ShowValueLabels + AxisTitleFontSize + AxisLabelFontSize + ValueLabelFontSize + LegendConfig + MappingType + RangeType + +RimWellIASettings - class RimWellIASettings + Name + IsChecked + GeomechCase + BaseDir + StartMeasuredDepth + EndMeasuredDepth + BufferXY + ModelingParameters + TimeStepParameters + showBox + startDate + boxValid + +RimWellIASettingsCollection - class RimWellIASettingsCollection + WellIASettings + +RimWellLogExtractionCurve - class RimWellLogExtractionCurve + Show + AutoCheckStateBasedOnCurveData + CurveName + TemplateText + CurveNamingMethod + LegendDescription + AutoName + ShowLegend + ShowErrorBars + Color + FillColor + Thickness + CurveInterpolation + LineStyle + FillStyle + PointSymbol + SymbolEdgeColor + SymbolSkipPxDist + SymbolLabel + SymbolSize + SymbolLabelPosition + PlotCurveAppearance + AdditionalDataSources + RectAnnotation + StackCurve + StackPhaseColors + TrajectoryType + CurveWellPath + ReferenceWellPath + SimulationWellName + BranchDetection + Branch + CurveCase + CurveEclipseResult + CurveGeomechResult + CurveTimeStep + GeomPartId + AddCaseNameToCurveName + AddPropertyToCurveName + AddWellNameToCurveName + AddTimestepToCurveName + AddDateToCurveName + +RimWellLogExtractionCurveNameConfig - class RimWellLogExtractionCurveNameConfig + CustomCurveName + AddCaseName + AddProperty + AddWellName + AddTimeStep + AddDate + +RimWellLogFileCurveNameConfig - class RimWellLogLasFileCurveNameConfig + CustomCurveName + +RimWellLogLasFileCurveNameConfig - class RimWellLogLasFileCurveNameConfig + CustomCurveName + +RimWellLogPlotNameConfig - class RimWellLogPlotNameConfig + CustomCurveName + +RimWellLogRftCurveNameConfig - class RimWellLogRftCurveNameConfig + CustomCurveName + +RimWellLogWbsCurve - class RimWellLogWbsCurve + Show + AutoCheckStateBasedOnCurveData + CurveName + TemplateText + CurveNamingMethod + LegendDescription + AutoName + ShowLegend + ShowErrorBars + Color + FillColor + Thickness + CurveInterpolation + LineStyle + FillStyle + PointSymbol + SymbolEdgeColor + SymbolSkipPxDist + SymbolLabel + SymbolSize + SymbolLabelPosition + PlotCurveAppearance + AdditionalDataSources + RectAnnotation + StackCurve + StackPhaseColors + TrajectoryType + CurveWellPath + ReferenceWellPath + SimulationWellName + BranchDetection + Branch + CurveCase + CurveEclipseResult + CurveGeomechResult + CurveTimeStep + GeomPartId + AddCaseNameToCurveName + AddPropertyToCurveName + AddWellNameToCurveName + AddTimestepToCurveName + AddDateToCurveName + SmoothCurve + SmoothingThreshold + MaximumCurvePointInterval + +RimWellPathEntry - class RimWellPathEntry + Name + Selected + WellPathType + surveyType + requestUrl + wellPathFilePath + +RimWellPathImport - class RimWellPathImport + WellTypeSurvey + WellTypePlans + UtmMode + UtmNorth + UtmSouth + UtmEast + UtmWest + Regions + +RimWellPathTieIn - class RimWellPathTieIn + ParentWellPath + ChildWellPath + TieInMeasuredDepth + AddValveAtConnection + Valve + +RiuCreateMultipleFractionsUi - class RiuCreateMultipleFractionsUi + SourceCase + MinDistanceFromWellTd + MaxFracturesPerWell + Options + FractureCreationSummary + +RiuMultipleFractionsOptions - class RicCreateMultipleFracturesOptionItemUi + TopKLayer + BaseKLayer + Template + MinSpacing + +ScriptLocation - class RimScriptCollection + ScriptDirectory + CalcScripts + SubDirectories + +SeismicCollection - class RimSeismicDataCollection + SeismicData + DifferenceData + +SeismicData - class RimSeismicData + LegendDefinition + userClipValue + userMuteThreshold + SeismicUserDecription + SeismicFilePath + +SeismicDataCollection - class RimSeismicDataCollection + SeismicData + DifferenceData + +SeismicDifferenceData - class RimSeismicDifferenceData + LegendDefinition + userClipValue + userMuteThreshold + SeismicUserDecription + SeismicData1 + SeismicData2 + +SeismicSection - class RimSeismicSection + Name + IsChecked + UserDescription + Type + SeismicData + WellPath + Targets + InlineIndex + CrosslineIndex + DepthIndex + LineThickness + LineColor + ShowSeismicOutline + ShowSectionLine + TransparentSection + DepthFilter + UpperThreshold + LowerThreshold + +SeismicSectionCollection - class RimSeismicSectionCollection + Name + IsChecked + UserDescription + SeismicSections + SurfaceIntersectionLinesScaleFactor + SurfacesWithVisibleSurfaceLines + +SeismicView - class RimSeismicView + WindowController + ShowWindow + WindowGeometry + Id + (A)ViewId + NameConfig + CameraPosition + CameraPointOfInterest + PerspectiveProjection + GridZScale + BackgroundColor + (A)ViewBackgroundColor + MaximumFrameRate + CurrentTimeStep + MeshMode + SurfaceMode + ShowGridBox + DisableLighting + ShowZScale + ComparisonView + FontSize + AnnotationStrategy + AnnotationCountHint + UseCustomAnnotationStrategy + SeismicData + SurfaceInViewCollection + SeismicSectionCollection + AnnotationCollection + OverlayInfoConfig + +SeismicViewCollection - class RimSeismicViewCollection + Views + +SimWellFracture - class RimSimWellFracture + Name + IsChecked + FractureDef + EditTemplate + CreateEllipseTemplate + CreateStimPlanTemplate + AutoUpdateWellPathDepthAtFractureFromTemplate + WellPathDepthAtFracture + Azimuth + PerforationLength + PerforationEfficiency + WellDiameter + Dip + Tilt + FractureUnit + TimeIndexToPlot + MeasuredDepth + Branch + +SimWellFractureCollection - class RimSimWellFractureCollection + Fractures + +StimPlanFractureTemplate - class RimStimPlanFractureTemplate + Id + UserDescription + UnitSystem + Orientation + UserDefinedPerforationLength + AzimuthAngle + SkinFactor + PerforationLength + PerforationEfficiency + WellDiameter + ConductivityType + WellPathDepthAtFracture + FractureContainmentField + NonDarcyFlowType + UserDefinedDFactor + FractureWidthType + FractureWidth + BetaFactorType + InertialCoefficient + PermeabilityType + RelativePermeability + EffectivePermeability + RelativeGasDensity + GasViscosity + HeightScaleFactor + WidthScaleFactor + DFactorScaleFactor + ConductivityFactor + StimPlanFileName + UserDefinedWellPathDepthAtFracture + BorderPolygonResultName + ActiveTimeStepIndex + ConductivityResultName + ShowStimPlanMesh + +StimPlanModel - class RimStimPlanModel + Name + IsChecked + StimPlanModelTemplate + EditModelTemplate + EclipseCase + TimeStep + InitialPressureEclipseCase + StaticEclipseCase + MeasuredDepth + ExtractionOffsetTop + ExtractionOffsetBottom + ExtractionDepthTop + ExtractionDepthBottom + ExtractionType + ThicknessDirectionWellPath + BoundingBoxHorizontal + BoundingBoxVertical + UseDetailedFluidLoss + RelativePermeabilityFactor + PoroElasticConstant + ThermalExpansionCoefficient + PerforationLength + FractureOrientation + AzimuthAngle + FormationDip + AutoComputeBarrier + Barrier + DistanceToBarrier + BarrierDip + WellPenetrationLayer + ShowOnlyBarrierFault + ShowAllFaults + BarrierFaultName + BarrierTextAnnotation + PerforationInterval + +StimPlanModelCollection - class RimStimPlanModelCollection + Name + IsChecked + StimPlanModels + +StimPlanModelCurve - class RimStimPlanModelCurve + Show + AutoCheckStateBasedOnCurveData + CurveName + TemplateText + CurveNamingMethod + LegendDescription + AutoName + ShowLegend + ShowErrorBars + Color + FillColor + Thickness + CurveInterpolation + LineStyle + FillStyle + PointSymbol + SymbolEdgeColor + SymbolSkipPxDist + SymbolLabel + SymbolSize + SymbolLabelPosition + PlotCurveAppearance + AdditionalDataSources + RectAnnotation + StackCurve + StackPhaseColors + TrajectoryType + CurveWellPath + ReferenceWellPath + SimulationWellName + BranchDetection + Branch + CurveCase + CurveEclipseResult + CurveGeomechResult + CurveTimeStep + GeomPartId + AddCaseNameToCurveName + AddPropertyToCurveName + AddWellNameToCurveName + AddTimestepToCurveName + AddDateToCurveName + StimPlanModel + CurveProperty + +StimPlanModelPlot - class RimStimPlanModelPlot + WindowController + ShowWindow + WindowGeometry + Id + (A)ViewId + ShowPlotTitle + ShowTrackLegends + TrackLegendsHorizontal + LegendItemsClickable + TitleFontSize + LegendDeltaFontSize + LegendPosition + PlotDescription + TemplateText + PlotNamingMethod + DepthType + DepthUnit + MinimumDepth + MaximumDepth + ShowDepthGridLines + AutoScaleDepthEnabled + DepthAxisVisibility + ShowDepthMarkerLine + AutoZoomMinDepthFactor + AutoZoomMaxDepthFactor + DepthAnnotations + SubTitleFontSize + AxisTitleFontSize + AxisValueFontSize + NameConfig + FilterEnsembleCurveSet + DepthEqualization + Tracks + DepthOrientation + StimPlanModel + EditModel + EclipseCase + TimeStep + +StimPlanModelPlotCollection - class RimStimPlanModelPlotCollection + StimPlanModelPlots + +StimPlanModelTemplate - class RimStimPlanModelTemplate + Name + Id + DynamicEclipseCase + TimeStep + InitialPressureEclipseCase + UseForInitialPressure + UseForPressure + EditPressureTable + StaticEclipseCase + UseEqlNumForPressureInterpolation + DefaultPorosity + DefaultPermeability + DefaultFacies + VerticalStress + VerticalStressGradient + StressDepth + ReferenceTemperature + ReferenceTemperatureGradient + ReferenceTemperatureDepth + OverburdenHeight + OverburdenFormation + OverburdenFacies + OverburdenPorosity + OverburdenPermeability + OverburdenFluidDensity + UnderburdenHeight + UnderburdenFormation + UnderburdenFacies + UnderburdenPorosity + UnderburdenPermeability + UnderburdenFluidDensity + FaciesInitialPressureConfigs + PressureTable + ElasticProperties + FaciesProperties + NonNetLayers + +StimPlanModelTemplateCollection - class RimStimPlanModelTemplateCollection + StimPlanModelTemplates + NextValidId + +StreamlineInViewCollection - class RimStreamlineInViewCollection + LegendDefinition + Name + FlowThreshold + LengthThreshold + Resolution + MaxDays + UseProducers + UseInjectors + Phase + isActive + VisualizationMode + ColorMode + AnimationSpeed + AnimationIndex + ScaleFactor + TracerLength + +StringParameter - class RimStringParameter + Name + Label + Description + Advanced + Valid + Value + +SummaryAddress - class RimSummaryAddress + SummaryVarType + SummaryQuantityName + SummaryRegion + SummaryRegion2 + SummaryWellGroup + SummaryNetworkGroup + SummaryWell + SummaryWellSegment + SummaryLgr + SummaryCellI + SummaryCellJ + SummaryCellK + SummaryAquifer + IsErrorResult + CalculationId + CaseId + EnsembleId + +SummaryCaseCollection - class RimSummaryCaseMainCollection + SummaryCases + SummaryCaseCollections + +SummaryCaseSubCollection - class RimSummaryCaseCollection + SummaryCases + SummaryCollectionName + CreateAutoName + NameCount + IsEnsemble + Id + (A)EnsembleId + +SummaryCrossPlot - class RimSummaryCrossPlot + WindowController + ShowWindow + WindowGeometry + Id + (A)ViewId + ShowPlotTitle + ShowTrackLegends + TrackLegendsHorizontal + LegendItemsClickable + TitleFontSize + LegendDeltaFontSize + LegendPosition + RowSpan + ColSpan + IsUsingAutoName + PlotDescription + normalizeCurveYValues + useQtChartsPlot + SummaryCurveCollection + EnsembleCurveSetCollection + GridTimeHistoryCurves + AsciiDataCurves + AxisProperties + LeftYAxisProperties + RightYAxisProperties + BottomAxisProperties + TimeAxisProperties + +SummaryCrossPlotCollection - class RimSummaryCrossPlotCollection + SummaryCrossPlots + +SummaryCurve - class RimSummaryCurve + Show + AutoCheckStateBasedOnCurveData + CurveName + TemplateText + CurveNamingMethod + LegendDescription + AutoName + ShowLegend + ShowErrorBars + Color + FillColor + Thickness + CurveInterpolation + LineStyle + FillStyle + PointSymbol + SymbolEdgeColor + SymbolSkipPxDist + SymbolLabel + SymbolSize + SymbolLabelPosition + PlotCurveAppearance + AdditionalDataSources + RectAnnotation + StackCurve + StackPhaseColors + SummaryCase + SummaryAddress + Resampling + HorizontalAxisType + SummaryCaseX + SummaryAddressX + IsEnsembleCurve + PlotAxis + Axis + XAxis + SummaryCurveNameConfig + isTopZWithinCategory + +SummaryCurveAutoName - class RimSummaryCurveAutoName + LongVectorName + VectorName + Unit + RegionNumber + WellGroupName + WellName + WellSegmentNumber + LgrName + Completion + Aquifer + CaseName + +SummaryObservedDataFile - class RimSummaryObservedDataFile + ShortName + NameSetting + ShowSubNodesInTree + AutoShortyName + SummaryHeaderFilename + Id + (A)CaseId + UseCustomIdentifier + SummaryType + IdentifierName + +SummaryPageDownloadEntity - class SummaryPageDownloadEntity + Name + RequestUrl + ResponseFilename + +SummaryPlot - class RimSummaryPlot + WindowController + ShowWindow + WindowGeometry + Id + (A)ViewId + ShowPlotTitle + ShowTrackLegends + TrackLegendsHorizontal + LegendItemsClickable + TitleFontSize + LegendDeltaFontSize + LegendPosition + RowSpan + ColSpan + IsUsingAutoName + PlotDescription + normalizeCurveYValues + useQtChartsPlot + SummaryCurveCollection + EnsembleCurveSetCollection + GridTimeHistoryCurves + AsciiDataCurves + AxisProperties + LeftYAxisProperties + RightYAxisProperties + BottomAxisProperties + TimeAxisProperties + +SummaryPlotCollection - class RimSummaryPlotCollection + SummaryPlots + +SummaryTimeAxisProperties - class RimSummaryTimeAxisProperties + Active + ShowTitle + Title + AutoZoom + TimeMode + TimeUnit + VisibleDateRangeMax + VisibleDateRangeMin + VisibleTimeRangeMax + VisibleTimeRangeMin + VisibleTimeModeRangeMax + VisibleTimeModeRangeMin + TitlePosition + FontSize + ValuesFontSize + AutoDate + DateComponents + TimeComponents + DateFormat + TimeFormat + TickmarkType + TickmarkInterval + TickmarkIntervalStep + MajorTickmarkCount + Annotations + +SummaryYAxisProperties - class RimPlotAxisProperties + Active + Name + AxisTitle + AutoTitle + DisplayLongName + DisplayShortName + DisplayUnitText + CustomTitle + VisibleRangeMax + VisibleRangeMin + NumberFormat + Decimals + ScaleFactor + AutoZoom + LogarithmicScale + AxisInverted + ShowNumbers + PlotAxis + PlotAxisIndex + TitlePosition + TitleDeltaFontSize + ValueDeltaFontSize + Annotations + MajorTickmarkCount + +Surface - class RimFileSurface + SurfaceUserDecription + SurfaceColor + DepthOffset + SurfaceFilePath + +SurfaceCollection - class RimSurfaceCollection + SurfaceUserDecription + SubCollections + SurfacesField + +SurfaceInView - class RimSurfaceInView + Active + ShowInactiveCells + UseSeparateIntersectionDataSource + SeparateIntersectionDataSource + Name + SurfaceRef + ResultDefinition + +SurfaceInViewCollection - class RimSurfaceInViewCollection + Name + IsChecked + SurfacesInViewFieldCollections + SurfacesInViewField + SurfaceCollectionRef + +SurfaceResultDefinition - class RimSurfaceResultDefinition + Name + IsChecked + PropertyName + LegendConfig + SurfaceInView + +TC2 - class TC2 + ta + da + ia + ba + +TestCommand1 - class TestCommand1 + TextArgument + DoubleArgument + IntArgument + BoolArgument + +ThermalFractureTemplate - class RimThermalFractureTemplate + Id + UserDescription + UnitSystem + Orientation + UserDefinedPerforationLength + AzimuthAngle + SkinFactor + PerforationLength + PerforationEfficiency + WellDiameter + ConductivityType + WellPathDepthAtFracture + FractureContainmentField + NonDarcyFlowType + UserDefinedDFactor + FractureWidthType + FractureWidth + BetaFactorType + InertialCoefficient + PermeabilityType + RelativePermeability + EffectivePermeability + RelativeGasDensity + GasViscosity + HeightScaleFactor + WidthScaleFactor + DFactorScaleFactor + ConductivityFactor + StimPlanFileName + UserDefinedWellPathDepthAtFracture + BorderPolygonResultName + ActiveTimeStepIndex + ConductivityResultName + FilterCakePressureDrop + +TofAccumulatedPhaseFractionsPlot - class RimTofAccumulatedPhaseFractionsPlot + WindowController + ShowWindow + WindowGeometry + PlotDescription + ShowPlotTitle + MaxTof + +TotalWellAllocationPlot - class RimTotalWellAllocationPlot + WindowController + ShowWindow + WindowGeometry + PlotDescription + ShowPlotTitle + +TriangleGeometry - class RimcTriangleGeometry + XCoords + YCoords + ZCoords + Connections + MeshXCoords + MeshYCoords + MeshZCoords + FaultMeshXCoords + FaultMeshYCoords + FaultMeshZCoords + DisplayModelOffset + +UserDefinedFilter - class RimUserDefinedFilter + UserDescription + Active + Case + FilterType + GridIndex + PropagateToSubGrids + IndividualCellIndices + +UserDefinedPolylinesAnnotation - class RimUserDefinedPolylinesAnnotation + IsActive + ClosePolyline + ShowLines + ShowSpheres + Appearance + Name + Targets + +ValveTemplate - class RimValveTemplate + Name + UnitSystem + CompletionType + UserLabel + OrificeDiameter + FlowCoefficient + AICDParameters + +ValveTemplateCollection - class RimValveTemplateCollection + ValveDefinitions + ValveUnits + +VfpPlot - class RimVfpPlot + WindowController + ShowWindow + WindowGeometry + Id + (A)ViewId + ShowPlotTitle + ShowTrackLegends + TrackLegendsHorizontal + LegendItemsClickable + TitleFontSize + LegendDeltaFontSize + LegendPosition + RowSpan + ColSpan + PlotTitle + FilePath + TableType + TableNumber + ReferenceDepth + FlowingPhase + FlowingWaterFraction + FlowingGasFraction + InterpolatedVariable + PrimaryVariable + FamilyVariable + LiquidFlowRateIdx + THPIdx + ArtificialLiftQuantityIdx + WaterCutIdx + GasLiquidRatioIdx + +View3dOverlayInfoConfig - class Rim3dOverlayInfoConfig + Active + ShowAnimProgress + ShowInfoText + ShowResultInfo + ShowHistogram + ShowVolumeWeightedMean + ShowVersionInfo + StatisticsTimeRange + StatisticsCellRange + +ViewController - class RimViewController + Active + Name + ManagedView + SyncCamera + ShowCursor + SyncTimeStep + SyncCellResult + SyncLegendDefinitions + SyncRangeFilters + SyncPropertyFilters + DuplicatePropertyFilters + +ViewLinker - class RimViewLinker + Name + MainView + ManagedViews + +WbsParameters - class RimWbsParameters + PorePressureReservoirSource + PorePressureNonReservoirSource + UserPPNonReservoir + PoissionRatioSource + UcsSource + OBG0Source + DFSource + K0SHSource + FGShaleSource + K0FGSource + WaterDensitySource + UserPoissonRatio + UserUcs + UserDF + UserK0FG + UserK0SH + FGMultiplier + WaterDensity + GeoMechCase + WellPath + TimeStep + FrameIndex + +Well - class RimSimWellInView + Name + (A)WellName + ShowWell + ShowWellLabel + ShowWellHead + ShowWellPipe + ShowWellSpheres + ShowWellDisks + WellHeadScaleFactor + WellPipeRadiusScale + WellPipeColor + WellDiskColor + ShowWellCells + ShowWellCellFence + FractureCollection + +WellAllocationPlot - class RimWellAllocationPlot + WindowController + ShowWindow + WindowGeometry + PlotDescription + ShowPlotTitle + BranchDetection + CurveCase + PlotTimeStep + WellName + FlowDiagSolution + FlowType + GroupSmallContributions + SmallContributionsThreshold + AccumulatedWellFlowPlot + TotalWellFlowPlot + WellAllocLegend + TofAccumulatedPhaseFractionsPlot + +WellAllocationPlotLegend - class RimWellAllocationPlotLegend + ShowPlotLegend + +WellBoreStabilityPlot - class RimWellBoreStabilityPlot + WindowController + ShowWindow + WindowGeometry + Id + (A)ViewId + ShowPlotTitle + ShowTrackLegends + TrackLegendsHorizontal + LegendItemsClickable + TitleFontSize + LegendDeltaFontSize + LegendPosition + PlotDescription + TemplateText + PlotNamingMethod + DepthType + DepthUnit + MinimumDepth + MaximumDepth + ShowDepthGridLines + AutoScaleDepthEnabled + DepthAxisVisibility + ShowDepthMarkerLine + AutoZoomMinDepthFactor + AutoZoomMaxDepthFactor + DepthAnnotations + SubTitleFontSize + AxisTitleFontSize + AxisValueFontSize + NameConfig + FilterEnsembleCurveSet + DepthEqualization + Tracks + DepthOrientation + WbsParameters + +WellDistributionPlot - class RimWellDistributionPlot + WindowController + ShowWindow + WindowGeometry + Id + (A)ViewId + ShowPlotTitle + ShowTrackLegends + TrackLegendsHorizontal + LegendItemsClickable + TitleFontSize + LegendDeltaFontSize + LegendPosition + RowSpan + ColSpan + Case + TimeStepIndex + WellName + Phase + GroupSmallContributions + SmallContributionsRelativeThreshold + MaximumTOF + +WellDistributionPlotCollection - class RimWellDistributionPlotCollection + WindowController + ShowWindow + WindowGeometry + Id + (A)ViewId + ShowPlotTitle + ShowTrackLegends + TrackLegendsHorizontal + LegendItemsClickable + TitleFontSize + LegendDeltaFontSize + LegendPosition + Case + TimeStepIndex + WellName + GroupSmallContributions + SmallContributionsRelativeThreshold + MaximumTOF + Plots + ShowOil + ShowGas + ShowWater + PlotDescription + +WellFlowRateCurve - class RimWellFlowRateCurve + Show + AutoCheckStateBasedOnCurveData + CurveName + TemplateText + CurveNamingMethod + LegendDescription + AutoName + ShowLegend + ShowErrorBars + Color + FillColor + Thickness + CurveInterpolation + LineStyle + FillStyle + PointSymbol + SymbolEdgeColor + SymbolSkipPxDist + SymbolLabel + SymbolSize + SymbolLabelPosition + PlotCurveAppearance + AdditionalDataSources + RectAnnotation + StackCurve + StackPhaseColors + +WellLogCalculatedCurve - class RimWellLogCalculatedCurve + Show + AutoCheckStateBasedOnCurveData + CurveName + TemplateText + CurveNamingMethod + LegendDescription + AutoName + ShowLegend + ShowErrorBars + Color + FillColor + Thickness + CurveInterpolation + LineStyle + FillStyle + PointSymbol + SymbolEdgeColor + SymbolSkipPxDist + SymbolLabel + SymbolSize + SymbolLabelPosition + PlotCurveAppearance + AdditionalDataSources + RectAnnotation + StackCurve + StackPhaseColors + Operator + DepthSource + FirstWellLogCurve + SecondWellLogCurve + +WellLogExtractionCurve - class RimWellLogExtractionCurve + Show + AutoCheckStateBasedOnCurveData + CurveName + TemplateText + CurveNamingMethod + LegendDescription + AutoName + ShowLegend + ShowErrorBars + Color + FillColor + Thickness + CurveInterpolation + LineStyle + FillStyle + PointSymbol + SymbolEdgeColor + SymbolSkipPxDist + SymbolLabel + SymbolSize + SymbolLabelPosition + PlotCurveAppearance + AdditionalDataSources + RectAnnotation + StackCurve + StackPhaseColors + TrajectoryType + CurveWellPath + ReferenceWellPath + SimulationWellName + BranchDetection + Branch + CurveCase + CurveEclipseResult + CurveGeomechResult + CurveTimeStep + GeomPartId + AddCaseNameToCurveName + AddPropertyToCurveName + AddWellNameToCurveName + AddTimestepToCurveName + AddDateToCurveName + +WellLogFile - class RimWellLogLasFile + FileName + WellLogFileChannels + WellName + Date + Name + WellFlowCondition + +WellLogFileChannel - class RimWellLogFileChannel + Name + +WellLogFileCurve - class RimWellLogLasFileCurve + Show + AutoCheckStateBasedOnCurveData + CurveName + TemplateText + CurveNamingMethod + LegendDescription + AutoName + ShowLegend + ShowErrorBars + Color + FillColor + Thickness + CurveInterpolation + LineStyle + FillStyle + PointSymbol + SymbolEdgeColor + SymbolSkipPxDist + SymbolLabel + SymbolSize + SymbolLabelPosition + PlotCurveAppearance + AdditionalDataSources + RectAnnotation + StackCurve + StackPhaseColors + CurveWellPath + CurveWellLogChannel + WellLogFile + +WellLogLasFile - class RimWellLogLasFile + FileName + WellLogFileChannels + WellName + Date + Name + WellFlowCondition + +WellLogLasFileCurve - class RimWellLogLasFileCurve + Show + AutoCheckStateBasedOnCurveData + CurveName + TemplateText + CurveNamingMethod + LegendDescription + AutoName + ShowLegend + ShowErrorBars + Color + FillColor + Thickness + CurveInterpolation + LineStyle + FillStyle + PointSymbol + SymbolEdgeColor + SymbolSkipPxDist + SymbolLabel + SymbolSize + SymbolLabelPosition + PlotCurveAppearance + AdditionalDataSources + RectAnnotation + StackCurve + StackPhaseColors + CurveWellPath + CurveWellLogChannel + WellLogFile + +WellLogPlot - class RimWellLogPlot + WindowController + ShowWindow + WindowGeometry + Id + (A)ViewId + ShowPlotTitle + ShowTrackLegends + TrackLegendsHorizontal + LegendItemsClickable + TitleFontSize + LegendDeltaFontSize + LegendPosition + PlotDescription + TemplateText + PlotNamingMethod + DepthType + DepthUnit + MinimumDepth + MaximumDepth + ShowDepthGridLines + AutoScaleDepthEnabled + DepthAxisVisibility + ShowDepthMarkerLine + AutoZoomMinDepthFactor + AutoZoomMaxDepthFactor + DepthAnnotations + SubTitleFontSize + AxisTitleFontSize + AxisValueFontSize + NameConfig + FilterEnsembleCurveSet + DepthEqualization + Tracks + DepthOrientation + +WellLogPlotCollection - class RimWellLogPlotCollection + WellLogPlots + +WellLogPlotTrack - class RimWellLogTrack + WindowController + ShowWindow + WindowGeometry + Id + (A)ViewId + ShowPlotTitle + ShowTrackLegends + TrackLegendsHorizontal + LegendItemsClickable + TitleFontSize + LegendDeltaFontSize + LegendPosition + RowSpan + ColSpan + TrackDescription + Curves + VisibleXRangeMin + VisibleXRangeMax + AutoScaleX + LogarithmicScaleX + InvertPropertyValueAxis + IsPropertyAxisEnabled + ShowXGridLines + ExplicitTickIntervals + MinAndMaxTicksOnly + MajorTickIntervals + MinorTickIntervals + AxisFontSize + AnnotationType + RegionDisplay + ColorShadingLegend + ColorShadingTransparency + ShowFormationLabels + RegionLabelFontSize + FormationSource + FormationTrajectoryType + FormationWellPath + FormationWellPathForSourceWellPath + FormationSimulationWellName + FormationBranchIndex + FormationBranchDetection + FormationCase + FormationLevel + ShowFormationFluids + ShowWellPathAttributes + WellPathAttributesInLegend + ShowWellPathCompletions + WellPathCompletionsInLegend + ShowWellPathAttrBothSides + ShowWellPathAttrLabels + AttributesWellPathSource + AttributesCollection + AutoCheckStateBasedOnCurveData + OverburdenHeight + UnderburdenHeight + ResultDefinition + EnsembleWellLogCurveSet + +WellLogRftCurve - class RimWellLogRftCurve + Show + AutoCheckStateBasedOnCurveData + CurveName + TemplateText + CurveNamingMethod + LegendDescription + AutoName + ShowLegend + ShowErrorBars + Color + FillColor + Thickness + CurveInterpolation + LineStyle + FillStyle + PointSymbol + SymbolEdgeColor + SymbolSkipPxDist + SymbolLabel + SymbolSize + SymbolLabelPosition + PlotCurveAppearance + AdditionalDataSources + RectAnnotation + StackCurve + StackPhaseColors + CurveEclipseResultCase + CurveSummaryCase + CurveEnsemble + ObservedFmuRftData + PressureDepthData + TimeStep + WellName + BranchIndex + BranchDetection + WellLogChannelName + RftDataType + SegmentResultName + SegmentBranchIndex + SegmentBranchType + ScaleFactor + CurveColorByPhase + +WellMeasurement - class RimWellMeasurement + WellName + Depth + Date + Value + Kind + Quality + Remark + FilePath + +WellMeasurementCurve - class RimWellMeasurementCurve + Show + AutoCheckStateBasedOnCurveData + CurveName + TemplateText + CurveNamingMethod + LegendDescription + AutoName + ShowLegend + ShowErrorBars + Color + FillColor + Thickness + CurveInterpolation + LineStyle + FillStyle + PointSymbol + SymbolEdgeColor + SymbolSkipPxDist + SymbolLabel + SymbolSize + SymbolLabelPosition + PlotCurveAppearance + AdditionalDataSources + RectAnnotation + StackCurve + StackPhaseColors + CurveWellPath + CurveMeasurementKind + +WellMeasurementFilePath - class RimWellMeasurementFilePath + UserDecription + FilePath + +WellMeasurementInView - class RimWellMeasurementInView + Name + IsChecked + MeasurementKind + LegendDefinition + WellsSerialized + AvailableWellsSerialized + LowerBound + UpperBound + QualityFilter + RadiusScaleFactor + +WellMeasurements - class RimWellMeasurementCollection + Measurements + ImportedFiles + +WellMeasurementsInView - class RimWellMeasurementInViewCollection + Name + IsChecked + MeasurementKinds + linkWellVisibility + +WellPath - class RimFileWellPath + AirGap + DatumElevation + UnitSystem + SimWellName + SimBranchIndex + ShowWellPathLabel + MeasuredDepthLabelInterval + ShowWellPath + WellPathRadiusScale + WellPathColor + Completions + CompletionSettings + WellLogFiles + CollectionOf3dWellLogCurves + WellPathFormationKeyInFile + WellPathFormationFilePath + WellPathAttributes + WellPathTieIn + WellIASettings + WellPathFilepath + WellPathFilePathInCache + WellPathNumberInFile + UseAutoGeneratedPointAtSeaLevel + +WellPathAicdParameters - class RimWellPathAicdParameters + DeviceOpen + StrengthAICD + DensityCalibrationFluid + ViscosityCalibrationFluid + VolumeFlowRateExponent + ViscosityFunctionExponent + CriticalWaterLiquidFractionEmul + ViscosityTransitionRegionEmul + MaxRatioOfEmulsionVisc + MaxFlowRate + ExponentOilDensity + ExponentWaterDensity + ExponentGasDensity + ExponentOilViscosity + ExponentWaterViscosity + ExponentGasViscosity + +WellPathAttribute - class RimWellPathAttribute + CompletionType + DepthStart + DepthEnd + DiameterInInches + +WellPathAttributes - class RimWellPathAttributeCollection + Name + IsChecked + Attributes + +WellPathBase - class RimWellPath + AirGap + DatumElevation + UnitSystem + SimWellName + SimBranchIndex + ShowWellPathLabel + MeasuredDepthLabelInterval + ShowWellPath + WellPathRadiusScale + WellPathColor + Completions + CompletionSettings + WellLogFiles + CollectionOf3dWellLogCurves + WellPathFormationKeyInFile + WellPathFormationFilePath + WellPathAttributes + WellPathTieIn + WellIASettings + +WellPathCompletionSettings - class RimWellPathCompletionSettings + WellNameForExport + WellGroupNameForExport + ReferenceDepthForExport + WellTypeForExport + DrainageRadiusForPI + GasInflowEq + AutoWellShutIn + AllowWellCrossFlow + WellBoreFluidPVTTable + HydrostaticDensity + FluidInPlaceRegion + MswParameters + MswLinerDiameter + MswRoughness + +WellPathCompletions - class RimWellPathCompletions + Perforations + Fishbones + Fractures + StimPlanModels + WellNameForExport + WellGroupNameForExport + ReferenceDepthForExport + WellTypeForExport + DrainageRadiusForPI + GasInflowEq + AutoWellShutIn + AllowWellCrossFlow + WellBoreFluidPVTTable + HydrostaticDensity + FluidInPlaceRegion + +WellPathFracture - class RimWellPathFracture + Name + IsChecked + FractureDef + EditTemplate + CreateEllipseTemplate + CreateStimPlanTemplate + AutoUpdateWellPathDepthAtFractureFromTemplate + WellPathDepthAtFracture + Azimuth + PerforationLength + PerforationEfficiency + WellDiameter + Dip + Tilt + FractureUnit + TimeIndexToPlot + MeasuredDepth + +WellPathFractureCollection - class RimWellPathFractureCollection + Name + IsChecked + Fractures + +WellPathGeometry - class RimWellPathGeometryDef + ReferencePosUtmXyd + AirGap + MdAtFirstTarget + WellPathTargets + ShowAbsolutePosForWellTargets + UseTopLevelWellReferencePoint + UseAutoGeneratedTargetAtSeaLevel + LinkReferencePointUpdates + AttachedToParentWell + FixedWellPathPoints + FixedMeasuredDepths + ShowSpheres + SphereColor + SphereRadiusFactor + WellTargetHandleScalingFactor + +WellPathGeometryDef - class RimWellPathGeometryDef + ReferencePosUtmXyd + AirGap + MdAtFirstTarget + WellPathTargets + ShowAbsolutePosForWellTargets + UseTopLevelWellReferencePoint + UseAutoGeneratedTargetAtSeaLevel + LinkReferencePointUpdates + AttachedToParentWell + FixedWellPathPoints + FixedMeasuredDepths + ShowSpheres + SphereColor + SphereRadiusFactor + WellTargetHandleScalingFactor + +WellPathGroup - class RimWellPathGroup + AirGap + DatumElevation + UnitSystem + SimWellName + SimBranchIndex + ShowWellPathLabel + MeasuredDepthLabelInterval + ShowWellPath + WellPathRadiusScale + WellPathColor + Completions + CompletionSettings + WellLogFiles + CollectionOf3dWellLogCurves + WellPathFormationKeyInFile + WellPathFormationFilePath + WellPathAttributes + WellPathTieIn + WellIASettings + ChildWellPaths + GroupName + AddValveAtConnection + Valve + +WellPathTarget - class RimWellPathTarget + IsEnabled + TargetPoint + TargetPointForDisplay + TargetMeasuredDepth + Dogleg1 + Dogleg2 + UseFixedAzimuth + Azimuth + UseFixedInclination + Inclination + EstimatedDogleg1 + EstimatedDogleg2 + EstimatedAzimuth + EstimatedInclination + TargetType + HasTangentConstraint + +WellPathValve - class RimWellPathValve + Name + IsChecked + ValveTemplate + StartMeasuredDepth + ValveLocations + EditTemplate + CreateTemplate + +WellPaths - class RimWellPathCollection + Active + ShowWellPathLabel + WellPathLabelColor + GlobalWellPathVisibility + WellPathRadiusScale + WellPathClip + WellPathClipZDistance + WellPaths + WellMeasurements + +WellPltPlot - class RimWellPltPlot + WindowController + ShowWindow + WindowGeometry + Id + (A)ViewId + ShowPlotTitle + ShowTrackLegends + TrackLegendsHorizontal + LegendItemsClickable + TitleFontSize + LegendDeltaFontSize + LegendPosition + PlotDescription + TemplateText + PlotNamingMethod + DepthType + DepthUnit + MinimumDepth + MaximumDepth + ShowDepthGridLines + AutoScaleDepthEnabled + DepthAxisVisibility + ShowDepthMarkerLine + AutoZoomMinDepthFactor + AutoZoomMaxDepthFactor + DepthAnnotations + SubTitleFontSize + AxisTitleFontSize + AxisValueFontSize + NameConfig + FilterEnsembleCurveSet + DepthEqualization + Tracks + DepthOrientation + WellLog + WellName + Sources + TimeSteps + UseStandardConditionCurves + UseReservoirConditionCurves + Phases + +WellPltPlotCollection - class RimPltPlotCollection + PltPlots + +WellRftEnsembleCurveSet - class RimWellRftEnsembleCurveSet + Ensemble + ColorMode + EnsembleParameter + LegendConfig + EclipseResultCase + +WellRftPlot - class RimWellRftPlot + WindowController + ShowWindow + WindowGeometry + Id + (A)ViewId + ShowPlotTitle + ShowTrackLegends + TrackLegendsHorizontal + LegendItemsClickable + TitleFontSize + LegendDeltaFontSize + LegendPosition + PlotDescription + TemplateText + PlotNamingMethod + DepthType + DepthUnit + MinimumDepth + MaximumDepth + ShowDepthGridLines + AutoScaleDepthEnabled + DepthAxisVisibility + ShowDepthMarkerLine + AutoZoomMinDepthFactor + AutoZoomMaxDepthFactor + DepthAnnotations + SubTitleFontSize + AxisTitleFontSize + AxisValueFontSize + NameConfig + FilterEnsembleCurveSet + DepthEqualization + Tracks + DepthOrientation + ShowStatisticsCurves + ShowEnsembleCurves + ShowErrorObserved + WellLog + WellName + BranchIndex + BranchDetection + EnsembleCurveSets + EclipseResultCase + +WellRftPlotCollection - class RimRftPlotCollection + RftPlots + +Wells - class RimSimWellInViewCollection + Active + ShowWellsIntersectingVisibleCells + WellHeadScale + WellHeadPositionScaleFactor + WellPipeRadiusScale + CellCenterSphereScale + WellLabelColor + ShowConnectionStatusColors + WellColorForApply + WellPipeColors + WellPipeVertexCount + WellPipeCoordType + DefaultWellFenceDirection + WellCellTransparency + IsAutoDetectingBranches + WellHeadPosition + Wells + ShowWellValvesTristate + WellDiskSummaryCase + WellDiskQuantity + WellDiskPropertyType + WellDiskPropertyConfigType + WellDiskShowQuantityLabels + WellDiskShowLabelsBackground + WellDiskScaleFactor + WellDiskColor + ShowWellCommunicationLines + +cafNamedTreeNode - class cafNamedTreeNode + ChildNodes + Name + IsChecked + +cafObjectReferenceTreeNode - class cafObjectReferenceTreeNode + ChildNodes + ReferencedObject + +cafTreeNode - class cafTreeNode + ChildNodes + +cloneView - class RicfCloneView + viewId + +closeProject - class RicfCloseProject + +computeCaseGroupStatistics - class RicfComputeCaseGroupStatistics + caseGroupId + caseIds + +createGridCaseGroup - class RicfCreateGridCaseGroup + casePaths + +createGridCaseGroupResult - class RicfCreateGridCaseGroupResult + groupId + groupName + +createLgrForCompletions - class RicfCreateLgrForCompletions + caseId + timeStep + wellPathNames + refinementI + refinementJ + refinementK + splitType + +createMultiPlot - class RicNewMultiPlotFeature + plots + +createMultipleFractures - class RicfCreateMultipleFractures + caseId + wellPathNames + minDistFromWellTd + maxFracturesPerWell + templateId + topLayer + baseLayer + spacing + action + +createSaturationPressurePlots - class RicfCreateSaturationPressurePlots + caseIds + +createStatisticsCase - class RicfCreateStatisticsCase + caseGroupId + +createStatisticsCaseResult - class RicfCreateStatisticsCaseResult + caseId + +createView - class RicfCreateView + caseId + +createViewResult - class RicfCreateViewResult + viewId + +createWbsPlotResult - class RicfCreateWbsPlotResult + viewId + +createWellBoreStabilityPlot - class RicfCreateWellBoreStabilityPlotFeature + caseId + wellPath + timeStep + wbsParameters + +exportContourMapToText - class RicExportContourMapToTextFeature + exportFileName + exportLocalCoordinates + undefinedValueLabel + excludeUndefinedValues + viewId + +exportFlowCharacteristics - class RicfExportFlowCharacteristics + caseId + timeSteps + injectors + producers + fileName + minimumCommunication + aquiferCellThreshold + +exportLgrForCompletions - class RicfExportLgrForCompletions + caseId + timeStep + wellPathNames + refinementI + refinementJ + refinementK + splitType + +exportMsw - class RicfExportMsw + caseId + wellPath + includePerforations + includeFishbones + includeFractures + fileSplit + +exportMultiCaseSnapshots - class RicfExportMultiCaseSnapshots + gridListFile + +exportProperty - class RicfExportProperty + caseId + timeStep + property + eclipseKeyword + undefinedValue + exportFile + +exportPropertyInViews - class RicfExportPropertyInViews + caseId + viewIds + viewNames + undefinedValue + +exportSimWellFractureCompletions - class RicfExportSimWellFractureCompletions + caseId + viewId + viewName + timeStep + simulationWellNames + fileSplit + compdatExport + +exportSnapshots - class RicfExportSnapshots + type + prefix + caseId + viewId + exportFolder + plotOutputFormat + +exportVisibleCells - class RicfExportVisibleCells + caseId + viewId + viewName + exportKeyword + visibleActiveCellsValue + hiddenActiveCellsValue + inactiveCellsValue + +exportWellLogPlotData - class RicfExportWellLogPlotData + exportFormat + viewId + exportFolder + filePrefix + exportTvdRkb + capitalizeFileNames + resampleInterval + convertCurveUnits + +exportWellLogPlotDataResult - class RicfExportWellLogPlotDataResult + exportedFiles + +exportWellPathCompletions - class RicfExportWellPathCompletions + caseId + timeStep + wellPathNames + fileSplit + compdatExport + combinationMode + includeMsw + useNtgHorizontally + includePerforations + includeFishbones + includeFractures + excludeMainBoreForFishbones + performTransScaling + transScalingTimeStep + transScalingWBHPFromSummary + transScalingWBHP + exportComments + exportWelspec + customFileName + +exportWellPaths - class RicfExportWellPaths + wellPathNames + mdStepSize + +importFormationNames - class RicfImportFormationNames + formationFiles + applyToCaseId + +importWellLogFiles - class RicfImportWellLogFiles + wellLogFolder + wellLogFiles + +importWellLogFilesResult - class RicfImportWellLogFilesResult + wellPathNames + +importWellPaths - class RicImportWellPaths + wellPathFolder + wellPathFiles + +importWellPathsResult - class RicImportWellPathsResult + wellPathNames + +loadCase - class RicfLoadCase + path + gridOnly + +loadCaseResult - class RicfLoadCaseResult + id + +openProject - class RicfOpenProject + path + +replaceCase - class RicfSingleCaseReplace + caseId + newGridFile + +replaceMultipleCases - class RicfMultiCaseReplace + +replaceSourceCases - class RicfReplaceSourceCases + caseGroupId + gridListFile + +runOctaveScript - class RicfRunOctaveScript + path + caseIds + +saveProject - class RicSaveProjectFeature + filePath + +saveProjectAs - class RicSaveProjectAsFeature + filePath + +scaleFractureTemplate - class RicfScaleFractureTemplate + id + halfLength + height + dFactor + conductivity + width + +setExportFolder - class RicfSetExportFolder + type + path + createFolder + +setFractureContainment - class RicfSetFractureContainment + id + topLayer + baseLayer + +setMainWindowSize - class RicfSetMainWindowSize + height + width + +setPlotWindowSize - class RicfSetPlotWindowSize + height + width + +setStartDir - class RicfSetStartDir + path + +setTimeStep - class RicfSetTimeStep + caseId + viewId + timeStep + +stackCurves - class RicStackSelectedCurvesFeature + curves + +unstackCurves - class RicUnstackSelectedCurvesFeature + curves + diff --git a/ApplicationLibCode/Adm/projectfilekeywords/2023.12/ri-objectKeywords.txt b/ApplicationLibCode/Adm/projectfilekeywords/2023.12/ri-objectKeywords.txt new file mode 100644 index 0000000000..8960515ae6 --- /dev/null +++ b/ApplicationLibCode/Adm/projectfilekeywords/2023.12/ri-objectKeywords.txt @@ -0,0 +1,471 @@ +// ResInsight version string : 2023.12.0-RC_03 +// Report generated : Mon Dec 11 13:16:58 2023 +// +// + +AnalysisPlot +AnalysisPlotCollection +AnalysisPlotDataEntry +Annotations +AsciiDataCurve +CalcScript +CellEdgeResultSlot +CellFilterCollection +CellIndexFilter +CellPropertyFilter +CellPropertyFilters +CellRangeFilter +CellRangeFilterCollection +ChangeDataSourceFeatureUi +CmdAddItemExecData +CmdDeleteItemExecData +CmdSelectionChangeExecData +ColorLegend +ColorLegendCollection +ColorLegendItem +CompletionTemplateCollection +CorrelationMatrixPlot +CorrelationPlot +CorrelationPlotCollection +CorrelationReportPlot +CrossSection +CrossSectionCollection +CsvSummaryCase +CurveIntersection +DataContainerFloat +DataContainerString +DataContainerTime +DeclineCurve +DepthTrackPlot +DoubleParameter +Eclipse2dViewCollection +EclipseCase +EclipseGeometrySelectionItem +EclipseResultAddress +ElasticProperties +ElasticPropertyScaling +ElasticPropertyScalingCollection +EnsembleFractureStatistics +EnsembleFractureStatisticsPlot +EnsembleFractureStatisticsPlotCollection +EnsembleStatisticsSurface +EnsembleSurface +EnsembleWellLogStatisticsCurve +EnsembleWellLogs +EnsembleWellLogsCollection +FaciesInitialPressureConfig +FaciesProperties +Fault +FaultReactivationModel +FaultReactivationModelCollection +Faults +FileSummaryCase +FileSurface +FishbonesCollection +FishbonesMultipleSubs +FishbonesPipeProperties +FlowCharacteristicsPlot +FlowDiagSolution +FlowPlotCollection +FormationNames +FormationNamesCollectionObject +FractureContainment +FractureDefinitionCollection +FractureGroupStatisticsCollection +FractureTemplateCollection +GeoMech2dViewCollection +GeoMechGeometrySelectionItem +GeoMechPart +GeoMechPartCollection +GeoMechPropertyFilter +GeoMechPropertyFilters +GeoMechResultDefinition +GeoMechResultSlot +GeoMechView +GridCaseSurface +GridCollection +GridCrossPlotCurve +GridCrossPlotCurveSet +GridCrossPlotRegressionCurve +GridInfo +GridInfoCollection +GridStatisticsPlot +GridStatisticsPlotCollection +GridSummaryCase +GridTimeHistoryCurve +IntegerParameter +Intersection2dView +Intersection2dViewCollection +IntersectionBox +IntersectionCollection +IntersectionResultDefinition +Legend +ListParameter +MainPlotCollection +MdiWindowController +MockModelSettings +ModeledWellPath +MultiPlot +MultiSnapshotDefinition +MultiSummaryPlot +NonNetLayers +ObservedDataCollection +ObservedFmuRftData +ObservedPressureDepthData +ParameterGroup +ParameterList +ParameterResultCrossPlot +PdmDocument +PdmObjectCollection +PdmObjectGroup +Perforation +PerforationCollection +PlotDataFilterCollection +PlotDataFilterItem +PlotTemplateCollection +PlotTemplateFileItem +PolyLineFilter +PolygonFilter +PolylineTarget +PolylinesFromFileAnnotation +PressureTable +PressureTableItem +PropertyFilter +RegressionAnalysisCurve +ResInsightAnalysisModels +ResInsightGeoMechCase +ResInsightGeoMechModels +ResInsightOilField +ResInsightProject +ResampleData +ReservoirCellResultStorage +ReservoirView +ResultDefinition +ResultSlot +ResultStorageEntryInfo +RftAddress +RiaMemoryCleanup +RiaPreferences +RiaPreferencesGeoMech +RiaPreferencesSummary +RiaPreferencesSystem +RiaRegressionTest +RicCaseAndFileExportSettingsUi +RicCellRangeUi +RicCreateDepthAdjustedLasFilesUi +RicCreateEnsembleSurfaceUi +RicCreateEnsembleWellLogUi +RicCreateMultipleWellPathLateralsUi +RicCreateRftPlotsFeatureUi +RicDeleteItemExecData +RicExportCarfinUi +RicExportCompletionDataSettingsUi +RicExportContourMapToTextUi +RicExportEclipseInputGridUi +RicExportLgrUi +RicExportToLasFileObj +RicExportToLasFileResampleUi +RicExportWellPathsUi +RicGridCalculator +RicHoloLensCreateSessionUi +RicHoloLensExportToFolderUi +RicHoloLensServerSettings +RicLinkVisibleViewsFeatureUi +RicPasteAsciiDataToSummaryPlotFeatureUi +RicSaturationPressureUi +RicSaveEclipseInputVisibleCellsUi +RicSaveMultiPlotTemplateFeatureSettings +RicSelectCaseOrEnsembleUi +RicSelectPlotTemplateUi +RicSelectSummaryPlotUI +RicSelectViewUI +RicSummaryAddressSelection +RicSummaryCurveCalculator +RicSummaryCurveCreator +RicWellPathsUnitSystemSettingsUi +RifReaderSettings +Rim3dWellLogCurveCollection +Rim3dWellLogExtractionCurve +Rim3dWellLogFileCurve +Rim3dWellLogRftCurve +RimAnnotationCollection +RimAnnotationCollectionBase +RimAnnotationGroupCollection +RimAnnotationLineAppearance +RimAnnotationTextAppearance +RimBinaryExportSettings +RimCaseCollection +RimCellFilterCollection +RimCommandExecuteScript +RimCommandIssueFieldChanged +RimCommandObject +RimCommandRouter +RimContourMapView +RimCsvUserData +RimCustomObjectiveFunction +RimCustomObjectiveFunctionCollection +RimCustomObjectiveFunctionWeight +RimDerivedEnsembleCase +RimDerivedEnsembleCaseCollection +RimDialogData +RimEclipseContourMapProjection +RimEclipseResultAddressCollection +RimElementVectorResult +RimEllipseFractureTemplate +RimEnsembleCurveFilter +RimEnsembleCurveFilterCollection +RimEnsembleCurveSet +RimEnsembleCurveSetCollection +RimEnsembleStatistics +RimEnsembleWellLogCurveSet +RimEquilibriumAxisAnnotation +RimExportInputSettings +RimFaultResultSlot +RimFractureExportSettings +RimGeoMechContourMapProjection +RimGeoMechContourMapView +RimGeoMechFaultReactivationResult +RimGridCalculation +RimGridCalculationCollection +RimGridCalculationVariable +RimGridCrossPlot +RimGridCrossPlotCollection +RimGridCrossPlotCurveSetNameConfig +RimGridCrossPlotNameConfig +RimIdenticalGridCaseGroup +RimInputProperty +RimInputPropertyCollection +RimInputReservoir +RimIntersectionResultsDefinitionCollection +RimMeasurement +RimMswCompletionParameters +RimMudWeightWindowParameters +RimMultiPlotCollection +RimMultipleEclipseResults +RimMultipleLocations +RimMultipleValveLocations +RimNonDarcyPerforationParameters +RimObjectiveFunction +RimObservedEclipseUserData +RimOilFieldEntry +RimOilRegionEntry +RimPlotAxisAnnotation +RimPlotCellFilterCollection +RimPlotCellPropertyFilter +RimPlotRectAnnotation +RimPolylineAppearance +RimPolylinesAnnotationInView +RimPolylinesFromFileAnnotationInView +RimProcess +RimReachCircleAnnotation +RimReachCircleAnnotationInView +RimResultSelectionUi +RimRftCase +RimRftTopologyCurve +RimRoffCase +RimSEGYConvertOptions +RimSaturationPressurePlot +RimSaturationPressurePlotCollection +RimSeismicView +RimStatisticalCalculation +RimStatisticalCollection +RimStimPlanColors +RimStimPlanFractureTemplate +RimStimPlanLegendConfig +RimSummaryAddressCollection +RimSummaryAddressSelector +RimSummaryCalculation +RimSummaryCalculationCollection +RimSummaryCalculationVariable +RimSummaryCurveCollection +RimSummaryCurveCollectionModifier +RimSummaryMultiPlotCollection +RimSummaryPlotManager +RimSummaryTable +RimSummaryTableCollection +RimSurfaceIntersectionBand +RimSurfaceIntersectionCollection +RimSurfaceIntersectionCurve +RimTensorResults +RimTernaryLegendConfig +RimTextAnnotation +RimTextAnnotationInView +RimThermalFractureTemplate +RimTimeAxisAnnotation +RimTimeStepFilter +RimUserDefinedIndexFilter +RimUserDefinedPolylinesAnnotationInView +RimVfpPlotCollection +RimViewLinkerCollection +RimViewNameConfig +RimVirtualPerforationResults +RimWellAllocationOverTimePlot +RimWellConnectivityTable +RimWellIASettings +RimWellIASettingsCollection +RimWellLogExtractionCurve +RimWellLogExtractionCurveNameConfig +RimWellLogFileCurveNameConfig +RimWellLogLasFileCurveNameConfig +RimWellLogPlotNameConfig +RimWellLogRftCurveNameConfig +RimWellLogWbsCurve +RimWellPathEntry +RimWellPathImport +RimWellPathTieIn +RiuCreateMultipleFractionsUi +RiuMultipleFractionsOptions +ScriptLocation +SeismicCollection +SeismicData +SeismicDataCollection +SeismicDifferenceData +SeismicSection +SeismicSectionCollection +SeismicView +SeismicViewCollection +SimWellFracture +SimWellFractureCollection +StimPlanFractureTemplate +StimPlanModel +StimPlanModelCollection +StimPlanModelCurve +StimPlanModelPlot +StimPlanModelPlotCollection +StimPlanModelTemplate +StimPlanModelTemplateCollection +StreamlineInViewCollection +StringParameter +SummaryAddress +SummaryCaseCollection +SummaryCaseSubCollection +SummaryCrossPlot +SummaryCrossPlotCollection +SummaryCurve +SummaryCurveAutoName +SummaryObservedDataFile +SummaryPageDownloadEntity +SummaryPlot +SummaryPlotCollection +SummaryTimeAxisProperties +SummaryYAxisProperties +Surface +SurfaceCollection +SurfaceInView +SurfaceInViewCollection +SurfaceResultDefinition +TC2 +TestCommand1 +ThermalFractureTemplate +TofAccumulatedPhaseFractionsPlot +TotalWellAllocationPlot +TriangleGeometry +UserDefinedFilter +UserDefinedPolylinesAnnotation +ValveTemplate +ValveTemplateCollection +VfpPlot +View3dOverlayInfoConfig +ViewController +ViewLinker +WbsParameters +Well +WellAllocationPlot +WellAllocationPlotLegend +WellBoreStabilityPlot +WellDistributionPlot +WellDistributionPlotCollection +WellFlowRateCurve +WellLogCalculatedCurve +WellLogExtractionCurve +WellLogFile +WellLogFileChannel +WellLogFileCurve +WellLogLasFile +WellLogLasFileCurve +WellLogPlot +WellLogPlotCollection +WellLogPlotTrack +WellLogRftCurve +WellMeasurement +WellMeasurementCurve +WellMeasurementFilePath +WellMeasurementInView +WellMeasurements +WellMeasurementsInView +WellPath +WellPathAicdParameters +WellPathAttribute +WellPathAttributes +WellPathBase +WellPathCompletionSettings +WellPathCompletions +WellPathFracture +WellPathFractureCollection +WellPathGeometry +WellPathGeometryDef +WellPathGroup +WellPathTarget +WellPathValve +WellPaths +WellPltPlot +WellPltPlotCollection +WellRftEnsembleCurveSet +WellRftPlot +WellRftPlotCollection +Wells +cafNamedTreeNode +cafObjectReferenceTreeNode +cafTreeNode +cloneView +closeProject +computeCaseGroupStatistics +createGridCaseGroup +createGridCaseGroupResult +createLgrForCompletions +createMultiPlot +createMultipleFractures +createSaturationPressurePlots +createStatisticsCase +createStatisticsCaseResult +createView +createViewResult +createWbsPlotResult +createWellBoreStabilityPlot +exportContourMapToText +exportFlowCharacteristics +exportLgrForCompletions +exportMsw +exportMultiCaseSnapshots +exportProperty +exportPropertyInViews +exportSimWellFractureCompletions +exportSnapshots +exportVisibleCells +exportWellLogPlotData +exportWellLogPlotDataResult +exportWellPathCompletions +exportWellPaths +importFormationNames +importWellLogFiles +importWellLogFilesResult +importWellPaths +importWellPathsResult +loadCase +loadCaseResult +openProject +replaceCase +replaceMultipleCases +replaceSourceCases +runOctaveScript +saveProject +saveProjectAs +scaleFractureTemplate +setExportFolder +setFractureContainment +setMainWindowSize +setPlotWindowSize +setStartDir +setTimeStep +stackCurves +unstackCurves diff --git a/ApplicationLibCode/Application/RiaApplication.cpp b/ApplicationLibCode/Application/RiaApplication.cpp index dea00e24bb..8211705f7d 100644 --- a/ApplicationLibCode/Application/RiaApplication.cpp +++ b/ApplicationLibCode/Application/RiaApplication.cpp @@ -51,6 +51,7 @@ #include "RimEclipseCaseCollection.h" #include "RimEclipseView.h" #include "RimEnsembleWellLogsCollection.h" +#include "RimFaultReactivationModelCollection.h" #include "RimFormationNamesCollection.h" #include "RimFractureTemplateCollection.h" #include "RimGeoMechCase.h" @@ -685,6 +686,19 @@ bool RiaApplication::loadProject( const QString& projectFileName, ProjectLoadAct cas->intersectionViewCollection()->syncFromExistingIntersections( false ); } + { + std::vector views; + m_project->allViews( views ); + + for ( auto view : views ) + { + if ( auto eclipseView = dynamic_cast( view ) ) + { + eclipseView->faultReactivationModelCollection()->loadDataAndUpdate(); + } + } + } + for ( RimOilField* oilField : m_project->oilFields ) { for ( auto seisView : oilField->seismicViewCollection()->views() ) diff --git a/ApplicationLibCode/Application/RiaPreferences.cpp b/ApplicationLibCode/Application/RiaPreferences.cpp index d1e99b9b80..3439233871 100644 --- a/ApplicationLibCode/Application/RiaPreferences.cpp +++ b/ApplicationLibCode/Application/RiaPreferences.cpp @@ -229,6 +229,11 @@ RiaPreferences::RiaPreferences() CAF_PDM_InitField( &m_useQtChartsPlotByDefault, "useQtChartsPlotByDefault", false, "Use QtChart as Default Plot Type" ); caf::PdmUiNativeCheckBoxEditor::configureFieldForEditor( &m_useQtChartsPlotByDefault ); + CAF_PDM_InitFieldNoDefault( &m_gridCalculationExpressionFolder, "gridCalculationExpressionFolder", "Grid Calculation Expression Folder" ); + CAF_PDM_InitFieldNoDefault( &m_summaryCalculationExpressionFolder, + "summaryCalculationExpressionFolder", + "Summary Calculation Expression Folder" ); + CAF_PDM_InitField( &m_surfaceImportResamplingDistance, "SurfaceImportResamplingDistance", 100.0, @@ -292,6 +297,10 @@ void RiaPreferences::defineEditorAttribute( const caf::PdmFieldHandle* field, QS myAttr->m_selectDirectory = true; myAttr->m_appendUiSelectedFolderToText = true; } + else if ( field == &m_gridCalculationExpressionFolder || field == &m_summaryCalculationExpressionFolder ) + { + myAttr->m_selectDirectory = true; + } } } @@ -331,16 +340,16 @@ void RiaPreferences::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& { caf::PdmUiGroup* colorGroup = uiOrdering.addNewGroup( "Default Colors" ); colorGroup->add( &defaultViewerBackgroundColor ); - colorGroup->add( &defaultGridLineColors, false ); + colorGroup->appendToRow( &defaultGridLineColors ); colorGroup->add( &defaultFaultGridLineColors ); - colorGroup->add( &defaultWellLabelColor, false ); - colorGroup->add( &m_guiTheme, { true, 2 } ); + colorGroup->appendToRow( &defaultWellLabelColor ); + colorGroup->add( &m_guiTheme, { .newRow = true, .totalColumnSpan = 2 } ); caf::PdmUiGroup* fontGroup = uiOrdering.addNewGroup( "Default Font Sizes" ); fontGroup->add( &defaultSceneFontSize ); - fontGroup->add( &defaultAnnotationFontSize, false ); + fontGroup->appendToRow( &defaultAnnotationFontSize ); fontGroup->add( &defaultWellLabelFontSize ); - fontGroup->add( &defaultPlotFontSize, false ); + fontGroup->appendToRow( &defaultPlotFontSize ); caf::PdmUiGroup* viewsGroup = uiOrdering.addNewGroup( "3d Views" ); viewsGroup->add( &m_defaultMeshModeType ); @@ -348,9 +357,9 @@ void RiaPreferences::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& viewsGroup->add( &m_defaultScaleFactorZ ); viewsGroup->add( &m_showLegendBackground ); - viewsGroup->add( &m_enableFaultsByDefault, { false, 1 } ); + viewsGroup->add( &m_enableFaultsByDefault, { .newRow = false, .totalColumnSpan = 1 } ); viewsGroup->add( &m_showInfoBox ); - viewsGroup->add( &m_showGridBox, { false, 1 } ); + viewsGroup->add( &m_showGridBox, { .newRow = false, .totalColumnSpan = 1 } ); caf::PdmUiGroup* otherGroup = uiOrdering.addNewGroup( "Other" ); otherGroup->add( &ssihubAddress ); @@ -394,11 +403,11 @@ void RiaPreferences::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& caf::PdmUiGroup* pageSetup = generalGrp->addNewGroup( "Page Setup" ); pageSetup->add( &m_pageSize ); - pageSetup->add( &m_pageOrientation, false ); + pageSetup->appendToRow( &m_pageOrientation ); pageSetup->add( &m_pageLeftMargin ); - pageSetup->add( &m_pageRightMargin, false ); + pageSetup->appendToRow( &m_pageRightMargin ); pageSetup->add( &m_pageTopMargin ); - pageSetup->add( &m_pageBottomMargin, false ); + pageSetup->appendToRow( &m_pageBottomMargin ); generalGrp->add( &m_useQtChartsPlotByDefault ); m_useQtChartsPlotByDefault.uiCapability()->setUiHidden( true ); @@ -448,6 +457,10 @@ void RiaPreferences::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& exportGroup->add( &csvTextExportFieldSeparator ); exportGroup->add( &m_openExportedPdfInViewer ); exportGroup->add( &m_writeEchoInGrdeclFiles ); + + caf::PdmUiGroup* otherGroup = uiOrdering.addNewGroup( "Other" ); + otherGroup->add( &m_gridCalculationExpressionFolder ); + otherGroup->add( &m_summaryCalculationExpressionFolder ); } else if ( RiaApplication::enableDevelopmentFeatures() && uiConfigName == RiaPreferences::tabNameSystem() ) { @@ -838,6 +851,22 @@ QString RiaPreferences::defaultMultiLateralWellNamePattern() return "?*Y*"; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RiaPreferences::gridCalculationExpressionFolder() const +{ + return m_gridCalculationExpressionFolder().path(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RiaPreferences::summaryCalculationExpressionFolder() const +{ + return m_summaryCalculationExpressionFolder().path(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/Application/RiaPreferences.h b/ApplicationLibCode/Application/RiaPreferences.h index 1157fa1433..bcceb40a82 100644 --- a/ApplicationLibCode/Application/RiaPreferences.h +++ b/ApplicationLibCode/Application/RiaPreferences.h @@ -102,6 +102,9 @@ class RiaPreferences : public caf::PdmObject QString multiLateralWellNamePattern() const; static QString defaultMultiLateralWellNamePattern(); + QString gridCalculationExpressionFolder() const; + QString summaryCalculationExpressionFolder() const; + // 3D view RiaDefines::MeshModeType defaultMeshModeType() const; RiaDefines::RINavigationPolicy navigationPolicy() const; @@ -193,6 +196,9 @@ class RiaPreferences : public caf::PdmObject caf::PdmField m_lastUsedPlotTemplate; caf::PdmField m_useQtChartsPlotByDefault; + caf::PdmField m_gridCalculationExpressionFolder; + caf::PdmField m_summaryCalculationExpressionFolder; + // Script paths caf::PdmField m_octaveExecutable; caf::PdmField m_pythonExecutable; diff --git a/ApplicationLibCode/Application/RiaPreferencesSummary.cpp b/ApplicationLibCode/Application/RiaPreferencesSummary.cpp index dc0eacf3cc..9983ba5364 100644 --- a/ApplicationLibCode/Application/RiaPreferencesSummary.cpp +++ b/ApplicationLibCode/Application/RiaPreferencesSummary.cpp @@ -361,6 +361,8 @@ RiaPreferencesSummary::SummaryRestartFilesImportMode RiaPreferencesSummary::summ //-------------------------------------------------------------------------------------------------- QString RiaPreferencesSummary::defaultSummaryCurvesTextFilter() const { + if ( m_defaultSummaryPlot() != DefaultSummaryPlotType::DATA_VECTORS ) return {}; + return m_defaultSummaryCurvesTextFilter; } diff --git a/ApplicationLibCode/Application/RiaResultNames.cpp b/ApplicationLibCode/Application/RiaResultNames.cpp index 5db1de4257..9bb98050d4 100644 --- a/ApplicationLibCode/Application/RiaResultNames.cpp +++ b/ApplicationLibCode/Application/RiaResultNames.cpp @@ -251,6 +251,14 @@ QString RiaResultNames::combinedRiMultResultName() return "riMULTXYZ"; } +//-------------------------------------------------------------------------------------------------- +/// Result containing 1 for cells with NNCs and 0 for cells without NNCs +//-------------------------------------------------------------------------------------------------- +QString RiaResultNames::riNncCells() +{ + return "riNncCells"; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/Application/RiaResultNames.h b/ApplicationLibCode/Application/RiaResultNames.h index a56594c201..e6b600eca9 100644 --- a/ApplicationLibCode/Application/RiaResultNames.h +++ b/ApplicationLibCode/Application/RiaResultNames.h @@ -56,6 +56,8 @@ QString riMultYResultName(); QString riMultZResultName(); QString combinedRiMultResultName(); +QString riNncCells(); + QString riAreaNormTranXResultName(); QString riAreaNormTranYResultName(); QString riAreaNormTranZResultName(); diff --git a/ApplicationLibCode/Application/RiaThermalFractureDefines.cpp b/ApplicationLibCode/Application/RiaThermalFractureDefines.cpp index 5c22254dd2..6d1e7abe2f 100644 --- a/ApplicationLibCode/Application/RiaThermalFractureDefines.cpp +++ b/ApplicationLibCode/Application/RiaThermalFractureDefines.cpp @@ -73,6 +73,14 @@ QString viscosityResultName() return "Viscosity"; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString filtrateThicknessResultName() +{ + return "FiltrateThickness"; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -98,7 +106,7 @@ QString getExpectedThermalFractureUnit( const QString& name, RiaDefines::Eclipse { "Velocity", { "m/sec", "ft/sec" } }, { "ResPressure", { "BARa", "psia" } }, { "ResTemperature", { "deg C", "deg F" } }, - { "FiltrateThickness", { "cm", "inches" } }, + { RiaDefines::filtrateThicknessResultName(), { "cm", "inches" } }, { RiaDefines::filtratePressureDropResultName(), { "bar", "psi" } }, { "EffectiveResStress", { "bar", "psi" } }, { "EffectiveFracStress", { "bar", "psi" } }, diff --git a/ApplicationLibCode/Application/RiaThermalFractureDefines.h b/ApplicationLibCode/Application/RiaThermalFractureDefines.h index 59947419de..7d43821a0a 100644 --- a/ApplicationLibCode/Application/RiaThermalFractureDefines.h +++ b/ApplicationLibCode/Application/RiaThermalFractureDefines.h @@ -30,6 +30,7 @@ QString leakoffMobilityResultName(); QString filterCakeMobilityResultName(); QString injectivityFactorResultName(); QString viscosityResultName(); +QString filtrateThicknessResultName(); QString getExpectedThermalFractureUnit( const QString& name, RiaDefines::EclipseUnitSystem unitSystem ); diff --git a/ApplicationLibCode/Application/Tools/RiaSummaryAddressAnalyzer.cpp b/ApplicationLibCode/Application/Tools/RiaSummaryAddressAnalyzer.cpp index d045e62f8d..5969e00b50 100644 --- a/ApplicationLibCode/Application/Tools/RiaSummaryAddressAnalyzer.cpp +++ b/ApplicationLibCode/Application/Tools/RiaSummaryAddressAnalyzer.cpp @@ -63,17 +63,25 @@ void RiaSummaryAddressAnalyzer::appendAddresses( const std::set& addresses ) { - // RiaSummaryCurveAddress can be used to represent cross plot curves. Set the flag m_onlyCrossPlotCurves to true, and this will be set - // to false in analyzeSingleAddress if we detect a time curve + // RiaSummaryCurveAddress can be used to represent cross plot curves. Count curves, and set the flag m_onlyCrossPlotCurves to true if + // all curves are cross plot curves - m_onlyCrossPlotCurves = true; + size_t crossPlotCurveCount = 0; for ( const auto& adr : addresses ) { + auto adrX = adr.summaryAddressX(); + if ( adrX.isValid() && adrX.category() != SummaryCategory::SUMMARY_TIME ) + { + crossPlotCurveCount++; + } + // Use Y address first, to make sure the ordering of cross plot names is correct analyzeSingleAddress( adr.summaryAddressY() ); analyzeSingleAddress( adr.summaryAddressX() ); } + + m_onlyCrossPlotCurves = ( crossPlotCurveCount == addresses.size() ); } //-------------------------------------------------------------------------------------------------- @@ -474,8 +482,6 @@ void RiaSummaryAddressAnalyzer::analyzeSingleAddress( const RifEclipseSummaryAdd if ( address.category() == SummaryCategory::SUMMARY_TIME ) { - m_onlyCrossPlotCurves = false; - // A time address has no other information than SummaryCategory::SUMMARY_TIME return; } diff --git a/ApplicationLibCode/Application/Tools/RiaSummaryStringTools.cpp b/ApplicationLibCode/Application/Tools/RiaSummaryStringTools.cpp index 44df0dd8c7..2e4edb12aa 100644 --- a/ApplicationLibCode/Application/Tools/RiaSummaryStringTools.cpp +++ b/ApplicationLibCode/Application/Tools/RiaSummaryStringTools.cpp @@ -254,7 +254,7 @@ std::set RiaSummaryStringTools::computeFilteredAddress if ( includeDiffCurves ) return addresses; - const auto diffText = RifReaderEclipseSummary::differenceIdentifier(); + const auto diffText = RifEclipseSummaryAddressDefines::differenceIdentifier(); std::set addressesWithoutDiffVectors; for ( const auto& adr : addresses ) diff --git a/ApplicationLibCode/CMakeLists.txt b/ApplicationLibCode/CMakeLists.txt index d7b7f31b23..57192e6738 100644 --- a/ApplicationLibCode/CMakeLists.txt +++ b/ApplicationLibCode/CMakeLists.txt @@ -339,6 +339,8 @@ if(MSVC) set(BUILD_FLAGS_FOR_MSVC "/W3 /wd4190 /wd4100 /wd4127") + message(STATUS "CMAKE_CXX_COMPILER_VERSION ${CMAKE_CXX_COMPILER_VERSION}") + if(CMAKE_CXX_COMPILER_VERSION LESS_EQUAL 19.14) # The following warning is generated over 800 times from a qwt header only # using VS2015 Disabling temporarily warning C4505 'function' : unreferenced @@ -346,6 +348,11 @@ if(MSVC) set(BUILD_FLAGS_FOR_MSVC "${BUILD_FLAGS_FOR_MSVC} /wd4505") endif() + if(CMAKE_CXX_COMPILER_VERSION GREATER_EQUAL 19.38) + # https://github.com/OPM/ResInsight/issues/10844 + set(BUILD_FLAGS_FOR_MSVC "${BUILD_FLAGS_FOR_MSVC} /wd4996") + endif() + message(STATUS "BUILD_FLAGS_FOR_MSVC ${BUILD_FLAGS_FOR_MSVC}") set_target_properties( ${PROJECT_NAME} PROPERTIES COMPILE_FLAGS ${BUILD_FLAGS_FOR_MSVC} diff --git a/ApplicationLibCode/CommandFileInterface/RicfExportVisibleCells.cpp b/ApplicationLibCode/CommandFileInterface/RicfExportVisibleCells.cpp index 806fe44a48..991675e440 100644 --- a/ApplicationLibCode/CommandFileInterface/RicfExportVisibleCells.cpp +++ b/ApplicationLibCode/CommandFileInterface/RicfExportVisibleCells.cpp @@ -103,7 +103,7 @@ caf::PdmScriptResponse RicfExportVisibleCells::execute() QString exportFolder = RicfCommandFileExecutor::instance()->getExportPath( RicfCommandFileExecutor::ExportType::CELLS ); if ( exportFolder.isNull() ) { - exportFolder = RiaApplication::instance()->createAbsolutePathFromProjectRelativePath( "visibleCells" ); + exportFolder = RiaApplication::instance()->currentProjectPath(); } RiaViewRedrawScheduler::instance()->clearViewsScheduledForUpdate(); diff --git a/ApplicationLibCode/Commands/CMakeLists.txt b/ApplicationLibCode/Commands/CMakeLists.txt index d0aa8eeaf1..931eb11e82 100644 --- a/ApplicationLibCode/Commands/CMakeLists.txt +++ b/ApplicationLibCode/Commands/CMakeLists.txt @@ -110,6 +110,11 @@ if(MSVC) set(BUILD_FLAGS_FOR_MSVC "${BUILD_FLAGS_FOR_MSVC} /wd4505") endif() + if(CMAKE_CXX_COMPILER_VERSION GREATER_EQUAL 19.38) + # https://github.com/OPM/ResInsight/issues/10844 + set(BUILD_FLAGS_FOR_MSVC "${BUILD_FLAGS_FOR_MSVC} /wd4996") + endif() + set_target_properties( ${PROJECT_NAME} PROPERTIES COMPILE_FLAGS ${BUILD_FLAGS_FOR_MSVC} ) diff --git a/ApplicationLibCode/Commands/CMakeLists_files.cmake b/ApplicationLibCode/Commands/CMakeLists_files.cmake index f47103fbd8..d2fcebaf9a 100644 --- a/ApplicationLibCode/Commands/CMakeLists_files.cmake +++ b/ApplicationLibCode/Commands/CMakeLists_files.cmake @@ -89,6 +89,10 @@ set(SOURCE_GROUP_HEADER_FILES ${CMAKE_CURRENT_LIST_DIR}/RicImportRevealSummaryCaseFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicImportStimPlanSummaryCaseFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicCopyGridStatisticsToClipboardFeature.h + ${CMAKE_CURRENT_LIST_DIR}/RicExportGridCalculationExpressionsFeature.h + ${CMAKE_CURRENT_LIST_DIR}/RicImportGridCalculationExpressionsFeature.h + ${CMAKE_CURRENT_LIST_DIR}/RicExportSummaryCalculationExpressionsFeature.h + ${CMAKE_CURRENT_LIST_DIR}/RicImportSummaryCalculationExpressionsFeature.h ) set(SOURCE_GROUP_SOURCE_FILES @@ -181,6 +185,10 @@ set(SOURCE_GROUP_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/RicImportRevealSummaryCaseFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicImportStimPlanSummaryCaseFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicCopyGridStatisticsToClipboardFeature.cpp + ${CMAKE_CURRENT_LIST_DIR}/RicExportGridCalculationExpressionsFeature.cpp + ${CMAKE_CURRENT_LIST_DIR}/RicImportGridCalculationExpressionsFeature.cpp + ${CMAKE_CURRENT_LIST_DIR}/RicExportSummaryCalculationExpressionsFeature.cpp + ${CMAKE_CURRENT_LIST_DIR}/RicImportSummaryCalculationExpressionsFeature.cpp ) if(RESINSIGHT_USE_QT_CHARTS) diff --git a/ApplicationLibCode/Commands/CellFilterCommands/RicNewPolygonFilter3dviewFeature.cpp b/ApplicationLibCode/Commands/CellFilterCommands/RicNewPolygonFilter3dviewFeature.cpp index 20b07254e8..52db3a8110 100644 --- a/ApplicationLibCode/Commands/CellFilterCommands/RicNewPolygonFilter3dviewFeature.cpp +++ b/ApplicationLibCode/Commands/CellFilterCommands/RicNewPolygonFilter3dviewFeature.cpp @@ -38,8 +38,10 @@ CAF_CMD_SOURCE_INIT( RicNewPolygonFilter3dviewFeature, "RicNewPolygonFilter3dvie void RicNewPolygonFilter3dviewFeature::onActionTriggered( bool isChecked ) { // Get the selected Cell Filter Collection - RimGridView* viewOrComparisonView = RiaApplication::instance()->activeMainOrComparisonGridView(); - RimCellFilterCollection* filtColl = viewOrComparisonView->cellFilterCollection(); + RimGridView* viewOrComparisonView = RiaApplication::instance()->activeMainOrComparisonGridView(); + if ( !viewOrComparisonView ) return; + + RimCellFilterCollection* filtColl = viewOrComparisonView->cellFilterCollection(); // and the case to use RimCase* sourceCase = viewOrComparisonView->ownerCase(); diff --git a/ApplicationLibCode/Commands/CellFilterCommands/RicNewRangeFilterSlice3dviewFeature.cpp b/ApplicationLibCode/Commands/CellFilterCommands/RicNewRangeFilterSlice3dviewFeature.cpp index fba1a94bc4..f595655460 100644 --- a/ApplicationLibCode/Commands/CellFilterCommands/RicNewRangeFilterSlice3dviewFeature.cpp +++ b/ApplicationLibCode/Commands/CellFilterCommands/RicNewRangeFilterSlice3dviewFeature.cpp @@ -41,6 +41,7 @@ bool RicNewRangeFilterSlice3dviewFeature::isCommandEnabled() const if ( !view ) return false; RimGridView* viewOrComparisonView = RiaApplication::instance()->activeMainOrComparisonGridView(); + if ( !viewOrComparisonView ) return false; RimViewController* vc = viewOrComparisonView->viewController(); if ( !vc ) return true; @@ -58,6 +59,7 @@ void RicNewRangeFilterSlice3dviewFeature::onActionTriggered( bool isChecked ) RimGridView* activeView = RiaApplication::instance()->activeGridView(); RimGridView* viewOrComparisonView = RiaApplication::instance()->activeMainOrComparisonGridView(); + if ( !viewOrComparisonView ) return; RimCase* sourceCase = viewOrComparisonView->ownerCase(); diff --git a/ApplicationLibCode/Commands/CompletionExportCommands/RicWellPathExportCompletionDataFeatureImpl.cpp b/ApplicationLibCode/Commands/CompletionExportCommands/RicWellPathExportCompletionDataFeatureImpl.cpp index e66732370e..99f450e497 100644 --- a/ApplicationLibCode/Commands/CompletionExportCommands/RicWellPathExportCompletionDataFeatureImpl.cpp +++ b/ApplicationLibCode/Commands/CompletionExportCommands/RicWellPathExportCompletionDataFeatureImpl.cpp @@ -193,6 +193,11 @@ void RicWellPathExportCompletionDataFeatureImpl::exportCompletions( const std::v for ( auto wellPathLateral : allWellPathLaterals ) { + // Skip well paths that are not enabled, no export of WELSEGS or COMPDAT + // https://github.com/OPM/ResInsight/issues/10754 + // + if ( !wellPathLateral->isEnabled() ) continue; + // Generate completion data if ( exportSettings.includePerforations ) diff --git a/ApplicationLibCode/Commands/CompletionExportCommands/RicWellPathExportCompletionDataFeatureImpl.h b/ApplicationLibCode/Commands/CompletionExportCommands/RicWellPathExportCompletionDataFeatureImpl.h index 6c26562e0d..7668f3e278 100644 --- a/ApplicationLibCode/Commands/CompletionExportCommands/RicWellPathExportCompletionDataFeatureImpl.h +++ b/ApplicationLibCode/Commands/CompletionExportCommands/RicWellPathExportCompletionDataFeatureImpl.h @@ -126,11 +126,11 @@ class RicWellPathExportCompletionDataFeatureImpl static std::vector computeDynamicCompletionsForWellPath( RimWellPath* wellPath, RimEclipseCase* eclipseCase, size_t timeStepIndex ); +private: static std::vector generatePerforationsCompdatValues( gsl::not_null wellPath, const std::vector& intervals, const RicExportCompletionDataSettingsUi& settings ); -private: static double calculateTransmissibilityAsEclipseDoes( RimEclipseCase* eclipseCase, double skinFactor, double wellRadius, diff --git a/ApplicationLibCode/Commands/ExportCommands/RicExportEclipseSectorModelUi.cpp b/ApplicationLibCode/Commands/ExportCommands/RicExportEclipseSectorModelUi.cpp index b1c67b422e..3a16a078e5 100644 --- a/ApplicationLibCode/Commands/ExportCommands/RicExportEclipseSectorModelUi.cpp +++ b/ApplicationLibCode/Commands/ExportCommands/RicExportEclipseSectorModelUi.cpp @@ -314,16 +314,16 @@ void RicExportEclipseSectorModelUi::defineUiOrdering( QString uiConfigName, caf: exportInLocalCoordinates.uiCapability()->setUiReadOnly( !exportGrid() ); caf::PdmUiGroup* gridBoxGroup = uiOrdering.addNewGroup( "Grid Box Selection" ); - gridBoxGroup->add( &exportGridBox, { true, 4, 1 } ); + gridBoxGroup->add( &exportGridBox, { .newRow = true, .totalColumnSpan = 4, .leftLabelColumnSpan = 1 } ); - gridBoxGroup->add( &minI, { true, 2, 1 } ); - gridBoxGroup->add( &minJ, false ); - gridBoxGroup->add( &minK, false ); + gridBoxGroup->add( &minI, { .newRow = true, .totalColumnSpan = 2, .leftLabelColumnSpan = 1 } ); + gridBoxGroup->appendToRow( &minJ ); + gridBoxGroup->appendToRow( &minK ); - gridBoxGroup->add( &maxI, { true, 2, 1 } ); - gridBoxGroup->add( &maxJ, false ); - gridBoxGroup->add( &maxK, false ); - gridBoxGroup->add( &makeInvisibleCellsInactive, { true, 2, 1 } ); + gridBoxGroup->add( &maxI, { .newRow = true, .totalColumnSpan = 2, .leftLabelColumnSpan = 1 } ); + gridBoxGroup->appendToRow( &maxJ ); + gridBoxGroup->appendToRow( &maxK ); + gridBoxGroup->add( &makeInvisibleCellsInactive, { .newRow = true, .totalColumnSpan = 2, .leftLabelColumnSpan = 1 } ); minI.uiCapability()->setUiReadOnly( exportGridBox() != MANUAL_SELECTION ); minJ.uiCapability()->setUiReadOnly( exportGridBox() != MANUAL_SELECTION ); @@ -333,9 +333,9 @@ void RicExportEclipseSectorModelUi::defineUiOrdering( QString uiConfigName, caf: maxK.uiCapability()->setUiReadOnly( exportGridBox() != MANUAL_SELECTION ); caf::PdmUiGroup* gridRefinement = uiOrdering.addNewGroup( "Grid Refinement" ); - gridRefinement->add( &refinementCountI, { true, 2, 1 } ); - gridRefinement->add( &refinementCountJ, { false } ); - gridRefinement->add( &refinementCountK, { false } ); + gridRefinement->add( &refinementCountI, { .newRow = true, .totalColumnSpan = 2, .leftLabelColumnSpan = 1 } ); + gridRefinement->appendToRow( &refinementCountJ ); + gridRefinement->appendToRow( &refinementCountK ); refinementCountI.uiCapability()->setUiReadOnly( !exportGrid() ); refinementCountJ.uiCapability()->setUiReadOnly( !exportGrid() ); refinementCountK.uiCapability()->setUiReadOnly( !exportGrid() ); diff --git a/ApplicationLibCode/Commands/ExportCommands/RicExportLgrUi.cpp b/ApplicationLibCode/Commands/ExportCommands/RicExportLgrUi.cpp index 3dd7b7ba79..afdbcfe1cb 100644 --- a/ApplicationLibCode/Commands/ExportCommands/RicExportLgrUi.cpp +++ b/ApplicationLibCode/Commands/ExportCommands/RicExportLgrUi.cpp @@ -220,19 +220,19 @@ void RicExportLgrUi::fieldChangedByUi( const caf::PdmFieldHandle* changedField, //-------------------------------------------------------------------------------------------------- void RicExportLgrUi::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) { - caf::PdmUiOrdering::LayoutOptions layout( true, 6, 1 ); + caf::PdmUiOrdering::LayoutOptions layout = { .newRow = true, .totalColumnSpan = 6, .leftLabelColumnSpan = 1 }; uiOrdering.add( &m_caseToApply, layout ); uiOrdering.add( &m_timeStep, layout ); uiOrdering.add( &m_exportFolder, layout ); uiOrdering.add( &m_includeFractures, layout ); uiOrdering.add( &m_includeFishbones, layout ); uiOrdering.add( &m_includePerforations, layout ); - uiOrdering.add( &m_splitType, { true, 6, 1 } ); + uiOrdering.add( &m_splitType, { .newRow = true, .totalColumnSpan = 6, .leftLabelColumnSpan = 1 } ); caf::PdmUiGroup* gridRefinement = uiOrdering.addNewGroup( "Grid Refinement" ); - gridRefinement->add( &m_cellCountI, { true, 2, 1 } ); - gridRefinement->add( &m_cellCountJ, { false } ); - gridRefinement->add( &m_cellCountK, { false } ); + gridRefinement->add( &m_cellCountI, { .newRow = true, .totalColumnSpan = 2, .leftLabelColumnSpan = 1 } ); + gridRefinement->appendToRow( &m_cellCountJ ); + gridRefinement->appendToRow( &m_cellCountK ); // uiOrdering.add(&m_wellPathsInfo); uiOrdering.skipRemainingFields( true ); diff --git a/ApplicationLibCode/Commands/ExportCommands/RicSaveEclipseInputVisibleCellsUi.h b/ApplicationLibCode/Commands/ExportCommands/RicSaveEclipseInputVisibleCellsUi.h index dec2d74d22..560a8970c3 100644 --- a/ApplicationLibCode/Commands/ExportCommands/RicSaveEclipseInputVisibleCellsUi.h +++ b/ApplicationLibCode/Commands/ExportCommands/RicSaveEclipseInputVisibleCellsUi.h @@ -31,6 +31,7 @@ class RicSaveEclipseInputVisibleCellsUi : public caf::PdmObject CAF_PDM_HEADER_INIT; public: + // Values are exposed in gRPC .proto. Do not change without also changing .proto enum ExportKeyword { FLUXNUM, diff --git a/ApplicationLibCode/Commands/GeoMechCommands/RicNewFaultReactModelingFeature.cpp b/ApplicationLibCode/Commands/GeoMechCommands/RicNewFaultReactModelingFeature.cpp index 9591b0a2b3..3ef13c393a 100644 --- a/ApplicationLibCode/Commands/GeoMechCommands/RicNewFaultReactModelingFeature.cpp +++ b/ApplicationLibCode/Commands/GeoMechCommands/RicNewFaultReactModelingFeature.cpp @@ -93,16 +93,10 @@ void RicNewFaultReactModelingFeature::onActionTriggered( bool isChecked ) normal *= eclView->ownerCase()->characteristicCellSize(); normal *= 3; - auto antiNormal = -1.0 * normal; + if ( !eclView->mainGrid()->isFaceNormalsOutwards() ) normal = normal * -1.0; - auto camPos = eclView->viewer()->mainCamera()->position(); - - auto target1 = cell.faceCenter( face ); - auto candidate1 = target1 + normal; - auto candidate2 = target1 + antiNormal; - auto target2 = candidate1; - - if ( camPos.pointDistance( candidate2 ) < camPos.pointDistance( candidate1 ) ) target2 = candidate2; + cvf::Vec3d target1 = cell.faceCenter( face ); + cvf::Vec3d target2 = target1 + normal; // get base directory for our work, should be a new, empty folder somewhere QString defaultDir = @@ -112,7 +106,8 @@ void RicNewFaultReactModelingFeature::onActionTriggered( bool isChecked ) if ( baseDir.isNull() || baseDir.isEmpty() ) return; QString errMsg; - auto model = eclView->faultReactivationModelCollection()->addNewModel( rimFault, target1, target2, baseDir, errMsg ); + auto model = + eclView->faultReactivationModelCollection()->addNewModel( rimFault, currentCellIndex, face, target1, target2, baseDir, errMsg ); if ( model != nullptr ) { model->updateTimeSteps(); diff --git a/ApplicationLibCode/Commands/OperationsUsingObjReferences/CMakeLists_files.cmake b/ApplicationLibCode/Commands/OperationsUsingObjReferences/CMakeLists_files.cmake index 2aef75e722..26aece0cb1 100644 --- a/ApplicationLibCode/Commands/OperationsUsingObjReferences/CMakeLists_files.cmake +++ b/ApplicationLibCode/Commands/OperationsUsingObjReferences/CMakeLists_files.cmake @@ -6,6 +6,7 @@ set(SOURCE_GROUP_HEADER_FILES ${CMAKE_CURRENT_LIST_DIR}/RicPasteEclipseViewsFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicPasteGeoMechViewsFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicPasteIntersectionsFeature.h + ${CMAKE_CURRENT_LIST_DIR}/RicPasteCellFiltersFeature.h ) set(SOURCE_GROUP_SOURCE_FILES @@ -16,6 +17,7 @@ set(SOURCE_GROUP_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/RicPasteEclipseViewsFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicPasteGeoMechViewsFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicPasteIntersectionsFeature.cpp + ${CMAKE_CURRENT_LIST_DIR}/RicPasteCellFiltersFeature.cpp ) list(APPEND COMMAND_CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES}) diff --git a/ApplicationLibCode/Commands/OperationsUsingObjReferences/RicCopyReferencesToClipboardFeature.cpp b/ApplicationLibCode/Commands/OperationsUsingObjReferences/RicCopyReferencesToClipboardFeature.cpp index 61cd114bd9..83bf35ea71 100644 --- a/ApplicationLibCode/Commands/OperationsUsingObjReferences/RicCopyReferencesToClipboardFeature.cpp +++ b/ApplicationLibCode/Commands/OperationsUsingObjReferences/RicCopyReferencesToClipboardFeature.cpp @@ -20,6 +20,7 @@ #include "RicCopyReferencesToClipboardFeature.h" #include "RimBoxIntersection.h" +#include "RimCellFilter.h" #include "RimEclipseCase.h" #include "RimEclipseView.h" #include "RimEnsembleCurveSet.h" @@ -136,6 +137,7 @@ bool RicCopyReferencesToClipboardFeature::isCopyOfObjectSupported( caf::PdmObjec if ( dynamic_cast( pdmObject ) ) return true; if ( dynamic_cast( pdmObject ) ) return true; if ( dynamic_cast( pdmObject ) ) return true; + if ( dynamic_cast( pdmObject ) ) return true; // Copy support based combined logic RimWellAllocationPlot* wellAllocPlot = pdmObject->firstAncestorOrThisOfType(); diff --git a/ApplicationLibCode/Commands/OperationsUsingObjReferences/RicPasteCellFiltersFeature.cpp b/ApplicationLibCode/Commands/OperationsUsingObjReferences/RicPasteCellFiltersFeature.cpp new file mode 100644 index 0000000000..c809985609 --- /dev/null +++ b/ApplicationLibCode/Commands/OperationsUsingObjReferences/RicPasteCellFiltersFeature.cpp @@ -0,0 +1,99 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 "RicPasteCellFiltersFeature.h" + +#include "RicPasteFeatureImpl.h" + +#include "RimCase.h" +#include "RimCellFilter.h" +#include "RimCellFilterCollection.h" + +#include "cafPdmObjectGroup.h" +#include "cafPdmPointer.h" +#include "cafSelectionManager.h" + +#include + +CAF_CMD_SOURCE_INIT( RicPasteCellFiltersFeature, "RicPasteCellFiltersFeature" ); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RicPasteCellFiltersFeature::isCommandEnabled() const +{ + caf::PdmObjectGroup objectGroup; + RicPasteFeatureImpl::findObjectsFromClipboardRefs( &objectGroup ); + + std::vector> typedObjects; + objectGroup.objectsByType( &typedObjects ); + if ( typedObjects.empty() ) + { + return false; + } + + if ( dynamic_cast( caf::SelectionManager::instance()->selectedItem() ) ) + { + return true; + } + + return false; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicPasteCellFiltersFeature::onActionTriggered( bool isChecked ) +{ + auto cellFilterCollection = dynamic_cast( caf::SelectionManager::instance()->selectedItem() ); + if ( !cellFilterCollection ) return; + + auto eclipseCase = cellFilterCollection->firstAncestorOfType(); + + caf::PdmObjectGroup objectGroup; + RicPasteFeatureImpl::findObjectsFromClipboardRefs( &objectGroup ); + + for ( auto obj : objectGroup.objects ) + { + auto duplicatedObject = + dynamic_cast( obj->xmlCapability()->copyByXmlSerialization( caf::PdmDefaultObjectFactory::instance() ) ); + + if ( duplicatedObject ) + { + cellFilterCollection->addFilterAndNotifyChanges( duplicatedObject, eclipseCase ); + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicPasteCellFiltersFeature::setupActionLook( QAction* actionToSetup ) +{ + actionToSetup->setText( "Paste Filter" ); + + RicPasteFeatureImpl::setIconAndShortcuts( actionToSetup ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicPasteCellFiltersFeature::pasteGeometryCellFilters( RimCellFilterCollection* cellFilterCollection ) +{ + if ( !cellFilterCollection ) return; +} diff --git a/ApplicationLibCode/Commands/OperationsUsingObjReferences/RicPasteCellFiltersFeature.h b/ApplicationLibCode/Commands/OperationsUsingObjReferences/RicPasteCellFiltersFeature.h new file mode 100644 index 0000000000..aedc9df244 --- /dev/null +++ b/ApplicationLibCode/Commands/OperationsUsingObjReferences/RicPasteCellFiltersFeature.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 "cafCmdFeature.h" + +class RimCellFilterCollection; + +//================================================================================================== +/// +//================================================================================================== +class RicPasteCellFiltersFeature : public caf::CmdFeature +{ + CAF_CMD_HEADER_INIT; + +protected: + bool isCommandEnabled() const override; + void onActionTriggered( bool isChecked ) override; + void setupActionLook( QAction* actionToSetup ) override; + +private: + void pasteGeometryCellFilters( RimCellFilterCollection* cellFilterCollection ); +}; diff --git a/ApplicationLibCode/Commands/PlotBuilderCommands/RicAppendSummaryPlotsForObjectsFeature.cpp b/ApplicationLibCode/Commands/PlotBuilderCommands/RicAppendSummaryPlotsForObjectsFeature.cpp index 9d2fca8c24..434cef964d 100644 --- a/ApplicationLibCode/Commands/PlotBuilderCommands/RicAppendSummaryPlotsForObjectsFeature.cpp +++ b/ApplicationLibCode/Commands/PlotBuilderCommands/RicAppendSummaryPlotsForObjectsFeature.cpp @@ -77,6 +77,7 @@ void RicAppendSummaryPlotsForObjectsFeature::appendPlots( RimSummaryMultiPlot* if ( summaryAdrCollection->contentType() == RimSummaryAddressCollection::CollectionContentType::SUMMARY_CASE ) { summaryMultiPlot->addPlot( duplicatedPlot ); + duplicatedPlot->resolveReferencesRecursively(); auto summaryCase = RiaSummaryTools::summaryCaseById( summaryAdrCollection->caseId() ); if ( summaryCase ) @@ -84,6 +85,7 @@ void RicAppendSummaryPlotsForObjectsFeature::appendPlots( RimSummaryMultiPlot* for ( auto c : duplicatedPlot->summaryCurves() ) { c->setSummaryCaseY( summaryCase ); + c->setSummaryCaseX( summaryCase ); } } @@ -98,14 +100,11 @@ void RicAppendSummaryPlotsForObjectsFeature::appendPlots( RimSummaryMultiPlot* } else { - auto adrMods = RimSummaryAddressModifier::createAddressModifiersForPlot( duplicatedPlot ); - for ( auto adrMod : adrMods ) - { - auto sourceAddress = adrMod.address(); - auto modifiedAdr = modifyAddress( sourceAddress, summaryAdrCollection ); + const auto objectName = summaryAdrCollection->name().toStdString(); + auto contentType = summaryAdrCollection->contentType(); + auto curveProviders = RimSummaryAddressModifier::createAddressProviders( duplicatedPlot ); + RimSummaryAddressModifier::updateAddressesByObjectName( curveProviders, objectName, contentType ); - adrMod.setAddress( modifiedAdr ); - } summaryMultiPlot->addPlot( duplicatedPlot ); duplicatedPlot->resolveReferencesRecursively(); } @@ -247,7 +246,7 @@ bool RicAppendSummaryPlotsForObjectsFeature::isSelectionCompatibleWithPlot( cons for ( auto plot : plotsForObjectType ) { - auto addresses = RimSummaryAddressModifier::createEclipseSummaryAddress( plot ); + auto addresses = RimSummaryAddressModifier::allSummaryAddressesY( plot ); analyzer.appendAddresses( addresses ); } } @@ -284,45 +283,6 @@ bool RicAppendSummaryPlotsForObjectsFeature::isSelectionCompatibleWithPlot( cons return true; } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -RifEclipseSummaryAddress RicAppendSummaryPlotsForObjectsFeature::modifyAddress( const RifEclipseSummaryAddress& sourceAddress, - RimSummaryAddressCollection* summaryAddressCollection ) -{ - CAF_ASSERT( summaryAddressCollection ); - - auto adr = sourceAddress; - - auto objectName = summaryAddressCollection->name().toStdString(); - if ( summaryAddressCollection->contentType() == RimSummaryAddressCollection::CollectionContentType::WELL ) - { - adr.setWellName( objectName ); - } - else if ( summaryAddressCollection->contentType() == RimSummaryAddressCollection::CollectionContentType::GROUP ) - { - adr.setGroupName( objectName ); - } - else if ( summaryAddressCollection->contentType() == RimSummaryAddressCollection::CollectionContentType::REGION ) - { - int intValue = RiaStdStringTools::toInt( objectName ); - if ( intValue == -1 ) - { - QString errorText = QString( "Failed to convert region text to region integer value " - "for region text : " ) + - summaryAddressCollection->name(); - - RiaLogging::error( errorText ); - } - else - { - adr.setRegion( intValue ); - } - } - - return adr; -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -341,7 +301,7 @@ std::vector RiaSummaryAddressAnalyzer myAnalyser; for ( auto sourcePlot : sourcePlots ) { - auto addresses = RimSummaryAddressModifier::createEclipseSummaryAddress( sourcePlot ); + auto addresses = RimSummaryAddressModifier::allSummaryAddressesY( sourcePlot ); myAnalyser.appendAddresses( addresses ); } @@ -396,7 +356,7 @@ std::vector } else { - auto addresses = RimSummaryAddressModifier::createEclipseSummaryAddress( sourcePlot ); + auto addresses = RimSummaryAddressModifier::allSummaryAddressesY( sourcePlot ); for ( const auto& a : addresses ) { diff --git a/ApplicationLibCode/Commands/PlotBuilderCommands/RicAppendSummaryPlotsForObjectsFeature.h b/ApplicationLibCode/Commands/PlotBuilderCommands/RicAppendSummaryPlotsForObjectsFeature.h index 1a73852403..594b238a42 100644 --- a/ApplicationLibCode/Commands/PlotBuilderCommands/RicAppendSummaryPlotsForObjectsFeature.h +++ b/ApplicationLibCode/Commands/PlotBuilderCommands/RicAppendSummaryPlotsForObjectsFeature.h @@ -62,7 +62,4 @@ class RicAppendSummaryPlotsForObjectsFeature : public caf::CmdFeature private: static std::vector createAddressCollections( const std::vector& cases, const std::vector& ensembles ); - - static RifEclipseSummaryAddress modifyAddress( const RifEclipseSummaryAddress& sourceAddress, - RimSummaryAddressCollection* summaryAddressCollection ); }; diff --git a/ApplicationLibCode/Commands/PlotBuilderCommands/RicNewSummaryMultiPlotFromDataVectorFeature.cpp b/ApplicationLibCode/Commands/PlotBuilderCommands/RicNewSummaryMultiPlotFromDataVectorFeature.cpp index c2bd8af901..91006dedb6 100644 --- a/ApplicationLibCode/Commands/PlotBuilderCommands/RicNewSummaryMultiPlotFromDataVectorFeature.cpp +++ b/ApplicationLibCode/Commands/PlotBuilderCommands/RicNewSummaryMultiPlotFromDataVectorFeature.cpp @@ -125,7 +125,7 @@ void RicNewSummaryMultiPlotFromDataVectorFeature::onActionTriggered( bool isChec if ( !addr.isHistoryVector() ) { auto historyAddr = addr; - historyAddr.setVectorName( addr.vectorName() + RifReaderEclipseSummary::historyIdentifier() ); + historyAddr.setVectorName( addr.vectorName() + RifEclipseSummaryAddressDefines::historyIdentifier() ); if ( availableAddresses.count( historyAddr ) > 0 ) eclipseAddresses.insert( historyAddr ); } diff --git a/ApplicationLibCode/Commands/PlotTemplateCommands/RicSaveMultiPlotTemplateFeature.cpp b/ApplicationLibCode/Commands/PlotTemplateCommands/RicSaveMultiPlotTemplateFeature.cpp index a44c3cf7d2..293c791b20 100644 --- a/ApplicationLibCode/Commands/PlotTemplateCommands/RicSaveMultiPlotTemplateFeature.cpp +++ b/ApplicationLibCode/Commands/PlotTemplateCommands/RicSaveMultiPlotTemplateFeature.cpp @@ -166,7 +166,7 @@ QString RicSaveMultiPlotTemplateFeature::createTextFromObject( RimSummaryMultiPl std::set sourceStrings; const QString summaryFieldKeyword = RicSummaryPlotTemplateTools::summaryCaseFieldKeyword(); - for ( const auto& curve : summaryPlot->allCurves( RimSummaryDataSourceStepping::Axis::Y_AXIS ) ) + for ( const auto& curve : summaryPlot->allCurves() ) { auto fieldHandle = curve->findField( summaryFieldKeyword ); if ( fieldHandle ) @@ -186,7 +186,7 @@ QString RicSaveMultiPlotTemplateFeature::createTextFromObject( RimSummaryMultiPl std::set sourceStrings; const QString summaryFieldKeyword = RicSummaryPlotTemplateTools::summaryCaseXFieldKeyword(); - for ( const auto& curve : summaryPlot->allCurves( RimSummaryDataSourceStepping::Axis::Y_AXIS ) ) + for ( const auto& curve : summaryPlot->allCurves() ) { if ( curve->axisTypeX() != RiaDefines::HorizontalAxisType::SUMMARY_VECTOR ) continue; diff --git a/ApplicationLibCode/Commands/PlotTemplateCommands/RicSummaryPlotTemplateTools.cpp b/ApplicationLibCode/Commands/PlotTemplateCommands/RicSummaryPlotTemplateTools.cpp index 0717d016d0..bd02e4765c 100644 --- a/ApplicationLibCode/Commands/PlotTemplateCommands/RicSummaryPlotTemplateTools.cpp +++ b/ApplicationLibCode/Commands/PlotTemplateCommands/RicSummaryPlotTemplateTools.cpp @@ -247,7 +247,7 @@ void RicSummaryPlotTemplateTools::setValuesForPlaceholders( RimSummaryPlot* { // Replace single summary curves data sources - auto summaryCurves = summaryPlot->allCurves( RimSummaryDataSourceStepping::Axis::Y_AXIS ); + auto summaryCurves = summaryPlot->allCurves(); for ( const auto& curve : summaryCurves ) { auto summaryCaseHandle = curve->findField( RicSummaryPlotTemplateTools::summaryCaseFieldKeyword() ); diff --git a/ApplicationLibCode/Commands/RicCreateTemporaryLgrFeature.cpp b/ApplicationLibCode/Commands/RicCreateTemporaryLgrFeature.cpp index d845392420..27d9a7cfa5 100644 --- a/ApplicationLibCode/Commands/RicCreateTemporaryLgrFeature.cpp +++ b/ApplicationLibCode/Commands/RicCreateTemporaryLgrFeature.cpp @@ -285,16 +285,18 @@ void RicCreateTemporaryLgrFeature::deleteAllCachedData( RimEclipseCase* eclipseC { if ( eclipseCase ) { + std::vector categoriesToExclude = { RiaDefines::ResultCatType::GENERATED }; + RigCaseCellResultsData* cellResultsDataMatrix = eclipseCase->results( RiaDefines::PorosityModelType::MATRIX_MODEL ); if ( cellResultsDataMatrix ) { - cellResultsDataMatrix->freeAllocatedResultsData(); + cellResultsDataMatrix->freeAllocatedResultsData( categoriesToExclude, std::nullopt ); } RigCaseCellResultsData* cellResultsDataFracture = eclipseCase->results( RiaDefines::PorosityModelType::FRACTURE_MODEL ); if ( cellResultsDataFracture ) { - cellResultsDataFracture->freeAllocatedResultsData(); + cellResultsDataFracture->freeAllocatedResultsData( categoriesToExclude, std::nullopt ); } RigEclipseCaseData* eclipseCaseData = eclipseCase->eclipseCaseData(); diff --git a/ApplicationLibCode/Commands/RicExportGridCalculationExpressionsFeature.cpp b/ApplicationLibCode/Commands/RicExportGridCalculationExpressionsFeature.cpp new file mode 100644 index 0000000000..53a5b35d00 --- /dev/null +++ b/ApplicationLibCode/Commands/RicExportGridCalculationExpressionsFeature.cpp @@ -0,0 +1,115 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 "RicExportGridCalculationExpressionsFeature.h" + +#include "RiaGuiApplication.h" +#include "RiaLogging.h" +#include "RiaPreferences.h" + +#include "RifGridCalculation.h" +#include "RifGridCalculationExporter.h" +#include "RimGridCalculationCollection.h" +#include "RimGridCalculationVariable.h" +#include "RimProject.h" + +#include "Riu3DMainWindowTools.h" +#include "RiuFileDialogTools.h" + +#include +#include +#include + +CAF_CMD_SOURCE_INIT( RicExportGridCalculationExpressionsFeature, "RicExportGridCalculationExpressionsFeature" ); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RicExportGridCalculationExpressionsFeature::gridCalculationExpressionId() +{ + return "GRID_CALCULATION_EXPRESSION"; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicExportGridCalculationExpressionsFeature::onActionTriggered( bool isChecked ) +{ + auto proj = RimProject::current(); + auto calcColl = proj->gridCalculationCollection(); + + if ( calcColl->calculations().empty() ) return; + + QString fallbackPath = RiaPreferences::current()->gridCalculationExpressionFolder(); + auto app = RiaGuiApplication::instance(); + QString startPath = + app->lastUsedDialogDirectoryWithFallback( RicExportGridCalculationExpressionsFeature::gridCalculationExpressionId(), fallbackPath ); + + QString fileName = RiuFileDialogTools::getSaveFileName( nullptr, + "Select File for Grid Calculation Expression Export", + startPath, + "Toml File(*.toml);;All files(*.*)" ); + if ( fileName.isEmpty() ) return; + + auto fi = QFileInfo( fileName ); + if ( fi.suffix().isEmpty() ) + { + fileName += ".toml"; + } + QString absPath = fi.absolutePath(); + + app->setLastUsedDialogDirectory( RicExportGridCalculationExpressionsFeature::gridCalculationExpressionId(), absPath ); + + std::vector calculations; + for ( auto calculation : calcColl->calculations() ) + { + RifGridCalculation calc; + calc.description = calculation->description().toStdString(); + calc.expression = calculation->expression().toStdString(); + for ( auto variable : calculation->allVariables() ) + { + if ( auto gridVariable = dynamic_cast( variable ) ) + { + RifGridCalculationVariable var; + var.resultVariable = gridVariable->resultVariable().toStdString(); + var.resultType = caf::AppEnum::text( gridVariable->resultCategoryType() ).toStdString(); + var.name = gridVariable->name().toStdString(); + calc.variables.push_back( var ); + } + } + + calculations.push_back( calc ); + } + + auto [isOk, errorMessage] = RifGridCalculationExporter::writeToFile( calculations, fileName.toStdString() ); + if ( !isOk ) + { + RiaLogging::errorInMessageBox( Riu3DMainWindowTools::mainWindowWidget(), + "Grid Calculation Export Error", + QString::fromStdString( errorMessage ) ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicExportGridCalculationExpressionsFeature::setupActionLook( QAction* actionToSetup ) +{ + actionToSetup->setText( "Export Grid Calculation Expressions" ); + actionToSetup->setIcon( QIcon( ":/Calculator.svg" ) ); +} diff --git a/ApplicationLibCode/Commands/RicExportGridCalculationExpressionsFeature.h b/ApplicationLibCode/Commands/RicExportGridCalculationExpressionsFeature.h new file mode 100644 index 0000000000..50b7d89655 --- /dev/null +++ b/ApplicationLibCode/Commands/RicExportGridCalculationExpressionsFeature.h @@ -0,0 +1,35 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 "cafCmdFeature.h" + +//================================================================================================== +/// +//================================================================================================== +class RicExportGridCalculationExpressionsFeature : public caf::CmdFeature +{ + CAF_CMD_HEADER_INIT; + + static QString gridCalculationExpressionId(); + +private: + void onActionTriggered( bool isChecked ) override; + void setupActionLook( QAction* actionToSetup ) override; +}; diff --git a/ApplicationLibCode/Commands/RicExportSummaryCalculationExpressionsFeature.cpp b/ApplicationLibCode/Commands/RicExportSummaryCalculationExpressionsFeature.cpp new file mode 100644 index 0000000000..c2bd8c196e --- /dev/null +++ b/ApplicationLibCode/Commands/RicExportSummaryCalculationExpressionsFeature.cpp @@ -0,0 +1,120 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 "RicExportSummaryCalculationExpressionsFeature.h" + +#include "RiaGuiApplication.h" +#include "RiaLogging.h" +#include "RiaPreferences.h" + +#include "RifSummaryCalculation.h" +#include "RifSummaryCalculationExporter.h" +#include "RimProject.h" +#include "RimSummaryAddress.h" +#include "RimSummaryCalculationCollection.h" +#include "RimSummaryCalculationVariable.h" + +#include "RiuFileDialogTools.h" +#include "RiuPlotMainWindow.h" + +#include +#include +#include + +CAF_CMD_SOURCE_INIT( RicExportSummaryCalculationExpressionsFeature, "RicExportSummaryCalculationExpressionsFeature" ); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RicExportSummaryCalculationExpressionsFeature::summaryCalculationExpressionId() +{ + return "SUMMARY_CALCULATION_EXPRESSION"; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicExportSummaryCalculationExpressionsFeature::onActionTriggered( bool isChecked ) +{ + auto proj = RimProject::current(); + auto calcColl = proj->calculationCollection(); + + if ( calcColl->calculations().empty() ) return; + + QString fallbackPath = RiaPreferences::current()->summaryCalculationExpressionFolder(); + auto app = RiaGuiApplication::instance(); + QString startPath = + app->lastUsedDialogDirectoryWithFallback( RicExportSummaryCalculationExpressionsFeature::summaryCalculationExpressionId(), + fallbackPath ); + + QString fileName = RiuFileDialogTools::getSaveFileName( nullptr, + "Select File for Summary Calculation Expression Export", + startPath, + "Toml File(*.toml);;All files(*.*)" ); + if ( fileName.isEmpty() ) return; + + auto fi = QFileInfo( fileName ); + if ( fi.suffix().isEmpty() ) + { + fileName += ".toml"; + } + QString absPath = fi.absolutePath(); + + app->setLastUsedDialogDirectory( RicExportSummaryCalculationExpressionsFeature::summaryCalculationExpressionId(), absPath ); + + std::vector calculations; + for ( auto calculation : calcColl->calculations() ) + { + if ( auto summaryCalculation = dynamic_cast( calculation ) ) + { + RifSummaryCalculation calc; + calc.expression = calculation->expression().toStdString(); + calc.unit = calculation->unitName().toStdString(); + calc.distributeToAllCases = summaryCalculation->isDistributeToAllCases(); + calc.distributeToOther = summaryCalculation->isDistributeToOtherItems(); + + for ( auto variable : calculation->allVariables() ) + { + if ( auto gridVariable = dynamic_cast( variable ) ) + { + RifSummaryCalculationVariable var; + var.address = gridVariable->summaryAddress()->address().toEclipseTextAddress(); + var.name = gridVariable->name().toStdString(); + calc.variables.push_back( var ); + } + } + + calculations.push_back( calc ); + } + } + + auto [isOk, errorMessage] = RifSummaryCalculationExporter::writeToFile( calculations, fileName.toStdString() ); + if ( !isOk ) + { + RiaLogging::errorInMessageBox( RiuPlotMainWindow::instance(), "Summary Calculation Export Error", QString::fromStdString( errorMessage ) ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicExportSummaryCalculationExpressionsFeature::setupActionLook( QAction* actionToSetup ) +{ + actionToSetup->setText( "Export Summary Calculation Expressions" ); + actionToSetup->setIcon( QIcon( ":/Calculator.svg" ) ); +} diff --git a/ApplicationLibCode/Commands/RicExportSummaryCalculationExpressionsFeature.h b/ApplicationLibCode/Commands/RicExportSummaryCalculationExpressionsFeature.h new file mode 100644 index 0000000000..51a477b9c0 --- /dev/null +++ b/ApplicationLibCode/Commands/RicExportSummaryCalculationExpressionsFeature.h @@ -0,0 +1,35 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 "cafCmdFeature.h" + +//================================================================================================== +/// +//================================================================================================== +class RicExportSummaryCalculationExpressionsFeature : public caf::CmdFeature +{ + CAF_CMD_HEADER_INIT; + + static QString summaryCalculationExpressionId(); + +private: + void onActionTriggered( bool isChecked ) override; + void setupActionLook( QAction* actionToSetup ) override; +}; diff --git a/ApplicationLibCode/Commands/RicGridCalculatorUi.cpp b/ApplicationLibCode/Commands/RicGridCalculatorUi.cpp index de33f232cc..09d7f74799 100644 --- a/ApplicationLibCode/Commands/RicGridCalculatorUi.cpp +++ b/ApplicationLibCode/Commands/RicGridCalculatorUi.cpp @@ -22,6 +22,9 @@ #include "RimProject.h" #include "RimUserDefinedCalculationCollection.h" +#include "cafCmdFeature.h" +#include "cafCmdFeatureManager.h" + CAF_PDM_SOURCE_INIT( RicGridCalculatorUi, "RicGridCalculator" ); //-------------------------------------------------------------------------------------------------- @@ -62,3 +65,25 @@ RimUserDefinedCalculationCollection* RicGridCalculatorUi::calculationCollection( { return RimProject::current()->gridCalculationCollection(); } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicGridCalculatorUi::exportCalculations() +{ + if ( auto feature = caf::CmdFeatureManager::instance()->getCommandFeature( "RicExportGridCalculationExpressionsFeature" ) ) + { + feature->action()->trigger(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicGridCalculatorUi::importCalculations() +{ + if ( auto feature = caf::CmdFeatureManager::instance()->getCommandFeature( "RicImportGridCalculationExpressionsFeature" ) ) + { + feature->action()->trigger(); + } +} diff --git a/ApplicationLibCode/Commands/RicGridCalculatorUi.h b/ApplicationLibCode/Commands/RicGridCalculatorUi.h index 7798a8ee95..db5f3425e8 100644 --- a/ApplicationLibCode/Commands/RicGridCalculatorUi.h +++ b/ApplicationLibCode/Commands/RicGridCalculatorUi.h @@ -36,4 +36,8 @@ class RicGridCalculatorUi : public RicUserDefinedCalculatorUi QString calulationGroupName() const override; RimUserDefinedCalculationCollection* calculationCollection() const override; void notifyCalculatedNameChanged( int id, const QString& newName ) const override; + +protected: + void exportCalculations() override; + void importCalculations() override; }; diff --git a/ApplicationLibCode/Commands/RicImportGridCalculationExpressionsFeature.cpp b/ApplicationLibCode/Commands/RicImportGridCalculationExpressionsFeature.cpp new file mode 100644 index 0000000000..f761dcdb33 --- /dev/null +++ b/ApplicationLibCode/Commands/RicImportGridCalculationExpressionsFeature.cpp @@ -0,0 +1,117 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 "RicImportGridCalculationExpressionsFeature.h" +#include "RicExportGridCalculationExpressionsFeature.h" + +#include "RiaGuiApplication.h" +#include "RiaLogging.h" +#include "RiaPreferences.h" + +#include "RimEclipseCaseTools.h" +#include "RimEclipseResultAddress.h" +#include "RimGridCalculationCollection.h" +#include "RimGridCalculationVariable.h" +#include "RimProject.h" + +#include "Riu3DMainWindowTools.h" +#include "RiuFileDialogTools.h" + +#include "RifGridCalculationImporter.h" + +#include "cafPdmDefaultObjectFactory.h" +#include "cafPdmXmlObjectHandle.h" + +#include +#include +#include +#include + +CAF_CMD_SOURCE_INIT( RicImportGridCalculationExpressionsFeature, "RicImportGridCalculationExpressionsFeature" ); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicImportGridCalculationExpressionsFeature::onActionTriggered( bool isChecked ) +{ + auto app = RiaGuiApplication::instance(); + + QString defaultDir = app->lastUsedDialogDirectoryWithFallback( RicExportGridCalculationExpressionsFeature::gridCalculationExpressionId(), + RiaPreferences::current()->gridCalculationExpressionFolder() ); + + QString fileName = + RiuFileDialogTools::getOpenFileName( nullptr, "Import Grid Calculation Expressions", defaultDir, "Toml File(*.toml);;All files(*.*)" ); + if ( fileName.isEmpty() ) return; + + auto [calculations, errorMessage] = RifGridCalculationImporter::readFromFile( fileName.toStdString() ); + if ( !errorMessage.empty() ) + { + RiaLogging::errorInMessageBox( Riu3DMainWindowTools::mainWindowWidget(), + "Grid Calculation Import Error", + QString::fromStdString( errorMessage ) ); + return; + } + + auto proj = RimProject::current(); + auto calcColl = proj->gridCalculationCollection(); + + RimEclipseCase* firstCase = nullptr; + auto eclCases = RimEclipseCaseTools::allEclipseGridCases(); + if ( !eclCases.empty() ) firstCase = eclCases.front(); + + for ( auto calc : calculations ) + { + bool addDefaultExpression = false; + auto gridCalculation = dynamic_cast( calcColl->addCalculation( addDefaultExpression ) ); + if ( gridCalculation ) + { + gridCalculation->setExpression( QString::fromStdString( calc.expression ) ); + gridCalculation->setDescription( QString::fromStdString( calc.description ) ); + gridCalculation->setUnit( QString::fromStdString( calc.unit ) ); + for ( auto var : calc.variables ) + { + auto variable = dynamic_cast( gridCalculation->addVariable( QString::fromStdString( var.name ) ) ); + RimEclipseResultAddress address; + + RiaDefines::ResultCatType myEnum = + caf::AppEnum::fromText( QString::fromStdString( var.resultType ) ); + address.setEclipseCase( firstCase ); + address.setResultName( QString::fromStdString( var.resultVariable ) ); + address.setResultType( myEnum ); + variable->setEclipseResultAddress( address ); + } + + if ( firstCase ) + { + gridCalculation->assignEclipseCaseForNullPointers( firstCase ); + } + } + } + + QString absPath = QFileInfo( fileName ).absolutePath(); + app->setLastUsedDialogDirectory( RicExportGridCalculationExpressionsFeature::gridCalculationExpressionId(), absPath ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicImportGridCalculationExpressionsFeature::setupActionLook( QAction* actionToSetup ) +{ + actionToSetup->setText( "Import Grid Calculation Expressions" ); + actionToSetup->setIcon( QIcon( ":/Calculator.svg" ) ); +} diff --git a/ApplicationLibCode/Commands/RicImportGridCalculationExpressionsFeature.h b/ApplicationLibCode/Commands/RicImportGridCalculationExpressionsFeature.h new file mode 100644 index 0000000000..fce6ba20e7 --- /dev/null +++ b/ApplicationLibCode/Commands/RicImportGridCalculationExpressionsFeature.h @@ -0,0 +1,33 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 "cafCmdFeature.h" + +//================================================================================================== +/// +//================================================================================================== +class RicImportGridCalculationExpressionsFeature : public caf::CmdFeature +{ + CAF_CMD_HEADER_INIT; + +private: + void onActionTriggered( bool isChecked ) override; + void setupActionLook( QAction* actionToSetup ) override; +}; diff --git a/ApplicationLibCode/Commands/RicImportSummaryCalculationExpressionsFeature.cpp b/ApplicationLibCode/Commands/RicImportSummaryCalculationExpressionsFeature.cpp new file mode 100644 index 0000000000..c595db5f55 --- /dev/null +++ b/ApplicationLibCode/Commands/RicImportSummaryCalculationExpressionsFeature.cpp @@ -0,0 +1,116 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 "RicImportSummaryCalculationExpressionsFeature.h" +#include "RicExportSummaryCalculationExpressionsFeature.h" + +#include "RiaGuiApplication.h" +#include "RiaLogging.h" +#include "RiaPreferences.h" + +#include "RimOilField.h" +#include "RimProject.h" +#include "RimSummaryAddress.h" +#include "RimSummaryCalculationCollection.h" +#include "RimSummaryCalculationVariable.h" +#include "RimSummaryCase.h" +#include "RimSummaryCaseMainCollection.h" + +#include "RiuFileDialogTools.h" +#include "RiuPlotMainWindow.h" + +#include "RifSummaryCalculationImporter.h" + +#include +#include +#include +#include + +CAF_CMD_SOURCE_INIT( RicImportSummaryCalculationExpressionsFeature, "RicImportSummaryCalculationExpressionsFeature" ); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicImportSummaryCalculationExpressionsFeature::onActionTriggered( bool isChecked ) +{ + auto app = RiaGuiApplication::instance(); + + QString defaultDir = + app->lastUsedDialogDirectoryWithFallback( RicExportSummaryCalculationExpressionsFeature::summaryCalculationExpressionId(), + RiaPreferences::current()->summaryCalculationExpressionFolder() ); + + QString fileName = + RiuFileDialogTools::getOpenFileName( nullptr, "Import Summary Calculation Expressions", defaultDir, "Toml File(*.toml);;All files(*.*)" ); + if ( fileName.isEmpty() ) return; + + auto [calculations, errorMessage] = RifSummaryCalculationImporter::readFromFile( fileName.toStdString() ); + if ( !errorMessage.empty() ) + { + RiaLogging::errorInMessageBox( RiuPlotMainWindow::instance(), "Summary Calculation Import Error", QString::fromStdString( errorMessage ) ); + return; + } + + auto proj = RimProject::current(); + auto calcColl = proj->calculationCollection(); + + RimSummaryCaseMainCollection* sumCaseColl = proj->activeOilField() ? proj->activeOilField()->summaryCaseMainCollection() : nullptr; + RimSummaryCase* firstCase = nullptr; + if ( sumCaseColl && !sumCaseColl->allSummaryCases().empty() ) + { + firstCase = sumCaseColl->allSummaryCases().front(); + } + + for ( auto calc : calculations ) + { + bool addDefaultExpression = false; + auto summaryCalculation = dynamic_cast( calcColl->addCalculation( addDefaultExpression ) ); + if ( summaryCalculation ) + { + summaryCalculation->setExpression( QString::fromStdString( calc.expression ) ); + summaryCalculation->setDescription( QString::fromStdString( calc.expression ) ); + summaryCalculation->setUnit( QString::fromStdString( calc.unit ) ); + summaryCalculation->setDistributeToAllCases( calc.distributeToAllCases ); + summaryCalculation->setDistributeToOtherItems( calc.distributeToOther ); + + for ( auto var : calc.variables ) + { + auto variable = + dynamic_cast( summaryCalculation->addVariable( QString::fromStdString( var.name ) ) ); + RifEclipseSummaryAddress address = RifEclipseSummaryAddress::fromEclipseTextAddress( var.address ); + + RimSummaryAddress summaryAddress; + summaryAddress.setAddress( address ); + if ( firstCase ) summaryAddress.setCaseId( firstCase->caseId() ); + variable->setSummaryAddress( summaryAddress ); + variable->setName( QString::fromStdString( var.name ) ); + } + } + } + + QString absPath = QFileInfo( fileName ).absolutePath(); + app->setLastUsedDialogDirectory( RicExportSummaryCalculationExpressionsFeature::summaryCalculationExpressionId(), absPath ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicImportSummaryCalculationExpressionsFeature::setupActionLook( QAction* actionToSetup ) +{ + actionToSetup->setText( "Import Grid Calculation Expressions" ); + actionToSetup->setIcon( QIcon( ":/Calculator.svg" ) ); +} diff --git a/ApplicationLibCode/Commands/RicImportSummaryCalculationExpressionsFeature.h b/ApplicationLibCode/Commands/RicImportSummaryCalculationExpressionsFeature.h new file mode 100644 index 0000000000..58d0367ce7 --- /dev/null +++ b/ApplicationLibCode/Commands/RicImportSummaryCalculationExpressionsFeature.h @@ -0,0 +1,33 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 "cafCmdFeature.h" + +//================================================================================================== +/// +//================================================================================================== +class RicImportSummaryCalculationExpressionsFeature : public caf::CmdFeature +{ + CAF_CMD_HEADER_INIT; + +private: + void onActionTriggered( bool isChecked ) override; + void setupActionLook( QAction* actionToSetup ) override; +}; diff --git a/ApplicationLibCode/Commands/RicNewContourMapViewFeature.cpp b/ApplicationLibCode/Commands/RicNewContourMapViewFeature.cpp index b39fc11a86..8611c14ec1 100644 --- a/ApplicationLibCode/Commands/RicNewContourMapViewFeature.cpp +++ b/ApplicationLibCode/Commands/RicNewContourMapViewFeature.cpp @@ -276,6 +276,10 @@ RimEclipseContourMapView* RicNewContourMapViewFeature::createEclipseContourMapFr //-------------------------------------------------------------------------------------------------- RimEclipseContourMapView* RicNewContourMapViewFeature::createEclipseContourMap( RimEclipseCase* eclipseCase ) { + // Make sure case is open before accessing active cell info + eclipseCase->ensureReservoirCaseIsOpen(); + if ( !eclipseCase->eclipseCaseData() ) return nullptr; + RimEclipseContourMapView* contourMap = new RimEclipseContourMapView(); contourMap->setEclipseCase( eclipseCase ); diff --git a/ApplicationLibCode/Commands/RicNewViewFeature.cpp b/ApplicationLibCode/Commands/RicNewViewFeature.cpp index e784879aac..1907f42cd3 100644 --- a/ApplicationLibCode/Commands/RicNewViewFeature.cpp +++ b/ApplicationLibCode/Commands/RicNewViewFeature.cpp @@ -19,6 +19,8 @@ #include "RicNewViewFeature.h" +#include "RiaLogging.h" + #include "Rim3dView.h" #include "RimEclipseCase.h" #include "RimEclipseContourMapView.h" @@ -26,7 +28,6 @@ #include "RimGeoMechCase.h" #include "RimGeoMechView.h" -#include "RiaLogging.h" #include "Riu3DMainWindowTools.h" #include "cafSelectionManager.h" @@ -45,6 +46,9 @@ void RicNewViewFeature::addReservoirView( RimEclipseCase* eclipseCase, RimGeoMec if ( newView ) { Riu3DMainWindowTools::setExpanded( newView ); + + // Select the new view to make sure RiaApplication::setActiveReservoirView() is called + Riu3DMainWindowTools::selectAsCurrentItem( newView ); } } diff --git a/ApplicationLibCode/Commands/RicUserDefinedCalculatorUi.cpp b/ApplicationLibCode/Commands/RicUserDefinedCalculatorUi.cpp index 16197bc80a..771f36f912 100644 --- a/ApplicationLibCode/Commands/RicUserDefinedCalculatorUi.cpp +++ b/ApplicationLibCode/Commands/RicUserDefinedCalculatorUi.cpp @@ -25,7 +25,6 @@ #include "cafPdmUiListEditor.h" #include "cafPdmUiObjectEditorHandle.h" #include "cafPdmUiPushButtonEditor.h" -#include "cafPdmUiTreeSelectionEditor.h" CAF_PDM_ABSTRACT_SOURCE_INIT( RicUserDefinedCalculatorUi, "RicUserDefinedCalculator" ); @@ -38,7 +37,6 @@ RicUserDefinedCalculatorUi::RicUserDefinedCalculatorUi() CAF_PDM_InitFieldNoDefault( &m_currentCalculation, "CurrentCalculation", "" ); m_currentCalculation.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::HIDDEN ); - // m_currentCalculation.uiCapability()->setUiEditorTypeName(caf::PdmUiTreeSelectionEditor::uiEditorTypeName()); m_currentCalculation.uiCapability()->setUiEditorTypeName( caf::PdmUiListEditor::uiEditorTypeName() ); CAF_PDM_InitFieldNoDefault( &m_newCalculation, "NewCalculation", "New Calculation" ); @@ -47,7 +45,13 @@ RicUserDefinedCalculatorUi::RicUserDefinedCalculatorUi() CAF_PDM_InitFieldNoDefault( &m_deleteCalculation, "DeleteCalculation", "Delete Calculation" ); RicUserDefinedCalculatorUi::assignPushButtonEditor( &m_deleteCalculation ); - m_calcContextMenuMgr = std::unique_ptr( new RiuCalculationsContextMenuManager() ); + CAF_PDM_InitFieldNoDefault( &m_importCalculations, "ImportCalculations", "Import Calculations" ); + RicUserDefinedCalculatorUi::assignPushButtonEditor( &m_importCalculations ); + + CAF_PDM_InitFieldNoDefault( &m_exportCalculations, "ExportCalculations", "Export Calculations" ); + RicUserDefinedCalculatorUi::assignPushButtonEditor( &m_exportCalculations ); + + m_calcContextMenuMgr = std::make_unique(); } //-------------------------------------------------------------------------------------------------- @@ -64,6 +68,8 @@ RimUserDefinedCalculation* RicUserDefinedCalculatorUi::currentCalculation() cons void RicUserDefinedCalculatorUi::setCurrentCalculation( RimUserDefinedCalculation* calculation ) { m_currentCalculation = calculation; + + connectSignals( m_currentCalculation() ); } //-------------------------------------------------------------------------------------------------- @@ -101,6 +107,7 @@ void RicUserDefinedCalculatorUi::fieldChangedByUi( const caf::PdmFieldHandle* ch m_newCalculation = false; m_currentCalculation = calculationCollection()->addCalculation(); + connectSignals( m_currentCalculation ); updateConnectedEditors(); } @@ -117,6 +124,20 @@ void RicUserDefinedCalculatorUi::fieldChangedByUi( const caf::PdmFieldHandle* ch caf::PdmUiObjectEditorHandle::updateUiAllObjectEditors(); } } + else if ( changedField == &m_currentCalculation && m_currentCalculation() ) + { + connectSignals( m_currentCalculation() ); + } + else if ( changedField == &m_importCalculations ) + { + importCalculations(); + m_importCalculations = false; + } + else if ( changedField == &m_exportCalculations ) + { + exportCalculations(); + m_exportCalculations = false; + } } //-------------------------------------------------------------------------------------------------- @@ -126,14 +147,14 @@ void RicUserDefinedCalculatorUi::defineUiOrdering( QString uiConfigName, caf::Pd { if ( !m_currentCalculation() && !calculationCollection()->calculations().empty() ) { - m_currentCalculation = calculationCollection()->calculations()[0]; + setCurrentCalculation( calculationCollection()->calculations()[0] ); } { caf::PdmUiGroup* group = uiOrdering.addNewGroupWithKeyword( "Calculations", calculationsGroupName() ); group->add( &m_currentCalculation ); group->add( &m_newCalculation ); - group->add( &m_deleteCalculation ); + group->appendToRow( &m_deleteCalculation ); } { @@ -143,6 +164,13 @@ void RicUserDefinedCalculatorUi::defineUiOrdering( QString uiConfigName, caf::Pd m_currentCalculation->uiOrdering( uiConfigName, *group ); } } + + caf::PdmUiGroup* group = uiOrdering.findGroup( calculationsGroupName() ); + if ( group ) + { + group->add( &m_importCalculations ); + group->appendToRow( &m_exportCalculations ); + } } //-------------------------------------------------------------------------------------------------- @@ -179,7 +207,7 @@ void RicUserDefinedCalculatorUi::assignPushButtonEditor( caf::PdmFieldHandle* fi //-------------------------------------------------------------------------------------------------- void RicUserDefinedCalculatorUi::assignPushButtonEditorText( caf::PdmUiEditorAttribute* attribute, const QString& text ) { - caf::PdmUiPushButtonEditorAttribute* attrib = dynamic_cast( attribute ); + auto* attrib = dynamic_cast( attribute ); if ( attrib ) { attrib->m_buttonText = text; @@ -205,6 +233,11 @@ bool RicUserDefinedCalculatorUi::calculate() const notifyCalculatedNameChanged( m_currentCalculation()->id(), currentCurveName ); } + if ( !m_currentCalculation()->preCalculate() ) + { + return false; + } + if ( !m_currentCalculation()->calculate() ) { return false; @@ -230,6 +263,14 @@ void RicUserDefinedCalculatorUi::defineEditorAttribute( const caf::PdmFieldHandl { RicUserDefinedCalculatorUi::assignPushButtonEditorText( attribute, "Delete Calculation" ); } + else if ( &m_importCalculations == field ) + { + RicUserDefinedCalculatorUi::assignPushButtonEditorText( attribute, "Import Calculations" ); + } + else if ( &m_exportCalculations == field ) + { + RicUserDefinedCalculatorUi::assignPushButtonEditorText( attribute, "Export Calculations" ); + } } //-------------------------------------------------------------------------------------------------- @@ -244,7 +285,7 @@ void RicUserDefinedCalculatorUi::onEditorWidgetsCreated() for ( const auto& e : m_currentCalculation.uiCapability()->connectedEditors() ) { - caf::PdmUiListEditor* listEditor = dynamic_cast( e ); + auto* listEditor = dynamic_cast( e ); if ( !listEditor ) continue; QWidget* widget = listEditor->editorWidget(); @@ -253,3 +294,22 @@ void RicUserDefinedCalculatorUi::onEditorWidgetsCreated() m_calcContextMenuMgr->attachWidget( widget, this ); } } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicUserDefinedCalculatorUi::onVariableUpdated( const SignalEmitter* emitter ) +{ + updateConnectedEditors(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicUserDefinedCalculatorUi::connectSignals( RimUserDefinedCalculation* calculation ) +{ + if ( calculation ) + { + calculation->variableUpdated.connect( this, &RicUserDefinedCalculatorUi::onVariableUpdated ); + } +} diff --git a/ApplicationLibCode/Commands/RicUserDefinedCalculatorUi.h b/ApplicationLibCode/Commands/RicUserDefinedCalculatorUi.h index 05d40297ef..13f8609adb 100644 --- a/ApplicationLibCode/Commands/RicUserDefinedCalculatorUi.h +++ b/ApplicationLibCode/Commands/RicUserDefinedCalculatorUi.h @@ -19,9 +19,11 @@ #pragma once #include "RiuCalculationsContextMenuManager.h" + #include "cafPdmField.h" #include "cafPdmObject.h" #include "cafPdmPtrField.h" + #include class RimUserDefinedCalculationCollection; @@ -48,23 +50,31 @@ class RicUserDefinedCalculatorUi : public caf::PdmObject virtual RimUserDefinedCalculationCollection* calculationCollection() const = 0; virtual void notifyCalculatedNameChanged( int id, const QString& newName ) const = 0; -private: - void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override; +protected: void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override; - QList calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions ) override; + void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override; void defineEditorAttribute( const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute ) override; - void onEditorWidgetsCreated() override; + QList calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions ) override; + void onEditorWidgetsCreated() override; + + virtual void exportCalculations() = 0; + virtual void importCalculations() = 0; -private: // TODO : Move to a common caf helper class static void assignPushButtonEditor( caf::PdmFieldHandle* fieldHandle ); static void assignPushButtonEditorText( caf::PdmUiEditorAttribute* attribute, const QString& text ); +private: + void onVariableUpdated( const SignalEmitter* emitter ); + void connectSignals( RimUserDefinedCalculation* calculation ); + private: caf::PdmPtrField m_currentCalculation; caf::PdmField m_newCalculation; caf::PdmField m_deleteCalculation; + caf::PdmField m_exportCalculations; + caf::PdmField m_importCalculations; std::unique_ptr m_calcContextMenuMgr; }; diff --git a/ApplicationLibCode/Commands/SeismicCommands/RicImportSeismicFeature.cpp b/ApplicationLibCode/Commands/SeismicCommands/RicImportSeismicFeature.cpp index ddc62fe7b0..5a6e56bea0 100644 --- a/ApplicationLibCode/Commands/SeismicCommands/RicImportSeismicFeature.cpp +++ b/ApplicationLibCode/Commands/SeismicCommands/RicImportSeismicFeature.cpp @@ -69,12 +69,7 @@ void RicImportSeismicFeature::onActionTriggered( bool isChecked ) if ( !seisColl ) return; - RimSeismicDataInterface* newData = seisColl->importSeismicFromFile( fileName ); - - // workaround to make tree selection work, otherwise "Cell Results" gets selected for some reason - QApplication::processEvents(); - - if ( newData ) + if ( auto newData = seisColl->importSeismicFromFile( fileName ) ) { Riu3DMainWindowTools::selectAsCurrentItem( newData ); diff --git a/ApplicationLibCode/Commands/SummaryPlotCommands/RicSummaryCurveCalculatorUi.cpp b/ApplicationLibCode/Commands/SummaryPlotCommands/RicSummaryCurveCalculatorUi.cpp index acef817ca5..cfe135d6ba 100644 --- a/ApplicationLibCode/Commands/SummaryPlotCommands/RicSummaryCurveCalculatorUi.cpp +++ b/ApplicationLibCode/Commands/SummaryPlotCommands/RicSummaryCurveCalculatorUi.cpp @@ -25,6 +25,9 @@ #include "RimUserDefinedCalculation.h" #include "RimUserDefinedCalculationCollection.h" +#include "cafCmdFeature.h" +#include "cafCmdFeatureManager.h" + CAF_PDM_SOURCE_INIT( RicSummaryCurveCalculatorUi, "RicSummaryCurveCalculator" ); //-------------------------------------------------------------------------------------------------- @@ -66,3 +69,25 @@ RimUserDefinedCalculationCollection* RicSummaryCurveCalculatorUi::calculationCol { return RimProject::current()->calculationCollection(); } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicSummaryCurveCalculatorUi::exportCalculations() +{ + if ( auto feature = caf::CmdFeatureManager::instance()->getCommandFeature( "RicExportSummaryCalculationExpressionsFeature" ) ) + { + feature->action()->trigger(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicSummaryCurveCalculatorUi::importCalculations() +{ + if ( auto feature = caf::CmdFeatureManager::instance()->getCommandFeature( "RicImportSummaryCalculationExpressionsFeature" ) ) + { + feature->action()->trigger(); + } +} \ No newline at end of file diff --git a/ApplicationLibCode/Commands/SummaryPlotCommands/RicSummaryCurveCalculatorUi.h b/ApplicationLibCode/Commands/SummaryPlotCommands/RicSummaryCurveCalculatorUi.h index 60f3728b24..6a61a2d913 100644 --- a/ApplicationLibCode/Commands/SummaryPlotCommands/RicSummaryCurveCalculatorUi.h +++ b/ApplicationLibCode/Commands/SummaryPlotCommands/RicSummaryCurveCalculatorUi.h @@ -36,4 +36,8 @@ class RicSummaryCurveCalculatorUi : public RicUserDefinedCalculatorUi QString calulationGroupName() const override; RimUserDefinedCalculationCollection* calculationCollection() const override; void notifyCalculatedNameChanged( int id, const QString& newName ) const override; + +protected: + void exportCalculations() override; + void importCalculations() override; }; diff --git a/ApplicationLibCode/Commands/SummaryPlotCommands/RicSummaryPlotEditorUi.cpp b/ApplicationLibCode/Commands/SummaryPlotCommands/RicSummaryPlotEditorUi.cpp index 82dc74aaed..28b5a8b808 100644 --- a/ApplicationLibCode/Commands/SummaryPlotCommands/RicSummaryPlotEditorUi.cpp +++ b/ApplicationLibCode/Commands/SummaryPlotCommands/RicSummaryPlotEditorUi.cpp @@ -97,10 +97,7 @@ RicSummaryPlotEditorUi::RicSummaryPlotEditorUi() CAF_PDM_InitFieldNoDefault( &m_regionAppearanceType, "RegionAppearanceType", "Region" ); m_previewPlot = std::make_unique(); - - CAF_PDM_InitFieldNoDefault( &m_useAutoPlotTitleProxy, "UseAutoPlotTitle", "Auto Plot Title" ); - m_useAutoPlotTitleProxy.registerGetMethod( this, &RicSummaryPlotEditorUi::proxyPlotAutoTitle ); - m_useAutoPlotTitleProxy.registerSetMethod( this, &RicSummaryPlotEditorUi::proxyEnablePlotAutoTitle ); + m_previewPlot->setLegendPosition( RiuPlotWidget::Legend::TOP ); CAF_PDM_InitFieldNoDefault( &m_applyButtonField, "ApplySelection", "" ); m_applyButtonField = false; @@ -173,6 +170,7 @@ void RicSummaryPlotEditorUi::updateFromSummaryPlot( RimSummaryPlot* targetPlot, { setDefaultCurveSelection( defaultSources ); m_previewPlot->enableAutoPlotTitle( true ); + m_previewPlot->setPlotTitleVisible( false ); syncPreviewCurvesFromUiSelection(); m_plotContainer = nullptr; } @@ -263,12 +261,6 @@ void RicSummaryPlotEditorUi::fieldChangedByUi( const caf::PdmFieldHandle* change m_previewPlot->loadDataAndUpdate(); m_appearanceApplyButton = false; } - else if ( changedField == &m_useAutoPlotTitleProxy ) - { - m_previewPlot->updatePlotTitle(); - - m_previewPlot->summaryCurveCollection()->updateConnectedEditors(); - } } //-------------------------------------------------------------------------------------------------- @@ -328,8 +320,6 @@ void RicSummaryPlotEditorUi::defineUiOrdering( QString uiConfigName, caf::PdmUiO uiOrdering.addNewGroupWithKeyword( "Plot and Curve Name Configuration", RiuSummaryCurveDefinitionKeywords::nameConfig() ); autoNameGroup->setCollapsedByDefault(); - autoNameGroup->add( &m_useAutoPlotTitleProxy ); - m_curveNameConfig->uiOrdering( uiConfigName, *autoNameGroup ); // Fields to be displayed directly in UI @@ -705,8 +695,6 @@ void RicSummaryPlotEditorUi::updateTargetPlot() newCurveSet->setParentPlotNoReplot( m_targetPlot->plotWidget() ); } - m_targetPlot->enableAutoPlotTitle( m_useAutoPlotTitleProxy() ); - m_targetPlot->loadDataAndUpdate(); m_targetPlot->updateConnectedEditors(); @@ -718,7 +706,7 @@ void RicSummaryPlotEditorUi::updateTargetPlot() //-------------------------------------------------------------------------------------------------- void RicSummaryPlotEditorUi::copyCurveAndAddToPlot( const RimSummaryCurve* curve, RimSummaryPlot* plot, bool forceVisible ) { - RimSummaryCurve* curveCopy = + auto curveCopy = dynamic_cast( curve->xmlCapability()->copyByXmlSerialization( caf::PdmDefaultObjectFactory::instance() ) ); CVF_ASSERT( curveCopy ); @@ -727,11 +715,11 @@ void RicSummaryPlotEditorUi::copyCurveAndAddToPlot( const RimSummaryCurve* curve curveCopy->setCheckState( true ); } - plot->addCurveNoUpdate( curveCopy, false ); - curveCopy->setLeftOrRightAxisY( curve->axisY() ); - - // The curve creator is not a descendant of the project, and need to be set manually curveCopy->setSummaryCaseY( curve->summaryCaseY() ); + + bool autoAssignAxis = true; + plot->addCurveNoUpdate( curveCopy, autoAssignAxis ); + curveCopy->initAfterReadRecursively(); curveCopy->loadDataAndUpdate( false ); } @@ -915,25 +903,6 @@ void RicSummaryPlotEditorUi::selectionEditorFieldChanged() syncPreviewCurvesFromUiSelection(); } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RicSummaryPlotEditorUi::proxyEnablePlotAutoTitle( const bool& enable ) -{ - m_previewPlot->enableAutoPlotTitle( enable ); - m_previewPlot->setPlotTitleVisible( enable ); - m_previewPlot->updateCurveNames(); - m_previewPlot->loadDataAndUpdate(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool RicSummaryPlotEditorUi::proxyPlotAutoTitle() const -{ - return m_previewPlot->autoPlotTitle(); -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/Commands/SummaryPlotCommands/RicSummaryPlotEditorUi.h b/ApplicationLibCode/Commands/SummaryPlotCommands/RicSummaryPlotEditorUi.h index b0d179dde3..893815274e 100644 --- a/ApplicationLibCode/Commands/SummaryPlotCommands/RicSummaryPlotEditorUi.h +++ b/ApplicationLibCode/Commands/SummaryPlotCommands/RicSummaryPlotEditorUi.h @@ -103,9 +103,6 @@ class RicSummaryPlotEditorUi : public caf::PdmObject bool isObservedData( RimSummaryCase* sumCase ) const; void selectionEditorFieldChanged(); - - void proxyEnablePlotAutoTitle( const bool& enable ); - bool proxyPlotAutoTitle() const; void setInitialCurveVisibility( const RimSummaryPlot* targetPlot ); private: @@ -113,8 +110,6 @@ class RicSummaryPlotEditorUi : public caf::PdmObject std::unique_ptr m_previewPlot; - caf::PdmProxyValueField m_useAutoPlotTitleProxy; - caf::PdmField m_useAutoAppearanceAssignment; caf::PdmField m_appearanceApplyButton; caf::PdmField m_caseAppearanceType; diff --git a/ApplicationLibCode/Commands/SummaryPlotCommands/RicSummaryPlotEditorWidgetCreator.cpp b/ApplicationLibCode/Commands/SummaryPlotCommands/RicSummaryPlotEditorWidgetCreator.cpp index f9bd40abc9..ecb14439c4 100644 --- a/ApplicationLibCode/Commands/SummaryPlotCommands/RicSummaryPlotEditorWidgetCreator.cpp +++ b/ApplicationLibCode/Commands/SummaryPlotCommands/RicSummaryPlotEditorWidgetCreator.cpp @@ -148,16 +148,6 @@ QWidget* RicSummaryPlotEditorWidgetCreator::createWidget( QWidget* parent ) m_lowerRightLayout->setContentsMargins( 0, 0, 0, 0 ); m_secondRowLayout->addLayout( m_lowerRightLayout ); - { - auto label = new QLabel( "Plot Preview" ); - label->setAlignment( Qt::AlignCenter ); - auto font = label->font(); - font.setPixelSize( 20 ); - label->setFont( font ); - - m_lowerRightLayout->insertWidget( 0, label ); - } - m_firstColumnSplitter = new QSplitter( Qt::Vertical ); m_firstColumnSplitter->setContentsMargins( 0, 0, 0, 0 ); diff --git a/ApplicationLibCode/Commands/WellLogCommands/CMakeLists_files.cmake b/ApplicationLibCode/Commands/WellLogCommands/CMakeLists_files.cmake index a6df37a9af..069574882e 100644 --- a/ApplicationLibCode/Commands/WellLogCommands/CMakeLists_files.cmake +++ b/ApplicationLibCode/Commands/WellLogCommands/CMakeLists_files.cmake @@ -31,6 +31,8 @@ set(SOURCE_GROUP_HEADER_FILES ${CMAKE_CURRENT_LIST_DIR}/RicNewRftSegmentWellLogPlotFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicNewMultiPhaseRftSegmentPlotFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicNewWellLogCalculatedCurveFeature.h + ${CMAKE_CURRENT_LIST_DIR}/RicCreateRftPlotsFeature.h + ${CMAKE_CURRENT_LIST_DIR}/RicCreateRftPlotsFeatureUi.h ) set(SOURCE_GROUP_SOURCE_FILES @@ -66,6 +68,8 @@ set(SOURCE_GROUP_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/RicNewRftSegmentWellLogPlotFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicNewMultiPhaseRftSegmentPlotFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicNewWellLogCalculatedCurveFeature.cpp + ${CMAKE_CURRENT_LIST_DIR}/RicCreateRftPlotsFeature.cpp + ${CMAKE_CURRENT_LIST_DIR}/RicCreateRftPlotsFeatureUi.cpp ) list(APPEND COMMAND_CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES}) diff --git a/ApplicationLibCode/Commands/WellLogCommands/RicCreateRftPlotsFeature.cpp b/ApplicationLibCode/Commands/WellLogCommands/RicCreateRftPlotsFeature.cpp new file mode 100644 index 0000000000..274daa40f4 --- /dev/null +++ b/ApplicationLibCode/Commands/WellLogCommands/RicCreateRftPlotsFeature.cpp @@ -0,0 +1,167 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 "RicCreateRftPlotsFeature.h" + +#include "RiaLogging.h" + +#include "RicCreateRftPlotsFeatureUi.h" + +#include "RifReaderRftInterface.h" + +#include "RimMainPlotCollection.h" +#include "RimRftPlotCollection.h" +#include "RimSummaryCase.h" +#include "RimSummaryCaseCollection.h" +#include "RimWellLogPlotNameConfig.h" +#include "RimWellLogTrack.h" +#include "RimWellPlotTools.h" +#include "RimWellRftPlot.h" + +#include "RiuPlotMainWindowTools.h" + +#include "cafPdmUiPropertyViewDialog.h" +#include "cafSelectionManager.h" + +#include + +CAF_CMD_SOURCE_INIT( RicCreateRftPlotsFeature, "RicCreateRftPlotsFeature" ); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicCreateRftPlotsFeature::onActionTriggered( bool isChecked ) +{ + auto sourcePlot = dynamic_cast( caf::SelectionManager::instance()->selectedItem() ); + if ( !sourcePlot ) return; + + RimRftPlotCollection* rftPlotColl = RimMainPlotCollection::current()->rftPlotCollection(); + if ( !rftPlotColl ) return; + + std::set wellsWithRftData; + + auto dataSource = sourcePlot->dataSource(); + if ( auto summaryCollection = std::get_if( &dataSource ) ) + { + wellsWithRftData = ( *summaryCollection )->wellsWithRftData(); + } + else if ( auto summaryCase = std::get_if( &dataSource ) ) + { + RifReaderRftInterface* reader = ( *summaryCase )->rftReader(); + if ( reader ) + { + wellsWithRftData = reader->wellNames(); + } + } + + if ( wellsWithRftData.empty() ) return; + + RicCreateRftPlotsFeatureUi ui; + ui.setAllWellNames( { wellsWithRftData.begin(), wellsWithRftData.end() } ); + + caf::PdmUiPropertyViewDialog propertyDialog( nullptr, &ui, "Select RFT wells", "" ); + if ( propertyDialog.exec() != QDialog::Accepted ) return; + + for ( const auto& wellName : ui.selectedWellNames() ) + { + appendRftPlotForWell( wellName, rftPlotColl, sourcePlot ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicCreateRftPlotsFeature::appendRftPlotForWell( const QString& wellName, RimRftPlotCollection* rftPlotColl, RimWellRftPlot* sourcePlot ) +{ + if ( !rftPlotColl ) + { + RiaLogging::error( "Missing RFT plot collection, no RFT plot created." ); + return; + } + + if ( !sourcePlot ) + { + RiaLogging::error( "Missing source RFT plot, no RFT plot created." ); + return; + } + + // Create a RFT plot based on wellName, and reuse the data source selection in sourcePlot + + auto rftPlot = + dynamic_cast( sourcePlot->xmlCapability()->copyByXmlSerialization( caf::PdmDefaultObjectFactory::instance() ) ); + if ( !rftPlot ) return; + + rftPlot->setSimWellOrWellPathName( wellName ); + rftPlotColl->addPlot( rftPlot ); + rftPlot->resolveReferencesRecursively(); + rftPlot->applyInitialSelections( sourcePlot->dataSource() ); + + const auto generatedName = rftPlot->simWellOrWellPathName(); // We may have been given a default well name + const QString plotName = QString( RimWellRftPlot::plotNameFormatString() ).arg( generatedName ); + + rftPlot->nameConfig()->setCustomName( plotName ); + + rftPlot->loadDataAndUpdate(); + rftPlotColl->updateConnectedEditors(); + + RiuPlotMainWindowTools::showPlotMainWindow(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicCreateRftPlotsFeature::appendRftPlotForWell( const QString& wellName, RimRftPlotCollection* rftPlotColl ) +{ + if ( !rftPlotColl ) + { + RiaLogging::error( "Missing RFT plot collection, no RFT plot created." ); + return; + } + + // Create a default RFT plot based on well name, and toggle on all available data sources in this RFT plot + + auto rftPlot = new RimWellRftPlot(); + rftPlot->setSimWellOrWellPathName( wellName ); + + auto plotTrack = new RimWellLogTrack(); + rftPlot->addPlot( plotTrack ); + plotTrack->setDescription( QString( "Track %1" ).arg( rftPlot->plotCount() ) ); + + rftPlotColl->addPlot( rftPlot ); + rftPlot->applyInitialSelections( {} ); + + const auto generatedName = rftPlot->simWellOrWellPathName(); // We may have been given a default well name + const QString plotName = QString( RimWellRftPlot::plotNameFormatString() ).arg( generatedName ); + + rftPlot->nameConfig()->setCustomName( plotName ); + rftPlot->setNamingMethod( RiaDefines::ObjectNamingMethod::CUSTOM ); + rftPlot->loadDataAndUpdate(); + rftPlotColl->updateConnectedEditors(); + + RiuPlotMainWindowTools::showPlotMainWindow(); + RiuPlotMainWindowTools::onObjectAppended( rftPlot, plotTrack ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicCreateRftPlotsFeature::setupActionLook( QAction* actionToSetup ) +{ + actionToSetup->setText( "Create Multiple RFT Plots" ); + actionToSetup->setIcon( QIcon( ":/FlowCharPlot16x16.png" ) ); +} diff --git a/ApplicationLibCode/Commands/WellLogCommands/RicCreateRftPlotsFeature.h b/ApplicationLibCode/Commands/WellLogCommands/RicCreateRftPlotsFeature.h new file mode 100644 index 0000000000..2f738d0b0e --- /dev/null +++ b/ApplicationLibCode/Commands/WellLogCommands/RicCreateRftPlotsFeature.h @@ -0,0 +1,44 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 "cafCmdFeature.h" + +#include + +#include + +class RimRftPlotCollection; +class RimWellRftPlot; + +//================================================================================================== +/// +//================================================================================================== +class RicCreateRftPlotsFeature : public caf::CmdFeature +{ + CAF_CMD_HEADER_INIT; + + static void appendRftPlotForWell( const QString& wellName, RimRftPlotCollection* rftPlotColl ); + +private: + void onActionTriggered( bool isChecked ) override; + void setupActionLook( QAction* actionToSetup ) override; + + void appendRftPlotForWell( const QString& wellName, RimRftPlotCollection* rftPlotColl, RimWellRftPlot* sourcePlot ); +}; diff --git a/ApplicationLibCode/Commands/WellLogCommands/RicCreateRftPlotsFeatureUi.cpp b/ApplicationLibCode/Commands/WellLogCommands/RicCreateRftPlotsFeatureUi.cpp new file mode 100644 index 0000000000..da625734d2 --- /dev/null +++ b/ApplicationLibCode/Commands/WellLogCommands/RicCreateRftPlotsFeatureUi.cpp @@ -0,0 +1,67 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 "RicCreateRftPlotsFeatureUi.h" + +#include "cafPdmUiTreeSelectionEditor.h" + +CAF_PDM_SOURCE_INIT( RicCreateRftPlotsFeatureUi, "RicCreateRftPlotsFeatureUi" ); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RicCreateRftPlotsFeatureUi::RicCreateRftPlotsFeatureUi() +{ + CAF_PDM_InitObject( "RicCreateRftPlotsFeatureUi" ); + + CAF_PDM_InitFieldNoDefault( &m_selectedWellNames, "SelectedWellNames", "Well Names" ); + m_selectedWellNames.uiCapability()->setUiEditorTypeName( caf::PdmUiTreeSelectionEditor::uiEditorTypeName() ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicCreateRftPlotsFeatureUi::setAllWellNames( const std::vector& wellNames ) +{ + m_allWellNames = wellNames; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RicCreateRftPlotsFeatureUi::selectedWellNames() const +{ + return m_selectedWellNames(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QList RicCreateRftPlotsFeatureUi::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions ) +{ + QList options; + if ( fieldNeedingOptions == &m_selectedWellNames ) + { + for ( const auto& wellName : m_allWellNames ) + { + options.append( caf::PdmOptionItemInfo( wellName, wellName ) ); + } + } + + return options; +} diff --git a/ApplicationLibCode/Commands/WellLogCommands/RicCreateRftPlotsFeatureUi.h b/ApplicationLibCode/Commands/WellLogCommands/RicCreateRftPlotsFeatureUi.h new file mode 100644 index 0000000000..d24bd55fa8 --- /dev/null +++ b/ApplicationLibCode/Commands/WellLogCommands/RicCreateRftPlotsFeatureUi.h @@ -0,0 +1,49 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 "cafPdmField.h" +#include "cafPdmObject.h" +#include "cafPdmPtrField.h" + +#include + +#include + +//================================================================================================== +/// +//================================================================================================== +class RicCreateRftPlotsFeatureUi : public caf::PdmObject +{ + CAF_PDM_HEADER_INIT; + +public: + RicCreateRftPlotsFeatureUi(); + + void setAllWellNames( const std::vector& wellNames ); + std::vector selectedWellNames() const; + +protected: + QList calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions ) override; + +private: + caf::PdmField> m_selectedWellNames; + + std::vector m_allWellNames; +}; diff --git a/ApplicationLibCode/Commands/WellLogCommands/RicNewRftPlotFeature.cpp b/ApplicationLibCode/Commands/WellLogCommands/RicNewRftPlotFeature.cpp index 7831ebae6b..b7d0dfab25 100644 --- a/ApplicationLibCode/Commands/WellLogCommands/RicNewRftPlotFeature.cpp +++ b/ApplicationLibCode/Commands/WellLogCommands/RicNewRftPlotFeature.cpp @@ -18,16 +18,12 @@ #include "RicNewRftPlotFeature.h" +#include "RicCreateRftPlotsFeature.h" + #include "RimMainPlotCollection.h" #include "RimRftPlotCollection.h" #include "RimSimWellInView.h" -#include "RimWellLogPlot.h" -#include "RimWellLogPlotNameConfig.h" -#include "RimWellLogTrack.h" #include "RimWellPath.h" -#include "RimWellRftPlot.h" - -#include "RiuPlotMainWindowTools.h" #include "cafSelectionManagerTools.h" @@ -42,7 +38,7 @@ CAF_CMD_SOURCE_INIT( RicNewRftPlotFeature, "RicNewRftPlotFeature" ); //-------------------------------------------------------------------------------------------------- bool RicNewRftPlotFeature::isCommandEnabled() const { - RimRftPlotCollection* simWell = caf::firstAncestorOfTypeFromSelectedObject(); + auto* simWell = caf::firstAncestorOfTypeFromSelectedObject(); if ( simWell ) return true; if ( selectedWellName().isEmpty() ) @@ -63,28 +59,7 @@ void RicNewRftPlotFeature::onActionTriggered( bool isChecked ) { QString wellName = selectedWellName(); - RimWellRftPlot* rftPlot = new RimWellRftPlot(); - - rftPlot->setSimWellOrWellPathName( wellName ); - - RimWellLogTrack* plotTrack = new RimWellLogTrack(); - rftPlot->addPlot( plotTrack ); - plotTrack->setDescription( QString( "Track %1" ).arg( rftPlot->plotCount() ) ); - - rftPlotColl->addPlot( rftPlot ); - rftPlot->applyInitialSelections(); - - wellName = rftPlot->simWellOrWellPathName(); // We may have been given a default well name - QString plotName = QString( RimWellRftPlot::plotNameFormatString() ).arg( wellName ); - - rftPlot->nameConfig()->setCustomName( plotName ); - rftPlot->setNamingMethod( RiaDefines::ObjectNamingMethod::CUSTOM ); - - rftPlot->loadDataAndUpdate(); - rftPlotColl->updateConnectedEditors(); - - RiuPlotMainWindowTools::showPlotMainWindow(); - RiuPlotMainWindowTools::onObjectAppended( rftPlot, plotTrack ); + RicCreateRftPlotsFeature::appendRftPlotForWell( wellName, rftPlotColl ); } } @@ -102,11 +77,11 @@ void RicNewRftPlotFeature::setupActionLook( QAction* actionToSetup ) //-------------------------------------------------------------------------------------------------- QString RicNewRftPlotFeature::selectedWellName() { - RimSimWellInView* simWell = caf::firstAncestorOfTypeFromSelectedObject(); + auto* simWell = caf::firstAncestorOfTypeFromSelectedObject(); if ( simWell ) return simWell->name(); - RimWellPath* rimWellPath = caf::firstAncestorOfTypeFromSelectedObject(); + auto* rimWellPath = caf::firstAncestorOfTypeFromSelectedObject(); if ( rimWellPath ) return rimWellPath->name(); - return QString(); + return {}; } diff --git a/ApplicationLibCode/FileInterface/CMakeLists_files.cmake b/ApplicationLibCode/FileInterface/CMakeLists_files.cmake index c2d4e79bf6..310f3cfbd9 100644 --- a/ApplicationLibCode/FileInterface/CMakeLists_files.cmake +++ b/ApplicationLibCode/FileInterface/CMakeLists_files.cmake @@ -89,6 +89,12 @@ set(SOURCE_GROUP_HEADER_FILES ${CMAKE_CURRENT_LIST_DIR}/RifFaultReactivationModelExporter.h ${CMAKE_CURRENT_LIST_DIR}/RifThermalToStimPlanFractureXmlOutput.h ${CMAKE_CURRENT_LIST_DIR}/RifEclipseSummaryAddressDefines.h + ${CMAKE_CURRENT_LIST_DIR}/RifGridCalculation.h + ${CMAKE_CURRENT_LIST_DIR}/RifGridCalculationImporter.h + ${CMAKE_CURRENT_LIST_DIR}/RifGridCalculationExporter.h + ${CMAKE_CURRENT_LIST_DIR}/RifSummaryCalculation.h + ${CMAKE_CURRENT_LIST_DIR}/RifSummaryCalculationImporter.h + ${CMAKE_CURRENT_LIST_DIR}/RifSummaryCalculationExporter.h ) set(SOURCE_GROUP_SOURCE_FILES @@ -179,6 +185,10 @@ set(SOURCE_GROUP_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/RifFaultReactivationModelExporter.cpp ${CMAKE_CURRENT_LIST_DIR}/RifThermalToStimPlanFractureXmlOutput.cpp ${CMAKE_CURRENT_LIST_DIR}/RifEclipseSummaryAddressDefines.cpp + ${CMAKE_CURRENT_LIST_DIR}/RifGridCalculationImporter.cpp + ${CMAKE_CURRENT_LIST_DIR}/RifGridCalculationExporter.cpp + ${CMAKE_CURRENT_LIST_DIR}/RifSummaryCalculationImporter.cpp + ${CMAKE_CURRENT_LIST_DIR}/RifSummaryCalculationExporter.cpp ) list(APPEND CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES}) diff --git a/ApplicationLibCode/FileInterface/RifEclipseSummaryAddress.cpp b/ApplicationLibCode/FileInterface/RifEclipseSummaryAddress.cpp index a9bb8817fb..1de9f37e2c 100644 --- a/ApplicationLibCode/FileInterface/RifEclipseSummaryAddress.cpp +++ b/ApplicationLibCode/FileInterface/RifEclipseSummaryAddress.cpp @@ -727,6 +727,18 @@ std::string RifEclipseSummaryAddress::itemUiText() const return text; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::string RifEclipseSummaryAddress::toEclipseTextAddress() const +{ + std::string noVectorName = itemUiText(); + if ( noVectorName.empty() ) + return m_vectorName; + else + return m_vectorName + ":" + noVectorName; +} + //-------------------------------------------------------------------------------------------------- /// Returns the stringified address component requested //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/FileInterface/RifEclipseSummaryAddress.h b/ApplicationLibCode/FileInterface/RifEclipseSummaryAddress.h index 8dddb06d52..5a1af9875f 100644 --- a/ApplicationLibCode/FileInterface/RifEclipseSummaryAddress.h +++ b/ApplicationLibCode/FileInterface/RifEclipseSummaryAddress.h @@ -120,6 +120,8 @@ class RifEclipseSummaryAddress std::string ensembleStatisticsVectorName() const; + std::string toEclipseTextAddress() const; + // Derived properties std::string uiText() const; diff --git a/ApplicationLibCode/FileInterface/RifEclipseSummaryAddressDefines.cpp b/ApplicationLibCode/FileInterface/RifEclipseSummaryAddressDefines.cpp index 7ebb9ca2cf..df4a459575 100644 --- a/ApplicationLibCode/FileInterface/RifEclipseSummaryAddressDefines.cpp +++ b/ApplicationLibCode/FileInterface/RifEclipseSummaryAddressDefines.cpp @@ -73,3 +73,19 @@ std::string RifEclipseSummaryAddressDefines::statisticsTypeToString( StatisticsT caf::AppEnum enumType( type ); return enumType.uiText().toStdString(); } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::string RifEclipseSummaryAddressDefines::differenceIdentifier() +{ + return "_DIFF"; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::string RifEclipseSummaryAddressDefines::historyIdentifier() +{ + return "H"; +} diff --git a/ApplicationLibCode/FileInterface/RifEclipseSummaryAddressDefines.h b/ApplicationLibCode/FileInterface/RifEclipseSummaryAddressDefines.h index a13978928b..7eff78ef04 100644 --- a/ApplicationLibCode/FileInterface/RifEclipseSummaryAddressDefines.h +++ b/ApplicationLibCode/FileInterface/RifEclipseSummaryAddressDefines.h @@ -79,4 +79,7 @@ std::string statisticsNameP90(); std::string statisticsNameMean(); std::string statisticsTypeToString( StatisticsType type ); +std::string differenceIdentifier(); +std::string historyIdentifier(); + }; // namespace RifEclipseSummaryAddressDefines diff --git a/ApplicationLibCode/FileInterface/RifEclipseUnifiedRestartFileAccess.cpp b/ApplicationLibCode/FileInterface/RifEclipseUnifiedRestartFileAccess.cpp index 406cd9dd6c..a62874f114 100644 --- a/ApplicationLibCode/FileInterface/RifEclipseUnifiedRestartFileAccess.cpp +++ b/ApplicationLibCode/FileInterface/RifEclipseUnifiedRestartFileAccess.cpp @@ -91,11 +91,6 @@ bool RifEclipseUnifiedRestartFileAccess::openFile() if ( !m_ecl_file ) { RiaLogging::error( QString( "Failed to open file %1 using index file." ).arg( m_filename ) ); - RiaLogging::info( QString( "Will try to open file without index file." ) ); - } - else - { - RiaLogging::info( QString( "Imported file %1 using index file." ).arg( m_filename ) ); } } } @@ -118,13 +113,9 @@ bool RifEclipseUnifiedRestartFileAccess::openFile() { bool success = ecl_file_write_index( m_ecl_file, RiaStringEncodingTools::toNativeEncoded( indexFileName ).data() ); - if ( success ) - { - RiaLogging::info( QString( "Exported index file to %1 " ).arg( indexFileName ) ); - } - else + if ( !success ) { - RiaLogging::info( QString( "Failed to exported index file to %1 " ).arg( indexFileName ) ); + RiaLogging::error( QString( "Failed to exported index file to %1 " ).arg( indexFileName ) ); } } } diff --git a/ApplicationLibCode/FileInterface/RifFaultReactivationModelExporter.cpp b/ApplicationLibCode/FileInterface/RifFaultReactivationModelExporter.cpp index 6f93af3a72..c9d7113380 100644 --- a/ApplicationLibCode/FileInterface/RifFaultReactivationModelExporter.cpp +++ b/ApplicationLibCode/FileInterface/RifFaultReactivationModelExporter.cpp @@ -25,8 +25,12 @@ #include "RiaBaseDefs.h" #include "RiaEclipseUnitTools.h" #include "RiaVersionInfo.h" +#include "RiaWellLogUnitTools.h" #include "RifInpExportTools.h" +#include "RimFaultReactivationDataAccess.h" +#include "RimFaultReactivationEnums.h" +#include "RimFaultReactivationModel.h" #include #include @@ -43,20 +47,23 @@ std::pair RifFaultReactivationModelExporter::exportToStream( using PartBorderSurface = RimFaultReactivation::BorderSurface; std::vector> borders = { { PartBorderSurface::UpperSurface, "TOP" }, { PartBorderSurface::FaultSurface, "FAULT" }, - { PartBorderSurface::LowerSurface, "BASE" } }; + { PartBorderSurface::LowerSurface, "BASE" }, + { PartBorderSurface::Seabed, "SEABED" } }; // The two parts are "mirrored", so face number 4 of the two parts should face eachother. using FaultGridPart = RimFaultReactivation::GridPart; - std::map, int> faces = { { { FaultGridPart::PART1, PartBorderSurface::FaultSurface }, 4 }, - { { FaultGridPart::PART1, PartBorderSurface::UpperSurface }, 4 }, - { { FaultGridPart::PART1, PartBorderSurface::LowerSurface }, 4 }, - { { FaultGridPart::PART2, PartBorderSurface::FaultSurface }, 4 }, - { { FaultGridPart::PART2, PartBorderSurface::UpperSurface }, 4 }, - { { FaultGridPart::PART2, PartBorderSurface::LowerSurface }, 4 } }; + std::map, int> faces = { { { FaultGridPart::FW, PartBorderSurface::FaultSurface }, 4 }, + { { FaultGridPart::FW, PartBorderSurface::UpperSurface }, 4 }, + { { FaultGridPart::FW, PartBorderSurface::LowerSurface }, 4 }, + { { FaultGridPart::FW, PartBorderSurface::Seabed }, 2 }, + { { FaultGridPart::HW, PartBorderSurface::FaultSurface }, 4 }, + { { FaultGridPart::HW, PartBorderSurface::UpperSurface }, 4 }, + { { FaultGridPart::HW, PartBorderSurface::LowerSurface }, 4 }, + { { FaultGridPart::HW, PartBorderSurface::Seabed }, 2 } }; std::map partNames = { - { FaultGridPart::PART1, "LEFT_PART" }, - { FaultGridPart::PART2, "RIGHT_PART" }, + { FaultGridPart::FW, "FW" }, + { FaultGridPart::HW, "HW" }, }; std::map boundaries = { @@ -71,7 +78,19 @@ std::pair RifFaultReactivationModelExporter::exportToStream( { RimFaultReactivation::ElementSets::UnderBurden, "UNDERBURDEN" }, }; - double faultFriction = 0.0; + double faultFriction = 0.0; + bool useGridVoidRatio = rimModel.useGridVoidRatio(); + bool useGridPorePressure = rimModel.useGridPorePressure(); + bool useGridTemperature = rimModel.useGridTemperature(); + bool useGridDensity = rimModel.useGridDensity(); + bool useGridElasticProperties = rimModel.useGridElasticProperties(); + bool useGridStress = rimModel.useGridStress(); + + double seaBedDepth = rimModel.seaBedDepth(); + double waterDensity = rimModel.waterDensity(); + double seaWaterLoad = RiaWellLogUnitTools::gravityAcceleration() * seaBedDepth * waterDensity; + + auto dataAccess = rimModel.dataAccess(); auto model = rimModel.model(); CAF_ASSERT( !model.isNull() ); @@ -79,13 +98,27 @@ std::pair RifFaultReactivationModelExporter::exportToStream( std::vector()>> methods = { [&]() { return printHeading( stream, applicationNameAndVersion ); }, [&]() { return printParts( stream, *model, partNames, borders, faces, boundaries, materialNames ); }, - [&]() { return printAssembly( stream, *model, partNames, rimModel.localCoordSysNormalsXY() ); }, - [&]() { return printMaterials( stream, rimModel, materialNames ); }, + [&]() { return printAssembly( stream, *model, partNames, model->modelLocalNormalsXY() ); }, + [&]() + { + return printMaterials( stream, rimModel, materialNames, *dataAccess, exportDirectory, partNames, useGridDensity, useGridElasticProperties ); + }, [&]() { return printInteractionProperties( stream, faultFriction ); }, [&]() { return printBoundaryConditions( stream, *model, partNames, boundaries ); }, - [&]() { return printPredefinedFields( stream, partNames ); }, + [&]() { return printPredefinedFields( stream, *model, *dataAccess, exportDirectory, partNames, useGridVoidRatio, useGridStress ); }, [&]() { return printInteractions( stream, partNames, borders ); }, - [&]() { return printSteps( stream, *model, partNames, rimModel.selectedTimeSteps(), exportDirectory ); }, + [&]() + { + return printSteps( stream, + *model, + *dataAccess, + partNames, + rimModel.selectedTimeSteps(), + exportDirectory, + useGridPorePressure, + useGridTemperature, + seaWaterLoad ); + }, }; for ( auto method : methods ) @@ -156,8 +189,8 @@ std::pair RifFaultReactivationModelExporter::printParts( const std::vector>& elements = grid->elementIndices(); RifInpExportTools::printElements( stream, elements ); - RifInpExportTools::printNodeSet( stream, partName, 1, nodes.size(), false ); - RifInpExportTools::printElementSet( stream, partName, 1, elements.size() ); + RifInpExportTools::printNodeSet( stream, "ALL", 1, nodes.size(), false ); + RifInpExportTools::printElementSet( stream, "ALL", 1, elements.size() ); RifInpExportTools::printNodeSet( stream, "PORE_PRESSURE", 1, nodes.size(), true ); @@ -253,7 +286,7 @@ std::pair CAF_ASSERT( partNameIt != partNames.end() ); std::string partName = partNameIt->second; - RifInpExportTools::printHeading( stream, "Transform, nset=" + partName + "." + partName ); + RifInpExportTools::printHeading( stream, "Transform, nset=" + partName + ".ALL" ); auto [dir1, dir2] = transform; RifInpExportTools::printNumbers( stream, { dir1.x(), dir1.y(), dir1.z(), dir2.x(), dir2.y(), dir2.z() } ); } @@ -269,7 +302,12 @@ std::pair std::pair RifFaultReactivationModelExporter::printMaterials( std::ostream& stream, const RimFaultReactivationModel& rimModel, - const std::map& materialNames ) + const std::map& materialNames, + const RimFaultReactivationDataAccess& dataAccess, + const std::string& exportDirectory, + const std::map& partNames, + bool densityFromGrid, + bool elasticPropertiesFromGrid ) { // MATERIALS PART struct Material @@ -310,14 +348,74 @@ std::pair { RifInpExportTools::printHeading( stream, "Material, name=" + mat.name ); RifInpExportTools::printHeading( stream, "Density" ); - RifInpExportTools::printNumber( stream, mat.density ); + if ( densityFromGrid ) + { + RifInpExportTools::printLine( stream, "DENSITY" ); + } + else + { + RifInpExportTools::printNumber( stream, mat.density ); + } + RifInpExportTools::printHeading( stream, "Elastic" ); - RifInpExportTools::printNumbers( stream, { mat.youngsModulus, mat.poissonNumber } ); + if ( elasticPropertiesFromGrid ) + { + RifInpExportTools::printLine( stream, "ELASTICS" ); + } + else + { + RifInpExportTools::printNumbers( stream, { mat.youngsModulus, mat.poissonNumber } ); + } RifInpExportTools::printHeading( stream, "Permeability, specific=1." ); RifInpExportTools::printNumbers( stream, { mat.permeability1, mat.permeability2 } ); } + if ( densityFromGrid ) + { + // Export the density to a separate inp file + std::string tableName = "DENSITY"; + std::string fileName = tableName + ".inp"; + + std::string filePath = createFilePath( exportDirectory, fileName ); + + auto model = rimModel.model(); + bool isOk = writePropertiesToFile( *model, + dataAccess, + { RimFaultReactivation::Property::Density }, + { "DENSITY" }, + 0, + filePath, + partNames, + tableName, + ", 1." ); + if ( !isOk ) return { false, "Failed to create density file." }; + + RifInpExportTools::printHeading( stream, "INCLUDE, input=" + fileName ); + } + + if ( elasticPropertiesFromGrid ) + { + // Export the elastic properties to a separate inp file + std::string tableName = "ELASTICS"; + std::string fileName = tableName + ".inp"; + std::string filePath = createFilePath( exportDirectory, fileName ); + + auto model = rimModel.model(); + bool isOk = writePropertiesToFile( *model, + dataAccess, + { RimFaultReactivation::Property::YoungsModulus, RimFaultReactivation::Property::PoissonsRatio }, + { "MODULUS", "RATIO" }, + 0, + filePath, + partNames, + tableName, + ", 2." ); + if ( !isOk ) return { false, "Failed to create elastic properties file." }; + + RifInpExportTools::printHeading( stream, "INCLUDE, input=" + fileName ); + } + return { true, "" }; } @@ -387,7 +485,7 @@ std::pair auto partNameIt = partNames.find( part ); CAF_ASSERT( partNameIt != partNames.end() ); std::string partName = partNameIt->second; - printBoundaryCondition( stream, partName + "." + partName, partSymmetry ); + printBoundaryCondition( stream, partName + ".ALL", partSymmetry ); } return { true, "" }; @@ -398,7 +496,12 @@ std::pair //-------------------------------------------------------------------------------------------------- std::pair RifFaultReactivationModelExporter::printPredefinedFields( std::ostream& stream, - const std::map& partNames ) + const RigFaultReactivationModel& model, + const RimFaultReactivationDataAccess& dataAccess, + const std::string& exportDirectory, + const std::map& partNames, + bool voidRatioFromEclipse, + bool stressFromGrid ) { // PREDEFINED FIELDS struct PredefinedField @@ -411,8 +514,11 @@ std::pair std::vector fields; for ( auto [part, partName] : partNames ) { - std::string name = partName + "." + partName; - fields.push_back( PredefinedField{ .initialConditionType = "RATIO", .partName = name, .value = 0.3 } ); + std::string name = partName + ".ALL"; + if ( !voidRatioFromEclipse ) + { + fields.push_back( PredefinedField{ .initialConditionType = "RATIO", .partName = name, .value = 0.3 } ); + } fields.push_back( PredefinedField{ .initialConditionType = "PORE PRESSURE", .partName = name, .value = 0.0 } ); } @@ -424,17 +530,69 @@ std::pair RifInpExportTools::printLine( stream, field.partName + ", " + std::to_string( field.value ) ); } + if ( voidRatioFromEclipse ) + { + std::string ratioName = "RATIO"; + + // Export the ratio to a separate inp file for each step + std::string fileName = ratioName + ".inp"; + std::string filePath = createFilePath( exportDirectory, fileName ); + + // Use void ratio from first time step + size_t timeStep = 0; + bool isOk = writePropertyToFile( model, dataAccess, RimFaultReactivation::Property::VoidRatio, timeStep, filePath, partNames, "" ); + if ( !isOk ) return { false, "Failed to create " + ratioName + " file." }; + + RifInpExportTools::printHeading( stream, "Initial Conditions, TYPE=" + ratioName ); + RifInpExportTools::printHeading( stream, "INCLUDE, input=" + fileName ); + } + + if ( stressFromGrid ) + { + std::string stressName = "STRESS"; + + // Export the stress to a separate inp file + std::string fileName = stressName + ".inp"; + std::string filePath = createFilePath( exportDirectory, fileName ); + + // Use stress from first time step + size_t timeStep = 0; + bool isOk = writePropertiesToFile( model, + dataAccess, + { RimFaultReactivation::Property::StressTop, + RimFaultReactivation::Property::DepthTop, + RimFaultReactivation::Property::StressBottom, + RimFaultReactivation::Property::DepthBottom, + RimFaultReactivation::Property::LateralStressComponentX, + RimFaultReactivation::Property::LateralStressComponentY }, + {}, + timeStep, + filePath, + partNames, + "", + "" ); + + if ( !isOk ) return { false, "Failed to create " + stressName + " file." }; + + RifInpExportTools::printHeading( stream, "Initial Conditions, TYPE=" + stressName ); + RifInpExportTools::printHeading( stream, "INCLUDE, input=" + fileName ); + } + return { true, "" }; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::pair RifFaultReactivationModelExporter::printSteps( std::ostream& stream, - const RigFaultReactivationModel& model, +std::pair RifFaultReactivationModelExporter::printSteps( std::ostream& stream, + const RigFaultReactivationModel& model, + const RimFaultReactivationDataAccess& dataAccess, const std::map& partNames, const std::vector& timeSteps, - const std::string& exportDirectory ) + const std::string& exportDirectory, + bool useGridPorePressure, + bool useGridTemperature, + double seaWaterLoad ) { // First time step has to be selected in order to export currently if ( timeSteps.size() < 2 ) return { false, "Failed to export fault reactivation INP: needs at least two time steps." }; @@ -442,10 +600,9 @@ std::pair RifFaultReactivationModelExporter::printSteps( std: for ( int i = 0; i < static_cast( timeSteps.size() ); i++ ) { std::string stepNum = std::to_string( i + 1 ); - std::string stepName = "Step-" + stepNum; + std::string stepName = timeSteps[i].toString( "yyyy-MM-dd" ).toStdString(); RifInpExportTools::printComment( stream, "----------------------------------------------------------------" ); RifInpExportTools::printSectionComment( stream, "STEP: " + stepName ); - RifInpExportTools::printComment( stream, "Time step: " + timeSteps[i].toString().toStdString() ); RifInpExportTools::printHeading( stream, "Step, name=" + stepName + ", nlgeom=NO" ); @@ -453,35 +610,51 @@ std::pair RifFaultReactivationModelExporter::printSteps( std: RifInpExportTools::printHeading( stream, stepType ); RifInpExportTools::printNumbers( stream, { 1.0, 1.0, 1e-05, 1.0 } ); - RifInpExportTools::printSectionComment( stream, "BOUNDARY CONDITIONS" ); + if ( i == 0 ) + { + RifInpExportTools::printHeading( stream, "Dload" ); + RifInpExportTools::printLine( stream, ",GRAV, 9.80665, 0., 0., -1." ); - // Export the pore pressure to a separate inp file for each step - QString fileName = "PORE_PRESSURE_DATE_" + timeSteps[i].toString( "yyyyMMdd" ) + "_" + QString::fromStdString( stepName ) + ".inp"; + RifInpExportTools::printComment( stream, "SEAWATER LOAD" ); - QString filePath = QString( "%1/%2" ).arg( QString::fromStdString( exportDirectory ) ).arg( fileName ); + for ( auto [part, partName] : partNames ) + { + RifInpExportTools::printHeading( stream, "Dsload" ); + std::string seaBedName = partName + "." + "SEABED"; + RifInpExportTools::printLine( stream, seaBedName + ", P, " + std::to_string( seaWaterLoad ) ); + } + } - std::ofstream ppStream( filePath.toStdString() ); - if ( !ppStream.good() ) + if ( useGridPorePressure ) { - return { false, "Failed to create pore pressure file." }; + RifInpExportTools::printSectionComment( stream, "BOUNDARY CONDITIONS" ); + + // Export the pore pressure to a separate inp file for each step + std::string fileName = createFileName( "PORE_PRESSURE", stepName ); + std::string filePath = createFilePath( exportDirectory, fileName ); + + bool isOk = + writePropertyToFile( model, dataAccess, RimFaultReactivation::Property::PorePressure, i, filePath, partNames, "8, 8, " ); + if ( !isOk ) return { false, "Failed to create pore pressure file." }; + + RifInpExportTools::printHeading( stream, "Boundary, type=displacement" ); + RifInpExportTools::printHeading( stream, "INCLUDE, input=" + fileName ); } - for ( auto [part, partName] : partNames ) + if ( useGridTemperature ) { - auto grid = model.grid( part ); + RifInpExportTools::printSectionComment( stream, "TEMPERATURE" ); - const std::vector& nodes = grid->nodes(); + // Export the temperature to a separate inp file for each step + std::string fileName = createFileName( "TEMPERATURE", stepName ); + std::string filePath = createFilePath( exportDirectory, fileName ); - const std::vector porePressure = grid->nodePorePressure( i ); - for ( size_t i = 0; i < nodes.size(); i++ ) - { - std::string line = partName + "." + std::to_string( i + 1 ) + ", 8, 8, " + std::to_string( porePressure[i] ); - RifInpExportTools::printLine( ppStream, line ); - } - } + bool isOk = writePropertyToFile( model, dataAccess, RimFaultReactivation::Property::Temperature, i, filePath, partNames, "" ); + if ( !isOk ) return { false, "Failed to create temperature file." }; - RifInpExportTools::printHeading( stream, "Boundary, type=displacement" ); - RifInpExportTools::printHeading( stream, "INCLUDE, input=" + fileName.toStdString() ); + RifInpExportTools::printHeading( stream, "Temperature" ); + RifInpExportTools::printHeading( stream, "INCLUDE, input=" + fileName ); + } RifInpExportTools::printSectionComment( stream, "OUTPUT REQUESTS" ); RifInpExportTools::printHeading( stream, "Restart, write, frequency=0" ); @@ -498,6 +671,93 @@ std::pair RifFaultReactivationModelExporter::printSteps( std: return { true, "" }; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RifFaultReactivationModelExporter::writePropertyToFile( const RigFaultReactivationModel& model, + const RimFaultReactivationDataAccess& dataAccess, + RimFaultReactivation::Property property, + size_t outputTimeStep, + const std::string& filePath, + const std::map& partNames, + const std::string& additionalData ) +{ + std::ofstream stream( filePath ); + if ( !stream.good() ) return false; + + for ( auto [part, partName] : partNames ) + { + auto grid = model.grid( part ); + + const std::vector& nodes = grid->globalNodes(); + const std::vector values = dataAccess.propertyValues( part, property, outputTimeStep ); + if ( values.size() != nodes.size() ) return false; + + for ( size_t i = 0; i < nodes.size(); i++ ) + { + std::string line = partName + ".ALL." + std::to_string( i + 1 ) + ", " + additionalData + std::to_string( values[i] ); + RifInpExportTools::printLine( stream, line ); + } + } + + return true; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RifFaultReactivationModelExporter::writePropertiesToFile( const RigFaultReactivationModel& model, + const RimFaultReactivationDataAccess& dataAccess, + const std::vector& properties, + const std::vector& propertyNames, + size_t outputTimeStep, + const std::string& filePath, + const std::map& partNames, + const std::string& tableName, + const std::string& heading ) +{ + std::ofstream stream( filePath ); + if ( !stream.good() ) return false; + + bool includeHeader = !propertyNames.empty(); + if ( includeHeader ) + { + RifInpExportTools::printHeading( stream, "Distribution Table, name=" + tableName + "_Table" ); + std::string propertyNamesLine; + for ( size_t i = 0; i < propertyNames.size(); i++ ) + { + propertyNamesLine += propertyNames[i]; + if ( i != propertyNames.size() - 1 ) propertyNamesLine += ", "; + } + RifInpExportTools::printLine( stream, propertyNamesLine ); + + RifInpExportTools::printHeading( stream, "Distribution, name=" + tableName + ", location=ELEMENT, Table=" + tableName + "_Table" ); + + RifInpExportTools::printLine( stream, heading ); + } + + for ( auto [part, partName] : partNames ) + { + auto grid = model.grid( part ); + + const std::vector>& elementIndices = grid->elementIndices(); + for ( size_t i = 0; i < elementIndices.size(); i++ ) + { + std::string line = partName + ".ALL." + std::to_string( i + 1 ); + for ( auto property : properties ) + { + const std::vector values = dataAccess.propertyValues( part, property, outputTimeStep ); + if ( values.size() != elementIndices.size() ) return false; + + line += ", " + std::to_string( values[i] ); + } + RifInpExportTools::printLine( stream, line ); + } + } + + return true; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -509,23 +769,43 @@ std::pair RifInpExportTools::printSectionComment( stream, "INTERACTIONS" ); for ( const auto& [border, borderName] : borders ) { - RifInpExportTools::printComment( stream, "Interaction: " + borderName ); - - std::string interactionName = "NON-FAULT"; - std::string extra; - if ( border == RimFaultReactivation::BorderSurface::FaultSurface ) + if ( border != RimFaultReactivation::BorderSurface::Seabed ) { - interactionName = "FAULT"; - extra = ", adjust=0.0"; - } + RifInpExportTools::printComment( stream, "Interaction: " + borderName ); + + std::string interactionName = "NON-FAULT"; + std::string extra; + if ( border == RimFaultReactivation::BorderSurface::FaultSurface ) + { + interactionName = "FAULT"; + extra = ", adjust=0.0"; + } - RifInpExportTools::printHeading( stream, - "Contact Pair, interaction=" + interactionName + ", small sliding, type=SURFACE TO SURFACE" + extra ); + RifInpExportTools::printHeading( stream, + "Contact Pair, interaction=" + interactionName + ", small sliding, type=SURFACE TO SURFACE" + + extra ); - std::string part1Name = partNames.find( RimFaultReactivation::GridPart::PART1 )->second; - std::string part2Name = partNames.find( RimFaultReactivation::GridPart::PART2 )->second; - RifInpExportTools::printLine( stream, part1Name + "." + borderName + ", " + part2Name + "." + borderName ); + std::string part1Name = partNames.find( RimFaultReactivation::GridPart::FW )->second; + std::string part2Name = partNames.find( RimFaultReactivation::GridPart::HW )->second; + RifInpExportTools::printLine( stream, part1Name + "." + borderName + ", " + part2Name + "." + borderName ); + } } return { true, "" }; } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::string RifFaultReactivationModelExporter::createFileName( const std::string& title, const std::string& stepName ) +{ + return QString( "%1_%2.inp" ).arg( QString::fromStdString( title ) ).arg( QString::fromStdString( stepName ) ).toStdString(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::string RifFaultReactivationModelExporter::createFilePath( const std::string& dir, const std::string& fileName ) +{ + return dir + "/" + fileName; +}; diff --git a/ApplicationLibCode/FileInterface/RifFaultReactivationModelExporter.h b/ApplicationLibCode/FileInterface/RifFaultReactivationModelExporter.h index 8c56fe58e9..14dffd1e79 100644 --- a/ApplicationLibCode/FileInterface/RifFaultReactivationModelExporter.h +++ b/ApplicationLibCode/FileInterface/RifFaultReactivationModelExporter.h @@ -56,7 +56,12 @@ class RifFaultReactivationModelExporter static std::pair printMaterials( std::ostream& stream, const RimFaultReactivationModel& rimModel, - const std::map& materialNames ); + const std::map& materialNames, + const RimFaultReactivationDataAccess& dataAccess, + const std::string& exportDirectory, + const std::map& partNames, + bool densityFromGrid, + bool elasticPropertiesFromGrid ); static std::pair printInteractionProperties( std::ostream& stream, double faultFriction ); static std::pair printBoundaryConditions( std::ostream& stream, @@ -64,15 +69,46 @@ class RifFaultReactivationModelExporter const std::map& partNames, const std::map& boundaries ); static std::pair printPredefinedFields( std::ostream& stream, - const std::map& partNames ); + const RigFaultReactivationModel& model, + const RimFaultReactivationDataAccess& dataAccess, + const std::string& exportDirectory, + const std::map& partNames, + bool useGridVoidRatio, + bool useGridStress ); static std::pair printSteps( std::ostream& stream, const RigFaultReactivationModel& model, + const RimFaultReactivationDataAccess& dataAccess, const std::map& partNames, const std::vector& timeSteps, - const std::string& exportDirectory ); + const std::string& exportDirectory, + bool useGridPorePressure, + bool useGridTemperature, + double seaWaterLoad ); static std::pair printInteractions( std::ostream& stream, const std::map& partNames, const std::vector>& borders ); + + static bool writePropertyToFile( const RigFaultReactivationModel& model, + const RimFaultReactivationDataAccess& dataAccess, + RimFaultReactivation::Property property, + size_t outputTimeStep, + const std::string& filePath, + const std::map& partNames, + const std::string& additionalData ); + + static bool writePropertiesToFile( const RigFaultReactivationModel& model, + const RimFaultReactivationDataAccess& dataAccess, + const std::vector& properties, + const std::vector& propertyNames, + size_t outputTimeStep, + const std::string& filePath, + const std::map& partNames, + const std::string& tableName, + const std::string& heading ); + + static std::string createFileName( const std::string& title, const std::string& stepName ); + + static std::string createFilePath( const std::string& dir, const std::string& fileName ); }; diff --git a/ApplicationLibCode/FileInterface/RifGridCalculation.h b/ApplicationLibCode/FileInterface/RifGridCalculation.h new file mode 100644 index 0000000000..5efa8ef0fe --- /dev/null +++ b/ApplicationLibCode/FileInterface/RifGridCalculation.h @@ -0,0 +1,40 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 + +//================================================================================================== +// +//================================================================================================== +struct RifGridCalculationVariable +{ + std::string name; + std::string resultType; + std::string resultVariable; +}; + +struct RifGridCalculation +{ + std::string description; + std::string expression; + std::string unit; + std::vector variables; +}; diff --git a/ApplicationLibCode/FileInterface/RifGridCalculationExporter.cpp b/ApplicationLibCode/FileInterface/RifGridCalculationExporter.cpp new file mode 100644 index 0000000000..ac9788cc63 --- /dev/null +++ b/ApplicationLibCode/FileInterface/RifGridCalculationExporter.cpp @@ -0,0 +1,72 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 "RifGridCalculationExporter.h" + +#include + +#include + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::pair RifGridCalculationExporter::writeToFile( const std::vector& calculations, + const std::string& filePath ) +{ + std::ofstream stream( filePath ); + if ( !stream.good() ) return { false, "Unable to open file: " + filePath }; + + return writeToStream( calculations, stream ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::pair RifGridCalculationExporter::writeToStream( const std::vector& calculations, + std::ostream& stream ) +{ + auto calculationsVector = toml::array(); + + for ( auto calculation : calculations ) + { + auto variablesVector = toml::array{}; + for ( auto variable : calculation.variables ) + { + variablesVector.push_back( toml::table{ + { "name", variable.name }, + { "variable", variable.resultVariable }, + { "type", variable.resultType }, + } ); + } + + calculationsVector.push_back( toml::table{ + { "description", calculation.description }, + { "expression", calculation.expression }, + { "unit", calculation.unit }, + { "variables", variablesVector }, + } ); + } + + auto tbl = toml::table{ + { "grid-calculation", calculationsVector }, + }; + + stream << tbl; + + return { stream.good(), "" }; +} diff --git a/ApplicationLibCode/FileInterface/RifGridCalculationExporter.h b/ApplicationLibCode/FileInterface/RifGridCalculationExporter.h new file mode 100644 index 0000000000..d19c6a98de --- /dev/null +++ b/ApplicationLibCode/FileInterface/RifGridCalculationExporter.h @@ -0,0 +1,34 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 "RifGridCalculation.h" + +#include +#include + +//================================================================================================== +// +//================================================================================================== +class RifGridCalculationExporter +{ +public: + static std::pair writeToFile( const std::vector& calculations, const std::string& filePath ); + static std::pair writeToStream( const std::vector& calculations, std::ostream& stream ); +}; diff --git a/ApplicationLibCode/FileInterface/RifGridCalculationImporter.cpp b/ApplicationLibCode/FileInterface/RifGridCalculationImporter.cpp new file mode 100644 index 0000000000..3df4bf3acb --- /dev/null +++ b/ApplicationLibCode/FileInterface/RifGridCalculationImporter.cpp @@ -0,0 +1,100 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 "RifGridCalculationImporter.h" + +#include + +#include +#include + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::pair, std::string> RifGridCalculationImporter::readFromFile( const std::string& filePath ) +{ + std::ifstream stream( filePath ); + if ( !stream.good() ) return { {}, "Unable to open file: " + filePath }; + + return readFromStream( stream ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::pair, std::string> RifGridCalculationImporter::readFromStream( std::istream& stream ) +{ + try + { + toml::table tbl = toml::parse( stream ); + + auto calculationsVector = tbl["grid-calculation"]; + + std::vector calculations; + + if ( toml::array* arr = calculationsVector.as_array() ) + { + for ( auto&& a : *arr ) + { + RifGridCalculation calculation; + if ( toml::table* calc = a.as_table() ) + { + calculation.description = calc->at_path( "description" ).value_or( "" ); + if ( calculation.description.empty() ) throw std::runtime_error( "Missing description." ); + + calculation.expression = calc->at_path( "expression" ).value_or( "" ); + if ( calculation.expression.empty() ) throw std::runtime_error( "Missing expression." ); + + calculation.unit = calc->at_path( "unit" ).value_or( "" ); + + if ( toml::array* vars = calc->at_path( "variables" ).as_array() ) + { + std::vector variables; + for ( auto&& v : *vars ) + { + if ( toml::table* var = v.as_table() ) + { + RifGridCalculationVariable variable; + variable.name = var->at_path( "name" ).value_or( "" ); + variable.resultType = var->at_path( "type" ).value_or( "" ); + variable.resultVariable = var->at_path( "variable" ).value_or( "" ); + if ( variable.name.empty() || variable.resultType.empty() || variable.resultVariable.empty() ) + throw std::runtime_error( "Incomplete variable: Missing either name, result type or result variable." ); + variables.push_back( variable ); + } + } + calculation.variables = variables; + } + + calculations.push_back( calculation ); + } + } + } + + if ( calculations.empty() ) + { + return { calculations, "No calculations imported." }; + } + + return { calculations, "" }; + } + catch ( const std::runtime_error& error ) + { + return { {}, error.what() }; + } +} diff --git a/ApplicationLibCode/FileInterface/RifGridCalculationImporter.h b/ApplicationLibCode/FileInterface/RifGridCalculationImporter.h new file mode 100644 index 0000000000..5a636d550b --- /dev/null +++ b/ApplicationLibCode/FileInterface/RifGridCalculationImporter.h @@ -0,0 +1,34 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 "RifGridCalculation.h" + +#include +#include + +//================================================================================================== +// +//================================================================================================== +class RifGridCalculationImporter +{ +public: + static std::pair, std::string> readFromFile( const std::string& filePath ); + static std::pair, std::string> readFromStream( std::istream& stream ); +}; diff --git a/ApplicationLibCode/FileInterface/RifOpmCommonSummary.cpp b/ApplicationLibCode/FileInterface/RifOpmCommonSummary.cpp index 4c8227c1aa..6b411262b9 100644 --- a/ApplicationLibCode/FileInterface/RifOpmCommonSummary.cpp +++ b/ApplicationLibCode/FileInterface/RifOpmCommonSummary.cpp @@ -111,7 +111,10 @@ bool RifOpmCommonEclipseSummary::open( const QString& fileName, bool includeRest { auto temporarySummaryFile = std::make_unique( smspecFileName.toStdString(), includeRestartFiles ); - temporarySummaryFile->make_esmry_file(); + if ( temporarySummaryFile->numberOfTimeSteps() > 0 ) + { + temporarySummaryFile->make_esmry_file(); + } RifOpmCommonEclipseSummary::increaseEsmryFileCount(); } @@ -214,15 +217,22 @@ void RifOpmCommonEclipseSummary::buildMetaData() if ( m_enhancedReader ) { - keywords = m_enhancedReader->keywordList(); - startOfSimulation = m_enhancedReader->startdate(); - daysSinceStartOfSimulation = m_enhancedReader->get( "TIME" ); + keywords = m_enhancedReader->keywordList(); + startOfSimulation = m_enhancedReader->startdate(); + + if ( m_enhancedReader->numberOfTimeSteps() > 0 ) + { + daysSinceStartOfSimulation = m_enhancedReader->get( "TIME" ); + } } else if ( m_standardReader ) { - keywords = m_standardReader->keywordList(); - startOfSimulation = m_standardReader->startdate(); - daysSinceStartOfSimulation = m_standardReader->get( "TIME" ); + keywords = m_standardReader->keywordList(); + startOfSimulation = m_standardReader->startdate(); + if ( m_standardReader->numberOfTimeSteps() > 0 ) + { + daysSinceStartOfSimulation = m_standardReader->get( "TIME" ); + } } const auto startAsTimeT = std::chrono::system_clock::to_time_t( startOfSimulation ); diff --git a/ApplicationLibCode/FileInterface/RifReaderEclipseOutput.cpp b/ApplicationLibCode/FileInterface/RifReaderEclipseOutput.cpp index b50728dada..b4ee519238 100644 --- a/ApplicationLibCode/FileInterface/RifReaderEclipseOutput.cpp +++ b/ApplicationLibCode/FileInterface/RifReaderEclipseOutput.cpp @@ -1243,6 +1243,12 @@ RigWellResultPoint RifReaderEclipseOutput::createWellResultPoint( const RigGridB resultPoint.setFlowData( volumeRate, oilRate, adjustedGasRate, waterRate ); resultPoint.setConnectionFactor( connectionFactor ); + + auto ijkOneBased = grid->ijkFromCellIndexOneBased( gridCellIndex ); + if ( ijkOneBased ) + { + resultPoint.setIjk( *ijkOneBased ); + } } return resultPoint; diff --git a/ApplicationLibCode/FileInterface/RifReaderEclipseSummary.cpp b/ApplicationLibCode/FileInterface/RifReaderEclipseSummary.cpp index 69cf598f41..68f4c0ef1d 100644 --- a/ApplicationLibCode/FileInterface/RifReaderEclipseSummary.cpp +++ b/ApplicationLibCode/FileInterface/RifReaderEclipseSummary.cpp @@ -176,7 +176,8 @@ std::pair> RifReaderEclipseSummary::values( const RifE if ( m_differenceAddresses.count( resultAddress ) ) { const std::string& quantityName = resultAddress.vectorName(); - auto historyQuantity = quantityName.substr( 0, quantityName.size() - differenceIdentifier().size() ) + historyIdentifier(); + auto historyQuantity = quantityName.substr( 0, quantityName.size() - RifEclipseSummaryAddressDefines::differenceIdentifier().size() ) + + RifEclipseSummaryAddressDefines::historyIdentifier(); RifEclipseSummaryAddress nativeAdrNoHistory = resultAddress; nativeAdrNoHistory.setVectorName( historyQuantity ); @@ -251,10 +252,10 @@ void RifReaderEclipseSummary::buildMetaData() { const std::string& s = adr.vectorName(); - if ( !RiaStdStringTools::endsWith( s, historyIdentifier() ) ) + if ( !RiaStdStringTools::endsWith( s, RifEclipseSummaryAddressDefines::historyIdentifier() ) ) { RifEclipseSummaryAddress candidate = adr; - candidate.setVectorName( s + historyIdentifier() ); + candidate.setVectorName( s + RifEclipseSummaryAddressDefines::historyIdentifier() ); if ( m_allResultAddresses.count( candidate ) ) { adrWithHistory = candidate; @@ -267,7 +268,7 @@ void RifReaderEclipseSummary::buildMetaData() { RifEclipseSummaryAddress candidate = adr; - std::string s = candidate.vectorName() + differenceIdentifier(); + std::string s = candidate.vectorName() + RifEclipseSummaryAddressDefines::differenceIdentifier(); candidate.setVectorName( s ); m_allResultAddresses.insert( candidate ); @@ -296,7 +297,7 @@ std::string RifReaderEclipseSummary::unitName( const RifEclipseSummaryAddress& r if ( reader ) { auto nativeName = resultAddress.vectorName(); - auto stringToRemove = RifReaderEclipseSummary::differenceIdentifier(); + auto stringToRemove = RifEclipseSummaryAddressDefines::differenceIdentifier(); if ( RiaStdStringTools::endsWith( nativeName, stringToRemove ) ) { nativeName = nativeName.substr( 0, nativeName.size() - stringToRemove.size() ); diff --git a/ApplicationLibCode/FileInterface/RifReaderEclipseSummary.h b/ApplicationLibCode/FileInterface/RifReaderEclipseSummary.h index f07da1f88d..7028e384d3 100644 --- a/ApplicationLibCode/FileInterface/RifReaderEclipseSummary.h +++ b/ApplicationLibCode/FileInterface/RifReaderEclipseSummary.h @@ -55,9 +55,6 @@ class RifReaderEclipseSummary : public RifSummaryReaderInterface std::string unitName( const RifEclipseSummaryAddress& resultAddress ) const override; RiaDefines::EclipseUnitSystem unitSystem() const override; - static std::string differenceIdentifier() { return "_DIFF"; } - static const std::string historyIdentifier() { return "H"; } - private: void buildMetaData(); diff --git a/ApplicationLibCode/FileInterface/RifReaderFmuRft.cpp b/ApplicationLibCode/FileInterface/RifReaderFmuRft.cpp index 9329f66a7e..48ce021b71 100644 --- a/ApplicationLibCode/FileInterface/RifReaderFmuRft.cpp +++ b/ApplicationLibCode/FileInterface/RifReaderFmuRft.cpp @@ -122,7 +122,7 @@ std::vector RifReaderFmuRft::labels( const RifEclipseRftAddress& rftAdd for ( const auto& observation : m_observations ) { - if ( observation.wellDate.wellName == rftAddress.wellName() ) + if ( observation.wellDate.wellName == rftAddress.wellName() && observation.wellDate.dateTime == rftAddress.timeStep() ) { formationLabels.push_back( QString( "%1 - Pressure: %2 +/- %3" ).arg( observation.location.formation ).arg( observation.pressure ).arg( observation.pressureError ) ); @@ -183,7 +183,7 @@ void RifReaderFmuRft::values( const RifEclipseRftAddress& rftAddress, std::vecto for ( const auto& observation : m_observations ) { - if ( observation.wellDate.wellName == rftAddress.wellName() ) + if ( observation.wellDate.wellName == rftAddress.wellName() && observation.wellDate.dateTime == rftAddress.timeStep() ) { switch ( rftAddress.wellLogChannel() ) { @@ -238,23 +238,19 @@ void RifReaderFmuRft::importData() for ( const auto& [wellName, measurementCount] : nameAndMeasurementCount ) { - QString txtFile = QString( "%1.txt" ).arg( wellName ); - auto locations = importLocations( dir.absoluteFilePath( txtFile ) ); - if ( locations.empty() ) continue; - for ( int i = 0; i < measurementCount; i++ ) { int measurementId = i + 1; - auto findObservationFileName = []( const QString& wellName, int measurementId, const QDir& dir ) -> QString + auto findFileName = []( const QString& wellName, const QString& extension, int measurementId, const QDir& dir ) -> QString { - QString candidate = dir.absoluteFilePath( QString( "%1_%2.obs" ).arg( wellName ).arg( measurementId ) ); + QString candidate = dir.absoluteFilePath( QString( "%1_%2.%3" ).arg( wellName ).arg( measurementId ).arg( extension ) ); if ( QFile::exists( candidate ) ) { return candidate; } - QString candidateOldFormat = dir.absoluteFilePath( QString( "%1.obs" ).arg( wellName ) ); + QString candidateOldFormat = dir.absoluteFilePath( QString( "%1.%2" ).arg( wellName ).arg( extension ) ); if ( QFile::exists( candidateOldFormat ) ) { return candidateOldFormat; @@ -263,7 +259,13 @@ void RifReaderFmuRft::importData() return {}; }; - QString observationFileName = findObservationFileName( wellName, measurementId, dir ); + // The text file name can be either _.txt or .txt + QString txtFile = findFileName( wellName, "txt", measurementId, dir ); + auto locations = importLocations( dir.absoluteFilePath( txtFile ) ); + if ( locations.empty() ) continue; + + // The observation file name can be either _.obs or .obs + QString observationFileName = findFileName( wellName, "obs", measurementId, dir ); if ( observationFileName.isEmpty() ) continue; for ( const auto& wellDate : wellDates ) diff --git a/ApplicationLibCode/FileInterface/RifSummaryCalculation.h b/ApplicationLibCode/FileInterface/RifSummaryCalculation.h new file mode 100644 index 0000000000..6fac29335e --- /dev/null +++ b/ApplicationLibCode/FileInterface/RifSummaryCalculation.h @@ -0,0 +1,40 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 + +//================================================================================================== +// +//================================================================================================== +struct RifSummaryCalculationVariable +{ + std::string name; + std::string address; +}; + +struct RifSummaryCalculation +{ + std::string expression; + std::string unit; + bool distributeToAllCases; + bool distributeToOther; + std::vector variables; +}; diff --git a/ApplicationLibCode/FileInterface/RifSummaryCalculationExporter.cpp b/ApplicationLibCode/FileInterface/RifSummaryCalculationExporter.cpp new file mode 100644 index 0000000000..9429bef710 --- /dev/null +++ b/ApplicationLibCode/FileInterface/RifSummaryCalculationExporter.cpp @@ -0,0 +1,72 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 "RifSummaryCalculationExporter.h" + +#include + +#include + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::pair RifSummaryCalculationExporter::writeToFile( const std::vector& calculations, + const std::string& filePath ) +{ + std::ofstream stream( filePath ); + if ( !stream.good() ) return { false, "Unable to open file: " + filePath }; + + return writeToStream( calculations, stream ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::pair RifSummaryCalculationExporter::writeToStream( const std::vector& calculations, + std::ostream& stream ) +{ + auto calculationsVector = toml::array(); + + for ( auto calculation : calculations ) + { + auto variablesVector = toml::array{}; + for ( auto variable : calculation.variables ) + { + variablesVector.push_back( toml::table{ + { "name", variable.name }, + { "address", variable.address }, + } ); + } + + calculationsVector.push_back( toml::table{ + { "expression", calculation.expression }, + { "unit", calculation.unit }, + { "distribute-to-other-items", calculation.distributeToOther }, + { "distribute-to-all-cases", calculation.distributeToAllCases }, + { "variables", variablesVector }, + } ); + } + + auto tbl = toml::table{ + { "summary-calculation", calculationsVector }, + }; + + stream << tbl; + + return { stream.good(), "" }; +} diff --git a/ApplicationLibCode/FileInterface/RifSummaryCalculationExporter.h b/ApplicationLibCode/FileInterface/RifSummaryCalculationExporter.h new file mode 100644 index 0000000000..22b92629ce --- /dev/null +++ b/ApplicationLibCode/FileInterface/RifSummaryCalculationExporter.h @@ -0,0 +1,34 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 "RifSummaryCalculation.h" + +#include +#include + +//================================================================================================== +// +//================================================================================================== +class RifSummaryCalculationExporter +{ +public: + static std::pair writeToFile( const std::vector& calculations, const std::string& filePath ); + static std::pair writeToStream( const std::vector& calculations, std::ostream& stream ); +}; diff --git a/ApplicationLibCode/FileInterface/RifSummaryCalculationImporter.cpp b/ApplicationLibCode/FileInterface/RifSummaryCalculationImporter.cpp new file mode 100644 index 0000000000..1b8831e981 --- /dev/null +++ b/ApplicationLibCode/FileInterface/RifSummaryCalculationImporter.cpp @@ -0,0 +1,98 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 "RifSummaryCalculationImporter.h" + +#include + +#include +#include + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::pair, std::string> RifSummaryCalculationImporter::readFromFile( const std::string& filePath ) +{ + std::ifstream stream( filePath ); + if ( !stream.good() ) return { {}, "Unable to open file: " + filePath }; + + return readFromStream( stream ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::pair, std::string> RifSummaryCalculationImporter::readFromStream( std::istream& stream ) +{ + try + { + toml::table tbl = toml::parse( stream ); + + auto calculationsVector = tbl["summary-calculation"]; + + std::vector calculations; + + if ( toml::array* arr = calculationsVector.as_array() ) + { + for ( auto&& a : *arr ) + { + RifSummaryCalculation calculation; + if ( toml::table* calc = a.as_table() ) + { + calculation.expression = calc->at_path( "expression" ).value_or( "" ); + if ( calculation.expression.empty() ) throw std::runtime_error( "Missing expression." ); + + calculation.distributeToOther = calc->at_path( "distribute-to-other-items" ).value_or( true ); + calculation.distributeToAllCases = calc->at_path( "distribute-to-all-cases" ).value_or( true ); + calculation.unit = calc->at_path( "unit" ).value_or( "" ); + + if ( toml::array* vars = calc->at_path( "variables" ).as_array() ) + { + std::vector variables; + for ( auto&& v : *vars ) + { + if ( toml::table* var = v.as_table() ) + { + RifSummaryCalculationVariable variable; + variable.name = var->at_path( "name" ).value_or( "" ); + variable.address = var->at_path( "address" ).value_or( "" ); + if ( variable.name.empty() || variable.address.empty() ) + throw std::runtime_error( "Incomplete variable: Missing either name or address." ); + variables.push_back( variable ); + } + } + calculation.variables = variables; + } + + calculations.push_back( calculation ); + } + } + } + + if ( calculations.empty() ) + { + return { calculations, "No calculations imported." }; + } + + return { calculations, "" }; + } + catch ( const std::runtime_error& error ) + { + return { {}, error.what() }; + } +} diff --git a/ApplicationLibCode/FileInterface/RifSummaryCalculationImporter.h b/ApplicationLibCode/FileInterface/RifSummaryCalculationImporter.h new file mode 100644 index 0000000000..8a72e7950d --- /dev/null +++ b/ApplicationLibCode/FileInterface/RifSummaryCalculationImporter.h @@ -0,0 +1,34 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 "RifSummaryCalculation.h" + +#include +#include + +//================================================================================================== +// +//================================================================================================== +class RifSummaryCalculationImporter +{ +public: + static std::pair, std::string> readFromFile( const std::string& filePath ); + static std::pair, std::string> readFromStream( std::istream& stream ); +}; diff --git a/ApplicationLibCode/GeoMech/OdbReader/RifInpReader.cpp b/ApplicationLibCode/GeoMech/OdbReader/RifInpReader.cpp index 38131318d0..4908f9e95b 100644 --- a/ApplicationLibCode/GeoMech/OdbReader/RifInpReader.cpp +++ b/ApplicationLibCode/GeoMech/OdbReader/RifInpReader.cpp @@ -81,11 +81,12 @@ bool RifInpReader::readFemParts( RigFemPartCollection* femParts ) CVF_ASSERT( femParts ); // The key in the maps is the part ID - std::map parts; - std::map>> nodes; - std::map>>> elements; + std::map parts; + std::map>> nodes; + std::map>>> elements; + std::map>>> elementSets; - read( m_stream, parts, nodes, elements ); + read( m_stream, parts, nodes, elements, elementSets ); RiaLogging::debug( QString( "Read FEM parts: %1 nodes: %2 elements: %3" ).arg( parts.size() ).arg( nodes.size() ).arg( elements.size() ) ); @@ -147,6 +148,13 @@ bool RifInpReader::readFemParts( RigFemPartCollection* femParts ) femPart->appendElement( elmType, elmId, indexBasedConnectivities.data() ); } + // read element sets + auto elementSetsForPart = elementSets[partId]; + for ( auto [setName, elementSet] : elementSetsForPart ) + { + femPart->addElementSet( setName, elementSet ); + } + femPart->setElementPartId( femParts->partCount() ); femParts->addFemPart( femPart ); @@ -159,10 +167,11 @@ bool RifInpReader::readFemParts( RigFemPartCollection* femParts ) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RifInpReader::read( std::istream& stream, - std::map& parts, - std::map>>& nodes, - std::map>>>& elements ) +void RifInpReader::read( std::istream& stream, + std::map& parts, + std::map>>& nodes, + std::map>>>& elements, + std::map>>>& elementSets ) { std::string line; @@ -202,6 +211,14 @@ void RifInpReader::read( std::istream& skipComments( stream ); elements[partId] = readElements( stream ); } + else if ( uppercasedLine.starts_with( "*ELSET," ) ) + { + bool isGenerateSet = uppercasedLine.find( "GENERATE" ) != std::string::npos; + skipComments( stream ); + std::string setName = parseLabel( line, "elset" ); + auto elementSet = isGenerateSet ? readElementSetGenerate( stream ) : readElementSet( stream ); + elementSets[partId].push_back( { setName, elementSet } ); + } continue; } @@ -284,6 +301,75 @@ std::vector>> RifInpReader::readElements( std::i return partElements; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RifInpReader::readElementSet( std::istream& stream ) +{ + std::vector elementSet; + + // Read until we find a new section (which should start with a '*'). + while ( stream.peek() != '*' && stream.peek() != EOF ) + { + // Read entire line of comma-separated values + std::string line; + std::getline( stream, line ); + + // Process the comma-separated values + auto parts = RiaStdStringTools::splitString( line, ',' ); + for ( auto part : parts ) + { + std::string trimmedPart = RiaStdStringTools::trimString( part ); + + if ( !trimmedPart.empty() ) + { + int elementId = RiaStdStringTools::toInt( trimmedPart ) - 1; + elementSet.push_back( elementId ); + } + } + } + + return elementSet; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RifInpReader::readElementSetGenerate( std::istream& stream ) +{ + std::vector elementSet; + + // Read until we find a new section (which should start with a '*'). + while ( stream.peek() != '*' && stream.peek() != EOF ) + { + // Read entire line of comma-separated values + std::string line; + std::getline( stream, line ); + + // Process the comma-separated values + auto parts = RiaStdStringTools::splitString( line, ',' ); + if ( parts.size() >= 3 ) + { + int firstElement = RiaStdStringTools::toInt( parts[0] ); + int lastElement = RiaStdStringTools::toInt( parts[1] ); + int increment = RiaStdStringTools::toInt( parts[2] ); + if ( lastElement < firstElement || increment <= 0 ) + { + RiaLogging::error( "Encountered illegal set definition (using GENERATE keyword)." ); + return elementSet; + } + + for ( int i = firstElement; i < lastElement; i += increment ) + { + int elementId = i - 1; + elementSet.push_back( elementId ); + } + } + } + + return elementSet; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/GeoMech/OdbReader/RifInpReader.h b/ApplicationLibCode/GeoMech/OdbReader/RifInpReader.h index 36dc2fc1fc..b28c2fcf9e 100644 --- a/ApplicationLibCode/GeoMech/OdbReader/RifInpReader.h +++ b/ApplicationLibCode/GeoMech/OdbReader/RifInpReader.h @@ -77,11 +77,14 @@ class RifInpReader : public RifGeoMechReaderInterface static std::string parseLabel( const std::string& line, const std::string& labelName ); static std::vector> readNodes( std::istream& stream ); static std::vector>> readElements( std::istream& stream ); + static std::vector readElementSet( std::istream& stream ); + static std::vector readElementSetGenerate( std::istream& stream ); - static void read( std::istream& stream, - std::map& parts, - std::map>>& nodes, - std::map>>>& elements ); + static void read( std::istream& stream, + std::map& parts, + std::map>>& nodes, + std::map>>>& elements, + std::map>>>& elementSets ); private: std::map> m_partElementSetNames; diff --git a/ApplicationLibCode/ModelVisualization/Faults/RivFaultReactivationModelPartMgr.cpp b/ApplicationLibCode/ModelVisualization/Faults/RivFaultReactivationModelPartMgr.cpp index 82e42b1cca..7892f14051 100644 --- a/ApplicationLibCode/ModelVisualization/Faults/RivFaultReactivationModelPartMgr.cpp +++ b/ApplicationLibCode/ModelVisualization/Faults/RivFaultReactivationModelPartMgr.cpp @@ -110,26 +110,10 @@ void RivFaultReactivationModelPartMgr::appendGeometryPartsToModel( cvf::ModelBas { if ( !m_canUseShaders ) return; - auto plane = m_frm->faultPlane(); - if ( plane->isValid() && m_frm->showFaultPlane() ) - { - cvf::Vec3dArray displayPoints; - displayPoints.reserve( plane->rect().size() ); - - for ( auto& vOrg : plane->rect() ) - { - displayPoints.add( displayCoordTransform->transformToDisplayCoord( vOrg ) ); - } - - cvf::ref quadPart = createSingleTexturedQuadPart( displayPoints, plane->texture(), false ); - - vizModel->addPart( quadPart.p() ); - } - auto theModel = m_frm->model(); if ( theModel->isValid() && m_frm->showModel() ) { - for ( auto part : theModel->allModelParts() ) + for ( auto part = 0; part < RigFaultReactivationModel::numModelParts(); part++ ) { cvf::Vec3dArray displayPoints; displayPoints.reserve( theModel->rect( part ).size() ); diff --git a/ApplicationLibCode/ModelVisualization/RivWellFracturePartMgr.cpp b/ApplicationLibCode/ModelVisualization/RivWellFracturePartMgr.cpp index 45f8ce0b3a..6c176fee00 100644 --- a/ApplicationLibCode/ModelVisualization/RivWellFracturePartMgr.cpp +++ b/ApplicationLibCode/ModelVisualization/RivWellFracturePartMgr.cpp @@ -923,7 +923,11 @@ void RivWellFracturePartMgr::appendFracturePerforationLengthParts( const RimEcli if ( !m_rimFracture->isChecked() ) return; if ( !m_rimFracture->fractureTemplate() ) return; - if ( m_rimFracture->fractureTemplate()->orientationType() != RimFractureTemplate::ALONG_WELL_PATH ) return; + + bool hasPerforation = ( m_rimFracture->fractureTemplate()->orientationType() == RimFractureTemplate::ALONG_WELL_PATH || + ( m_rimFracture->fractureTemplate()->orientationType() == RimFractureTemplate::AZIMUTH && + m_rimFracture->fractureTemplate()->useUserDefinedPerforationLength() ) ); + if ( !hasPerforation ) return; auto displayCoordTransform = activeView.displayCoordTransform(); if ( displayCoordTransform.isNull() ) return; diff --git a/ApplicationLibCode/ProjectDataModel/AnalysisPlots/RimAnalysisPlot.cpp b/ApplicationLibCode/ProjectDataModel/AnalysisPlots/RimAnalysisPlot.cpp index f747a7c4df..e152671799 100644 --- a/ApplicationLibCode/ProjectDataModel/AnalysisPlots/RimAnalysisPlot.cpp +++ b/ApplicationLibCode/ProjectDataModel/AnalysisPlots/RimAnalysisPlot.cpp @@ -489,8 +489,8 @@ void RimAnalysisPlot::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering { caf::PdmUiGroup* selVectorsGrp = uiOrdering.addNewGroup( "Selected Vectors" ); selVectorsGrp->add( &m_selectedVarsUiField ); - selVectorsGrp->add( &m_selectVariablesButtonField, { false } ); - selVectorsGrp->add( &m_referenceCase, { true, 3, 2 } ); + selVectorsGrp->appendToRow( &m_selectVariablesButtonField ); + selVectorsGrp->add( &m_referenceCase, { .newRow = true, .totalColumnSpan = 3, .leftLabelColumnSpan = 2 } ); QString vectorNames; if ( updateAndGetCurveAnalyzer() ) @@ -521,22 +521,22 @@ void RimAnalysisPlot::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering caf::PdmUiGroup* titleGrp = uiOrdering.addNewGroup( "Title and Legend" ); titleGrp->add( &m_showPlotTitle ); - titleGrp->add( &m_useAutoPlotTitle, { false } ); - titleGrp->add( &m_description, { false } ); + titleGrp->appendToRow( &m_useAutoPlotTitle ); + titleGrp->appendToRow( &m_description ); m_description.uiCapability()->setUiReadOnly( m_useAutoPlotTitle() ); titleGrp->add( &m_showPlotLegends ); titleGrp->add( &m_legendFontSize ); m_legendFontSize.uiCapability()->setUiReadOnly( !m_showPlotLegends() ); caf::PdmUiGroup* chartSettings = uiOrdering.addNewGroup( "Bar Settings" ); - chartSettings->add( &m_barOrientation, { true, 3, 2 } ); + chartSettings->add( &m_barOrientation, { .newRow = true, .totalColumnSpan = 3, .leftLabelColumnSpan = 2 } ); chartSettings->add( &m_majorGroupType ); chartSettings->add( &m_mediumGroupType ); chartSettings->add( &m_minorGroupType ); chartSettings->add( &m_valueSortOperation ); chartSettings->add( &m_useTopBarsFilter ); - chartSettings->add( &m_maxBarCount, { false } ); + chartSettings->appendToRow( &m_maxBarCount ); m_maxBarCount.uiCapability()->setUiReadOnly( !m_useTopBarsFilter() ); chartSettings->add( &m_sortGroupForColors ); diff --git a/ApplicationLibCode/ProjectDataModel/AnalysisPlots/RimPlotDataFilterItem.cpp b/ApplicationLibCode/ProjectDataModel/AnalysisPlots/RimPlotDataFilterItem.cpp index ace327b647..6cf447df64 100644 --- a/ApplicationLibCode/ProjectDataModel/AnalysisPlots/RimPlotDataFilterItem.cpp +++ b/ApplicationLibCode/ProjectDataModel/AnalysisPlots/RimPlotDataFilterItem.cpp @@ -336,19 +336,19 @@ void RimPlotDataFilterItem::defineUiOrdering( QString uiConfigName, caf::PdmUiOr updateMaxMinAndDefaultValues( false ); - uiOrdering.add( &m_filterTarget, { true, -1, 1 } ); + uiOrdering.add( &m_filterTarget, { .leftLabelColumnSpan = 1 } ); if ( m_filterTarget() == ENSEMBLE_CASE ) { - uiOrdering.add( &m_filterEnsembleParameter, { true, caf::PdmUiOrdering::LayoutOptions::MAX_COLUMN_SPAN, 1 } ); + uiOrdering.add( &m_filterEnsembleParameter, { .leftLabelColumnSpan = 1 } ); } else { - uiOrdering.add( &m_filterQuantityUiField, { true, caf::PdmUiOrdering::LayoutOptions::MAX_COLUMN_SPAN, 1 } ); + uiOrdering.add( &m_filterQuantityUiField, { .leftLabelColumnSpan = 1 } ); // uiOrdering.add( &m_filterQuantitySelectButton, {false, 1, 0} ); } if ( m_filterTarget() != ENSEMBLE_CASE ) { - uiOrdering.add( &m_consideredTimestepsType, { true, caf::PdmUiOrdering::LayoutOptions::MAX_COLUMN_SPAN, 1 } ); + uiOrdering.add( &m_consideredTimestepsType, { .leftLabelColumnSpan = 1 } ); if ( m_consideredTimestepsType == SELECT_TIMESTEPS || m_consideredTimestepsType == SELECT_TIMESTEP_RANGE ) { uiOrdering.add( &m_explicitlySelectedTimeSteps ); @@ -367,16 +367,16 @@ void RimPlotDataFilterItem::defineUiOrdering( QString uiConfigName, caf::PdmUiOr } else { - uiOrdering.add( &m_filterOperation, { true, 2, 1 } ); + uiOrdering.add( &m_filterOperation, { .totalColumnSpan = 2, .leftLabelColumnSpan = 1 } ); if ( m_filterOperation() == RANGE ) { - uiOrdering.add( &m_max, { true, caf::PdmUiOrdering::LayoutOptions::MAX_COLUMN_SPAN, 1 } ); - uiOrdering.add( &m_min, { true, caf::PdmUiOrdering::LayoutOptions::MAX_COLUMN_SPAN, 1 } ); + uiOrdering.add( &m_max, { .leftLabelColumnSpan = 1 } ); + uiOrdering.add( &m_min, { .leftLabelColumnSpan = 1 } ); } else if ( m_filterOperation == TOP_N || m_filterOperation == BOTTOM_N ) { - uiOrdering.add( &m_topBottomN, { false } ); + uiOrdering.appendToRow( &m_topBottomN ); } } diff --git a/ApplicationLibCode/ProjectDataModel/Annotations/RimReachCircleAnnotation.cpp b/ApplicationLibCode/ProjectDataModel/Annotations/RimReachCircleAnnotation.cpp index c69778426a..3bb69c5eab 100644 --- a/ApplicationLibCode/ProjectDataModel/Annotations/RimReachCircleAnnotation.cpp +++ b/ApplicationLibCode/ProjectDataModel/Annotations/RimReachCircleAnnotation.cpp @@ -128,7 +128,7 @@ void RimReachCircleAnnotation::defineUiOrdering( QString uiConfigName, caf::PdmU { uiOrdering.add( &m_name ); uiOrdering.add( &m_centerPointXyd ); - uiOrdering.add( &m_centerPointPickEnabled, false ); + uiOrdering.appendToRow( &m_centerPointPickEnabled ); uiOrdering.add( &m_radius ); auto appearanceGroup = uiOrdering.addNewGroup( "Appearance" ); diff --git a/ApplicationLibCode/ProjectDataModel/Annotations/RimTextAnnotation.cpp b/ApplicationLibCode/ProjectDataModel/Annotations/RimTextAnnotation.cpp index df8fa68b69..4cf8a14fb1 100644 --- a/ApplicationLibCode/ProjectDataModel/Annotations/RimTextAnnotation.cpp +++ b/ApplicationLibCode/ProjectDataModel/Annotations/RimTextAnnotation.cpp @@ -149,9 +149,9 @@ const QString& RimTextAnnotation::text() const void RimTextAnnotation::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) { uiOrdering.add( &m_anchorPointXyd ); - uiOrdering.add( &m_anchorPointPickEnabledButtonField, false ); + uiOrdering.appendToRow( &m_anchorPointPickEnabledButtonField ); uiOrdering.add( &m_labelPointXyd ); - uiOrdering.add( &m_labelPointPickEnabledButtonField, false ); + uiOrdering.appendToRow( &m_labelPointPickEnabledButtonField ); uiOrdering.add( &m_text ); diff --git a/ApplicationLibCode/ProjectDataModel/CellFilters/RimCellFilter.h b/ApplicationLibCode/ProjectDataModel/CellFilters/RimCellFilter.h index 833960a7d6..f61474d541 100644 --- a/ApplicationLibCode/ProjectDataModel/CellFilters/RimCellFilter.h +++ b/ApplicationLibCode/ProjectDataModel/CellFilters/RimCellFilter.h @@ -91,6 +91,7 @@ class RimCellFilter : public caf::PdmObject virtual void updateCompundFilter( cvf::CellRangeFilter* cellRangeFilter, int gridIndex ){}; virtual void updateCellIndexFilter( cvf::UByteArray* includeVisibility, cvf::UByteArray* excludeVisibility, int gridIndex ){}; virtual QString fullName() const; + virtual void onGridChanged(){}; protected: caf::PdmFieldHandle* userDescriptionField() override; diff --git a/ApplicationLibCode/ProjectDataModel/CellFilters/RimCellFilterCollection.cpp b/ApplicationLibCode/ProjectDataModel/CellFilters/RimCellFilterCollection.cpp index 668776fb62..4625282d4e 100644 --- a/ApplicationLibCode/ProjectDataModel/CellFilters/RimCellFilterCollection.cpp +++ b/ApplicationLibCode/ProjectDataModel/CellFilters/RimCellFilterCollection.cpp @@ -282,15 +282,26 @@ RimUserDefinedFilter* RimCellFilterCollection::addNewUserDefinedFilter( RimCase* //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RimUserDefinedIndexFilter* RimCellFilterCollection::addNewUserDefinedIndexFilter( RimCase* srcCase ) +RimUserDefinedIndexFilter* RimCellFilterCollection::addNewUserDefinedIndexFilter( RimCase* srcCase, const std::vector& defCellIndexes ) { RimUserDefinedIndexFilter* pFilter = new RimUserDefinedIndexFilter(); pFilter->setCase( srcCase ); + pFilter->setCellIndexes( defCellIndexes ); addFilter( pFilter ); onFilterUpdated( pFilter ); return pFilter; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimCellFilterCollection::addFilterAndNotifyChanges( RimCellFilter* pFilter, RimCase* srcCase ) +{ + addFilter( pFilter ); + pFilter->setCase( srcCase ); + onFilterUpdated( pFilter ); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -383,6 +394,17 @@ void RimCellFilterCollection::removeFilter( RimCellFilter* filter ) m_cellFilters.removeChild( filter ); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimCellFilterCollection::notifyGridReload() +{ + for ( RimCellFilter* filter : m_cellFilters ) + { + filter->onGridChanged(); + } +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/CellFilters/RimCellFilterCollection.h b/ApplicationLibCode/ProjectDataModel/CellFilters/RimCellFilterCollection.h index 61408d10e4..87a7d808ba 100644 --- a/ApplicationLibCode/ProjectDataModel/CellFilters/RimCellFilterCollection.h +++ b/ApplicationLibCode/ProjectDataModel/CellFilters/RimCellFilterCollection.h @@ -56,9 +56,11 @@ class RimCellFilterCollection : public caf::PdmObject RimCellRangeFilter* addNewCellRangeFilter( RimCase* srcCase, int gridIndex, int sliceDirection = -1, int defaultSlice = -1 ); RimCellIndexFilter* addNewCellIndexFilter( RimCase* srcCase ); RimUserDefinedFilter* addNewUserDefinedFilter( RimCase* srcCase ); - RimUserDefinedIndexFilter* addNewUserDefinedIndexFilter( RimCase* srcCase ); + RimUserDefinedIndexFilter* addNewUserDefinedIndexFilter( RimCase* srcCase, const std::vector& defCellIndexes = {} ); + void addFilterAndNotifyChanges( RimCellFilter* pFilter, RimCase* srcCase ); void removeFilter( RimCellFilter* filter ); + void notifyGridReload(); bool isEmpty() const; bool isActive() const; diff --git a/ApplicationLibCode/ProjectDataModel/CellFilters/RimCellIndexFilter.cpp b/ApplicationLibCode/ProjectDataModel/CellFilters/RimCellIndexFilter.cpp index 4169132718..29289962a9 100644 --- a/ApplicationLibCode/ProjectDataModel/CellFilters/RimCellIndexFilter.cpp +++ b/ApplicationLibCode/ProjectDataModel/CellFilters/RimCellIndexFilter.cpp @@ -161,13 +161,11 @@ void RimCellIndexFilter::updateCells() auto part = parts->part( m_gridIndex() ); auto setNames = part->elementSetNames(); + m_name = QString::fromStdString( part->name() ); + if ( m_setId() < (int)setNames.size() ) { - m_name = QString::fromStdString( part->elementSetNames()[m_setId] ); - } - else - { - m_name = QString::fromStdString( part->name() ); + m_name = m_name + " : " + QString::fromStdString( part->elementSetNames()[m_setId] ); } auto cells = part->elementSet( m_setId() ); @@ -178,3 +176,11 @@ void RimCellIndexFilter::updateCells() } } } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimCellIndexFilter::onGridChanged() +{ + m_cells.clear(); +} diff --git a/ApplicationLibCode/ProjectDataModel/CellFilters/RimCellIndexFilter.h b/ApplicationLibCode/ProjectDataModel/CellFilters/RimCellIndexFilter.h index 76433e3766..175fa247bc 100644 --- a/ApplicationLibCode/ProjectDataModel/CellFilters/RimCellIndexFilter.h +++ b/ApplicationLibCode/ProjectDataModel/CellFilters/RimCellIndexFilter.h @@ -36,6 +36,8 @@ class RimCellIndexFilter : public RimCellFilter void updateCellIndexFilter( cvf::UByteArray* includeVisibility, cvf::UByteArray* excludeVisibility, int gridIndex ) override; + void onGridChanged() override; + protected: void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override; void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override; diff --git a/ApplicationLibCode/ProjectDataModel/CellFilters/RimPolygonFilter.cpp b/ApplicationLibCode/ProjectDataModel/CellFilters/RimPolygonFilter.cpp index 979ee4fc35..77e4599511 100644 --- a/ApplicationLibCode/ProjectDataModel/CellFilters/RimPolygonFilter.cpp +++ b/ApplicationLibCode/ProjectDataModel/CellFilters/RimPolygonFilter.cpp @@ -452,6 +452,14 @@ caf::PickEventHandler* RimPolygonFilter::pickEventHandler() const return m_pickTargetsEventHandler.get(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPolygonFilter::onGridChanged() +{ + m_cells.clear(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/CellFilters/RimPolygonFilter.h b/ApplicationLibCode/ProjectDataModel/CellFilters/RimPolygonFilter.h index 1f43706df9..4ff7ca0ec5 100644 --- a/ApplicationLibCode/ProjectDataModel/CellFilters/RimPolygonFilter.h +++ b/ApplicationLibCode/ProjectDataModel/CellFilters/RimPolygonFilter.h @@ -89,6 +89,7 @@ class RimPolygonFilter : public RimCellFilter, public RimPolylinePickerInterface caf::PickEventHandler* pickEventHandler() const override; void updateCellIndexFilter( cvf::UByteArray* includeVisibility, cvf::UByteArray* excludeVisibility, int gridIndex ) override; + void onGridChanged() override; cvf::ref polyLinesData() const override; diff --git a/ApplicationLibCode/ProjectDataModel/CellFilters/RimUserDefinedIndexFilter.cpp b/ApplicationLibCode/ProjectDataModel/CellFilters/RimUserDefinedIndexFilter.cpp index 95d879ad8b..c11f58f2ef 100644 --- a/ApplicationLibCode/ProjectDataModel/CellFilters/RimUserDefinedIndexFilter.cpp +++ b/ApplicationLibCode/ProjectDataModel/CellFilters/RimUserDefinedIndexFilter.cpp @@ -47,6 +47,20 @@ RimUserDefinedIndexFilter::~RimUserDefinedIndexFilter() { } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimUserDefinedIndexFilter::setCellIndexes( std::vector cellIndexes ) +{ + std::vector cIdxs; + + for ( auto cIdx : cellIndexes ) + { + cIdxs.push_back( (int)cIdx ); + } + m_individualCellIndexes.setValue( cIdxs ); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -87,10 +101,13 @@ void RimUserDefinedIndexFilter::updateCellIndexFilter( cvf::UByteArray* includeV { if ( gridIndex != m_gridIndex() ) return; + const auto filterSize = (int)includeVisibility->size(); + if ( m_filterMode == FilterModeType::INCLUDE ) { for ( auto cellIdx : m_individualCellIndexes() ) { + if ( cellIdx >= filterSize ) continue; ( *includeVisibility )[cellIdx] = true; } } @@ -98,6 +115,7 @@ void RimUserDefinedIndexFilter::updateCellIndexFilter( cvf::UByteArray* includeV { for ( auto cellIdx : m_individualCellIndexes() ) { + if ( cellIdx >= filterSize ) continue; ( *excludeVisibility )[cellIdx] = false; } } diff --git a/ApplicationLibCode/ProjectDataModel/CellFilters/RimUserDefinedIndexFilter.h b/ApplicationLibCode/ProjectDataModel/CellFilters/RimUserDefinedIndexFilter.h index 63085a3f75..fc721c70df 100644 --- a/ApplicationLibCode/ProjectDataModel/CellFilters/RimUserDefinedIndexFilter.h +++ b/ApplicationLibCode/ProjectDataModel/CellFilters/RimUserDefinedIndexFilter.h @@ -36,6 +36,8 @@ class RimUserDefinedIndexFilter : public RimCellFilter RimUserDefinedIndexFilter(); ~RimUserDefinedIndexFilter() override; + void setCellIndexes( std::vector cellIndexes ); + void updateCellIndexFilter( cvf::UByteArray* includeVisibility, cvf::UByteArray* excludeVisibility, int gridIndex ) override; protected: diff --git a/ApplicationLibCode/ProjectDataModel/Completions/RimMswCompletionParameters.cpp b/ApplicationLibCode/ProjectDataModel/Completions/RimMswCompletionParameters.cpp index b987757935..f94aa76643 100644 --- a/ApplicationLibCode/ProjectDataModel/Completions/RimMswCompletionParameters.cpp +++ b/ApplicationLibCode/ProjectDataModel/Completions/RimMswCompletionParameters.cpp @@ -67,8 +67,10 @@ RimMswCompletionParameters::RimMswCompletionParameters() CAF_PDM_InitField( &m_refMD, "RefMD", 0.0, "" ); CAF_PDM_InitField( &m_customValuesForLateral, "CustomValuesForLateral", false, "Custom Values for Lateral" ); - CAF_PDM_InitField( &m_linerDiameter, "LinerDiameter", std::numeric_limits::infinity(), "Liner Inner Diameter" ); - CAF_PDM_InitField( &m_roughnessFactor, "RoughnessFactor", std::numeric_limits::infinity(), "Roughness Factor" ); + + const auto unitSystem = RiaDefines::EclipseUnitSystem::UNITS_METRIC; + CAF_PDM_InitField( &m_linerDiameter, "LinerDiameter", RimMswCompletionParameters::defaultLinerDiameter( unitSystem ), "Liner Inner Diameter" ); + CAF_PDM_InitField( &m_roughnessFactor, "RoughnessFactor", RimMswCompletionParameters::defaultRoughnessFactor( unitSystem ), "Roughness Factor" ); CAF_PDM_InitFieldNoDefault( &m_pressureDrop, "PressureDrop", "Pressure Drop" ); CAF_PDM_InitFieldNoDefault( &m_lengthAndDepth, "LengthAndDepth", "Length and Depth" ); @@ -85,17 +87,6 @@ RimMswCompletionParameters::~RimMswCompletionParameters() { } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool RimMswCompletionParameters::isDefault() const -{ - return m_refMDType() == ReferenceMDEnum() && m_refMD() == m_refMD.defaultValue() && - m_linerDiameter() == m_linerDiameter.defaultValue() && m_roughnessFactor() == m_roughnessFactor.defaultValue() && - m_pressureDrop == PressureDropEnum() && m_enforceMaxSegmentLength() == m_enforceMaxSegmentLength.defaultValue() && - m_maxSegmentLength() == m_maxSegmentLength.defaultValue(); -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -148,13 +139,21 @@ double RimMswCompletionParameters::linerDiameter( RiaDefines::EclipseUnitSystem { return RiaEclipseUnitTools::feetToMeter( diameter ); } - else if ( wellPath->unitSystem() == RiaDefines::EclipseUnitSystem::UNITS_METRIC && unitSystem == RiaDefines::EclipseUnitSystem::UNITS_FIELD ) + if ( wellPath->unitSystem() == RiaDefines::EclipseUnitSystem::UNITS_METRIC && unitSystem == RiaDefines::EclipseUnitSystem::UNITS_FIELD ) { return RiaEclipseUnitTools::meterToFeet( diameter ); } return diameter; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RimMswCompletionParameters::linerDiameter() const +{ + return m_linerDiameter(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -164,10 +163,8 @@ double RimMswCompletionParameters::defaultLinerDiameter( RiaDefines::EclipseUnit { return 0.152; } - else - { - return 0.5; - } + + return 0.5; } //-------------------------------------------------------------------------------------------------- @@ -187,7 +184,7 @@ double RimMswCompletionParameters::roughnessFactor( RiaDefines::EclipseUnitSyste { return RiaEclipseUnitTools::feetToMeter( rFactor ); } - else if ( wellPath->unitSystem() == RiaDefines::EclipseUnitSystem::UNITS_METRIC && unitSystem == RiaDefines::EclipseUnitSystem::UNITS_FIELD ) + if ( wellPath->unitSystem() == RiaDefines::EclipseUnitSystem::UNITS_METRIC && unitSystem == RiaDefines::EclipseUnitSystem::UNITS_FIELD ) { return RiaEclipseUnitTools::meterToFeet( rFactor ); } @@ -195,6 +192,14 @@ double RimMswCompletionParameters::roughnessFactor( RiaDefines::EclipseUnitSyste return rFactor; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RimMswCompletionParameters::roughnessFactor() const +{ + return m_roughnessFactor(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -204,10 +209,8 @@ double RimMswCompletionParameters::defaultRoughnessFactor( RiaDefines::EclipseUn { return 1.0e-5; } - else - { - return 3.28e-5; - } + + return 3.28e-5; } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/Completions/RimMswCompletionParameters.h b/ApplicationLibCode/ProjectDataModel/Completions/RimMswCompletionParameters.h index c8c537f199..a982d82e41 100644 --- a/ApplicationLibCode/ProjectDataModel/Completions/RimMswCompletionParameters.h +++ b/ApplicationLibCode/ProjectDataModel/Completions/RimMswCompletionParameters.h @@ -54,15 +54,14 @@ class RimMswCompletionParameters : public caf::PdmObject RimMswCompletionParameters(); ~RimMswCompletionParameters() override; - bool isDefault() const; RimMswCompletionParameters& operator=( const RimMswCompletionParameters& rhs ); ReferenceMDType referenceMDType() const; double manualReferenceMD() const; double linerDiameter( RiaDefines::EclipseUnitSystem unitSystem ) const; - static double defaultLinerDiameter( RiaDefines::EclipseUnitSystem unitSystem ); + double linerDiameter() const; + double roughnessFactor() const; double roughnessFactor( RiaDefines::EclipseUnitSystem unitSystem ) const; - static double defaultRoughnessFactor( RiaDefines::EclipseUnitSystem unitSystem ); PressureDropEnum pressureDrop() const; LengthAndDepthEnum lengthAndDepth() const; double maxSegmentLength() const; @@ -84,6 +83,10 @@ class RimMswCompletionParameters : public caf::PdmObject void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override; void initAfterRead() override; +private: + static double defaultLinerDiameter( RiaDefines::EclipseUnitSystem unitSystem ); + static double defaultRoughnessFactor( RiaDefines::EclipseUnitSystem unitSystem ); + private: caf::PdmField m_refMDType; caf::PdmField m_refMD; diff --git a/ApplicationLibCode/ProjectDataModel/Completions/RimThermalFractureTemplate.cpp b/ApplicationLibCode/ProjectDataModel/Completions/RimThermalFractureTemplate.cpp index 724e04bced..65fb1f04f2 100644 --- a/ApplicationLibCode/ProjectDataModel/Completions/RimThermalFractureTemplate.cpp +++ b/ApplicationLibCode/ProjectDataModel/Completions/RimThermalFractureTemplate.cpp @@ -35,6 +35,7 @@ #include "RimEclipseView.h" #include "RimFracture.h" +#include "RimProject.h" #include "RimStimPlanColors.h" #include "RimWellPath.h" #include "RimWellPathFracture.h" @@ -151,6 +152,19 @@ bool RimThermalFractureTemplate::setBorderPolygonResultNameToDefault() return false; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimThermalFractureTemplate::fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) +{ + RimMeshFractureTemplate::fieldChangedByUi( changedField, oldValue, newValue ); + + if ( &m_filterCakePressureDropType == changedField ) + { + onLoadDataAndUpdateGeometryHasChanged(); + } +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/Completions/RimThermalFractureTemplate.h b/ApplicationLibCode/ProjectDataModel/Completions/RimThermalFractureTemplate.h index 416e5f3773..7cd3533893 100644 --- a/ApplicationLibCode/ProjectDataModel/Completions/RimThermalFractureTemplate.h +++ b/ApplicationLibCode/ProjectDataModel/Completions/RimThermalFractureTemplate.h @@ -115,6 +115,7 @@ class RimThermalFractureTemplate : public RimMeshFractureTemplate protected: void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override; + void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override; QString getFileSelectionFilter() const override; QStringList conductivityResultNames() const override; diff --git a/ApplicationLibCode/ProjectDataModel/Completions/RimWellPathCompletionSettings.cpp b/ApplicationLibCode/ProjectDataModel/Completions/RimWellPathCompletionSettings.cpp index 22f665fbac..29a73cd208 100644 --- a/ApplicationLibCode/ProjectDataModel/Completions/RimWellPathCompletionSettings.cpp +++ b/ApplicationLibCode/ProjectDataModel/Completions/RimWellPathCompletionSettings.cpp @@ -24,6 +24,8 @@ #include "RimWellPath.h" #include "cafPdmDoubleStringValidator.h" +#include "cafPdmFieldScriptingCapability.h" +#include "cafPdmObjectScriptingCapability.h" #include "cafPdmUiLineEditor.h" #include "cafPdmUiOrdering.h" #include "cafPdmUiTreeOrdering.h" @@ -79,13 +81,13 @@ CAF_PDM_SOURCE_INIT( RimWellPathCompletionSettings, "WellPathCompletionSettings" //-------------------------------------------------------------------------------------------------- RimWellPathCompletionSettings::RimWellPathCompletionSettings() { - CAF_PDM_InitObject( "Completion Settings", ":/CompletionsSymbol16x16.png" ); - CAF_PDM_InitField( &m_wellNameForExport, "WellNameForExport", QString(), "Well Name" ); + CAF_PDM_InitScriptableObject( "Completion Settings", ":/CompletionsSymbol16x16.png" ); + CAF_PDM_InitScriptableField( &m_wellNameForExport, "WellNameForExport", QString(), "Well Name" ); m_wellNameForExport.uiCapability()->setUiEditorTypeName( caf::PdmUiLineEditor::uiEditorTypeName() ); - CAF_PDM_InitField( &m_groupName, "WellGroupNameForExport", QString(), "Group Name" ); + CAF_PDM_InitScriptableFieldWithScriptKeyword( &m_groupName, "WellGroupNameForExport", "GroupNameForExport", QString(), "Group Name" ); CAF_PDM_InitField( &m_referenceDepth, "ReferenceDepthForExport", QString(), "Reference Depth for BHP" ); - CAF_PDM_InitFieldNoDefault( &m_preferredFluidPhase, "WellTypeForExport", "Preferred Fluid Phase" ); + CAF_PDM_InitScriptableFieldNoDefault( &m_preferredFluidPhase, "WellTypeForExport", "Preferred Fluid Phase" ); CAF_PDM_InitField( &m_drainageRadiusForPI, "DrainageRadiusForPI", QString( "0.0" ), "Drainage Radius for PI" ); CAF_PDM_InitFieldNoDefault( &m_gasInflowEquation, "GasInflowEq", "Gas Inflow Equation" ); CAF_PDM_InitFieldNoDefault( &m_automaticWellShutIn, "AutoWellShutIn", "Automatic well shut-in" ); @@ -98,6 +100,14 @@ RimWellPathCompletionSettings::RimWellPathCompletionSettings() m_mswParameters = new RimMswCompletionParameters; m_mswParameters.uiCapability()->setUiTreeHidden( true ); m_mswParameters.uiCapability()->setUiTreeChildrenHidden( true ); + + CAF_PDM_InitScriptableFieldNoDefault( &m_mswLinerDiameter, "MswLinerDiameter", "MSW Liner Diameter" ); + m_mswLinerDiameter.registerGetMethod( this, &RimWellPathCompletionSettings::mswLinerDiameter ); + m_mswLinerDiameter.registerSetMethod( this, &RimWellPathCompletionSettings::setMswLinerDiameter ); + + CAF_PDM_InitScriptableFieldNoDefault( &m_mswRoughness, "MswRoughness", "MSW Roughness" ); + m_mswRoughness.registerGetMethod( this, &RimWellPathCompletionSettings::mswRoughness ); + m_mswRoughness.registerSetMethod( this, &RimWellPathCompletionSettings::setMswRoughness ); } //-------------------------------------------------------------------------------------------------- @@ -361,3 +371,35 @@ QString RimWellPathCompletionSettings::formatStringForExport( const QString& tex if ( text.contains( ' ' ) ) return QString( "'%1'" ).arg( text ); return text; } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellPathCompletionSettings::setMswRoughness( const double& roughness ) +{ + m_mswParameters->setRoughnessFactor( roughness ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RimWellPathCompletionSettings::mswRoughness() const +{ + return m_mswParameters->roughnessFactor(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellPathCompletionSettings::setMswLinerDiameter( const double& diameter ) +{ + m_mswParameters->setLinerDiameter( diameter ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RimWellPathCompletionSettings::mswLinerDiameter() const +{ + return m_mswParameters->linerDiameter(); +} diff --git a/ApplicationLibCode/ProjectDataModel/Completions/RimWellPathCompletionSettings.h b/ApplicationLibCode/ProjectDataModel/Completions/RimWellPathCompletionSettings.h index 16ebd75847..e7f8b62937 100644 --- a/ApplicationLibCode/ProjectDataModel/Completions/RimWellPathCompletionSettings.h +++ b/ApplicationLibCode/ProjectDataModel/Completions/RimWellPathCompletionSettings.h @@ -20,6 +20,7 @@ #include "cafPdmChildField.h" #include "cafPdmField.h" #include "cafPdmObject.h" +#include "cafPdmProxyValueField.h" class RimMswCompletionParameters; class RimWellPathCompletionsLegacy; @@ -93,6 +94,11 @@ class RimWellPathCompletionSettings : public caf::PdmObject private: QString formatStringForExport( const QString& text, const QString& defaultText = "" ) const; + void setMswRoughness( const double& roughness ); + double mswRoughness() const; + void setMswLinerDiameter( const double& diameter ); + double mswLinerDiameter() const; + private: friend class RimWellPathCompletions; @@ -110,4 +116,9 @@ class RimWellPathCompletionSettings : public caf::PdmObject caf::PdmField m_fluidInPlaceRegion; caf::PdmChildField m_mswParameters; + + // Use proxy fields for selected parameters in RimMswCompletionParameters, so it is possible to modify these values from the same + // scripting object + caf::PdmProxyValueField m_mswLinerDiameter; + caf::PdmProxyValueField m_mswRoughness; }; diff --git a/ApplicationLibCode/ProjectDataModel/Completions/RimWellPathFracture.cpp b/ApplicationLibCode/ProjectDataModel/Completions/RimWellPathFracture.cpp index 3a19cb5c80..85911f9f0b 100644 --- a/ApplicationLibCode/ProjectDataModel/Completions/RimWellPathFracture.cpp +++ b/ApplicationLibCode/ProjectDataModel/Completions/RimWellPathFracture.cpp @@ -259,9 +259,9 @@ void RimWellPathFracture::defineUiOrdering( QString uiConfigName, caf::PdmUiOrde if ( m_fractureTemplate() ) { - uiOrdering.add( nameField(), caf::PdmUiOrdering::LayoutOptions( true, 3, 1 ) ); - uiOrdering.add( &m_fractureTemplate, { true, 2, 1 } ); - uiOrdering.add( &m_editFractureTemplate, { false, 1, 0 } ); + uiOrdering.add( nameField(), { .newRow = true, .totalColumnSpan = 3, .leftLabelColumnSpan = 1 } ); + uiOrdering.add( &m_fractureTemplate, { .totalColumnSpan = 2, .leftLabelColumnSpan = 1 } ); + uiOrdering.add( &m_editFractureTemplate, { .newRow = false, .totalColumnSpan = 1, .leftLabelColumnSpan = 0 } ); } else { @@ -270,7 +270,7 @@ void RimWellPathFracture::defineUiOrdering( QString uiConfigName, caf::PdmUiOrde if ( RimProject::current()->allFractureTemplates().empty() ) { uiOrdering.add( &m_createEllipseFractureTemplate ); - uiOrdering.add( &m_createStimPlanFractureTemplate, false ); + uiOrdering.appendToRow( &m_createStimPlanFractureTemplate ); } else { diff --git a/ApplicationLibCode/ProjectDataModel/Completions/RimWellPathValve.cpp b/ApplicationLibCode/ProjectDataModel/Completions/RimWellPathValve.cpp index 82965c32a5..f209c73400 100644 --- a/ApplicationLibCode/ProjectDataModel/Completions/RimWellPathValve.cpp +++ b/ApplicationLibCode/ProjectDataModel/Completions/RimWellPathValve.cpp @@ -510,14 +510,14 @@ void RimWellPathValve::defineUiOrdering( QString uiConfigName, caf::PdmUiOrderin { uiOrdering.skipRemainingFields( true ); - uiOrdering.add( &m_valveTemplate, { true, 2, 1 } ); + uiOrdering.add( &m_valveTemplate, { .totalColumnSpan = 2, .leftLabelColumnSpan = 1 } ); { if ( m_valveTemplate() != nullptr ) { - uiOrdering.add( &m_editValveTemplate, false ); + uiOrdering.appendToRow( &m_editValveTemplate ); } - uiOrdering.add( &m_createValveTemplate, false ); + uiOrdering.appendToRow( &m_createValveTemplate ); } if ( uiConfigName != "TemplateOnly" ) @@ -538,7 +538,7 @@ void RimWellPathValve::defineUiOrdering( QString uiConfigName, caf::PdmUiOrderin m_measuredDepth.uiCapability()->setUiName( "Measured Depth [ft]" ); } } - uiOrdering.add( &m_measuredDepth, { true, 3, 1 } ); + uiOrdering.add( &m_measuredDepth, { .totalColumnSpan = 3, .leftLabelColumnSpan = 1 } ); } } diff --git a/ApplicationLibCode/ProjectDataModel/CorrelationPlots/RimAbstractCorrelationPlot.cpp b/ApplicationLibCode/ProjectDataModel/CorrelationPlots/RimAbstractCorrelationPlot.cpp index bbdf37bb51..1a3013eb7a 100644 --- a/ApplicationLibCode/ProjectDataModel/CorrelationPlots/RimAbstractCorrelationPlot.cpp +++ b/ApplicationLibCode/ProjectDataModel/CorrelationPlots/RimAbstractCorrelationPlot.cpp @@ -748,13 +748,13 @@ void RimAbstractCorrelationPlot::appendDataSourceFields( QString uiConfigName, c m_selectedVarsUiField = selectedVectorNamesText(); curveDataGroup->add( &m_selectedVarsUiField ); - curveDataGroup->add( &m_pushButtonSelectSummaryAddress, { false, 1, 0 } ); + curveDataGroup->add( &m_pushButtonSelectSummaryAddress, { .newRow = false, .totalColumnSpan = 1, .leftLabelColumnSpan = 0 } ); curveDataGroup->add( &m_timeStepFilter ); curveDataGroup->add( &m_timeStep ); curveDataGroup->add( &m_useCaseFilter ); curveDataGroup->add( &m_curveSetForFiltering ); m_curveSetForFiltering.uiCapability()->setUiHidden( !m_useCaseFilter() ); - curveDataGroup->add( &m_editCaseFilter, { false, 1, 0 } ); + curveDataGroup->add( &m_editCaseFilter, { .newRow = false, .totalColumnSpan = 1, .leftLabelColumnSpan = 0 } ); m_editCaseFilter.uiCapability()->setUiHidden( !m_useCaseFilter() ); } diff --git a/ApplicationLibCode/ProjectDataModel/Faults/CMakeLists_files.cmake b/ApplicationLibCode/ProjectDataModel/Faults/CMakeLists_files.cmake index 26d1414139..c904cfb827 100644 --- a/ApplicationLibCode/ProjectDataModel/Faults/CMakeLists_files.cmake +++ b/ApplicationLibCode/ProjectDataModel/Faults/CMakeLists_files.cmake @@ -5,6 +5,12 @@ set(SOURCE_GROUP_HEADER_FILES ${CMAKE_CURRENT_LIST_DIR}/RimFaultReactivationModelCollection.h ${CMAKE_CURRENT_LIST_DIR}/RimFaultReactivationTools.h ${CMAKE_CURRENT_LIST_DIR}/RimFaultReactivationDataAccess.h + ${CMAKE_CURRENT_LIST_DIR}/RimFaultReactivationDataAccessor.h + ${CMAKE_CURRENT_LIST_DIR}/RimFaultReactivationDataAccessorPorePressure.h + ${CMAKE_CURRENT_LIST_DIR}/RimFaultReactivationDataAccessorVoidRatio.h + ${CMAKE_CURRENT_LIST_DIR}/RimFaultReactivationDataAccessorTemperature.h + ${CMAKE_CURRENT_LIST_DIR}/RimFaultReactivationDataAccessorGeoMech.h + ${CMAKE_CURRENT_LIST_DIR}/RimFaultReactivationDataAccessorStress.h ${CMAKE_CURRENT_LIST_DIR}/RimFaultReactivationEnums.h ) @@ -15,6 +21,12 @@ set(SOURCE_GROUP_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/RimFaultReactivationModelCollection.cpp ${CMAKE_CURRENT_LIST_DIR}/RimFaultReactivationTools.cpp ${CMAKE_CURRENT_LIST_DIR}/RimFaultReactivationDataAccess.cpp + ${CMAKE_CURRENT_LIST_DIR}/RimFaultReactivationDataAccessor.cpp + ${CMAKE_CURRENT_LIST_DIR}/RimFaultReactivationDataAccessorPorePressure.cpp + ${CMAKE_CURRENT_LIST_DIR}/RimFaultReactivationDataAccessorVoidRatio.cpp + ${CMAKE_CURRENT_LIST_DIR}/RimFaultReactivationDataAccessorTemperature.cpp + ${CMAKE_CURRENT_LIST_DIR}/RimFaultReactivationDataAccessorGeoMech.cpp + ${CMAKE_CURRENT_LIST_DIR}/RimFaultReactivationDataAccessorStress.cpp ) list(APPEND CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES}) diff --git a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationDataAccess.cpp b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationDataAccess.cpp index 05edc676d2..20b961580f 100644 --- a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationDataAccess.cpp +++ b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationDataAccess.cpp @@ -18,42 +18,61 @@ #include "RimFaultReactivationDataAccess.h" +#include "RiaDefines.h" #include "RiaPorosityModel.h" #include "RigCaseCellResultsData.h" +#include "RigCaseToCaseCellMapperTools.h" #include "RigEclipseCaseData.h" #include "RigEclipseResultAddress.h" #include "RigFault.h" +#include "RigFaultReactivationModel.h" +#include "RigGriddedPart3d.h" #include "RigMainGrid.h" #include "RigResultAccessorFactory.h" #include "RimEclipseCase.h" +#include "RimFaultReactivationDataAccessor.h" +#include "RimFaultReactivationDataAccessorGeoMech.h" +#include "RimFaultReactivationDataAccessorPorePressure.h" +#include "RimFaultReactivationDataAccessorStress.h" +#include "RimFaultReactivationDataAccessorTemperature.h" +#include "RimFaultReactivationDataAccessorVoidRatio.h" +#include "RimFaultReactivationEnums.h" //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RimFaultReactivationDataAccess::RimFaultReactivationDataAccess( RimEclipseCase* thecase, size_t timeStepIndex ) - : m_case( thecase ) - , m_caseData( nullptr ) - , m_mainGrid( nullptr ) - , m_timeStepIndex( timeStepIndex ) +RimFaultReactivationDataAccess::RimFaultReactivationDataAccess( RimEclipseCase* thecase, + RimGeoMechCase* geoMechCase, + const std::vector& timeSteps ) + : m_timeSteps( timeSteps ) { - if ( m_case ) + // TODO: correct default pore pressure gradient? + m_accessors.push_back( std::make_shared( thecase, 1.0 ) ); + m_accessors.push_back( std::make_shared( thecase, 0.0001 ) ); + m_accessors.push_back( std::make_shared( thecase ) ); + if ( geoMechCase ) { - m_caseData = m_case->eclipseCaseData(); - m_mainGrid = m_case->mainGrid(); - } - if ( m_caseData ) - { - RigEclipseResultAddress resVarAddress( RiaDefines::ResultCatType::DYNAMIC_NATIVE, "PRESSURE" ); + std::vector properties = { RimFaultReactivation::Property::YoungsModulus, + RimFaultReactivation::Property::PoissonsRatio, + RimFaultReactivation::Property::Density }; - m_case->results( RiaDefines::PorosityModelType::MATRIX_MODEL )->ensureKnownResultLoaded( resVarAddress ); + for ( auto property : properties ) + { + m_accessors.push_back( std::make_shared( geoMechCase, property ) ); + } - m_resultAccessor = RigResultAccessorFactory::createFromResultAddress( m_caseData, - 0, - RiaDefines::PorosityModelType::MATRIX_MODEL, - timeStepIndex, - resVarAddress ); + std::vector stressProperties = { RimFaultReactivation::Property::StressTop, + RimFaultReactivation::Property::DepthTop, + RimFaultReactivation::Property::StressBottom, + RimFaultReactivation::Property::DepthBottom, + RimFaultReactivation::Property::LateralStressComponentX, + RimFaultReactivation::Property::LateralStressComponentY }; + for ( auto property : stressProperties ) + { + m_accessors.push_back( std::make_shared( geoMechCase, property ) ); + } } } @@ -67,67 +86,125 @@ RimFaultReactivationDataAccess::~RimFaultReactivationDataAccess() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimFaultReactivationDataAccess::useCellIndexAdjustment( std::map adjustments ) +std::vector RimFaultReactivationDataAccess::propertyValues( RimFaultReactivation::GridPart gridPart, + RimFaultReactivation::Property property, + size_t outputTimeStep ) const { - m_cellIndexAdjustment = adjustments; + const auto it = m_propertyValues.find( { gridPart, property } ); + if ( it == m_propertyValues.end() || outputTimeStep >= it->second.size() ) return {}; + return it->second[outputTimeStep]; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -size_t RimFaultReactivationDataAccess::findAdjustedCellIndex( const cvf::Vec3d& position, - const RigMainGrid* grid, - const std::map& cellIndexAdjustmentMap ) +void RimFaultReactivationDataAccess::clearModelData() { - CAF_ASSERT( grid != nullptr ); - - size_t cellIdx = grid->findReservoirCellIndexFromPoint( position ); - - // adjust cell index if present in the map - if ( auto search = cellIndexAdjustmentMap.find( cellIdx ); search != cellIndexAdjustmentMap.end() ) - { - cellIdx = search->second; - } - - return cellIdx; + m_accessors.clear(); + m_propertyValues.clear(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -double RimFaultReactivationDataAccess::porePressureAtPosition( const cvf::Vec3d& position, double defaultPorePressureGradient ) const +std::vector RimFaultReactivationDataAccess::extractModelData( const RigFaultReactivationModel& model, + RimFaultReactivation::GridPart gridPart, + RimFaultReactivation::Property property, + size_t timeStep ) { - if ( ( m_mainGrid != nullptr ) && m_resultAccessor.notNull() ) + std::set nodeProperties = { RimFaultReactivation::Property::PorePressure, + RimFaultReactivation::Property::VoidRatio, + RimFaultReactivation::Property::Temperature }; + + auto computeAverageDepth = []( const std::vector& positions, const std::vector& indices ) + { + double sum = 0.0; + for ( size_t idx : indices ) + sum += positions[idx].z(); + + return sum / indices.size(); + }; + + std::shared_ptr accessor = getAccessor( property ); + if ( accessor ) { - auto cellIdx = findAdjustedCellIndex( position, m_mainGrid, m_cellIndexAdjustment ); + accessor->setTimeStep( timeStep ); - if ( ( cellIdx != cvf::UNDEFINED_SIZE_T ) ) + auto grid = model.grid( gridPart ); + + std::vector values; + + if ( nodeProperties.contains( property ) ) { - double value = m_resultAccessor->cellScalar( cellIdx ); - if ( !std::isinf( value ) ) + for ( auto& node : grid->globalNodes() ) { - return 100000.0 * m_resultAccessor->cellScalar( cellIdx ); // return in pascal, not bar + double value = accessor->valueAtPosition( node ); + values.push_back( value ); } } + else + { + size_t numElements = grid->elementIndices().size(); + for ( size_t elementIndex = 0; elementIndex < numElements; elementIndex++ ) + { + std::vector corners = grid->elementCorners( elementIndex ); + + double topDepth = computeAverageDepth( corners, { 0, 1, 2, 3 } ); + double bottomDepth = computeAverageDepth( corners, { 4, 5, 6, 7 } ); + + cvf::Vec3d position = RigCaseToCaseCellMapperTools::calculateCellCenter( corners.data() ); + double value = accessor->valueAtPosition( position, topDepth, bottomDepth ); + values.push_back( value ); + } + } + + return values; } - return calculatePorePressure( std::abs( position.z() ), defaultPorePressureGradient ); + return {}; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -double RimFaultReactivationDataAccess::calculatePorePressure( double depth, double gradient ) +void RimFaultReactivationDataAccess::extractModelData( const RigFaultReactivationModel& model ) { - return gradient * 9.81 * depth * 1000.0; + auto properties = { RimFaultReactivation::Property::PorePressure, + RimFaultReactivation::Property::VoidRatio, + RimFaultReactivation::Property::Temperature, + RimFaultReactivation::Property::YoungsModulus, + RimFaultReactivation::Property::PoissonsRatio, + RimFaultReactivation::Property::Density, + RimFaultReactivation::Property::StressTop, + RimFaultReactivation::Property::DepthTop, + RimFaultReactivation::Property::StressBottom, + RimFaultReactivation::Property::DepthBottom, + RimFaultReactivation::Property::LateralStressComponentX, + RimFaultReactivation::Property::LateralStressComponentY }; + + for ( auto property : properties ) + { + for ( auto part : model.allGridParts() ) + { + std::vector> dataForAllTimeSteps; + for ( size_t timeStep : m_timeSteps ) + { + dataForAllTimeSteps.push_back( extractModelData( model, part, property, timeStep ) ); + } + m_propertyValues[{ part, property }] = dataForAllTimeSteps; + } + } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -size_t RimFaultReactivationDataAccess::timeStepIndex() const +std::shared_ptr RimFaultReactivationDataAccess::getAccessor( RimFaultReactivation::Property property ) const { - return m_timeStepIndex; + for ( auto accessor : m_accessors ) + if ( accessor->isMatching( property ) ) return accessor; + + return nullptr; } //-------------------------------------------------------------------------------------------------- @@ -135,19 +212,16 @@ size_t RimFaultReactivationDataAccess::timeStepIndex() const //-------------------------------------------------------------------------------------------------- bool RimFaultReactivationDataAccess::elementHasValidData( std::vector elementCorners ) const { + auto accessor = getAccessor( RimFaultReactivation::Property::PorePressure ); + if ( !accessor ) return false; + + accessor->setTimeStep( 0 ); + int nValid = 0; + for ( auto& p : elementCorners ) { - auto cellIdx = findAdjustedCellIndex( p, m_mainGrid, m_cellIndexAdjustment ); - - if ( ( cellIdx != cvf::UNDEFINED_SIZE_T ) ) - { - double value = m_resultAccessor->cellScalar( cellIdx ); - if ( !std::isinf( value ) ) - { - nValid++; - } - } + if ( accessor->hasValidDataAtPosition( p ) ) nValid++; } // if more than half of the nodes have valid data, we're ok diff --git a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationDataAccess.h b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationDataAccess.h index 9ae70d04a6..0410ade5a6 100644 --- a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationDataAccess.h +++ b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationDataAccess.h @@ -18,16 +18,20 @@ #pragma once -#include "cvfObject.h" +#include "RimFaultReactivationDataAccessor.h" + +#include "RimFaultReactivationEnums.h" + #include "cvfVector3.h" #include +#include #include class RimEclipseCase; -class RigEclipseCaseData; -class RigResultAccessor; -class RigMainGrid; +class RimGeoMechCase; +class RimFaultReactivationDataAccessor; +class RigFaultReactivationModel; //================================================================================================== /// @@ -36,28 +40,28 @@ class RigMainGrid; class RimFaultReactivationDataAccess { public: - RimFaultReactivationDataAccess( RimEclipseCase* thecase, size_t timeStepIndex ); + RimFaultReactivationDataAccess( RimEclipseCase* eclipseCase, RimGeoMechCase* geoMechCase, const std::vector& timeSteps ); ~RimFaultReactivationDataAccess(); - void useCellIndexAdjustment( std::map adjustments ); + void extractModelData( const RigFaultReactivationModel& model ); - double porePressureAtPosition( const cvf::Vec3d& position, double defaultPorePressureGradient ) const; + void clearModelData(); - size_t timeStepIndex() const; - - static size_t - findAdjustedCellIndex( const cvf::Vec3d& position, const RigMainGrid* grid, const std::map& cellIndexAdjustmentMap ); + std::vector + propertyValues( RimFaultReactivation::GridPart gridPart, RimFaultReactivation::Property property, size_t outputTimeStep ) const; bool elementHasValidData( std::vector elementCorners ) const; -protected: - static double calculatePorePressure( double depth, double gradient ); - private: - RimEclipseCase* m_case; - RigEclipseCaseData* m_caseData; - const RigMainGrid* m_mainGrid; - size_t m_timeStepIndex; - cvf::ref m_resultAccessor; - std::map m_cellIndexAdjustment; + std::shared_ptr getAccessor( RimFaultReactivation::Property property ) const; + + std::vector extractModelData( const RigFaultReactivationModel& model, + RimFaultReactivation::GridPart gridPart, + RimFaultReactivation::Property property, + size_t timeStep ); + + std::vector> m_accessors; + std::vector m_timeSteps; + + std::map, std::vector>> m_propertyValues; }; diff --git a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationDataAccessor.cpp b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationDataAccessor.cpp new file mode 100644 index 0000000000..c12f04b509 --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationDataAccessor.cpp @@ -0,0 +1,47 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 "RimFaultReactivationDataAccessor.h" + +#include "RigMainGrid.h" + +#include "cafAssert.h" + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimFaultReactivationDataAccessor::RimFaultReactivationDataAccessor() +{ + m_timeStep = -1; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimFaultReactivationDataAccessor::~RimFaultReactivationDataAccessor() +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFaultReactivationDataAccessor::setTimeStep( size_t timeStep ) +{ + m_timeStep = timeStep; + updateResultAccessor(); +} diff --git a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationDataAccessor.h b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationDataAccessor.h new file mode 100644 index 0000000000..2a125fb1b8 --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationDataAccessor.h @@ -0,0 +1,54 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 "cvfVector3.h" + +#include "RimFaultReactivationEnums.h" + +#include +#include + +class RigMainGrid; + +//================================================================================================== +/// +/// +//================================================================================================== +class RimFaultReactivationDataAccessor +{ +public: + RimFaultReactivationDataAccessor(); + ~RimFaultReactivationDataAccessor(); + + virtual void setTimeStep( size_t timeStep ); + + virtual bool isMatching( RimFaultReactivation::Property property ) const = 0; + + virtual double valueAtPosition( const cvf::Vec3d& position, + double topDepth = std::numeric_limits::infinity(), + double bottomDepth = std::numeric_limits::infinity() ) const = 0; + + virtual bool hasValidDataAtPosition( const cvf::Vec3d& position ) const = 0; + +protected: + virtual void updateResultAccessor() = 0; + + size_t m_timeStep; +}; diff --git a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationDataAccessorGeoMech.cpp b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationDataAccessorGeoMech.cpp new file mode 100644 index 0000000000..5465fd67db --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationDataAccessorGeoMech.cpp @@ -0,0 +1,132 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 "RimFaultReactivationDataAccessorGeoMech.h" + +#include "RiaEclipseUnitTools.h" + +#include "RigFemPartCollection.h" +#include "RigFemPartResultsCollection.h" +#include "RigFemResultAddress.h" +#include "RigFemScalarResultFrames.h" +#include "RigGeoMechCaseData.h" +#include "RigHexIntersectionTools.h" +#include "RigMainGrid.h" +#include "RigResultAccessorFactory.h" + +#include "RimFaultReactivationEnums.h" +#include "RimGeoMechCase.h" +#include "RimWellIADataAccess.h" + +#include +#include + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimFaultReactivationDataAccessorGeoMech::RimFaultReactivationDataAccessorGeoMech( RimGeoMechCase* geoMechCase, + RimFaultReactivation::Property property ) + : m_geoMechCase( geoMechCase ) + , m_property( property ) +{ + m_geoMechCaseData = geoMechCase->geoMechData(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimFaultReactivationDataAccessorGeoMech::~RimFaultReactivationDataAccessorGeoMech() +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFaultReactivationDataAccessorGeoMech::updateResultAccessor() +{ + const int partIndex = 0; + + auto loadFrameLambda = [&]( auto femParts, RigFemResultAddress addr ) -> RigFemScalarResultFrames* + { + auto result = femParts->findOrLoadScalarResult( partIndex, addr ); + if ( result->frameData( 0, 0 ).empty() ) + { + return nullptr; + } + return result; + }; + + auto femParts = m_geoMechCaseData->femPartResults(); + m_resultFrames = loadFrameLambda( femParts, getResultAddress( m_property ) ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RigFemResultAddress RimFaultReactivationDataAccessorGeoMech::getResultAddress( RimFaultReactivation::Property property ) +{ + if ( property == RimFaultReactivation::Property::YoungsModulus ) return RigFemResultAddress( RIG_ELEMENT, "MODULUS", "" ); + if ( property == RimFaultReactivation::Property::PoissonsRatio ) return RigFemResultAddress( RIG_ELEMENT, "RATIO", "" ); + CAF_ASSERT( property == RimFaultReactivation::Property::Density ); + return RigFemResultAddress( RIG_ELEMENT, "DENSITY", "" ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimFaultReactivationDataAccessorGeoMech::isMatching( RimFaultReactivation::Property property ) const +{ + return property == m_property; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RimFaultReactivationDataAccessorGeoMech::valueAtPosition( const cvf::Vec3d& position, double topDepth, double bottomDepth ) const + +{ + if ( !m_resultFrames ) return std::numeric_limits::infinity(); + + RimWellIADataAccess iaDataAccess( m_geoMechCase ); + int elementIdx = iaDataAccess.elementIndex( position ); + if ( elementIdx != -1 ) + { + int timeStepIndex = 0; + int frameIndex = 0; + + const std::vector& data = m_resultFrames->frameData( timeStepIndex, frameIndex ); + if ( elementIdx >= static_cast( data.size() ) ) return std::numeric_limits::infinity(); + + if ( m_property == RimFaultReactivation::Property::YoungsModulus ) + { + return RiaEclipseUnitTools::gigaPascalToPascal( data[elementIdx] ); + } + return data[elementIdx]; + } + + return std::numeric_limits::infinity(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimFaultReactivationDataAccessorGeoMech::hasValidDataAtPosition( const cvf::Vec3d& position ) const +{ + double value = valueAtPosition( position ); + return !std::isinf( value ); +} diff --git a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationDataAccessorGeoMech.h b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationDataAccessorGeoMech.h new file mode 100644 index 0000000000..99efa722f2 --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationDataAccessorGeoMech.h @@ -0,0 +1,58 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 "RimFaultReactivationDataAccessor.h" +#include "RimFaultReactivationEnums.h" + +#include "RigFemResultAddress.h" + +class RigFemPartResultsCollection; +class RimGeoMechCase; +class RigGeoMechCaseData; +class RigFemScalarResultFrames; + +//================================================================================================== +/// +/// +//================================================================================================== +class RimFaultReactivationDataAccessorGeoMech : public RimFaultReactivationDataAccessor +{ +public: + RimFaultReactivationDataAccessorGeoMech( RimGeoMechCase* geoMechCase, RimFaultReactivation::Property property ); + ~RimFaultReactivationDataAccessorGeoMech(); + + bool isMatching( RimFaultReactivation::Property property ) const override; + + double valueAtPosition( const cvf::Vec3d& position, + double topDepth = std::numeric_limits::infinity(), + double bottomDepth = std::numeric_limits::infinity() ) const override; + + bool hasValidDataAtPosition( const cvf::Vec3d& position ) const override; + +private: + void updateResultAccessor() override; + + static RigFemResultAddress getResultAddress( RimFaultReactivation::Property property ); + + RimGeoMechCase* m_geoMechCase; + RimFaultReactivation::Property m_property; + RigGeoMechCaseData* m_geoMechCaseData; + RigFemScalarResultFrames* m_resultFrames; +}; diff --git a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationDataAccessorPorePressure.cpp b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationDataAccessorPorePressure.cpp new file mode 100644 index 0000000000..67a137a8ce --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationDataAccessorPorePressure.cpp @@ -0,0 +1,125 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 "RimFaultReactivationDataAccessorPorePressure.h" +#include "RimFaciesProperties.h" +#include "RimFaultReactivationEnums.h" + +#include "RiaDefines.h" +#include "RiaPorosityModel.h" + +#include "RigCaseCellResultsData.h" +#include "RigEclipseCaseData.h" +#include "RigEclipseResultAddress.h" +#include "RigMainGrid.h" +#include "RigResultAccessorFactory.h" + +#include "RimEclipseCase.h" + +#include + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimFaultReactivationDataAccessorPorePressure::RimFaultReactivationDataAccessorPorePressure( RimEclipseCase* eclipseCase, + double porePressureGradient ) + : m_eclipseCase( eclipseCase ) + , m_defaultPorePressureGradient( porePressureGradient ) + , m_caseData( nullptr ) + , m_mainGrid( nullptr ) +{ + if ( m_eclipseCase ) + { + m_caseData = m_eclipseCase->eclipseCaseData(); + m_mainGrid = m_eclipseCase->mainGrid(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimFaultReactivationDataAccessorPorePressure::~RimFaultReactivationDataAccessorPorePressure() +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFaultReactivationDataAccessorPorePressure::updateResultAccessor() +{ + if ( m_caseData ) + { + RigEclipseResultAddress resVarAddress( RiaDefines::ResultCatType::DYNAMIC_NATIVE, "PRESSURE" ); + m_eclipseCase->results( RiaDefines::PorosityModelType::MATRIX_MODEL )->ensureKnownResultLoaded( resVarAddress ); + + m_resultAccessor = RigResultAccessorFactory::createFromResultAddress( m_caseData, + 0, + RiaDefines::PorosityModelType::MATRIX_MODEL, + m_timeStep, + resVarAddress ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimFaultReactivationDataAccessorPorePressure::isMatching( RimFaultReactivation::Property property ) const +{ + return property == RimFaultReactivation::Property::PorePressure; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RimFaultReactivationDataAccessorPorePressure::valueAtPosition( const cvf::Vec3d& position, double topDepth, double bottomDepth ) const +{ + if ( ( m_mainGrid != nullptr ) && m_resultAccessor.notNull() ) + { + auto cellIdx = m_mainGrid->findReservoirCellIndexFromPoint( position ); + if ( cellIdx != cvf::UNDEFINED_SIZE_T ) + { + double value = m_resultAccessor->cellScalar( cellIdx ); + if ( !std::isinf( value ) ) + { + return 100000.0 * value; // return in pascal, not bar + } + } + } + + return calculatePorePressure( std::abs( position.z() ), m_defaultPorePressureGradient ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RimFaultReactivationDataAccessorPorePressure::calculatePorePressure( double depth, double gradient ) +{ + return gradient * 9.81 * depth * 1000.0; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimFaultReactivationDataAccessorPorePressure::hasValidDataAtPosition( const cvf::Vec3d& position ) const +{ + auto cellIdx = m_mainGrid->findReservoirCellIndexFromPoint( position ); + if ( cellIdx == cvf::UNDEFINED_SIZE_T ) return false; + + double value = m_resultAccessor->cellScalar( cellIdx ); + return !std::isinf( value ); +} diff --git a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationDataAccessorPorePressure.h b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationDataAccessorPorePressure.h new file mode 100644 index 0000000000..bd80a0e34d --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationDataAccessorPorePressure.h @@ -0,0 +1,60 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 "cvfObject.h" +#include "cvfVector3.h" + +#include "RimFaultReactivationDataAccessor.h" +#include "RimFaultReactivationEnums.h" + +class RimEclipseCase; +class RigEclipseCaseData; +class RigMainGrid; +class RigResultAccessor; + +//================================================================================================== +/// +/// +//================================================================================================== +class RimFaultReactivationDataAccessorPorePressure : public RimFaultReactivationDataAccessor +{ +public: + RimFaultReactivationDataAccessorPorePressure( RimEclipseCase* eclipseCase, double porePressureGradient ); + ~RimFaultReactivationDataAccessorPorePressure(); + + bool isMatching( RimFaultReactivation::Property property ) const override; + + double valueAtPosition( const cvf::Vec3d& position, + double topDepth = std::numeric_limits::infinity(), + double bottomDepth = std::numeric_limits::infinity() ) const override; + + bool hasValidDataAtPosition( const cvf::Vec3d& position ) const override; + +private: + void updateResultAccessor() override; + + static double calculatePorePressure( double depth, double gradient ); + + RimEclipseCase* m_eclipseCase; + RigEclipseCaseData* m_caseData; + const RigMainGrid* m_mainGrid; + double m_defaultPorePressureGradient; + cvf::ref m_resultAccessor; +}; diff --git a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationDataAccessorStress.cpp b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationDataAccessorStress.cpp new file mode 100644 index 0000000000..c6596816e5 --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationDataAccessorStress.cpp @@ -0,0 +1,179 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 "RimFaultReactivationDataAccessorStress.h" + +#include "RiaEclipseUnitTools.h" + +#include "RigFemAddressDefines.h" +#include "RigFemPartCollection.h" +#include "RigFemPartResultsCollection.h" +#include "RigFemResultAddress.h" +#include "RigFemScalarResultFrames.h" +#include "RigGeoMechCaseData.h" +#include "RigResultAccessorFactory.h" + +#include "RimFaultReactivationEnums.h" +#include "RimGeoMechCase.h" +#include "RimWellIADataAccess.h" + +#include +#include + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimFaultReactivationDataAccessorStress::RimFaultReactivationDataAccessorStress( RimGeoMechCase* geoMechCase, + RimFaultReactivation::Property property ) + : m_geoMechCase( geoMechCase ) + , m_property( property ) +{ + m_geoMechCaseData = geoMechCase->geoMechData(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimFaultReactivationDataAccessorStress::~RimFaultReactivationDataAccessorStress() +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFaultReactivationDataAccessorStress::updateResultAccessor() +{ + const int partIndex = 0; + + auto loadFrameLambda = [&]( auto femParts, RigFemResultAddress addr ) -> RigFemScalarResultFrames* + { + auto result = femParts->findOrLoadScalarResult( partIndex, addr ); + if ( result->frameData( 0, 0 ).empty() ) + { + return nullptr; + } + return result; + }; + + auto femParts = m_geoMechCaseData->femPartResults(); + m_femPart = femParts->parts()->part( partIndex ); + m_s33Frames = loadFrameLambda( femParts, getResultAddress( "ST", "S33" ) ); + m_s11Frames = loadFrameLambda( femParts, getResultAddress( "ST", "S11" ) ); + m_s22Frames = loadFrameLambda( femParts, getResultAddress( "ST", "S22" ) ); + m_porFrames = loadFrameLambda( femParts, RigFemAddressDefines::elementNodalPorBarAddress() ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RigFemResultAddress RimFaultReactivationDataAccessorStress::getResultAddress( const std::string& fieldName, const std::string& componentName ) +{ + return RigFemResultAddress( RIG_ELEMENT_NODAL, fieldName, componentName ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimFaultReactivationDataAccessorStress::isMatching( RimFaultReactivation::Property property ) const +{ + return property == m_property; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RimFaultReactivationDataAccessorStress::valueAtPosition( const cvf::Vec3d& position, double topDepth, double bottomDepth ) const +{ + if ( !m_porFrames || !m_s11Frames || !m_s22Frames || !m_s33Frames || !m_femPart ) return std::numeric_limits::infinity(); + + RimWellIADataAccess iaDataAccess( m_geoMechCase ); + int centerElementIdx = iaDataAccess.elementIndex( position ); + + cvf::Vec3d topPosition( position.x(), position.y(), topDepth ); + int topElementIdx = iaDataAccess.elementIndex( topPosition ); + + cvf::Vec3d bottomPosition( position.x(), position.y(), bottomDepth ); + int bottomElementIdx = iaDataAccess.elementIndex( bottomPosition ); + if ( centerElementIdx != -1 && topElementIdx != -1 && bottomElementIdx != -1 ) + { + int timeStepIndex = 0; + int frameIndex = 0; + + const std::vector& s11Data = m_s11Frames->frameData( timeStepIndex, frameIndex ); + const std::vector& s22Data = m_s22Frames->frameData( timeStepIndex, frameIndex ); + const std::vector& s33Data = m_s33Frames->frameData( timeStepIndex, frameIndex ); + const std::vector& porData = m_porFrames->frameData( timeStepIndex, frameIndex ); + + if ( m_property == RimFaultReactivation::Property::StressTop ) + { + double s33 = interpolatedResultValue( iaDataAccess, m_femPart, topPosition, s33Data ); + double porBar = interpolatedResultValue( iaDataAccess, m_femPart, topPosition, porData ); + return RiaEclipseUnitTools::barToPascal( s33 - porBar ); + } + else if ( m_property == RimFaultReactivation::Property::StressBottom ) + { + double s33 = interpolatedResultValue( iaDataAccess, m_femPart, bottomPosition, s33Data ); + double porBar = interpolatedResultValue( iaDataAccess, m_femPart, bottomPosition, porData ); + return RiaEclipseUnitTools::barToPascal( s33 - porBar ); + } + else if ( m_property == RimFaultReactivation::Property::DepthTop ) + { + return topDepth; + } + else if ( m_property == RimFaultReactivation::Property::DepthBottom ) + { + return bottomDepth; + } + else if ( m_property == RimFaultReactivation::Property::LateralStressComponentX ) + { + double s11 = interpolatedResultValue( iaDataAccess, m_femPart, position, s11Data ); + double s33 = interpolatedResultValue( iaDataAccess, m_femPart, position, s33Data ); + double porBar = interpolatedResultValue( iaDataAccess, m_femPart, position, porData ); + return ( s11 - porBar ) / ( s33 - porBar ); + } + else if ( m_property == RimFaultReactivation::Property::LateralStressComponentY ) + { + double s22 = interpolatedResultValue( iaDataAccess, m_femPart, position, s22Data ); + double s33 = interpolatedResultValue( iaDataAccess, m_femPart, position, s33Data ); + double porBar = interpolatedResultValue( iaDataAccess, m_femPart, position, porData ); + return ( s22 - porBar ) / ( s33 - porBar ); + } + } + + return std::numeric_limits::infinity(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimFaultReactivationDataAccessorStress::hasValidDataAtPosition( const cvf::Vec3d& position ) const +{ + double value = valueAtPosition( position ); + return !std::isinf( value ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RimFaultReactivationDataAccessorStress::interpolatedResultValue( RimWellIADataAccess& iaDataAccess, + const RigFemPart* femPart, + const cvf::Vec3d& position, + const std::vector& scalarResults ) const +{ + return iaDataAccess.interpolatedResultValue( femPart, scalarResults, RIG_ELEMENT_NODAL, position ); +} diff --git a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationDataAccessorStress.h b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationDataAccessorStress.h new file mode 100644 index 0000000000..53a87f1bb4 --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationDataAccessorStress.h @@ -0,0 +1,71 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 "RimFaultReactivationDataAccessor.h" +#include "RimFaultReactivationEnums.h" + +#include "RigFemResultAddress.h" + +#include + +class RigFemPartResultsCollection; +class RimGeoMechCase; +class RigGeoMechCaseData; +class RigFemScalarResultFrames; +class RigFemPart; +class RimWellIADataAccess; + +//================================================================================================== +/// +/// +//================================================================================================== +class RimFaultReactivationDataAccessorStress : public RimFaultReactivationDataAccessor +{ +public: + RimFaultReactivationDataAccessorStress( RimGeoMechCase* geoMechCase, RimFaultReactivation::Property property ); + ~RimFaultReactivationDataAccessorStress(); + + bool isMatching( RimFaultReactivation::Property property ) const override; + + double valueAtPosition( const cvf::Vec3d& position, + double topDepth = std::numeric_limits::infinity(), + double bottomDepth = std::numeric_limits::infinity() ) const override; + + bool hasValidDataAtPosition( const cvf::Vec3d& position ) const override; + +private: + void updateResultAccessor() override; + + static RigFemResultAddress getResultAddress( const std::string& fieldName, const std::string& componentName ); + + double interpolatedResultValue( RimWellIADataAccess& iaDataAccess, + const RigFemPart* femPart, + const cvf::Vec3d& position, + const std::vector& scalarResults ) const; + + RimGeoMechCase* m_geoMechCase; + RimFaultReactivation::Property m_property; + RigGeoMechCaseData* m_geoMechCaseData; + RigFemScalarResultFrames* m_s11Frames; + RigFemScalarResultFrames* m_s22Frames; + RigFemScalarResultFrames* m_s33Frames; + RigFemScalarResultFrames* m_porFrames; + const RigFemPart* m_femPart; +}; diff --git a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationDataAccessorTemperature.cpp b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationDataAccessorTemperature.cpp new file mode 100644 index 0000000000..49364a25d8 --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationDataAccessorTemperature.cpp @@ -0,0 +1,107 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 "RimFaultReactivationDataAccessorTemperature.h" +#include "RimFaultReactivationEnums.h" + +#include "RiaDefines.h" +#include "RiaPorosityModel.h" + +#include "RigCaseCellResultsData.h" +#include "RigEclipseCaseData.h" +#include "RigEclipseResultAddress.h" +#include "RigMainGrid.h" +#include "RigResultAccessorFactory.h" + +#include "RimEclipseCase.h" + +#include +#include + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimFaultReactivationDataAccessorTemperature::RimFaultReactivationDataAccessorTemperature( RimEclipseCase* eclipseCase ) + : m_eclipseCase( eclipseCase ) + , m_caseData( nullptr ) + , m_mainGrid( nullptr ) +{ + if ( m_eclipseCase ) + { + m_caseData = m_eclipseCase->eclipseCaseData(); + m_mainGrid = m_eclipseCase->mainGrid(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimFaultReactivationDataAccessorTemperature::~RimFaultReactivationDataAccessorTemperature() +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFaultReactivationDataAccessorTemperature::updateResultAccessor() +{ + if ( m_caseData ) + { + RigEclipseResultAddress resVarAddress( RiaDefines::ResultCatType::DYNAMIC_NATIVE, "TEMP" ); + m_eclipseCase->results( RiaDefines::PorosityModelType::MATRIX_MODEL )->ensureKnownResultLoaded( resVarAddress ); + m_resultAccessor = RigResultAccessorFactory::createFromResultAddress( m_caseData, + 0, + RiaDefines::PorosityModelType::MATRIX_MODEL, + m_timeStep, + resVarAddress ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimFaultReactivationDataAccessorTemperature::isMatching( RimFaultReactivation::Property property ) const +{ + return property == RimFaultReactivation::Property::Temperature; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RimFaultReactivationDataAccessorTemperature::valueAtPosition( const cvf::Vec3d& position, double topDepth, double bottomDepth ) const +{ + if ( ( m_mainGrid != nullptr ) && m_resultAccessor.notNull() ) + { + auto cellIdx = m_mainGrid->findReservoirCellIndexFromPoint( position ); + if ( cellIdx != cvf::UNDEFINED_SIZE_T ) + { + return m_resultAccessor->cellScalar( cellIdx ); + } + } + + return std::numeric_limits::infinity(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimFaultReactivationDataAccessorTemperature::hasValidDataAtPosition( const cvf::Vec3d& position ) const +{ + auto cellIdx = m_mainGrid->findReservoirCellIndexFromPoint( position ); + return ( cellIdx != cvf::UNDEFINED_SIZE_T ); +} diff --git a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationDataAccessorTemperature.h b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationDataAccessorTemperature.h new file mode 100644 index 0000000000..25c828b067 --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationDataAccessorTemperature.h @@ -0,0 +1,57 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 "cvfObject.h" +#include "cvfVector3.h" + +#include "RimFaultReactivationDataAccessor.h" +#include "RimFaultReactivationEnums.h" + +class RimEclipseCase; +class RigEclipseCaseData; +class RigMainGrid; +class RigResultAccessor; + +//================================================================================================== +/// +/// +//================================================================================================== +class RimFaultReactivationDataAccessorTemperature : public RimFaultReactivationDataAccessor +{ +public: + RimFaultReactivationDataAccessorTemperature( RimEclipseCase* eclipseCase ); + ~RimFaultReactivationDataAccessorTemperature(); + + bool isMatching( RimFaultReactivation::Property property ) const override; + + double valueAtPosition( const cvf::Vec3d& position, + double topDepth = std::numeric_limits::infinity(), + double bottomDepth = std::numeric_limits::infinity() ) const override; + + bool hasValidDataAtPosition( const cvf::Vec3d& position ) const override; + +private: + void updateResultAccessor() override; + + RimEclipseCase* m_eclipseCase; + RigEclipseCaseData* m_caseData; + const RigMainGrid* m_mainGrid; + cvf::ref m_resultAccessor; +}; diff --git a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationDataAccessorVoidRatio.cpp b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationDataAccessorVoidRatio.cpp new file mode 100644 index 0000000000..f0c7e91e5a --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationDataAccessorVoidRatio.cpp @@ -0,0 +1,115 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 "RimFaultReactivationDataAccessorVoidRatio.h" +#include "RimFaciesProperties.h" +#include "RimFaultReactivationEnums.h" + +#include "RiaDefines.h" +#include "RiaPorosityModel.h" + +#include "RigCaseCellResultsData.h" +#include "RigEclipseCaseData.h" +#include "RigEclipseResultAddress.h" +#include "RigMainGrid.h" +#include "RigResultAccessorFactory.h" + +#include "RimEclipseCase.h" + +#include + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimFaultReactivationDataAccessorVoidRatio::RimFaultReactivationDataAccessorVoidRatio( RimEclipseCase* eclipseCase, double missingValue ) + : m_eclipseCase( eclipseCase ) + , m_missingValue( missingValue ) + , m_caseData( nullptr ) + , m_mainGrid( nullptr ) +{ + if ( m_eclipseCase ) + { + m_caseData = m_eclipseCase->eclipseCaseData(); + m_mainGrid = m_eclipseCase->mainGrid(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimFaultReactivationDataAccessorVoidRatio::~RimFaultReactivationDataAccessorVoidRatio() +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFaultReactivationDataAccessorVoidRatio::updateResultAccessor() +{ + if ( m_caseData ) + { + RigEclipseResultAddress resVarAddress( RiaDefines::ResultCatType::STATIC_NATIVE, "PORO" ); + m_eclipseCase->results( RiaDefines::PorosityModelType::MATRIX_MODEL )->ensureKnownResultLoaded( resVarAddress ); + m_resultAccessor = RigResultAccessorFactory::createFromResultAddress( m_caseData, + 0, + RiaDefines::PorosityModelType::MATRIX_MODEL, + m_timeStep, + resVarAddress ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimFaultReactivationDataAccessorVoidRatio::isMatching( RimFaultReactivation::Property property ) const +{ + return property == RimFaultReactivation::Property::VoidRatio; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RimFaultReactivationDataAccessorVoidRatio::valueAtPosition( const cvf::Vec3d& position, double topDepth, double bottomDepth ) const +{ + if ( ( m_mainGrid != nullptr ) && m_resultAccessor.notNull() ) + { + auto cellIdx = m_mainGrid->findReservoirCellIndexFromPoint( position ); + if ( cellIdx != cvf::UNDEFINED_SIZE_T ) + { + double porosity = m_resultAccessor->cellScalar( cellIdx ); + if ( !std::isinf( porosity ) && porosity != 1.0 ) + { + return porosity / ( 1.0 - porosity ); + } + } + } + + return m_missingValue; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimFaultReactivationDataAccessorVoidRatio::hasValidDataAtPosition( const cvf::Vec3d& position ) const +{ + auto cellIdx = m_mainGrid->findReservoirCellIndexFromPoint( position ); + if ( cellIdx == cvf::UNDEFINED_SIZE_T ) return false; + + double value = m_resultAccessor->cellScalar( cellIdx ); + return !std::isinf( value ); +} diff --git a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationDataAccessorVoidRatio.h b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationDataAccessorVoidRatio.h new file mode 100644 index 0000000000..0b8eafca88 --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationDataAccessorVoidRatio.h @@ -0,0 +1,58 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 "cvfObject.h" +#include "cvfVector3.h" + +#include "RimFaultReactivationDataAccessor.h" +#include "RimFaultReactivationEnums.h" + +class RimEclipseCase; +class RigEclipseCaseData; +class RigMainGrid; +class RigResultAccessor; + +//================================================================================================== +/// +/// +//================================================================================================== +class RimFaultReactivationDataAccessorVoidRatio : public RimFaultReactivationDataAccessor +{ +public: + RimFaultReactivationDataAccessorVoidRatio( RimEclipseCase* eclipseCase, double missingValue ); + ~RimFaultReactivationDataAccessorVoidRatio(); + + bool isMatching( RimFaultReactivation::Property property ) const override; + + double valueAtPosition( const cvf::Vec3d& position, + double topDepth = std::numeric_limits::infinity(), + double bottomDepth = std::numeric_limits::infinity() ) const override; + + bool hasValidDataAtPosition( const cvf::Vec3d& position ) const override; + +private: + void updateResultAccessor() override; + + RimEclipseCase* m_eclipseCase; + RigEclipseCaseData* m_caseData; + const RigMainGrid* m_mainGrid; + double m_missingValue; + cvf::ref m_resultAccessor; +}; diff --git a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationEnums.h b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationEnums.h index f2d49a15bf..e9504aab6c 100644 --- a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationEnums.h +++ b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationEnums.h @@ -21,27 +21,18 @@ namespace RimFaultReactivation { -enum class ModelParts -{ - HiPart1, - MidPart1, - LowPart1, - HiPart2, - MidPart2, - LowPart2 -}; - enum class GridPart { - PART1, - PART2 + FW, // footwall + HW // hanging wall }; enum class BorderSurface { UpperSurface, FaultSurface, - LowerSurface + LowerSurface, + Seabed }; enum class Boundary @@ -58,4 +49,20 @@ enum class ElementSets IntraReservoir }; +enum class Property +{ + PorePressure, + VoidRatio, + Temperature, + Density, + YoungsModulus, + PoissonsRatio, + StressTop, + StressBottom, + DepthTop, + DepthBottom, + LateralStressComponentX, + LateralStressComponentY +}; + } // namespace RimFaultReactivation diff --git a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationModel.cpp b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationModel.cpp index 69c781ab37..0ded3a19f1 100644 --- a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationModel.cpp +++ b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationModel.cpp @@ -26,8 +26,11 @@ #include "RifJsonEncodeDecode.h" #include "RifParameterXmlReader.h" +#include "RigActiveCellInfo.h" #include "RigBasicPlane.h" +#include "RigEclipseCaseData.h" #include "RigFaultReactivationModel.h" +#include "RigFaultReactivationModelGenerator.h" #include "RigPolyLinesData.h" #include "WellPathCommands/PointTangentManipulator/RicPolyline3dEditor.h" @@ -44,6 +47,7 @@ #include "RimFaultInView.h" #include "RimFaultInViewCollection.h" #include "RimFaultReactivationDataAccess.h" +#include "RimFaultReactivationEnums.h" #include "RimFaultReactivationTools.h" #include "RimGeoMechCase.h" #include "RimParameterGroup.h" @@ -75,36 +79,36 @@ RimFaultReactivationModel::RimFaultReactivationModel() CAF_PDM_InitField( &m_userDescription, "UserDescription", QString( "Model" ), "Name" ); CAF_PDM_InitFieldNoDefault( &m_geomechCase, "GeoMechCase", "Global GeoMech Model" ); - CAF_PDM_InitFieldNoDefault( &m_baseDir, "BaseDirectory", "Working folder" ); + CAF_PDM_InitFieldNoDefault( &m_baseDir, "BaseDirectory", "Working Folder" ); CAF_PDM_InitField( &m_modelThickness, "ModelThickness", 100.0, "Model Cell Thickness" ); - CAF_PDM_InitField( &m_extentHorizontal, "HorizontalExtent", 1000.0, "Horizontal Extent" ); - CAF_PDM_InitField( &m_extentVerticalAbove, "VerticalExtentAbove", 200.0, "Vertical Extent Above Anchor" ); - m_extentVerticalAbove.uiCapability()->setUiEditorTypeName( caf::PdmUiDoubleSliderEditor::uiEditorTypeName() ); - m_extentVerticalAbove.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::LabelPosType::TOP ); - CAF_PDM_InitField( &m_extentVerticalBelow, "VerticalExtentBelow", 200.0, "Vertical Extent Below Anchor" ); - m_extentVerticalBelow.uiCapability()->setUiEditorTypeName( caf::PdmUiDoubleSliderEditor::uiEditorTypeName() ); - m_extentVerticalBelow.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::LabelPosType::TOP ); - - CAF_PDM_InitField( &m_modelExtentFromAnchor, "ModelExtentFromAnchor", 1000.0, "Horz. Extent from Anchor" ); - CAF_PDM_InitField( &m_modelMinZ, "ModelMinZ", 0.0, "Start Depth" ); + CAF_PDM_InitField( &m_modelExtentFromAnchor, "ModelExtentFromAnchor", 3000.0, "Horz. Extent from Anchor" ); + CAF_PDM_InitField( &m_modelMinZ, "ModelMinZ", 0.0, "Seabed Depth" ); CAF_PDM_InitField( &m_modelBelowSize, "ModelBelowSize", 500.0, "Depth Below Fault" ); - CAF_PDM_InitField( &m_showFaultPlane, "ShowFaultPlane", true, "Show Fault Plane" ); - CAF_PDM_InitField( &m_showModelPlane, "ShowModelPlane", false, "Show 2D Model" ); + CAF_PDM_InitFieldNoDefault( &m_startCellIndex, "StartCellIndex", "Start Cell Index" ); + CAF_PDM_InitFieldNoDefault( &m_startCellFace, "StartCellFace", "Start Cell Face" ); + m_startCellIndex = 0; + m_startCellFace = cvf::StructGridInterface::FaceType::NO_FACE; + + CAF_PDM_InitField( &m_faultExtendUpwards, "FaultExtendUpwards", 0.0, "Above Reservoir" ); + m_faultExtendUpwards.uiCapability()->setUiEditorTypeName( caf::PdmUiDoubleSliderEditor::uiEditorTypeName() ); + CAF_PDM_InitField( &m_faultExtendDownwards, "FaultExtendDownwards", 0.0, "Below Reservoir" ); + m_faultExtendDownwards.uiCapability()->setUiEditorTypeName( caf::PdmUiDoubleSliderEditor::uiEditorTypeName() ); + + CAF_PDM_InitField( &m_showModelPlane, "ShowModelPlane", true, "Show 2D Model" ); CAF_PDM_InitFieldNoDefault( &m_fault, "Fault", "Fault" ); m_fault.uiCapability()->setUiReadOnly( true ); - CAF_PDM_InitField( &m_faultPlaneColor, "FaultPlaneColor", cvf::Color3f( cvf::Color3f::GRAY ), "Plane Color" ); CAF_PDM_InitField( &m_modelPart1Color, "ModelPart1Color", cvf::Color3f( cvf::Color3f::GREEN ), "Part 1 Color" ); CAF_PDM_InitField( &m_modelPart2Color, "ModelPart2Color", cvf::Color3f( cvf::Color3f::BLUE ), "Part 2 Color" ); - CAF_PDM_InitField( &m_numberOfCellsHorzPart1, "NumberOfCellsHorzPart1", 20, "Horizontal Number of Cells, Part 1" ); - CAF_PDM_InitField( &m_numberOfCellsHorzPart2, "NumberOfCellsHorzPart2", 20, "Horizontal Number of Cells, Part 2" ); - CAF_PDM_InitField( &m_numberOfCellsVertUp, "NumberOfCellsVertUp", 20, "Vertical Number of Cells, Upper Part" ); - CAF_PDM_InitField( &m_numberOfCellsVertMid, "NumberOfCellsVertMid", 20, "Vertical Number of Cells, Middle Part" ); - CAF_PDM_InitField( &m_numberOfCellsVertLow, "NumberOfCellsVertLow", 20, "Vertical Number of Cells, Lower Part" ); + CAF_PDM_InitField( &m_maxReservoirCellHeight, "MaxReservoirCellHeight", 20.0, "Max. Reservoir Cell Height" ); + CAF_PDM_InitField( &m_cellHeightGrowFactor, "CellHeightGrowFactor", 1.05, "Cell Height Grow Factor" ); + + CAF_PDM_InitField( &m_minReservoirCellWidth, "MinReservoirCellWidth", 20.0, "Reservoir Cell Width" ); + CAF_PDM_InitField( &m_cellWidthGrowFactor, "CellWidthGrowFactor", 1.05, "Cell Width Grow Factor" ); CAF_PDM_InitField( &m_useLocalCoordinates, "UseLocalCoordinates", false, "Export Using Local Coordinates" ); @@ -114,6 +118,15 @@ RimFaultReactivationModel::RimFaultReactivationModel() m_selectedTimeSteps.uiCapability()->setUiEditorTypeName( caf::PdmUiTreeSelectionEditor::uiEditorTypeName() ); m_selectedTimeSteps.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::TOP ); + CAF_PDM_InitField( &m_useGridPorePressure, "UseGridPorePressure", true, "Output Grid Pore Pressure" ); + CAF_PDM_InitField( &m_useGridVoidRatio, "UseGridVoidRatio", true, "Output Grid Void Ratio" ); + CAF_PDM_InitField( &m_useGridTemperature, "UseGridTemperature", true, "Output Grid Temperature" ); + CAF_PDM_InitField( &m_useGridDensity, "UseGridDensity", false, "Output Grid Density" ); + CAF_PDM_InitField( &m_useGridElasticProperties, "UseGridElasticProperties", false, "Output Grid Elastic Properties" ); + CAF_PDM_InitField( &m_useGridStress, "UseGridStress", false, "Output Grid Stress" ); + + CAF_PDM_InitField( &m_waterDensity, "WaterDensity", 1030.0, "Water Density [kg/m3]" ); + CAF_PDM_InitFieldNoDefault( &m_targets, "Targets", "Targets" ); m_targets.uiCapability()->setUiEditorTypeName( caf::PdmUiTableViewEditor::uiEditorTypeName() ); m_targets.uiCapability()->setUiTreeChildrenHidden( true ); @@ -127,8 +140,7 @@ RimFaultReactivationModel::RimFaultReactivationModel() setDeletable( true ); - m_faultPlane = new RigBasicPlane(); - m_modelPlane = new RigFaultReactivationModel(); + m_2Dmodel = new RigFaultReactivationModel(); } //-------------------------------------------------------------------------------------------------- @@ -138,14 +150,6 @@ RimFaultReactivationModel::~RimFaultReactivationModel() { } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimFaultReactivationModel::initAfterRead() -{ - updateVisualization(); -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -213,9 +217,11 @@ std::pair RimFaultReactivationModel::validateBeforeRun() cons //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimFaultReactivationModel::setFault( RimFaultInView* fault ) +void RimFaultReactivationModel::setFaultInformation( RimFaultInView* fault, size_t cellIndex, cvf::StructGridInterface::FaceType face ) { - m_fault = fault; + m_fault = fault; + m_startCellIndex = cellIndex; + m_startCellFace = face; } //-------------------------------------------------------------------------------------------------- @@ -293,46 +299,31 @@ void RimFaultReactivationModel::updateVisualization() auto view = firstAncestorOrThisOfType(); if ( !view ) return; - auto normal = m_targets[1]->targetPointXYZ() - m_targets[0]->targetPointXYZ(); - normal.z() = normal.z() * view->scaleZ() * view->scaleZ(); - normal.normalize(); - - m_faultPlane->setPlane( m_targets[0]->targetPointXYZ(), normal ); - m_faultPlane->setMaxExtentFromAnchor( m_extentHorizontal, m_extentVerticalAbove, m_extentVerticalBelow ); - m_faultPlane->setColor( m_faultPlaneColor ); - m_faultPlane->updateRect(); + if ( m_startCellIndex() == 0 ) return; + if ( m_startCellFace() == cvf::StructGridInterface::FaceType::NO_FACE ) return; + if ( m_targets.size() < 2 ) return; - double maxZ = m_faultPlane->maxDepth(); - auto [topInt, bottomInt] = m_faultPlane->intersectTopBottomLine(); + auto normal = m_targets[1]->targetPointXYZ() - m_targets[0]->targetPointXYZ(); + normal.z() = 0.0; + if ( !normal.normalize() ) return; - cvf::Vec3d zdir( 0, 0, 1 ); - auto modelNormal = normal ^ zdir; + auto modelNormal = normal ^ cvf::Vec3d::Z_AXIS; modelNormal.normalize(); - m_modelPlane->setPlane( m_targets[0]->targetPointXYZ(), modelNormal ); - m_modelPlane->setFaultPlaneIntersect( topInt, bottomInt ); - m_modelPlane->setMaxExtentFromAnchor( m_modelExtentFromAnchor, m_modelMinZ, maxZ + m_modelBelowSize ); - m_modelPlane->setPartColors( m_modelPart1Color, m_modelPart2Color ); - m_modelPlane->setCellCounts( m_numberOfCellsHorzPart1, - m_numberOfCellsHorzPart2, - m_numberOfCellsVertUp, - m_numberOfCellsVertMid, - m_numberOfCellsVertLow ); - m_modelPlane->setThickness( m_modelThickness ); - - // set up transform to local coordinate system - { - auto [xVec, yVec] = localCoordSysNormalsXY(); - cvf::Mat4d transform = cvf::Mat4d::fromCoordSystemAxes( &xVec, &yVec, &cvf::Vec3d::Z_AXIS ); - cvf::Vec3d center = m_targets[0]->targetPointXYZ() * -1.0; - center.z() = 0.0; - center.transformPoint( transform ); - transform.setTranslation( center ); - m_modelPlane->setLocalCoordTransformation( transform ); - m_modelPlane->setUseLocalCoordinates( m_useLocalCoordinates ); - } - - m_modelPlane->updateGeometry(); + auto generator = std::make_shared( m_targets[0]->targetPointXYZ(), modelNormal ); + generator->setFault( m_fault()->faultGeometry() ); + generator->setGrid( eclipseCase()->mainGrid() ); + generator->setActiveCellInfo( eclipseCase()->eclipseCaseData()->activeCellInfo( RiaDefines::PorosityModelType::MATRIX_MODEL ) ); + generator->setModelSize( m_modelMinZ, m_modelBelowSize, m_modelExtentFromAnchor ); + generator->setFaultBufferDepth( m_faultExtendUpwards, m_faultExtendDownwards ); + generator->setModelThickness( m_modelThickness ); + generator->setModelGriddingOptions( m_maxReservoirCellHeight, m_cellHeightGrowFactor, m_minReservoirCellWidth, m_cellWidthGrowFactor ); + generator->setupLocalCoordinateTransform(); + generator->setUseLocalCoordinates( m_useLocalCoordinates ); + + m_2Dmodel->setPartColors( m_modelPart1Color, m_modelPart2Color ); + m_2Dmodel->setGenerator( generator ); + m_2Dmodel->updateGeometry( m_startCellIndex, (cvf::StructGridInterface::FaceType)m_startCellFace() ); view->scheduleCreateDisplayModelAndRedraw(); } @@ -400,28 +391,12 @@ RivFaultReactivationModelPartMgr* RimFaultReactivationModel::partMgr() return m_partMgr.p(); } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -cvf::ref RimFaultReactivationModel::faultPlane() const -{ - return m_faultPlane; -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- cvf::ref RimFaultReactivationModel::model() const { - return m_modelPlane; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool RimFaultReactivationModel::showFaultPlane() const -{ - return m_showFaultPlane; + return m_2Dmodel; } //-------------------------------------------------------------------------------------------------- @@ -432,24 +407,6 @@ 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; - - xNormal.z() = 0.0; - yNormal.z() = 0.0; - xNormal.normalize(); - yNormal.normalize(); - - yNormal = xNormal ^ cvf::Vec3d::Z_AXIS; - - return std::make_pair( xNormal, yNormal ); -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -461,14 +418,6 @@ void RimFaultReactivationModel::defineUiOrdering( QString uiConfigName, caf::Pdm genGrp->add( &m_baseDir ); genGrp->add( &m_geomechCase ); - auto faultGrp = uiOrdering.addNewGroup( "Fault Plane" ); - - faultGrp->add( &m_showFaultPlane ); - faultGrp->add( &m_faultPlaneColor ); - faultGrp->add( &m_extentHorizontal ); - faultGrp->add( &m_extentVerticalAbove ); - faultGrp->add( &m_extentVerticalBelow ); - auto modelGrp = uiOrdering.addNewGroup( "2D Model" ); modelGrp->add( &m_showModelPlane ); @@ -477,23 +426,47 @@ void RimFaultReactivationModel::defineUiOrdering( QString uiConfigName, caf::Pdm sizeModelGrp->add( &m_modelMinZ ); sizeModelGrp->add( &m_modelBelowSize ); - auto gridModelGrp = modelGrp->addNewGroup( "Grid" ); + if ( m_geomechCase() != nullptr ) + { + m_modelMinZ.setValue( std::abs( m_geomechCase->allCellsBoundingBox().max().z() ) ); + m_modelMinZ.uiCapability()->setUiReadOnly( true ); + } + else + { + m_modelMinZ.uiCapability()->setUiReadOnly( false ); + } + + auto faultGrp = modelGrp->addNewGroup( "Fault Extension" ); + faultGrp->add( &m_faultExtendUpwards ); + faultGrp->add( &m_faultExtendDownwards ); + + auto gridModelGrp = modelGrp->addNewGroup( "Grid Definition" ); + gridModelGrp->add( &m_maxReservoirCellHeight ); + gridModelGrp->add( &m_cellHeightGrowFactor ); + + gridModelGrp->add( &m_minReservoirCellWidth ); + gridModelGrp->add( &m_cellWidthGrowFactor ); gridModelGrp->add( &m_modelThickness ); - gridModelGrp->add( &m_numberOfCellsHorzPart1 ); - gridModelGrp->add( &m_numberOfCellsHorzPart2 ); - gridModelGrp->add( &m_numberOfCellsVertUp ); - gridModelGrp->add( &m_numberOfCellsVertMid ); - gridModelGrp->add( &m_numberOfCellsVertLow ); - gridModelGrp->add( &m_useLocalCoordinates ); + + auto appModelGrp = modelGrp->addNewGroup( "Appearance" ); + appModelGrp->setCollapsedByDefault(); + appModelGrp->add( &m_modelPart1Color ); + appModelGrp->add( &m_modelPart2Color ); auto timeStepGrp = uiOrdering.addNewGroup( "Time Steps" ); timeStepGrp->add( &m_timeStepFilter ); timeStepGrp->add( &m_selectedTimeSteps ); - auto appModelGrp = modelGrp->addNewGroup( "Appearance" ); - appModelGrp->add( &m_modelPart1Color ); - appModelGrp->add( &m_modelPart2Color ); + auto propertiesGrp = uiOrdering.addNewGroup( "Export" ); + propertiesGrp->add( &m_useLocalCoordinates ); + propertiesGrp->add( &m_useGridPorePressure ); + propertiesGrp->add( &m_useGridVoidRatio ); + propertiesGrp->add( &m_useGridTemperature ); + propertiesGrp->add( &m_useGridDensity ); + propertiesGrp->add( &m_useGridElasticProperties ); + propertiesGrp->add( &m_useGridStress ); + propertiesGrp->add( &m_waterDensity ); auto trgGroup = uiOrdering.addNewGroup( "Debug" ); trgGroup->setCollapsedByDefault(); @@ -507,12 +480,25 @@ void RimFaultReactivationModel::defineUiOrdering( QString uiConfigName, caf::Pdm //-------------------------------------------------------------------------------------------------- void RimFaultReactivationModel::fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) { - if ( changedField == &m_userDescription ) + if ( ( changedField == &m_useGridPorePressure ) || ( changedField == &m_useGridVoidRatio ) || ( changedField == &m_useGridTemperature ) || + ( changedField == &m_useGridDensity ) || ( changedField == &m_useGridElasticProperties ) ) + { + return; // do nothing + } + else if ( changedField == &m_userDescription ) { updateConnectedEditors(); } else { + if ( changedField == &m_geomechCase ) + { + if ( m_geomechCase() != nullptr ) + { + m_modelMinZ.setValue( std::abs( m_geomechCase()->allCellsBoundingBox().max().z() ) ); + } + } + updateVisualization(); } } @@ -530,7 +516,7 @@ void RimFaultReactivationModel::defineEditorAttribute( const caf::PdmFieldHandle tvAttribute->resizePolicy = caf::PdmUiTableViewEditorAttribute::RESIZE_TO_FIT_CONTENT; } } - else if ( ( field == &m_extentVerticalAbove ) || ( field == &m_extentVerticalBelow ) ) + else if ( ( field == &m_faultExtendUpwards ) || ( field == &m_faultExtendDownwards ) ) { auto* attr = dynamic_cast( attribute ); @@ -679,16 +665,18 @@ QString RimFaultReactivationModel::baseFilename() const //-------------------------------------------------------------------------------------------------- bool RimFaultReactivationModel::exportModelSettings() { - if ( m_faultPlane.isNull() ) return false; + if ( m_2Dmodel.isNull() ) return false; + if ( !m_2Dmodel->isValid() ) return false; QMap settings; - auto [topPosition, bottomPosition] = m_faultPlane->intersectTopBottomLine(); - auto faultNormal = m_faultPlane->normal(); + auto [topPosition, bottomPosition] = m_2Dmodel->faultTopBottom(); + auto faultNormal = m_2Dmodel->faultNormal(); - // make sure we move horizontally + // make sure we move horizontally, and along the 2D model faultNormal.z() = 0.0; faultNormal.normalize(); + faultNormal = faultNormal ^ cvf::Vec3d::Z_AXIS; RimFaultReactivationTools::addSettingsToMap( settings, faultNormal, topPosition, bottomPosition ); @@ -701,7 +689,7 @@ bool RimFaultReactivationModel::exportModelSettings() //-------------------------------------------------------------------------------------------------- bool RimFaultReactivationModel::extractAndExportModelData() { - model()->clearModelData(); + if ( m_dataAccess ) m_dataAccess->clearModelData(); if ( !exportModelSettings() ) return false; @@ -718,24 +706,9 @@ bool RimFaultReactivationModel::extractAndExportModelData() selectedTimeStepIndexes.push_back( idx - m_availableTimeSteps.begin() ); } - auto grid = eCase->mainGrid(); - - // generate cell index mappings for cells that ends up at the wrong side of the fault - model()->generateCellIndexMapping( grid ); - - // generate element sets for the various data parts of the model - { - RimFaultReactivationDataAccess dataAccess( eCase, 0 ); - model()->generateElementSets( &dataAccess, grid ); - } - // extract data for each timestep - size_t outputTimeStepIndex = 0; - for ( auto timeStepIdx : selectedTimeStepIndexes ) - { - RimFaultReactivationDataAccess dataAccess( eCase, timeStepIdx ); - model()->extractModelData( &dataAccess, outputTimeStepIndex++ ); - } + m_dataAccess = std::make_shared( eCase, geoMechCase(), selectedTimeStepIndexes ); + m_dataAccess->extractModelData( *model() ); return true; } @@ -766,3 +739,75 @@ std::array RimFaultReactivationModel::materialParameters( ElementSets return retVal; } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::shared_ptr RimFaultReactivationModel::dataAccess() const +{ + return m_dataAccess; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimFaultReactivationModel::useGridVoidRatio() const +{ + return m_useGridVoidRatio(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimFaultReactivationModel::useGridPorePressure() const +{ + return m_useGridPorePressure(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimFaultReactivationModel::useGridTemperature() const +{ + return m_useGridTemperature(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimFaultReactivationModel::useGridDensity() const +{ + return m_useGridDensity(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimFaultReactivationModel::useGridElasticProperties() const +{ + return m_useGridElasticProperties(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimFaultReactivationModel::useGridStress() const +{ + return m_useGridStress(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RimFaultReactivationModel::seaBedDepth() const +{ + return m_modelMinZ; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RimFaultReactivationModel::waterDensity() const +{ + return m_waterDensity; +} diff --git a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationModel.h b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationModel.h index 114c37de55..e3c741b5eb 100644 --- a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationModel.h +++ b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationModel.h @@ -18,6 +18,7 @@ #pragma once #include "RimCheckableNamedObject.h" +#include "RimFaultReactivationDataAccess.h" #include "RimFaultReactivationEnums.h" #include "RimPolylinePickerInterface.h" #include "RimPolylinesDataInterface.h" @@ -27,12 +28,12 @@ #include "cafPdmChildArrayField.h" #include "cafPdmChildField.h" #include "cafPdmField.h" +#include "cafPdmFieldCvfColor.h" #include "cafPdmObject.h" #include "cafPdmPtrField.h" -// Include to make Pdm work for cvf::Color -#include "cafPdmFieldCvfColor.h" #include "cvfColor3.h" +#include "cvfStructGrid.h" #include "cvfVector3.h" #include @@ -52,6 +53,7 @@ class RimTimeStepFilter; class RivFaultReactivationModelPartMgr; class RigBasicPlane; class RigFaultReactivationModel; +class RimFaultReactivationDataAccess; namespace cvf { @@ -77,7 +79,7 @@ class RimFaultReactivationModel : public RimCheckableNamedObject, public RimPoly std::pair validateBeforeRun() const; - void setFault( RimFaultInView* fault ); + void setFaultInformation( RimFaultInView* fault, size_t cellIndex, cvf::StructGridInterface::FaceType face ); RimFaultInView* fault() const; void setTargets( cvf::Vec3d target1, cvf::Vec3d target2 ); @@ -89,6 +91,7 @@ class RimFaultReactivationModel : public RimCheckableNamedObject, public RimPoly void deleteTarget( RimPolylineTarget* targetToDelete ) override; void updateEditorsAndVisualization() override; void updateVisualization() override; + std::vector activeTargets() const override; bool pickingEnabled() const override; caf::PickEventHandler* pickEventHandler() const override; @@ -96,14 +99,9 @@ class RimFaultReactivationModel : public RimCheckableNamedObject, public RimPoly // polyline data interface cvf::ref polyLinesData() const override; - cvf::ref faultPlane() const; - bool showFaultPlane() const; - cvf::ref model() const; bool showModel() const; - std::pair localCoordSysNormalsXY() const; - bool extractAndExportModelData(); QString baseDir() const; @@ -121,6 +119,18 @@ class RimFaultReactivationModel : public RimCheckableNamedObject, public RimPoly void updateTimeSteps(); + std::shared_ptr dataAccess() const; + + bool useGridVoidRatio() const; + bool useGridPorePressure() const; + bool useGridTemperature() const; + bool useGridDensity() const; + bool useGridElasticProperties() const; + bool useGridStress() const; + + double seaBedDepth() const; + double waterDensity() const; + protected: caf::PdmFieldHandle* userDescriptionField() override; QList calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions ) override; @@ -132,8 +142,6 @@ class RimFaultReactivationModel : public RimCheckableNamedObject, public RimPoly RimEclipseCase* eclipseCase(); RimGeoMechCase* geoMechCase(); - void initAfterRead() override; - QString baseFilename() const; bool exportModelSettings(); @@ -150,28 +158,38 @@ class RimFaultReactivationModel : public RimCheckableNamedObject, public RimPoly caf::PdmPtrField m_fault; caf::PdmPtrField m_geomechCase; caf::PdmChildArrayField m_targets; - caf::PdmField m_faultPlaneColor; caf::PdmField m_modelPart1Color; caf::PdmField m_modelPart2Color; - caf::PdmField m_showFaultPlane; caf::PdmField m_showModelPlane; - caf::PdmField m_extentVerticalAbove; - caf::PdmField m_extentVerticalBelow; - caf::PdmField m_extentHorizontal; caf::PdmField m_modelExtentFromAnchor; caf::PdmField m_modelMinZ; caf::PdmField m_modelBelowSize; - caf::PdmField m_numberOfCellsHorzPart1; - caf::PdmField m_numberOfCellsHorzPart2; - caf::PdmField m_numberOfCellsVertUp; - caf::PdmField m_numberOfCellsVertMid; - caf::PdmField m_numberOfCellsVertLow; - caf::PdmField m_useLocalCoordinates; - cvf::ref m_faultPlane; - cvf::ref m_modelPlane; + caf::PdmField m_faultExtendUpwards; + caf::PdmField m_faultExtendDownwards; + + caf::PdmField m_maxReservoirCellHeight; + caf::PdmField m_cellHeightGrowFactor; + caf::PdmField m_minReservoirCellWidth; + caf::PdmField m_cellWidthGrowFactor; + + caf::PdmField m_useLocalCoordinates; + + caf::PdmField m_useGridPorePressure; + caf::PdmField m_useGridVoidRatio; + caf::PdmField m_useGridTemperature; + caf::PdmField m_useGridDensity; + caf::PdmField m_useGridElasticProperties; + caf::PdmField m_useGridStress; + + caf::PdmField m_waterDensity; + + caf::PdmField m_startCellIndex; + caf::PdmField m_startCellFace; + + cvf::ref m_2Dmodel; caf::PdmField m_timeStepFilter; caf::PdmField> m_selectedTimeSteps; @@ -179,4 +197,6 @@ class RimFaultReactivationModel : public RimCheckableNamedObject, public RimPoly caf::PdmChildArrayField m_materialParameters; std::vector m_availableTimeSteps; + + std::shared_ptr m_dataAccess; }; diff --git a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationModelCollection.cpp b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationModelCollection.cpp index acf2f78012..2659903554 100644 --- a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationModelCollection.cpp +++ b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationModelCollection.cpp @@ -61,14 +61,16 @@ RimFaultReactivationModelCollection::~RimFaultReactivationModelCollection() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RimFaultReactivationModel* RimFaultReactivationModelCollection::addNewModel( RimFaultInView* fault, - cvf::Vec3d target1, - cvf::Vec3d target2, - QString baseDir, - QString& outErrMsg ) +RimFaultReactivationModel* RimFaultReactivationModelCollection::addNewModel( RimFaultInView* fault, + size_t cellIndex, + cvf::StructGridInterface::FaceType face, + cvf::Vec3d target1, + cvf::Vec3d target2, + QString baseDir, + QString& outErrMsg ) { auto newModel = new RimFaultReactivationModel(); - newModel->setFault( fault ); + newModel->setFaultInformation( fault, cellIndex, face ); newModel->setBaseDir( baseDir ); newModel->setUserDescription( fault->name() ); newModel->setTargets( target1, target2 ); @@ -210,3 +212,14 @@ void RimFaultReactivationModelCollection::syncTimeSteps() frm->updateTimeSteps(); } } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFaultReactivationModelCollection::loadDataAndUpdate() +{ + for ( auto& frm : m_models ) + { + frm->updateVisualization(); + } +} diff --git a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationModelCollection.h b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationModelCollection.h index 5df7ae7bb8..9f8708a94b 100644 --- a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationModelCollection.h +++ b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationModelCollection.h @@ -22,6 +22,7 @@ #include "cafPdmChildArrayField.h" #include "cafPdmField.h" +#include "cvfStructGrid.h" #include "cvfVector3.h" #include @@ -50,7 +51,13 @@ class RimFaultReactivationModelCollection : public RimCheckableNamedObject RimFaultReactivationModelCollection(); ~RimFaultReactivationModelCollection() override; - RimFaultReactivationModel* addNewModel( RimFaultInView* fault, cvf::Vec3d target1, cvf::Vec3d target2, QString baseDir, QString& errMsg ); + RimFaultReactivationModel* addNewModel( RimFaultInView* fault, + size_t cellIndex, + cvf::StructGridInterface::FaceType face, + cvf::Vec3d target1, + cvf::Vec3d target2, + QString baseDir, + QString& errMsg ); bool empty(); int size(); @@ -67,6 +74,8 @@ class RimFaultReactivationModelCollection : public RimCheckableNamedObject void syncTimeSteps(); + void loadDataAndUpdate(); + protected: caf::PdmFieldHandle* userDescriptionField() override; diff --git a/ApplicationLibCode/ProjectDataModel/Flow/RimWellAllocationOverTimePlot.cpp b/ApplicationLibCode/ProjectDataModel/Flow/RimWellAllocationOverTimePlot.cpp index da85f01253..39d18ae5d4 100644 --- a/ApplicationLibCode/ProjectDataModel/Flow/RimWellAllocationOverTimePlot.cpp +++ b/ApplicationLibCode/ProjectDataModel/Flow/RimWellAllocationOverTimePlot.cpp @@ -270,7 +270,7 @@ RiuPlotWidget* RimWellAllocationOverTimePlot::doCreatePlotViewWidget( QWidget* m // Remove event filter to disable unwanted highlighting on left click in plot. plotWidget->removeEventFilter(); - new RiuContextMenuLauncher( m_plotWidget, { "RicShowPlotDataFeature" } ); + new RiuContextMenuLauncher( plotWidget, { "RicShowPlotDataFeature" } ); m_plotWidget = plotWidget; RiuQwtPlotTools::enableDateBasedBottomXAxis( m_plotWidget->qwtPlot(), diff --git a/ApplicationLibCode/ProjectDataModel/Flow/RimWellConnectivityTable.cpp b/ApplicationLibCode/ProjectDataModel/Flow/RimWellConnectivityTable.cpp index 3cb1504f7b..b5041f26c0 100644 --- a/ApplicationLibCode/ProjectDataModel/Flow/RimWellConnectivityTable.cpp +++ b/ApplicationLibCode/ProjectDataModel/Flow/RimWellConnectivityTable.cpp @@ -492,7 +492,7 @@ void RimWellConnectivityTable::defineUiOrdering( QString uiConfigName, caf::PdmU caf::PdmUiGroup* producerGroup = selectionGroup->addNewGroup( "Producers" ); producerGroup->add( &m_selectedProducerTracersUiField ); producerGroup->add( &m_syncSelectedInjectorsFromProducerSelection ); - caf::PdmUiGroup* injectorGroup = selectionGroup->addNewGroup( "Injectors", false ); + caf::PdmUiGroup* injectorGroup = selectionGroup->addNewGroup( "Injectors", { .newRow = false } ); injectorGroup->add( &m_selectedInjectorTracersUiField ); injectorGroup->add( &m_syncSelectedProducersFromInjectorSelection ); diff --git a/ApplicationLibCode/ProjectDataModel/Flow/RimWellRftPlot.cpp b/ApplicationLibCode/ProjectDataModel/Flow/RimWellRftPlot.cpp index c62c830fb3..86882e2e1f 100644 --- a/ApplicationLibCode/ProjectDataModel/Flow/RimWellRftPlot.cpp +++ b/ApplicationLibCode/ProjectDataModel/Flow/RimWellRftPlot.cpp @@ -242,7 +242,7 @@ QString RimWellRftPlot::associatedSimWellName() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimWellRftPlot::applyInitialSelections() +void RimWellRftPlot::applyInitialSelections( std::variant dataSource ) { std::map wellSources = findWellSources(); if ( m_wellPathNameOrSimWellName() == "None" && !wellSources.empty() ) @@ -250,22 +250,49 @@ void RimWellRftPlot::applyInitialSelections() m_wellPathNameOrSimWellName = wellSources.begin()->first; } - std::vector sourcesToSelect; - const QString simWellName = associatedSimWellName(); + RimSummaryCaseCollection* ensemble = nullptr; + RimSummaryCase* summaryCase = nullptr; - for ( RimEclipseResultCase* const rftCase : RimWellPlotTools::rftCasesForWell( simWellName ) ) + if ( auto summaryCollection = std::get_if( &dataSource ) ) { - sourcesToSelect.push_back( RifDataSourceForRftPlt( RifDataSourceForRftPlt::SourceType::RFT_SIM_WELL_DATA, rftCase ) ); + ensemble = *summaryCollection; } - - for ( RimEclipseResultCase* const gridCase : RimWellPlotTools::gridCasesForWell( simWellName ) ) + else if ( auto sumCase = std::get_if( &dataSource ) ) { - sourcesToSelect.push_back( RifDataSourceForRftPlt( RifDataSourceForRftPlt::SourceType::GRID_MODEL_CELL_DATA, gridCase ) ); + summaryCase = *sumCase; } - for ( RimSummaryCaseCollection* const ensemble : RimWellPlotTools::rftEnsemblesForWell( simWellName ) ) + bool summaryOrEnsembleSelected = ( summaryCase || ensemble ); + + std::vector sourcesToSelect; + const QString simWellName = associatedSimWellName(); + + if ( !summaryOrEnsembleSelected ) { - sourcesToSelect.push_back( RifDataSourceForRftPlt( ensemble ) ); + for ( RimEclipseResultCase* const rftCase : RimWellPlotTools::rftCasesForWell( simWellName ) ) + { + sourcesToSelect.push_back( RifDataSourceForRftPlt( RifDataSourceForRftPlt::SourceType::RFT_SIM_WELL_DATA, rftCase ) ); + } + + for ( RimEclipseResultCase* const gridCase : RimWellPlotTools::gridCasesForWell( simWellName ) ) + { + sourcesToSelect.push_back( RifDataSourceForRftPlt( RifDataSourceForRftPlt::SourceType::GRID_MODEL_CELL_DATA, gridCase ) ); + } + + for ( RimSummaryCaseCollection* const ensemble : RimWellPlotTools::rftEnsemblesForWell( simWellName ) ) + { + sourcesToSelect.push_back( RifDataSourceForRftPlt( ensemble ) ); + } + + for ( auto singleCase : RiaSummaryTools::singleTopLevelSummaryCases() ) + { + sourcesToSelect.push_back( RifDataSourceForRftPlt( singleCase, nullptr, nullptr ) ); + } + } + else + { + if ( summaryCase ) sourcesToSelect.push_back( RifDataSourceForRftPlt( summaryCase, nullptr, nullptr ) ); + if ( ensemble ) sourcesToSelect.push_back( RifDataSourceForRftPlt( ensemble ) ); } std::vector wellLogFiles = RimWellPlotTools::wellLogFilesContainingPressure( m_wellPathNameOrSimWellName ); @@ -1514,6 +1541,23 @@ RimWellRftEnsembleCurveSet* RimWellRftPlot::findEnsembleCurveSet( RimSummaryCase return nullptr; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::variant RimWellRftPlot::dataSource() const +{ + // Return the first selected ensemble, if any + // If no ensemble is selected, return the first selected summary case, if any + + for ( const auto& source : m_selectedSources() ) + { + if ( source.ensemble() ) return source.ensemble(); + if ( source.summaryCase() ) return source.summaryCase(); + } + + return {}; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/Flow/RimWellRftPlot.h b/ApplicationLibCode/ProjectDataModel/Flow/RimWellRftPlot.h index 168ff2f8d6..6cbb040255 100644 --- a/ApplicationLibCode/ProjectDataModel/Flow/RimWellRftPlot.h +++ b/ApplicationLibCode/ProjectDataModel/Flow/RimWellRftPlot.h @@ -38,6 +38,7 @@ #include #include #include +#include class RimEclipseCase; class RimEclipseResultCase; @@ -83,7 +84,8 @@ class RimWellRftPlot : public RimWellLogPlot int branchIndex() const; - void applyInitialSelections(); + std::variant dataSource() const; + void applyInitialSelections( std::variant dataSource ); static const char* plotNameFormatString(); diff --git a/ApplicationLibCode/ProjectDataModel/GeoMech/RimGeoMechCase.cpp b/ApplicationLibCode/ProjectDataModel/GeoMech/RimGeoMechCase.cpp index afa40fe602..e1c5879a14 100644 --- a/ApplicationLibCode/ProjectDataModel/GeoMech/RimGeoMechCase.cpp +++ b/ApplicationLibCode/ProjectDataModel/GeoMech/RimGeoMechCase.cpp @@ -35,6 +35,7 @@ #include "RigGeoMechCaseData.h" #include "Rim2dIntersectionViewCollection.h" +#include "RimCellFilterCollection.h" #include "RimFormationNames.h" #include "RimGeoMechCellColors.h" #include "RimGeoMechContourMapView.h" @@ -216,6 +217,7 @@ void RimGeoMechCase::reloadDataAndUpdate() { v->resetVizLogic(); v->loadDataAndUpdate(); + v->cellFilterCollection()->notifyGridReload(); v->setCurrentTimeStep( v->currentTimeStep() ); } diff --git a/ApplicationLibCode/ProjectDataModel/GridCrossPlots/RimGridCrossPlotDataSet.cpp b/ApplicationLibCode/ProjectDataModel/GridCrossPlots/RimGridCrossPlotDataSet.cpp index 4c8b199a79..8d52f7d19a 100644 --- a/ApplicationLibCode/ProjectDataModel/GridCrossPlots/RimGridCrossPlotDataSet.cpp +++ b/ApplicationLibCode/ProjectDataModel/GridCrossPlots/RimGridCrossPlotDataSet.cpp @@ -1006,7 +1006,7 @@ void RimGridCrossPlotDataSet::defineUiOrdering( QString uiConfigName, caf::PdmUi caf::PdmUiGroup* xAxisGroup = invisibleFullWidthGroup->addNewGroup( "X-Axis Property" ); m_xAxisProperty->uiOrdering( uiConfigName, *xAxisGroup ); - caf::PdmUiGroup* yAxisGroup = invisibleFullWidthGroup->addNewGroup( "Y-Axis Property", false ); + caf::PdmUiGroup* yAxisGroup = invisibleFullWidthGroup->addNewGroup( "Y-Axis Property", { .newRow = false } ); m_yAxisProperty->uiOrdering( uiConfigName, *yAxisGroup ); } diff --git a/ApplicationLibCode/ProjectDataModel/Rim2dIntersectionView.cpp b/ApplicationLibCode/ProjectDataModel/Rim2dIntersectionView.cpp index c52a4852b4..63e67d833c 100644 --- a/ApplicationLibCode/ProjectDataModel/Rim2dIntersectionView.cpp +++ b/ApplicationLibCode/ProjectDataModel/Rim2dIntersectionView.cpp @@ -598,31 +598,29 @@ void Rim2dIntersectionView::onUpdateDisplayModelForCurrentTimeStep() cvf::Scene* frameScene = nativeOrOverrideViewer()->frame( m_currentTimeStep, isUsingOverrideViewer() ); if ( frameScene ) { + cvf::String name = "SimWellPipeMod"; + Rim3dView::removeModelByName( frameScene, name ); + + cvf::ref simWellModelBasicList = new cvf::ModelBasicList; + simWellModelBasicList->setName( name ); + + m_flatSimWellPipePartMgr->appendFlattenedDynamicGeometryPartsToModel( simWellModelBasicList.p(), + m_currentTimeStep, + displayCoordTransform().p(), + m_intersection->extentLength(), + m_intersection->branchIndex() ); + + for ( double offset : m_flatSimWellPipePartMgr->flattenedBranchWellHeadOffsets() ) { - cvf::String name = "SimWellPipeMod"; - Rim3dView::removeModelByName( frameScene, name ); - - cvf::ref simWellModelBasicList = new cvf::ModelBasicList; - simWellModelBasicList->setName( name ); - - m_flatSimWellPipePartMgr->appendFlattenedDynamicGeometryPartsToModel( simWellModelBasicList.p(), - m_currentTimeStep, - displayCoordTransform().p(), - m_intersection->extentLength(), - m_intersection->branchIndex() ); - - for ( double offset : m_flatSimWellPipePartMgr->flattenedBranchWellHeadOffsets() ) - { - m_flatWellHeadPartMgr->appendFlattenedDynamicGeometryPartsToModel( simWellModelBasicList.p(), - m_currentTimeStep, - displayCoordTransform().p(), - offset ); - } - - simWellModelBasicList->updateBoundingBoxesRecursive(); - frameScene->addModel( simWellModelBasicList.p() ); - m_flatSimWellPipePartMgr->updatePipeResultColor( m_currentTimeStep ); + m_flatWellHeadPartMgr->appendFlattenedDynamicGeometryPartsToModel( simWellModelBasicList.p(), + m_currentTimeStep, + displayCoordTransform().p(), + offset ); } + + simWellModelBasicList->updateBoundingBoxesRecursive(); + frameScene->addModel( simWellModelBasicList.p() ); + m_flatSimWellPipePartMgr->updatePipeResultColor( m_currentTimeStep ); } } @@ -631,34 +629,36 @@ void Rim2dIntersectionView::onUpdateDisplayModelForCurrentTimeStep() cvf::Scene* frameScene = nativeOrOverrideViewer()->frame( m_currentTimeStep, isUsingOverrideViewer() ); if ( frameScene ) { - { - cvf::String name = "WellPipeDynMod"; - Rim3dView::removeModelByName( frameScene, name ); - cvf::ref dynWellPathModel = new cvf::ModelBasicList; - dynWellPathModel->setName( name ); - - m_flatWellpathPartMgr->appendFlattenedDynamicGeometryPartsToModel( dynWellPathModel.p(), - m_currentTimeStep, - displayCoordTransform().p(), - ownerCase()->characteristicCellSize(), - ownerCase()->activeCellsBoundingBox() ); - dynWellPathModel->updateBoundingBoxesRecursive(); - frameScene->addModel( dynWellPathModel.p() ); - } + cvf::String name = "WellPipeDynMod"; + Rim3dView::removeModelByName( frameScene, name ); + cvf::ref dynWellPathModel = new cvf::ModelBasicList; + dynWellPathModel->setName( name ); + + m_flatWellpathPartMgr->appendFlattenedDynamicGeometryPartsToModel( dynWellPathModel.p(), + m_currentTimeStep, + displayCoordTransform().p(), + ownerCase()->characteristicCellSize(), + ownerCase()->activeCellsBoundingBox() ); + dynWellPathModel->updateBoundingBoxesRecursive(); + frameScene->addModel( dynWellPathModel.p() ); } } - if ( m_flatIntersectionPartMgr.notNull() && hasResults() ) - { - m_flatIntersectionPartMgr->updateCellResultColor( m_currentTimeStep, - m_legendConfig->scalarMapper(), - m_ternaryLegendConfig()->scalarMapper() ); - } - else + if ( m_flatIntersectionPartMgr.notNull() ) { - m_flatIntersectionPartMgr->applySingleColorEffect(); + if ( hasResults() ) + { + m_flatIntersectionPartMgr->updateCellResultColor( m_currentTimeStep, + m_legendConfig->scalarMapper(), + m_ternaryLegendConfig()->scalarMapper() ); + } + else + { + m_flatIntersectionPartMgr->applySingleColorEffect(); + } } } + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/Rim3dView.cpp b/ApplicationLibCode/ProjectDataModel/Rim3dView.cpp index 8f8de11b71..19f00ad9df 100644 --- a/ApplicationLibCode/ProjectDataModel/Rim3dView.cpp +++ b/ApplicationLibCode/ProjectDataModel/Rim3dView.cpp @@ -29,6 +29,7 @@ #include "RicfCommandObject.h" +#include "Rim2dIntersectionView.h" #include "Rim3dWellLogCurve.h" #include "RimAnnotationCollection.h" #include "RimAnnotationInViewCollection.h" @@ -40,6 +41,7 @@ #include "RimMeasurement.h" #include "RimOilField.h" #include "RimProject.h" +#include "RimSeismicView.h" #include "RimTools.h" #include "RimViewController.h" #include "RimViewLinker.h" @@ -581,8 +583,7 @@ std::set Rim3dView::viewsUsingThisAsComparisonView() { if ( field->keyword() == m_comparisonView.keyword() ) { - Rim3dView* containingView = nullptr; - containingView = dynamic_cast( field->ownerObject() ); + Rim3dView* containingView = dynamic_cast( field->ownerObject() ); if ( containingView && containingView->activeComparisonView() == this ) { containingViews.insert( containingView ); @@ -593,6 +594,32 @@ std::set Rim3dView::viewsUsingThisAsComparisonView() return containingViews; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector Rim3dView::validComparisonViews() const +{ + auto isIntersectionView = []( const Rim3dView* view ) { return dynamic_cast( view ) != nullptr; }; + + std::vector views; + RimProject::current()->allViews( views ); + + std::vector validComparisonViews; + for ( auto view : views ) + { + if ( dynamic_cast( view ) ) continue; + + bool isSameViewType = isIntersectionView( this ) == isIntersectionView( view ); + + if ( view != this && isSameViewType ) + { + validComparisonViews.push_back( view ); + } + } + + return validComparisonViews; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -1518,21 +1545,13 @@ QList Rim3dView::calculateValueOptions( const caf::PdmFi if ( fieldNeedingOptions == &m_comparisonView ) { - RimProject* proj = RimProject::current(); - if ( proj ) + std::vector views = validComparisonViews(); + for ( auto view : views ) { - std::vector views; - proj->allViews( views ); - for ( auto view : views ) - { - if ( view != this ) - { - RiaOptionItemFactory::appendOptionItemFromViewNameAndCaseName( view, &options ); - } - } - - options.push_front( caf::PdmOptionItemInfo( "None", nullptr ) ); + RiaOptionItemFactory::appendOptionItemFromViewNameAndCaseName( view, &options ); } + + options.push_front( caf::PdmOptionItemInfo( "None", nullptr ) ); } else if ( fieldNeedingOptions == &m_fontSize ) { diff --git a/ApplicationLibCode/ProjectDataModel/Rim3dView.h b/ApplicationLibCode/ProjectDataModel/Rim3dView.h index d27dbb01c8..c58b5daedd 100644 --- a/ApplicationLibCode/ProjectDataModel/Rim3dView.h +++ b/ApplicationLibCode/ProjectDataModel/Rim3dView.h @@ -183,11 +183,12 @@ class Rim3dView : public RimViewWindow, public RiuViewerToViewInterface, public bool isScaleZEditable(); double scaleZ() const; - bool isMasterView() const; - Rim3dView* activeComparisonView() const; - void setComparisonView( Rim3dView* compView ); - std::set viewsUsingThisAsComparisonView(); - void updateMdiWindowTitle() override; + bool isMasterView() const; + Rim3dView* activeComparisonView() const; + void setComparisonView( Rim3dView* compView ); + std::set viewsUsingThisAsComparisonView(); + void updateMdiWindowTitle() override; + std::vector validComparisonViews() const; RimViewLinker* assosiatedViewLinker() const override; RimViewController* viewController() const override; diff --git a/ApplicationLibCode/ProjectDataModel/RimContextCommandBuilder.cpp b/ApplicationLibCode/ProjectDataModel/RimContextCommandBuilder.cpp index 18e1b3bf52..8745c6db91 100644 --- a/ApplicationLibCode/ProjectDataModel/RimContextCommandBuilder.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimContextCommandBuilder.cpp @@ -168,6 +168,7 @@ #include "RimWellPathFracture.h" #include "RimWellPathFractureCollection.h" #include "RimWellPltPlot.h" +#include "RimWellRftPlot.h" #ifdef USE_QTCHARTS #include "RimEnsembleFractureStatisticsPlotCollection.h" @@ -631,6 +632,10 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection() { menuBuilder << "RicDuplicateSummaryTableFeature"; } + else if ( dynamic_cast( firstUiItem ) ) + { + menuBuilder << "RicCreateRftPlotsFeature"; + } else if ( dynamic_cast( firstUiItem ) && !dynamic_cast( firstUiItem ) ) { menuBuilder << "RicPasteWellLogPlotFeature"; @@ -1029,6 +1034,8 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection() } else if ( dynamic_cast( firstUiItem ) ) { + menuBuilder << "RicPasteCellFiltersFeature"; + menuBuilder << "Separator"; menuBuilder << "RicNewPolygonFilterFeature"; menuBuilder << "RicNewUserDefinedFilterFeature"; menuBuilder << "RicNewUserDefinedIndexFilterFeature"; diff --git a/ApplicationLibCode/ProjectDataModel/RimCustomObjectiveFunctionWeight.cpp b/ApplicationLibCode/ProjectDataModel/RimCustomObjectiveFunctionWeight.cpp index 3316f1a889..f459d88122 100644 --- a/ApplicationLibCode/ProjectDataModel/RimCustomObjectiveFunctionWeight.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimCustomObjectiveFunctionWeight.cpp @@ -192,7 +192,7 @@ void RimCustomObjectiveFunctionWeight::fieldChangedByUi( const caf::PdmFieldHand void RimCustomObjectiveFunctionWeight::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) { uiOrdering.add( &m_objectiveValuesSummaryAddressesUiField ); - uiOrdering.add( &m_objectiveValuesSelectSummaryAddressPushButton, { false, 1, 0 } ); + uiOrdering.add( &m_objectiveValuesSelectSummaryAddressPushButton, { .newRow = false, .totalColumnSpan = 1, .leftLabelColumnSpan = 0 } ); uiOrdering.add( &m_weightValue ); uiOrdering.add( &m_objectiveFunction ); diff --git a/ApplicationLibCode/ProjectDataModel/RimEclipseCase.cpp b/ApplicationLibCode/ProjectDataModel/RimEclipseCase.cpp index 39afe7c0ea..9b97a53668 100644 --- a/ApplicationLibCode/ProjectDataModel/RimEclipseCase.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimEclipseCase.cpp @@ -590,6 +590,9 @@ void RimEclipseCase::buildResultChildNodes() { m_resultAddressCollections.deleteChildren(); + auto cellResultData = results( RiaDefines::PorosityModelType::MATRIX_MODEL ); + if ( !cellResultData ) return; + std::vector resultTypes = { RiaDefines::ResultCatType::STATIC_NATIVE, RiaDefines::ResultCatType::DYNAMIC_NATIVE, RiaDefines::ResultCatType::INPUT_PROPERTY, @@ -601,14 +604,10 @@ void RimEclipseCase::buildResultChildNodes() QString name = caf::AppEnum::uiText( resultType ); resultAddressCollection->setName( name ); - auto cellResultData = results( RiaDefines::PorosityModelType::MATRIX_MODEL ); - if ( cellResultData ) + QStringList resultNames = cellResultData->resultNames( resultType ); + for ( auto resultName : resultNames ) { - QStringList resultNames = cellResultData->resultNames( resultType ); - for ( auto resultName : resultNames ) - { - resultAddressCollection->addAddress( resultName, resultType, this ); - } + resultAddressCollection->addAddress( resultName, resultType, this ); } m_resultAddressCollections.push_back( resultAddressCollection ); @@ -985,54 +984,51 @@ bool RimEclipseCase::openReserviorCase() if ( createPlaceholderEntries ) { + if ( RigCaseCellResultsData* results = this->results( RiaDefines::PorosityModelType::MATRIX_MODEL ) ) { - RigCaseCellResultsData* results = this->results( RiaDefines::PorosityModelType::MATRIX_MODEL ); - if ( results ) - { - results->createPlaceholderResultEntries(); - // After the placeholder result for combined transmissibility is created, - // make sure the nnc transmissibilities can be addressed by this scalarResultIndex as well + results->createPlaceholderResultEntries(); + // After the placeholder result for combined transmissibility is created, + // make sure the nnc transmissibilities can be addressed by this scalarResultIndex as well - RigEclipseResultAddress combinedTransmissibilityResAddr( RiaDefines::ResultCatType::STATIC_NATIVE, - RiaResultNames::combinedTransmissibilityResultName() ); - if ( results->hasResultEntry( combinedTransmissibilityResAddr ) ) - { - eclipseCaseData()->mainGrid()->nncData()->setEclResultAddress( RiaDefines::propertyNameCombTrans(), - combinedTransmissibilityResAddr ); - } + RigEclipseResultAddress combinedTransmissibilityResAddr( RiaDefines::ResultCatType::STATIC_NATIVE, + RiaResultNames::combinedTransmissibilityResultName() ); + if ( results->hasResultEntry( combinedTransmissibilityResAddr ) ) + { + eclipseCaseData()->mainGrid()->nncData()->setEclResultAddress( RiaDefines::propertyNameCombTrans(), + combinedTransmissibilityResAddr ); + } - RigEclipseResultAddress combinedWaterFluxResAddr( RiaDefines::ResultCatType::DYNAMIC_NATIVE, - RiaResultNames::combinedWaterFluxResultName() ); - if ( results->hasResultEntry( combinedWaterFluxResAddr ) ) - { - eclipseCaseData()->mainGrid()->nncData()->setEclResultAddress( RiaDefines::propertyNameFluxWat(), combinedWaterFluxResAddr ); - } + RigEclipseResultAddress combinedWaterFluxResAddr( RiaDefines::ResultCatType::DYNAMIC_NATIVE, + RiaResultNames::combinedWaterFluxResultName() ); + if ( results->hasResultEntry( combinedWaterFluxResAddr ) ) + { + eclipseCaseData()->mainGrid()->nncData()->setEclResultAddress( RiaDefines::propertyNameFluxWat(), combinedWaterFluxResAddr ); + } - RigEclipseResultAddress combinedOilFluxResAddr( RiaDefines::ResultCatType::DYNAMIC_NATIVE, - RiaResultNames::combinedOilFluxResultName() ); - if ( results->hasResultEntry( combinedOilFluxResAddr ) ) - { - eclipseCaseData()->mainGrid()->nncData()->setEclResultAddress( RiaDefines::propertyNameFluxOil(), combinedOilFluxResAddr ); - } - RigEclipseResultAddress combinedGasFluxResAddr( RiaDefines::ResultCatType::DYNAMIC_NATIVE, - RiaResultNames::combinedGasFluxResultName() ); + RigEclipseResultAddress combinedOilFluxResAddr( RiaDefines::ResultCatType::DYNAMIC_NATIVE, + RiaResultNames::combinedOilFluxResultName() ); + if ( results->hasResultEntry( combinedOilFluxResAddr ) ) + { + eclipseCaseData()->mainGrid()->nncData()->setEclResultAddress( RiaDefines::propertyNameFluxOil(), combinedOilFluxResAddr ); + } + RigEclipseResultAddress combinedGasFluxResAddr( RiaDefines::ResultCatType::DYNAMIC_NATIVE, + RiaResultNames::combinedGasFluxResultName() ); - if ( results->hasResultEntry( combinedGasFluxResAddr ) ) - { - eclipseCaseData()->mainGrid()->nncData()->setEclResultAddress( RiaDefines::propertyNameFluxGas(), combinedGasFluxResAddr ); - } + if ( results->hasResultEntry( combinedGasFluxResAddr ) ) + { + eclipseCaseData()->mainGrid()->nncData()->setEclResultAddress( RiaDefines::propertyNameFluxGas(), combinedGasFluxResAddr ); } } + if ( RigCaseCellResultsData* results = this->results( RiaDefines::PorosityModelType::FRACTURE_MODEL ) ) { - RigCaseCellResultsData* results = this->results( RiaDefines::PorosityModelType::FRACTURE_MODEL ); - if ( results ) - { - results->createPlaceholderResultEntries(); - } + results->createPlaceholderResultEntries(); } } + // Build result child nodes after the placeholder entries have been created + if ( m_resultAddressCollections.empty() ) buildResultChildNodes(); + createTimeStepFormatString(); // Associate existing well paths with simulation wells diff --git a/ApplicationLibCode/ProjectDataModel/RimEclipseCaseTools.cpp b/ApplicationLibCode/ProjectDataModel/RimEclipseCaseTools.cpp index 2c8ee8740a..be0abdfa9f 100644 --- a/ApplicationLibCode/ProjectDataModel/RimEclipseCaseTools.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimEclipseCaseTools.cpp @@ -19,6 +19,7 @@ #include "RimEclipseCaseTools.h" #include "RimEclipseResultCase.h" +#include "RimEclipseStatisticsCase.h" #include "RimProject.h" //-------------------------------------------------------------------------------------------------- @@ -53,3 +54,30 @@ std::vector RimEclipseCaseTools::eclipseResultCases() return resultCases; } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RimEclipseCaseTools::allEclipseGridCases() +{ + // Find all Eclipse cases, including all single grid cases and source cases in a grid case group. Statistics cases are excluded. + + RimProject* proj = RimProject::current(); + if ( proj ) + { + std::vector eclipseCases; + for ( auto c : proj->allGridCases() ) + { + if ( dynamic_cast( c ) ) continue; + + if ( auto ec = dynamic_cast( c ) ) + { + eclipseCases.push_back( ec ); + } + } + + return eclipseCases; + } + + return {}; +} diff --git a/ApplicationLibCode/ProjectDataModel/RimEclipseCaseTools.h b/ApplicationLibCode/ProjectDataModel/RimEclipseCaseTools.h index 751460bb4b..0c197957ba 100644 --- a/ApplicationLibCode/ProjectDataModel/RimEclipseCaseTools.h +++ b/ApplicationLibCode/ProjectDataModel/RimEclipseCaseTools.h @@ -29,6 +29,12 @@ class RimEclipseResultCase; class RimEclipseCaseTools { public: - static std::vector eclipseCases(); + // Single grid cases not part of a grid case group + static std::vector eclipseCases(); + + // Result cases based on RimEclipseCaseTools::elipseCases() static std::vector eclipseResultCases(); + + // All Eclipse cases including grid case group source cases, excluding statistics cases + static std::vector allEclipseGridCases(); }; diff --git a/ApplicationLibCode/ProjectDataModel/RimEclipseCellColors.cpp b/ApplicationLibCode/ProjectDataModel/RimEclipseCellColors.cpp index 6f658f0a6e..e563561f0b 100644 --- a/ApplicationLibCode/ProjectDataModel/RimEclipseCellColors.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimEclipseCellColors.cpp @@ -145,7 +145,10 @@ void RimEclipseCellColors::changeLegendConfig( QString resultVarNameOfNewLegend int caseId = 0; if ( eclipseCase() ) caseId = eclipseCase()->caseId(); - auto newLegend = createLegendForResult( caseId, resultVarNameOfNewLegend, m_useDiscreteLogLevels, hasCategoryResult() ); + bool useCategoryLegend = hasCategoryResult(); + if ( m_resultType() == RiaDefines::ResultCatType::FORMATION_NAMES ) useCategoryLegend = true; + + auto newLegend = createLegendForResult( caseId, resultVarNameOfNewLegend, m_useDiscreteLogLevels, useCategoryLegend ); newLegend->changed.connect( this, &RimEclipseCellColors::onLegendConfigChanged ); diff --git a/ApplicationLibCode/ProjectDataModel/RimEclipseResultDefinition.cpp b/ApplicationLibCode/ProjectDataModel/RimEclipseResultDefinition.cpp index 8d9252cb18..ea63ec6231 100644 --- a/ApplicationLibCode/ProjectDataModel/RimEclipseResultDefinition.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimEclipseResultDefinition.cpp @@ -1485,7 +1485,7 @@ void RimEclipseResultDefinition::defineUiOrdering( QString uiConfigName, caf::Pd injectorGroup->add( &m_selectedInjectorTracersUiField ); injectorGroup->add( &m_syncInjectorToProducerSelection ); - caf::PdmUiGroup* producerGroup = selectionGroup->addNewGroup( "Producers", false ); + caf::PdmUiGroup* producerGroup = selectionGroup->addNewGroup( "Producers", { .newRow = false } ); producerGroup->add( &m_selectedProducerTracersUiField ); producerGroup->add( &m_syncProducerToInjectorSelection ); } diff --git a/ApplicationLibCode/ProjectDataModel/RimEclipseStatisticsCase.cpp b/ApplicationLibCode/ProjectDataModel/RimEclipseStatisticsCase.cpp index c1485f3f4f..070b9e55b2 100644 --- a/ApplicationLibCode/ProjectDataModel/RimEclipseStatisticsCase.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimEclipseStatisticsCase.cpp @@ -20,6 +20,7 @@ #include "RimEclipseStatisticsCase.h" +#include "RiaOptionItemFactory.h" #include "RiaResultNames.h" #include "RicNewViewFeature.h" @@ -34,8 +35,10 @@ #include "RimEclipseCellColors.h" #include "RimEclipseStatisticsCaseEvaluator.h" #include "RimEclipseView.h" +#include "RimGridCalculationCollection.h" #include "RimIdenticalGridCaseGroup.h" #include "RimIntersectionCollection.h" +#include "RimProject.h" #include "RimReservoirCellResultsStorage.h" #include "RimSimWellInViewCollection.h" @@ -44,6 +47,7 @@ #include "cafPdmFieldScriptingCapability.h" #include "cafPdmUiPushButtonEditor.h" #include "cafPdmUiTextEditor.h" +#include "cafPdmUiTreeSelectionEditor.h" #include "cafProgressInfo.h" namespace caf @@ -51,10 +55,19 @@ namespace caf template <> void caf::AppEnum::setUp() { - addItem( RimEclipseStatisticsCase::NEAREST_OBSERVATION, "NearestObservationPercentile", "Nearest Observation" ); - addItem( RimEclipseStatisticsCase::HISTOGRAM_ESTIMATED, "HistogramEstimatedPercentile", "Histogram based estimate" ); - addItem( RimEclipseStatisticsCase::INTERPOLATED_OBSERVATION, "InterpolatedObservationPercentile", "Interpolated Observation" ); - setDefault( RimEclipseStatisticsCase::INTERPOLATED_OBSERVATION ); + addItem( RimEclipseStatisticsCase::PercentileCalcType::NEAREST_OBSERVATION, "NearestObservationPercentile", "Nearest Observation" ); + addItem( RimEclipseStatisticsCase::PercentileCalcType::HISTOGRAM_ESTIMATED, "HistogramEstimatedPercentile", "Histogram based estimate" ); + addItem( RimEclipseStatisticsCase::PercentileCalcType::INTERPOLATED_OBSERVATION, + "InterpolatedObservationPercentile", + "Interpolated Observation" ); + setDefault( RimEclipseStatisticsCase::PercentileCalcType::INTERPOLATED_OBSERVATION ); +} +template <> +void caf::AppEnum::setUp() +{ + addItem( RimEclipseStatisticsCase::DataSourceType::GRID_CALCULATION, "GridCalculation", "Grid Calculation" ); + addItem( RimEclipseStatisticsCase::DataSourceType::CASE_PROPERTY, "CaseProperty", "Case Property" ); + setDefault( RimEclipseStatisticsCase::DataSourceType::CASE_PROPERTY ); } } // namespace caf @@ -78,6 +91,14 @@ RimEclipseStatisticsCase::RimEclipseStatisticsCase() m_selectionSummary.uiCapability()->setUiEditorTypeName( caf::PdmUiTextEditor::uiEditorTypeName() ); m_selectionSummary.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::HIDDEN ); + CAF_PDM_InitFieldNoDefault( &m_dataSourceForStatistics, "DataSourceForStatistics", "Data Source" ); + + CAF_PDM_InitFieldNoDefault( &m_gridCalculation, "GridCalculation", "Grid Calculation" ); + CAF_PDM_InitFieldNoDefault( &m_gridCalculationFilterView, "GridCalculationFilterView", "Filter By View" ); + + CAF_PDM_InitScriptableFieldNoDefault( &m_selectedTimeSteps, "SelectedTimeSteps", "Time Step Selection" ); + m_selectedTimeSteps.uiCapability()->setUiEditorTypeName( caf::PdmUiTreeSelectionEditor::uiEditorTypeName() ); + CAF_PDM_InitScriptableFieldNoDefault( &m_resultType, "ResultType", "Result Type" ); m_resultType.xmlCapability()->setIOWritable( false ); CAF_PDM_InitScriptableFieldNoDefault( &m_porosityModel, "PorosityModel", "Porosity Model" ); @@ -120,6 +141,8 @@ RimEclipseStatisticsCase::RimEclipseStatisticsCase() m_flipXAxis.uiCapability()->setUiHidden( true ); m_flipYAxis.uiCapability()->setUiHidden( true ); m_activeFormationNames.uiCapability()->setUiHidden( true ); + + m_displayNameOption = RimCaseDisplayNameTools::DisplayName::CUSTOM; } //-------------------------------------------------------------------------------------------------- @@ -174,6 +197,8 @@ bool RimEclipseStatisticsCase::openEclipseGridFile() m_populateSelectionAfterLoadingGrid = false; } + initializeSelectedTimeSteps(); + return true; } @@ -240,6 +265,26 @@ void RimEclipseStatisticsCase::setSourceProperties( RiaDefines::ResultCatType pr } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimEclipseStatisticsCase::selectAllTimeSteps() +{ + RimIdenticalGridCaseGroup* idgcg = caseGroup(); + if ( idgcg && idgcg->mainCase() ) + { + int timeStepCount = idgcg->mainCase()->timeStepStrings().size(); + + if ( timeStepCount > 0 ) + { + std::vector allTimeSteps; + allTimeSteps.resize( timeStepCount ); + std::iota( allTimeSteps.begin(), allTimeSteps.end(), 0 ); + m_selectedTimeSteps = allTimeSteps; + } + } +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -256,15 +301,39 @@ void RimEclipseStatisticsCase::computeStatistics() std::vector sourceCases = getSourceCases(); + if ( m_dataSourceForStatistics() == DataSourceType::GRID_CALCULATION && m_gridCalculation() ) + { + auto proj = RimProject::current(); + auto calcColl = proj->gridCalculationCollection(); + + auto dependentCalculations = calcColl->dependentCalculations( m_gridCalculation() ); + if ( dependentCalculations.empty() ) + { + // No calculations found, usually triggered by a circular dependency of calculations. Error message displayed by + // dependentCalculations(). + return; + } + + std::vector timeStepIndices( m_selectedTimeSteps().begin(), m_selectedTimeSteps().end() ); + + for ( auto calc : dependentCalculations ) + { + cvf::UByteArray* inputValueVisibilityFilter = nullptr; + if ( m_gridCalculationFilterView() ) + { + inputValueVisibilityFilter = m_gridCalculationFilterView()->currentTotalCellVisibility().p(); + } + + bool evaluateDependentCalculations = false; + calc->calculateForCases( sourceCases, inputValueVisibilityFilter, timeStepIndices, evaluateDependentCalculations ); + } + } + if ( sourceCases.empty() || !sourceCases.at( 0 )->results( RiaDefines::PorosityModelType::MATRIX_MODEL ) ) { return; } - // The first source has been read completely from disk, and contains grid and meta data - // Use this information for all cases in the case group - size_t timeStepCount = sourceCases.at( 0 )->results( RiaDefines::PorosityModelType::MATRIX_MODEL )->maxTimeStepCount(); - RimStatisticsConfig statisticsConfig; statisticsConfig.m_calculatePercentiles = m_calculatePercentiles(); @@ -273,11 +342,7 @@ void RimEclipseStatisticsCase::computeStatistics() statisticsConfig.m_pMinPos = m_lowPercentile(); statisticsConfig.m_pValMethod = m_percentileCalculationType(); - std::vector timeStepIndices; - for ( size_t i = 0; i < timeStepCount; i++ ) - { - timeStepIndices.push_back( i ); - } + auto timeStepIndices = m_selectedTimeSteps(); // If no dynamic data is present, we might end up with no time steps. Make sure we have at least one. if ( timeStepIndices.empty() ) @@ -289,70 +354,82 @@ void RimEclipseStatisticsCase::computeStatistics() QList resultSpecification; - for ( size_t pIdx = 0; pIdx < m_selectedDynamicProperties().size(); ++pIdx ) + if ( m_dataSourceForStatistics() == DataSourceType::CASE_PROPERTY ) { - resultSpecification.append( RimEclipseStatisticsCaseEvaluator::ResSpec( RiaDefines::PorosityModelType::MATRIX_MODEL, - RiaDefines::ResultCatType::DYNAMIC_NATIVE, - m_selectedDynamicProperties()[pIdx] ) ); - } + for ( size_t pIdx = 0; pIdx < m_selectedDynamicProperties().size(); ++pIdx ) + { + resultSpecification.append( RimEclipseStatisticsCaseEvaluator::ResSpec( RiaDefines::PorosityModelType::MATRIX_MODEL, + RiaDefines::ResultCatType::DYNAMIC_NATIVE, + m_selectedDynamicProperties()[pIdx] ) ); + } - for ( size_t pIdx = 0; pIdx < m_selectedStaticProperties().size(); ++pIdx ) - { - resultSpecification.append( RimEclipseStatisticsCaseEvaluator::ResSpec( RiaDefines::PorosityModelType::MATRIX_MODEL, - RiaDefines::ResultCatType::STATIC_NATIVE, - m_selectedStaticProperties()[pIdx] ) ); - } + for ( size_t pIdx = 0; pIdx < m_selectedStaticProperties().size(); ++pIdx ) + { + resultSpecification.append( RimEclipseStatisticsCaseEvaluator::ResSpec( RiaDefines::PorosityModelType::MATRIX_MODEL, + RiaDefines::ResultCatType::STATIC_NATIVE, + m_selectedStaticProperties()[pIdx] ) ); + } - for ( size_t pIdx = 0; pIdx < m_selectedGeneratedProperties().size(); ++pIdx ) - { - resultSpecification.append( RimEclipseStatisticsCaseEvaluator::ResSpec( RiaDefines::PorosityModelType::MATRIX_MODEL, - RiaDefines::ResultCatType::GENERATED, - m_selectedGeneratedProperties()[pIdx] ) ); - } + for ( size_t pIdx = 0; pIdx < m_selectedGeneratedProperties().size(); ++pIdx ) + { + resultSpecification.append( RimEclipseStatisticsCaseEvaluator::ResSpec( RiaDefines::PorosityModelType::MATRIX_MODEL, + RiaDefines::ResultCatType::GENERATED, + m_selectedGeneratedProperties()[pIdx] ) ); + } - for ( size_t pIdx = 0; pIdx < m_selectedInputProperties().size(); ++pIdx ) - { - resultSpecification.append( RimEclipseStatisticsCaseEvaluator::ResSpec( RiaDefines::PorosityModelType::MATRIX_MODEL, - RiaDefines::ResultCatType::INPUT_PROPERTY, - m_selectedInputProperties()[pIdx] ) ); - } + for ( size_t pIdx = 0; pIdx < m_selectedInputProperties().size(); ++pIdx ) + { + resultSpecification.append( RimEclipseStatisticsCaseEvaluator::ResSpec( RiaDefines::PorosityModelType::MATRIX_MODEL, + RiaDefines::ResultCatType::INPUT_PROPERTY, + m_selectedInputProperties()[pIdx] ) ); + } - for ( size_t pIdx = 0; pIdx < m_selectedFractureDynamicProperties().size(); ++pIdx ) - { - resultSpecification.append( RimEclipseStatisticsCaseEvaluator::ResSpec( RiaDefines::PorosityModelType::FRACTURE_MODEL, - RiaDefines::ResultCatType::DYNAMIC_NATIVE, - m_selectedFractureDynamicProperties()[pIdx] ) ); - } + for ( size_t pIdx = 0; pIdx < m_selectedFractureDynamicProperties().size(); ++pIdx ) + { + resultSpecification.append( RimEclipseStatisticsCaseEvaluator::ResSpec( RiaDefines::PorosityModelType::FRACTURE_MODEL, + RiaDefines::ResultCatType::DYNAMIC_NATIVE, + m_selectedFractureDynamicProperties()[pIdx] ) ); + } - for ( size_t pIdx = 0; pIdx < m_selectedFractureStaticProperties().size(); ++pIdx ) - { - resultSpecification.append( RimEclipseStatisticsCaseEvaluator::ResSpec( RiaDefines::PorosityModelType::FRACTURE_MODEL, - RiaDefines::ResultCatType::STATIC_NATIVE, - m_selectedFractureStaticProperties()[pIdx] ) ); - } + for ( size_t pIdx = 0; pIdx < m_selectedFractureStaticProperties().size(); ++pIdx ) + { + resultSpecification.append( RimEclipseStatisticsCaseEvaluator::ResSpec( RiaDefines::PorosityModelType::FRACTURE_MODEL, + RiaDefines::ResultCatType::STATIC_NATIVE, + m_selectedFractureStaticProperties()[pIdx] ) ); + } - for ( size_t pIdx = 0; pIdx < m_selectedFractureGeneratedProperties().size(); ++pIdx ) - { - resultSpecification.append( RimEclipseStatisticsCaseEvaluator::ResSpec( RiaDefines::PorosityModelType::FRACTURE_MODEL, - RiaDefines::ResultCatType::GENERATED, - m_selectedFractureGeneratedProperties()[pIdx] ) ); - } + for ( size_t pIdx = 0; pIdx < m_selectedFractureGeneratedProperties().size(); ++pIdx ) + { + resultSpecification.append( RimEclipseStatisticsCaseEvaluator::ResSpec( RiaDefines::PorosityModelType::FRACTURE_MODEL, + RiaDefines::ResultCatType::GENERATED, + m_selectedFractureGeneratedProperties()[pIdx] ) ); + } - for ( size_t pIdx = 0; pIdx < m_selectedFractureInputProperties().size(); ++pIdx ) + for ( size_t pIdx = 0; pIdx < m_selectedFractureInputProperties().size(); ++pIdx ) + { + resultSpecification.append( RimEclipseStatisticsCaseEvaluator::ResSpec( RiaDefines::PorosityModelType::FRACTURE_MODEL, + RiaDefines::ResultCatType::INPUT_PROPERTY, + m_selectedFractureInputProperties()[pIdx] ) ); + } + } + else if ( m_dataSourceForStatistics() == DataSourceType::GRID_CALCULATION && m_gridCalculation() ) { - resultSpecification.append( RimEclipseStatisticsCaseEvaluator::ResSpec( RiaDefines::PorosityModelType::FRACTURE_MODEL, - RiaDefines::ResultCatType::INPUT_PROPERTY, - m_selectedFractureInputProperties()[pIdx] ) ); + auto calculationName = m_gridCalculation->shortName(); + + resultSpecification.append( RimEclipseStatisticsCaseEvaluator::ResSpec( RiaDefines::PorosityModelType::MATRIX_MODEL, + RiaDefines::ResultCatType::GENERATED, + calculationName ) ); } - RimEclipseStatisticsCaseEvaluator stat( sourceCases, timeStepIndices, statisticsConfig, resultCase, gridCaseGroup ); + bool clearGridCalculationMemory = m_dataSourceForStatistics() == DataSourceType::GRID_CALCULATION; + RimEclipseStatisticsCaseEvaluator stat( sourceCases, timeStepIndices, statisticsConfig, resultCase, gridCaseGroup, clearGridCalculationMemory ); if ( m_useZeroAsInactiveCellValue ) { stat.useZeroAsValueForInActiveCellsBasedOnUnionOfActiveCells(); } - stat.evaluateForResults( resultSpecification ); + stat.evaluateForResults( resultSpecification, m_gridCalculationFilterView() ); } //-------------------------------------------------------------------------------------------------- /// @@ -419,37 +496,63 @@ void RimEclipseStatisticsCase::defineUiOrdering( QString uiConfigName, caf::PdmU uiOrdering.add( &m_calculateEditCommand ); - caf::PdmUiGroup* group = uiOrdering.addNewGroup( "Summary of Calculation Setup" ); - group->add( &m_useZeroAsInactiveCellValue ); - m_useZeroAsInactiveCellValue.uiCapability()->setUiHidden( hasComputedStatistics() ); - group->add( &m_selectionSummary ); - - group = uiOrdering.addNewGroup( "Properties to consider" ); - group->setUiHidden( hasComputedStatistics() ); - group->add( &m_resultType ); - group->add( &m_porosityModel ); - group->add( &m_selectedDynamicProperties ); - group->add( &m_selectedStaticProperties ); - group->add( &m_selectedGeneratedProperties ); - group->add( &m_selectedInputProperties ); - group->add( &m_selectedFractureDynamicProperties ); - group->add( &m_selectedFractureStaticProperties ); - group->add( &m_selectedFractureGeneratedProperties ); - group->add( &m_selectedFractureInputProperties ); - - group = uiOrdering.addNewGroup( "Percentile setup" ); - group->setUiHidden( hasComputedStatistics() ); - group->add( &m_calculatePercentiles ); - group->add( &m_percentileCalculationType ); - group->add( &m_lowPercentile ); - group->add( &m_midPercentile ); - group->add( &m_highPercentile ); - - group = uiOrdering.addNewGroup( "Case Options" ); - group->add( &m_wellDataSourceCase ); - group->add( &m_activeFormationNames ); - group->add( &m_flipXAxis ); - group->add( &m_flipYAxis ); + { + caf::PdmUiGroup* group = uiOrdering.addNewGroup( "Summary of Calculation Setup" ); + group->add( &m_useZeroAsInactiveCellValue ); + m_useZeroAsInactiveCellValue.uiCapability()->setUiHidden( hasComputedStatistics() ); + group->add( &m_selectionSummary ); + } + + { + auto group = uiOrdering.addNewGroup( "Properties to consider" ); + group->setUiHidden( hasComputedStatistics() ); + group->add( &m_dataSourceForStatistics ); + + if ( m_dataSourceForStatistics() == DataSourceType::GRID_CALCULATION ) + { + group->add( &m_gridCalculation ); + group->add( &m_gridCalculationFilterView ); + } + else + { + group->add( &m_resultType ); + group->add( &m_porosityModel ); + group->add( &m_selectedDynamicProperties ); + group->add( &m_selectedStaticProperties ); + group->add( &m_selectedGeneratedProperties ); + group->add( &m_selectedInputProperties ); + group->add( &m_selectedFractureDynamicProperties ); + group->add( &m_selectedFractureStaticProperties ); + group->add( &m_selectedFractureGeneratedProperties ); + group->add( &m_selectedFractureInputProperties ); + } + } + + { + auto group = uiOrdering.addNewGroup( "Time Step Selection" ); + group->setCollapsedByDefault(); + group->add( &m_selectedTimeSteps ); + } + + { + auto group = uiOrdering.addNewGroup( "Percentile setup" ); + group->setUiHidden( hasComputedStatistics() ); + group->add( &m_calculatePercentiles ); + group->add( &m_percentileCalculationType ); + group->add( &m_lowPercentile ); + group->add( &m_midPercentile ); + group->add( &m_highPercentile ); + } + + { + auto group = uiOrdering.addNewGroup( "Case Options" ); + group->add( &m_wellDataSourceCase ); + group->add( &m_activeFormationNames ); + group->add( &m_flipXAxis ); + group->add( &m_flipYAxis ); + } + + uiOrdering.skipRemainingFields(); } QList toOptionList( const QStringList& varList ) @@ -468,16 +571,77 @@ QList toOptionList( const QStringList& varList ) //-------------------------------------------------------------------------------------------------- QList RimEclipseStatisticsCase::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions ) { - QList options; - RimIdenticalGridCaseGroup* idgcg = caseGroup(); if ( !( caseGroup() && caseGroup()->mainCase() && caseGroup()->mainCase()->eclipseCaseData() ) ) { + return {}; + } + + if ( &m_dataSourceForStatistics == fieldNeedingOptions ) + { + QList options; + + { + caf::IconProvider iconProvider( ":/Case48x48.png" ); + options.push_back( caf::PdmOptionItemInfo( caf::AppEnum::uiText( DataSourceType::CASE_PROPERTY ), + DataSourceType::CASE_PROPERTY, + false, + iconProvider ) ); + } + { + caf::IconProvider iconProvider( ":/Calculator.svg" ); + options.push_back( caf::PdmOptionItemInfo( caf::AppEnum::uiText( DataSourceType::GRID_CALCULATION ), + DataSourceType::GRID_CALCULATION, + false, + iconProvider ) ); + } + + return options; + } + + if ( &m_gridCalculation == fieldNeedingOptions ) + { + QList options; + + for ( auto calc : RimProject::current()->gridCalculationCollection()->calculations() ) + { + options.push_back( caf::PdmOptionItemInfo( calc->shortName(), calc ) ); + } + return options; } RigEclipseCaseData* caseData = idgcg->mainCase()->eclipseCaseData(); + if ( &m_selectedTimeSteps == fieldNeedingOptions ) + { + QList options; + + const auto timeStepStrings = idgcg->mainCase()->timeStepStrings(); + + int index = 0; + for ( const auto& text : timeStepStrings ) + { + options.push_back( caf::PdmOptionItemInfo( text, index++ ) ); + } + + return options; + } + + if ( &m_gridCalculationFilterView == fieldNeedingOptions ) + { + QList options; + + options.push_back( caf::PdmOptionItemInfo( "None", nullptr ) ); + + for ( const auto& view : views() ) + { + RiaOptionItemFactory::appendOptionItemFromViewNameAndCaseName( view, &options ); + } + + return options; + } + if ( &m_selectedDynamicProperties == fieldNeedingOptions ) { QStringList varList = @@ -540,9 +704,7 @@ QList RimEclipseStatisticsCase::calculateValueOptions( c return toOptionList( sourceCaseNames ); } - if ( options.empty() ) options = RimEclipseCase::calculateValueOptions( fieldNeedingOptions ); - - return options; + return RimEclipseCase::calculateValueOptions( fieldNeedingOptions ); } //-------------------------------------------------------------------------------------------------- @@ -569,6 +731,15 @@ void RimEclipseStatisticsCase::fieldChangedByUi( const caf::PdmFieldHandle* chan m_calculateEditCommand = false; } + if ( &m_dataSourceForStatistics == changedField && m_gridCalculation() == nullptr ) + { + auto calculations = RimProject::current()->gridCalculationCollection()->calculations(); + if ( !calculations.empty() ) + { + m_gridCalculation = dynamic_cast( calculations.front() ); + } + } + if ( &m_wellDataSourceCase == changedField ) { loadSimulationWellDataFromSourceCase(); @@ -662,15 +833,26 @@ void RimEclipseStatisticsCase::updateSelectionSummaryLabel() } html += "

"; - addPropertySetToHtmlText( html, "Dynamic properties", m_selectedDynamicProperties() ); - addPropertySetToHtmlText( html, "Static properties", m_selectedStaticProperties() ); - addPropertySetToHtmlText( html, "Generated properties", m_selectedGeneratedProperties() ); - addPropertySetToHtmlText( html, "Input properties", m_selectedInputProperties() ); + if ( m_dataSourceForStatistics() == DataSourceType::CASE_PROPERTY ) + { + addPropertySetToHtmlText( html, "Dynamic properties", m_selectedDynamicProperties() ); + addPropertySetToHtmlText( html, "Static properties", m_selectedStaticProperties() ); + addPropertySetToHtmlText( html, "Generated properties", m_selectedGeneratedProperties() ); + addPropertySetToHtmlText( html, "Input properties", m_selectedInputProperties() ); + + addPropertySetToHtmlText( html, "Dynamic properties, fracture model", m_selectedFractureDynamicProperties() ); + addPropertySetToHtmlText( html, "Static properties, fracture model", m_selectedFractureStaticProperties() ); + addPropertySetToHtmlText( html, "Generated properties, fracture model", m_selectedFractureGeneratedProperties() ); + addPropertySetToHtmlText( html, "Input properties, fracture model", m_selectedFractureInputProperties() ); + } - addPropertySetToHtmlText( html, "Dynamic properties, fracture model", m_selectedFractureDynamicProperties() ); - addPropertySetToHtmlText( html, "Static properties, fracture model", m_selectedFractureStaticProperties() ); - addPropertySetToHtmlText( html, "Generated properties, fracture model", m_selectedFractureGeneratedProperties() ); - addPropertySetToHtmlText( html, "Input properties, fracture model", m_selectedFractureInputProperties() ); + if ( m_dataSourceForStatistics() == DataSourceType::GRID_CALCULATION && m_gridCalculation() ) + { + html += "

Grid calculation:

"; + html += "

"; + html += m_gridCalculation()->shortName(); + html += "

"; + } m_selectionSummary = html; } @@ -699,6 +881,17 @@ void RimEclipseStatisticsCase::defineEditorAttribute( const caf::PdmFieldHandle* } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimEclipseStatisticsCase::initializeSelectedTimeSteps() +{ + if ( RimProject::current()->isProjectFileVersionEqualOrOlderThan( "2023.10.0" ) ) + { + selectAllTimeSteps(); + } +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -810,6 +1003,22 @@ void RimEclipseStatisticsCase::computeStatisticsAndUpdateViews() { RicNewViewFeature::addReservoirView( this, nullptr ); } + + if ( reservoirViews.size() == 1 ) + { + // If only one view, set the first result as active + + if ( auto cellResultsData = results( RiaDefines::PorosityModelType::MATRIX_MODEL ) ) + { + auto firstView = reservoirViews[0]; + + std::vector resAddresses = cellResultsData->existingResults(); + if ( firstView && !resAddresses.empty() ) + { + firstView->cellResult()->setFromEclipseResultAddress( resAddresses[0] ); + } + } + } } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/RimEclipseStatisticsCase.h b/ApplicationLibCode/ProjectDataModel/RimEclipseStatisticsCase.h index 1bade5cb64..e9c0a825c2 100644 --- a/ApplicationLibCode/ProjectDataModel/RimEclipseStatisticsCase.h +++ b/ApplicationLibCode/ProjectDataModel/RimEclipseStatisticsCase.h @@ -35,6 +35,7 @@ class RigSimWellData; class RimEclipseResultDefinition; class RimEclipseStatisticsCaseCollection; class RimIdenticalGridCaseGroup; +class RimGridCalculation; //================================================================================================== // @@ -45,6 +46,20 @@ class RimEclipseStatisticsCase : public RimEclipseCase { CAF_PDM_HEADER_INIT; +public: + enum class PercentileCalcType + { + NEAREST_OBSERVATION, + HISTOGRAM_ESTIMATED, + INTERPOLATED_OBSERVATION + }; + + enum class DataSourceType + { + GRID_CALCULATION, + CASE_PROPERTY + }; + public: RimEclipseStatisticsCase(); ~RimEclipseStatisticsCase() override; @@ -63,18 +78,12 @@ class RimEclipseStatisticsCase : public RimEclipseCase RimCaseCollection* parentStatisticsCaseCollection() const; - enum PercentileCalcType - { - NEAREST_OBSERVATION, - HISTOGRAM_ESTIMATED, - INTERPOLATED_OBSERVATION - }; - caf::PdmField m_calculateEditCommand; void populateResultSelectionAfterLoadingGrid(); void setSourceProperties( RiaDefines::ResultCatType propertyType, const std::vector& propertyNames ); + void selectAllTimeSteps(); private: void scheduleACTIVEGeometryRegenOnReservoirViews(); @@ -95,8 +104,16 @@ class RimEclipseStatisticsCase : public RimEclipseCase void loadSimulationWellDataFromSourceCase(); void defineEditorAttribute( const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute ) override; + void initializeSelectedTimeSteps(); private: + caf::PdmField> m_dataSourceForStatistics; + + caf::PdmPtrField m_gridCalculation; + caf::PdmPtrField m_gridCalculationFilterView; + + caf::PdmField> m_selectedTimeSteps; + caf::PdmField> m_resultType; caf::PdmField> m_porosityModel; diff --git a/ApplicationLibCode/ProjectDataModel/RimEclipseStatisticsCaseEvaluator.cpp b/ApplicationLibCode/ProjectDataModel/RimEclipseStatisticsCaseEvaluator.cpp index 2801701125..17f10eb79d 100644 --- a/ApplicationLibCode/ProjectDataModel/RimEclipseStatisticsCaseEvaluator.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimEclipseStatisticsCaseEvaluator.cpp @@ -29,6 +29,7 @@ #include "RigResultModifierFactory.h" #include "RigStatisticsMath.h" +#include "RimEclipseView.h" #include "RimIdenticalGridCaseGroup.h" #include "RimReservoirCellResultsStorage.h" @@ -103,7 +104,7 @@ QString createResultNamePVal( const QString& resultName, double pValPos ) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimEclipseStatisticsCaseEvaluator::evaluateForResults( const QList& resultSpecification ) +void RimEclipseStatisticsCaseEvaluator::evaluateForResults( const QList& resultSpecification, RimEclipseView* filterView ) { CVF_ASSERT( m_destinationCase ); @@ -116,23 +117,23 @@ void RimEclipseStatisticsCaseEvaluator::evaluateForResults( const QList for ( size_t timeIndicesIdx = 0; timeIndicesIdx < m_timeStepIndices.size(); timeIndicesIdx++ ) { - size_t timeStepIdx = m_timeStepIndices[timeIndicesIdx]; + auto timeStepIdx = m_timeStepIndices[timeIndicesIdx]; for ( size_t gridIdx = 0; gridIdx < m_destinationCase->gridCount(); gridIdx++ ) { RigGridBase* grid = m_destinationCase->grid( gridIdx ); - for ( int resSpecIdx = 0; resSpecIdx < resultSpecification.size(); resSpecIdx++ ) + for ( const auto& resSpec : resultSpecification ) { - RiaDefines::PorosityModelType poroModel = resultSpecification[resSpecIdx].m_poroModel; - RiaDefines::ResultCatType resultType = resultSpecification[resSpecIdx].m_resType; - QString resultName = resultSpecification[resSpecIdx].m_resVarName; + RiaDefines::PorosityModelType poroModel = resSpec.m_poroModel; + RiaDefines::ResultCatType resultType = resSpec.m_resType; + QString resultName = resSpec.m_resVarName; size_t activeCellCount = m_destinationCase->activeCellInfo( poroModel )->reservoirActiveCellCount(); if ( activeCellCount == 0 ) continue; - size_t dataAccessTimeStepIndex = timeStepIdx; + auto dataAccessTimeStepIndex = static_cast( timeStepIdx ); // Always evaluate statistics once, and always use time step index zero if ( resultType == RiaDefines::ResultCatType::STATIC_NATIVE ) @@ -145,10 +146,8 @@ void RimEclipseStatisticsCaseEvaluator::evaluateForResults( const QList // Build data access objects for source scalar results cvf::Collection sourceDataAccessList; - for ( size_t caseIdx = 0; caseIdx < m_sourceCases.size(); caseIdx++ ) + for ( RimEclipseCase* sourceCase : m_sourceCases ) { - RimEclipseCase* sourceCase = m_sourceCases.at( caseIdx ); - // Trigger loading of dataset // NB! Many other functions are based on loading of all time steps at the same time // Use this concept carefully @@ -184,27 +183,36 @@ void RimEclipseStatisticsCaseEvaluator::evaluateForResults( const QList statisticalResultNames[PMID] = createResultNamePVal( resultName, m_statisticsConfig.m_pMidPos ); statisticalResultNames[PMAX] = createResultNamePVal( resultName, m_statisticsConfig.m_pMaxPos ); - for ( size_t stIdx = 0; stIdx < statisticalResultNames.size(); ++stIdx ) + for ( const auto& statisticalResultName : statisticalResultNames ) { cvf::ref resultModifier = RigResultModifierFactory::createResultModifier( m_destinationCase, grid->gridIndex(), poroModel, dataAccessTimeStepIndex, - RigEclipseResultAddress( resultType, statisticalResultNames[stIdx] ) ); + RigEclipseResultAddress( resultType, statisticalResultName ) ); destinationDataAccessList.push_back( resultModifier.p() ); } std::vector statParams( STAT_PARAM_COUNT, HUGE_VAL ); std::vector values( sourceDataAccessList.size(), HUGE_VAL ); - int cellCount = static_cast( grid->cellCount() ); + auto cellCount = static_cast( grid->cellCount() ); + + cvf::ref visibility; + if ( filterView ) + { + visibility = filterView->currentTotalCellVisibility(); + } // Loop over the cells in the grid, get the case values, and calculate the cell statistics #pragma omp parallel for schedule( dynamic ) firstprivate( statParams, values ) for ( int cellIdx = 0; cellIdx < cellCount; cellIdx++ ) { size_t reservoirCellIndex = grid->reservoirCellIndex( cellIdx ); + + if ( visibility.notNull() && !visibility->val( reservoirCellIndex ) ) continue; + if ( m_destinationCase->activeCellInfo( poroModel )->isActive( reservoirCellIndex ) ) { // Extract the cell values from each of the cases and assemble them into one vector @@ -245,7 +253,7 @@ void RimEclipseStatisticsCaseEvaluator::evaluateForResults( const QList // Calculate percentiles if ( m_statisticsConfig.m_calculatePercentiles ) { - if ( m_statisticsConfig.m_pValMethod == RimEclipseStatisticsCase::NEAREST_OBSERVATION ) + if ( m_statisticsConfig.m_pValMethod == RimEclipseStatisticsCase::PercentileCalcType::NEAREST_OBSERVATION ) { std::vector pValPoss; pValPoss.push_back( m_statisticsConfig.m_pMinPos ); @@ -259,7 +267,7 @@ void RimEclipseStatisticsCaseEvaluator::evaluateForResults( const QList statParams[PMID] = pVals[1]; statParams[PMAX] = pVals[2]; } - else if ( m_statisticsConfig.m_pValMethod == RimEclipseStatisticsCase::HISTOGRAM_ESTIMATED ) + else if ( m_statisticsConfig.m_pValMethod == RimEclipseStatisticsCase::PercentileCalcType::HISTOGRAM_ESTIMATED ) { std::vector histogram; RigHistogramCalculator histCalc( statParams[MIN], statParams[MAX], 100, &histogram ); @@ -271,7 +279,8 @@ void RimEclipseStatisticsCaseEvaluator::evaluateForResults( const QList statParams[PMAX] = histCalc.calculatePercentil( m_statisticsConfig.m_pMaxPos / 100.0, RigStatisticsMath::PercentileStyle::SWITCHED ); } - else if ( m_statisticsConfig.m_pValMethod == RimEclipseStatisticsCase::INTERPOLATED_OBSERVATION ) + else if ( m_statisticsConfig.m_pValMethod == + RimEclipseStatisticsCase::PercentileCalcType::INTERPOLATED_OBSERVATION ) { std::vector pValPoss; pValPoss.push_back( m_statisticsConfig.m_pMinPos ); @@ -310,14 +319,15 @@ void RimEclipseStatisticsCaseEvaluator::evaluateForResults( const QList // Microsoft note: On Windows, the maximum number of files open at the same time is 512 // http://msdn.microsoft.com/en-us/library/kdfaxaay%28vs.71%29.aspx - for ( size_t caseIdx = 0; caseIdx < m_sourceCases.size(); caseIdx++ ) - { - RimEclipseCase* eclipseCase = m_sourceCases.at( caseIdx ); + std::vector categoriesToExclude; + if ( !m_clearGridCalculationMemory ) categoriesToExclude.push_back( RiaDefines::ResultCatType::GENERATED ); + for ( RimEclipseCase* eclipseCase : m_sourceCases ) + { if ( eclipseCase->reservoirViews.empty() ) { - eclipseCase->results( RiaDefines::PorosityModelType::MATRIX_MODEL )->freeAllocatedResultsData(); - eclipseCase->results( RiaDefines::PorosityModelType::FRACTURE_MODEL )->freeAllocatedResultsData(); + eclipseCase->results( RiaDefines::PorosityModelType::MATRIX_MODEL )->freeAllocatedResultsData( categoriesToExclude, timeStepIdx ); + eclipseCase->results( RiaDefines::PorosityModelType::FRACTURE_MODEL )->freeAllocatedResultsData( categoriesToExclude, timeStepIdx ); } } @@ -330,11 +340,11 @@ void RimEclipseStatisticsCaseEvaluator::evaluateForResults( const QList //-------------------------------------------------------------------------------------------------- void RimEclipseStatisticsCaseEvaluator::addNamedResults( const QList& resultSpecification ) { - for ( int i = 0; i < resultSpecification.size(); i++ ) + for ( const auto& resSpec : resultSpecification ) { - RiaDefines::PorosityModelType poroModel = resultSpecification[i].m_poroModel; - RiaDefines::ResultCatType resultType = resultSpecification[i].m_resType; - QString resultName = resultSpecification[i].m_resVarName; + RiaDefines::PorosityModelType poroModel = resSpec.m_poroModel; + RiaDefines::ResultCatType resultType = resSpec.m_resType; + QString resultName = resSpec.m_resVarName; size_t activeCellCount = m_destinationCase->activeCellInfo( poroModel )->reservoirActiveCellCount(); if ( activeCellCount == 0 ) continue; @@ -347,10 +357,10 @@ void RimEclipseStatisticsCaseEvaluator::addNamedResults( const QList& r // Create new result data structures to contain the statistical values std::vector statisticalResultNames; + statisticalResultNames.push_back( createResultNameMean( resultName ) ); statisticalResultNames.push_back( createResultNameMin( resultName ) ); statisticalResultNames.push_back( createResultNameMax( resultName ) ); statisticalResultNames.push_back( createResultNameSum( resultName ) ); - statisticalResultNames.push_back( createResultNameMean( resultName ) ); statisticalResultNames.push_back( createResultNameDev( resultName ) ); statisticalResultNames.push_back( createResultNameRange( resultName ) ); @@ -361,9 +371,9 @@ void RimEclipseStatisticsCaseEvaluator::addNamedResults( const QList& r statisticalResultNames.push_back( createResultNamePVal( resultName, m_statisticsConfig.m_pMaxPos ) ); } - for ( size_t j = 0; j < statisticalResultNames.size(); ++j ) + for ( const auto& statisticalResultName : statisticalResultNames ) { - addNamedResult( destCellResultsData, resultType, statisticalResultNames[j], activeCellCount ); + addNamedResult( destCellResultsData, resultType, statisticalResultName, activeCellCount ); } } } @@ -372,10 +382,11 @@ void RimEclipseStatisticsCaseEvaluator::addNamedResults( const QList& r /// //-------------------------------------------------------------------------------------------------- RimEclipseStatisticsCaseEvaluator::RimEclipseStatisticsCaseEvaluator( const std::vector& sourceCases, - const std::vector& timeStepIndices, + const std::vector& timeStepIndices, const RimStatisticsConfig& statisticsConfig, RigEclipseCaseData* destinationCase, - RimIdenticalGridCaseGroup* identicalGridCaseGroup ) + RimIdenticalGridCaseGroup* identicalGridCaseGroup, + bool clearGridCalculationMemory ) : m_sourceCases( sourceCases ) , m_statisticsConfig( statisticsConfig ) , m_destinationCase( destinationCase ) @@ -383,6 +394,7 @@ RimEclipseStatisticsCaseEvaluator::RimEclipseStatisticsCaseEvaluator( const std: , m_timeStepIndices( timeStepIndices ) , m_identicalGridCaseGroup( identicalGridCaseGroup ) , m_useZeroAsInactiveCellValue( false ) + , m_clearGridCalculationMemory( clearGridCalculationMemory ) { if ( !sourceCases.empty() ) { diff --git a/ApplicationLibCode/ProjectDataModel/RimEclipseStatisticsCaseEvaluator.h b/ApplicationLibCode/ProjectDataModel/RimEclipseStatisticsCaseEvaluator.h index 7b086d9bd9..fd59666e53 100644 --- a/ApplicationLibCode/ProjectDataModel/RimEclipseStatisticsCaseEvaluator.h +++ b/ApplicationLibCode/ProjectDataModel/RimEclipseStatisticsCaseEvaluator.h @@ -38,7 +38,7 @@ class RimStatisticsConfig , m_pMinPos( 10.0 ) , m_pMidPos( 50.0 ) , m_pMaxPos( 90.0 ) - , m_pValMethod( RimEclipseStatisticsCase::INTERPOLATED_OBSERVATION ) + , m_pValMethod( RimEclipseStatisticsCase::PercentileCalcType::INTERPOLATED_OBSERVATION ) { } @@ -54,10 +54,11 @@ class RimEclipseStatisticsCaseEvaluator { public: RimEclipseStatisticsCaseEvaluator( const std::vector& sourceCases, - const std::vector& timeStepIndices, + const std::vector& timeStepIndices, const RimStatisticsConfig& statisticsConfig, RigEclipseCaseData* destinationCase, - RimIdenticalGridCaseGroup* identicalGridCaseGroup ); + RimIdenticalGridCaseGroup* identicalGridCaseGroup, + bool clearGridCalculationMemory ); struct ResSpec { @@ -80,7 +81,7 @@ class RimEclipseStatisticsCaseEvaluator void useZeroAsValueForInActiveCellsBasedOnUnionOfActiveCells(); - void evaluateForResults( const QList& resultSpecification ); + void evaluateForResults( const QList& resultSpecification, RimEclipseView* filterView ); private: void addNamedResults( const QList& resultSpecification ); @@ -105,11 +106,12 @@ class RimEclipseStatisticsCaseEvaluator private: std::vector m_sourceCases; - std::vector m_timeStepIndices; + std::vector m_timeStepIndices; size_t m_reservoirCellCount; RimStatisticsConfig m_statisticsConfig; RigEclipseCaseData* m_destinationCase; RimIdenticalGridCaseGroup* m_identicalGridCaseGroup; bool m_useZeroAsInactiveCellValue; + bool m_clearGridCalculationMemory; }; diff --git a/ApplicationLibCode/ProjectDataModel/RimEclipseView.cpp b/ApplicationLibCode/ProjectDataModel/RimEclipseView.cpp index 66b72eadd7..53c72285d5 100644 --- a/ApplicationLibCode/ProjectDataModel/RimEclipseView.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimEclipseView.cpp @@ -48,6 +48,7 @@ #include "RimCellEdgeColors.h" #include "RimCellFilterCollection.h" #include "RimEclipseCase.h" +#include "RimEclipseCaseTools.h" #include "RimEclipseCellColors.h" #include "RimEclipseFaultColors.h" #include "RimEclipsePropertyFilter.h" @@ -82,6 +83,7 @@ #include "RimStreamlineInViewCollection.h" #include "RimSurfaceInViewCollection.h" #include "RimTernaryLegendConfig.h" +#include "RimTools.h" #include "RimViewController.h" #include "RimViewLinker.h" #include "RimViewNameConfig.h" @@ -140,6 +142,8 @@ RimEclipseView::RimEclipseView() "EclipseView", "The Eclipse 3d Reservoir View" ); + CAF_PDM_InitFieldNoDefault( &m_customEclipseCase, "CustomEclipseCase", "Custom Case" ); + CAF_PDM_InitScriptableFieldWithScriptKeywordNoDefault( &m_cellResult, "GridCellResult", "CellResult", "Cell Result", ":/CellResult.png" ); m_cellResult = new RimEclipseCellColors(); m_cellResult.uiCapability()->setUiTreeHidden( true ); @@ -378,6 +382,19 @@ void RimEclipseView::setVisibleGridPartsWatertight() } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimEclipseView::propagateEclipseCaseToChildObjects() +{ + auto currentEclipseCase = eclipseCase(); + + cellResult()->setEclipseCase( currentEclipseCase ); + faultResultSettings()->customFaultResult()->setEclipseCase( currentEclipseCase ); + cellFilterCollection()->setCase( currentEclipseCase ); + m_streamlineCollection->setEclipseCase( currentEclipseCase ); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -385,6 +402,20 @@ void RimEclipseView::fieldChangedByUi( const caf::PdmFieldHandle* changedField, { RimGridView::fieldChangedByUi( changedField, oldValue, newValue ); + if ( changedField == &m_customEclipseCase ) + { + propagateEclipseCaseToChildObjects(); + + // Sync with RimReloadCaseTools::updateAll3dViews + loadDataAndUpdate(); + updateGridBoxData(); + updateAnnotationItems(); + + zoomAll(); + + return; + } + if ( changedField == &m_showInvalidCells ) { scheduleGeometryRegen( INACTIVE ); @@ -453,7 +484,7 @@ void RimEclipseView::onCreateDisplayModel() RiuMainWindow::instance()->setResultInfo(QString("RimEclipseView::onCreateDisplayModel() ") + QString::number(callCount++)); #endif - if ( !( m_eclipseCase && m_eclipseCase->eclipseCaseData() ) ) return; + if ( !( eclipseCase() && eclipseCase()->eclipseCaseData() ) ) return; const bool cellFiltersActive = cellFilterCollection()->hasActiveFilters(); const bool propertyFiltersActive = eclipsePropertyFilterCollection()->hasActiveFilters(); @@ -1062,11 +1093,11 @@ void RimEclipseView::onLoadDataAndUpdate() onUpdateScaleTransform(); - if ( m_eclipseCase ) + if ( eclipseCase() ) { - if ( !m_eclipseCase->openReserviorCase() ) + if ( !eclipseCase()->openReserviorCase() ) { - RiaLogging::warning( "Could not open the Eclipse Grid file: \n" + m_eclipseCase->gridFileName() ); + RiaLogging::warning( "Could not open the Eclipse Grid file: \n" + eclipseCase()->gridFileName() ); setEclipseCase( nullptr ); return; } @@ -1278,9 +1309,9 @@ void RimEclipseView::onUpdateDisplayModelVisibility() //-------------------------------------------------------------------------------------------------- RigCaseCellResultsData* RimEclipseView::currentGridCellResults() const { - if ( m_eclipseCase ) + if ( eclipseCase() ) { - return m_eclipseCase->results( cellResult()->porosityModel() ); + return eclipseCase()->results( cellResult()->porosityModel() ); } return nullptr; @@ -1291,9 +1322,9 @@ RigCaseCellResultsData* RimEclipseView::currentGridCellResults() const //-------------------------------------------------------------------------------------------------- const RigActiveCellInfo* RimEclipseView::currentActiveCellInfo() const { - if ( m_eclipseCase && m_eclipseCase->eclipseCaseData() ) + if ( eclipseCase() && eclipseCase()->eclipseCaseData() ) { - return m_eclipseCase->eclipseCaseData()->activeCellInfo( cellResult()->porosityModel() ); + return eclipseCase()->eclipseCaseData()->activeCellInfo( cellResult()->porosityModel() ); } return nullptr; @@ -1367,15 +1398,15 @@ void RimEclipseView::onUpdateLegends() } } - if ( !m_eclipseCase || !nativeOrOverrideViewer() || !m_eclipseCase->eclipseCaseData() ) + if ( !eclipseCase() || !nativeOrOverrideViewer() || !eclipseCase()->eclipseCaseData() ) { return; } - RigEclipseCaseData* eclipseCase = m_eclipseCase->eclipseCaseData(); - CVF_ASSERT( eclipseCase ); + RigEclipseCaseData* eclipseCaseData = eclipseCase()->eclipseCaseData(); + CVF_ASSERT( eclipseCaseData ); - RigCaseCellResultsData* results = eclipseCase->results( cellResult()->porosityModel() ); + RigCaseCellResultsData* results = eclipseCaseData->results( cellResult()->porosityModel() ); CVF_ASSERT( results ); updateLegendRangesTextAndVisibility( cellResult()->legendConfig(), @@ -1535,10 +1566,8 @@ void RimEclipseView::updateLegendRangesTextAndVisibility( RimRegularLegendConfig void RimEclipseView::setEclipseCase( RimEclipseCase* reservoir ) { m_eclipseCase = reservoir; - cellResult()->setEclipseCase( reservoir ); - faultResultSettings()->customFaultResult()->setEclipseCase( reservoir ); - cellFilterCollection()->setCase( reservoir ); - m_streamlineCollection->setEclipseCase( reservoir ); + + propagateEclipseCaseToChildObjects(); } //-------------------------------------------------------------------------------------------------- @@ -1546,6 +1575,8 @@ void RimEclipseView::setEclipseCase( RimEclipseCase* reservoir ) //-------------------------------------------------------------------------------------------------- RimEclipseCase* RimEclipseView::eclipseCase() const { + if ( m_customEclipseCase() != nullptr ) return m_customEclipseCase(); + return m_eclipseCase; } @@ -1564,9 +1595,9 @@ RimEclipseCase* RimEclipseView::eclipseCase() const //-------------------------------------------------------------------------------------------------- void RimEclipseView::syncronizeWellsWithResults() { - if ( !( m_eclipseCase && m_eclipseCase->eclipseCaseData() ) ) return; + if ( !( eclipseCase() && eclipseCase()->eclipseCaseData() ) ) return; - cvf::Collection wellResults = m_eclipseCase->eclipseCaseData()->wellResults(); + cvf::Collection wellResults = eclipseCase()->eclipseCaseData()->wellResults(); std::vector> newWells; @@ -1880,6 +1911,10 @@ void RimEclipseView::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& caf::PdmUiGroup* nameGroup = uiOrdering.addNewGroup( "View Name" ); nameConfig()->uiOrdering( uiConfigName, *nameGroup ); + caf::PdmUiGroup* advancedGroup = uiOrdering.addNewGroup( "Advanced" ); + advancedGroup->setCollapsedByDefault(); + advancedGroup->add( &m_customEclipseCase ); + uiOrdering.skipRemainingFields( true ); } @@ -1949,6 +1984,40 @@ std::set RimEclipseView::allVisibleFaultGeometryTypes() const return faultGeoTypes; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QList RimEclipseView::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions ) +{ + if ( fieldNeedingOptions == &m_customEclipseCase ) + { + QList options; + + options.push_back( caf::PdmOptionItemInfo( "None", nullptr ) ); + + if ( m_eclipseCase && m_eclipseCase->mainGrid() ) + { + auto currentGridCount = m_eclipseCase->mainGrid()->gridCount(); + + for ( auto eclCase : RimEclipseCaseTools::allEclipseGridCases() ) + { + // Find all grid cases with same number of LGRs. If the grid count differs, a crash will happen related to + // RimGridCollection::mainEclipseGrid(). This function is using firstAncestorOrThisOfType() to find the Eclipse case. If the + // custom case in RimEclipseView has a different number of LGRs, a crash will happen + + if ( eclCase && ( eclCase != m_eclipseCase ) && eclCase->mainGrid() && eclCase->mainGrid()->gridCount() == currentGridCount ) + { + options.push_back( caf::PdmOptionItemInfo( eclCase->caseUserDescription(), eclCase, false, eclCase->uiIconProvider() ) ); + } + } + } + + return options; + } + + return RimGridView::calculateValueOptions( fieldNeedingOptions ); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/RimEclipseView.h b/ApplicationLibCode/ProjectDataModel/RimEclipseView.h index 847122b191..75c45ee640 100644 --- a/ApplicationLibCode/ProjectDataModel/RimEclipseView.h +++ b/ApplicationLibCode/ProjectDataModel/RimEclipseView.h @@ -184,6 +184,8 @@ class RimEclipseView : public RimGridView RimPropertyFilterCollection* nativePropertyFilterCollection(); virtual std::set allVisibleFaultGeometryTypes() const; + QList calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions ) override; + private: QString createAutoName() const override; @@ -217,6 +219,8 @@ class RimEclipseView : public RimGridView void setVisibleGridParts( const std::vector& cellSets ); void setVisibleGridPartsWatertight(); + void propagateEclipseCaseToChildObjects(); + protected: cvf::ref m_faultReactVizModel; @@ -241,7 +245,8 @@ class RimEclipseView : public RimGridView caf::PdmChildField m_propertyFilterCollection; caf::PdmPointer m_overridePropertyFilterCollection; - caf::PdmPointer m_eclipseCase; + caf::PdmPointer m_eclipseCase; + caf::PdmPtrField m_customEclipseCase; cvf::ref m_reservoirGridPartManager; cvf::ref m_simWellsPartManager; diff --git a/ApplicationLibCode/ProjectDataModel/RimGridCalculation.cpp b/ApplicationLibCode/ProjectDataModel/RimGridCalculation.cpp index 330a94c65e..6b93ceccf8 100644 --- a/ApplicationLibCode/ProjectDataModel/RimGridCalculation.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimGridCalculation.cpp @@ -19,18 +19,11 @@ #include "RimGridCalculation.h" #include "RiaDefines.h" +#include "RiaGuiApplication.h" #include "RiaLogging.h" #include "RiaPorosityModel.h" #include "RigActiveCellInfo.h" -#include "RimEclipseCase.h" -#include "RimEclipseCellColors.h" -#include "RimEclipseView.h" -#include "RimGridCalculationVariable.h" -#include "RimProject.h" -#include "RimReloadCaseTools.h" -#include "RimTools.h" - #include "RigCaseCellResultsData.h" #include "RigEclipseCaseData.h" #include "RigEclipseResultAddress.h" @@ -38,9 +31,26 @@ #include "RigMainGrid.h" #include "RigResultAccessor.h" #include "RigResultAccessorFactory.h" +#include "RigStatisticsMath.h" + +#include "RimEclipseCase.h" +#include "RimEclipseCaseTools.h" +#include "RimEclipseCellColors.h" +#include "RimEclipseStatisticsCase.h" +#include "RimEclipseView.h" +#include "RimGridCalculationCollection.h" +#include "RimGridCalculationVariable.h" +#include "RimProject.h" +#include "RimReloadCaseTools.h" +#include "RimTools.h" #include "expressionparser/ExpressionParser.h" +#include "cafPdmUiTreeSelectionEditor.h" + +#include +#include + CAF_PDM_SOURCE_INIT( RimGridCalculation, "RimGridCalculation" ); namespace caf @@ -65,7 +75,52 @@ RimGridCalculation::RimGridCalculation() CAF_PDM_InitFieldNoDefault( &m_defaultValueType, "DefaultValueType", "Non-visible Cell Value" ); CAF_PDM_InitField( &m_defaultValue, "DefaultValue", 0.0, "Custom Value" ); CAF_PDM_InitFieldNoDefault( &m_destinationCase, "DestinationCase", "Destination Case" ); + CAF_PDM_InitField( &m_applyToAllCases, "AllDestinationCase", false, "Apply to All Cases" ); CAF_PDM_InitField( &m_defaultPropertyVariableIndex, "DefaultPropertyVariableName", 0, "Property Variable Name" ); + + CAF_PDM_InitFieldNoDefault( &m_selectedTimeSteps, "SelectedTimeSteps", "Time Step Selection" ); + m_selectedTimeSteps.uiCapability()->setUiEditorTypeName( caf::PdmUiTreeSelectionEditor::uiEditorTypeName() ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimGridCalculation::preCalculate() const +{ + if ( RiaGuiApplication::isRunning() && m_applyToAllCases() ) + { + const QString cacheKey = "GridCalculatorMessage"; + + auto cacheValue = RiaApplication::instance()->cacheDataObject( cacheKey ); + if ( cacheValue.isValid() && cacheValue.canConvert() ) + { + return cacheValue.toBool(); + } + + QCheckBox* cb = new QCheckBox( "Don't show this question again" ); + + QMessageBox msgbox; + msgbox.setWindowTitle( "Grid Property Calculator" ); + msgbox.setText( "Calculation will be executed on all grid model cases.\nDo you want to continue?\n" ); + msgbox.setIcon( QMessageBox::Icon::Question ); + msgbox.addButton( QMessageBox::Yes ); + msgbox.addButton( QMessageBox::No ); + msgbox.setDefaultButton( QMessageBox::Yes ); + msgbox.setCheckBox( cb ); + + auto reply = msgbox.exec(); + + bool returnValue = ( reply == QMessageBox::Yes ); + + if ( cb->isChecked() && returnValue ) + { + RiaApplication::instance()->setCacheDataObject( cacheKey, returnValue ); + } + + return returnValue; + } + + return true; } //-------------------------------------------------------------------------------------------------- @@ -85,112 +140,62 @@ RimGridCalculationVariable* RimGridCalculation::createVariable() //-------------------------------------------------------------------------------------------------- bool RimGridCalculation::calculate() { - QString leftHandSideVariableName = RimGridCalculation::findLeftHandSide( m_expression ); - - RimEclipseCase* eclipseCase = outputEclipseCase(); - if ( !eclipseCase ) + for ( auto calculationCase : outputEclipseCases() ) { - RiaLogging::errorInMessageBox( nullptr, - "Grid Property Calculator", - QString( "No case found for calculation : %1" ).arg( leftHandSideVariableName ) ); - return false; - } + if ( !calculationCase ) continue; - auto [isOk, errorMessage] = validateVariables(); - if ( !isOk ) - { - RiaLogging::errorInMessageBox( nullptr, "Grid Property Calculator", errorMessage ); - return false; - } - - for ( auto variableCase : inputCases() ) - { - if ( !eclipseCase->isGridSizeEqualTo( variableCase ) ) + for ( auto inputCase : inputCases() ) { - QString msg = "Detected IJK mismatch between input cases and destination case. All grid " - "cases must have identical IJK sizes."; - RiaLogging::errorInMessageBox( nullptr, "Grid Property Calculator", msg ); - return false; + if ( !calculationCase->isGridSizeEqualTo( inputCase ) ) + { + QString msg = "Detected IJK mismatch between input cases and destination case. All grid " + "cases must have identical IJK sizes."; + RiaLogging::errorInMessageBox( nullptr, "Grid Property Calculator", msg ); + return false; + } } } - auto porosityModel = RiaDefines::PorosityModelType::MATRIX_MODEL; - - RigEclipseResultAddress resAddr( RiaDefines::ResultCatType::GENERATED, leftHandSideVariableName ); - - if ( !eclipseCase->results( porosityModel )->ensureKnownResultLoaded( resAddr ) ) + cvf::UByteArray* inputValueVisibilityFilter = nullptr; + if ( m_cellFilterView() ) { - bool needsToBeStored = false; - eclipseCase->results( porosityModel )->createResultEntry( resAddr, needsToBeStored ); + inputValueVisibilityFilter = m_cellFilterView()->currentTotalCellVisibility().p(); } - eclipseCase->results( porosityModel )->clearScalarResult( resAddr ); - - // If an input grid is present, max time step count is zero. Make sure the time step count for the calculation is - // always 1 or more. - const size_t timeStepCount = std::max( size_t( 1 ), eclipseCase->results( porosityModel )->maxTimeStepCount() ); + std::optional> timeSteps = std::nullopt; - std::vector>* scalarResultFrames = - eclipseCase->results( porosityModel )->modifiableCellScalarResultTimesteps( resAddr ); - scalarResultFrames->resize( timeStepCount ); - - for ( size_t tsId = 0; tsId < timeStepCount; tsId++ ) + if ( !m_selectedTimeSteps().empty() ) { - std::vector> values; - for ( size_t i = 0; i < m_variables.size(); i++ ) - { - RimGridCalculationVariable* v = dynamic_cast( m_variables[i] ); - CAF_ASSERT( v != nullptr ); - values.push_back( getInputVectorForVariable( v, tsId, porosityModel, outputEclipseCase() ) ); - } - - ExpressionParser parser; - for ( size_t i = 0; i < m_variables.size(); i++ ) - { - RimGridCalculationVariable* v = dynamic_cast( m_variables[i] ); - CAF_ASSERT( v != nullptr ); - parser.assignVector( v->name(), values[i] ); - } - - std::vector resultValues; - resultValues.resize( values[0].size() ); - parser.assignVector( leftHandSideVariableName, resultValues ); - - QString errorText; - bool evaluatedOk = parser.expandIfStatementsAndEvaluate( m_expression, &errorText ); - - if ( evaluatedOk ) + std::vector tmp; + for ( auto t : m_selectedTimeSteps() ) { - if ( m_cellFilterView() ) - { - filterResults( m_cellFilterView(), values, m_defaultValueType(), m_defaultValue(), resultValues, porosityModel, outputEclipseCase() ); - } - - scalarResultFrames->at( tsId ) = resultValues; - - m_isDirty = false; + tmp.push_back( static_cast( t ) ); } - else - { - QString s = "The following error message was received from the parser library : \n\n"; - s += errorText; - RiaLogging::errorInMessageBox( nullptr, "Grid Property Calculator", s ); - return false; - } + timeSteps = tmp; } - eclipseCase->updateResultAddressCollection(); - - return true; + bool evaluateDependentCalculations = true; + return calculateForCases( outputEclipseCases(), inputValueVisibilityFilter, timeSteps, evaluateDependentCalculations ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RimEclipseCase* RimGridCalculation::outputEclipseCase() const +std::vector RimGridCalculation::outputEclipseCases() const { - return m_destinationCase; + if ( m_applyToAllCases ) + { + // Find all Eclipse cases suitable for grid calculations. This includes all single grid cases and source cases in a grid case group. + // Exclude the statistics cases, as it is not possible to use them in a grid calculations. + // + // Note that data read from file can be released from memory when statistics for a time step is calculated. See + // RimEclipseStatisticsCaseEvaluator::evaluateForResults() + + return RimEclipseCaseTools::allEclipseGridCases(); + } + + return { m_destinationCase }; } //-------------------------------------------------------------------------------------------------- @@ -230,6 +235,13 @@ void RimGridCalculation::defineUiOrdering( QString uiConfigName, caf::PdmUiOrder uiOrdering.add( &m_destinationCase ); + uiOrdering.add( &m_applyToAllCases ); + if ( !allSourceCasesAreEqualToDestinationCase() ) + { + m_applyToAllCases = false; + } + m_applyToAllCases.uiCapability()->setUiReadOnly( !allSourceCasesAreEqualToDestinationCase() ); + caf::PdmUiGroup* filterGroup = uiOrdering.addNewGroup( "Cell Filter" ); filterGroup->setCollapsedByDefault(); filterGroup->add( &m_cellFilterView ); @@ -244,6 +256,10 @@ void RimGridCalculation::defineUiOrdering( QString uiConfigName, caf::PdmUiOrder filterGroup->add( &m_defaultValue ); } + caf::PdmUiGroup* timeStepGroup = uiOrdering.addNewGroup( "Time Step Filter" ); + timeStepGroup->setCollapsedByDefault(); + timeStepGroup->add( &m_selectedTimeSteps ); + uiOrdering.skipRemainingFields(); } @@ -278,27 +294,19 @@ QList RimGridCalculation::calculateValueOptions( const c } else if ( fieldNeedingOptions == &m_destinationCase ) { - if ( inputCases().empty() ) + RimEclipseCase* firstInputCase = nullptr; + + if ( !inputCases().empty() ) { - RimTools::eclipseCaseOptionItems( &options ); + firstInputCase = inputCases()[0]; } - else - { - RimEclipseCase* firstInputCase = inputCases()[0]; - RimProject* proj = RimProject::current(); - if ( proj ) - { - std::vector cases = proj->allGridCases(); - for ( RimCase* c : cases ) - { - auto* eclipseCase = dynamic_cast( c ); - if ( !eclipseCase ) continue; - if ( !firstInputCase->isGridSizeEqualTo( eclipseCase ) ) continue; + for ( auto eclipseCase : RimEclipseCaseTools::allEclipseGridCases() ) + { + if ( !eclipseCase ) continue; + if ( firstInputCase && !firstInputCase->isGridSizeEqualTo( eclipseCase ) ) continue; - options.push_back( caf::PdmOptionItemInfo( c->caseUserDescription(), c, false, c->uiIconProvider() ) ); - } - } + options.push_back( caf::PdmOptionItemInfo( eclipseCase->caseUserDescription(), eclipseCase, false, eclipseCase->uiIconProvider() ) ); } options.push_front( caf::PdmOptionItemInfo( "None", nullptr ) ); @@ -313,6 +321,23 @@ QList RimGridCalculation::calculateValueOptions( const c options.push_back( caf::PdmOptionItemInfo( optionText, i ) ); } } + else if ( &m_selectedTimeSteps == fieldNeedingOptions ) + { + RimEclipseCase* firstEclipseCase = nullptr; + if ( !inputCases().empty() ) firstEclipseCase = inputCases().front(); + + if ( firstEclipseCase ) + { + const auto timeStepStrings = firstEclipseCase->timeStepStrings(); + + int index = 0; + for ( const auto& text : timeStepStrings ) + { + options.push_back( caf::PdmOptionItemInfo( text, index++ ) ); + } + } + } + return options; } @@ -338,16 +363,39 @@ void RimGridCalculation::initAfterRead() //-------------------------------------------------------------------------------------------------- void RimGridCalculation::onVariableUpdated( const SignalEmitter* emitter ) { - if ( m_destinationCase == nullptr ) + if ( auto variable = dynamic_cast( emitter ) ) { - auto variable = dynamic_cast( emitter ); - if ( variable && variable->eclipseCase() ) + if ( auto variableCase = variable->eclipseCase() ) { - m_destinationCase = variable->eclipseCase(); + if ( !m_destinationCase || !m_destinationCase->isGridSizeEqualTo( variableCase ) ) + { + m_destinationCase = variableCase; + } + } + } - updateConnectedEditors(); + updateConnectedEditors(); + + variableUpdated.send(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimGridCalculation::allSourceCasesAreEqualToDestinationCase() const +{ + if ( m_destinationCase() == nullptr ) return false; + + for ( const auto& variable : m_variables ) + { + auto gridVar = dynamic_cast( variable.p() ); + if ( gridVar ) + { + if ( gridVar->eclipseCase() != m_destinationCase() ) return false; } } + + return true; } //-------------------------------------------------------------------------------------------------- @@ -363,14 +411,20 @@ RigEclipseResultAddress RimGridCalculation::outputAddress() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::vector RimGridCalculation::getInputVectorForVariable( RimGridCalculationVariable* v, - size_t tsId, - RiaDefines::PorosityModelType porosityModel, - RimEclipseCase* outputEclipseCase ) const +std::vector RimGridCalculation::getDataForVariable( RimGridCalculationVariable* variable, + size_t tsId, + RiaDefines::PorosityModelType porosityModel, + RimEclipseCase* destinationCase, + bool useDataFromDestinationCase ) const { - int timeStep = v->timeStep(); + // The data can be taken from the destination case or from the calculation variable. + auto eclipseCase = useDataFromDestinationCase ? destinationCase : variable->eclipseCase(); + + if ( !eclipseCase ) return {}; - auto resultCategoryType = v->resultCategoryType(); + int timeStep = variable->timeStep(); + + auto resultCategoryType = variable->resultCategoryType(); // General case is to use the data from the given time step size_t timeStepToUse = tsId; @@ -386,35 +440,28 @@ std::vector RimGridCalculation::getInputVectorForVariable( RimGridCalcul timeStepToUse = timeStep; } - RigEclipseResultAddress resAddr( resultCategoryType, v->resultVariable() ); + RigEclipseResultAddress resAddr( resultCategoryType, variable->resultVariable() ); - auto mainGrid = v->eclipseCase()->mainGrid(); - size_t maxGridCount = mainGrid->gridCount(); + auto eclipseCaseData = eclipseCase->eclipseCaseData(); + auto rigCaseCellResultsData = eclipseCaseData->results( porosityModel ); + if ( !rigCaseCellResultsData->ensureKnownResultLoaded( resAddr ) ) return {}; - auto activeCellInfo = outputEclipseCase->eclipseCaseData()->activeCellInfo( porosityModel ); - size_t cellCount = activeCellInfo->reservoirActiveCellCount(); + // Active cell info must always be retrieved from the destination case, as the returned vector must be of the same size as number of + // active cells in the destination case. + auto activeCellInfoDestination = destinationCase->eclipseCaseData()->activeCellInfo( porosityModel ); + auto activeReservoirCells = activeCellInfoDestination->activeReservoirCellIndices(); - std::vector inputValues( cellCount ); - for ( size_t gridIdx = 0; gridIdx < maxGridCount; ++gridIdx ) - { - auto grid = mainGrid->gridByIndex( gridIdx ); + std::vector values( activeCellInfoDestination->activeReservoirCellIndices().size() ); - cvf::ref sourceResultAccessor = - RigResultAccessorFactory::createFromResultAddress( v->eclipseCase()->eclipseCaseData(), gridIdx, porosityModel, timeStepToUse, resAddr ); + auto resultAccessor = RigResultAccessorFactory::createFromResultAddress( eclipseCaseData, 0, porosityModel, timeStepToUse, resAddr ); #pragma omp parallel for - for ( int localGridCellIdx = 0; localGridCellIdx < static_cast( grid->cellCount() ); localGridCellIdx++ ) - { - const size_t reservoirCellIndex = grid->reservoirCellIndex( localGridCellIdx ); - if ( activeCellInfo->isActive( reservoirCellIndex ) ) - { - size_t cellResultIndex = activeCellInfo->cellResultIndex( reservoirCellIndex ); - inputValues[cellResultIndex] = sourceResultAccessor->cellScalar( localGridCellIdx ); - } - } + for ( int i = 0; i < static_cast( activeReservoirCells.size() ); i++ ) + { + values[i] = resultAccessor->cellScalarGlobIdx( activeReservoirCells[i] ); } - return inputValues; + return values; } //-------------------------------------------------------------------------------------------------- @@ -503,10 +550,12 @@ void RimGridCalculation::filterResults( RimGridView* //-------------------------------------------------------------------------------------------------- void RimGridCalculation::updateDependentObjects() { - RimEclipseCase* eclipseCase = outputEclipseCase(); - if ( eclipseCase ) + for ( RimEclipseCase* eclipseCase : outputEclipseCases() ) { - RimReloadCaseTools::updateAll3dViews( eclipseCase ); + if ( eclipseCase ) + { + RimReloadCaseTools::updateAll3dViews( eclipseCase ); + } } } @@ -521,23 +570,293 @@ void RimGridCalculation::removeDependentObjects() RigEclipseResultAddress resAddr( RiaDefines::ResultCatType::GENERATED, leftHandSideVariableName ); - RimEclipseCase* eclipseCase = outputEclipseCase(); - if ( eclipseCase ) + for ( RimEclipseCase* eclipseCase : outputEclipseCases() ) { - // Select "None" result if the result that is being removed were displayed in a view. - for ( auto v : eclipseCase->reservoirViews() ) + if ( eclipseCase ) { - if ( v->cellResult()->resultType() == resAddr.resultCatType() && v->cellResult()->resultVariable() == resAddr.resultName() ) + // Select "None" result if the result that is being removed were displayed in a view. + for ( auto v : eclipseCase->reservoirViews() ) { - v->cellResult()->setResultType( RiaDefines::ResultCatType::GENERATED ); - v->cellResult()->setResultVariable( "None" ); + if ( v->cellResult()->resultType() == resAddr.resultCatType() && v->cellResult()->resultVariable() == resAddr.resultName() ) + { + v->cellResult()->setResultType( RiaDefines::ResultCatType::GENERATED ); + v->cellResult()->setResultVariable( "None" ); + } } + + eclipseCase->results( porosityModel )->clearScalarResult( resAddr ); + eclipseCase->results( porosityModel )->setRemovedTagOnGeneratedResult( resAddr ); + + RimReloadCaseTools::updateAll3dViews( eclipseCase ); } + } +} - eclipseCase->results( porosityModel )->clearScalarResult( resAddr ); - eclipseCase->results( porosityModel )->setRemovedTagOnGeneratedResult( resAddr ); +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimGridCalculation::calculateForCases( const std::vector& calculationCases, + cvf::UByteArray* inputValueVisibilityFilter, + std::optional> timeSteps, + bool evaluateDependentCalculations ) +{ + if ( calculationCases.empty() ) return true; + + if ( evaluateDependentCalculations ) findAndEvaluateDependentCalculations( calculationCases, inputValueVisibilityFilter, timeSteps ); + + QString leftHandSideVariableName = RimGridCalculation::findLeftHandSide( m_expression ); - RimReloadCaseTools::updateAll3dViews( eclipseCase ); + auto [isOk, errorMessage] = validateVariables(); + if ( !isOk ) + { + RiaLogging::errorInMessageBox( nullptr, "Grid Property Calculator", errorMessage ); + return false; + } + + const bool isMultipleCasesPresent = calculationCases.size() > 1; + const bool hasAggregationExpression = m_expression().contains( "sum" ) || m_expression().contains( "avg" ) || + m_expression().contains( "min" ) || m_expression().contains( "max" ) || + m_expression().contains( "count" ); + + if ( isMultipleCasesPresent ) + { + QString txt = "Starting calculation '" + description() + "' for " + QString::number( calculationCases.size() ) + " cases."; + RiaLogging::info( txt ); + + if ( hasAggregationExpression ) + { + RiaLogging::info( QString( " Detected aggregated value in expression '%1'." ).arg( m_expression() ) ); + RiaLogging::info( QString( " Aggregated value per realization is displayed in one column per time step." ) ); + } + } + + std::vector> allAggregatedValues; + + bool anyErrorsDetected = false; + for ( RimEclipseCase* calculationCase : calculationCases ) + { + if ( !calculationCase ) + { + RiaLogging::errorInMessageBox( nullptr, + "Grid Property Calculator", + QString( "No case found for calculation : %1" ).arg( leftHandSideVariableName ) ); + anyErrorsDetected = true; + continue; + } + + auto porosityModel = RiaDefines::PorosityModelType::MATRIX_MODEL; + + RigEclipseResultAddress resAddr( RiaDefines::ResultCatType::GENERATED, leftHandSideVariableName ); + + if ( !calculationCase->results( porosityModel )->ensureKnownResultLoaded( resAddr ) ) + { + bool needsToBeStored = false; + calculationCase->results( porosityModel )->createResultEntry( resAddr, needsToBeStored ); + } + + calculationCase->results( porosityModel )->clearScalarResult( resAddr ); + + // If an input grid is present, max time step count is zero. Make sure the time step count for the calculation is + // always 1 or more. + const size_t timeStepCount = std::max( size_t( 1 ), calculationCase->results( porosityModel )->maxTimeStepCount() ); + + if ( calculationCase == calculationCases.front() && hasAggregationExpression ) + { + // Print time header + + auto timeStepStrings = calculationCase->timeStepStrings(); + + QString timeHeader; + for ( size_t tsId = 0; tsId < timeStepCount; tsId++ ) + { + // Skip time steps that are not in the list of time steps to calculate + if ( timeSteps && std::find( timeSteps->begin(), timeSteps->end(), tsId ) == timeSteps->end() ) continue; + + timeHeader += "\t"; + auto index = static_cast( tsId ); + + if ( index < timeStepStrings.size() ) + { + timeHeader += timeStepStrings.at( static_cast( tsId ) ); + } + else + timeHeader += "Undefined"; + } + RiaLogging::info( timeHeader ); + } + + std::vector>* scalarResultFrames = + calculationCase->results( porosityModel )->modifiableCellScalarResultTimesteps( resAddr ); + scalarResultFrames->resize( timeStepCount ); + + std::vector aggregatedValuesOneTimeStep; + + for ( size_t tsId = 0; tsId < timeStepCount; tsId++ ) + { + // Skip time steps that are not in the list of time steps to calculate + if ( timeSteps && std::find( timeSteps->begin(), timeSteps->end(), tsId ) == timeSteps->end() ) continue; + + std::vector> dataForAllVariables; + for ( size_t i = 0; i < m_variables.size(); i++ ) + { + RimGridCalculationVariable* v = dynamic_cast( m_variables[i] ); + CAF_ASSERT( v != nullptr ); + + bool useDataFromDestinationCase = ( v->eclipseCase() == m_destinationCase ); + + auto dataForVariable = getDataForVariable( v, tsId, porosityModel, calculationCase, useDataFromDestinationCase ); + if ( dataForVariable.empty() ) + { + RiaLogging::error( QString( " No data found for variable '%1'." ).arg( v->name() ) ); + } + else if ( inputValueVisibilityFilter ) + { + const double defaultValue = 0.0; + replaceFilteredValuesWithDefaultValue( defaultValue, inputValueVisibilityFilter, dataForVariable, porosityModel, calculationCase ); + } + + dataForAllVariables.push_back( dataForVariable ); + } + + ExpressionParser parser; + for ( size_t i = 0; i < m_variables.size(); i++ ) + { + RimGridCalculationVariable* v = dynamic_cast( m_variables[i] ); + CAF_ASSERT( v != nullptr ); + parser.assignVector( v->name(), dataForAllVariables[i] ); + } + + std::vector resultValues; + resultValues.resize( dataForAllVariables[0].size() ); + parser.assignVector( leftHandSideVariableName, resultValues ); + + QString errorText; + bool evaluatedOk = parser.expandIfStatementsAndEvaluate( m_expression, &errorText ); + + if ( evaluatedOk ) + { + if ( hasAggregationExpression ) + { + auto it = + std::find_if( resultValues.begin(), resultValues.end(), []( double v ) { return ( !std::isnan( v ) && v != 0.0 ); } ); + if ( it != resultValues.end() ) + { + aggregatedValuesOneTimeStep.push_back( *it ); + } + else + { + aggregatedValuesOneTimeStep.push_back( 0.0 ); + } + } + + if ( m_cellFilterView() && !resultValues.empty() ) + { + filterResults( m_cellFilterView(), + dataForAllVariables, + m_defaultValueType(), + m_defaultValue(), + resultValues, + porosityModel, + calculationCase ); + } + + scalarResultFrames->at( tsId ) = resultValues; + + m_isDirty = false; + } + else + { + QString s = "The following error message was received from the parser library : \n\n"; + s += errorText; + + RiaLogging::errorInMessageBox( nullptr, "Grid Property Calculator", s ); + return false; + } + + calculationCase->updateResultAddressCollection(); + } + + if ( hasAggregationExpression ) + { + QString txt = " " + calculationCase->caseUserDescription(); + + for ( auto v : aggregatedValuesOneTimeStep ) + { + txt += "\t" + QString::number( v ); + } + + allAggregatedValues.push_back( aggregatedValuesOneTimeStep ); + + RiaLogging::info( txt ); + } + } + + if ( isMultipleCasesPresent ) + { + auto [anyError, statisticsText] = createStatisticsText( allAggregatedValues ); + if ( anyError ) + { + anyErrorsDetected = true; + } + else if ( !statisticsText.empty() ) + { + RiaLogging::info( " Statistics" ); + for ( const auto& txt : statisticsText ) + { + RiaLogging::info( txt ); + } + } + + QString txt = "Completed calculation '" + description() + "' for " + QString::number( calculationCases.size() ) + " cases."; + RiaLogging::info( txt ); + } + + return !anyErrorsDetected; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimGridCalculation::findAndEvaluateDependentCalculations( const std::vector& calculationCases, + cvf::UByteArray* inputValueVisibilityFilter, + std::optional> timeSteps ) +{ + auto proj = RimProject::current(); + auto calcColl = proj->gridCalculationCollection(); + + auto dependentCalculations = calcColl->dependentCalculations( this ); + for ( auto dependentCalc : dependentCalculations ) + { + if ( dependentCalc == this ) continue; + + // Propagate the settings for this calculation to the dependent calculation. This will allow changes on top level calculation to be + // propagated to dependent calculations automatically. Do not trigger findAndEvaluateDependentCalculations() recursively, as all + // dependent calculations are traversed in this function. + + bool evaluateDependentCalculations = false; + dependentCalc->calculateForCases( calculationCases, inputValueVisibilityFilter, timeSteps, evaluateDependentCalculations ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimGridCalculation::assignEclipseCaseForNullPointers( RimEclipseCase* eclipseCase ) +{ + if ( m_destinationCase() == nullptr ) + { + m_destinationCase = eclipseCase; + } + + for ( auto v : m_variables ) + { + if ( auto gridVar = dynamic_cast( v.p() ) ) + { + if ( gridVar->eclipseCase() == nullptr ) + { + gridVar->setEclipseCase( eclipseCase ); + } + } } } @@ -593,3 +912,92 @@ void RimGridCalculation::onChildrenUpdated( caf::PdmChildArrayFieldHandle* child } } } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::pair RimGridCalculation::createStatisticsText( const std::vector>& values ) +{ + bool anyErrorsDetected = false; + QStringList statisticsText; + + if ( values.empty() ) return { anyErrorsDetected, statisticsText }; + + size_t size = values.front().size(); + for ( const auto& aggregatedVector : values ) + { + if ( aggregatedVector.size() != size ) + { + QString msg = "Detected mismatch in number of time steps for aggregated values. All grid " + "cases must have identical number of time steps."; + RiaLogging::error( msg ); + anyErrorsDetected = true; + return { anyErrorsDetected, statisticsText }; + } + } + + std::vector minValues; + std::vector p90Values; + std::vector p50Values; + std::vector avgValues; + std::vector p10Values; + std::vector maxValues; + + for ( size_t timeIdx = 0; timeIdx < values.front().size(); timeIdx++ ) + { + std::vector valuesForTimeStep; + + for ( auto v : values ) + { + valuesForTimeStep.push_back( v[timeIdx] ); + } + + // Required to have minimum 8 values to calculate statistics + if ( valuesForTimeStep.size() < 8 ) continue; + + double p90 = std::numeric_limits::infinity(); + double p50 = std::numeric_limits::infinity(); + double avg = std::numeric_limits::infinity(); + double p10 = std::numeric_limits::infinity(); + + auto [min, max] = std::minmax_element( valuesForTimeStep.begin(), valuesForTimeStep.end() ); + + RigStatisticsMath::calculateStatisticsCurves( valuesForTimeStep, &p10, &p50, &p90, &avg, RigStatisticsMath::PercentileStyle::SWITCHED ); + + minValues.push_back( *min ); + p90Values.push_back( p90 ); + p50Values.push_back( p50 ); + avgValues.push_back( avg ); + p10Values.push_back( p10 ); + maxValues.push_back( *max ); + } + + if ( !minValues.empty() ) + { + QString minTxt = " Minimum"; + QString p90Txt = " P90 "; + QString p50Txt = " P50 "; + QString avgTxt = " Mean "; + QString p10Txt = " P10 "; + QString maxTxt = " Maximum"; + + for ( size_t timeIdx = 0; timeIdx < p10Values.size(); timeIdx++ ) + { + minTxt += "\t" + QString::number( minValues[timeIdx] ); + p90Txt += "\t" + QString::number( p90Values[timeIdx] ); + p50Txt += "\t" + QString::number( p50Values[timeIdx] ); + avgTxt += "\t" + QString::number( avgValues[timeIdx] ); + p10Txt += "\t" + QString::number( p10Values[timeIdx] ); + maxTxt += "\t" + QString::number( maxValues[timeIdx] ); + } + + statisticsText.push_back( minTxt ); + statisticsText.push_back( p90Txt ); + statisticsText.push_back( p50Txt ); + statisticsText.push_back( avgTxt ); + statisticsText.push_back( p10Txt ); + statisticsText.push_back( maxTxt ); + } + + return { anyErrorsDetected, statisticsText }; +} diff --git a/ApplicationLibCode/ProjectDataModel/RimGridCalculation.h b/ApplicationLibCode/ProjectDataModel/RimGridCalculation.h index 87cfb999bb..9a922da6c1 100644 --- a/ApplicationLibCode/ProjectDataModel/RimGridCalculation.h +++ b/ApplicationLibCode/ProjectDataModel/RimGridCalculation.h @@ -25,6 +25,8 @@ #include "cafSignal.h" #include "cvfArray.h" +#include + class RimEclipseCase; class RimGridView; class RigEclipseResultAddress; @@ -47,25 +49,39 @@ class RimGridCalculation : public RimUserDefinedCalculation RimGridCalculation(); + bool preCalculate() const override; bool calculate() override; + void updateDependentObjects() override; void removeDependentObjects() override; - RimEclipseCase* outputEclipseCase() const; - RigEclipseResultAddress outputAddress() const; + std::vector outputEclipseCases() const; + RigEclipseResultAddress outputAddress() const; + bool calculateForCases( const std::vector& calculationCases, + cvf::UByteArray* inputValueVisibilityFilter, + std::optional> timeSteps, + bool evaluateDependentCalculations ); + + void findAndEvaluateDependentCalculations( const std::vector& calculationCases, + cvf::UByteArray* inputValueVisibilityFilter, + std::optional> timeSteps ); + + void assignEclipseCaseForNullPointers( RimEclipseCase* eclipseCase ); std::vector inputCases() const; + RimGridCalculationVariable* createVariable() override; + protected: void onChildrenUpdated( caf::PdmChildArrayFieldHandle* childArray, std::vector& updatedObjects ) override; - RimGridCalculationVariable* createVariable() override; - std::pair validateVariables(); + std::pair validateVariables(); - std::vector getInputVectorForVariable( RimGridCalculationVariable* v, - size_t tsId, - RiaDefines::PorosityModelType porosityModel, - RimEclipseCase* outputEclipseCase ) const; + std::vector getDataForVariable( RimGridCalculationVariable* variable, + size_t tsId, + RiaDefines::PorosityModelType porosityModel, + RimEclipseCase* destinationCase, + bool useDataFromDestinationCase ) const; void filterResults( RimGridView* cellFilterView, const std::vector>& values, @@ -96,11 +112,18 @@ class RimGridCalculation : public RimUserDefinedCalculation private: void onVariableUpdated( const SignalEmitter* emitter ); + bool allSourceCasesAreEqualToDestinationCase() const; + + static std::pair createStatisticsText( const std::vector>& values ); private: caf::PdmPtrField m_cellFilterView; caf::PdmField> m_defaultValueType; caf::PdmField m_defaultValue; caf::PdmPtrField m_destinationCase; - caf::PdmField m_defaultPropertyVariableIndex; + caf::PdmField m_applyToAllCases; + + caf::PdmField> m_selectedTimeSteps; + + caf::PdmField m_defaultPropertyVariableIndex; }; diff --git a/ApplicationLibCode/ProjectDataModel/RimGridCalculationCollection.cpp b/ApplicationLibCode/ProjectDataModel/RimGridCalculationCollection.cpp index 7a1367ac39..3a85a89e6d 100644 --- a/ApplicationLibCode/ProjectDataModel/RimGridCalculationCollection.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimGridCalculationCollection.cpp @@ -57,14 +57,14 @@ std::vector RimGridCalculationCollection::sortedGridCalcula // Check if source calculation is depending on other. Will check one level dependency. auto isSourceDependingOnOther = []( const RimGridCalculation* source, const RimGridCalculation* other ) -> bool { - auto outputCase = source->outputEclipseCase(); - auto outputAdr = source->outputAddress(); + auto outputCases = source->outputEclipseCases(); + auto outputAdr = source->outputAddress(); for ( auto v : other->allVariables() ) { auto gridVariable = dynamic_cast( v ); - if ( gridVariable->eclipseCase() == outputCase && outputAdr.resultCatType() == gridVariable->resultCategoryType() && - outputAdr.resultName() == gridVariable->resultVariable() ) + if ( std::find( outputCases.begin(), outputCases.end(), gridVariable->eclipseCase() ) != outputCases.end() && + outputAdr.resultCatType() == gridVariable->resultCategoryType() && outputAdr.resultName() == gridVariable->resultVariable() ) { return true; } @@ -94,6 +94,22 @@ std::vector RimGridCalculationCollection::sortedGridCalcula return sortedCalculations; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RimGridCalculationCollection::dependentCalculations( RimGridCalculation* sourceCalculation ) const +{ + // Find all dependent grid calculations recursively. The ordering of calculations is least dependent first. + + std::vector calculations; + + if ( !dependentCalculationsRecursively( sourceCalculation, calculations ) ) return {}; + + std::reverse( calculations.begin(), calculations.end() ); + + return calculations; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -102,6 +118,49 @@ void RimGridCalculationCollection::rebuildCaseMetaData() ensureValidCalculationIds(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimGridCalculation* RimGridCalculationCollection::findCalculation( const QString& calculationName ) const +{ + for ( auto userCalculation : calculations() ) + { + auto gridCalculation = dynamic_cast( userCalculation ); + if ( gridCalculation && gridCalculation->shortName() == calculationName ) return gridCalculation; + } + + return nullptr; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimGridCalculationCollection::dependentCalculationsRecursively( RimGridCalculation* sourceCalculation, + std::vector& calculations ) const +{ + if ( std::find( calculations.begin(), calculations.end(), sourceCalculation ) != calculations.end() ) + { + RiaLogging::error( "Detected circular dependency for " + sourceCalculation->description() ); + return false; + } + + calculations.push_back( sourceCalculation ); + + for ( auto v : sourceCalculation->allVariables() ) + { + auto gridVariable = dynamic_cast( v ); + if ( gridVariable->resultCategoryType() == RiaDefines::ResultCatType::GENERATED ) + { + if ( auto other = findCalculation( gridVariable->resultVariable() ) ) + { + if ( !dependentCalculationsRecursively( other, calculations ) ) return false; + } + } + } + + return true; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/RimGridCalculationCollection.h b/ApplicationLibCode/ProjectDataModel/RimGridCalculationCollection.h index 03a767837a..bc57397e43 100644 --- a/ApplicationLibCode/ProjectDataModel/RimGridCalculationCollection.h +++ b/ApplicationLibCode/ProjectDataModel/RimGridCalculationCollection.h @@ -36,7 +36,11 @@ class RimGridCalculationCollection : public RimUserDefinedCalculationCollection RimGridCalculation* createCalculation() const override; std::vector sortedGridCalculations() const; + std::vector dependentCalculations( RimGridCalculation* sourceCalculation ) const; private: + RimGridCalculation* findCalculation( const QString& calculationName ) const; + bool dependentCalculationsRecursively( RimGridCalculation* sourceCalculation, std::vector& calculations ) const; + void initAfterRead() override; }; diff --git a/ApplicationLibCode/ProjectDataModel/RimGridCalculationVariable.cpp b/ApplicationLibCode/ProjectDataModel/RimGridCalculationVariable.cpp index d074ca3cf7..14dcd9c3a7 100644 --- a/ApplicationLibCode/ProjectDataModel/RimGridCalculationVariable.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimGridCalculationVariable.cpp @@ -70,7 +70,15 @@ QString RimGridCalculationVariable::displayString() const if ( m_eclipseCase() ) nameComponents.append( m_eclipseCase()->uiName() ); nameComponents.append( m_resultVariable() ); - return nameComponents.join( " - " ); + return nameComponents.join( " : " ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimGridCalculationVariable::setEclipseCase( RimEclipseCase* eclipseCase ) +{ + m_eclipseCase = eclipseCase; } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/RimGridCalculationVariable.h b/ApplicationLibCode/ProjectDataModel/RimGridCalculationVariable.h index eff36cff0e..a07e6ac9ad 100644 --- a/ApplicationLibCode/ProjectDataModel/RimGridCalculationVariable.h +++ b/ApplicationLibCode/ProjectDataModel/RimGridCalculationVariable.h @@ -46,6 +46,8 @@ class RimGridCalculationVariable : public RimUserDefinedCalculationVariable QString displayString() const override; + void setEclipseCase( RimEclipseCase* eclipseCase ); + RimEclipseCase* eclipseCase() const; RiaDefines::ResultCatType resultCategoryType() const; QString resultVariable() const; diff --git a/ApplicationLibCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp b/ApplicationLibCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp index 1f9065017e..6d95200da1 100644 --- a/ApplicationLibCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp @@ -433,6 +433,7 @@ RimEclipseStatisticsCase* RimIdenticalGridCaseGroup::createStatisticsCase( bool newStatisticsCase->openEclipseGridFile(); newStatisticsCase->eclipseCaseData()->computeActiveCellBoundingBoxes(); + newStatisticsCase->selectAllTimeSteps(); return newStatisticsCase; } diff --git a/ApplicationLibCode/ProjectDataModel/RimMainPlotCollection.cpp b/ApplicationLibCode/ProjectDataModel/RimMainPlotCollection.cpp index 208c85b8b8..fbae6cd76d 100644 --- a/ApplicationLibCode/ProjectDataModel/RimMainPlotCollection.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimMainPlotCollection.cpp @@ -210,7 +210,7 @@ void RimMainPlotCollection::initAfterRead() auto summaryPlot = new RimSummaryPlot; summaryMultiPlot->addPlot( summaryPlot ); - for ( auto curve : crossPlot->allCurves( RimSummaryDataSourceStepping::Axis::Y_AXIS ) ) + for ( auto curve : crossPlot->allCurves() ) { crossPlot->removeCurve( curve ); diff --git a/ApplicationLibCode/ProjectDataModel/RimPlotCurve.cpp b/ApplicationLibCode/ProjectDataModel/RimPlotCurve.cpp index fbb6a5e3a0..ba905fb0df 100644 --- a/ApplicationLibCode/ProjectDataModel/RimPlotCurve.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimPlotCurve.cpp @@ -25,6 +25,7 @@ #include "RimEnsembleCurveSet.h" #include "RimEnsembleCurveSetCollection.h" +#include "RimMultiPlot.h" #include "RimNameConfig.h" #include "RimPlotRectAnnotation.h" #include "RimProject.h" @@ -915,7 +916,9 @@ void RimPlotCurve::updateLegendEntryVisibilityNoPlotUpdate() } } - if ( !anyCalculated && summaryPlot->ensembleCurveSetCollection()->curveSets().empty() && summaryPlot->curveCount() == 1 ) + auto isMultiPlot = ( firstAncestorOrThisOfType() != nullptr ); + + if ( !anyCalculated && isMultiPlot && summaryPlot->ensembleCurveSetCollection()->curveSets().empty() && summaryPlot->curveCount() == 1 ) { // Disable display of legend if the summary plot has only one single curve showLegendInPlot = false; @@ -1039,7 +1042,6 @@ void RimPlotCurve::updateCurveAppearance() // Make sure the legend lines are long enough to distinguish between line types. // Standard width in Qwt is 8 which is too short. - // Use 10 and scale this by curve thickness + add space for displaying symbol. if ( m_curveAppearance->lineStyle() != RiuQwtPlotCurveDefines::LineStyleEnum::STYLE_NONE ) { QSize legendIconSize = m_plotCurve->legendIconSize(); @@ -1050,7 +1052,7 @@ void RimPlotCurve::updateCurveAppearance() symbolWidth = symbol->boundingRect().size().width() + 2; } - int width = std::max( 10 * m_curveAppearance->lineThickness(), ( symbolWidth * 3 ) / 2 ); + int width = std::max( 20, ( symbolWidth * 3 ) / 2 ); legendIconSize.setWidth( width ); m_plotCurve->setLegendIconSize( legendIconSize ); diff --git a/ApplicationLibCode/ProjectDataModel/RimRegularLegendConfig.cpp b/ApplicationLibCode/ProjectDataModel/RimRegularLegendConfig.cpp index 05b647fc46..0a038c0a84 100644 --- a/ApplicationLibCode/ProjectDataModel/RimRegularLegendConfig.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimRegularLegendConfig.cpp @@ -1275,8 +1275,8 @@ void RimRegularLegendConfig::defineUiOrdering( QString uiConfigName, caf::PdmUiO formatGr->add( &m_precision ); formatGr->add( &m_tickNumberFormat ); - formatGr->add( &m_colorLegend, { true, 2, 1 } ); - formatGr->add( &m_selectColorLegendButton, { false, 1, 0 } ); + formatGr->add( &m_colorLegend, { .totalColumnSpan = 2, .leftLabelColumnSpan = 1 } ); + formatGr->add( &m_selectColorLegendButton, { .newRow = false, .totalColumnSpan = 1, .leftLabelColumnSpan = 0 } ); caf::PdmUiOrdering* mappingGr = uiOrdering.addNewGroup( "Mapping" ); mappingGr->add( &m_mappingMode ); @@ -1297,8 +1297,8 @@ void RimRegularLegendConfig::defineUiOrdering( QString uiConfigName, caf::PdmUiO //-------------------------------------------------------------------------------------------------- void RimRegularLegendConfig::defineUiOrderingColorOnly( caf::PdmUiOrdering* colorGroup ) { - colorGroup->add( &m_colorLegend, { true, 2, 1 } ); - colorGroup->add( &m_selectColorLegendButton, { false, 1, 0 } ); + colorGroup->add( &m_colorLegend, { .newRow = true, .totalColumnSpan = 2, .leftLabelColumnSpan = 1 } ); + colorGroup->add( &m_selectColorLegendButton, { .newRow = false, .totalColumnSpan = 1, .leftLabelColumnSpan = 0 } ); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp b/ApplicationLibCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp index c4dc9e7c0c..011209b48f 100644 --- a/ApplicationLibCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp @@ -96,7 +96,8 @@ void RimReservoirCellResultsStorage::setupBeforeSave() bool hasResultsToStore = false; for ( size_t rIdx = 0; rIdx < resAddrs.size(); ++rIdx ) { - if ( m_cellResults->resultInfo( resAddrs[rIdx] )->needsToBeStored() ) + auto resInfo = m_cellResults->resultInfo( resAddrs[rIdx] ); + if ( resInfo && resInfo->needsToBeStored() ) { hasResultsToStore = true; break; diff --git a/ApplicationLibCode/ProjectDataModel/RimResultSelectionUi.cpp b/ApplicationLibCode/ProjectDataModel/RimResultSelectionUi.cpp index 4723e67886..76edca567e 100644 --- a/ApplicationLibCode/ProjectDataModel/RimResultSelectionUi.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimResultSelectionUi.cpp @@ -110,8 +110,7 @@ QList RimResultSelectionUi::calculateValueOptions( const if ( fieldNeedingOptions == &m_eclipseCase ) { - auto cases = RimEclipseCaseTools::eclipseCases(); - for ( auto* c : cases ) + for ( auto* c : RimEclipseCaseTools::allEclipseGridCases() ) { options.push_back( caf::PdmOptionItemInfo( c->caseUserDescription(), c, false, c->uiIconProvider() ) ); } diff --git a/ApplicationLibCode/ProjectDataModel/RimSummaryCalculation.cpp b/ApplicationLibCode/ProjectDataModel/RimSummaryCalculation.cpp index b95bf4bcec..111c7b7bad 100644 --- a/ApplicationLibCode/ProjectDataModel/RimSummaryCalculation.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimSummaryCalculation.cpp @@ -61,8 +61,11 @@ RimSummaryCalculation::RimSummaryCalculation() { CAF_PDM_InitObject( "RimSummaryCalculation", ":/octave.png", "Calculation", "" ); - CAF_PDM_InitField( &m_distributeToOtherItems, "DistributeToOtherItems", true, "Distribute to other items (wells, groups, ..)" ); + CAF_PDM_InitField( &m_distributeToOtherItems, "DistributeToOtherItems", true, "Distribute to other items (wells, groups, ...)" ); caf::PdmUiNativeCheckBoxEditor::configureFieldForEditor( &m_distributeToOtherItems ); + + CAF_PDM_InitField( &m_distributeToAllCases, "DistributeToAllCases", true, "Distribute to All Cases" ); + caf::PdmUiNativeCheckBoxEditor::configureFieldForEditor( &m_distributeToAllCases ); } //-------------------------------------------------------------------------------------------------- @@ -465,6 +468,20 @@ void RimSummaryCalculation::removeDependentObjects() //-------------------------------------------------------------------------------------------------- std::vector RimSummaryCalculation::allAddressesForSummaryCase( RimSummaryCase* summaryCase ) const { + if ( !m_distributeToAllCases ) + { + for ( auto& v : m_variables ) + { + if ( auto variable = dynamic_cast( v.p() ) ) + { + if ( variable->summaryCase() != summaryCase ) + { + return {}; + } + } + } + } + auto variables = getVariables(); if ( variables && !variables.value().empty() ) { @@ -682,3 +699,35 @@ QString RimSummaryCalculation::buildCalculationName() const return name; } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimSummaryCalculation::setDistributeToOtherItems( bool enable ) +{ + m_distributeToOtherItems = enable; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimSummaryCalculation::setDistributeToAllCases( bool enable ) +{ + m_distributeToAllCases = enable; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimSummaryCalculation::isDistributeToOtherItems() const +{ + return m_distributeToOtherItems(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimSummaryCalculation::isDistributeToAllCases() const +{ + return m_distributeToAllCases(); +} diff --git a/ApplicationLibCode/ProjectDataModel/RimSummaryCalculation.h b/ApplicationLibCode/ProjectDataModel/RimSummaryCalculation.h index 3237eb3617..8f73d7ce96 100644 --- a/ApplicationLibCode/ProjectDataModel/RimSummaryCalculation.h +++ b/ApplicationLibCode/ProjectDataModel/RimSummaryCalculation.h @@ -66,6 +66,12 @@ class RimSummaryCalculation : public RimUserDefinedCalculation QString buildCalculationName() const override; + void setDistributeToOtherItems( bool enable ); + void setDistributeToAllCases( bool enable ); + + bool isDistributeToOtherItems() const; + bool isDistributeToAllCases() const; + protected: RimSummaryCalculationVariable* createVariable() override; @@ -91,4 +97,5 @@ class RimSummaryCalculation : public RimUserDefinedCalculation private: caf::PdmField m_distributeToOtherItems; + caf::PdmField m_distributeToAllCases; }; diff --git a/ApplicationLibCode/ProjectDataModel/RimUserDefinedCalculation.cpp b/ApplicationLibCode/ProjectDataModel/RimUserDefinedCalculation.cpp index 3cd0259d85..6601ac4588 100644 --- a/ApplicationLibCode/ProjectDataModel/RimUserDefinedCalculation.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimUserDefinedCalculation.cpp @@ -42,6 +42,7 @@ CAF_PDM_XML_ABSTRACT_SOURCE_INIT( RimUserDefinedCalculation, "RimUserDefinedCalc /// //-------------------------------------------------------------------------------------------------- RimUserDefinedCalculation::RimUserDefinedCalculation() + : variableUpdated( this ) { CAF_PDM_InitObject( "RimUserDefinedCalculation", ":/octave.png", "Calculation", "" ); @@ -177,6 +178,14 @@ QString RimUserDefinedCalculation::unitName() const return m_unit; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimUserDefinedCalculation::setUnit( const QString& unit ) +{ + m_unit = unit; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -244,6 +253,14 @@ bool RimUserDefinedCalculation::parseExpression() return true; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimUserDefinedCalculation::preCalculate() const +{ + return true; +} + //-------------------------------------------------------------------------------------------------- /// Find the last assignment using := and interpret the text before the := as LHS //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/RimUserDefinedCalculation.h b/ApplicationLibCode/ProjectDataModel/RimUserDefinedCalculation.h index 253de806be..f8a229bce9 100644 --- a/ApplicationLibCode/ProjectDataModel/RimUserDefinedCalculation.h +++ b/ApplicationLibCode/ProjectDataModel/RimUserDefinedCalculation.h @@ -36,6 +36,9 @@ class RimUserDefinedCalculation : public caf::PdmObject { CAF_PDM_HEADER_INIT; +public: + caf::Signal<> variableUpdated; + public: RimUserDefinedCalculation(); @@ -51,11 +54,12 @@ class RimUserDefinedCalculation : public caf::PdmObject std::vector allVariables() const; - void setExpression( const QString& expr ); - QString expression() const; - QString unitName() const; - + void setExpression( const QString& expr ); + QString expression() const; + void setUnit( const QString& unit ); + QString unitName() const; bool parseExpression(); + virtual bool preCalculate() const; virtual bool calculate() = 0; virtual void updateDependentObjects() = 0; virtual void removeDependentObjects() = 0; @@ -67,6 +71,8 @@ class RimUserDefinedCalculation : public caf::PdmObject QString shortName() const; + RimUserDefinedCalculationVariable* addVariable( const QString& name ); + protected: virtual RimUserDefinedCalculationVariable* createVariable() = 0; @@ -75,7 +81,6 @@ class RimUserDefinedCalculation : public caf::PdmObject void defineEditorAttribute( const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute ) override; RimUserDefinedCalculationVariable* findByName( const QString& name ) const; - RimUserDefinedCalculationVariable* addVariable( const QString& name ); void deleteVariable( RimUserDefinedCalculationVariable* calcVariable ); virtual QString buildCalculationName() const; diff --git a/ApplicationLibCode/ProjectDataModel/RimUserDefinedCalculationCollection.cpp b/ApplicationLibCode/ProjectDataModel/RimUserDefinedCalculationCollection.cpp index ec9f9e66fc..b30dcf0ec4 100644 --- a/ApplicationLibCode/ProjectDataModel/RimUserDefinedCalculationCollection.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimUserDefinedCalculationCollection.cpp @@ -40,15 +40,18 @@ RimUserDefinedCalculationCollection::RimUserDefinedCalculationCollection() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RimUserDefinedCalculation* RimUserDefinedCalculationCollection::addCalculation() +RimUserDefinedCalculation* RimUserDefinedCalculationCollection::addCalculation( bool addDefaultExpression ) { RimUserDefinedCalculation* calculation = createCalculation(); assignCalculationIdToCalculation( calculation ); - QString varName = QString( "Calculation_%1" ).arg( calculation->id() ); - calculation->setDescription( varName ); - calculation->setExpression( varName + " := x + y" ); - calculation->parseExpression(); + if ( addDefaultExpression ) + { + QString varName = QString( "Calculation_%1" ).arg( calculation->id() ); + calculation->setDescription( varName ); + calculation->setExpression( varName + " := x + y" ); + calculation->parseExpression(); + } m_calculations.push_back( calculation ); diff --git a/ApplicationLibCode/ProjectDataModel/RimUserDefinedCalculationCollection.h b/ApplicationLibCode/ProjectDataModel/RimUserDefinedCalculationCollection.h index 66698e9f24..7f6fc22122 100644 --- a/ApplicationLibCode/ProjectDataModel/RimUserDefinedCalculationCollection.h +++ b/ApplicationLibCode/ProjectDataModel/RimUserDefinedCalculationCollection.h @@ -37,7 +37,7 @@ class RimUserDefinedCalculationCollection : public caf::PdmObject public: RimUserDefinedCalculationCollection(); - RimUserDefinedCalculation* addCalculation(); + RimUserDefinedCalculation* addCalculation( bool addDefaultExpression = true ); RimUserDefinedCalculation* addCalculationCopy( const RimUserDefinedCalculation* sourceCalculation ); void deleteCalculation( RimUserDefinedCalculation* calculation ); std::vector calculations() const; diff --git a/ApplicationLibCode/ProjectDataModel/StimPlanModel/RimStimPlanModel.cpp b/ApplicationLibCode/ProjectDataModel/StimPlanModel/RimStimPlanModel.cpp index cbff11281b..84554e9cd3 100644 --- a/ApplicationLibCode/ProjectDataModel/StimPlanModel/RimStimPlanModel.cpp +++ b/ApplicationLibCode/ProjectDataModel/StimPlanModel/RimStimPlanModel.cpp @@ -835,9 +835,9 @@ void RimStimPlanModel::defineUiOrdering( QString uiConfigName, caf::PdmUiOrderin m_barrierTextAnnotation.uiCapability()->setUiHidden( true ); m_azimuthAngle.uiCapability()->setUiHidden( m_fractureOrientation() != RimStimPlanModel::FractureOrientation::AZIMUTH ); - uiOrdering.add( nameField(), caf::PdmUiOrdering::LayoutOptions( true, 3, 1 ) ); - uiOrdering.add( &m_stimPlanModelTemplate, { true, 2, 1 } ); - uiOrdering.add( &m_editStimPlanModelTemplate, { false, 1, 0 } ); + uiOrdering.add( nameField(), { .newRow = true, .totalColumnSpan = 3, .leftLabelColumnSpan = 1 } ); + uiOrdering.add( &m_stimPlanModelTemplate, { .newRow = true, .totalColumnSpan = 2, .leftLabelColumnSpan = 1 } ); + uiOrdering.add( &m_editStimPlanModelTemplate, { .newRow = false, .totalColumnSpan = 1, .leftLabelColumnSpan = 0 } ); uiOrdering.add( &m_staticEclipseCase ); @@ -852,11 +852,11 @@ void RimStimPlanModel::defineUiOrdering( QString uiConfigName, caf::PdmUiOrderin uiOrdering.add( &m_thicknessDirection ); caf::PdmUiOrdering* extractionBoundariesGroup = uiOrdering.addNewGroup( "Extraction Depth Boundaries" ); - extractionBoundariesGroup->add( &m_extractionOffsetTop, caf::PdmUiOrdering::LayoutOptions( true, 3, 1 ) ); - extractionBoundariesGroup->add( &m_extractionDepthTop, { false, 2, 1 } ); + extractionBoundariesGroup->add( &m_extractionOffsetTop, { .newRow = true, .totalColumnSpan = 3, .leftLabelColumnSpan = 1 } ); + extractionBoundariesGroup->add( &m_extractionDepthTop, { .newRow = false, .totalColumnSpan = 2, .leftLabelColumnSpan = 1 } ); - extractionBoundariesGroup->add( &m_extractionOffsetBottom, caf::PdmUiOrdering::LayoutOptions( true, 3, 1 ) ); - extractionBoundariesGroup->add( &m_extractionDepthBottom, { false, 2, 1 } ); + extractionBoundariesGroup->add( &m_extractionOffsetBottom, { .newRow = true, .totalColumnSpan = 3, .leftLabelColumnSpan = 1 } ); + extractionBoundariesGroup->add( &m_extractionDepthBottom, { .newRow = false, .totalColumnSpan = 2, .leftLabelColumnSpan = 1 } ); caf::PdmUiOrdering* boundingBoxGroup = uiOrdering.addNewGroup( "Bounding Box" ); boundingBoxGroup->add( &m_boundingBoxHorizontal ); @@ -881,8 +881,8 @@ void RimStimPlanModel::defineUiOrdering( QString uiConfigName, caf::PdmUiOrderin asymmetricGroup->add( &m_barrierDip ); asymmetricGroup->add( &m_barrierFaultName ); - asymmetricGroup->add( &m_showOnlyBarrierFault, caf::PdmUiOrdering::LayoutOptions( true, 2, 1 ) ); - asymmetricGroup->add( &m_showAllFaults, { false, 1, 0 } ); + asymmetricGroup->add( &m_showOnlyBarrierFault, { .newRow = true, .totalColumnSpan = 2, .leftLabelColumnSpan = 1 } ); + asymmetricGroup->add( &m_showAllFaults, { .newRow = false, .totalColumnSpan = 1, .leftLabelColumnSpan = 0 } ); asymmetricGroup->add( &m_wellPenetrationLayer ); diff --git a/ApplicationLibCode/ProjectDataModel/StimPlanModel/RimStimPlanModelPlot.cpp b/ApplicationLibCode/ProjectDataModel/StimPlanModel/RimStimPlanModelPlot.cpp index 8fdba73925..23247d2071 100644 --- a/ApplicationLibCode/ProjectDataModel/StimPlanModel/RimStimPlanModelPlot.cpp +++ b/ApplicationLibCode/ProjectDataModel/StimPlanModel/RimStimPlanModelPlot.cpp @@ -85,8 +85,8 @@ RimStimPlanModel* RimStimPlanModelPlot::stimPlanModel() //-------------------------------------------------------------------------------------------------- void RimStimPlanModelPlot::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) { - uiOrdering.add( &m_stimPlanModel, { true, 2, 1 } ); - uiOrdering.add( &m_editStimPlanModel, { false, 1, 0 } ); + uiOrdering.add( &m_stimPlanModel, { .newRow = true, .totalColumnSpan = 2, .leftLabelColumnSpan = 1 } ); + uiOrdering.add( &m_editStimPlanModel, { .newRow = false, .totalColumnSpan = 1, .leftLabelColumnSpan = 0 } ); uiOrdering.add( &m_eclipseCase ); uiOrdering.add( &m_timeStep ); diff --git a/ApplicationLibCode/ProjectDataModel/StimPlanModel/RimStimPlanModelTemplate.cpp b/ApplicationLibCode/ProjectDataModel/StimPlanModel/RimStimPlanModelTemplate.cpp index e197946bd1..d1c966d33a 100644 --- a/ApplicationLibCode/ProjectDataModel/StimPlanModel/RimStimPlanModelTemplate.cpp +++ b/ApplicationLibCode/ProjectDataModel/StimPlanModel/RimStimPlanModelTemplate.cpp @@ -248,8 +248,8 @@ void RimStimPlanModelTemplate::defineUiOrdering( QString uiConfigName, caf::PdmU pressureDataSourceGroup->add( &m_dynamicEclipseCase ); pressureDataSourceGroup->add( &m_timeStep ); pressureDataSourceGroup->add( &m_initialPressureEclipseCase ); - pressureDataSourceGroup->add( &m_useTableForInitialPressure, { true, 2, 1 } ); - pressureDataSourceGroup->add( &m_editPressureTable, { false, 1, 0 } ); + pressureDataSourceGroup->add( &m_useTableForInitialPressure, { .newRow = true, .totalColumnSpan = 2, .leftLabelColumnSpan = 1 } ); + pressureDataSourceGroup->add( &m_editPressureTable, { .newRow = false, .totalColumnSpan = 1, .leftLabelColumnSpan = 0 } ); pressureDataSourceGroup->add( &m_useTableForPressure ); pressureDataSourceGroup->add( &m_useEqlnumForPressureInterpolation ); m_initialPressureEclipseCase.uiCapability()->setUiReadOnly( m_useTableForInitialPressure() ); diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveFilter.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveFilter.cpp index 179b3d1fd7..dac5bc9f3d 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveFilter.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveFilter.cpp @@ -448,7 +448,7 @@ void RimEnsembleCurveFilter::defineUiOrdering( QString uiConfigName, caf::PdmUiO else if ( m_filterMode() == FilterMode::BY_OBJECTIVE_FUNCTION ) { uiOrdering.add( &m_objectiveValuesSummaryAddressesUiField ); - uiOrdering.add( &m_objectiveValuesSelectSummaryAddressPushButton, { false, 1, 0 } ); + uiOrdering.add( &m_objectiveValuesSelectSummaryAddressPushButton, { .newRow = false, .totalColumnSpan = 1, .leftLabelColumnSpan = 0 } ); { auto equationGroup = uiOrdering.addNewGroup( "Equation" ); m_objectiveFunction->uiOrdering( "", *equationGroup ); diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSet.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSet.cpp index bcaccbd915..a853a227c6 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSet.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSet.cpp @@ -836,6 +836,7 @@ void RimEnsembleCurveSet::fieldChangedByUi( const caf::PdmFieldHandle* changedFi plot->updateAxes(); plot->updatePlotTitle(); updateAllCurves(); + plot->zoomAll(); } else if ( changedField == &m_resampling || changedField == &m_useCustomAppearance || changedField == &m_lineStyle || changedField == &m_pointSymbol || changedField == &m_symbolSize || changedField == &m_statisticsLineStyle || @@ -1129,7 +1130,7 @@ void RimEnsembleCurveSet::defineUiOrdering( QString uiConfigName, caf::PdmUiOrde caf::PdmUiGroup* curveDataGroup = uiOrdering.addNewGroup( "Summary Vector" ); curveDataGroup->add( &m_yValuesSummaryCaseCollection ); curveDataGroup->add( &m_yValuesSummaryAddressUiField ); - curveDataGroup->add( &m_yPushButtonSelectSummaryAddress, { false, 1, 0 } ); + curveDataGroup->add( &m_yPushButtonSelectSummaryAddress, { .newRow = false, .totalColumnSpan = 1, .leftLabelColumnSpan = 0 } ); if ( !isXAxisSummaryVector() ) { @@ -1326,7 +1327,8 @@ void RimEnsembleCurveSet::appendColorGroup( caf::PdmUiOrdering& uiOrdering ) if ( m_colorMode == ColorMode::BY_OBJECTIVE_FUNCTION ) { colorsGroup->add( &m_objectiveValuesSummaryAddressesUiField ); - colorsGroup->add( &m_objectiveValuesSelectSummaryAddressPushButton, { false, 1, 0 } ); + colorsGroup->add( &m_objectiveValuesSelectSummaryAddressPushButton, + { .newRow = false, .totalColumnSpan = 1, .leftLabelColumnSpan = 0 } ); { auto equationGroup = colorsGroup->addNewGroup( "Equation" ); @@ -2106,6 +2108,12 @@ void RimEnsembleCurveSet::updateEnsembleCurves( const std::vectorplotWidget()->createPlotCurve( nullptr, "" ) ); + + int curveThickness = 3; + m_plotCurveForLegendText->setAppearance( RiuQwtPlotCurveDefines::LineStyleEnum::STYLE_SOLID, + RiuQwtPlotCurveDefines::CurveInterpolationEnum::INTERPOLATION_POINT_TO_POINT, + curveThickness, + RiaColorTools::toQColor( m_mainEnsembleColor() ) ); } m_plotCurveForLegendText->attachToPlot( plot->plotWidget() ); updateEnsembleLegendItem(); @@ -2447,28 +2455,26 @@ void RimEnsembleCurveSet::updateEnsembleLegendItem() m_plotCurveForLegendText->setTitle( name() ); - { - RiuPlotCurveSymbol* symbol = m_plotCurveForLegendText->createSymbol( RiuPlotCurveSymbol::SYMBOL_CROSS ); - - if ( RimEnsembleCurveSetColorManager::hasSameColorForAllRealizationCurves( m_colorMode() ) ) - { - QColor curveColor = mainEnsembleColor(); - QPen curvePen( curveColor ); - curvePen.setWidth( 2 ); + RiuPlotCurveSymbol* symbol = m_plotCurveForLegendText->createSymbol( RiuPlotCurveSymbol::SYMBOL_NONE ); - symbol->setPen( curvePen ); - symbol->setSize( 6, 6 ); - } - else if ( m_colorMode == ColorMode::BY_ENSEMBLE_PARAM ) - { - QPixmap p = QPixmap( ":/Legend.png" ); - symbol->setPixmap( p ); - symbol->setSize( 8, 8 ); - } + if ( RimEnsembleCurveSetColorManager::hasSameColorForAllRealizationCurves( m_colorMode() ) ) + { + QColor curveColor = mainEnsembleColor(); + QPen curvePen( curveColor ); + curvePen.setWidth( 2 ); - m_plotCurveForLegendText->setSymbol( symbol ); + symbol->setPen( curvePen ); + symbol->setSize( 6, 6 ); + } + else if ( m_colorMode == ColorMode::BY_ENSEMBLE_PARAM ) + { + QPixmap p = QPixmap( ":/Legend.png" ); + symbol->setPixmap( p ); + symbol->setSize( 8, 8 ); } + m_plotCurveForLegendText->setSymbol( symbol ); + bool showLegendItem = isCurvesVisible(); m_plotCurveForLegendText->setVisibleInLegend( showLegendItem ); } diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSetCollection.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSetCollection.cpp index 5632c314fa..6892254a68 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSetCollection.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSetCollection.cpp @@ -51,7 +51,6 @@ RimEnsembleCurveSetCollection::RimEnsembleCurveSetCollection() CAF_PDM_InitFieldNoDefault( &m_ySourceStepping, "YSourceStepping", "" ); m_ySourceStepping = new RimSummaryPlotSourceStepping; - m_ySourceStepping->setSourceSteppingType( RimSummaryDataSourceStepping::Axis::Y_AXIS ); m_ySourceStepping.uiCapability()->setUiTreeHidden( true ); m_ySourceStepping.uiCapability()->setUiTreeChildrenHidden( true ); m_ySourceStepping.xmlCapability()->disableIO(); diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimMultipleSummaryPlotNameHelper.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimMultipleSummaryPlotNameHelper.cpp index 6a2b987ccc..705dede726 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimMultipleSummaryPlotNameHelper.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimMultipleSummaryPlotNameHelper.cpp @@ -256,3 +256,17 @@ std::string RimMultiSummaryPlotNameHelper::titleCompletion() const return ""; } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +size_t RimMultiSummaryPlotNameHelper::numberOfCases() const +{ + size_t caseCount = 0; + for ( auto nameHelper : m_nameHelpers ) + { + caseCount += nameHelper->numberOfCases(); + } + + return caseCount; +} diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimMultipleSummaryPlotNameHelper.h b/ApplicationLibCode/ProjectDataModel/Summary/RimMultipleSummaryPlotNameHelper.h index 641e4da947..652f2cbd12 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimMultipleSummaryPlotNameHelper.h +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimMultipleSummaryPlotNameHelper.h @@ -52,6 +52,8 @@ class RimMultiSummaryPlotNameHelper : public RimSummaryNameHelper std::string titleSegment() const override; std::string titleCompletion() const override; + size_t numberOfCases() const override; + private: std::vector m_nameHelpers; }; diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimObjectiveFunction.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimObjectiveFunction.cpp index d8b5c9df3c..33be813418 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimObjectiveFunction.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimObjectiveFunction.cpp @@ -105,10 +105,10 @@ double RimObjectiveFunction::value( RimSummaryCase* for ( auto vectorSummaryAddress : vectorSummaryAddresses ) { - std::string s = vectorSummaryAddress.vectorName() + RifReaderEclipseSummary::differenceIdentifier(); + std::string s = vectorSummaryAddress.vectorName() + RifEclipseSummaryAddressDefines::differenceIdentifier(); if ( !vectorSummaryAddress.vectorName().empty() ) { - if ( vectorSummaryAddress.vectorName().find( RifReaderEclipseSummary::differenceIdentifier() ) != std::string::npos ) + if ( vectorSummaryAddress.vectorName().find( RifEclipseSummaryAddressDefines::differenceIdentifier() ) != std::string::npos ) { s = vectorSummaryAddress.vectorName(); } @@ -116,7 +116,8 @@ double RimObjectiveFunction::value( RimSummaryCase* vectorSummaryAddressDiff.setVectorName( s ); RifEclipseSummaryAddress vectorSummaryAddressHistory = vectorSummaryAddress; - vectorSummaryAddressHistory.setVectorName( vectorSummaryAddress.vectorName() + RifReaderEclipseSummary::historyIdentifier() ); + vectorSummaryAddressHistory.setVectorName( vectorSummaryAddress.vectorName() + + RifEclipseSummaryAddressDefines::historyIdentifier() ); if ( readerInterface->allResultAddresses().count( vectorSummaryAddressDiff ) ) { diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimObjectiveFunctionTools.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimObjectiveFunctionTools.cpp index 52311ef86b..b9d62f8110 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimObjectiveFunctionTools.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimObjectiveFunctionTools.cpp @@ -62,7 +62,7 @@ std::string RimObjectiveFunctionTools::nativeQuantityName( const std::string& qu std::string nativeName = quantityName; { - auto stringToRemove = RifReaderEclipseSummary::differenceIdentifier(); + auto stringToRemove = RifEclipseSummaryAddressDefines::differenceIdentifier(); if ( RiaStdStringTools::endsWith( nativeName, stringToRemove ) ) { nativeName = nativeName.substr( 0, nativeName.size() - stringToRemove.size() ); @@ -70,7 +70,7 @@ std::string RimObjectiveFunctionTools::nativeQuantityName( const std::string& qu } { - auto stringToRemove = RifReaderEclipseSummary::historyIdentifier(); + auto stringToRemove = RifEclipseSummaryAddressDefines::historyIdentifier(); if ( RiaStdStringTools::endsWith( nativeName, stringToRemove ) ) { nativeName = nativeName.substr( 0, nativeName.size() - stringToRemove.size() ); diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryAddressModifier.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryAddressModifier.cpp index b62de94173..039f807072 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryAddressModifier.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryAddressModifier.cpp @@ -18,6 +18,9 @@ #include "RimSummaryAddressModifier.h" +#include "RiaLogging.h" +#include "RiaStdStringTools.h" + #include "RifEclipseSummaryAddress.h" #include "RimEnsembleCurveSet.h" @@ -27,85 +30,183 @@ //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RimSummaryAddressModifier::RimSummaryAddressModifier( RimSummaryCurve* curve ) - : m_curve( curve ) - , m_curveSet( nullptr ) +RifEclipseSummaryAddress RimSummaryAddressModifier::replaceObjectName( const RifEclipseSummaryAddress& sourceAdr, + std::string objectName, + RimSummaryAddressCollection::CollectionContentType contentType ) { + auto adr = sourceAdr; + + if ( contentType == RimSummaryAddressCollection::CollectionContentType::WELL ) + { + adr.setWellName( objectName ); + } + else if ( contentType == RimSummaryAddressCollection::CollectionContentType::GROUP ) + { + adr.setGroupName( objectName ); + } + else if ( contentType == RimSummaryAddressCollection::CollectionContentType::REGION ) + { + int intValue = RiaStdStringTools::toInt( objectName ); + if ( intValue == -1 ) + { + QString errorText = QString( "Failed to convert region text to region integer value " + "for region text : %1" ) + .arg( QString::fromStdString( objectName ) ); + + RiaLogging::error( errorText ); + } + else + { + adr.setRegion( intValue ); + } + } + + return adr; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RimSummaryAddressModifier::RimSummaryAddressModifier( RimEnsembleCurveSet* curveSet ) - : m_curve( nullptr ) - , m_curveSet( curveSet ) +std::vector RimSummaryAddressModifier::curveAddresses( const std::vector& curveAddressProviders ) { + std::vector addresses; + + for ( auto& provider : curveAddressProviders ) + { + std::visit( + [&addresses]( auto&& arg ) + { + auto curveAdr = RimSummaryAddressModifier::curveAddress( arg ); + addresses.push_back( curveAdr ); + }, + provider ); + }; + + return addresses; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::vector RimSummaryAddressModifier::createAddressModifiersForPlot( RimSummaryPlot* summaryPlot ) +void RimSummaryAddressModifier::applyAddressesToCurveAddressProviders( const std::vector& curveAddressProviders, + const std::vector& addresses ) { - std::vector mods; - if ( summaryPlot ) + if ( curveAddressProviders.size() != addresses.size() ) return; + + for ( size_t i = 0; i < curveAddressProviders.size(); i++ ) { - auto curveSets = summaryPlot->curveSets(); - for ( auto curveSet : curveSets ) - { - mods.emplace_back( RimSummaryAddressModifier( curveSet ) ); - } + auto provider = curveAddressProviders[i]; + const auto& address = addresses[i]; - auto curves = summaryPlot->allCurves( RimSummaryDataSourceStepping::Axis::Y_AXIS ); - for ( auto c : curves ) - { - mods.emplace_back( RimSummaryAddressModifier( c ) ); - } + std::visit( [address]( auto&& arg ) { RimSummaryAddressModifier::setCurveAddress( arg, address ); }, provider ); + }; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RimSummaryAddressModifier::createAddressProviders( RimSummaryPlot* summaryPlot ) +{ + std::vector providers; + + for ( auto c : summaryPlot->allCurves() ) + { + providers.push_back( c ); } - return mods; + for ( auto cs : summaryPlot->curveSets() ) + { + providers.push_back( cs ); + } + + return providers; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RimSummaryAddressModifier::allSummaryAddressesY( RimSummaryPlot* summaryPlot ) +{ + std::vector addresses; + + auto curveAddressProviders = createAddressProviders( summaryPlot ); + for ( auto& provider : curveAddressProviders ) + { + std::visit( + [&addresses]( auto&& arg ) + { + auto curveAdr = RimSummaryAddressModifier::curveAddress( arg ); + addresses.push_back( curveAdr.summaryAddressY() ); + }, + provider ); + }; + + return addresses; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::vector RimSummaryAddressModifier::createEclipseSummaryAddress( RimSummaryPlot* summaryPlot ) +void RimSummaryAddressModifier::updateAddressesByObjectName( const std::vector& curveAddressProviders, + const std::string& objectName, + RimSummaryAddressCollection::CollectionContentType contentType ) { - auto mods = createAddressModifiersForPlot( summaryPlot ); - return convertToEclipseSummaryAddress( mods ); + for ( auto& provider : curveAddressProviders ) + { + std::visit( + [objectName, contentType]( auto&& arg ) + { + const auto sourceAdr = RimSummaryAddressModifier::curveAddress( arg ); + + const auto sourceX = sourceAdr.summaryAddressX(); + const auto sourceY = sourceAdr.summaryAddressY(); + + const auto newAdrX = RimSummaryAddressModifier::replaceObjectName( sourceX, objectName, contentType ); + const auto newAdrY = RimSummaryAddressModifier::replaceObjectName( sourceY, objectName, contentType ); + + RimSummaryAddressModifier::setCurveAddress( arg, RiaSummaryCurveAddress( newAdrX, newAdrY ) ); + }, + provider ); + }; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RifEclipseSummaryAddress RimSummaryAddressModifier::address() const +RiaSummaryCurveAddress RimSummaryAddressModifier::curveAddress( RimEnsembleCurveSet* curveSet ) { - if ( m_curve ) return m_curve->summaryAddressY(); - if ( m_curveSet ) return m_curveSet->summaryAddressY(); + if ( curveSet == nullptr ) return RiaSummaryCurveAddress( RifEclipseSummaryAddress() ); + return curveSet->curveAddress(); +} - return {}; +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiaSummaryCurveAddress RimSummaryAddressModifier::curveAddress( RimSummaryCurve* curve ) +{ + if ( curve == nullptr ) return RiaSummaryCurveAddress( RifEclipseSummaryAddress() ); + return curve->curveAddress(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimSummaryAddressModifier::setAddress( const RifEclipseSummaryAddress& address ) +void RimSummaryAddressModifier::setCurveAddress( RimEnsembleCurveSet* curveSet, const RiaSummaryCurveAddress& curveAdr ) { - if ( m_curve ) m_curve->setSummaryAddressY( address ); - if ( m_curveSet ) m_curveSet->setSummaryAddressYAndStatisticsFlag( address ); + if ( curveSet ) + { + curveSet->setCurveAddress( curveAdr ); + } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::vector - RimSummaryAddressModifier::convertToEclipseSummaryAddress( const std::vector& modifiers ) +void RimSummaryAddressModifier::setCurveAddress( RimSummaryCurve* curve, const RiaSummaryCurveAddress& curveAdr ) { - std::vector tmp; - tmp.reserve( modifiers.size() ); - for ( const auto& m : modifiers ) + if ( curve ) { - tmp.emplace_back( m.address() ); + curve->setSummaryAddressX( curveAdr.summaryAddressX() ); + curve->setSummaryAddressY( curveAdr.summaryAddressY() ); } - return tmp; } diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryAddressModifier.h b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryAddressModifier.h index 92e09cb931..829ca69cd8 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryAddressModifier.h +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryAddressModifier.h @@ -18,29 +18,44 @@ #pragma once +#include "RimSummaryAddressCollection.h" + +#include +#include + class RimSummaryCurve; class RimEnsembleCurveSet; class RimSummaryPlot; class RifEclipseSummaryAddress; +class RiaSummaryCurveAddress; -#include - +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- class RimSummaryAddressModifier { public: - RimSummaryAddressModifier( RimSummaryCurve* curve ); - RimSummaryAddressModifier( RimEnsembleCurveSet* curveSet ); + // Define a variant for summary curves and ensemble curve set. This way we can treat them as similar object without a + // common base class + using CurveAddressProvider = std::variant; - static std::vector createAddressModifiersForPlot( RimSummaryPlot* summaryPlot ); - static std::vector createEclipseSummaryAddress( RimSummaryPlot* summaryPlot ); + static std::vector createAddressProviders( RimSummaryPlot* summaryPlot ); + static std::vector curveAddresses( const std::vector& curveAddressProviders ); + static void applyAddressesToCurveAddressProviders( const std::vector& curveAddressProviders, + const std::vector& addresses ); - RifEclipseSummaryAddress address() const; - void setAddress( const RifEclipseSummaryAddress& address ); + static std::vector allSummaryAddressesY( RimSummaryPlot* summaryPlot ); -private: - static std::vector convertToEclipseSummaryAddress( const std::vector& modifiers ); + static void updateAddressesByObjectName( const std::vector& curveAddressProviders, + const std::string& objectName, + RimSummaryAddressCollection::CollectionContentType contentType ); private: - RimSummaryCurve* m_curve; - RimEnsembleCurveSet* m_curveSet; + static RiaSummaryCurveAddress curveAddress( RimSummaryCurve* curve ); + static RiaSummaryCurveAddress curveAddress( RimEnsembleCurveSet* curveSet ); + static void setCurveAddress( RimEnsembleCurveSet* curveSet, const RiaSummaryCurveAddress& curveAdr ); + static void setCurveAddress( RimSummaryCurve* curve, const RiaSummaryCurveAddress& curveAdr ); + static RifEclipseSummaryAddress replaceObjectName( const RifEclipseSummaryAddress& sourceAdr, + std::string objectName, + RimSummaryAddressCollection::CollectionContentType contentType ); }; diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryAddressSelector.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryAddressSelector.cpp index 9d184eeb4c..ffcc9e5464 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryAddressSelector.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryAddressSelector.cpp @@ -350,15 +350,15 @@ void RimSummaryAddressSelector::defineUiOrdering( QString uiConfigName, caf::Pdm // Update the UI field, as this is not serialized to file m_summaryAddressUiField = m_summaryAddress->address(); - uiOrdering.add( &m_summaryAddressUiField, { true, 2, 1 } ); - uiOrdering.add( &m_pushButtonSelectSummaryAddress, { false, 1, 0 } ); + uiOrdering.add( &m_summaryAddressUiField, { .newRow = true, .totalColumnSpan = 2, .leftLabelColumnSpan = 1 } ); + uiOrdering.add( &m_pushButtonSelectSummaryAddress, { .newRow = false, .totalColumnSpan = 1, .leftLabelColumnSpan = 0 } ); if ( m_showResampling ) { - uiOrdering.add( &m_resamplingPeriod, { true, 3, 1 } ); + uiOrdering.add( &m_resamplingPeriod, { .newRow = true, .totalColumnSpan = 3, .leftLabelColumnSpan = 1 } ); } - uiOrdering.add( &m_plotAxisProperties, { true, 3, 1 } ); + uiOrdering.add( &m_plotAxisProperties, { .newRow = true, .totalColumnSpan = 3, .leftLabelColumnSpan = 1 } ); uiOrdering.skipRemainingFields( true ); } diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCurve.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCurve.cpp index 9cca668d4f..2e99a4e360 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCurve.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCurve.cpp @@ -843,7 +843,7 @@ double RimSummaryCurve::computeCurveZValue() { zOrder = RiuQwtPlotCurveDefines::zDepthForIndex( RiuQwtPlotCurveDefines::ZIndex::Z_ENSEMBLE_STAT_CURVE ); } - else if ( sumCase->ensemble() ) + else if ( firstAncestorOrThisOfType() ) { zOrder = RiuQwtPlotCurveDefines::zDepthForIndex( RiuQwtPlotCurveDefines::ZIndex::Z_ENSEMBLE_CURVE ); } @@ -902,22 +902,22 @@ void RimSummaryCurve::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering { QString curveDataGroupName = "Summary Vector"; caf::PdmUiGroup* curveDataGroup = uiOrdering.addNewGroupWithKeyword( curveDataGroupName, "curveDataGroupName" ); - curveDataGroup->add( &m_yValuesSummaryCase, { true, 3, 1 } ); - curveDataGroup->add( &m_yValuesSummaryAddressUiField, { true, 2, 1 } ); - curveDataGroup->add( &m_yPushButtonSelectSummaryAddress, { false, 1, 0 } ); - curveDataGroup->add( &m_yValuesResampling, { true, 3, 1 } ); - curveDataGroup->add( &m_yPlotAxisProperties, { true, 3, 1 } ); + curveDataGroup->add( &m_yValuesSummaryCase, { .newRow = true, .totalColumnSpan = 3, .leftLabelColumnSpan = 1 } ); + curveDataGroup->add( &m_yValuesSummaryAddressUiField, { .newRow = true, .totalColumnSpan = 2, .leftLabelColumnSpan = 1 } ); + curveDataGroup->add( &m_yPushButtonSelectSummaryAddress, { .newRow = false, .totalColumnSpan = 1, .leftLabelColumnSpan = 0 } ); + curveDataGroup->add( &m_yValuesResampling, { .newRow = true, .totalColumnSpan = 3, .leftLabelColumnSpan = 1 } ); + curveDataGroup->add( &m_yPlotAxisProperties, { .newRow = true, .totalColumnSpan = 3, .leftLabelColumnSpan = 1 } ); curveDataGroup->add( &m_showErrorBars ); } if ( m_showXAxisGroup ) { caf::PdmUiGroup* curveDataGroup = uiOrdering.addNewGroup( "Summary Vector X Axis" ); - curveDataGroup->add( &m_xAxisType, { true, 3, 1 } ); - curveDataGroup->add( &m_xValuesSummaryCase, { true, 3, 1 } ); - curveDataGroup->add( &m_xValuesSummaryAddressUiField, { true, 2, 1 } ); - curveDataGroup->add( &m_xPushButtonSelectSummaryAddress, { false, 1, 0 } ); - curveDataGroup->add( &m_xPlotAxisProperties, { true, 3, 1 } ); + curveDataGroup->add( &m_xAxisType, { .newRow = true, .totalColumnSpan = 3, .leftLabelColumnSpan = 1 } ); + curveDataGroup->add( &m_xValuesSummaryCase, { .newRow = true, .totalColumnSpan = 3, .leftLabelColumnSpan = 1 } ); + curveDataGroup->add( &m_xValuesSummaryAddressUiField, { .newRow = true, .totalColumnSpan = 2, .leftLabelColumnSpan = 1 } ); + curveDataGroup->add( &m_xPushButtonSelectSummaryAddress, { .newRow = false, .totalColumnSpan = 1, .leftLabelColumnSpan = 0 } ); + curveDataGroup->add( &m_xPlotAxisProperties, { .newRow = true, .totalColumnSpan = 3, .leftLabelColumnSpan = 1 } ); } caf::PdmUiGroup* stackingGroup = uiOrdering.addNewGroup( "Stacking" ); @@ -1154,6 +1154,7 @@ void RimSummaryCurve::fieldChangedByUi( const caf::PdmFieldHandle* changedField, } plot->updateAxes(); plot->updatePlotTitle(); + plot->zoomAll(); loadAndUpdate = true; } else if ( &m_showCurve == changedField ) diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCurveAutoName.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCurveAutoName.cpp index efd0dd1d30..abff633c20 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCurveAutoName.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCurveAutoName.cpp @@ -279,8 +279,18 @@ QString RimSummaryCurveAutoName::buildCurveName( const RifEclipseSummaryAddress& if ( m_caseName && !skipSubString ) { + const bool isTextEmptyBeforeCaseName = text.empty(); + if ( !text.empty() ) text += ", "; text += caseName; + + if ( isTextEmptyBeforeCaseName && currentNameHelper && currentNameHelper->numberOfCases() > 1 && + currentNameHelper->vectorNames().size() > 1 ) + { + // Add vector name to the case name if there are multiple cases and multiple vectors + + text += ":" + summaryAddress.vectorName(); + } } } diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCurveCollection.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCurveCollection.cpp index c9616ac569..cecd9a0381 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCurveCollection.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCurveCollection.cpp @@ -65,24 +65,9 @@ RimSummaryCurveCollection::RimSummaryCurveCollection() CAF_PDM_InitFieldNoDefault( &m_ySourceStepping, "YSourceStepping", "" ); m_ySourceStepping = new RimSummaryPlotSourceStepping; - m_ySourceStepping->setSourceSteppingType( RimSummaryDataSourceStepping::Axis::Y_AXIS ); m_ySourceStepping.uiCapability()->setUiTreeHidden( true ); m_ySourceStepping.uiCapability()->setUiTreeChildrenHidden( true ); m_ySourceStepping.xmlCapability()->disableIO(); - - CAF_PDM_InitFieldNoDefault( &m_xSourceStepping, "XSourceStepping", "" ); - m_xSourceStepping = new RimSummaryPlotSourceStepping; - m_xSourceStepping->setSourceSteppingType( RimSummaryDataSourceStepping::Axis::X_AXIS ); - m_xSourceStepping.uiCapability()->setUiTreeHidden( true ); - m_xSourceStepping.uiCapability()->setUiTreeChildrenHidden( true ); - m_xSourceStepping.xmlCapability()->disableIO(); - - CAF_PDM_InitFieldNoDefault( &m_unionSourceStepping, "UnionSourceStepping", "" ); - m_unionSourceStepping = new RimSummaryPlotSourceStepping; - m_unionSourceStepping->setSourceSteppingType( RimSummaryDataSourceStepping::Axis::UNION_X_Y_AXIS ); - m_unionSourceStepping.uiCapability()->setUiTreeHidden( true ); - m_unionSourceStepping.uiCapability()->setUiTreeChildrenHidden( true ); - m_unionSourceStepping.xmlCapability()->disableIO(); } //-------------------------------------------------------------------------------------------------- @@ -128,7 +113,9 @@ void RimSummaryCurveCollection::onChildrenUpdated( caf::PdmChildArrayFieldHandle { for ( auto obj : updatedObjects ) { - if ( auto curve = dynamic_cast( obj ) ) + // Must use firstAncestorOrThisOfType, since we need to update the curve appearance if the object is a child of a + // RimSummaryCurve. This is the case when modifying curve appearance. + if ( auto curve = obj->firstAncestorOrThisOfType() ) { curve->updateCurveAppearance(); } @@ -255,70 +242,6 @@ std::vector RimSummaryCurveCollection::curves() const return m_curves.childrenByType(); } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -std::vector RimSummaryCurveCollection::curvesForSourceStepping( RimSummaryDataSourceStepping::Axis steppingType ) const -{ - std::vector stepCurves; - - if ( m_curveForSourceStepping ) - { - stepCurves.push_back( m_curveForSourceStepping ); - - { - // Add corresponding history/summary curve with or without H - - const std::string historyIdentifier = "H"; - - std::string vectorName; - - if ( steppingType == RimSummaryDataSourceStepping::Axis::X_AXIS ) - { - vectorName = m_curveForSourceStepping->summaryAddressX().vectorName(); - } - else if ( steppingType == RimSummaryDataSourceStepping::Axis::Y_AXIS ) - { - vectorName = m_curveForSourceStepping->summaryAddressY().vectorName(); - } - - std::string candidateName; - if ( RiaStdStringTools::endsWith( vectorName, historyIdentifier ) ) - { - candidateName = vectorName.substr( 0, vectorName.size() - 1 ); - } - else - { - candidateName = vectorName + historyIdentifier; - } - - for ( const auto& c : curves() ) - { - if ( steppingType == RimSummaryDataSourceStepping::Axis::X_AXIS ) - { - if ( c->summaryCaseX() == m_curveForSourceStepping->summaryCaseX() && c->summaryAddressX().vectorName() == candidateName ) - { - stepCurves.push_back( c ); - } - } - else if ( steppingType == RimSummaryDataSourceStepping::Axis::Y_AXIS ) - { - if ( c->summaryCaseY() == m_curveForSourceStepping->summaryCaseY() && c->summaryAddressY().vectorName() == candidateName ) - { - stepCurves.push_back( c ); - } - } - } - } - } - else - { - stepCurves = curves(); - } - - return stepCurves; -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -425,22 +348,9 @@ RimSummaryCurve* RimSummaryCurveCollection::curveForSourceStepping() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RimSummaryPlotSourceStepping* RimSummaryCurveCollection::sourceSteppingObject( RimSummaryDataSourceStepping::Axis sourceSteppingType ) const +RimSummaryPlotSourceStepping* RimSummaryCurveCollection::sourceSteppingObject() const { - if ( sourceSteppingType == RimSummaryDataSourceStepping::Axis::X_AXIS ) - { - return m_xSourceStepping(); - } - else if ( sourceSteppingType == RimSummaryDataSourceStepping::Axis::Y_AXIS ) - { - return m_ySourceStepping(); - } - if ( sourceSteppingType == RimSummaryDataSourceStepping::Axis::UNION_X_Y_AXIS ) - { - return m_unionSourceStepping(); - } - - return nullptr; + return m_ySourceStepping(); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCurveCollection.h b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCurveCollection.h index 364744a2f7..376188283e 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCurveCollection.h +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCurveCollection.h @@ -52,11 +52,10 @@ class RimSummaryCurveCollection : public caf::PdmObject void setCurveForSourceStepping( RimSummaryCurve* curve ); RimSummaryCurve* curveForSourceStepping() const; - RimSummaryPlotSourceStepping* sourceSteppingObject( RimSummaryDataSourceStepping::Axis sourceSteppingType ) const; + RimSummaryPlotSourceStepping* sourceSteppingObject() const; std::set horizontalAxisTypes() const; std::vector curves() const; - std::vector curvesForSourceStepping( RimSummaryDataSourceStepping::Axis steppingType ) const; void setCurveAsTopZWithinCategory( RimSummaryCurve* curve ); @@ -108,8 +107,6 @@ class RimSummaryCurveCollection : public caf::PdmObject caf::PdmField m_editPlot; caf::PdmChildField m_ySourceStepping; - caf::PdmChildField m_xSourceStepping; - caf::PdmChildField m_unionSourceStepping; caf::PdmPointer m_currentSummaryCurve; caf::PdmPointer m_curveForSourceStepping; diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryDataSourceStepping.h b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryDataSourceStepping.h index b050ace7db..ee01a0dd7e 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryDataSourceStepping.h +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryDataSourceStepping.h @@ -26,13 +26,6 @@ class RimEnsembleCurveSet; class RimSummaryDataSourceStepping { public: - enum class Axis - { - Y_AXIS, - X_AXIS, - UNION_X_Y_AXIS - }; - enum class SourceSteppingDimension { SUMMARY_CASE, @@ -48,8 +41,7 @@ class RimSummaryDataSourceStepping }; public: - virtual std::vector availableAxes() const = 0; - virtual std::vector curvesForStepping( RimSummaryDataSourceStepping::Axis axis ) const = 0; - virtual std::vector allCurves( RimSummaryDataSourceStepping::Axis axis ) const = 0; - virtual std::vector curveSets() const = 0; + virtual std::vector curvesForStepping() const = 0; + virtual std::vector allCurves() const = 0; + virtual std::vector curveSets() const = 0; }; diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryMultiPlot.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryMultiPlot.cpp index 3947ddc59c..204dc6d3e1 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryMultiPlot.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryMultiPlot.cpp @@ -163,7 +163,6 @@ RimSummaryMultiPlot::RimSummaryMultiPlot() CAF_PDM_InitFieldNoDefault( &m_sourceStepping, "SourceStepping", "" ); m_sourceStepping = new RimSummaryPlotSourceStepping; - m_sourceStepping->setSourceSteppingType( RimSummaryDataSourceStepping::Axis::Y_AXIS ); m_sourceStepping->setSourceSteppingObject( this ); m_sourceStepping.uiCapability()->setUiTreeHidden( true ); m_sourceStepping.uiCapability()->setUiTreeChildrenHidden( true ); @@ -308,21 +307,13 @@ void RimSummaryMultiPlot::updateAfterPlotRemove() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::vector RimSummaryMultiPlot::availableAxes() const -{ - return { RimSummaryDataSourceStepping::Axis::X_AXIS }; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -std::vector RimSummaryMultiPlot::curvesForStepping( RimSummaryDataSourceStepping::Axis axis ) const +std::vector RimSummaryMultiPlot::curvesForStepping() const { std::vector curves; for ( auto summaryPlot : summaryPlots() ) { - for ( auto curve : summaryPlot->curvesForStepping( axis ) ) + for ( auto curve : summaryPlot->curvesForStepping() ) { curves.push_back( curve ); } @@ -352,13 +343,13 @@ std::vector RimSummaryMultiPlot::curveSets() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::vector RimSummaryMultiPlot::allCurves( RimSummaryDataSourceStepping::Axis axis ) const +std::vector RimSummaryMultiPlot::allCurves() const { std::vector curves; for ( auto summaryPlot : summaryPlots() ) { - for ( auto curve : summaryPlot->allCurves( axis ) ) + for ( auto curve : summaryPlot->allCurves() ) { curves.push_back( curve ); } @@ -378,7 +369,7 @@ void RimSummaryMultiPlot::populateNameHelper( RimSummaryPlotNameHelper* nameHelp std::vector sumCases; std::vector ensembleCases; - for ( RimSummaryCurve* curve : allCurves( RimSummaryDataSourceStepping::Axis::Y_AXIS ) ) + for ( RimSummaryCurve* curve : allCurves() ) { addresses.push_back( curve->curveAddress() ); sumCases.push_back( curve->summaryCaseY() ); @@ -456,7 +447,7 @@ void RimSummaryMultiPlot::fieldChangedByUi( const caf::PdmFieldHandle* changedFi } else if ( changedField == &m_linkTimeAxis ) { - updateTimeAxisRangesFromFirstPlot(); + updateTimeAxisRangesFromFirstTimePlot(); } else if ( changedField == &m_linkSubPlotAxes || changedField == &m_axisRangeAggregation || changedField == &m_linkTimeAxis ) { @@ -760,7 +751,7 @@ void RimSummaryMultiPlot::zoomAll() updateZoom(); - updateTimeAxisRangesFromFirstPlot(); + updateTimeAxisRangesFromFirstTimePlot(); return; } @@ -770,18 +761,31 @@ void RimSummaryMultiPlot::zoomAll() syncAxisRanges(); - updateTimeAxisRangesFromFirstPlot(); + updateTimeAxisRangesFromFirstTimePlot(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimSummaryMultiPlot::updateTimeAxisRangesFromFirstPlot() +void RimSummaryMultiPlot::updateTimeAxisRangesFromFirstTimePlot() { - if ( m_linkTimeAxis && !summaryPlots().empty() ) + if ( m_linkTimeAxis ) { - setAutoScaleXEnabled( false ); - syncTimeAxisRanges( summaryPlots().front() ); + auto allPlots = summaryPlots(); + for ( auto plot : allPlots ) + { + auto curves = plot->summaryAndEnsembleCurves(); + for ( auto curve : curves ) + { + if ( curve->axisTypeX() == RiaDefines::HorizontalAxisType::TIME ) + { + setAutoScaleXEnabled( false ); + syncTimeAxisRanges( plot ); + + return; + } + } + } } } @@ -794,7 +798,7 @@ void RimSummaryMultiPlot::setDefaultRangeAggregationSteppingDimension() for ( auto p : summaryPlots() ) { - auto addresses = RimSummaryAddressModifier::createEclipseSummaryAddress( p ); + auto addresses = RimSummaryAddressModifier::allSummaryAddressesY( p ); analyzer.appendAddresses( addresses ); } @@ -1263,7 +1267,7 @@ void RimSummaryMultiPlot::analyzePlotsAndAdjustAppearanceSettings() for ( auto p : summaryPlots() ) { - auto addresses = RimSummaryAddressModifier::createEclipseSummaryAddress( p ); + auto addresses = RimSummaryAddressModifier::allSummaryAddressesY( p ); analyzer.appendAddresses( addresses ); } @@ -1525,7 +1529,7 @@ void RimSummaryMultiPlot::appendSubPlotByStepping( int direction ) if ( m_sourceStepping()->stepDimension() == RimSummaryDataSourceStepping::SourceSteppingDimension::SUMMARY_CASE ) { RimSummaryCase* newCase = m_sourceStepping()->stepCase( direction ); - for ( auto curve : newPlot->allCurves( RimSummaryDataSourceStepping::Axis::Y_AXIS ) ) + for ( auto curve : newPlot->allCurves() ) { curve->setSummaryCaseY( newCase ); @@ -1545,12 +1549,17 @@ void RimSummaryMultiPlot::appendSubPlotByStepping( int direction ) } else { - auto mods = RimSummaryAddressModifier::createAddressModifiersForPlot( newPlot ); - for ( auto& mod : mods ) + std::vector newCurveAdrs; + + auto curveAddressProviders = RimSummaryAddressModifier::createAddressProviders( newPlot ); + for ( const auto& adr : RimSummaryAddressModifier::curveAddresses( curveAddressProviders ) ) { - auto modifiedAdr = m_sourceStepping()->stepAddress( mod.address(), direction ); - mod.setAddress( modifiedAdr ); + const auto adrX = m_sourceStepping()->stepAddress( adr.summaryAddressX(), direction ); + const auto adrY = m_sourceStepping()->stepAddress( adr.summaryAddressY(), direction ); + newCurveAdrs.push_back( RiaSummaryCurveAddress( adrX, adrY ) ); } + + RimSummaryAddressModifier::applyAddressesToCurveAddressProviders( curveAddressProviders, newCurveAdrs ); } } @@ -1572,7 +1581,7 @@ void RimSummaryMultiPlot::appendCurveByStepping( int direction ) { std::vector addresses; - for ( auto curve : plot->allCurves( RimSummaryDataSourceStepping::Axis::Y_AXIS ) ) + for ( auto curve : plot->allCurves() ) { auto address = curve->summaryAddressY(); auto sumCase = curve->summaryCaseY(); diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryMultiPlot.h b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryMultiPlot.h index a36d17f1bd..5797a0fbec 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryMultiPlot.h +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryMultiPlot.h @@ -68,10 +68,9 @@ class RimSummaryMultiPlot : public RimMultiPlot, public RimSummaryDataSourceStep void setAutoPlotTitle( bool enable ); void setAutoSubPlotTitle( bool enable ); - std::vector availableAxes() const override; - std::vector curvesForStepping( RimSummaryDataSourceStepping::Axis axis ) const override; - std::vector curveSets() const override; - std::vector allCurves( RimSummaryDataSourceStepping::Axis axis ) const override; + std::vector curvesForStepping() const override; + std::vector curveSets() const override; + std::vector allCurves() const override; void addPlot( RimPlot* plot ) override; void insertPlot( RimPlot* plot, size_t index ) override; @@ -148,7 +147,7 @@ class RimSummaryMultiPlot : public RimMultiPlot, public RimSummaryDataSourceStep void onSubPlotAxisReloadRequired( const caf::SignalEmitter* emitter, RimSummaryPlot* summaryPlot ); void onSubPlotAutoTitleChanged( const caf::SignalEmitter* emitter, bool isEnabled ); - void updateTimeAxisRangesFromFirstPlot(); + void updateTimeAxisRangesFromFirstTimePlot(); void updateReadOnlyState(); diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryNameHelper.h b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryNameHelper.h index f2c6b48680..641f3c0fcd 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryNameHelper.h +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryNameHelper.h @@ -59,4 +59,6 @@ class RimSummaryNameHelper virtual std::string titleBlock() const = 0; virtual std::string titleSegment() const = 0; virtual std::string titleCompletion() const = 0; + + virtual size_t numberOfCases() const = 0; }; diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlot.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlot.cpp index 72d135edb9..48865ab7fa 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlot.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlot.cpp @@ -128,6 +128,7 @@ RimSummaryPlot::RimSummaryPlot() , m_isValid( true ) , axisChangedReloadRequired( this ) , autoTitleChanged( this ) + , m_legendPosition( RiuPlotWidget::Legend::BOTTOM ) { CAF_PDM_InitScriptableObject( "Summary Plot", ":/SummaryPlotLight16x16.png", "", "A Summary Plot" ); @@ -422,46 +423,7 @@ void RimSummaryPlot::onAxisSelected( RiuPlotAxis axis, bool toggle ) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimSummaryPlot::moveCurvesToPlot( RimSummaryPlot* plot, const std::vector curves, int insertAtPosition ) -{ - CAF_ASSERT( plot ); - - std::set srcPlots; - - for ( auto curve : curves ) - { - auto srcPlot = curve->firstAncestorOrThisOfTypeAsserted(); - - srcPlot->removeCurve( curve ); - srcPlots.insert( srcPlot ); - } - - for ( auto srcPlot : srcPlots ) - { - srcPlot->updateConnectedEditors(); - srcPlot->loadDataAndUpdate(); - } - for ( size_t cIdx = 0; cIdx < curves.size(); ++cIdx ) - { - if ( insertAtPosition >= 0 ) - { - size_t position = (size_t)insertAtPosition + cIdx; - plot->insertCurve( curves[cIdx], position ); - } - else - { - plot->addCurveNoUpdate( curves[cIdx] ); - } - } - - plot->updateConnectedEditors(); - plot->updateStackedCurveData(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -std::vector RimSummaryPlot::curvesForStepping( RimSummaryDataSourceStepping::Axis axis ) const +std::vector RimSummaryPlot::curvesForStepping() const { auto curveForStepping = summaryCurveCollection()->curveForSourceStepping(); if ( curveForStepping ) @@ -483,26 +445,11 @@ std::vector RimSummaryPlot::curveSets() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::vector RimSummaryPlot::allCurves( RimSummaryDataSourceStepping::Axis axis ) const +std::vector RimSummaryPlot::allCurves() const { return summaryCurves(); } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -std::vector RimSummaryPlot::availableAxes() const -{ - auto axisTypes = m_summaryCurveCollection->horizontalAxisTypes(); - - if ( axisTypes.contains( RiaDefines::HorizontalAxisType::SUMMARY_VECTOR ) ) - { - return { RimSummaryDataSourceStepping::Axis::X_AXIS, RimSummaryDataSourceStepping::Axis::Y_AXIS }; - } - - return { RimSummaryDataSourceStepping::Axis::X_AXIS }; -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -705,7 +652,14 @@ void RimSummaryPlot::updateLegend() { if ( plotWidget() ) { - plotWidget()->setInternalLegendVisible( m_showPlotLegends && !isSubPlot() ); + if ( m_showPlotLegends && !isSubPlot() ) + { + plotWidget()->insertLegend( m_legendPosition ); + } + else + { + plotWidget()->clearLegend(); + } for ( auto c : summaryCurves() ) { @@ -720,6 +674,14 @@ void RimSummaryPlot::updateLegend() } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimSummaryPlot::setLegendPosition( RiuPlotWidget::Legend position ) +{ + m_legendPosition = position; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -942,9 +904,7 @@ void RimSummaryPlot::updateNumericalAxis( RiaDefines::PlotAxis plotAxis ) { if ( summaryCurve->axisY() == riuPlotAxis ) { - curveDefs.push_back( RiaSummaryCurveDefinition( summaryCurve->summaryCaseY(), - summaryCurve->summaryAddressY(), - summaryCurve->isEnsembleCurve() ) ); + curveDefs.emplace_back( summaryCurve->summaryCaseY(), summaryCurve->summaryAddressY(), summaryCurve->isEnsembleCurve() ); } if ( summaryCurve->axisX() == riuPlotAxis ) { @@ -1182,7 +1142,7 @@ void RimSummaryPlot::overrideTimeAxisSettingsIfTooManyCustomTickmarks( RimSummar // prevent large number of tickmarks by accident. const auto [minValue, maxValue] = plotWidget()->axisRange( RimSummaryPlot::plotAxisForTime() ); const double ticksInterval = timeAxisProperties->getTickmarkIntervalDouble(); - const uint numTicks = static_cast( std::ceil( ( maxValue - minValue ) / ticksInterval ) ); + const auto numTicks = static_cast( std::ceil( ( maxValue - minValue ) / ticksInterval ) ); if ( numTicks > MAX_NUM_TICKS ) { if ( showMessageBox ) @@ -1242,16 +1202,6 @@ void RimSummaryPlot::ensureRequiredAxisObjectsForCurves() m_axisPropertiesArray.push_back( axisProperties ); } - - auto axisTypes = m_summaryCurveCollection->horizontalAxisTypes(); - if ( axisTypes.contains( RiaDefines::HorizontalAxisType::SUMMARY_VECTOR ) ) - { - m_sourceStepping->setSourceSteppingType( RimSummaryDataSourceStepping::Axis::UNION_X_Y_AXIS ); - } - else - { - m_sourceStepping->setSourceSteppingType( RimSummaryDataSourceStepping::Axis::Y_AXIS ); - } } //-------------------------------------------------------------------------------------------------- @@ -1968,7 +1918,14 @@ void RimSummaryPlot::onLoadDataAndUpdate() if ( plotWidget() ) { - plotWidget()->setInternalLegendVisible( m_showPlotLegends && !isSubPlot() ); + if ( m_showPlotLegends && !isSubPlot() ) + { + plotWidget()->insertLegend( m_legendPosition ); + } + else + { + plotWidget()->clearLegend(); + } plotWidget()->setLegendFontSize( legendFontSize() ); plotWidget()->updateLegend(); } @@ -2415,7 +2372,7 @@ RimSummaryPlot::CurveInfo RimSummaryPlot::handleAddressCollectionDrop( RimSummar auto curveSets = m_ensembleCurveSetCollection->curveSets(); for ( auto curveSet : curveSets ) { - sourceCurveDefs.push_back( RiaSummaryCurveDefinition( ensembleCase, curveSet->curveAddress() ) ); + sourceCurveDefs.emplace_back( ensembleCase, curveSet->curveAddress() ); } } @@ -2460,7 +2417,7 @@ RimSummaryPlot::CurveInfo RimSummaryPlot::handleAddressCollectionDrop( RimSummar if ( !addr.isHistoryVector() && RiaPreferencesSummary::current()->appendHistoryVectors() ) { auto historyAddr = addr; - historyAddr.setVectorName( addr.vectorName() + RifReaderEclipseSummary::historyIdentifier() ); + historyAddr.setVectorName( addr.vectorName() + RifEclipseSummaryAddressDefines::historyIdentifier() ); auto historyCurveDef = newCurveDef; historyCurveDef.setSummaryAddressY( historyAddr ); @@ -2520,7 +2477,7 @@ RimSummaryPlot::CurveInfo RimSummaryPlot::handleSummaryAddressDrop( RimSummaryAd if ( !summaryAddr->address().isHistoryVector() && RiaPreferencesSummary::current()->appendHistoryVectors() ) { auto historyAddr = summaryAddr->address(); - historyAddr.setVectorName( summaryAddr->address().vectorName() + RifReaderEclipseSummary::historyIdentifier() ); + historyAddr.setVectorName( summaryAddr->address().vectorName() + RifEclipseSummaryAddressDefines::historyIdentifier() ); newCurveAddresses.push_back( historyAddr ); } @@ -2899,7 +2856,7 @@ void RimSummaryPlot::updateNameHelperWithCurveData( RimSummaryPlotNameHelper* na RiaSummaryTools::getSummaryCasesAndAddressesForCalculation( curve->summaryAddressY().id(), sumCases, calcAddresses ); for ( const auto& adr : calcAddresses ) { - addresses.push_back( RiaSummaryCurveAddress( adr ) ); + addresses.emplace_back( adr ); } } else @@ -3078,7 +3035,7 @@ RimSummaryPlotSourceStepping* RimSummaryPlot::sourceSteppingObjectForKeyEventHan if ( axisTypes.contains( RiaDefines::HorizontalAxisType::SUMMARY_VECTOR ) ) { - return summaryCurveCollection()->sourceSteppingObject( RimSummaryDataSourceStepping::Axis::UNION_X_Y_AXIS ); + return summaryCurveCollection()->sourceSteppingObject(); } return m_sourceStepping; @@ -3185,8 +3142,6 @@ void RimSummaryPlot::assignYPlotAxis( RimSummaryCurve* curve ) { enum class AxisAssignmentStrategy { - ALL_TO_LEFT, - ALL_TO_RIGHT, ALTERNATING, USE_MATCHING_UNIT, USE_MATCHING_VECTOR @@ -3228,18 +3183,11 @@ void RimSummaryPlot::assignYPlotAxis( RimSummaryCurve* curve ) } else if ( strategy == AxisAssignmentStrategy::USE_MATCHING_UNIT ) { - bool isLeftUsed = false; - bool isRightUsed = false; - for ( auto c : summaryCurves() ) { if ( c == curve ) continue; - if ( c->axisY() == RiuPlotAxis::defaultLeft() ) isLeftUsed = true; - if ( c->axisY() == RiuPlotAxis::defaultRight() ) isRightUsed = true; - auto currentUnit = RiaStdStringTools::toUpper( c->unitNameY() ); - if ( currentUnit == destinationUnit ) { for ( RimPlotAxisPropertiesInterface* axisProperties : m_axisPropertiesArray ) @@ -3255,23 +3203,39 @@ void RimSummaryPlot::assignYPlotAxis( RimSummaryCurve* curve ) } } - if ( !isLeftUsed ) - { - curve->setLeftOrRightAxisY( RiuPlotAxis::defaultLeft() ); - return; - } + strategy = AxisAssignmentStrategy::ALTERNATING; + } - if ( !isRightUsed ) + auto isDefaultLeftAndRightUsed = [this]( RimSummaryCurve* currentCurve ) -> std::pair + { + bool defaultLeftUsed = false; + bool defaultRightUsed = false; + + for ( auto c : summaryCurves() ) { - curve->setLeftOrRightAxisY( RiuPlotAxis::defaultRight() ); - return; + if ( c == currentCurve ) continue; + + if ( c->axisY() == RiuPlotAxis::defaultLeft() ) defaultLeftUsed = true; + if ( c->axisY() == RiuPlotAxis::defaultRight() ) defaultRightUsed = true; } - strategy = AxisAssignmentStrategy::ALTERNATING; + return std::make_pair( defaultLeftUsed, defaultRightUsed ); + }; + + auto [defaultLeftUsed, defaultRightUsed] = isDefaultLeftAndRightUsed( curve ); + if ( !defaultLeftUsed ) + { + curve->setLeftOrRightAxisY( RiuPlotAxis::defaultLeft() ); + return; } - RiaDefines::PlotAxis plotAxisType = RiaDefines::PlotAxis::PLOT_AXIS_LEFT; + if ( !defaultRightUsed ) + { + curve->setLeftOrRightAxisY( RiuPlotAxis::defaultRight() ); + return; + } + RiaDefines::PlotAxis plotAxisType = RiaDefines::PlotAxis::PLOT_AXIS_LEFT; if ( strategy == AxisAssignmentStrategy::ALTERNATING ) { size_t axisCountLeft = countAxes( m_axisPropertiesArray.childrenByType(), RiaDefines::PlotAxis::PLOT_AXIS_LEFT ); @@ -3279,26 +3243,21 @@ void RimSummaryPlot::assignYPlotAxis( RimSummaryCurve* curve ) if ( axisCountLeft > axisCountRight ) plotAxisType = RiaDefines::PlotAxis::PLOT_AXIS_RIGHT; } - else if ( strategy == AxisAssignmentStrategy::ALL_TO_LEFT ) - { - plotAxisType = RiaDefines::PlotAxis::PLOT_AXIS_LEFT; - } - else if ( strategy == AxisAssignmentStrategy::ALL_TO_RIGHT ) - { - plotAxisType = RiaDefines::PlotAxis::PLOT_AXIS_RIGHT; - } - RiuPlotAxis newPlotAxis = RiuPlotAxis::defaultLeft(); if ( plotWidget() && plotWidget()->isMultiAxisSupported() ) { QString axisObjectName = "New Axis"; if ( !curve->summaryAddressY().uiText().empty() ) axisObjectName = QString::fromStdString( curve->summaryAddressY().uiText() ); - newPlotAxis = plotWidget()->createNextPlotAxis( plotAxisType ); + auto newPlotAxis = plotWidget()->createNextPlotAxis( plotAxisType ); addNewAxisProperties( newPlotAxis, axisObjectName ); + + curve->setLeftOrRightAxisY( newPlotAxis ); + return; } - curve->setLeftOrRightAxisY( newPlotAxis ); + // If we get here, we have no more axes to assign to, use left axis as fallback + curve->setLeftOrRightAxisY( RiuPlotAxis::defaultLeft() ); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlot.h b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlot.h index af71a8722c..a54133b8cf 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlot.h +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlot.h @@ -162,6 +162,7 @@ class RimSummaryPlot : public RimPlot, public RimSummaryDataSourceStepping void updateAll(); void updateLegend() override; + void setLegendPosition( RiuPlotWidget::Legend position ); void setPlotInfoLabel( const QString& label ); void showPlotInfoLabel( bool show ); @@ -196,12 +197,9 @@ class RimSummaryPlot : public RimPlot, public RimSummaryDataSourceStepping return 8; } - static void moveCurvesToPlot( RimSummaryPlot* plot, const std::vector curves, int insertAtPosition ); - - std::vector availableAxes() const override; - std::vector curvesForStepping( RimSummaryDataSourceStepping::Axis axis ) const override; - std::vector curveSets() const override; - std::vector allCurves( RimSummaryDataSourceStepping::Axis axis ) const override; + std::vector curvesForStepping() const override; + std::vector curveSets() const override; + std::vector allCurves() const override; std::vector plotAxes( RimPlotAxisProperties::Orientation orientation ) const; @@ -353,5 +351,6 @@ private slots: std::unique_ptr m_nameHelperAllCurves; caf::PdmChildField m_sourceStepping; - bool m_isValid; + bool m_isValid; + RiuPlotWidget::Legend m_legendPosition; }; diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlotManager.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlotManager.cpp index fd37ef95f0..a3f9be3ff2 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlotManager.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlotManager.cpp @@ -344,17 +344,17 @@ void RimSummaryPlotManager::defineUiOrdering( QString uiConfigName, caf::PdmUiOr uiOrdering.add( &m_filterText ); uiOrdering.add( &m_addressCandidates ); - uiOrdering.add( &m_selectedDataSources, false ); + uiOrdering.appendToRow( &m_selectedDataSources ); uiOrdering.add( &m_individualPlotPerVector ); - uiOrdering.add( &m_individualPlotPerDataSource, false ); + uiOrdering.appendToRow( &m_individualPlotPerDataSource ); uiOrdering.add( &m_individualPlotPerObject ); - uiOrdering.add( &m_createMultiPlot, false ); + uiOrdering.appendToRow( &m_createMultiPlot ); uiOrdering.add( &m_pushButtonAppend ); - uiOrdering.add( &m_pushButtonReplace, { false } ); - uiOrdering.add( &m_labelB, { false } ); - uiOrdering.add( &m_pushButtonNewPlot, { false } ); + uiOrdering.appendToRow( &m_pushButtonReplace ); + uiOrdering.appendToRow( &m_labelB ); + uiOrdering.appendToRow( &m_pushButtonNewPlot ); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlotNameHelper.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlotNameHelper.cpp index 50123b51a6..fdbfe67cd4 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlotNameHelper.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlotNameHelper.cpp @@ -270,6 +270,14 @@ std::string RimSummaryPlotNameHelper::titleCompletion() const return m_titleCompletion; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +size_t RimSummaryPlotNameHelper::numberOfCases() const +{ + return m_summaryCases.size() + m_ensembleCases.size(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlotNameHelper.h b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlotNameHelper.h index 0c86e67192..3de76c7175 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlotNameHelper.h +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlotNameHelper.h @@ -73,6 +73,8 @@ class RimSummaryPlotNameHelper : public RimSummaryNameHelper std::string titleSegment() const override; std::string titleCompletion() const override; + size_t numberOfCases() const override; + private: void clearTitleSubStrings(); void extractPlotTitleSubStrings(); diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlotSourceStepping.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlotSourceStepping.cpp index 9f026737b7..5119e94faf 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlotSourceStepping.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlotSourceStepping.cpp @@ -59,7 +59,6 @@ CAF_PDM_SOURCE_INIT( RimSummaryPlotSourceStepping, "RimSummaryCurveCollectionMod /// //-------------------------------------------------------------------------------------------------- RimSummaryPlotSourceStepping::RimSummaryPlotSourceStepping() - : m_sourceSteppingType( RimSummaryDataSourceStepping::Axis::Y_AXIS ) { CAF_PDM_InitObject( "Summary Curves Modifier" ); @@ -96,14 +95,6 @@ RimSummaryPlotSourceStepping::RimSummaryPlotSourceStepping() CAF_PDM_InitField( &m_autoUpdateAppearance, "AutoUpdateAppearance", false, "Update Appearance" ); } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimSummaryPlotSourceStepping::setSourceSteppingType( RimSummaryDataSourceStepping::Axis sourceSteppingType ) -{ - m_sourceSteppingType = sourceSteppingType; -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -325,7 +316,7 @@ QList RimSummaryPlotSourceStepping::calculateValueOption void RimSummaryPlotSourceStepping::fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) { std::vector curves; - if ( dataSourceSteppingObject() ) curves = dataSourceSteppingObject()->allCurves( m_sourceSteppingType ); + if ( dataSourceSteppingObject() ) curves = dataSourceSteppingObject()->allCurves(); bool isAutoZoomAllowed = false; bool doZoomAll = false; @@ -398,25 +389,19 @@ void RimSummaryPlotSourceStepping::fieldChangedByUi( const caf::PdmFieldHandle* for ( auto curve : curves ) { - if ( isYAxisStepping() ) + if ( previousCase == curve->summaryCaseY() ) { - if ( previousCase == curve->summaryCaseY() ) - { - curve->setSummaryCaseY( m_summaryCase ); + curve->setSummaryCaseY( m_summaryCase ); - if ( m_autoUpdateAppearance ) - { - curve->setCurveAppearanceFromCaseType(); - } + if ( m_autoUpdateAppearance ) + { + curve->setCurveAppearanceFromCaseType(); } } - if ( isXAxisStepping() ) + if ( previousCase == curve->summaryCaseX() ) { - if ( previousCase == curve->summaryCaseX() ) - { - curve->setSummaryCaseX( m_summaryCase ); - } + curve->setSummaryCaseX( m_summaryCase ); } } @@ -507,19 +492,13 @@ void RimSummaryPlotSourceStepping::fieldChangedByUi( const caf::PdmFieldHandle* { for ( auto curve : curves ) { - if ( isYAxisStepping() ) - { - RifEclipseSummaryAddress adr = curve->summaryAddressY(); - RimDataSourceSteppingTools::updateAddressIfMatching( oldValue, newValue, summaryCategoryToModify, adr ); - curve->setSummaryAddressY( adr ); - } + RifEclipseSummaryAddress adrY = curve->summaryAddressY(); + RimDataSourceSteppingTools::updateAddressIfMatching( oldValue, newValue, summaryCategoryToModify, adrY ); + curve->setSummaryAddressY( adrY ); - if ( isXAxisStepping() ) - { - RifEclipseSummaryAddress adr = curve->summaryAddressX(); - RimDataSourceSteppingTools::updateAddressIfMatching( oldValue, newValue, summaryCategoryToModify, adr ); - curve->setSummaryAddressX( adr ); - } + RifEclipseSummaryAddress adrX = curve->summaryAddressX(); + RimDataSourceSteppingTools::updateAddressIfMatching( oldValue, newValue, summaryCategoryToModify, adrX ); + curve->setSummaryAddressX( adrX ); } if ( dataSourceSteppingObject() ) @@ -634,7 +613,7 @@ std::set RimSummaryPlotSourceStepping::adressesForSour } std::vector curves; - if ( dataSourceSteppingObject() ) curves = dataSourceSteppingObject()->curvesForStepping( m_sourceSteppingType ); + if ( dataSourceSteppingObject() ) curves = dataSourceSteppingObject()->curvesForStepping(); size_t maxAddrCount = 0; int maxAddrIndex = -1; @@ -644,7 +623,7 @@ std::set RimSummaryPlotSourceStepping::adressesForSour auto curve = curves[i]; if ( !curve ) continue; - if ( isYAxisStepping() && curve->summaryCaseY() && curve->summaryCaseY()->summaryReader() ) + if ( curve->summaryCaseY() && curve->summaryCaseY()->summaryReader() ) { auto addresses = curve->summaryCaseY()->summaryReader()->allResultAddresses(); @@ -656,7 +635,7 @@ std::set RimSummaryPlotSourceStepping::adressesForSour } } - if ( isXAxisStepping() && curve->summaryCaseX() && curve->summaryCaseX()->summaryReader() ) + if ( curve->summaryCaseX() && curve->summaryCaseX()->summaryReader() ) { auto addresses = curve->summaryCaseX()->summaryReader()->allResultAddresses(); size_t addrCount = addresses.size(); @@ -672,13 +651,13 @@ std::set RimSummaryPlotSourceStepping::adressesForSour { auto curve = curves[maxAddrIndex]; - if ( isXAxisStepping() && curve->summaryCaseX() && curve->summaryCaseX()->summaryReader() ) + if ( curve->summaryCaseX() && curve->summaryCaseX()->summaryReader() ) { auto addresses = curve->summaryCaseX()->summaryReader()->allResultAddresses(); addressSet.insert( addresses.begin(), addresses.end() ); } - if ( isYAxisStepping() && curve->summaryCaseY() && curve->summaryCaseY()->summaryReader() ) + if ( curve->summaryCaseY() && curve->summaryCaseY()->summaryReader() ) { auto addresses = curve->summaryCaseY()->summaryReader()->allResultAddresses(); addressSet.insert( addresses.begin(), addresses.end() ); @@ -704,16 +683,13 @@ std::set RimSummaryPlotSourceStepping::addressesForCur } std::vector curves; - if ( dataSourceSteppingObject() ) curves = dataSourceSteppingObject()->curvesForStepping( m_sourceSteppingType ); + if ( dataSourceSteppingObject() ) curves = dataSourceSteppingObject()->curvesForStepping(); for ( auto curve : curves ) { - if ( isYAxisStepping() ) - { - addresses.insert( curve->summaryAddressY() ); - } + addresses.insert( curve->summaryAddressY() ); - if ( isXAxisStepping() ) + if ( curve->axisTypeX() == RiaDefines::HorizontalAxisType::SUMMARY_VECTOR ) { addresses.insert( curve->summaryAddressX() ); } @@ -731,15 +707,12 @@ std::set RimSummaryPlotSourceStepping::summaryCasesCurveCollect std::set sumCases; std::vector curves; - if ( dataSourceSteppingObject() ) curves = dataSourceSteppingObject()->curvesForStepping( m_sourceSteppingType ); + if ( dataSourceSteppingObject() ) curves = dataSourceSteppingObject()->curvesForStepping(); for ( auto c : curves ) { - if ( isYAxisStepping() ) - { - sumCases.insert( c->summaryCaseY() ); - } + sumCases.insert( c->summaryCaseY() ); - if ( isXAxisStepping() ) + if ( c->axisTypeX() == RiaDefines::HorizontalAxisType::SUMMARY_VECTOR ) { sumCases.insert( c->summaryCaseX() ); } @@ -918,30 +891,6 @@ std::set RimSummaryPlotSourceStepping::ensembleCollec return summaryCaseCollections; } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool RimSummaryPlotSourceStepping::isXAxisStepping() const -{ - if ( m_sourceSteppingType == RimSummaryDataSourceStepping::Axis::UNION_X_Y_AXIS ) return true; - - if ( m_sourceSteppingType == RimSummaryDataSourceStepping::Axis::X_AXIS ) return true; - - return false; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool RimSummaryPlotSourceStepping::isYAxisStepping() const -{ - if ( m_sourceSteppingType == RimSummaryDataSourceStepping::Axis::UNION_X_Y_AXIS ) return true; - - if ( m_sourceSteppingType == RimSummaryDataSourceStepping::Axis::Y_AXIS ) return true; - - return false; -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -1302,13 +1251,11 @@ void RimSummaryPlotSourceStepping::updateVectorNameInCurves( std::vector> curvesInPlot; for ( auto curve : curves ) { - if ( isYAxisStepping() ) { auto adr = curve->summaryAddressY(); if ( RimDataSourceSteppingTools::updateQuantityIfMatching( oldValue, newValue, adr ) ) curve->setSummaryAddressY( adr ); } - if ( isXAxisStepping() ) { auto adr = curve->summaryAddressX(); if ( RimDataSourceSteppingTools::updateQuantityIfMatching( oldValue, newValue, adr ) ) curve->setSummaryAddressX( adr ); @@ -1526,7 +1473,7 @@ std::vector RimSummaryPlotSourceStepping::plotsMatchingStepSettings( s } else { - auto addresses = RimSummaryAddressModifier::createEclipseSummaryAddress( plot ); + auto addresses = RimSummaryAddressModifier::allSummaryAddressesY( plot ); for ( const auto& a : addresses ) { diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlotSourceStepping.h b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlotSourceStepping.h index 76b1256dab..09cf0091d8 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlotSourceStepping.h +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlotSourceStepping.h @@ -49,7 +49,6 @@ class RimSummaryPlotSourceStepping : public caf::PdmObject public: RimSummaryPlotSourceStepping(); - void setSourceSteppingType( RimSummaryDataSourceStepping::Axis sourceSteppingType ); void setSourceSteppingObject( caf::PdmObject* sourceObject ); void applyNextStep(); @@ -92,9 +91,6 @@ class RimSummaryPlotSourceStepping : public caf::PdmObject std::vector activeFieldsForDataSourceStepping(); std::vector toolbarFieldsForDataSourceStepping(); - bool isXAxisStepping() const; - bool isYAxisStepping() const; - void modifyCurrentIndex( caf::PdmValueField* valueField, int indexOffset, bool notifyChange = true ); std::vector summaryCasesForSourceStepping(); @@ -132,6 +128,5 @@ class RimSummaryPlotSourceStepping : public caf::PdmObject caf::PdmField m_includeEnsembleCasesForCaseStepping; caf::PdmField m_autoUpdateAppearance; - RimSummaryDataSourceStepping::Axis m_sourceSteppingType; - std::vector m_cachedIdentifiers; + std::vector m_cachedIdentifiers; }; diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryTimeAxisProperties.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryTimeAxisProperties.cpp index 0ea047dce7..bc1dd831e3 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryTimeAxisProperties.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryTimeAxisProperties.cpp @@ -802,10 +802,10 @@ void RimSummaryTimeAxisProperties::defineUiOrdering( QString uiConfigName, caf:: timeGroup->add( &m_timeMode ); if ( m_timeMode() == DATE ) { - timeGroup->add( &m_visibleDateRangeMax, true ); - timeGroup->add( &m_visibleTimeRangeMax, false ); - timeGroup->add( &m_visibleDateRangeMin, true ); - timeGroup->add( &m_visibleTimeRangeMin, false ); + timeGroup->add( &m_visibleDateRangeMax ); + timeGroup->appendToRow( &m_visibleTimeRangeMax ); + timeGroup->add( &m_visibleDateRangeMin ); + timeGroup->appendToRow( &m_visibleTimeRangeMin ); } else { diff --git a/ApplicationLibCode/ProjectDataModel/WellPath/RimWellIADataAccess.cpp b/ApplicationLibCode/ProjectDataModel/WellPath/RimWellIADataAccess.cpp index d9cdbe76a4..c2bcf99ee3 100644 --- a/ApplicationLibCode/ProjectDataModel/WellPath/RimWellIADataAccess.cpp +++ b/ApplicationLibCode/ProjectDataModel/WellPath/RimWellIADataAccess.cpp @@ -117,15 +117,26 @@ double RimWellIADataAccess::interpolatedResultValue( QString fieldNa { RigFemResultAddress address( resultType, fieldName.toStdString(), componentName.toStdString() ); + RigFemPart* femPart = m_caseData->femParts()->part( 0 ); + const std::vector& scalarResults = m_caseData->femPartResults()->resultValues( address, 0, timeStep, frameId ); + + return interpolatedResultValue( femPart, scalarResults, resultType, position ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RimWellIADataAccess::interpolatedResultValue( const RigFemPart* femPart, + const std::vector& scalarResults, + RigFemResultPosEnum resultType, + const cvf::Vec3d& position ) +{ int elmIdx = elementIndex( position ); - RigFemPart* femPart = m_caseData->femParts()->part( 0 ); RigElementType elmType = femPart->elementType( elmIdx ); const int* elementConn = femPart->connectivities( elmIdx ); int elmNodeCount = RigFemTypes::elementNodeCount( elmType ); - const std::vector& scalarResults = m_caseData->femPartResults()->resultValues( address, 0, timeStep, frameId ); - std::array nodeResults; std::array nodeCorners; diff --git a/ApplicationLibCode/ProjectDataModel/WellPath/RimWellIADataAccess.h b/ApplicationLibCode/ProjectDataModel/WellPath/RimWellIADataAccess.h index 71fee0a183..4f240b02a2 100644 --- a/ApplicationLibCode/ProjectDataModel/WellPath/RimWellIADataAccess.h +++ b/ApplicationLibCode/ProjectDataModel/WellPath/RimWellIADataAccess.h @@ -28,6 +28,7 @@ class RimGeoMechCase; class RigGeoMechCaseData; +class RigFemPart; //================================================================================================== /// @@ -49,6 +50,11 @@ class RimWellIADataAccess int timeStep, int frameId ); + double interpolatedResultValue( const RigFemPart* femPart, + const std::vector& scalarResults, + RigFemResultPosEnum resultType, + const cvf::Vec3d& position ); + private: RimGeoMechCase* m_case; RigGeoMechCaseData* m_caseData; diff --git a/ApplicationLibCode/ProjectDataModel/WellPath/RimWellPath.cpp b/ApplicationLibCode/ProjectDataModel/WellPath/RimWellPath.cpp index bc026fb3be..049a8e56d2 100644 --- a/ApplicationLibCode/ProjectDataModel/WellPath/RimWellPath.cpp +++ b/ApplicationLibCode/ProjectDataModel/WellPath/RimWellPath.cpp @@ -129,7 +129,7 @@ RimWellPath::RimWellPath() m_completions = new RimWellPathCompletions; m_completions.uiCapability()->setUiTreeHidden( true ); - CAF_PDM_InitFieldNoDefault( &m_completionSettings, "CompletionSettings", "Completion Settings" ); + CAF_PDM_InitScriptableFieldNoDefault( &m_completionSettings, "CompletionSettings", "Completion Settings" ); m_completionSettings = new RimWellPathCompletionSettings; CAF_PDM_InitFieldNoDefault( &m_wellLogFiles, "WellLogFiles", "Well Log Files" ); diff --git a/ApplicationLibCode/ReservoirDataModel/CMakeLists_files.cmake b/ApplicationLibCode/ReservoirDataModel/CMakeLists_files.cmake index 8b0a2d36e5..e913f2ac12 100644 --- a/ApplicationLibCode/ReservoirDataModel/CMakeLists_files.cmake +++ b/ApplicationLibCode/ReservoirDataModel/CMakeLists_files.cmake @@ -92,6 +92,7 @@ set(SOURCE_GROUP_HEADER_FILES ${CMAKE_CURRENT_LIST_DIR}/RigBasicPlane.h ${CMAKE_CURRENT_LIST_DIR}/RigGriddedPart3d.h ${CMAKE_CURRENT_LIST_DIR}/RigFaultReactivationModel.h + ${CMAKE_CURRENT_LIST_DIR}/RigFaultReactivationModelGenerator.h ${CMAKE_CURRENT_LIST_DIR}/RigWellAllocationOverTime.h ${CMAKE_CURRENT_LIST_DIR}/RigWellResultBranch.h ${CMAKE_CURRENT_LIST_DIR}/RigWellResultFrame.h @@ -184,6 +185,7 @@ set(SOURCE_GROUP_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/RigBasicPlane.cpp ${CMAKE_CURRENT_LIST_DIR}/RigGriddedPart3d.cpp ${CMAKE_CURRENT_LIST_DIR}/RigFaultReactivationModel.cpp + ${CMAKE_CURRENT_LIST_DIR}/RigFaultReactivationModelGenerator.cpp ${CMAKE_CURRENT_LIST_DIR}/RigWellAllocationOverTime.cpp ${CMAKE_CURRENT_LIST_DIR}/RigWellResultBranch.cpp ${CMAKE_CURRENT_LIST_DIR}/RigWellResultFrame.cpp diff --git a/ApplicationLibCode/ReservoirDataModel/Completions/RigEclipseToStimPlanCalculator.cpp b/ApplicationLibCode/ReservoirDataModel/Completions/RigEclipseToStimPlanCalculator.cpp index 818dd82a28..ecae372472 100644 --- a/ApplicationLibCode/ReservoirDataModel/Completions/RigEclipseToStimPlanCalculator.cpp +++ b/ApplicationLibCode/ReservoirDataModel/Completions/RigEclipseToStimPlanCalculator.cpp @@ -85,6 +85,7 @@ void RigEclipseToStimPlanCalculator::computeValues() std::vector> injectivityFactors; std::vector> viscosities; std::vector> filterCakeMobilities; + std::vector> filtrateThicknesses; RimThermalFractureTemplate* thermalFractureTemplate = dynamic_cast( m_fracture->fractureTemplate() ); @@ -110,6 +111,12 @@ void RigEclipseToStimPlanCalculator::computeValues() RiaDefines::getExpectedThermalFractureUnit( RiaDefines::filterCakeMobilityResultName(), unitSystem ), timeStep ); + + filtrateThicknesses = + thermalFractureTemplate->resultValues( RiaDefines::filtrateThicknessResultName(), + RiaDefines::getExpectedThermalFractureUnit( RiaDefines::filtrateThicknessResultName(), + unitSystem ), + timeStep ); } for ( size_t i = 0; i < m_fractureGrid.fractureCells().size(); i++ ) @@ -127,6 +134,7 @@ void RigEclipseToStimPlanCalculator::computeValues() double injectivityFactor = resultValueAtIJ( injectivityFactors, m_fractureGrid, cellI, cellJ ); double viscosity = resultValueAtIJ( viscosities, m_fractureGrid, cellI, cellJ ); double filterCakeMobility = resultValueAtIJ( filterCakeMobilities, m_fractureGrid, cellI, cellJ ); + double filtrateThickness = resultValueAtIJ( filtrateThicknesses, m_fractureGrid, cellI, cellJ ); // Assumed value double relativePermeability = 1.0; @@ -141,6 +149,7 @@ void RigEclipseToStimPlanCalculator::computeValues() filterPressureDropType, injectivityFactor, filterCakeMobility, + filtrateThickness, viscosity, relativePermeability ); } diff --git a/ApplicationLibCode/ReservoirDataModel/Completions/RigEclipseToThermalCellTransmissibilityCalculator.cpp b/ApplicationLibCode/ReservoirDataModel/Completions/RigEclipseToThermalCellTransmissibilityCalculator.cpp index f8fb421bf4..cab1ac2b92 100644 --- a/ApplicationLibCode/ReservoirDataModel/Completions/RigEclipseToThermalCellTransmissibilityCalculator.cpp +++ b/ApplicationLibCode/ReservoirDataModel/Completions/RigEclipseToThermalCellTransmissibilityCalculator.cpp @@ -35,12 +35,14 @@ RigEclipseToThermalCellTransmissibilityCalculator::RigEclipseToThermalCellTransm RimThermalFractureTemplate::FilterCakePressureDrop filterCakePressureDrop, double injectivityFactor, double filterCakeMobility, + double filtrateThickness, double viscosity, double relativePermeability ) : RigEclipseToStimPlanCellTransmissibilityCalculator( caseToApply, fractureTransform, skinFactor, cDarcy, stimPlanCell, fracture ) , m_filterCakePressureDrop( filterCakePressureDrop ) , m_injectivityFactor( injectivityFactor ) , m_filterCakeMobility( filterCakeMobility ) + , m_filtrateThickness( filtrateThickness ) , m_viscosity( viscosity ) , m_relativePermeability( relativePermeability ) { @@ -60,11 +62,19 @@ double RigEclipseToThermalCellTransmissibilityCalculator::calculateTransmissibil } else if ( m_filterCakePressureDrop == RimThermalFractureTemplate::FilterCakePressureDrop::ABSOLUTE ) { - double filterCakeTransmissibility = ( m_viscosity / m_relativePermeability ) * fractureArea * m_filterCakeMobility; + // Take filter cake transmissibility into account only when filter cake exists (i.e. has thickness). + if ( m_filtrateThickness > 0.0 ) + { + double filterCakeTransmissibility = ( m_viscosity / m_relativePermeability ) * fractureArea * m_filterCakeMobility; - // Harmonic mean - return ( fractureMatrixTransimissibility * filterCakeTransmissibility ) / - ( fractureMatrixTransimissibility + filterCakeTransmissibility ); + // Harmonic mean + return ( fractureMatrixTransimissibility * filterCakeTransmissibility ) / + ( fractureMatrixTransimissibility + filterCakeTransmissibility ); + } + else + { + return fractureMatrixTransimissibility; + } } else { diff --git a/ApplicationLibCode/ReservoirDataModel/Completions/RigEclipseToThermalCellTransmissibilityCalculator.h b/ApplicationLibCode/ReservoirDataModel/Completions/RigEclipseToThermalCellTransmissibilityCalculator.h index cceebfaa3b..8b34506ef9 100644 --- a/ApplicationLibCode/ReservoirDataModel/Completions/RigEclipseToThermalCellTransmissibilityCalculator.h +++ b/ApplicationLibCode/ReservoirDataModel/Completions/RigEclipseToThermalCellTransmissibilityCalculator.h @@ -53,6 +53,7 @@ class RigEclipseToThermalCellTransmissibilityCalculator : public RigEclipseToSti RimThermalFractureTemplate::FilterCakePressureDrop filterCakePressureDrop, double injectvityFactor, double filterCakeMobility, + double filtrateThickness, double viscosity, double relativePermeability ); @@ -62,6 +63,7 @@ class RigEclipseToThermalCellTransmissibilityCalculator : public RigEclipseToSti RimThermalFractureTemplate::FilterCakePressureDrop m_filterCakePressureDrop; double m_injectivityFactor; double m_filterCakeMobility; + double m_filtrateThickness; double m_viscosity; double m_relativePermeability; }; diff --git a/ApplicationLibCode/ReservoirDataModel/ResultCalculators/CMakeLists_files.cmake b/ApplicationLibCode/ReservoirDataModel/ResultCalculators/CMakeLists_files.cmake index 1cfe84906e..3574828f35 100644 --- a/ApplicationLibCode/ReservoirDataModel/ResultCalculators/CMakeLists_files.cmake +++ b/ApplicationLibCode/ReservoirDataModel/ResultCalculators/CMakeLists_files.cmake @@ -7,6 +7,7 @@ set(SOURCE_GROUP_HEADER_FILES ${CMAKE_CURRENT_LIST_DIR}/RigOilVolumeResultCalculator.h ${CMAKE_CURRENT_LIST_DIR}/RigCellVolumeResultCalculator.h ${CMAKE_CURRENT_LIST_DIR}/RigAllanUtil.h + ${CMAKE_CURRENT_LIST_DIR}/RigCellsWithNncsCalculator.h ) set(SOURCE_GROUP_SOURCE_FILES @@ -18,6 +19,7 @@ set(SOURCE_GROUP_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/RigOilVolumeResultCalculator.cpp ${CMAKE_CURRENT_LIST_DIR}/RigCellVolumeResultCalculator.cpp ${CMAKE_CURRENT_LIST_DIR}/RigAllanUtil.cpp + ${CMAKE_CURRENT_LIST_DIR}/RigCellsWithNncsCalculator.cpp ) list(APPEND CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES}) diff --git a/ApplicationLibCode/ReservoirDataModel/ResultCalculators/RigCellsWithNncsCalculator.cpp b/ApplicationLibCode/ReservoirDataModel/ResultCalculators/RigCellsWithNncsCalculator.cpp new file mode 100644 index 0000000000..b91f45f56a --- /dev/null +++ b/ApplicationLibCode/ReservoirDataModel/ResultCalculators/RigCellsWithNncsCalculator.cpp @@ -0,0 +1,87 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 "RigCellsWithNncsCalculator.h" + +#include "RigActiveCellInfo.h" +#include "RigCaseCellResultsData.h" +#include "RigEclipseResultAddress.h" +#include "RigMainGrid.h" +#include "RigNNCData.h" + +//================================================================================================== +/// +//================================================================================================== +RigCellsWithNncsCalculator::RigCellsWithNncsCalculator( RigCaseCellResultsData& resultsData ) + : RigEclipseResultCalculator( resultsData ) +{ +} + +//================================================================================================== +/// +//================================================================================================== +RigCellsWithNncsCalculator::~RigCellsWithNncsCalculator() +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RigCellsWithNncsCalculator::isMatching( const RigEclipseResultAddress& resVarAddr ) const +{ + return ( resVarAddr.resultName() == RiaResultNames::riNncCells() && resVarAddr.resultCatType() == RiaDefines::ResultCatType::STATIC_NATIVE ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigCellsWithNncsCalculator::calculate( const RigEclipseResultAddress& resVarAddr, size_t timeStepIndex ) +{ + if ( !m_resultsData ) return; + if ( !m_resultsData->m_ownerCaseData ) return; + if ( m_resultsData->activeCellInfo()->reservoirActiveCellCount() == 0 ) return; + + auto nncData = m_resultsData->m_ownerMainGrid->nncData(); + auto connections = nncData->allConnections(); + + std::set uniqueReservoirIndices; + for ( size_t i = 0; i < nncData->eclipseConnectionCount(); i++ ) + { + uniqueReservoirIndices.insert( connections[i].c1GlobIdx() ); + uniqueReservoirIndices.insert( connections[i].c2GlobIdx() ); + } + + size_t scalarResultIndex = m_resultsData->findOrCreateScalarResultIndex( RigEclipseResultAddress( RiaDefines::ResultCatType::STATIC_NATIVE, + RiaResultNames::riNncCells() ), + false ); + + if ( m_resultsData->m_cellScalarResults[scalarResultIndex].empty() ) + { + m_resultsData->m_cellScalarResults[scalarResultIndex].resize( 1 ); + } + std::vector& resultValues = m_resultsData->m_cellScalarResults[scalarResultIndex][0]; + + size_t cellResultCount = m_resultsData->m_activeCellInfo->reservoirActiveCellCount(); + resultValues.resize( cellResultCount, 0 ); + + for ( auto reservoirCellIndex : uniqueReservoirIndices ) + { + size_t resultIndex = m_resultsData->activeCellInfo()->cellResultIndex( reservoirCellIndex ); + resultValues[resultIndex] = 1.0; + } +} diff --git a/ApplicationLibCode/ReservoirDataModel/ResultCalculators/RigCellsWithNncsCalculator.h b/ApplicationLibCode/ReservoirDataModel/ResultCalculators/RigCellsWithNncsCalculator.h new file mode 100644 index 0000000000..cfa1afe8d1 --- /dev/null +++ b/ApplicationLibCode/ReservoirDataModel/ResultCalculators/RigCellsWithNncsCalculator.h @@ -0,0 +1,33 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 "RigEclipseResultCalculator.h" + +//================================================================================================== +/// +//================================================================================================== +class RigCellsWithNncsCalculator : public RigEclipseResultCalculator +{ +public: + RigCellsWithNncsCalculator( RigCaseCellResultsData& resultsData ); + ~RigCellsWithNncsCalculator() override; + bool isMatching( const RigEclipseResultAddress& resVarAddr ) const override; + void calculate( const RigEclipseResultAddress& resVarAddr, size_t timeStepIndex ) override; +}; diff --git a/ApplicationLibCode/ReservoirDataModel/RigActiveCellInfo.cpp b/ApplicationLibCode/ReservoirDataModel/RigActiveCellInfo.cpp index 3ffae1ccea..2ecf32f6c7 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigActiveCellInfo.cpp +++ b/ApplicationLibCode/ReservoirDataModel/RigActiveCellInfo.cpp @@ -81,6 +81,14 @@ void RigActiveCellInfo::setCellResultIndex( size_t reservoirCellIndex, size_t re m_cellIndexToResultIndex[reservoirCellIndex] = reservoirCellResultIndex; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RigActiveCellInfo::activeReservoirCellIndices() const +{ + return m_activeCellIndices; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -110,6 +118,14 @@ void RigActiveCellInfo::computeDerivedData() { m_reservoirActiveCellCount += m_perGridActiveCellInfo[i].activeCellCount(); } + + for ( size_t i = 0; i < m_cellIndexToResultIndex.size(); i++ ) + { + if ( m_cellIndexToResultIndex[i] != cvf::UNDEFINED_SIZE_T ) + { + m_activeCellIndices.push_back( i ); + } + } } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ReservoirDataModel/RigActiveCellInfo.h b/ApplicationLibCode/ReservoirDataModel/RigActiveCellInfo.h index 3489cfc0a1..f016e2c2dd 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigActiveCellInfo.h +++ b/ApplicationLibCode/ReservoirDataModel/RigActiveCellInfo.h @@ -35,9 +35,10 @@ class RigActiveCellInfo : public cvf::Object size_t reservoirCellCount() const; size_t reservoirActiveCellCount() const; - bool isActive( size_t reservoirCellIndex ) const; - size_t cellResultIndex( size_t reservoirCellIndex ) const; - void setCellResultIndex( size_t reservoirCellIndex, size_t globalResultCellIndex ); + bool isActive( size_t reservoirCellIndex ) const; + size_t cellResultIndex( size_t reservoirCellIndex ) const; + void setCellResultIndex( size_t reservoirCellIndex, size_t globalResultCellIndex ); + std::vector activeReservoirCellIndices() const; void setGridCount( size_t gridCount ); void setGridActiveCellCounts( size_t gridIndex, size_t activeCellCount ); @@ -71,6 +72,7 @@ class RigActiveCellInfo : public cvf::Object std::vector m_perGridActiveCellInfo; std::vector m_cellIndexToResultIndex; + std::vector m_activeCellIndices; size_t m_reservoirActiveCellCount; diff --git a/ApplicationLibCode/ReservoirDataModel/RigCaseCellResultsData.cpp b/ApplicationLibCode/ReservoirDataModel/RigCaseCellResultsData.cpp index c4b771c438..b6e186c211 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigCaseCellResultsData.cpp +++ b/ApplicationLibCode/ReservoirDataModel/RigCaseCellResultsData.cpp @@ -33,6 +33,7 @@ #include "RigAllanUtil.h" #include "RigCaseCellResultCalculator.h" #include "RigCellVolumeResultCalculator.h" +#include "RigCellsWithNncsCalculator.h" #include "RigEclipseAllanFaultsStatCalc.h" #include "RigEclipseCaseData.h" #include "RigEclipseMultiPropertyStatCalc.h" @@ -699,23 +700,34 @@ void RigCaseCellResultsData::clearAllResults() /// Removes all the actual numbers put into this object, and frees up the memory. /// Does not touch the metadata in any way //-------------------------------------------------------------------------------------------------- -void RigCaseCellResultsData::freeAllocatedResultsData() +void RigCaseCellResultsData::freeAllocatedResultsData( std::vector categoriesToExclude, + std::optional timeStepIndexToRelease ) { for ( size_t resultIdx = 0; resultIdx < m_cellScalarResults.size(); ++resultIdx ) { - if ( resultIdx < m_resultInfos.size() && - m_resultInfos[resultIdx].eclipseResultAddress().resultCatType() == RiaDefines::ResultCatType::GENERATED ) + if ( resultIdx < m_resultInfos.size() ) { - // Not possible to recreate generated results, keep them - continue; + auto resultCategory = m_resultInfos[resultIdx].eclipseResultAddress().resultCatType(); + if ( std::find( categoriesToExclude.begin(), categoriesToExclude.end(), resultCategory ) != categoriesToExclude.end() ) + { + // Keep generated results for these categories + continue; + } } - for ( auto& tsIdx : m_cellScalarResults[resultIdx] ) + for ( size_t index = 0; index < m_cellScalarResults[resultIdx].size(); index++ ) { + if ( timeStepIndexToRelease && index != *timeStepIndexToRelease ) + { + // Keep generated results for these time steps + continue; + } + + auto& dataForTimeStep = m_cellScalarResults[resultIdx][index]; // Using swap with an empty vector as that is the safest way to really get rid of the allocated data in a // vector std::vector empty; - tsIdx.swap( empty ); + dataForTimeStep.swap( empty ); } } } @@ -1105,6 +1117,14 @@ void RigCaseCellResultsData::createPlaceholderResultEntries() findOrCreateScalarResultIndex( RigEclipseResultAddress( RiaDefines::ResultCatType::STATIC_NATIVE, RiaResultNames::faultDistanceName() ), needsToBeStored ); } + + // NNC cells, 1 for cells with NNC and 0 for other cells + { + findOrCreateScalarResultIndex( RigEclipseResultAddress( RiaDefines::ResultCatType::STATIC_NATIVE, + RiaDefines::ResultDataType::INTEGER, + RiaResultNames::riNncCells() ), + needsToBeStored ); + } } //-------------------------------------------------------------------------------------------------- @@ -1314,6 +1334,10 @@ size_t RigCaseCellResultsData::findOrLoadKnownScalarResult( const RigEclipseResu { computeFaultDistance(); } + else if ( resultName == RiaResultNames::riNncCells() ) + { + computeNncsCells(); + } } else if ( type == RiaDefines::ResultCatType::DYNAMIC_NATIVE ) { @@ -1885,6 +1909,16 @@ void RigCaseCellResultsData::computeFaultDistance() calculator.calculate( addr, 0 ); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigCaseCellResultsData::computeNncsCells() +{ + RigEclipseResultAddress addr( RiaDefines::ResultCatType::STATIC_NATIVE, RiaResultNames::riNncCells() ); + RigCellsWithNncsCalculator calculator( *this ); + calculator.calculate( addr, 0 ); +} + namespace RigTransmissibilityCalcTools { void calculateConnectionGeometry( const RigCell& c1, @@ -2626,8 +2660,11 @@ void RigCaseCellResultsData::computeCompletionTypeForTimeStep( size_t timeStep ) { for ( auto userCalculation : RimProject::current()->gridCalculationCollection()->calculations() ) { - auto gridCalculation = dynamic_cast( userCalculation ); - if ( gridCalculation && gridCalculation->outputEclipseCase() != eclipseCase ) continue; + if ( auto gridCalculation = dynamic_cast( userCalculation ) ) + { + auto outputCases = gridCalculation->outputEclipseCases(); + if ( std::find( outputCases.begin(), outputCases.end(), eclipseCase ) == outputCases.end() ) continue; + } QString generatedPropertyName = RimUserDefinedCalculation::findLeftHandSide( userCalculation->expression() ); if ( generatedPropertyName == propertyName ) diff --git a/ApplicationLibCode/ReservoirDataModel/RigCaseCellResultsData.h b/ApplicationLibCode/ReservoirDataModel/RigCaseCellResultsData.h index c6ac4577c9..d86abf5a26 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigCaseCellResultsData.h +++ b/ApplicationLibCode/ReservoirDataModel/RigCaseCellResultsData.h @@ -29,6 +29,7 @@ #include #include +#include #include class RifReaderInterface; @@ -116,7 +117,7 @@ class RigCaseCellResultsData : public cvf::Object void clearScalarResult( RiaDefines::ResultCatType type, const QString& resultName ); void clearScalarResult( const RigEclipseResultAddress& resultAddress ); void clearAllResults(); - void freeAllocatedResultsData(); + void freeAllocatedResultsData( std::vector categoriesToExclude, std::optional timeStepIndexToRelease ); void eraseAllSourSimData(); void setRemovedTagOnGeneratedResult( const RigEclipseResultAddress& resultAddress ); @@ -162,6 +163,7 @@ class RigCaseCellResultsData : public cvf::Object friend class RigIndexIjkResultCalculator; friend class RigOilVolumeResultCalculator; friend class RigCellVolumeResultCalculator; + friend class RigCellsWithNncsCalculator; size_t findOrLoadKnownScalarResultForTimeStep( const RigEclipseResultAddress& resVarAddr, size_t timeStepIndex ); size_t findOrCreateScalarResultIndex( const RigEclipseResultAddress& resVarAddr, bool needsToBeStored ); @@ -195,6 +197,7 @@ class RigCaseCellResultsData : public cvf::Object void computeIndexResults(); void computeFaultDistance(); + void computeNncsCells(); bool isDataPresent( size_t scalarResultIndex ) const; diff --git a/ApplicationLibCode/ReservoirDataModel/RigFaultReactivationModel.cpp b/ApplicationLibCode/ReservoirDataModel/RigFaultReactivationModel.cpp index be613392c2..e922fa0ece 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigFaultReactivationModel.cpp +++ b/ApplicationLibCode/ReservoirDataModel/RigFaultReactivationModel.cpp @@ -18,28 +18,21 @@ #include "RigFaultReactivationModel.h" +#include "RigFaultReactivationModelGenerator.h" #include "RigGriddedPart3d.h" #include "RigPolyLinesData.h" #include "RimFaultReactivationDataAccess.h" +#include "cafAssert.h" + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RigFaultReactivationModel::RigFaultReactivationModel() - : m_maxZ( 0 ) - , m_minZ( 0 ) - , m_maxHorzExtent( 0 ) - , m_isValid( false ) - , m_cellCountHorzPart1( 1 ) - , m_cellCountHorzPart2( 1 ) - , m_cellCountVertUpper( 1 ) - , m_cellCountVertMiddle( 1 ) - , m_cellCountVertLower( 1 ) - , m_thickness( 1.0 ) - + : m_isValid( false ) { - for ( auto part : allModelParts() ) + for ( int part = 0; part < numModelParts(); part++ ) { m_parts[part] = RigFRModelPart(); m_parts[part].texture = new cvf::TextureImage(); @@ -48,19 +41,15 @@ RigFaultReactivationModel::RigFaultReactivationModel() m_parts[part].rect.reserve( 4 ); } - m_cornerIndexes[ModelParts::HiPart1] = { 2, 3, 7, 6 }; - m_cornerIndexes[ModelParts::MidPart1] = { 1, 2, 6, 5 }; - m_cornerIndexes[ModelParts::LowPart1] = { 0, 1, 5, 4 }; - - m_cornerIndexes[ModelParts::HiPart2] = { 6, 7, 11, 10 }; - m_cornerIndexes[ModelParts::MidPart2] = { 5, 6, 10, 9 }; - m_cornerIndexes[ModelParts::LowPart2] = { 4, 5, 9, 8 }; + m_cornerIndexes[0] = { 0, 1, 7, 6 }; + m_cornerIndexes[1] = { 1, 2, 8, 7 }; + m_cornerIndexes[2] = { 2, 3, 9, 8 }; + m_cornerIndexes[3] = { 3, 4, 10, 9 }; + m_cornerIndexes[4] = { 4, 5, 11, 10 }; for ( auto part : allGridParts() ) { - m_3dparts[part] = std::make_shared( part == GridPart::PART2 ); - - m_cellIndexAdjustmentMap[part] = {}; + m_3dparts[part] = new RigGriddedPart3d(); } } @@ -69,14 +58,11 @@ RigFaultReactivationModel::RigFaultReactivationModel() //-------------------------------------------------------------------------------------------------- RigFaultReactivationModel::~RigFaultReactivationModel() { -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -std::vector RigFaultReactivationModel::allModelParts() const -{ - return { ModelParts::HiPart1, ModelParts::MidPart1, ModelParts::LowPart1, ModelParts::HiPart2, ModelParts::MidPart2, ModelParts::LowPart2 }; + for ( auto part : allGridParts() ) + { + if ( m_3dparts[part] != nullptr ) delete m_3dparts[part]; + m_3dparts[part] = nullptr; + } } //-------------------------------------------------------------------------------------------------- @@ -84,7 +70,7 @@ std::vector RigFaultReactivationModel::allMode //-------------------------------------------------------------------------------------------------- std::vector RigFaultReactivationModel::allGridParts() const { - return { GridPart::PART1, GridPart::PART2 }; + return { GridPart::FW, GridPart::HW }; } //-------------------------------------------------------------------------------------------------- @@ -93,7 +79,8 @@ std::vector RigFaultReactivationModel::allGridPa void RigFaultReactivationModel::reset() { m_isValid = false; - for ( auto part : allModelParts() ) + + for ( int part = 0; part < numModelParts(); part++ ) { m_parts[part].rect.clear(); m_parts[part].rect.reserve( 4 ); @@ -105,17 +92,6 @@ void RigFaultReactivationModel::reset() } } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RigFaultReactivationModel::clearModelData() -{ - for ( auto part : allGridParts() ) - { - m_3dparts[part]->clearModelData(); - } -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -124,27 +100,19 @@ bool RigFaultReactivationModel::isValid() const return m_isValid; } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RigFaultReactivationModel::setPlane( cvf::Vec3d anchorPoint, cvf::Vec3d normal ) -{ - m_planeAnchor = anchorPoint; - m_planeNormal = normal; - reset(); -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RigFaultReactivationModel::setPartColors( cvf::Color3f part1Color, cvf::Color3f part2Color ) { - for ( auto part : { ModelParts::HiPart1, ModelParts::MidPart1, ModelParts::LowPart1 } ) + const int oneSidedParts = numModelParts() / 2; + + for ( int part = 0; part < oneSidedParts; part++ ) { m_parts[part].texture->fill( cvf::Color4ub( part1Color.rByte(), part1Color.gByte(), part1Color.bByte(), 255 ) ); } - for ( auto part : { ModelParts::HiPart2, ModelParts::MidPart2, ModelParts::LowPart2 } ) + for ( int part = oneSidedParts; part < numModelParts(); part++ ) { m_parts[part].texture->fill( cvf::Color4ub( part2Color.rByte(), part2Color.gByte(), part2Color.bByte(), 255 ) ); } @@ -153,167 +121,68 @@ void RigFaultReactivationModel::setPartColors( cvf::Color3f part1Color, cvf::Col //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RigFaultReactivationModel::setMaxExtentFromAnchor( double maxExtentHorz, double minZ, double maxZ ) +void RigFaultReactivationModel::setGenerator( std::shared_ptr generator ) { - m_maxHorzExtent = maxExtentHorz; - m_minZ = minZ; - m_maxZ = maxZ; - reset(); + m_generator = generator; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RigFaultReactivationModel::setFaultPlaneIntersect( cvf::Vec3d faultPlaneTop, cvf::Vec3d faultPlaneBottom ) +std::pair RigFaultReactivationModel::modelLocalNormalsXY() const { - m_faultPlaneIntersectBottom = faultPlaneBottom; - m_faultPlaneIntersectTop = faultPlaneTop; - - reset(); + if ( m_generator.get() == nullptr ) + { + return std::make_pair( cvf::Vec3d( 1.0, 0.0, 0.0 ), cvf::Vec3d( 0.0, 1.0, 0.0 ) ); + } + return m_generator->modelLocalNormalsXY(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RigFaultReactivationModel::setCellCounts( int horzPart1, int horzPart2, int vertUpper, int vertMiddle, int vertLower ) +void RigFaultReactivationModel::updateGeometry( size_t startCell, cvf::StructGridInterface::FaceType startFace ) { - m_cellCountHorzPart1 = horzPart1; - m_cellCountHorzPart2 = horzPart2; - m_cellCountVertUpper = vertUpper; - m_cellCountVertMiddle = vertMiddle; - m_cellCountVertLower = vertLower; - reset(); -} -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RigFaultReactivationModel::setThickness( double thickness ) -{ - m_thickness = thickness; + auto frontPart = m_3dparts[GridPart::FW]; + auto backPart = m_3dparts[GridPart::HW]; - reset(); -} + m_generator->generateGeometry( startCell, startFace, frontPart, backPart ); -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RigFaultReactivationModel::setLocalCoordTransformation( cvf::Mat4d transform ) -{ - m_localCoordTransform = transform; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RigFaultReactivationModel::setUseLocalCoordinates( bool useLocalCoordinates ) -{ - m_3dparts[GridPart::PART1]->setUseLocalCoordinates( useLocalCoordinates ); - m_3dparts[GridPart::PART2]->setUseLocalCoordinates( useLocalCoordinates ); -} - -//-------------------------------------------------------------------------------------------------- -/// 7 -/// 3----------|----------- 11 -/// | | | -/// | | | -/// | | | -/// 2|---------|----------| 10 -/// | \6 | -/// | X Anchor | -/// | \ | -/// 1-------------|------- 9 -/// | 5| | -/// | | | -/// | | | -/// | | | -/// 0-------------|-------- 8 -/// 4 -/// -/// -/// -//-------------------------------------------------------------------------------------------------- -void RigFaultReactivationModel::updateGeometry() -{ - reset(); - - if ( ( m_maxHorzExtent <= 0.0 ) || ( m_minZ == m_maxZ ) ) + if ( backPart->topHeight() > frontPart->topHeight() ) { - return; + m_3dparts[GridPart::HW] = frontPart; + m_3dparts[GridPart::FW] = backPart; } - cvf::Vec3d zDir( 0, 0, 1 ); - - auto alongPlane = m_planeNormal ^ zDir; - alongPlane.normalize(); - - // how far from anchor point we should stop - const double extHorz = m_maxHorzExtent / 2.0; - auto mr = m_planeAnchor + alongPlane * extHorz; - auto ml = m_planeAnchor - alongPlane * extHorz; - - cvf::Vec3dArray points; - points.resize( 12 ); - - points[0] = ml; - points[0].z() = -m_maxZ; + auto& frontPoints = m_generator->frontPoints(); + auto& backPoints = m_generator->backPoints(); - points[1] = ml; - points[1].z() = m_faultPlaneIntersectBottom.z(); + const int oneSideParts = numModelParts() / 2; - points[2] = ml; - points[2].z() = m_faultPlaneIntersectTop.z(); - - points[3] = ml; - points[3].z() = -m_minZ; - - points[4] = m_faultPlaneIntersectBottom; - points[4].z() = -m_maxZ; - - points[5] = m_faultPlaneIntersectBottom; - points[6] = m_faultPlaneIntersectTop; - - points[7] = m_faultPlaneIntersectTop; - points[7].z() = -m_minZ; - - points[8] = mr; - points[8].z() = -m_maxZ; - - points[9] = mr; - points[9].z() = m_faultPlaneIntersectBottom.z(); - - points[10] = mr; - points[10].z() = m_faultPlaneIntersectTop.z(); - - points[11] = mr; - points[11].z() = -m_minZ; - - for ( auto part : allModelParts() ) + for ( int part = 0; part < oneSideParts; part++ ) { for ( auto i : m_cornerIndexes[part] ) { - m_parts[part].rect.push_back( points[i] ); + m_parts[part].rect.push_back( frontPoints[i] ); + } + } + for ( int part = 0; part < oneSideParts; part++ ) + { + for ( auto i : m_cornerIndexes[part] ) + { + m_parts[part + oneSideParts].rect.push_back( backPoints[i] ); } } m_isValid = true; - - generateGrids( points ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -cvf::Vec3d RigFaultReactivationModel::normal() const -{ - return m_planeNormal; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -std::vector RigFaultReactivationModel::rect( RimFaultReactivation::ModelParts part ) const +std::vector RigFaultReactivationModel::rect( int part ) const { return m_parts.at( part ).rect; } @@ -321,7 +190,7 @@ std::vector RigFaultReactivationModel::rect( RimFaultReactivation::M //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -cvf::ref RigFaultReactivationModel::texture( RimFaultReactivation::ModelParts part ) const +cvf::ref RigFaultReactivationModel::texture( int part ) const { return m_parts.at( part ).texture; } @@ -337,29 +206,7 @@ const std::vector>& RigFaultReactivationModel::meshLines //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RigFaultReactivationModel::generateGrids( cvf::Vec3dArray points ) -{ - m_3dparts[GridPart::PART1]->generateGeometry( { points[0], points[1], points[2], points[3], points[4], points[5], points[6], points[7] }, - m_cellCountHorzPart1, - m_cellCountVertLower, - m_cellCountVertMiddle, - m_cellCountVertUpper, - m_thickness ); - m_3dparts[GridPart::PART2]->generateGeometry( { points[8], points[9], points[10], points[11], points[4], points[5], points[6], points[7] }, - m_cellCountHorzPart2, - m_cellCountVertLower, - m_cellCountVertMiddle, - m_cellCountVertUpper, - m_thickness ); - - m_3dparts[GridPart::PART1]->generateLocalNodes( m_localCoordTransform ); - m_3dparts[GridPart::PART2]->generateLocalNodes( m_localCoordTransform ); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -std::shared_ptr RigFaultReactivationModel::grid( RimFaultReactivation::GridPart part ) const +const RigGriddedPart3d* RigFaultReactivationModel::grid( RimFaultReactivation::GridPart part ) const { return m_3dparts.at( part ); } @@ -367,30 +214,17 @@ std::shared_ptr RigFaultReactivationModel::grid( RimFaultReact //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RigFaultReactivationModel::extractModelData( RimFaultReactivationDataAccess* dataAccess, size_t outputTimeStep ) +const cvf::Vec3d RigFaultReactivationModel::faultNormal() const { - for ( auto part : allGridParts() ) - { - dataAccess->useCellIndexAdjustment( m_cellIndexAdjustmentMap[part] ); - m_3dparts[part]->extractModelData( dataAccess, outputTimeStep ); - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RigFaultReactivationModel::generateElementSets( const RimFaultReactivationDataAccess* dataAccess, const RigMainGrid* grid ) -{ - for ( auto part : allGridParts() ) - { - m_3dparts[part]->generateElementSets( dataAccess, grid ); - } + if ( m_generator.get() == nullptr ) return { 0.0, 0.0, 0.0 }; + return m_generator->normal(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RigFaultReactivationModel::generateCellIndexMapping( const RigMainGrid* grid ) +const std::pair RigFaultReactivationModel::faultTopBottom() const { - m_cellIndexAdjustmentMap.clear(); + if ( m_generator.get() == nullptr ) return std::make_pair( cvf::Vec3d(), cvf::Vec3d() ); + return m_generator->faultTopBottomPoints(); } diff --git a/ApplicationLibCode/ReservoirDataModel/RigFaultReactivationModel.h b/ApplicationLibCode/ReservoirDataModel/RigFaultReactivationModel.h index ca198f0d60..afd7077a5c 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigFaultReactivationModel.h +++ b/ApplicationLibCode/ReservoirDataModel/RigFaultReactivationModel.h @@ -25,16 +25,20 @@ #include "cvfMatrix4.h" #include "cvfObject.h" #include "cvfPlane.h" +#include "cvfStructGrid.h" #include "cvfTextureImage.h" #include "cvfVector3.h" +#include #include #include +#include #include class RigGriddedPart3d; class RigMainGrid; class RimFaultReactivationDataAccess; +class RigFaultReactivationModelGenerator; class RigFRModelPart { @@ -52,76 +56,42 @@ class RigFRModelPart //================================================================================================== class RigFaultReactivationModel : public cvf::Object { - using ModelParts = RimFaultReactivation::ModelParts; - using GridPart = RimFaultReactivation::GridPart; + using GridPart = RimFaultReactivation::GridPart; public: RigFaultReactivationModel(); ~RigFaultReactivationModel() override; - std::vector allModelParts() const; - std::vector allGridParts() const; + static int numModelParts() { return 10; }; + std::vector allGridParts() const; bool isValid() const; void reset(); - void setPlane( cvf::Vec3d anchorPoint, cvf::Vec3d normal ); - void setFaultPlaneIntersect( cvf::Vec3d faultPlaneTop, cvf::Vec3d faultPlaneBottom ); - void setMaxExtentFromAnchor( double maxExtentHorz, double minZ, double maxZ ); + void setGenerator( std::shared_ptr generator ); - void setCellCounts( int horzPart1, int horzPart2, int vertUpper, int vertMiddle, int vertLower ); - void setThickness( double thickness ); - void setLocalCoordTransformation( cvf::Mat4d transform ); - void setUseLocalCoordinates( bool useLocalCoordinates ); + std::pair modelLocalNormalsXY() const; - void updateGeometry(); - - cvf::Vec3d normal() const; + void updateGeometry( size_t startCell, cvf::StructGridInterface::FaceType startFace ); void setPartColors( cvf::Color3f part1Color, cvf::Color3f part2Color ); - std::vector rect( ModelParts part ) const; - cvf::ref texture( ModelParts part ) const; + std::vector rect( int nPart ) const; + cvf::ref texture( int nPart ) const; const std::vector>& meshLines( GridPart part ) const; - std::shared_ptr grid( GridPart part ) const; - - void generateCellIndexMapping( const RigMainGrid* grid ); - void generateElementSets( const RimFaultReactivationDataAccess* dataAccess, const RigMainGrid* grid ); - - void clearModelData(); - void extractModelData( RimFaultReactivationDataAccess* dataAccess, size_t outputTimeStep ); + const RigGriddedPart3d* grid( GridPart part ) const; -protected: - void generateGrids( cvf::Vec3dArray points ); + const cvf::Vec3d faultNormal() const; + const std::pair faultTopBottom() const; private: - cvf::Vec3d m_planeNormal; - cvf::Vec3d m_planeAnchor; - - cvf::Vec3d m_faultPlaneIntersectTop; - cvf::Vec3d m_faultPlaneIntersectBottom; - - double m_maxHorzExtent; - double m_minZ; - double m_maxZ; - - double m_thickness; - - int m_cellCountHorzPart1; - int m_cellCountHorzPart2; - int m_cellCountVertUpper; - int m_cellCountVertMiddle; - int m_cellCountVertLower; - - std::map> m_cornerIndexes; - - std::map m_parts; - bool m_isValid; + std::shared_ptr m_generator; - std::map> m_3dparts; + std::array, 5> m_cornerIndexes; + std::array m_parts; - std::map> m_cellIndexAdjustmentMap; + bool m_isValid; - cvf::Mat4d m_localCoordTransform; + std::map m_3dparts; }; diff --git a/ApplicationLibCode/ReservoirDataModel/RigFaultReactivationModelGenerator.cpp b/ApplicationLibCode/ReservoirDataModel/RigFaultReactivationModelGenerator.cpp new file mode 100644 index 0000000000..3f7142df90 --- /dev/null +++ b/ApplicationLibCode/ReservoirDataModel/RigFaultReactivationModelGenerator.cpp @@ -0,0 +1,662 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 "RigFaultReactivationModelGenerator.h" + +#include "RiaApplication.h" + +#include "RigActiveCellInfo.h" +#include "RigFault.h" +#include "RigGriddedPart3d.h" +#include "RigMainGrid.h" + +#include "RimCellFilterCollection.h" +#include "RimEclipseCase.h" +#include "RimEclipseView.h" +#include "RimGridView.h" +#include "RimUserDefinedIndexFilter.h" + +#include "cafHexGridIntersectionTools/cafHexGridIntersectionTools.h" + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RigFaultReactivationModelGenerator::RigFaultReactivationModelGenerator( cvf::Vec3d position, cvf::Vec3d normal ) + : m_startPosition( position ) + , m_normal( normal ) + , m_bufferAboveFault( 0.0 ) + , m_bufferBelowFault( 0.0 ) + , m_startDepth( 0.0 ) + , m_depthBelowFault( 100.0 ) + , m_horzExtentFromFault( 1000.0 ) + , m_modelThickness( 100.0 ) + , m_useLocalCoordinates( false ) + , m_cellSizeHeightFactor( 1.0 ) + , m_cellSizeWidthFactor( 1.0 ) + , m_maxCellHeight( 20.0 ) + , m_minCellWidth( 20.0 ) +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RigFaultReactivationModelGenerator::~RigFaultReactivationModelGenerator() +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigFaultReactivationModelGenerator::setFault( const RigFault* fault ) +{ + m_fault = fault; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigFaultReactivationModelGenerator::setGrid( const RigMainGrid* grid ) +{ + m_grid = grid; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigFaultReactivationModelGenerator::setActiveCellInfo( const RigActiveCellInfo* activeCellInfo ) +{ + m_activeCellInfo = activeCellInfo; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigFaultReactivationModelGenerator::setFaultBufferDepth( double aboveFault, double belowFault ) +{ + m_bufferAboveFault = aboveFault; + m_bufferBelowFault = belowFault; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigFaultReactivationModelGenerator::setModelSize( double startDepth, double depthBelowFault, double horzExtentFromFault ) +{ + m_startDepth = startDepth; + m_depthBelowFault = depthBelowFault; + m_horzExtentFromFault = horzExtentFromFault; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigFaultReactivationModelGenerator::setModelThickness( double thickness ) +{ + m_modelThickness = thickness; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigFaultReactivationModelGenerator::setUseLocalCoordinates( bool useLocalCoordinates ) +{ + m_useLocalCoordinates = useLocalCoordinates; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigFaultReactivationModelGenerator::setModelGriddingOptions( double maxCellHeight, + double cellSizeFactorHeight, + double minCellWidth, + double cellSizeFactorWidth ) +{ + m_maxCellHeight = maxCellHeight; + m_cellSizeHeightFactor = cellSizeFactorHeight; + m_minCellWidth = minCellWidth; + m_cellSizeWidthFactor = cellSizeFactorWidth; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::pair RigFaultReactivationModelGenerator::modelLocalNormalsXY() +{ + cvf::Vec3d xNormal = m_normal ^ cvf::Vec3d::Z_AXIS; + xNormal.z() = 0.0; + xNormal.normalize(); + + cvf::Vec3d yNormal = xNormal ^ cvf::Vec3d::Z_AXIS; + + return std::make_pair( xNormal, yNormal ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigFaultReactivationModelGenerator::setupLocalCoordinateTransform() +{ + auto [xNormal, yNormal] = modelLocalNormalsXY(); + + m_localCoordTransform = cvf::Mat4d::fromCoordSystemAxes( &xNormal, &yNormal, &cvf::Vec3d::Z_AXIS ); + cvf::Vec3d center = m_startPosition * -1.0; + center.z() = 0.0; + center.transformPoint( m_localCoordTransform ); + m_localCoordTransform.setTranslation( center ); +} + +//-------------------------------------------------------------------------------------------------- +/// change corner order to be consistent so that index (0,1) and (2,3) gives the lower and upper horz. lines no matter what I or J face we +/// have +//-------------------------------------------------------------------------------------------------- +const std::array RigFaultReactivationModelGenerator::faceIJCornerIndexes( cvf::StructGridInterface::FaceType face ) +{ + switch ( face ) + { + case cvf::StructGridInterface::POS_I: + case cvf::StructGridInterface::NEG_J: + return { 0, 1, 3, 2 }; + + case cvf::StructGridInterface::NEG_I: + case cvf::StructGridInterface::POS_J: + return { 0, 3, 1, 2 }; + + case cvf::StructGridInterface::POS_K: + case cvf::StructGridInterface::NEG_K: + case cvf::StructGridInterface::NO_FACE: + default: + break; + } + + CVF_ASSERT( false ); // not supported for K faces + return { 0, 0, 0, 0 }; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::Vec3d RigFaultReactivationModelGenerator::lineIntersect( const cvf::Plane& plane, cvf::Vec3d lineA, cvf::Vec3d lineB ) +{ + double dist = 0.0; + return caf::HexGridIntersectionTools::planeLineIntersectionForMC( plane, lineA, lineB, &dist ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +size_t RigFaultReactivationModelGenerator::oppositeStartCellIndex( const std::vector cellIndexColumn, + cvf::StructGridInterface::FaceType face ) +{ + auto oppositeStartFace = cvf::StructGridInterface::oppositeFace( face ); + bool bFoundOppositeCell = false; + size_t oppositeCellIdx = 0; + + for ( auto backCellIdx : cellIndexColumn ) + { + for ( auto& faultFace : m_fault->faultFaces() ) + { + if ( ( faultFace.m_nativeFace == face ) && ( faultFace.m_nativeReservoirCellIndex == backCellIdx ) ) + { + bFoundOppositeCell = true; + oppositeCellIdx = faultFace.m_oppositeReservoirCellIndex; + break; + } + else if ( ( faultFace.m_nativeFace == oppositeStartFace ) && ( faultFace.m_oppositeReservoirCellIndex == backCellIdx ) ) + { + bFoundOppositeCell = true; + oppositeCellIdx = faultFace.m_nativeReservoirCellIndex; + break; + } + } + + if ( bFoundOppositeCell ) break; + } + + return oppositeCellIdx; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigFaultReactivationModelGenerator::addFilter( QString name, std::vector cells ) +{ + RimEclipseView* view = dynamic_cast( RiaApplication::instance()->activeGridView() ); + if ( view == nullptr ) return; + + auto cellFilters = view->cellFilterCollection(); + if ( cellFilters == nullptr ) return; + + auto eCase = cellFilters->firstAncestorOfType(); + auto filter = cellFilters->addNewUserDefinedIndexFilter( eCase, cells ); + filter->setName( name ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +const std::array& RigFaultReactivationModelGenerator::frontPoints() const +{ + return m_frontPoints; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +const std::array& RigFaultReactivationModelGenerator::backPoints() const +{ + return m_backPoints; +} + +//-------------------------------------------------------------------------------------------------- +/// <---- fault normal * +/// * +/// 15 * +/// 7---------|------------ 23 top model * +/// | | | * +/// | | | * +/// 6|_____14_|___________| 22 top fault w/buffer * +/// 5|-----13-\-----------| 21 top fault front * +/// 4|---------\-12-------| 20 top fault back * +/// | X | start position in fault (user selected) * +/// 3|--------11-\--------| 19 bottom fault front * +/// 2|------------\-10----| 18 bottom fault back * +/// 1|_____________\______| 17 bottom fault w/buffer * +/// | 9| | * +/// | | | * +/// | | | * +/// 0--------------|------- 16 bottom model * +/// 8 * +/// front back * +//-------------------------------------------------------------------------------------------------- +void RigFaultReactivationModelGenerator::generatePointsFrontBack() +{ + std::array points; + + auto alongModel = m_normal ^ cvf::Vec3d::Z_AXIS; + alongModel.normalize(); + + double top_depth = -m_startDepth; + double bottom_depth = m_bottomFault.z() - m_depthBelowFault; + + cvf::Vec3d edge_front = m_startPosition - m_horzExtentFromFault * alongModel; + cvf::Vec3d edge_back = m_startPosition + m_horzExtentFromFault * alongModel; + + points[8] = m_bottomFault; + points[8].z() = bottom_depth; + + points[9] = m_bottomFault; + points[10] = m_bottomReservoirBack; + points[11] = m_bottomReservoirFront; + points[12] = m_topReservoirBack; + points[13] = m_topReservoirFront; + points[14] = m_topFault; + + points[15] = m_topFault; + points[15].z() = top_depth; + + for ( int i = 0; i < 8; i++ ) + { + points[i] = edge_front; + points[i].z() = points[i + 8].z(); + } + + for ( int i = 16; i < 24; i++ ) + { + points[i] = edge_back; + points[i].z() = points[i - 8].z(); + } + + std::array frontPoints; + std::array backPoints; + + // only return the corner points used for each part + std::vector frontMap = { 0, 1, 3, 5, 6, 7, 8, 9, 11, 13, 14, 15 }; + std::vector backMap = { 16, 17, 18, 20, 22, 23, 8, 9, 10, 12, 14, 15 }; + + for ( int i = 0; i < 12; i++ ) + { + m_frontPoints[i] = points[frontMap[i]]; + m_backPoints[i] = points[backMap[i]]; + } + + m_horizontalPartition = partition( m_startPosition.pointDistance( edge_front ), m_minCellWidth, m_cellSizeWidthFactor ); + // we start gridding from the far edges of the model, reverse the partition + std::reverse( m_horizontalPartition.begin(), m_horizontalPartition.end() ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +const std::vector RigFaultReactivationModelGenerator::partition( double distance, double startSize, double sizeFactor ) +{ + std::vector parts; + + double d = 0; + double step = startSize; + + while ( d < distance ) + { + parts.push_back( d / distance ); + d += step; + step *= sizeFactor; + } + + // get rid of outermost cell column if too small + if ( distance * ( 1.0 - parts.back() ) < startSize ) parts.pop_back(); + + parts.push_back( 1.0 ); + + return parts; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RigFaultReactivationModelGenerator::elementKLayers( const std::vector& cellIndexColumn ) +{ + std::vector kLayers; + + size_t i, j, k; + for ( auto idx : cellIndexColumn ) + { + m_grid->ijkFromCellIndexUnguarded( idx, &i, &j, &k ); + + if ( m_activeCellInfo->isActive( idx ) ) + { + kLayers.push_back( (int)k ); + } + else + { + kLayers.push_back( -1 * (int)k ); + } + } + + std::reverse( kLayers.begin(), kLayers.end() ); + + return kLayers; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigFaultReactivationModelGenerator::generateGeometry( size_t startCellIndex, + cvf::StructGridInterface::FaceType startFace, + RigGriddedPart3d* frontPart, + RigGriddedPart3d* backPart ) +{ + std::vector cellColumnBackSearch; + std::vector cellColumnBack; + std::vector cellColumnFront; + size_t i, j, k; + + // build column of cells behind fault + m_grid->ijkFromCellIndexUnguarded( startCellIndex, &i, &j, &k ); + cellColumnBackSearch.push_back( startCellIndex ); // want the user clicked cell to be the first in the search list + + for ( size_t kLayer = 0; kLayer < m_grid->cellCountK(); kLayer++ ) + { + if ( !m_grid->isCellValid( i, j, kLayer ) ) continue; + + auto cellIdx = m_grid->cellIndexFromIJKUnguarded( i, j, kLayer ); + + if ( cellIdx != startCellIndex ) cellColumnBackSearch.push_back( cellIdx ); + cellColumnBack.push_back( cellIdx ); + } + + // build cell column of cells in front of fault, opposite to the cell column behind the fault + auto oppositeStartFace = cvf::StructGridInterface::oppositeFace( startFace ); + size_t oppositeCellIdx = oppositeStartCellIndex( cellColumnBackSearch, startFace ); + + m_grid->ijkFromCellIndexUnguarded( oppositeCellIdx, &i, &j, &k ); + for ( size_t kLayer = 0; kLayer < m_grid->cellCountK(); kLayer++ ) + { + if ( !m_grid->isCellValid( i, j, kLayer ) ) continue; + + auto cellIdx = m_grid->cellIndexFromIJKUnguarded( i, j, kLayer ); + + cellColumnFront.push_back( cellIdx ); + } + + auto zPositionsBack = elementLayers( startFace, cellColumnBack ); + auto zPositionsFront = elementLayers( oppositeStartFace, cellColumnFront ); + auto kLayersBack = elementKLayers( cellColumnBack ); + auto kLayersFront = elementKLayers( cellColumnFront ); + + // add extra fault buffer below the fault, starting at the deepest bottom-most cell on either side of the fault + + double front_bottom = zPositionsFront.begin()->first; + double back_bottom = zPositionsBack.begin()->first; + m_bottomReservoirFront = zPositionsFront.begin()->second; + m_bottomReservoirBack = zPositionsBack.begin()->second; + + cvf::Vec3d bottom_point = m_bottomReservoirFront; + + if ( front_bottom > back_bottom ) + { + bottom_point = extrapolatePoint( ( ++zPositionsBack.begin() )->second, zPositionsBack.begin()->second, m_bufferBelowFault ); + } + else if ( front_bottom < back_bottom ) + { + bottom_point = extrapolatePoint( ( ++zPositionsFront.begin() )->second, zPositionsFront.begin()->second, m_bufferBelowFault ); + } + + m_bottomFault = bottom_point; + + // add extra fault buffer above the fault, starting at the shallowest top-most cell on either side of the fault + + double front_top = zPositionsFront.rbegin()->first; + double back_top = zPositionsBack.rbegin()->first; + m_topReservoirFront = zPositionsFront.rbegin()->second; + m_topReservoirBack = zPositionsBack.rbegin()->second; + + cvf::Vec3d top_point = m_topReservoirFront; + if ( front_top > back_top ) + { + top_point = extrapolatePoint( ( ++zPositionsFront.rbegin() )->second, zPositionsFront.rbegin()->second, m_bufferAboveFault ); + } + else if ( front_top < back_top ) + { + top_point = extrapolatePoint( ( ++zPositionsBack.rbegin() )->second, zPositionsBack.rbegin()->second, m_bufferAboveFault ); + } + m_topFault = top_point; + + splitLargeLayers( zPositionsFront, kLayersFront, m_maxCellHeight ); + splitLargeLayers( zPositionsBack, kLayersBack, m_maxCellHeight ); + + std::vector frontReservoirLayers; + for ( auto& kvp : zPositionsFront ) + frontReservoirLayers.push_back( kvp.second ); + + std::vector backReservoirLayers; + for ( auto& kvp : zPositionsBack ) + backReservoirLayers.push_back( kvp.second ); + + generatePointsFrontBack(); + + frontPart->generateGeometry( m_frontPoints, + frontReservoirLayers, + kLayersFront, + m_maxCellHeight, + m_cellSizeHeightFactor, + m_horizontalPartition, + m_modelThickness, + m_topReservoirFront.z() ); + backPart->generateGeometry( m_backPoints, + backReservoirLayers, + kLayersBack, + m_maxCellHeight, + m_cellSizeHeightFactor, + m_horizontalPartition, + m_modelThickness, + m_topReservoirBack.z() ); + + frontPart->generateLocalNodes( m_localCoordTransform ); + backPart->generateLocalNodes( m_localCoordTransform ); + + frontPart->setUseLocalCoordinates( m_useLocalCoordinates ); + backPart->setUseLocalCoordinates( m_useLocalCoordinates ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::map RigFaultReactivationModelGenerator::elementLayers( cvf::StructGridInterface::FaceType face, + std::vector& cellIndexColumn ) +{ + cvf::Plane modelPlane; + modelPlane.setFromPointAndNormal( m_startPosition, m_normal ); + + auto cornerIndexes = faceIJCornerIndexes( face ); + + std::map zPositions; + + std::vector okCells; + + for ( auto cellIdx : cellIndexColumn ) + { + RigCell cell = m_grid->cell( cellIdx ); + auto corners = cell.faceCorners( face ); + + cvf::Vec3d intersect1 = lineIntersect( modelPlane, corners[cornerIndexes[0]], corners[cornerIndexes[1]] ); + cvf::Vec3d intersect2 = lineIntersect( modelPlane, corners[cornerIndexes[2]], corners[cornerIndexes[3]] ); + + if ( intersect1.z() != intersect2.z() ) + { + zPositions[intersect1.z()] = intersect1; + zPositions[intersect2.z()] = intersect2; + okCells.push_back( cellIdx ); + } + } + + // only keep cells that have a valid height at the plane intersection + cellIndexColumn.clear(); + for ( auto idx : okCells ) + { + cellIndexColumn.push_back( idx ); + } + + return zPositions; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::Vec3d RigFaultReactivationModelGenerator::extrapolatePoint( cvf::Vec3d startPoint, cvf::Vec3d endPoint, double buffer ) +{ + cvf::Vec3d direction = endPoint - startPoint; + direction.normalize(); + + return endPoint + ( buffer * direction ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigFaultReactivationModelGenerator::splitLargeLayers( std::map& layers, std::vector& kLayers, double maxHeight ) +{ + std::vector additionalPoints; + + std::pair prevLayer; + std::vector newKLayers; + + bool first = true; + int k = 0; + + const int nLayers = (int)layers.size(); + int n = 0; + + for ( auto& layer : layers ) + { + if ( n++ == ( nLayers - 1 ) ) break; + + if ( first ) + { + prevLayer = layer; + first = false; + newKLayers.push_back( kLayers[k++] ); + continue; + } + + if ( std::abs( prevLayer.first - layer.first ) > maxHeight ) + { + const auto& points = interpolateExtraPoints( prevLayer.second, layer.second, maxHeight ); + for ( auto& p : points ) + { + additionalPoints.push_back( p ); + newKLayers.push_back( kLayers[k - 1] ); + } + } + + prevLayer = layer; + newKLayers.push_back( kLayers[k++] ); + } + + for ( auto& p : additionalPoints ) + { + layers[p.z()] = p; + } + + kLayers.clear(); + for ( auto k : newKLayers ) + { + kLayers.push_back( k ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +const std::vector RigFaultReactivationModelGenerator::interpolateExtraPoints( cvf::Vec3d from, cvf::Vec3d to, double maxStep ) +{ + std::vector points; + + const double distance = from.pointDistance( to ); + const int nSteps = (int)std::ceil( distance / maxStep ); + const double stepSize = distance / nSteps; + + auto stepVec = to - from; + stepVec.normalize(); + stepVec *= stepSize; + + cvf::Vec3d p = from; + + for ( int i = 1; i < nSteps; i++ ) + { + p += stepVec; + points.push_back( p ); + } + + return points; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +const cvf::Vec3d RigFaultReactivationModelGenerator::normal() const +{ + return m_normal; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +const std::pair RigFaultReactivationModelGenerator::faultTopBottomPoints() const +{ + return std::make_pair( m_topFault, m_bottomFault ); +} diff --git a/ApplicationLibCode/ReservoirDataModel/RigFaultReactivationModelGenerator.h b/ApplicationLibCode/ReservoirDataModel/RigFaultReactivationModelGenerator.h new file mode 100644 index 0000000000..b73f5ce417 --- /dev/null +++ b/ApplicationLibCode/ReservoirDataModel/RigFaultReactivationModelGenerator.h @@ -0,0 +1,121 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 "cvfMatrix4.h" +#include "cvfObject.h" +#include "cvfPlane.h" +#include "cvfStructGrid.h" +#include "cvfVector3.h" + +#include +#include +#include + +#include + +class RigFault; +class RigMainGrid; +class RigGriddedPart3d; +class RigActiveCellInfo; + +class RigFaultReactivationModelGenerator : cvf::Object +{ +public: + RigFaultReactivationModelGenerator( cvf::Vec3d position, cvf::Vec3d normal ); + ~RigFaultReactivationModelGenerator(); + + void setFault( const RigFault* fault ); + void setGrid( const RigMainGrid* grid ); + void setActiveCellInfo( const RigActiveCellInfo* activeCellInfo ); + void setFaultBufferDepth( double aboveFault, double belowFault ); + void setModelSize( double startDepth, double depthBelowFault, double horzExtentFromFault ); + void setModelThickness( double thickness ); + void setModelGriddingOptions( double maxCellHeight, double cellSizeFactorHeight, double minCellWidth, double cellSizeFactorWidth ); + + void setUseLocalCoordinates( bool useLocalCoordinates ); + void setupLocalCoordinateTransform(); + + std::pair modelLocalNormalsXY(); + + void generateGeometry( size_t startCellIndex, + cvf::StructGridInterface::FaceType startFace, + RigGriddedPart3d* frontPart, + RigGriddedPart3d* backPart ); + + const std::array& frontPoints() const; + const std::array& backPoints() const; + const cvf::Vec3d normal() const; + const std::pair faultTopBottomPoints() const; + +protected: + static const std::array faceIJCornerIndexes( cvf::StructGridInterface::FaceType face ); + static const std::vector interpolateExtraPoints( cvf::Vec3d from, cvf::Vec3d to, double maxStep ); + static const std::vector partition( double distance, double startSize, double sizeFactor ); + + static cvf::Vec3d lineIntersect( const cvf::Plane& plane, cvf::Vec3d lineA, cvf::Vec3d lineB ); + static cvf::Vec3d extrapolatePoint( cvf::Vec3d startPoint, cvf::Vec3d endPoint, double stopDepth ); + static void splitLargeLayers( std::map& layers, std::vector& kLayers, double maxHeight ); + + std::map elementLayers( cvf::StructGridInterface::FaceType face, std::vector& cellIndexColumn ); + std::vector elementKLayers( const std::vector& cellIndexColumn ); + + void addFilter( QString name, std::vector cells ); + + size_t oppositeStartCellIndex( const std::vector cellIndexColumn, cvf::StructGridInterface::FaceType face ); + + void generatePointsFrontBack(); + +private: + cvf::Vec3d m_startPosition; + cvf::Vec3d m_normal; + + std::array m_frontPoints; + std::array m_backPoints; + + std::vector m_horizontalPartition; + + cvf::cref m_fault; + cvf::cref m_grid; + cvf::cref m_activeCellInfo; + + double m_bufferAboveFault; + double m_bufferBelowFault; + + double m_startDepth; + double m_depthBelowFault; + double m_horzExtentFromFault; + double m_modelThickness; + + double m_maxCellHeight; + double m_cellSizeHeightFactor; + double m_minCellWidth; + double m_cellSizeWidthFactor; + + cvf::Vec3d m_topReservoirFront; + cvf::Vec3d m_topReservoirBack; + + cvf::Vec3d m_bottomReservoirFront; + cvf::Vec3d m_bottomReservoirBack; + + cvf::Vec3d m_topFault; + cvf::Vec3d m_bottomFault; + + cvf::Mat4d m_localCoordTransform; + bool m_useLocalCoordinates; +}; diff --git a/ApplicationLibCode/ReservoirDataModel/RigGridBase.cpp b/ApplicationLibCode/ReservoirDataModel/RigGridBase.cpp index 27d593d5e9..728012823a 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigGridBase.cpp +++ b/ApplicationLibCode/ReservoirDataModel/RigGridBase.cpp @@ -218,6 +218,34 @@ bool RigGridBase::ijkFromCellIndex( size_t cellIndex, size_t* i, size_t* j, size return true; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::optional RigGridBase::ijkFromCellIndex( size_t cellIndex ) const +{ + size_t i, j, k; + if ( ijkFromCellIndex( cellIndex, &i, &j, &k ) ) + { + return caf::VecIjk( i, j, k ); + } + + return std::nullopt; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::optional RigGridBase::ijkFromCellIndexOneBased( size_t cellIndex ) const +{ + size_t i, j, k; + if ( ijkFromCellIndex( cellIndex, &i, &j, &k ) ) + { + return caf::VecIjk( ++i, ++j, ++k ); + } + + return std::nullopt; +} + //-------------------------------------------------------------------------------------------------- /// This version does no if-guarding. Check that all dimensions of the grid are non-zero before using. /// Useful for running in a loop after doing the sanity check once. diff --git a/ApplicationLibCode/ReservoirDataModel/RigGridBase.h b/ApplicationLibCode/ReservoirDataModel/RigGridBase.h index 8ee20bd339..06a1d9c539 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigGridBase.h +++ b/ApplicationLibCode/ReservoirDataModel/RigGridBase.h @@ -23,11 +23,13 @@ #include "RifReaderInterface.h" #include "RigFault.h" +#include "cafVecIjk.h" #include "cvfBoundingBox.h" #include "cvfStructGrid.h" #include "cvfStructGridGeometryGenerator.h" #include "cvfVector3.h" +#include #include #include @@ -95,6 +97,9 @@ class RigGridBase : public cvf::StructGridInterface bool ijkFromCellIndex( size_t cellIndex, size_t* i, size_t* j, size_t* k ) const override; void ijkFromCellIndexUnguarded( size_t cellIndex, size_t* i, size_t* j, size_t* k ) const; + std::optional ijkFromCellIndex( size_t cellIndex ) const; + std::optional ijkFromCellIndexOneBased( size_t cellIndex ) const; + bool cellIJKFromCoordinate( const cvf::Vec3d& coord, size_t* i, size_t* j, size_t* k ) const override; void cellCornerVertices( size_t cellIndex, cvf::Vec3d vertices[8] ) const override; cvf::Vec3d cellCentroid( size_t cellIndex ) const override; diff --git a/ApplicationLibCode/ReservoirDataModel/RigGriddedPart3d.cpp b/ApplicationLibCode/ReservoirDataModel/RigGriddedPart3d.cpp index b993656473..cc7ac64de7 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigGriddedPart3d.cpp +++ b/ApplicationLibCode/ReservoirDataModel/RigGriddedPart3d.cpp @@ -21,15 +21,20 @@ #include "RigMainGrid.h" #include "RimFaultReactivationDataAccess.h" +#include "RimFaultReactivationEnums.h" #include "cvfBoundingBox.h" #include "cvfTextureImage.h" +#include +#include + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RigGriddedPart3d::RigGriddedPart3d( bool flipFrontBack ) +RigGriddedPart3d::RigGriddedPart3d() : m_useLocalCoordinates( false ) + , m_topHeight( 0.0 ) { } @@ -53,16 +58,16 @@ void RigGriddedPart3d::reset() m_elementIndices.clear(); m_meshLines.clear(); m_elementSets.clear(); - - clearModelData(); + m_elementKLayer.clear(); + m_elementLayers.clear(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RigGriddedPart3d::clearModelData() +std::vector RigGriddedPart3d::allRegions() { - m_nodePorePressure.clear(); + return { Regions::LowerUnderburden, Regions::UpperUnderburden, Regions::Reservoir, Regions::LowerOverburden, Regions::UpperOverburden }; } //-------------------------------------------------------------------------------------------------- @@ -74,81 +79,265 @@ cvf::Vec3d RigGriddedPart3d::stepVector( cvf::Vec3d start, cvf::Vec3d stop, int return vec.getNormalized() * ( vec.length() / nSteps ); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RigGriddedPart3d::generateConstantLayers( double zFrom, double zTo, double maxSize ) +{ + std::vector layers; + + double diff = zTo - zFrom; + + if ( diff == 0.0 ) return layers; + + if ( std::abs( diff ) <= maxSize ) + { + layers.push_back( std::min( zFrom, zTo ) ); + return layers; + } + + double steps = std::abs( diff / maxSize ); + + int nSteps = (int)std::ceil( steps ); + + double stepSize = diff / nSteps; + + for ( int i = 0; i < nSteps; i++ ) + { + layers.push_back( zFrom + stepSize * i ); + } + + std::sort( layers.begin(), layers.end() ); + + return layers; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RigGriddedPart3d::generateGrowingLayers( double zFrom, double zTo, double maxSize, double growfactor ) +{ + std::vector layers; + + double diff = zTo - zFrom; + if ( std::abs( diff ) <= maxSize ) + { + layers.push_back( std::min( zFrom, zTo ) ); + return layers; + } + + double startHeight = maxSize; + double curDepth = zFrom; + + if ( zTo < zFrom ) + { + while ( curDepth > zTo ) + { + layers.push_back( curDepth ); + curDepth -= startHeight; + startHeight *= growfactor; + } + } + else if ( zTo > zFrom ) + { + while ( curDepth < zTo ) + { + layers.push_back( curDepth ); + curDepth += startHeight; + startHeight *= growfactor; + } + } + + if ( std::abs( zTo - layers.back() ) < maxSize ) layers.pop_back(); + layers.push_back( zTo ); + + std::sort( layers.begin(), layers.end() ); + + return layers; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RigGriddedPart3d::extractZValues( std::vector points ) +{ + std::vector layers; + + for ( auto& p : points ) + { + layers.push_back( p.z() ); + } + + return layers; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigGriddedPart3d::updateReservoirElementLayers( const std::vector& reservoirLayers, const std::vector& kLayers ) +{ + const int nLayers = (int)reservoirLayers.size(); + + if ( nLayers < 2 ) return; + + int prevLayer = kLayers[0]; + double start = reservoirLayers[0].z(); + + for ( int l = 1; l < nLayers; l++ ) + { + auto currentZone = ( prevLayer >= 0 ) ? ElementSets::Reservoir : ElementSets::IntraReservoir; + + if ( l == nLayers - 1 ) + { + m_elementLayers[currentZone].push_back( std::make_pair( start, reservoirLayers[l].z() ) ); + continue; + } + + if ( ( ( prevLayer < 0 ) && ( kLayers[l] >= 0 ) ) || ( ( prevLayer >= 0 ) && ( kLayers[l] < 0 ) ) ) + { + m_elementLayers[currentZone].push_back( std::make_pair( start, reservoirLayers[l].z() ) ); + start = reservoirLayers[l].z(); + } + prevLayer = kLayers[l]; + } +} + //-------------------------------------------------------------------------------------------------- /// Point index in input /// /// -/// 3 ----------- 7 * -/// | | * -/// | | * -/// | | * -/// 2 |---------| 6 * -/// | \ * -/// | \ * -/// | \ * -/// 1 -------------| 5 * -/// | | * -/// | | * -/// | | * -/// | | * -/// 0 -------------- 4 * +/// 5 ------| 11 * +/// | OU | Overburden Upper * +/// 4 |------\10 * +/// | OL \ Overburden Lower * +/// 3 |--------\ 9 * +/// | \ * +/// | R \ Reservoir * +/// 2 |___________\ 8 * +/// | UU \ Underburden Upper * +/// 1 |-------------\7 * +/// | | * +/// | UL | Underburden Lower * +/// | | * +/// 0 -------------- 6 * /// -/// Assumes 0->4, 1->5, 2->6 and 3->7 is parallel +/// Assumes horizontal lines are parallel /// /// //-------------------------------------------------------------------------------------------------- -void RigGriddedPart3d::generateGeometry( std::vector inputPoints, - int nHorzCells, - int nVertCellsLower, - int nVertCellsMiddle, - int nVertCellsUpper, - double thickness ) +void RigGriddedPart3d::generateGeometry( const std::array& inputPoints, + const std::vector& reservoirLayers, + const std::vector& kLayers, + const double maxCellHeight, + double cellSizeFactor, + const std::vector& horizontalPartition, + double modelThickness, + double topHeight ) { reset(); - const cvf::Vec3d step0to1 = stepVector( inputPoints[0], inputPoints[1], nVertCellsLower ); - const cvf::Vec3d step1to2 = stepVector( inputPoints[1], inputPoints[2], nVertCellsMiddle ); - const cvf::Vec3d step2to3 = stepVector( inputPoints[2], inputPoints[3], nVertCellsUpper ); + m_topHeight = topHeight; - const cvf::Vec3d step4to5 = stepVector( inputPoints[4], inputPoints[5], nVertCellsLower ); - const cvf::Vec3d step5to6 = stepVector( inputPoints[5], inputPoints[6], nVertCellsMiddle ); - const cvf::Vec3d step6to7 = stepVector( inputPoints[6], inputPoints[7], nVertCellsUpper ); + std::map> layersPerRegion; - const cvf::Vec3d step0to4 = stepVector( inputPoints[0], inputPoints[4], nHorzCells ); + layersPerRegion[Regions::LowerUnderburden] = generateGrowingLayers( inputPoints[1].z(), inputPoints[0].z(), maxCellHeight, cellSizeFactor ); + layersPerRegion[Regions::UpperUnderburden] = generateConstantLayers( inputPoints[1].z(), inputPoints[2].z(), maxCellHeight ); + layersPerRegion[Regions::Reservoir] = extractZValues( reservoirLayers ); + layersPerRegion[Regions::LowerOverburden] = generateConstantLayers( inputPoints[3].z(), inputPoints[4].z(), maxCellHeight ); + layersPerRegion[Regions::UpperOverburden] = generateGrowingLayers( inputPoints[4].z(), inputPoints[5].z(), maxCellHeight, cellSizeFactor ); - cvf::Vec3d tVec = step0to4 ^ step0to1; - tVec.normalize(); - tVec *= thickness; + layersPerRegion[Regions::LowerUnderburden].pop_back(); // to avoid overlap with bottom of next region + layersPerRegion[Regions::Reservoir].pop_back(); // to avoid overlap with bottom of next region - const std::vector m_thicknessFactors = { -1.0, 0.0, 1.0 }; - const int nThicknessCells = 2; - const int nVertCells = nVertCellsLower + nVertCellsMiddle + nVertCellsUpper; + m_elementLayers[ElementSets::OverBurden] = { std::make_pair( inputPoints[3].z(), inputPoints[5].z() ) }; + m_elementLayers[ElementSets::UnderBurden] = { std::make_pair( inputPoints[0].z(), inputPoints[2].z() ) }; - const std::vector vertLines = { nVertCellsLower, nVertCellsMiddle, nVertCellsUpper + 1 }; - const std::vector firstSteps = { step0to1, step1to2, step2to3 }; - const std::vector lastSteps = { step4to5, step5to6, step6to7 }; + updateReservoirElementLayers( reservoirLayers, kLayers ); - // ** generate nodes + size_t nVertCells = 0; + size_t nHorzCells = horizontalPartition.size() - 1; - m_boundaryNodes[Boundary::Bottom] = {}; - m_boundaryNodes[Boundary::FarSide] = {}; + for ( auto region : allRegions() ) + { + nVertCells += layersPerRegion[region].size(); + } - m_nodes.reserve( (size_t)( ( nVertCells + 1 ) * ( nHorzCells + 1 ) ) ); + const std::vector m_thicknessFactors = { -1.0, 0.0, 1.0 }; + const int nThicknessCells = 2; + cvf::Vec3d tVec = stepVector( inputPoints[0], inputPoints[6], 1 ) ^ cvf::Vec3d::Z_AXIS; + tVec.normalize(); + tVec *= modelThickness; - cvf::Vec3d pFrom = inputPoints[0]; - cvf::Vec3d pTo = inputPoints[4]; + m_nodes.reserve( ( nVertCells + 1 ) * ( nHorzCells + 1 ) * ( nThicknessCells + 1 ) ); - unsigned int layer = 0; unsigned int nodeIndex = 0; + unsigned int layer = 0; + + cvf::Vec3d fromPos; + cvf::Vec3d toPos; + cvf::Vec3d fromStep; + cvf::Vec3d toStep; - for ( int i = 0; i < (int)vertLines.size(); i++ ) + for ( auto region : allRegions() ) { - for ( int v = 0; v < vertLines[i]; v++, layer++ ) + switch ( region ) { - cvf::Vec3d stepHorz = stepVector( pFrom, pTo, nHorzCells ); - cvf::Vec3d p = pFrom; - for ( int h = 0; h <= nHorzCells; h++ ) + case Regions::LowerUnderburden: + fromPos = inputPoints[0]; + toPos = inputPoints[6]; + fromStep = cvf::Vec3d( 0, 0, 0 ); + toStep = cvf::Vec3d( 0, 0, 0 ); + break; + + case Regions::UpperUnderburden: + fromPos = inputPoints[1]; + toPos = inputPoints[7]; + fromStep = stepVector( inputPoints[1], inputPoints[2], (int)layersPerRegion[region].size() ); + toStep = stepVector( inputPoints[7], inputPoints[8], (int)layersPerRegion[region].size() ); + break; + + case Regions::Reservoir: + fromPos = inputPoints[2]; + toPos = inputPoints[8]; + break; + + case Regions::LowerOverburden: + fromPos = inputPoints[3]; + toPos = inputPoints[9]; + fromStep = stepVector( inputPoints[3], inputPoints[4], (int)layersPerRegion[region].size() ); + toStep = stepVector( inputPoints[9], inputPoints[10], (int)layersPerRegion[region].size() ); + break; + + case Regions::UpperOverburden: + fromPos = inputPoints[4]; + toPos = inputPoints[10]; + fromStep = cvf::Vec3d( 0, 0, 0 ); + toStep = cvf::Vec3d( 0, 0, 0 ); + break; + } + + for ( int v = 0; v < (int)layersPerRegion[region].size(); v++, layer++ ) + { + if ( ( region == Regions::LowerUnderburden ) || ( region == Regions::UpperOverburden ) ) + { + fromPos.z() = layersPerRegion[region][v]; + toPos.z() = layersPerRegion[region][v]; + } + else if ( region == Regions::Reservoir ) + { + toPos = reservoirLayers[v]; + fromPos.z() = toPos.z(); + } + + cvf::Vec3d stepHorz = toPos - fromPos; + cvf::Vec3d p; + + m_meshLines.push_back( { fromPos, toPos } ); + + for ( int h = 0; h <= (int)nHorzCells; h++ ) { + p = toPos - horizontalPartition[h] * stepHorz; + for ( int t = 0; t <= nThicknessCells; t++, nodeIndex++ ) { m_nodes.push_back( p + m_thicknessFactors[t] * tVec ); @@ -161,42 +350,65 @@ void RigGriddedPart3d::generateGeometry( std::vector inputPoints, m_boundaryNodes[Boundary::FarSide].push_back( nodeIndex ); } } + } - p += stepHorz; + if ( region != Regions::Reservoir ) + { + fromPos += fromStep; + toPos += toStep; } - pFrom += firstSteps[i]; - pTo += lastSteps[i]; } } // ** generate elements of type hex8 - m_elementIndices.resize( (size_t)( nVertCells * nHorzCells * nThicknessCells ) ); + m_elementIndices.resize( (size_t)( ( nVertCells - 1 ) * nHorzCells * nThicknessCells ) ); + m_elementKLayer.resize( (size_t)( ( nVertCells - 1 ) * nHorzCells * nThicknessCells ) ); + m_borderSurfaceElements[RimFaultReactivation::BorderSurface::Seabed] = {}; m_borderSurfaceElements[RimFaultReactivation::BorderSurface::UpperSurface] = {}; m_borderSurfaceElements[RimFaultReactivation::BorderSurface::FaultSurface] = {}; m_borderSurfaceElements[RimFaultReactivation::BorderSurface::LowerSurface] = {}; + m_elementSets[ElementSets::OverBurden] = {}; + m_elementSets[ElementSets::Reservoir] = {}; + m_elementSets[ElementSets::IntraReservoir] = {}; + m_elementSets[ElementSets::UnderBurden] = {}; + m_boundaryElements[Boundary::Bottom] = {}; m_boundaryElements[Boundary::FarSide] = {}; int layerIndexOffset = 0; int elementIdx = 0; layer = 0; + int kLayer = 0; + + const int nVertCellsLower = (int)layersPerRegion[Regions::LowerUnderburden].size(); + const int nVertCellsFault = (int)( layersPerRegion[Regions::UpperUnderburden].size() + layersPerRegion[Regions::Reservoir].size() + + layersPerRegion[Regions::LowerOverburden].size() ); + + const int nVertCellsUnderburden = + (int)( layersPerRegion[Regions::LowerUnderburden].size() + layersPerRegion[Regions::UpperUnderburden].size() ); + const int nVertCellsReservoir = nVertCellsUnderburden + (int)( layersPerRegion[Regions::Reservoir].size() ); RimFaultReactivation::BorderSurface currentSurfaceRegion = RimFaultReactivation::BorderSurface::LowerSurface; + RimFaultReactivation::ElementSets currentElementSet = RimFaultReactivation::ElementSets::UnderBurden; - const int nextLayerIdxOff = ( nHorzCells + 1 ) * ( nThicknessCells + 1 ); + const int nextLayerIdxOff = ( (int)nHorzCells + 1 ) * ( nThicknessCells + 1 ); const int nThicknessOff = nThicknessCells + 1; + const int seaBedLayer = (int)( nVertCells - 2 ); - for ( int v = 0; v < nVertCells; v++, layer++ ) + for ( int v = 0; v < (int)nVertCells - 1; v++ ) { if ( v >= nVertCellsLower ) currentSurfaceRegion = RimFaultReactivation::BorderSurface::FaultSurface; - if ( v >= nVertCellsLower + nVertCellsMiddle ) currentSurfaceRegion = RimFaultReactivation::BorderSurface::UpperSurface; + if ( v >= nVertCellsLower + nVertCellsFault ) currentSurfaceRegion = RimFaultReactivation::BorderSurface::UpperSurface; + + if ( v >= nVertCellsUnderburden ) currentElementSet = RimFaultReactivation::ElementSets::Reservoir; + if ( v >= nVertCellsReservoir ) currentElementSet = RimFaultReactivation::ElementSets::OverBurden; int i = layerIndexOffset; - for ( int h = 0; h < nHorzCells; h++ ) + for ( int h = 0; h < (int)nHorzCells; h++ ) { for ( int t = 0; t < nThicknessCells; t++, elementIdx++ ) { @@ -210,14 +422,36 @@ void RigGriddedPart3d::generateGeometry( std::vector inputPoints, m_elementIndices[elementIdx].push_back( t + i + nThicknessOff + 1 ); m_elementIndices[elementIdx].push_back( t + i + 1 ); - if ( layer == 0 ) + if ( v == 0 ) { m_boundaryElements[Boundary::Bottom].push_back( elementIdx ); } + else if ( v == seaBedLayer ) + { + m_borderSurfaceElements[RimFaultReactivation::BorderSurface::Seabed].push_back( elementIdx ); + } if ( h == 0 ) { m_boundaryElements[Boundary::FarSide].push_back( elementIdx ); } + + if ( currentElementSet == RimFaultReactivation::ElementSets::Reservoir ) + { + m_elementKLayer[elementIdx] = kLayers[kLayer]; + if ( kLayers[kLayer] < 0 ) + { + m_elementSets[RimFaultReactivation::ElementSets::IntraReservoir].push_back( elementIdx ); + } + else + { + m_elementSets[currentElementSet].push_back( elementIdx ); + } + } + else + { + m_elementSets[currentElementSet].push_back( elementIdx ); + m_elementKLayer[elementIdx] = -2000; + } } i += nThicknessOff; } @@ -226,20 +460,18 @@ void RigGriddedPart3d::generateGeometry( std::vector inputPoints, m_borderSurfaceElements[currentSurfaceRegion].push_back( elementIdx - 2 ); m_borderSurfaceElements[currentSurfaceRegion].push_back( elementIdx - 1 ); + if ( currentElementSet == RimFaultReactivation::ElementSets::Reservoir ) + { + kLayer++; + } + layerIndexOffset += nextLayerIdxOff; } - // generate meshlines for 2d viz - - generateMeshlines( { inputPoints[0], inputPoints[1], inputPoints[5], inputPoints[4] }, nHorzCells, nVertCellsLower ); - generateMeshlines( { inputPoints[1], inputPoints[2], inputPoints[6], inputPoints[5] }, nHorzCells, nVertCellsMiddle ); - generateMeshlines( { inputPoints[2], inputPoints[3], inputPoints[7], inputPoints[6] }, nHorzCells, nVertCellsUpper ); - - // store the reservoir part corners for later - m_reservoirRect.clear(); - for ( auto i : { 1, 2, 6, 5 } ) + // vertical mesh lines for 2d display + for ( int i = 0; i < 5; i++ ) { - m_reservoirRect.push_back( inputPoints[i] ); + generateVerticalMeshlines( { inputPoints[i], inputPoints[i + 1], inputPoints[i + 7], inputPoints[i + 6] }, horizontalPartition ); } } @@ -256,35 +488,18 @@ void RigGriddedPart3d::generateGeometry( std::vector inputPoints, /// /// Assumes 0->3 and 1->2 is parallel //-------------------------------------------------------------------------------------------------- -void RigGriddedPart3d::generateMeshlines( const std::vector& cornerPoints, int numHorzCells, int numVertCells ) +void RigGriddedPart3d::generateVerticalMeshlines( const std::vector& cornerPoints, const std::vector& horzPartition ) { - cvf::Vec3d step0to1 = stepVector( cornerPoints[0], cornerPoints[1], numVertCells ); - cvf::Vec3d step0to3 = stepVector( cornerPoints[0], cornerPoints[3], numHorzCells ); - cvf::Vec3d step1to2 = stepVector( cornerPoints[1], cornerPoints[2], numHorzCells ); - cvf::Vec3d step3to2 = stepVector( cornerPoints[3], cornerPoints[2], numVertCells ); - - // horizontal lines - - cvf::Vec3d startP = cornerPoints[0]; - cvf::Vec3d endP = cornerPoints[3]; - - for ( int v = 0; v <= numVertCells; v++ ) - { - m_meshLines.push_back( { startP, endP } ); - startP += step0to1; - endP += step3to2; - } - - // vertical lines + cvf::Vec3d step0to3 = cornerPoints[3] - cornerPoints[0]; + cvf::Vec3d step1to2 = cornerPoints[2] - cornerPoints[1]; - startP = cornerPoints[0]; - endP = cornerPoints[1]; + int numHorzCells = (int)horzPartition.size(); - for ( int h = 0; h <= numHorzCells; h++ ) + for ( int h = 0; h < numHorzCells; h++ ) { + auto startP = cornerPoints[3] - horzPartition[h] * step0to3; + auto endP = cornerPoints[2] - horzPartition[h] * step1to2; m_meshLines.push_back( { startP, endP } ); - startP += step0to3; - endP += step1to2; } } @@ -321,6 +536,14 @@ bool RigGriddedPart3d::useLocalCoordinates() const return m_useLocalCoordinates; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RigGriddedPart3d::topHeight() const +{ + return m_topHeight; +} + //-------------------------------------------------------------------------------------------------- /// Output elements will be of type HEX8 /// @@ -342,130 +565,76 @@ const std::vector>& RigGriddedPart3d::elementIndices() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -const std::map>& RigGriddedPart3d::borderSurfaceElements() const +const std::vector RigGriddedPart3d::elementCorners( size_t elementIndex ) const { - return m_borderSurfaceElements; -} + if ( elementIndex >= m_elementIndices.size() ) return {}; -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -const std::vector>& RigGriddedPart3d::meshLines() const -{ - return m_meshLines; + std::vector corners; + + for ( auto nodeIdx : m_elementIndices[elementIndex] ) + { + if ( nodeIdx >= m_nodes.size() ) continue; + corners.push_back( m_nodes[nodeIdx] ); + } + + return corners; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -const std::map>& RigGriddedPart3d::boundaryElements() const +const std::map>& RigGriddedPart3d::borderSurfaceElements() const { - return m_boundaryElements; + return m_borderSurfaceElements; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -const std::map>& RigGriddedPart3d::boundaryNodes() const +const std::vector>& RigGriddedPart3d::meshLines() const { - return m_boundaryNodes; + return m_meshLines; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -const std::map>& RigGriddedPart3d::elementSets() const +const std::vector RigGriddedPart3d::elementKLayer() const { - return m_elementSets; + return m_elementKLayer; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -const std::vector& RigGriddedPart3d::nodePorePressure( size_t outputTimeStep ) const +const std::vector> RigGriddedPart3d::layers( RigGriddedPart3d::ElementSets elementSet ) const { - if ( outputTimeStep >= m_nodePorePressure.size() ) return m_emptyData; - return m_nodePorePressure[outputTimeStep]; + if ( m_elementLayers.count( elementSet ) == 0 ) return {}; + return m_elementLayers.at( elementSet ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RigGriddedPart3d::extractModelData( RimFaultReactivationDataAccess* dataAccess, size_t outputTimeStep ) +const std::map>& RigGriddedPart3d::boundaryElements() const { - if ( m_nodePorePressure.size() <= outputTimeStep ) - { - m_nodePorePressure.resize( outputTimeStep + 1 ); - } - - for ( auto& node : m_nodes ) - { - double pressure = dataAccess->porePressureAtPosition( node, 1.0 ); - m_nodePorePressure[outputTimeStep].push_back( pressure ); - } + return m_boundaryElements; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::pair RigGriddedPart3d::reservoirZTopBottom( const RigMainGrid* grid ) const +const std::map>& RigGriddedPart3d::boundaryNodes() const { - cvf::BoundingBox resBb; - for ( const auto& p : m_reservoirRect ) - { - resBb.add( p ); - } - std::vector intersectingCells; - grid->findIntersectingCells( resBb, &intersectingCells ); - - resBb.reset(); - for ( auto cellIdx : intersectingCells ) - { - resBb.add( grid->cell( cellIdx ).boundingBox() ); - } - - auto maxZ = resBb.max().z(); - auto minZ = resBb.min().z(); - - return std::make_pair( maxZ, minZ ); + return m_boundaryNodes; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RigGriddedPart3d::generateElementSets( const RimFaultReactivationDataAccess* dataAccess, const RigMainGrid* grid ) +const std::map>& RigGriddedPart3d::elementSets() const { - m_elementSets[ElementSets::OverBurden] = {}; - m_elementSets[ElementSets::Reservoir] = {}; - m_elementSets[ElementSets::IntraReservoir] = {}; - m_elementSets[ElementSets::UnderBurden] = {}; - - auto [topResZ, bottomResZ] = reservoirZTopBottom( grid ); - - for ( unsigned int i = 0; i < m_elementIndices.size(); i++ ) - { - auto corners = elementCorners( i ); - - if ( dataAccess->elementHasValidData( corners ) ) - { - m_elementSets[ElementSets::Reservoir].push_back( i ); - } - else - { - if ( elementIsAboveReservoir( corners, topResZ ) ) - { - m_elementSets[ElementSets::OverBurden].push_back( i ); - } - else if ( elementIsBelowReservoir( corners, bottomResZ ) ) - { - m_elementSets[ElementSets::UnderBurden].push_back( i ); - } - else - { - m_elementSets[ElementSets::IntraReservoir].push_back( i ); - } - } - } + return m_elementSets; } //-------------------------------------------------------------------------------------------------- @@ -480,49 +649,3 @@ void RigGriddedPart3d::generateLocalNodes( const cvf::Mat4d transform ) m_localNodes.push_back( node.getTransformedPoint( transform ) ); } } - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -std::vector RigGriddedPart3d::elementCorners( size_t elementIndex ) const -{ - if ( elementIndex >= m_elementIndices.size() ) return {}; - - std::vector corners; - - for ( auto nodeIdx : m_elementIndices[elementIndex] ) - { - if ( nodeIdx >= m_nodes.size() ) continue; - corners.push_back( m_nodes[nodeIdx] ); - } - - return corners; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool RigGriddedPart3d::elementIsAboveReservoir( const std::vector& cornerPoints, double threshold ) const -{ - int nValid = 0; - for ( auto& p : cornerPoints ) - { - if ( p.z() > threshold ) nValid++; - } - - return nValid > 4; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool RigGriddedPart3d::elementIsBelowReservoir( const std::vector& cornerPoints, double threshold ) const -{ - int nValid = 0; - for ( auto& p : cornerPoints ) - { - if ( p.z() < threshold ) nValid++; - } - - return nValid > 4; -} diff --git a/ApplicationLibCode/ReservoirDataModel/RigGriddedPart3d.h b/ApplicationLibCode/ReservoirDataModel/RigGriddedPart3d.h index 37861734ef..410bbccab7 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigGriddedPart3d.h +++ b/ApplicationLibCode/ReservoirDataModel/RigGriddedPart3d.h @@ -24,12 +24,10 @@ #include "cvfObject.h" #include "cvfVector3.h" +#include #include #include -class RigMainGrid; -class RimFaultReactivationDataAccess; - //================================================================================================== /// /// @@ -40,64 +38,74 @@ class RigGriddedPart3d : public cvf::Object using Boundary = RimFaultReactivation::Boundary; public: - RigGriddedPart3d( bool flipFrontBack ); + RigGriddedPart3d(); ~RigGriddedPart3d() override; void reset(); - void clearModelData(); - void generateGeometry( std::vector inputPoints, - int nHorzCells, - int nVertCellsLower, - int nVertCellsMiddle, - int nVertCellsUpper, - double thickness ); + void generateGeometry( const std::array& inputPoints, + const std::vector& reservoirLayers, + const std::vector& kLayers, + double maxCellHeight, + double cellSizeFactor, + const std::vector& horizontalPartition, + double modelThickness, + double topHeight ); - void generateElementSets( const RimFaultReactivationDataAccess* dataAccess, const RigMainGrid* grid ); void generateLocalNodes( const cvf::Mat4d transform ); - void extractModelData( RimFaultReactivationDataAccess* dataAccess, size_t outputTimeStep ); + void setUseLocalCoordinates( bool useLocalCoordinates ); + + bool useLocalCoordinates() const; + double topHeight() const; const std::vector& nodes() const; const std::vector& globalNodes() const; - void setUseLocalCoordinates( bool useLocalCoordinates ); - bool useLocalCoordinates() const; const std::vector>& elementIndices() const; const std::map>& borderSurfaceElements() const; - const std::vector>& meshLines() const; - std::vector elementCorners( size_t elementIndex ) const; - - const std::map>& boundaryElements() const; - const std::map>& boundaryNodes() const; - + const std::vector>& meshLines() const; + const std::map>& boundaryElements() const; + const std::map>& boundaryNodes() const; const std::map>& elementSets() const; - - const std::vector& nodePorePressure( size_t outputTimeStep ) const; + const std::vector elementKLayer() const; + const std::vector elementCorners( size_t elementIndex ) const; + const std::vector> layers( ElementSets elementSet ) const; protected: - cvf::Vec3d stepVector( cvf::Vec3d start, cvf::Vec3d stop, int nSteps ); - void generateMeshlines( const std::vector& cornerPoints, int numHorzCells, int numVertCells ); + static cvf::Vec3d stepVector( cvf::Vec3d start, cvf::Vec3d stop, int nSteps ); + static std::vector generateConstantLayers( double zFrom, double zTo, double maxSize ); + static std::vector generateGrowingLayers( double zFrom, double zTo, double maxSize, double growfactor ); + static std::vector extractZValues( std::vector ); - bool elementIsAboveReservoir( const std::vector& cornerPoints, double threshold ) const; - bool elementIsBelowReservoir( const std::vector& cornerPoints, double threshold ) const; + void generateVerticalMeshlines( const std::vector& cornerPoints, const std::vector& horzPartition ); + void updateReservoirElementLayers( const std::vector& reservoirLayers, const std::vector& kLayers ); - std::pair reservoirZTopBottom( const RigMainGrid* grid ) const; +private: + enum class Regions + { + LowerUnderburden = 0, // deepest region goes first + UpperUnderburden, + Reservoir, + LowerOverburden, + UpperOverburden + }; + + static std::vector allRegions(); private: bool m_useLocalCoordinates; + double m_topHeight; + std::vector m_nodes; std::vector m_localNodes; std::vector> m_elementIndices; + std::vector m_elementKLayer; std::map> m_borderSurfaceElements; std::vector> m_meshLines; std::map> m_boundaryElements; std::map> m_boundaryNodes; std::map> m_elementSets; - - std::vector> m_nodePorePressure; - const std::vector m_emptyData; - - std::vector m_reservoirRect; + std::map>> m_elementLayers; }; diff --git a/ApplicationLibCode/ReservoirDataModel/RigSimulationWellCenterLineCalculator.cpp b/ApplicationLibCode/ReservoirDataModel/RigSimulationWellCenterLineCalculator.cpp index 74b7e6e210..ee3cbadb8b 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigSimulationWellCenterLineCalculator.cpp +++ b/ApplicationLibCode/ReservoirDataModel/RigSimulationWellCenterLineCalculator.cpp @@ -220,19 +220,26 @@ void RigSimulationWellCenterLineCalculator::calculateWellPipeCenterlineForTimeSt bool isMultiSegmentWell = wellResults->isMultiSegmentWell(); -#if 0 // Fancy branch splitting, but with artifacts. Needs a bit more work to be better overall than the one we have. - RigWellResultFrame splittedWellFrame; - if (!isMultiSegmentWell && isAutoDetectBranches) - { - splittedWellFrame = splitIntoBranches(*wellFramePtr, eclipseCaseData); - wellFramePtr = &splittedWellFrame; - isMultiSegmentWell = true; - } -#endif - const RigWellResultFrame& wellFrame = *wellFramePtr; const std::vector resBranches = wellFrame.wellResultBranches(); + const bool debugOutput = false; + if ( debugOutput ) + { + for ( const auto& branch : resBranches ) + { + QString branchTxt; + for ( const auto& resultPoint : branch.branchResultPoints() ) + { + if ( resultPoint.cellIjk().has_value() ) + { + branchTxt += QString( " %1 \n" ).arg( QString::fromStdString( ( *resultPoint.cellIjk() ).toString() ) ); + } + } + RiaLogging::debug( branchTxt ); + } + } + // Well head // Match this position with well head position in RivWellHeadPartMgr::buildWellHeadParts() diff --git a/ApplicationLibCode/ReservoirDataModel/RigVisibleCategoriesCalculator.cpp b/ApplicationLibCode/ReservoirDataModel/RigVisibleCategoriesCalculator.cpp index 19f6723940..9c95cd0725 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigVisibleCategoriesCalculator.cpp +++ b/ApplicationLibCode/ReservoirDataModel/RigVisibleCategoriesCalculator.cpp @@ -240,6 +240,8 @@ void RigVisibleCategoriesCalculator::appendVisibleIntersectionCells( RimEclipseV for ( const auto geoGenerator : intersectionGeoGenerators ) { + if ( !geoGenerator->isAnyGeometryPresent() ) continue; + for ( const auto& cIdx : geoGenerator->triangleToCellIndex() ) { visibleCells.insert( cIdx ); diff --git a/ApplicationLibCode/ReservoirDataModel/RigWellResultPoint.cpp b/ApplicationLibCode/ReservoirDataModel/RigWellResultPoint.cpp index 5d17092969..3cd253efc8 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigWellResultPoint.cpp +++ b/ApplicationLibCode/ReservoirDataModel/RigWellResultPoint.cpp @@ -301,3 +301,19 @@ cvf::Vec3d RigWellResultPoint::bottomPosition() const { return m_bottomPosition; } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::optional RigWellResultPoint::cellIjk() const +{ + return m_cellIjk; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigWellResultPoint::setIjk( caf::VecIjk cellIJK ) +{ + m_cellIjk = cellIJK; +} diff --git a/ApplicationLibCode/ReservoirDataModel/RigWellResultPoint.h b/ApplicationLibCode/ReservoirDataModel/RigWellResultPoint.h index ad8134af8e..d770c39bef 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigWellResultPoint.h +++ b/ApplicationLibCode/ReservoirDataModel/RigWellResultPoint.h @@ -22,8 +22,11 @@ #include "cvfVector3.h" +#include "cafVecIjk.h" + #include +#include #include //================================================================================================== @@ -70,6 +73,9 @@ struct RigWellResultPoint cvf::Vec3d bottomPosition() const; + std::optional cellIjk() const; + void setIjk( caf::VecIjk cellIJK ); + private: size_t m_gridIndex; size_t m_cellIndex; //< Index to cell which is included in the well @@ -89,4 +95,6 @@ struct RigWellResultPoint double m_connectionFactor; bool m_isConnectedToValve; + + std::optional m_cellIjk; }; diff --git a/ApplicationLibCode/UnitTests/CMakeLists_files.cmake b/ApplicationLibCode/UnitTests/CMakeLists_files.cmake index 1b9033cf39..aa33ac608d 100644 --- a/ApplicationLibCode/UnitTests/CMakeLists_files.cmake +++ b/ApplicationLibCode/UnitTests/CMakeLists_files.cmake @@ -98,6 +98,8 @@ set(SOURCE_GROUP_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/RiaNumericalTools-Test.cpp ${CMAKE_CURRENT_LIST_DIR}/opm-import-well-data-Test.cpp ${CMAKE_CURRENT_LIST_DIR}/RifInpExportTools-Test.cpp + ${CMAKE_CURRENT_LIST_DIR}/RifGridCalculationIO-Test.cpp + ${CMAKE_CURRENT_LIST_DIR}/RifSummaryCalculationIO-Test.cpp ) if(RESINSIGHT_ENABLE_GRPC) diff --git a/ApplicationLibCode/UnitTests/RifGridCalculationIO-Test.cpp b/ApplicationLibCode/UnitTests/RifGridCalculationIO-Test.cpp new file mode 100644 index 0000000000..a45d232802 --- /dev/null +++ b/ApplicationLibCode/UnitTests/RifGridCalculationIO-Test.cpp @@ -0,0 +1,121 @@ +#include "gtest/gtest.h" + +#include "RiaTestDataDirectory.h" + +#include "RifGridCalculation.h" +#include "RifGridCalculationExporter.h" +#include "RifGridCalculationImporter.h" + +static const std::string GRID_CALCULATION_DIR = std::string( TEST_DATA_DIR ) + std::string( "/RifGridCalculationIO/" ); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +TEST( RifGridCalculationIO, importAndExport ) +{ + std::string fileName = GRID_CALCULATION_DIR + "calculations.toml"; + + RifGridCalculation calc1; + calc1.description = "My first calculation"; + calc1.expression = "answer = a + b"; + calc1.unit = "meter"; + RifGridCalculationVariable variable1; + variable1.name = "a"; + variable1.resultVariable = "PRESSURE"; + variable1.resultType = "DYNAMIC_NATIVE"; + RifGridCalculationVariable variable2; + variable2.name = "b"; + variable2.resultVariable = "PORO"; + variable2.resultType = "STATIC_NATIVE"; + calc1.variables = { variable1, variable2 }; + + RifGridCalculation calc2; + calc2.description = "My second calculation"; + calc2.expression = "answer = x + y"; + calc2.unit = "meter"; + RifGridCalculationVariable variable3; + variable3.name = "x"; + variable3.resultVariable = "PRESSURE"; + variable3.resultType = "DYNAMIC_NATIVE"; + RifGridCalculationVariable variable4; + variable4.name = "y"; + variable4.resultVariable = "PORO"; + variable4.resultType = "STATIC_NATIVE"; + calc2.variables = { variable3, variable4 }; + + std::vector calculations = { calc1, calc2 }; + + std::stringstream stream; + auto [isOk, errorMessage] = RifGridCalculationExporter::writeToStream( calculations, stream ); + EXPECT_TRUE( isOk ); + EXPECT_TRUE( errorMessage.empty() ); + + auto [importedCalculations, importErrorMessage] = RifGridCalculationImporter::readFromStream( stream ); + ASSERT_EQ( calculations.size(), importedCalculations.size() ); + + ASSERT_EQ( calculations[0].description, importedCalculations[0].description ); + ASSERT_EQ( calculations[0].expression, importedCalculations[0].expression ); + ASSERT_EQ( calculations[0].unit, importedCalculations[0].unit ); + ASSERT_EQ( calculations[0].variables.size(), importedCalculations[0].variables.size() ); + + for ( size_t v = 0; v < calculations[0].variables.size(); v++ ) + { + ASSERT_EQ( calculations[0].variables[v].name, importedCalculations[0].variables[v].name ); + ASSERT_EQ( calculations[0].variables[v].resultType, importedCalculations[0].variables[v].resultType ); + ASSERT_EQ( calculations[0].variables[v].resultVariable, importedCalculations[0].variables[v].resultVariable ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +TEST( RifGridCalculationIO, importEmptyStream ) +{ + std::stringstream stream; + auto [calculations, errorMessage] = RifGridCalculationImporter::readFromStream( stream ); + ASSERT_EQ( 0u, calculations.size() ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +TEST( RifGridCalculationIO, importNotToml ) +{ + std::stringstream stream; + stream << "this is not valid toml"; + + auto [calculations, errorMessage] = RifGridCalculationImporter::readFromStream( stream ); + ASSERT_EQ( 0u, calculations.size() ); + ASSERT_FALSE( errorMessage.empty() ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +TEST( RifGridCalculationIO, importWrongToml ) +{ + std::stringstream stream; + stream << "[library]\n" + << "book = \"book name\"\n" + << "authors = [\"Author Name\"]\n" + << "isbn = \"1234567\"\n"; + + auto [calculations, errorMessage] = RifGridCalculationImporter::readFromStream( stream ); + ASSERT_EQ( 0u, calculations.size() ); + ASSERT_FALSE( errorMessage.empty() ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +TEST( RifGridCalculationIO, importMissingDescriptionToml ) +{ + std::stringstream stream; + stream << "[[grid-calculation]]\n" + << "description = 'MY_ASNWER ( NORNE_ATW2013_RFTPLT_V2 : PRESSURE, NORNE_ATW2013_RFTPLT_V2 : PORO )'\n" + << "unit = ''\n"; + + auto [calculations, errorMessage] = RifGridCalculationImporter::readFromStream( stream ); + ASSERT_EQ( 0u, calculations.size() ); + ASSERT_FALSE( errorMessage.empty() ); +} diff --git a/ApplicationLibCode/UnitTests/RifReaderFmuRft-Test.cpp b/ApplicationLibCode/UnitTests/RifReaderFmuRft-Test.cpp index a2e0deddfd..b5145e2e88 100644 --- a/ApplicationLibCode/UnitTests/RifReaderFmuRft-Test.cpp +++ b/ApplicationLibCode/UnitTests/RifReaderFmuRft-Test.cpp @@ -65,7 +65,10 @@ TEST( RifReaderFmuRftTest, LoadFile ) std::vector values; reader.values( adr, &values ); + // Two measurements per date + if ( adr.wellName() == "R_A2" ) EXPECT_EQ( 2u, values.size() ); + + // One date with 6 measurements if ( adr.wellName() == "R_A6" ) EXPECT_EQ( 6u, values.size() ); - if ( adr.wellName() == "R_A2" ) EXPECT_EQ( 4u, values.size() ); } } diff --git a/ApplicationLibCode/UnitTests/RifSummaryCalculationIO-Test.cpp b/ApplicationLibCode/UnitTests/RifSummaryCalculationIO-Test.cpp new file mode 100644 index 0000000000..1964ecbe8b --- /dev/null +++ b/ApplicationLibCode/UnitTests/RifSummaryCalculationIO-Test.cpp @@ -0,0 +1,118 @@ +#include "gtest/gtest.h" + +#include "RiaTestDataDirectory.h" + +#include "RifSummaryCalculation.h" +#include "RifSummaryCalculationExporter.h" +#include "RifSummaryCalculationImporter.h" + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +TEST( RifSummaryCalculationIO, importAndExport ) +{ + RifSummaryCalculation calc1; + calc1.expression = "answer = a + b"; + calc1.unit = "meter"; + calc1.distributeToAllCases = true; + calc1.distributeToOther = false; + RifSummaryCalculationVariable variable1; + variable1.name = "a"; + variable1.address = "FOPT"; + RifSummaryCalculationVariable variable2; + variable2.name = "b"; + variable2.address = "FGPT"; + calc1.variables = { variable1, variable2 }; + + RifSummaryCalculation calc2; + calc2.expression = "answer = x + y"; + calc2.unit = ""; + calc2.distributeToAllCases = false; + calc2.distributeToOther = true; + RifSummaryCalculationVariable variable3; + variable3.name = "x"; + variable3.address = "WOPT"; + RifSummaryCalculationVariable variable4; + variable4.name = "y"; + variable4.address = "WOPR"; + calc2.variables = { variable3, variable4 }; + + std::vector calculations = { calc1, calc2 }; + + std::stringstream stream; + auto [isOk, errorMessage] = RifSummaryCalculationExporter::writeToStream( calculations, stream ); + EXPECT_TRUE( isOk ); + EXPECT_TRUE( errorMessage.empty() ); + + auto [importedCalculations, importErrorMessage] = RifSummaryCalculationImporter::readFromStream( stream ); + ASSERT_EQ( calculations.size(), importedCalculations.size() ); + + for ( size_t c = 0; c < calculations.size(); c++ ) + { + ASSERT_EQ( calculations[c].expression, importedCalculations[c].expression ); + ASSERT_EQ( calculations[c].unit, importedCalculations[c].unit ); + ASSERT_TRUE( calculations[c].distributeToOther == importedCalculations[c].distributeToOther ); + ASSERT_TRUE( calculations[c].distributeToAllCases == importedCalculations[c].distributeToAllCases ); + ASSERT_EQ( calculations[c].variables.size(), importedCalculations[c].variables.size() ); + + for ( size_t v = 0; v < calculations[c].variables.size(); v++ ) + { + ASSERT_EQ( calculations[c].variables[v].name, importedCalculations[c].variables[v].name ); + ASSERT_EQ( calculations[c].variables[v].address, importedCalculations[c].variables[v].address ); + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +TEST( RifSummaryCalculationIO, importEmptyStream ) +{ + std::stringstream stream; + auto [calculations, errorMessage] = RifSummaryCalculationImporter::readFromStream( stream ); + ASSERT_EQ( 0u, calculations.size() ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +TEST( RifSummaryCalculationIO, importNotToml ) +{ + std::stringstream stream; + stream << "this is not valid toml"; + + auto [calculations, errorMessage] = RifSummaryCalculationImporter::readFromStream( stream ); + ASSERT_EQ( 0u, calculations.size() ); + ASSERT_FALSE( errorMessage.empty() ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +TEST( RifSummaryCalculationIO, importWrongToml ) +{ + std::stringstream stream; + stream << "[library]\n" + << "book = \"book name\"\n" + << "authors = [\"Author Name\"]\n" + << "isbn = \"1234567\"\n"; + + auto [calculations, errorMessage] = RifSummaryCalculationImporter::readFromStream( stream ); + ASSERT_EQ( 0u, calculations.size() ); + ASSERT_FALSE( errorMessage.empty() ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +TEST( RifSummaryCalculationIO, importMissingDescriptionToml ) +{ + std::stringstream stream; + stream << "[[grid-calculation]]\n" + << "description = 'MY_ASNWER ( NORNE_ATW2013_RFTPLT_V2 : PRESSURE, NORNE_ATW2013_RFTPLT_V2 : PORO )'\n" + << "unit = ''\n"; + + auto [calculations, errorMessage] = RifSummaryCalculationImporter::readFromStream( stream ); + ASSERT_EQ( 0u, calculations.size() ); + ASSERT_FALSE( errorMessage.empty() ); +} diff --git a/ApplicationLibCode/UnitTests/TestData/SummaryData/empty-file/BLASTO_PRED-19.SMSPEC b/ApplicationLibCode/UnitTests/TestData/SummaryData/empty-file/BLASTO_PRED-19.SMSPEC new file mode 100644 index 0000000000..5e7d5ef53b Binary files /dev/null and b/ApplicationLibCode/UnitTests/TestData/SummaryData/empty-file/BLASTO_PRED-19.SMSPEC differ diff --git a/ApplicationLibCode/UnitTests/TestData/SummaryData/empty-file/BLASTO_PRED-19.UNSMRY b/ApplicationLibCode/UnitTests/TestData/SummaryData/empty-file/BLASTO_PRED-19.UNSMRY new file mode 100644 index 0000000000..53ce7ac5ec Binary files /dev/null and b/ApplicationLibCode/UnitTests/TestData/SummaryData/empty-file/BLASTO_PRED-19.UNSMRY differ diff --git a/ApplicationLibCode/UnitTests/opm-summary-Test.cpp b/ApplicationLibCode/UnitTests/opm-summary-Test.cpp index 5c9b6ab0a6..88abcce1c0 100644 --- a/ApplicationLibCode/UnitTests/opm-summary-Test.cpp +++ b/ApplicationLibCode/UnitTests/opm-summary-Test.cpp @@ -16,6 +16,7 @@ #include "opm/io/eclipse/ExtESmry.hpp" #include +#include static const QString H5_TEST_DATA_DIRECTORY = QString( "%1/h5-file/" ).arg( TEST_DATA_DIR ); @@ -295,6 +296,20 @@ TEST( OpmSummaryTests, OpmComputeSegmentTopology ) } } +TEST( OpmSummaryTests, OpenEmptySummaryFile ) +{ + QString SUMMARY_TEST_DATA_DIRECTORY = QString( "%1/SummaryData/empty-file/" ).arg( TEST_DATA_DIR ); + QString rootPath = SUMMARY_TEST_DATA_DIRECTORY + "BLASTO_PRED-19"; + QString smspecFilePath = rootPath + ".SMSPEC"; + + Opm::EclIO::ESmry eSmry( smspecFilePath.toStdString() ); + + // Test to verify that is is possible to read an empty summary file + // eSmry.make_esmry_file() will fail if the summary file is empty + + EXPECT_TRUE( eSmry.numberOfTimeSteps() == 0 ); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/UserInterface/RiuDragDrop.cpp b/ApplicationLibCode/UserInterface/RiuDragDrop.cpp index 4a99613920..ead07b0190 100644 --- a/ApplicationLibCode/UserInterface/RiuDragDrop.cpp +++ b/ApplicationLibCode/UserInterface/RiuDragDrop.cpp @@ -38,9 +38,6 @@ #include "RimSummaryCase.h" #include "RimSummaryCaseCollection.h" #include "RimSummaryCaseMainCollection.h" -#include "RimSummaryCurve.h" -#include "RimSummaryCurveCollection.h" -#include "RimSummaryPlot.h" #include "RimSurface.h" #include "RimSurfaceCollection.h" #include "RimWellAllocationPlot.h" @@ -250,9 +247,8 @@ Qt::ItemFlags RiuDragDrop::flags( const QModelIndex& index ) const } if ( dynamic_cast( uiItem ) || dynamic_cast( uiItem ) || - dynamic_cast( uiItem ) || dynamic_cast( uiItem ) || - dynamic_cast( uiItem ) || dynamic_cast( uiItem ) || - dynamic_cast( uiItem ) || dynamic_cast( uiItem ) ) + dynamic_cast( uiItem ) || dynamic_cast( uiItem ) || dynamic_cast( uiItem ) || + dynamic_cast( uiItem ) || dynamic_cast( uiItem ) ) { itemflags |= Qt::ItemIsDragEnabled; } @@ -320,13 +316,6 @@ Qt::ItemFlags RiuDragDrop::flags( const QModelIndex& index ) const } } } - else if ( dynamic_cast( uiItem ) || dynamic_cast( uiItem ) ) - { - if ( RiuTypedPdmObjects::containsTypedObjects( m_dragItems ) ) - { - itemflags |= Qt::ItemIsDropEnabled; - } - } else if ( dynamic_cast( uiItem ) ) { if ( RiuTypedPdmObjects::containsTypedObjects( m_dragItems ) ) @@ -416,12 +405,6 @@ bool RiuDragDrop::dropMimeData( const QMimeData* data, Qt::DropAction action, in return handleWellLogPlotDrop( action, draggedObjects, wellLogPlot, row ); } - auto summaryPlot = dropTarget->firstAncestorOrThisOfType(); - if ( summaryPlot ) - { - return handleSummaryPlotDrop( action, draggedObjects, summaryPlot, row ); - } - auto multiPlot = dropTarget->firstAncestorOrThisOfType(); if ( multiPlot ) { @@ -585,23 +568,6 @@ bool RiuDragDrop::handleWellLogPlotDrop( Qt::DropAction action, return false; } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool RiuDragDrop::handleSummaryPlotDrop( Qt::DropAction action, caf::PdmObjectGroup& objectGroup, RimSummaryPlot* summaryPlot, int insertAtPosition ) -{ - std::vector summaryCurves = RiuTypedPdmObjects::typedObjectsFromGroup( objectGroup ); - if ( !summaryCurves.empty() ) - { - if ( action == Qt::MoveAction ) - { - RimSummaryPlot::moveCurvesToPlot( summaryPlot, summaryCurves, insertAtPosition ); - return true; - } - } - return false; -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/UserInterface/RiuDragDrop.h b/ApplicationLibCode/UserInterface/RiuDragDrop.h index dffca288cc..f6b5531e5b 100644 --- a/ApplicationLibCode/UserInterface/RiuDragDrop.h +++ b/ApplicationLibCode/UserInterface/RiuDragDrop.h @@ -78,8 +78,6 @@ class RiuDragDrop : public caf::PdmUiDragDropInterface bool handleWellLogPlotDrop( Qt::DropAction action, caf::PdmObjectGroup& objectGroup, RimWellLogPlot* wellLogPlot, int insertAtPosition ); - bool handleSummaryPlotDrop( Qt::DropAction action, caf::PdmObjectGroup& objectGroup, RimSummaryPlot* summaryPlot, int insertAtPosition ); - bool handleMultiPlotDrop( Qt::DropAction action, caf::PdmObjectGroup& objectGroup, RimMultiPlot* multiPlot, int insertAtPosition ); bool handleSummaryCaseCollectionDrop( Qt::DropAction action, caf::PdmObjectGroup& objectGroup, diff --git a/ApplicationLibCode/UserInterface/RiuFemResultTextBuilder.cpp b/ApplicationLibCode/UserInterface/RiuFemResultTextBuilder.cpp index 3d87efc054..8ef22bbfbe 100644 --- a/ApplicationLibCode/UserInterface/RiuFemResultTextBuilder.cpp +++ b/ApplicationLibCode/UserInterface/RiuFemResultTextBuilder.cpp @@ -181,6 +181,17 @@ QString RiuFemResultTextBuilder::geometrySelectionText( QString itemSeparator ) } } } + std::array cornerCoords; + if ( femPart->fillElementCoordinates( m_cellIndex, cornerCoords ) ) + { + text += "\n\nElement corners:\n"; + + for ( auto p : cornerCoords ) + { + text += + QString( " [E: %1, N: %2, Depth: %3]\n" ).arg( p.x(), 5, 'f', 2 ).arg( p.y(), 5, 'f', 2 ).arg( -p.z(), 5, 'f', 2 ); + } + } } } diff --git a/ApplicationLibCode/UserInterface/RiuMainWindow.cpp b/ApplicationLibCode/UserInterface/RiuMainWindow.cpp index 083cd5775c..a85ff2d0aa 100644 --- a/ApplicationLibCode/UserInterface/RiuMainWindow.cpp +++ b/ApplicationLibCode/UserInterface/RiuMainWindow.cpp @@ -1320,7 +1320,8 @@ void RiuMainWindow::slotSubWindowActivated( QMdiSubWindow* subWindow ) Rim3dView* previousActiveReservoirView = RiaApplication::instance()->activeReservoirView(); Rim3dView* activatedView = dynamic_cast( findViewWindowFromSubWindow( subWindow ) ); - if ( !activatedView ) return; + if ( !activatedView || ( previousActiveReservoirView == activatedView ) ) return; + RiaApplication::instance()->setActiveReservoirView( activatedView ); if ( !isBlockingViewSelectionOnSubWindowActivated() ) diff --git a/ApplicationLibCode/UserInterface/RiuMainWindowBase.cpp b/ApplicationLibCode/UserInterface/RiuMainWindowBase.cpp index 569d15d07c..8f32f714f2 100644 --- a/ApplicationLibCode/UserInterface/RiuMainWindowBase.cpp +++ b/ApplicationLibCode/UserInterface/RiuMainWindowBase.cpp @@ -354,11 +354,12 @@ bool RiuMainWindowBase::isBlockingViewSelectionOnSubWindowActivated() const void RiuMainWindowBase::removeViewerFromMdiArea( RiuMdiArea* mdiArea, QWidget* viewer ) { bool removedSubWindowWasActive = false; + bool wasMaximized = true; - QMdiSubWindow* subWindowBeingClosed = findMdiSubWindow( viewer ); - bool wasMaximized = subWindowBeingClosed->isMaximized(); - if ( subWindowBeingClosed ) + if ( QMdiSubWindow* subWindowBeingClosed = findMdiSubWindow( viewer ) ) { + wasMaximized = subWindowBeingClosed->isMaximized(); + if ( subWindowBeingClosed->isActiveWindow() ) { // If we are removing the active window, we will need a new active window diff --git a/ApplicationLibCode/UserInterface/RiuMessagePanel.cpp b/ApplicationLibCode/UserInterface/RiuMessagePanel.cpp index fb919aa480..2e4bcdb8f5 100644 --- a/ApplicationLibCode/UserInterface/RiuMessagePanel.cpp +++ b/ApplicationLibCode/UserInterface/RiuMessagePanel.cpp @@ -24,6 +24,8 @@ #include "DockWidget.h" +#include "cafStyleSheetTools.h" + #include #include #include @@ -42,7 +44,7 @@ RiuMessagePanel::RiuMessagePanel( QWidget* parent ) : QWidget( parent ) { QVBoxLayout* layout = new QVBoxLayout( this ); - layout->setMargin( 0 ); + layout->setMargin( caf::StyleSheetTools::smallContentMargin() ); m_textEdit = new QPlainTextEdit; m_textEdit->setReadOnly( true ); diff --git a/ApplicationLibCode/UserInterface/RiuMultiPlotPage.cpp b/ApplicationLibCode/UserInterface/RiuMultiPlotPage.cpp index 92a21d47de..8bee618c16 100644 --- a/ApplicationLibCode/UserInterface/RiuMultiPlotPage.cpp +++ b/ApplicationLibCode/UserInterface/RiuMultiPlotPage.cpp @@ -866,7 +866,7 @@ void RiuMultiPlotPage::updateLegendFont( RiuQwtPlotLegend* legend ) { label->setFont( legendFont ); label->setMargin( 0 ); - label->setSpacing( 1 ); + label->setSpacing( 3 ); } legend->setFont( legendFont ); diff --git a/ApplicationLibCode/UserInterface/RiuPlotWidget.h b/ApplicationLibCode/UserInterface/RiuPlotWidget.h index 5885c06544..8668b6a1a6 100644 --- a/ApplicationLibCode/UserInterface/RiuPlotWidget.h +++ b/ApplicationLibCode/UserInterface/RiuPlotWidget.h @@ -117,11 +117,10 @@ class RiuPlotWidget : public QWidget, public RiuInterfaceToViewWindow virtual bool plotTitleEnabled() const = 0; virtual void setPlotTitleFontSize( int titleFontSize ) = 0; - virtual void setLegendFontSize( int fontSize ) = 0; - virtual void setInternalLegendVisible( bool visible ) = 0; - virtual void insertLegend( RiuPlotWidget::Legend ) = 0; - virtual void clearLegend() = 0; - virtual void updateLegend() = 0; + virtual void setLegendFontSize( int fontSize ) = 0; + virtual void insertLegend( RiuPlotWidget::Legend ) = 0; + virtual void clearLegend() = 0; + virtual void updateLegend() = 0; virtual void detachItems( RiuPlotWidget::PlotItemType plotItemType ) = 0; diff --git a/ApplicationLibCode/UserInterface/RiuQtChartsPlotWidget.cpp b/ApplicationLibCode/UserInterface/RiuQtChartsPlotWidget.cpp index ba8351b023..9b40d74598 100644 --- a/ApplicationLibCode/UserInterface/RiuQtChartsPlotWidget.cpp +++ b/ApplicationLibCode/UserInterface/RiuQtChartsPlotWidget.cpp @@ -287,21 +287,6 @@ void RiuQtChartsPlotWidget::setLegendFontSize( int fontSize ) } } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuQtChartsPlotWidget::setInternalLegendVisible( bool visible ) -{ - if ( visible ) - { - insertLegend( RiuPlotWidget::Legend::BOTTOM ); - } - else - { - clearLegend(); - } -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/UserInterface/RiuQtChartsPlotWidget.h b/ApplicationLibCode/UserInterface/RiuQtChartsPlotWidget.h index 470168cc9f..68bb3274dc 100644 --- a/ApplicationLibCode/UserInterface/RiuQtChartsPlotWidget.h +++ b/ApplicationLibCode/UserInterface/RiuQtChartsPlotWidget.h @@ -112,7 +112,6 @@ class RiuQtChartsPlotWidget : public RiuPlotWidget void setPlotTitleFontSize( int titleFontSize ) override; void setLegendFontSize( int fontSize ) override; - void setInternalLegendVisible( bool visible ) override; void insertLegend( RiuPlotWidget::Legend ) override; void clearLegend() override; diff --git a/ApplicationLibCode/UserInterface/RiuQwtPlotLegend.cpp b/ApplicationLibCode/UserInterface/RiuQwtPlotLegend.cpp index 500e97e76a..4cbd930265 100644 --- a/ApplicationLibCode/UserInterface/RiuQwtPlotLegend.cpp +++ b/ApplicationLibCode/UserInterface/RiuQwtPlotLegend.cpp @@ -91,7 +91,10 @@ QSize RiuQwtPlotLegend::sizeHint() const if ( legendLayout->itemCount() % numColumns ) numRows++; - int width = numColumns * legendLayout->maxItemWidth(); + // Extra width to workaround layout issue on linux + // https://github.com/OPM/ResInsight/issues/10785 + const int extraWidth = 20; + const int width = numColumns * legendLayout->maxItemWidth() + extraWidth; int maxHeight = 0; for ( unsigned int i = 0; i < legendLayout->itemCount(); ++i ) diff --git a/ApplicationLibCode/UserInterface/RiuQwtPlotWidget.cpp b/ApplicationLibCode/UserInterface/RiuQwtPlotWidget.cpp index d80a1e58f9..edee3ec0ad 100644 --- a/ApplicationLibCode/UserInterface/RiuQwtPlotWidget.cpp +++ b/ApplicationLibCode/UserInterface/RiuQwtPlotWidget.cpp @@ -270,22 +270,6 @@ void RiuQwtPlotWidget::setLegendFontSize( int fontSize ) } } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuQwtPlotWidget::setInternalLegendVisible( bool visible ) -{ - if ( visible ) - { - auto* legend = new QwtLegend( this ); - m_plot->insertLegend( legend, QwtPlot::BottomLegend ); - } - else - { - m_plot->insertLegend( nullptr ); - } -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/UserInterface/RiuQwtPlotWidget.h b/ApplicationLibCode/UserInterface/RiuQwtPlotWidget.h index 491070b391..5f34909a0c 100644 --- a/ApplicationLibCode/UserInterface/RiuQwtPlotWidget.h +++ b/ApplicationLibCode/UserInterface/RiuQwtPlotWidget.h @@ -103,7 +103,6 @@ class RiuQwtPlotWidget : public RiuPlotWidget void setPlotTitleFontSize( int titleFontSize ) override; void setLegendFontSize( int fontSize ) override; - void setInternalLegendVisible( bool visible ) override; void insertLegend( RiuPlotWidget::Legend ) override; void clearLegend() override; diff --git a/ApplicationLibCode/UserInterface/RiuSummaryQtChartsPlot.cpp b/ApplicationLibCode/UserInterface/RiuSummaryQtChartsPlot.cpp index 4f9f10b4c2..1429eed536 100644 --- a/ApplicationLibCode/UserInterface/RiuSummaryQtChartsPlot.cpp +++ b/ApplicationLibCode/UserInterface/RiuSummaryQtChartsPlot.cpp @@ -42,7 +42,7 @@ RiuSummaryQtChartsPlot::RiuSummaryQtChartsPlot( RimSummaryPlot* plot, QWidget* p RiuQtChartsPlotTools::setCommonPlotBehaviour( m_plotWidget ); RiuQtChartsPlotTools::setDefaultAxes( m_plotWidget ); - m_plotWidget->setInternalLegendVisible( true ); + m_plotWidget->insertLegend( RiuPlotWidget::Legend::BOTTOM ); } //-------------------------------------------------------------------------------------------------- /// diff --git a/ApplicationLibCode/UserInterface/RiuSummaryQuantityNameInfoProvider.cpp b/ApplicationLibCode/UserInterface/RiuSummaryQuantityNameInfoProvider.cpp index 5badea1ea1..c272f63464 100644 --- a/ApplicationLibCode/UserInterface/RiuSummaryQuantityNameInfoProvider.cpp +++ b/ApplicationLibCode/UserInterface/RiuSummaryQuantityNameInfoProvider.cpp @@ -71,7 +71,8 @@ RifEclipseSummaryAddressDefines::SummaryCategory RiuSummaryQuantityNameInfoProvi auto exactCategory = categoryFromVectorName( vectorName, exactMatch ); if ( exactCategory != RifEclipseSummaryAddressDefines::SummaryCategory::SUMMARY_INVALID ) return exactCategory; - if ( vectorName.size() < 3 || vectorName.size() > 8 ) return RifEclipseSummaryAddressDefines::SummaryCategory::SUMMARY_INVALID; + if ( ( vectorName.size() < 3 || vectorName.size() > 8 ) && !vectorName.ends_with( RifEclipseSummaryAddressDefines::differenceIdentifier() ) ) + return RifEclipseSummaryAddressDefines::SummaryCategory::SUMMARY_INVALID; // Try to match the base vector name with more heuristics auto strippedQuantityName = RifEclipseSummaryAddress::baseVectorName( vectorName ); diff --git a/ApplicationLibCode/UserInterface/RiuSummaryQwtPlot.cpp b/ApplicationLibCode/UserInterface/RiuSummaryQwtPlot.cpp index dfea11f16c..f821b33fac 100644 --- a/ApplicationLibCode/UserInterface/RiuSummaryQwtPlot.cpp +++ b/ApplicationLibCode/UserInterface/RiuSummaryQwtPlot.cpp @@ -103,7 +103,7 @@ RiuSummaryQwtPlot::RiuSummaryQwtPlot( RimSummaryPlot* plot, QWidget* parent /*= // PERFORMANCE NOTE // Do not set internal legends visible, as this will cause a performance hit. - m_plotWidget->setInternalLegendVisible( false ); + m_plotWidget->clearLegend(); m_annotationTool = std::unique_ptr( new RiuPlotAnnotationTool() ); } diff --git a/ApplicationLibCode/UserInterface/RiuSummaryVectorSelectionUi.cpp b/ApplicationLibCode/UserInterface/RiuSummaryVectorSelectionUi.cpp index 503c81f2e7..8345313380 100644 --- a/ApplicationLibCode/UserInterface/RiuSummaryVectorSelectionUi.cpp +++ b/ApplicationLibCode/UserInterface/RiuSummaryVectorSelectionUi.cpp @@ -1086,13 +1086,13 @@ std::set if ( m_hideDifferenceVectors ) { - const auto diffText = RifReaderEclipseSummary::differenceIdentifier(); + const auto diffText = RifEclipseSummaryAddressDefines::differenceIdentifier(); if ( RiaStdStringTools::endsWith( adr.vectorName(), diffText ) ) continue; } if ( m_hideVectorsWithoutHistory ) { - auto candidateName = adr.vectorName() + RifReaderEclipseSummary::historyIdentifier(); + auto candidateName = adr.vectorName() + RifEclipseSummaryAddressDefines::historyIdentifier(); bool found = false; for ( const auto& ad : addrUnion ) diff --git a/ApplicationLibCode/UserInterface/RiuViewerCommands.cpp b/ApplicationLibCode/UserInterface/RiuViewerCommands.cpp index aa1659bb75..37833f816a 100644 --- a/ApplicationLibCode/UserInterface/RiuViewerCommands.cpp +++ b/ApplicationLibCode/UserInterface/RiuViewerCommands.cpp @@ -167,20 +167,7 @@ void RiuViewerCommands::addCompareToViewMenu( caf::CmdFeatureMenuBuilder* menuBu auto* mainGridView = m_reservoirView.p(); if ( mainGridView && !mainGridView->activeComparisonView() ) { - std::vector validComparisonViews; - - std::vector views; - RimProject::current()->allViews( views ); - for ( auto view : views ) - { - if ( dynamic_cast( view ) ) continue; - - if ( view != mainGridView ) - { - validComparisonViews.push_back( view ); - } - } - + std::vector validComparisonViews = mainGridView->validComparisonViews(); if ( !validComparisonViews.empty() ) { menuBuilder->subMenuStart( "Compare To ...", QIcon( ":/ComparisonView16x16.png" ) ); diff --git a/CMakeLists.txt b/CMakeLists.txt index 57936de2a9..3ebbd8dfc3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,6 +49,7 @@ if(RESINSIGHT_VCPKG_AUTO_INSTALL) endif() set(CMAKE_CXX_STANDARD 20) + set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) @@ -351,12 +352,12 @@ endif() if(MSVC) FetchContent_Declare( openvds - URL https://bluware.jfrog.io/artifactory/Releases-OpenVDSPlus/3.2/openvds+-3.2.3-win.zip + URL https://bluware.jfrog.io/artifactory/Releases-OpenVDSPlus/3.2/openvds+-3.2.7-win.zip ) else() FetchContent_Declare( openvds - URL https://bluware.jfrog.io/artifactory/Releases-OpenVDSPlus/3.2/openvds+-3.2.3-manylinux_2014.tar.gz + URL https://bluware.jfrog.io/artifactory/Releases-OpenVDSPlus/3.2/openvds+-3.2.7-manylinux_2014.tar.gz ) endif() @@ -443,9 +444,11 @@ option(RESINSIGHT_BUILD_LIBS_FROM_SOURCE "Build opm-common from source" ON) mark_as_advanced(RESINSIGHT_BUILD_LIBS_FROM_SOURCE) if((NOT RESINSIGHT_BUILD_LIBS_FROM_SOURCE) AND MSVC) + # See description of URL here + # https://docs.github.com/en/repositories/releasing-projects-on-github/linking-to-releases FetchContent_Declare( ri-dependencies - URL https://github.com/CeetronSolutions/resinsight-dependencies/releases/download/2023.08/custom-opm-common.zip + URL https://github.com/CeetronSolutions/resinsight-dependencies/releases/latest/download/custom-opm-common.zip ) FetchContent_Populate(ri-dependencies) @@ -614,6 +617,12 @@ set_property( "Thirdparty" ) +# ############################################################################## +# toml++ +# ############################################################################## + +add_subdirectory(ThirdParty/tomlplusplus) + # ############################################################################## # Thirdparty libraries are put in ThirdParty solution folder # ############################################################################## @@ -876,11 +885,11 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Linux") set(OPENVDS_SHARED_LIB_FILES ${RESINSIGHT_OPENVDS_API_DIR}/lib64/libopenvds.so ${RESINSIGHT_OPENVDS_API_DIR}/lib64/libopenvds.so.3 - ${RESINSIGHT_OPENVDS_API_DIR}/lib64/libopenvds.so.3.2.3 - ${RESINSIGHT_OPENVDS_API_DIR}/lib64/libopenvds-968eeb36.so.3.2.3 + ${RESINSIGHT_OPENVDS_API_DIR}/lib64/libopenvds.so.3.2.7 + ${RESINSIGHT_OPENVDS_API_DIR}/lib64/libopenvds-e1541338.so.3.2.7 ${RESINSIGHT_OPENVDS_API_DIR}/lib64/libsegyutils.so ${RESINSIGHT_OPENVDS_API_DIR}/lib64/libsegyutils.so.3 - ${RESINSIGHT_OPENVDS_API_DIR}/lib64/libsegyutils.so.3.2.3 + ${RESINSIGHT_OPENVDS_API_DIR}/lib64/libsegyutils.so.3.2.7 ) install(FILES ${OPENVDS_SHARED_LIB_FILES} DESTINATION ${RESINSIGHT_INSTALL_FOLDER} diff --git a/Fwk/AppFwk/CMakeLists.txt b/Fwk/AppFwk/CMakeLists.txt index 439c66837e..09c9867301 100644 --- a/Fwk/AppFwk/CMakeLists.txt +++ b/Fwk/AppFwk/CMakeLists.txt @@ -32,8 +32,7 @@ else() include(${QT_USE_FILE}) endif(CEE_USE_QT5) -# Use CMake to enforce C++17 -set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) @@ -41,6 +40,9 @@ if(MSVC) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP") endif() +# CeeViz is not available here, exclude it from the build +set(CAF_EXCLUDE_CVF ON) + # Improvement Cmake 3.x If we have compiler requirements for this library, list # them target_compile_features(lib PUBLIC cxx_auto_type PRIVATE # cxx_variadic_templates) diff --git a/Fwk/AppFwk/CommonCode/cafVecIjk.cpp b/Fwk/AppFwk/CommonCode/cafVecIjk.cpp index 7f0d4175b5..788c6a3565 100644 --- a/Fwk/AppFwk/CommonCode/cafVecIjk.cpp +++ b/Fwk/AppFwk/CommonCode/cafVecIjk.cpp @@ -70,4 +70,12 @@ size_t VecIjk::k() const return m_values[2]; } -}; // namespace caf \ No newline at end of file +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::string VecIjk::toString() const +{ + return std::to_string( i() ) + ", " + std::to_string( j() ) + ", " + std::to_string( k() ); +} + +}; // namespace caf diff --git a/Fwk/AppFwk/CommonCode/cafVecIjk.h b/Fwk/AppFwk/CommonCode/cafVecIjk.h index 934f47b751..e80f813cc8 100644 --- a/Fwk/AppFwk/CommonCode/cafVecIjk.h +++ b/Fwk/AppFwk/CommonCode/cafVecIjk.h @@ -38,6 +38,7 @@ #include #include +#include namespace caf { @@ -50,6 +51,8 @@ class VecIjk size_t j() const; size_t k() const; + std::string toString() const; + private: std::array m_values; }; diff --git a/Fwk/AppFwk/cafPdmScripting/CMakeLists.txt b/Fwk/AppFwk/cafPdmScripting/CMakeLists.txt index c173cc2b42..7b1ddcc8bc 100644 --- a/Fwk/AppFwk/cafPdmScripting/CMakeLists.txt +++ b/Fwk/AppFwk/cafPdmScripting/CMakeLists.txt @@ -28,13 +28,22 @@ set(PROJECT_FILES cafPdmMarkdownGenerator.cpp cafPdmMarkdownBuilder.h cafPdmMarkdownBuilder.cpp +) + +set(CAF_LIBS cafProjectDataModel) + +if(NOT CAF_EXCLUDE_CVF) + list( + APPEND + PROJECT_FILES cafPdmFieldScriptingCapabilityCvfColor3.h cafPdmFieldScriptingCapabilityCvfColor3.cpp cafPdmFieldScriptingCapabilityCvfVec3d.h cafPdmFieldScriptingCapabilityCvfVec3d.cpp -) + ) -set(CAF_LIBS cafProjectDataModel cafPdmCvf) + list(APPEND CAF_LIBS cafPdmCvf) +endif() add_library(${PROJECT_NAME} ${PROJECT_FILES}) @@ -42,4 +51,10 @@ target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) target_link_libraries(${PROJECT_NAME} ${CAF_LIBS}) +if(CAF_EXCLUDE_CVF) + target_compile_definitions( + ${PROJECT_NAME} PRIVATE CAF_EXCLUDE_CVF=${CAF_EXCLUDE_CVF} + ) +endif() + source_group("" FILES ${PROJECT_FILES}) diff --git a/Fwk/AppFwk/cafPdmScripting/cafPdmPythonGenerator.cpp b/Fwk/AppFwk/cafPdmScripting/cafPdmPythonGenerator.cpp index 0cf1a94ad4..230361f774 100644 --- a/Fwk/AppFwk/cafPdmScripting/cafPdmPythonGenerator.cpp +++ b/Fwk/AppFwk/cafPdmScripting/cafPdmPythonGenerator.cpp @@ -38,8 +38,6 @@ #include "cafPdmAbstractFieldScriptingCapability.h" #include "cafPdmChildArrayField.h" #include "cafPdmChildField.h" -#include "cafPdmFieldScriptingCapabilityCvfColor3.h" -#include "cafPdmFieldScriptingCapabilityCvfVec3d.h" #include "cafPdmObject.h" #include "cafPdmObjectFactory.h" #include "cafPdmObjectMethod.h" @@ -47,6 +45,11 @@ #include "cafPdmProxyValueField.h" #include "cafPdmXmlFieldHandle.h" +#ifndef CAF_EXCLUDE_CVF +#include "cafPdmFieldScriptingCapabilityCvfColor3.h" +#include "cafPdmFieldScriptingCapabilityCvfVec3d.h" +#endif + #include #include @@ -550,12 +553,15 @@ QString PdmPythonGenerator::dataTypeString( const PdmFieldHandle* field, bool us { QString::fromStdString( typeid( bool ).name() ), "bool" }, { QString::fromStdString( typeid( time_t ).name() ), "int" }, { QString::fromStdString( typeid( QString ).name() ), "str" }, - { QString::fromStdString( typeid( cvf::Vec3d ).name() ), "List[float]" }, - { QString::fromStdString( typeid( cvf::Color3f ).name() ), "str" }, { QString::fromStdString( typeid( caf::FilePath ).name() ), "str" }, { QString::fromStdString( typeid( std::vector ).name() ), "List[float]" }, }; +#ifndef CAF_EXCLUDE_CVF + builtins[QString::fromStdString( typeid( cvf::Vec3d ).name() )] = "List[float]"; + builtins[QString::fromStdString( typeid( cvf::Color3f ).name() )] = "str"; +#endif + bool foundBuiltin = false; for ( auto builtin : builtins ) { diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/Resources/caf.qrc b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/Resources/caf.qrc index 75c375085f..8ca9aae321 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/Resources/caf.qrc +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/Resources/caf.qrc @@ -3,5 +3,6 @@ Down16x16.png Up16x16.png duplicate.svg + clear.svg diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/Resources/clear.svg b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/Resources/clear.svg new file mode 100644 index 0000000000..ace63852be --- /dev/null +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/Resources/clear.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiOrdering.cpp b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiOrdering.cpp index baf1518360..74c0b73f95 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiOrdering.cpp +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiOrdering.cpp @@ -48,10 +48,10 @@ namespace caf //-------------------------------------------------------------------------------------------------- PdmUiOrdering::~PdmUiOrdering() { - for ( size_t i = 0; i < m_createdGroups.size(); ++i ) + for ( auto& createdGroup : m_createdGroups ) { - delete m_createdGroups[i]; - m_createdGroups[i] = nullptr; + delete createdGroup; + createdGroup = nullptr; } } @@ -60,11 +60,11 @@ PdmUiOrdering::~PdmUiOrdering() //-------------------------------------------------------------------------------------------------- PdmUiGroup* PdmUiOrdering::addNewGroup( const QString& displayName, LayoutOptions layout ) { - PdmUiGroup* group = new PdmUiGroup; + auto* group = new PdmUiGroup; group->setUiName( displayName ); m_createdGroups.push_back( group ); - m_ordering.push_back( std::make_pair( group, layout ) ); + m_ordering.emplace_back( group, layout ); return group; } @@ -93,10 +93,8 @@ bool PdmUiOrdering::insertBeforeGroup( const QString& groupId, const PdmFieldHan pos.parent->insert( pos.indexInParent, field, layout ); return true; } - else - { - return false; - } + + return false; } //-------------------------------------------------------------------------------------------------- @@ -110,10 +108,8 @@ bool PdmUiOrdering::insertBeforeItem( const PdmUiItem* item, const PdmFieldHandl pos.parent->insert( pos.indexInParent, field, layout ); return true; } - else - { - return false; - } + + return false; } //-------------------------------------------------------------------------------------------------- @@ -184,7 +180,7 @@ caf::PdmUiGroup* PdmUiOrdering::insertNewGroupWithKeyword( size_t index, const QString& groupKeyword, LayoutOptions layout ) { - PdmUiGroup* group = new PdmUiGroup; + auto* group = new PdmUiGroup; group->setUiName( displayName ); m_createdGroups.push_back( group ); @@ -248,7 +244,7 @@ void PdmUiOrdering::add( const PdmFieldHandle* field, LayoutOptions layout ) CAF_ASSERT( uiItem ); CAF_ASSERT( !this->contains( uiItem ) ); - m_ordering.push_back( std::make_pair( uiItem, layout ) ); + m_ordering.emplace_back( uiItem, layout ); } //-------------------------------------------------------------------------------------------------- @@ -259,7 +255,15 @@ void PdmUiOrdering::add( const PdmObjectHandle* obj, LayoutOptions layout ) PdmUiObjectHandle* uiItem = uiObj( const_cast( obj ) ); CAF_ASSERT( uiItem ); CAF_ASSERT( !this->contains( uiItem ) ); - m_ordering.push_back( std::make_pair( uiItem, layout ) ); + m_ordering.emplace_back( uiItem, layout ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void PdmUiOrdering::appendToRow( const PdmFieldHandle* field ) +{ + add( field, { .newRow = false } ); } //-------------------------------------------------------------------------------------------------- @@ -325,7 +329,7 @@ PdmUiOrdering::TableLayout PdmUiOrdering::calculateTableLayout( const QString& u if ( m_ordering[i].second.newRow || i == 0u ) { - tableLayout.push_back( RowLayout() ); + tableLayout.emplace_back(); } tableLayout.back().push_back( m_ordering[i] ); } @@ -370,7 +374,7 @@ int PdmUiOrdering::nrOfExpandingItemsInRow( const RowLayout& rowItems ) const int nrOfExpandingItems = 0; for ( const FieldAndLayout& item : rowItems ) { - if ( item.second.totalColumnSpan == LayoutOptions::MAX_COLUMN_SPAN ) nrOfExpandingItems++; + if ( item.second.totalColumnSpan == MAX_COLUMN_SPAN ) nrOfExpandingItems++; } return nrOfExpandingItems; } @@ -401,7 +405,7 @@ void PdmUiOrdering::nrOfColumnsRequiredForItem( const FieldAndLayout& fieldAndLa if ( uiItem->uiLabelPosition() == PdmUiItemInfo::LEFT ) { *labelColumnsRequired = 1; - if ( layoutOption.leftLabelColumnSpan != LayoutOptions::MAX_COLUMN_SPAN ) + if ( layoutOption.leftLabelColumnSpan != MAX_COLUMN_SPAN ) { *labelColumnsRequired = layoutOption.leftLabelColumnSpan; } @@ -409,7 +413,7 @@ void PdmUiOrdering::nrOfColumnsRequiredForItem( const FieldAndLayout& fieldAndLa *totalColumnsRequired = *labelColumnsRequired + *fieldColumnsRequired; } - if ( layoutOption.totalColumnSpan != LayoutOptions::MAX_COLUMN_SPAN ) + if ( layoutOption.totalColumnSpan != MAX_COLUMN_SPAN ) { *totalColumnsRequired = layoutOption.totalColumnSpan; } @@ -424,10 +428,8 @@ caf::PdmUiItem* PdmUiOrdering::PositionFound::item() { return parent->uiItems()[indexInParent]; } - else - { - return nullptr; - } + + return nullptr; } //-------------------------------------------------------------------------------------------------- @@ -440,10 +442,8 @@ caf::PdmUiGroup* PdmUiOrdering::PositionFound::group() { return static_cast( g ); } - else - { - return nullptr; - } + + return nullptr; } } // End of namespace caf diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiOrdering.h b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiOrdering.h index d6bd5043e3..885c8d78da 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiOrdering.h +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiOrdering.h @@ -54,23 +54,22 @@ class PdmObjectHandle; class PdmUiOrdering { public: + static const int MAX_COLUMN_SPAN = -1; + struct LayoutOptions { - static const int MAX_COLUMN_SPAN = -1; - LayoutOptions( bool newRow = true, int totalColumnSpan = MAX_COLUMN_SPAN, int leftLabelColumnSpan = MAX_COLUMN_SPAN ) - : newRow( newRow ) - , totalColumnSpan( totalColumnSpan ) - , leftLabelColumnSpan( leftLabelColumnSpan ) - { - } - - bool newRow; - int totalColumnSpan; - int leftLabelColumnSpan; + bool newRow{ true }; + int totalColumnSpan{ MAX_COLUMN_SPAN }; + int leftLabelColumnSpan{ MAX_COLUMN_SPAN }; }; - typedef std::pair FieldAndLayout; - typedef std::vector RowLayout; - typedef std::vector TableLayout; + + // Required to use a static function as workaround instead of using LayoutOptions() + // https://stackoverflow.com/questions/53408962/try-to-understand-compiler-error-message-default-member-initializer-required-be + static LayoutOptions defaultLayoutOptions() { return {}; } + + using FieldAndLayout = std::pair; + using RowLayout = std::vector; + using TableLayout = std::vector; PdmUiOrdering() : m_skipRemainingFields( false ){}; @@ -79,33 +78,38 @@ class PdmUiOrdering PdmUiOrdering( const PdmUiOrdering& ) = delete; PdmUiOrdering& operator=( const PdmUiOrdering& ) = delete; - void add( const PdmFieldHandle* field, LayoutOptions layout = LayoutOptions() ); - void add( const PdmObjectHandle* obj, LayoutOptions layout = LayoutOptions() ); + void add( const PdmFieldHandle* field, LayoutOptions layout = defaultLayoutOptions() ); + + // Add a field without creating a new row + void appendToRow( const PdmFieldHandle* field ); + + void add( const PdmObjectHandle* obj, LayoutOptions layout = defaultLayoutOptions() ); bool insertBeforeGroup( const QString& groupId, const PdmFieldHandle* fieldToInsert, - LayoutOptions layout = LayoutOptions() ); + LayoutOptions layout = defaultLayoutOptions() ); bool insertBeforeItem( const PdmUiItem* item, const PdmFieldHandle* fieldToInsert, - LayoutOptions layout = LayoutOptions() ); + LayoutOptions layout = defaultLayoutOptions() ); - PdmUiGroup* addNewGroup( const QString& displayName, LayoutOptions layout = LayoutOptions() ); + PdmUiGroup* addNewGroup( const QString& displayName, LayoutOptions layout = defaultLayoutOptions() ); PdmUiGroup* createGroupBeforeGroup( const QString& groupId, const QString& displayName, - LayoutOptions layout = LayoutOptions() ); - PdmUiGroup* - createGroupBeforeItem( const PdmUiItem* item, const QString& displayName, LayoutOptions layout = LayoutOptions() ); + LayoutOptions layout = defaultLayoutOptions() ); + PdmUiGroup* createGroupBeforeItem( const PdmUiItem* item, + const QString& displayName, + LayoutOptions layout = defaultLayoutOptions() ); PdmUiGroup* addNewGroupWithKeyword( const QString& displayName, const QString& groupKeyword, - LayoutOptions layout = LayoutOptions() ); + LayoutOptions layout = defaultLayoutOptions() ); PdmUiGroup* createGroupWithIdBeforeGroup( const QString& groupId, const QString& displayName, const QString& newGroupId, - LayoutOptions layout = LayoutOptions() ); + LayoutOptions layout = defaultLayoutOptions() ); PdmUiGroup* createGroupWithIdBeforeItem( const PdmUiItem* item, const QString& displayName, const QString& newGroupId, - LayoutOptions layout = LayoutOptions() ); + LayoutOptions layout = defaultLayoutOptions() ); PdmUiGroup* findGroup( const QString& groupId ) const; @@ -140,11 +144,11 @@ class PdmUiOrdering PositionFound findItemPosition( const PdmUiItem* item ) const; private: - void insert( size_t index, const PdmFieldHandle* field, LayoutOptions layout = LayoutOptions() ); + void insert( size_t index, const PdmFieldHandle* field, LayoutOptions layout = defaultLayoutOptions() ); PdmUiGroup* insertNewGroupWithKeyword( size_t index, const QString& displayName, const QString& groupKeyword, - LayoutOptions layout = LayoutOptions() ); + LayoutOptions layout = defaultLayoutOptions() ); std::vector m_ordering; ///< The order of groups and fields std::vector m_createdGroups; ///< Owned PdmUiGroups, for memory management only @@ -153,4 +157,4 @@ class PdmUiOrdering } // End of namespace caf -#include "cafPdmUiGroup.h" \ No newline at end of file +#include "cafPdmUiGroup.h" diff --git a/Fwk/AppFwk/cafTests/cafTestApplication/MainWindow.cpp b/Fwk/AppFwk/cafTests/cafTestApplication/MainWindow.cpp index 741d220360..4d87f66a0c 100644 --- a/Fwk/AppFwk/cafTests/cafTestApplication/MainWindow.cpp +++ b/Fwk/AppFwk/cafTests/cafTestApplication/MainWindow.cpp @@ -577,53 +577,47 @@ class SmallGridDemoPdmObject : public caf::PdmObject void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override { uiOrdering.add( &m_intFieldStandard ); - uiOrdering.add( &m_intFieldUseFullSpace, - caf::PdmUiOrdering::LayoutOptions( true, - caf::PdmUiOrdering::LayoutOptions::MAX_COLUMN_SPAN, - caf::PdmUiOrdering::LayoutOptions::MAX_COLUMN_SPAN ) ); - uiOrdering.add( &m_intFieldUseFullSpaceLabel, - caf::PdmUiOrdering::LayoutOptions( true, 3, caf::PdmUiOrdering::LayoutOptions::MAX_COLUMN_SPAN ) ); - uiOrdering.add( &m_intFieldUseFullSpaceField, - caf::PdmUiOrdering::LayoutOptions( true, caf::PdmUiOrdering::LayoutOptions::MAX_COLUMN_SPAN, 1 ) ); - uiOrdering.add( &m_intFieldWideLabel, caf::PdmUiOrdering::LayoutOptions( true, 4, 3 ) ); - uiOrdering.add( &m_intFieldWideField, caf::PdmUiOrdering::LayoutOptions( true, 4, 1 ) ); - uiOrdering.add( &m_intFieldLeft, caf::PdmUiOrdering::LayoutOptions( true ) ); - uiOrdering.add( &m_intFieldRight, caf::PdmUiOrdering::LayoutOptions( false ) ); - uiOrdering.add( &m_intFieldWideBoth, caf::PdmUiOrdering::LayoutOptions( true, 4, 2 ) ); + uiOrdering.add( &m_intFieldUseFullSpace ); + uiOrdering.add( &m_intFieldUseFullSpaceLabel, { .totalColumnSpan = 3 } ); + uiOrdering.add( &m_intFieldUseFullSpaceField, { .leftLabelColumnSpan = 1 } ); + uiOrdering.add( &m_intFieldWideLabel, { .totalColumnSpan = 4, .leftLabelColumnSpan = 3 } ); + uiOrdering.add( &m_intFieldWideField, { .totalColumnSpan = 4, .leftLabelColumnSpan = 1 } ); + uiOrdering.add( &m_intFieldLeft ); + uiOrdering.appendToRow( &m_intFieldRight ); + uiOrdering.add( &m_intFieldWideBoth, { .totalColumnSpan = 4, .leftLabelColumnSpan = 2 } ); QString dynamicGroupName = QString( "Dynamic Group Text (%1)" ).arg( m_intFieldStandard ); - caf::PdmUiGroup* group = uiOrdering.addNewGroup( "Wide Group", { true, 4 } ); - group->add( &m_intFieldWideBoth2, caf::PdmUiOrdering::LayoutOptions( true, 6, 3 ) ); - group->add( &m_intFieldLeft2, caf::PdmUiOrdering::LayoutOptions( true ) ); - group->add( &m_intFieldCenter, caf::PdmUiOrdering::LayoutOptions( false ) ); - group->add( &m_intFieldRight2, caf::PdmUiOrdering::LayoutOptions( false ) ); - group->add( &m_intFieldLabelTop, caf::PdmUiOrdering::LayoutOptions( true, 6 ) ); - group->add( &m_stringFieldLabelHidden, caf::PdmUiOrdering::LayoutOptions( true, 6 ) ); - - caf::PdmUiGroup* autoGroup = - uiOrdering.addNewGroup( "Automatic Full Width Group", caf::PdmUiOrdering::LayoutOptions( true ) ); - autoGroup->add( &m_intFieldWideBothAuto, caf::PdmUiOrdering::LayoutOptions( true ) ); - autoGroup->add( &m_intFieldLeftAuto, caf::PdmUiOrdering::LayoutOptions( true ) ); - autoGroup->add( &m_intFieldCenterAuto, false ); - autoGroup->add( &m_intFieldRightAuto, caf::PdmUiOrdering::LayoutOptions( false ) ); - autoGroup->add( &m_intFieldLabelTopAuto, true ); - autoGroup->add( &m_stringFieldLabelHiddenAuto, true ); + caf::PdmUiGroup* group = uiOrdering.addNewGroup( "Wide Group", { .totalColumnSpan = 4 } ); + group->add( &m_intFieldWideBoth2, { .totalColumnSpan = 6, .leftLabelColumnSpan = 3 } ); + group->add( &m_intFieldLeft2 ); + group->appendToRow( &m_intFieldCenter ); + group->appendToRow( &m_intFieldRight2 ); + group->add( &m_intFieldLabelTop, { .totalColumnSpan = 6 } ); + group->add( &m_stringFieldLabelHidden, { .totalColumnSpan = 6 } ); + + caf::PdmUiGroup* autoGroup = uiOrdering.addNewGroup( "Automatic Full Width Group" ); + autoGroup->add( &m_intFieldWideBothAuto ); + autoGroup->add( &m_intFieldLeftAuto ); + autoGroup->appendToRow( &m_intFieldCenterAuto ); + autoGroup->appendToRow( &m_intFieldRightAuto ); + autoGroup->add( &m_intFieldLabelTopAuto ); + autoGroup->add( &m_stringFieldLabelHiddenAuto ); uiOrdering.add( &m_intFieldLeftOfGroup ); - caf::PdmUiGroup* group2 = uiOrdering.addNewGroup( "Right Group", caf::PdmUiOrdering::LayoutOptions( false, 2, 0 ) ); + caf::PdmUiGroup* group2 = + uiOrdering.addNewGroup( "Right Group", { .newRow = false, .totalColumnSpan = 2, .leftLabelColumnSpan = 0 } ); group2->setEnableFrame( false ); group2->add( &m_intFieldInsideGroup1 ); - caf::PdmUiGroup* group3 = uiOrdering.addNewGroup( "Narrow L", caf::PdmUiOrdering::LayoutOptions( true, 1 ) ); + caf::PdmUiGroup* group3 = uiOrdering.addNewGroup( "Narrow L", { .totalColumnSpan = 1 } ); group3->add( &m_intFieldInsideGroup2 ); - uiOrdering.add( &m_intFieldRightOfGroup, caf::PdmUiOrdering::LayoutOptions( false, 3, 2 ) ); + uiOrdering.add( &m_intFieldRightOfGroup, { .newRow = false, .totalColumnSpan = 3, .leftLabelColumnSpan = 2 } ); - caf::PdmUiGroup* groupL = uiOrdering.addNewGroup( "Left Group", caf::PdmUiOrdering::LayoutOptions( true, 1 ) ); + caf::PdmUiGroup* groupL = uiOrdering.addNewGroup( "Left Group", { .totalColumnSpan = 1 } ); groupL->add( &m_intFieldInsideGroup3 ); groupL->add( &m_intFieldInsideGroup5 ); - caf::PdmUiGroup* groupR = - uiOrdering.addNewGroup( "Right Wide Group", caf::PdmUiOrdering::LayoutOptions( false, 3 ) ); + caf::PdmUiGroup* groupR = uiOrdering.addNewGroup( "Right Wide Group", { .newRow = false, .totalColumnSpan = 3 } ); groupR->setEnableFrame( false ); groupR->add( &m_intFieldInsideGroup4 ); groupR->add( &m_intFieldInsideGroup6 ); @@ -690,7 +684,8 @@ class SmallDemoPdmObjectA : public caf::PdmObject CAF_PDM_InitField( &m_toggleField, "Toggle", false, - "Toggle Field much text much text much much text much text muchmuch text much text muchmuch " + "Toggle Field much text much text much much text much text muchmuch text much text " + "muchmuch " "text much " "text muchmuch text much text muchmuch text much text much", "", diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiComboBoxEditor.cpp b/Fwk/AppFwk/cafUserInterface/cafPdmUiComboBoxEditor.cpp index 1f51f29ec4..e0a9db744b 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiComboBoxEditor.cpp +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiComboBoxEditor.cpp @@ -61,6 +61,8 @@ CAF_PDM_UI_FIELD_EDITOR_SOURCE_INIT( PdmUiComboBoxEditor ); //-------------------------------------------------------------------------------------------------- void PdmUiComboBoxEditor::configureAndUpdateUi( const QString& uiConfigName ) { + if ( !uiField() ) return; + if ( !m_label.isNull() ) { PdmUiFieldEditorHandle::updateLabelFromField( m_label, uiConfigName ); @@ -412,6 +414,8 @@ QWidget* PdmUiComboBoxEditor::createLabelWidget( QWidget* parent ) //-------------------------------------------------------------------------------------------------- void PdmUiComboBoxEditor::slotIndexActivated( int index ) { + if ( !uiField() ) return; + uiField()->enableAutoValue( false ); if ( m_attributes.enableEditableContent ) @@ -439,6 +443,8 @@ void PdmUiComboBoxEditor::slotIndexActivated( int index ) //-------------------------------------------------------------------------------------------------- void PdmUiComboBoxEditor::slotEditTextChanged( const QString& text ) { + if ( !uiField() ) return; + if ( text == m_interactiveEditText ) return; uiField()->enableAutoValue( false ); @@ -480,6 +486,8 @@ void PdmUiComboBoxEditor::slotPreviousButtonPressed() //-------------------------------------------------------------------------------------------------- void PdmUiComboBoxEditor::slotApplyAutoValue() { + if ( !uiField() ) return; + bool enable = m_autoValueToolButton->isChecked(); uiField()->enableAutoValue( enable ); configureAndUpdateUi( "" ); diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiFormLayoutObjectEditor.cpp b/Fwk/AppFwk/cafUserInterface/cafPdmUiFormLayoutObjectEditor.cpp index 0e936df77a..67748340a1 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiFormLayoutObjectEditor.cpp +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiFormLayoutObjectEditor.cpp @@ -139,7 +139,7 @@ int caf::PdmUiFormLayoutObjectEditor::recursivelyConfigureAndUpdateUiOrderingInG &minimumItemColumnSpan, &minimumLabelColumnSpan, &minimumFieldColumnSpan ); - bool isExpandingItem = currentLayout.totalColumnSpan == PdmUiOrdering::LayoutOptions::MAX_COLUMN_SPAN; + bool isExpandingItem = currentLayout.totalColumnSpan == PdmUiOrdering::MAX_COLUMN_SPAN; int spareColumnsToAssign = 0; if ( isExpandingItem ) @@ -225,13 +225,13 @@ int caf::PdmUiFormLayoutObjectEditor::recursivelyConfigureAndUpdateUiOrderingInG { CAF_ASSERT( labelPos == PdmUiItemInfo::LEFT ); int leftLabelColumnSpan = minimumLabelColumnSpan; - if ( currentLayout.leftLabelColumnSpan == PdmUiOrdering::LayoutOptions::MAX_COLUMN_SPAN && - currentLayout.totalColumnSpan != PdmUiOrdering::LayoutOptions::MAX_COLUMN_SPAN ) + if ( currentLayout.leftLabelColumnSpan == PdmUiOrdering::MAX_COLUMN_SPAN && + currentLayout.totalColumnSpan != PdmUiOrdering::MAX_COLUMN_SPAN ) { leftLabelColumnSpan += spareColumnsToAssign; spareColumnsToAssign = 0; } - else if ( currentLayout.leftLabelColumnSpan == PdmUiOrdering::LayoutOptions::MAX_COLUMN_SPAN ) + else if ( currentLayout.leftLabelColumnSpan == PdmUiOrdering::MAX_COLUMN_SPAN ) { leftLabelColumnSpan += spareColumnsToAssign / 2; spareColumnsToAssign -= spareColumnsToAssign / 2; diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiPropertyView.cpp b/Fwk/AppFwk/cafUserInterface/cafPdmUiPropertyView.cpp index cb30269632..42cb5dc353 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiPropertyView.cpp +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiPropertyView.cpp @@ -38,6 +38,7 @@ #include "cafPdmObject.h" #include "cafPdmUiDefaultObjectEditor.h" +#include "cafStyleSheetTools.h" #include #include @@ -96,7 +97,10 @@ PdmUiPropertyView::PdmUiPropertyView( QWidget* parent, Qt::WindowFlags f ) m_scrollArea->setWidget( m_placeholder ); m_placeHolderLayout = new QVBoxLayout(); - m_placeHolderLayout->setContentsMargins( 5, 5, 5, 0 ); + m_placeHolderLayout->setContentsMargins( caf::StyleSheetTools::mediumContentMargin(), + caf::StyleSheetTools::mediumContentMargin(), + caf::StyleSheetTools::mediumContentMargin(), + 0 ); m_placeholder->setLayout( m_placeHolderLayout ); QVBoxLayout* dummy = new QVBoxLayout( this ); diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiTextEditor.cpp b/Fwk/AppFwk/cafUserInterface/cafPdmUiTextEditor.cpp index 284a691d39..781dce3f9b 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiTextEditor.cpp +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiTextEditor.cpp @@ -104,8 +104,8 @@ void PdmUiTextEditor::configureAndUpdateUi( const QString& uiConfigName ) PdmUiFieldEditorHandle::updateLabelFromField( m_label, uiConfigName ); - m_textEdit->setReadOnly( uiField()->isUiReadOnly( uiConfigName ) ); - // m_textEdit->setEnabled(!field()->isUiReadOnly(uiConfigName)); // Neccesary ? + bool isReadOnly = uiField()->isUiReadOnly( uiConfigName ); + m_textEdit->setReadOnly( isReadOnly ); m_textEdit->setToolTip( uiField()->uiToolTip( uiConfigName ) ); PdmUiTextEditorAttribute leab; @@ -125,7 +125,18 @@ void PdmUiTextEditor::configureAndUpdateUi( const QString& uiConfigName ) } else { - connect( m_textEdit, SIGNAL( editingFinished() ), this, SLOT( slotSetValueToField() ) ); + if ( isReadOnly ) + { + // Disable editingFinished signal when read only + // This can cause recursive update issues in some cases + // https://github.com/OPM/ResInsight/issues/10758 + disconnect( m_textEdit, SIGNAL( editingFinished() ), this, SLOT( slotSetValueToField() ) ); + } + else + { + connect( m_textEdit, SIGNAL( editingFinished() ), this, SLOT( slotSetValueToField() ) ); + } + m_saveButton->hide(); } diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiToolBarEditor.cpp b/Fwk/AppFwk/cafUserInterface/cafPdmUiToolBarEditor.cpp index e8e934204f..12e53d396c 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiToolBarEditor.cpp +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiToolBarEditor.cpp @@ -80,25 +80,29 @@ PdmUiToolBarEditor::~PdmUiToolBarEditor() //-------------------------------------------------------------------------------------------------- bool PdmUiToolBarEditor::isEditorDataEqualAndValid( const std::vector& fields ) const { - if ( m_fields.size() == fields.size() && m_fieldViews.size() == fields.size() ) + if ( m_fields.size() != fields.size() || m_fieldViews.size() != fields.size() ) { - bool equalContent = true; + return false; + } - for ( size_t i = 0; i < m_fields.size(); i++ ) + for ( size_t i = 0; i < m_fields.size(); i++ ) + { + auto currentField = m_fields[i]; + if ( currentField != fields[i] ) { - if ( m_fields[i] != fields[i] ) - { - equalContent = false; - } + return false; } - if ( equalContent ) + if ( currentField && currentField->uiCapability() ) { - return true; + auto contentText = currentField->uiCapability()->uiValue(); + // If there is no selection in a combo box, the content text is "-1" + // Rebuild the UI to make sure the available items in the combo box is updated + if ( contentText == "-1" ) return false; } } - return false; + return true; } //-------------------------------------------------------------------------------------------------- diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeView.cpp b/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeView.cpp index 72872aa9d2..0b95535da2 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeView.cpp +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeView.cpp @@ -42,7 +42,9 @@ #include "cafPdmUiTreeOrdering.h" #include "cafPdmUiTreeViewEditor.h" #include "cafQTreeViewStateSerializer.h" +#include "cafStyleSheetTools.h" +#include #include #include #include @@ -59,7 +61,12 @@ PdmUiTreeView::PdmUiTreeView( QWidget* parent, Qt::WindowFlags f ) : QWidget( parent, f ) { m_layout = new QVBoxLayout(); - m_layout->setContentsMargins( 0, 0, 0, 0 ); + + // 0 as content margin has been used for a long time, but that is too little + m_layout->setContentsMargins( caf::StyleSheetTools::mediumContentMargin(), + caf::StyleSheetTools::mediumContentMargin(), + caf::StyleSheetTools::mediumContentMargin(), + caf::StyleSheetTools::mediumContentMargin() ); setLayout( m_layout ); @@ -68,14 +75,14 @@ PdmUiTreeView::PdmUiTreeView( QWidget* parent, Qt::WindowFlags f ) m_searchBox = new QLineEdit( this ); m_searchBox->setPlaceholderText( "Type here to search in tree." ); searchLayout->addWidget( m_searchBox ); - m_clearSearchButton = new QPushButton( "X" ); - m_clearSearchButton->setMaximumSize( 30, 30 ); - searchLayout->addWidget( m_clearSearchButton ); + + m_clearAction = m_searchBox->addAction( QIcon( ":/caf/clear.svg" ), QLineEdit::TrailingPosition ); + connect( m_clearAction, &QAction::triggered, this, &PdmUiTreeView::slotOnClearSearchBox ); + m_clearAction->setVisible( false ); #if QT_VERSION >= QT_VERSION_CHECK( 5, 10, 0 ) m_layout->addLayout( searchLayout ); connect( m_searchBox, SIGNAL( textChanged( QString ) ), SLOT( slotOnSearchTextChanged() ) ); - connect( m_clearSearchButton, SIGNAL( clicked() ), SLOT( slotOnClearSearchBox() ) ); #endif m_treeViewEditor = new PdmUiTreeViewEditor(); @@ -169,6 +176,7 @@ void PdmUiTreeView::slotOnSelectionChanged() //-------------------------------------------------------------------------------------------------- void PdmUiTreeView::slotOnClearSearchBox() { + //m_clearAction->setVisible( false ); m_searchBox->setText( "" ); } @@ -180,6 +188,7 @@ void PdmUiTreeView::slotOnSearchTextChanged() QString searchText = m_searchBox->text().trimmed(); if ( searchText.isEmpty() ) { + m_clearAction->setVisible( false ); m_treeViewEditor->setFilterString( searchText ); if ( !m_treeStateString.isEmpty() ) { @@ -195,6 +204,7 @@ void PdmUiTreeView::slotOnSearchTextChanged() } m_treeViewEditor->setFilterString( searchText ); m_treeViewEditor->treeView()->expandAll(); + m_clearAction->setVisible( true ); } //-------------------------------------------------------------------------------------------------- diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeView.h b/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeView.h index f7c579bc2b..2e64fd2b9f 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeView.h +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeView.h @@ -46,8 +46,8 @@ class QItemSelection; class QMenu; class QModelIndex; class QLineEdit; -class QPushButton; class QSortFilterProxyModel; +class QAction; namespace caf { @@ -113,8 +113,8 @@ private slots: QString m_uiConfigName; QVBoxLayout* m_layout; QLineEdit* m_searchBox; - QPushButton* m_clearSearchButton; QString m_treeStateString; + QAction* m_clearAction; }; } // End of namespace caf diff --git a/Fwk/AppFwk/cafUserInterface/cafStyleSheetTools.cpp b/Fwk/AppFwk/cafUserInterface/cafStyleSheetTools.cpp index b32959fa01..7db448bcd4 100644 --- a/Fwk/AppFwk/cafUserInterface/cafStyleSheetTools.cpp +++ b/Fwk/AppFwk/cafUserInterface/cafStyleSheetTools.cpp @@ -70,3 +70,19 @@ QString StyleSheetTools::colorStringWithAlpha( const QColor& color ) { return QString( "rgba(%1, %2, %3, %4)" ).arg( color.red() ).arg( color.green() ).arg( color.blue() ).arg( color.alpha() ); } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +int StyleSheetTools::smallContentMargin() +{ + return 3; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +int StyleSheetTools::mediumContentMargin() +{ + return 6; +} diff --git a/Fwk/AppFwk/cafUserInterface/cafStyleSheetTools.h b/Fwk/AppFwk/cafUserInterface/cafStyleSheetTools.h index 4205ebe458..8f113fe535 100644 --- a/Fwk/AppFwk/cafUserInterface/cafStyleSheetTools.h +++ b/Fwk/AppFwk/cafUserInterface/cafStyleSheetTools.h @@ -50,6 +50,10 @@ class StyleSheetTools const QColor& backgroundColor, const QColor& backgroundFrameColor ); static QString colorStringWithAlpha( const QColor& color ); + + // Default content margin on most platforms is 11 pixels + static int smallContentMargin(); + static int mediumContentMargin(); }; } // namespace caf diff --git a/Fwk/CMakeLists.txt b/Fwk/CMakeLists.txt index 70d1aea4cb..ebc03e7082 100644 --- a/Fwk/CMakeLists.txt +++ b/Fwk/CMakeLists.txt @@ -8,7 +8,7 @@ else() message( STATUS "No buildcache found" ) endif() -set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD 20) project (TestCafAndVizFwk) diff --git a/GrpcInterface/GrpcProtos/Commands.proto b/GrpcInterface/GrpcProtos/Commands.proto index 604d927fed..3d1db2b9d1 100644 --- a/GrpcInterface/GrpcProtos/Commands.proto +++ b/GrpcInterface/GrpcProtos/Commands.proto @@ -144,14 +144,21 @@ message ExportWellPathRequest double mdStepSize = 2; } +enum ExportVisibleCellsKeywordType +{ + FLUXNUM = 0; + MULTNUM = 1; + ACTNUM = 2; +} + message ExportVisibleCellsRequest { - int32 caseId = 1; - int32 viewId = 2; - string exportKeyword = 3; - int32 visibleActiveCellsValue = 4; - int32 hiddenActiveCellsValue = 5; - int32 inactiveCellsValue = 6; + int32 caseId = 1; + int32 viewId = 2; + ExportVisibleCellsKeywordType exportKeyword = 3; + int32 visibleActiveCellsValue = 4; + int32 hiddenActiveCellsValue = 5; + int32 inactiveCellsValue = 6; } enum ExportFolderType { diff --git a/ResInsightVersion.cmake b/ResInsightVersion.cmake index 3fabd3445a..1c5132da43 100644 --- a/ResInsightVersion.cmake +++ b/ResInsightVersion.cmake @@ -1,17 +1,17 @@ set(RESINSIGHT_MAJOR_VERSION 2023) -set(RESINSIGHT_MINOR_VERSION 10) +set(RESINSIGHT_MINOR_VERSION 12) set(RESINSIGHT_PATCH_VERSION 0) # Opional text with no restrictions #set(RESINSIGHT_VERSION_TEXT "-dev") -#set(RESINSIGHT_VERSION_TEXT "-RC_04") +#set(RESINSIGHT_VERSION_TEXT "-RC_03") # Optional text # Must be unique and increasing within one combination of major/minor/patch version # The uniqueness of this text is independent of RESINSIGHT_VERSION_TEXT # Format of text must be ".xx" -#set(RESINSIGHT_DEV_VERSION ".16") +#set(RESINSIGHT_DEV_VERSION ".11") # https://github.com/CRAVA/crava/tree/master/libs/nrlib set(NRLIB_GITHUB_SHA "ba35d4359882f1c6f5e9dc30eb95fe52af50fd6f") diff --git a/ThirdParty/tomlplusplus b/ThirdParty/tomlplusplus new file mode 160000 index 0000000000..d8fa9a1fdd --- /dev/null +++ b/ThirdParty/tomlplusplus @@ -0,0 +1 @@ +Subproject commit d8fa9a1fddc90254cac2366dde23f0b613bc1280 diff --git a/ThirdParty/vcpkg b/ThirdParty/vcpkg index af2287382b..a42af01b72 160000 --- a/ThirdParty/vcpkg +++ b/ThirdParty/vcpkg @@ -1 +1 @@ -Subproject commit af2287382b1991dbdcb7e5112d236f3323b9dd7a +Subproject commit a42af01b72c28a8e1d7b48107b33e4f286a55ef6