From b0bf459b411db85981b574d6eb7a6b9370833b86 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 30 Apr 2019 08:18:09 +0200 Subject: [PATCH 001/396] Set version to 2019.04-dev.01 --- ResInsightVersion.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ResInsightVersion.cmake b/ResInsightVersion.cmake index 99c66ec8aa..7dc2ef9fb1 100644 --- a/ResInsightVersion.cmake +++ b/ResInsightVersion.cmake @@ -4,13 +4,13 @@ set(RESINSIGHT_MINOR_VERSION 04) set(RESINSIGHT_PATCH_VERSION 0) # Opional text with no restrictions -#set(RESINSIGHT_VERSION_TEXT "-rc1") +set(RESINSIGHT_VERSION_TEXT "-dev") # 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 ".01") +set(RESINSIGHT_DEV_VERSION ".01") # https://github.com/CRAVA/crava/tree/master/libs/nrlib set(NRLIB_GITHUB_SHA "ba35d4359882f1c6f5e9dc30eb95fe52af50fd6f") From d20ee3b3f135e0085fd06335421c608926cc8386 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 30 Apr 2019 10:45:41 +0200 Subject: [PATCH 002/396] Add field and object keywords based on 2019.04 --- .../2019.04/ri-fieldKeywords.txt | 2713 +++++++++++++++++ .../2019.04/ri-objectKeywords.txt | 280 ++ 2 files changed, 2993 insertions(+) create mode 100644 ApplicationCode/Adm/projectfilekeywords/2019.04/ri-fieldKeywords.txt create mode 100644 ApplicationCode/Adm/projectfilekeywords/2019.04/ri-objectKeywords.txt diff --git a/ApplicationCode/Adm/projectfilekeywords/2019.04/ri-fieldKeywords.txt b/ApplicationCode/Adm/projectfilekeywords/2019.04/ri-fieldKeywords.txt new file mode 100644 index 0000000000..0141a97cd5 --- /dev/null +++ b/ApplicationCode/Adm/projectfilekeywords/2019.04/ri-fieldKeywords.txt @@ -0,0 +1,2713 @@ +// ResInsight version string : 2019.04.0-dev.01 +// Report generated : Tue 30. Apr 10:17:11 2019 +// +// + +Annotations - class RimAnnotationInViewCollection + IsActive + TextAnnotations + AnnotationPlaneDepth + SnapAnnotations + TextAnnotationsInView + ReachCircleAnnotationsInView + UserDefinedPolylinesAnnotationsInView + PolylinesFromFileAnnotationsInView + +AsciiDataCurve - class RimAsciiDataCurve + Show + CurveName + CurveDescription + LegendDescription + AutoName + Color + Thickness + CurveInterpolation + LineStyle + PointSymbol + SymbolEdgeColor + SymbolSkipPxDist + ShowLegend + SymbolSize + ShowErrorBars + PlotAxis + TimeSteps + Values + Title + +CalcScript - class RimCalcScript + AbsolutePath + Content + +CalculatedSummaryCase - class RimCalculatedSummaryCase + ShortName + AutoShortyName + SummaryHeaderFilename + +CellEdgeResultSlot - class RimCellEdgeColors + EnableCellEdgeColors + propertyType + CellEdgeVariable + UseXVariable + UseYVariable + UseZVariable + LegendDefinition + SingleVarEdgeResult + +CellFilter - class RimCellFilter + UserDescription + Active + FilterType + +CellPropertyFilter - class RimEclipsePropertyFilter + UserDescription + Active + FilterType + SelectedValues + EvaluationRegion + ResultDefinition + Dummy_keyword + LowerBound + UpperBound + CategorySelection + +CellPropertyFilters - class RimEclipsePropertyFilterCollection + Active + PropertyFilters + +CellRangeFilter - class RimCellRangeFilter + UserDescription + Active + FilterType + GridIndex + PropagateToSubGrids + StartIndexI + CellCountI + StartIndexJ + CellCountJ + StartIndexK + CellCountK + UseIndividualCellIndices + IndividualCellIndices + +CellRangeFilterCollection - class RimCellRangeFilterCollection + RangeFilters + Active + +ChangeDataSourceFeatureUi - class RimWellLogCurveCommonDataSource + CurveCase + TrajectoryType + CurveWellPath + SimulationWellName + BranchDetection + Branch + CurveTimeStep + +CmdAddItemExecData - class caf::CmdAddItemExecData + PathToField + indexAfter + createdItemIndex + +CmdDeleteItemExecData - class caf::CmdDeleteItemExecData + PathToField + indexToObject + deletedObjectAsXml + +CmdFieldChangeExecData - class caf::CmdFieldChangeExecData + PathToField + +CompletionTemplateCollection - class RimCompletionTemplateCollection + FractureTemplates + ValveTemplates + +CrossSection - class RimIntersection + UserDescription + Active + Type + Direction + WellPath + SimulationWell + Points + AzimuthAngle + DipAngle + CustomExtrusionPoints + TwoAzimuthPoints + Branch + ExtentLength + lengthUp + lengthDown + ShowInactiveCells + m_activateUiAppendPointsCommand + inputExtrusionPointsFromViewerEnabled + inputTwoAzimuthPointsFromViewerEnabled + +CrossSectionCollection - class RimIntersectionCollection + CrossSections + IntersectionBoxes + Active + +Eclipse2dViewCollection - class RimEclipseContourMapViewCollection + EclipseViews + +EclipseCase - class RimEclipseResultCase + CaseUserDescription + CaseId + DefaultFormationNames + TimeStepFilter + IntersectionViewCollection + ReservoirViews + MatrixModelResults + FractureModelResults + FlipXAxis + FlipYAxis + CachedFileNamesContainingFaults + ContourMaps + FilesContainingFaults + CaseName + CaseFileName + UnitSystem + FlowDiagSolutions + CaseFolder + SourSimFileName + +EclipseGeometrySelectionItem - class RimEclipseGeometrySelectionItem + EclipseCase + GridIndex + CellIndex + LocalIntersectionPoint + +Fault - class RimFaultInView + FaultName + ShowFault + Color + +Faults - class RimFaultInViewCollection + Active + ShowFaultFaces + ShowOppositeFaultFaces + ShowFaultsOutsideFilters + FaultFaceCulling + ShowFaultLabel + FaultLabelColor + ShowNNCs + HideNncsWhenNoResultIsAvailable + NoCommonAreaNnncCollection + Faults + +FileSummaryCase - class RimFileSummaryCase + ShortName + AutoShortyName + SummaryHeaderFilename + IncludeRestartFiles + +FishbonesCollection - class RimFishbonesCollection + Name + IsChecked + FishbonesSubs + WellPathCollection + StartMD + MainBoreDiameter + MainBoreSkinFactor + MswParameters + LinerDiameter + RoughnessFactor + PressureDrop + LengthAndDepth + +FishbonesMultipleSubs - class RimFishbonesMultipleSubs + 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 + ApplyTimeSteps + CellPVThreshold + ShowLegend + CellFilter + CellFilterView + TracerFilter + SelectedTracerNames + ShowRegion + MinCommunication + MaxTof + +FlowDiagSolution - class RimFlowDiagSolution + UserDescription + +FlowPlotCollection - class RimFlowPlotCollection + FlowCharacteristicsPlot + DefaultWellAllocationPlot + StoredWellAllocationPlots + StoredFlowCharacteristicsPlots + +FormationNames - class RimFormationNames + FormationNamesFileName + +FormationNamesCollectionObject - class RimFormationNamesCollection + FormationNamesList + +FractureContainment - class RimFractureContainment + IsUsingFractureContainment + TopKLayer + BaseKLayer + TruncateAtFaults + FaultThrowValue + +FractureDefinitionCollection - 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 + +GeoMechPropertyFilter - class RimGeoMechPropertyFilter + UserDescription + Active + FilterType + SelectedValues + ResultDefinition + LowerBound + UpperBound + +GeoMechPropertyFilters - class RimGeoMechPropertyFilterCollection + Active + PropertyFilters + +GeoMechResultDefinition - class RimGeoMechResultDefinition + ResultPositionType + ResultFieldName + ResultComponentName + TimeLapseBaseTimeStep + CompactionRefLayer + ResultPositionTypeUi + ResultVariableUI + CompactionRefLayerUi + IsTimeLapseResult + +GeoMechResultSlot - class RimGeoMechCellColors + ResultPositionType + ResultFieldName + ResultComponentName + TimeLapseBaseTimeStep + CompactionRefLayer + ResultPositionTypeUi + ResultVariableUI + CompactionRefLayerUi + IsTimeLapseResult + LegendDefinition + +GeoMechView - class RimGeoMechView + WindowController + ShowWindow + WindowGeometry + NameConfig + UserDescription + CameraPosition + CameraPointOfInterest + PerspectiveProjection + GridZScale + ViewBackgroundColor + MaximumFrameRate + AnimationMode + CurrentTimeStep + MeshMode + SurfaceMode + ShowGridBox + DisableLighting + ShowZScale + RangeFilters + RangeFiltersControlled + CrossSections + GridCollection + OverlayInfoConfig + GridCellResult + TensorResults + PropertyFilters + +GridCollection - class RimGridCollection + IsActive + MainGrid + PersistentLgrs + TemporaryLgrs + +GridCrossPlotCurve - class RimGridCrossPlotCurve + Show + CurveName + CurveDescription + LegendDescription + AutoName + Color + Thickness + CurveInterpolation + LineStyle + PointSymbol + SymbolEdgeColor + SymbolSkipPxDist + ShowLegend + SymbolSize + ShowErrorBars + +GridCrossPlotCurveSet - class RimGridCrossPlotDataSet + Name + IsChecked + Case + TimeStep + VisibleCellView + Grouping + XAxisProperty + YAxisProperty + GroupingProperty + NameConfig + CrossPlotCurves + UseCustomColor + CustomColor + PlotCellFilterCollection + +GridInfo - class RimGridInfo + IsActive + GridName + GridIndex + +GridInfoCollection - class RimGridInfoCollection + IsActive + GridInfos + +GridSummaryCase - class RimGridSummaryCase + ShortName + AutoShortyName + SummaryHeaderFilename + Associated3DCase + CachedCasename + Associated3DCaseGridFileName + IncludeRestartFiles + +GridTimeHistoryCurve - class RimGridTimeHistoryCurve + Show + CurveName + CurveDescription + LegendDescription + AutoName + Color + Thickness + CurveInterpolation + LineStyle + PointSymbol + SymbolEdgeColor + SymbolSkipPxDist + ShowLegend + SymbolSize + ShowErrorBars + GeometrySelectionText + EclipseResultDefinition + GeoMechResultDefinition + GeometrySelectionItem + PlotAxis + +Intersection2dView - class Rim2dIntersectionView + WindowController + ShowWindow + WindowGeometry + NameConfig + UserDescription + CameraPosition + CameraPointOfInterest + PerspectiveProjection + GridZScale + ViewBackgroundColor + MaximumFrameRate + AnimationMode + CurrentTimeStep + MeshMode + SurfaceMode + ShowGridBox + DisableLighting + ShowZScale + Intersection + LegendDefinition + TernaryLegendDefinition + ShowDefiningPoints + ShowAxisLines + NameProxy + +Intersection2dViewCollection - class Rim2dIntersectionViewCollection + IntersectionViews + +IntersectionBox - class RimIntersectionBox + UserDescription + Active + singlePlaneState + MinXCoord + MaxXCoord + MinYCoord + MaxYCoord + MinDepth + MaxDepth + ShowInactiveCells + xySliderStepSize + DepthSliderStepSize + show3DManipulator + +Legend - class RimRegularLegendConfig + ShowLegend + NumberOfLevels + Precision + TickNumberFormat + ColorRangeMode + MappingMode + RangeType + UserDefinedMax + UserDefinedMin + ResultVariableUsage + +MainPlotCollection - class RimMainPlotCollection + Show + WellLogPlotCollection + RftPlotCollection + PltPlotCollection + SummaryPlotCollection + SummaryCrossPlotCollection + FlowPlotCollection + Rim3dCrossPlotCollection + RimSaturationPressurePlotCollection + +MdiWindowController - class RimMdiWindowController + MainWindowID + xPos + yPos + Width + Height + IsMaximized + +MockModelSettings - class RimMockModelSettings + CellCountX + CellCountY + CellCountZ + TotalCellCount + ResultCount + TimeStepCount + +ModeledWellPath - class RimModeledWellPath + WellPathName + DatumElevation + UnitSystem + SimWellName + SimBranchIndex + ShowWellPathLabel + ShowWellPath + WellPathRadiusScale + WellPathColor + Completions + WellLogFiles + CollectionOf3dWellLogCurves + WellPathFormationKeyInFile + WellPathFormationFilePath + WellLogFile + WellPathAttributes + WellPathGeometryDef + +MultiSnapshotDefinition - class RimAdvancedSnapshotExportDefinition + IsActive + View + EclipseResultType + SelectedEclipseResults + TimeStepStart + TimeStepEnd + SnapShotDirection + RangeFilterStart + RangeFilterEnd + AdditionalCases + +NoCommonAreaNNC - class RimNoCommonAreaNNC + Name + +ObservedDataCollection - class RimObservedDataCollection + ObservedDataArray + +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 + MswParameters + NonDarcyParameters + +PolylineTarget - class RimPolylineTarget + IsEnabled + TargetPointXyd + +PolylinesFromFileAnnotation - class RimPolylinesFromFileAnnotation + IsActive + ClosePolyline + ShowLines + ShowSpheres + Appearance + PolyLineFilePath + PolyLineDescription + +PropertyFilter - class RimPropertyFilter + UserDescription + Active + FilterType + SelectedValues + +ResInsightAnalysisModels - class RimEclipseCaseCollection + Reservoirs + CaseGroups + +ResInsightGeoMechCase - class RimGeoMechCase + CaseUserDescription + CaseId + DefaultFormationNames + TimeStepFilter + IntersectionViewCollection + CaseFileName + GeoMechViews + CaseCohesion + FrctionAngleDeg + ElementPropertyFileNames + ElementPropertyFileNameIndexUiSelection + closeElementPropertyFileCommad + reloadElementPropertyFileCommand + ContourMaps + +ResInsightGeoMechModels - class RimGeoMechModels + Cases + +ResInsightOilField - class RimOilField + AnalysisModels + GeoMechModels + WellPathCollection + CompletionTemplateCollection + SummaryCaseCollection + FormationNamesCollection + ObservedDataCollection + AnnotationCollection + FractureDefinitionCollection + Measurement + +ResInsightProject - class RimProject + DocumentFileName + ProjectFileVersionString + NextValidCaseId + NextValidCaseGroupId + OilFields + ScriptCollection + WellPathImport + MainPlotCollection + LinkedViews + CalculationCollection + CommandObjects + MultiSnapshotDefinitions + TreeViewState + TreeViewCurrentModelIndexPath + PlotWindowTreeViewState + PlotWindowTreeViewCurrentModelIndexPath + show3DWindow + showPlotWindow + tiled3DWindow + tiledPlotWindow + DialogData + Reservoirs + CaseGroups + +ReservoirCellResultStorage - class RimReservoirCellResultsStorage + ResultCacheFileName + ResultCacheEntries + +ReservoirView - class RimEclipseView + WindowController + ShowWindow + WindowGeometry + NameConfig + UserDescription + CameraPosition + CameraPointOfInterest + PerspectiveProjection + GridZScale + ViewBackgroundColor + MaximumFrameRate + AnimationMode + CurrentTimeStep + MeshMode + SurfaceMode + ShowGridBox + DisableLighting + ShowZScale + RangeFilters + RangeFiltersControlled + CrossSections + GridCollection + OverlayInfoConfig + GridCellResult + GridCellEdgeResult + FaultResultSettings + StimPlanColors + VirtualPerforationResult + WellCollection + FaultCollection + AnnotationCollection + PropertyFilters + ShowMainGrid + ShowInactiveCells + ShowInvalidCells + +ResultDefinition - class RimEclipseResultDefinition + ResultType + PorosityModelType + ResultVariable + FlowDiagSolution + TimeLapseBaseTimeStep + DifferenceCase + SelectedTracers + SelectedInjectorTracers + SelectedProducerTracers + SelectedSouringTracers + FlowTracerSelectionMode + PhaseSelection + MResultType + MPorosityModelType + MResultVariable + MFlowDiagSolution + MSyncSelectedInjProd + MSyncSelectedProdInj + MSelectedInjectorTracers + MSelectedProducerTracers + MSelectedSouringTracers + +ResultSlot - class RimEclipseCellColors + ResultType + PorosityModelType + ResultVariable + FlowDiagSolution + TimeLapseBaseTimeStep + DifferenceCase + SelectedTracers + SelectedInjectorTracers + SelectedProducerTracers + SelectedSouringTracers + FlowTracerSelectionMode + PhaseSelection + MResultType + MPorosityModelType + MResultVariable + MFlowDiagSolution + MSyncSelectedInjProd + MSyncSelectedProdInj + MSelectedInjectorTracers + MSelectedProducerTracers + MSelectedSouringTracers + LegendDefinition + ResultVarLegendDefinitionList + TernaryLegendDefinition + LegendDefinitionPtrField + +ResultStorageEntryInfo - class RimReservoirCellResultsStorageEntryInfo + ResultType + ResultName + TimeSteps + DaysSinceSimulationStart + FilePositionDataStart + +RftAddress - class RimDataSourceForRftPlt + SourceType + EclipseCase + WellLogFile + +RiaMemoryCleanup - class RiaMemoryCleanup + DataCase + ResultsToDelete + ClearSelectedData + +RiaPreferences - class RiaPreferences + navigationPolicy + scriptDirectory + scriptEditorExecutable + octaveExecutable + octaveShowHeaderInfoWhenExecutingScripts + ssihubAddress + defaultMeshModeType + defaultGridLineColors + defaultFaultGridLineColors + defaultWellLableColor + defaultViewerBackgroundColor + defaultScaleFactorZ + fontSizeInScene + defaultAnnotationFontSize + wellLabelFontSize + defaultPlotFontSize + showLasCurveWithoutTvdWarning + useShaders + showHud + appendClassNameToUiText + appendFieldKeywordToToolTipText + showTestToolbar + includeFractureDebugInfoFile + showLegendBackground + lastUsedProjectFileName + autocomputeDepth + loadAndShowSoil + summaryRestartFilesShowImportDialog + summaryImportMode + gridImportMode + holoLensExportFolder + holoLensDisableCertificateVerification + showProjectChangedDialog + readerSettings + +RiaRegressionTest - class RiaRegressionTest + workingFolder + folderContainingDiffTool + folderContainingGitTool + regressionTestFolder + showInteractiveDiffImages + useOpenMPForGeometryCreation + openReportInBrowser + testFilter + appendTestsAfterTestFilter + +RicCaseAndFileExportSettingsUi - class RicCaseAndFileExportSettingsUi + Folder + CaseToApply + +RicCellRangeUi - class RicCellRangeUi + Case + GridIndex + StartIndexI + StartIndexJ + StartIndexK + CellCountI + CellCountJ + CellCountK + +RicDeleteItemExecData - class RicDeleteItemExecData + PathToField + 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 + +RicExportEclipseInputGridUi - class RicExportEclipseSectorModelUi + ExportGrid + ExportGridFilename + ExportInLocalCoords + InvisibleCellActnum + GridBoxSelection + MinI + MinJ + MinK + MaxI + MaxJ + MaxK + ExportFaults + ExportFaultsFilename + RefinementCountI + RefinementCountJ + RefinementCountK + ExportParams + ExportParamsFilename + ExportMainKeywords + +RicExportLgrUi - class RicExportLgrUi + ExportFolder + CaseToApply + TimeStepIndex + IncludePerforations + IncludeFractures + IncludeFishbones + CellCountI + CellCountJ + CellCountK + SplitType + +RicExportToLasFileObj - class RicExportToLasFileObj + tvdrkbOffset + +RicExportToLasFileResampleUi - class RicExportToLasFileResampleUi + ExportFolder + ActivateResample + ResampleInterval + ExportTvdrkb + tvdrkbOffsets + +RicExportWellPathsUi - class RicExportWellPathsUi + ExportFolder + MdStepSize + +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 + PreviewText + +RicSaturationPressureUi - class RicSaturationPressureUi + CaseToApply + +RicSaveEclipseInputVisibleCellsUi - class RicSaveEclipseInputVisibleCellsUi + ExportFilename + ExportKeyword + VisibleActiveCellsValue + HiddenActiveCellsValue + InactiveCellsValue + +RicSelectSummaryPlotUI - class RicSelectSummaryPlotUI + SelectedSummaryPlot + CreateNewPlot + NewViewName + +RicSelectViewUI - class RicSelectViewUI + MasterView + CreateNewView + NewViewName + +RicSummaryAddressSelection - class RiuSummaryCurveDefSelection + SummaryCases + CurrentSummaryCategory + SelectedSummaryCategories + FieldVectors + Aquifers + AquiferVectors + NetworkVectors + MiscVectors + Regions + RegionsVectors + Region2RegionRegions + Region2RegionVectors + WellGroupWellGroupNames + WellGroupVectors + WellWellName + WellVectors + WellCompletionWellName + WellCompletionIjk + WellCompletionVectors + WellCompletionLgrLgrName + WellCompletionLgrWellName + WellCompletionLgrIjk + WellCompletionLgrVectors + WellLgrLgrName + WellLgrWellName + WellLgrVectors + WellSegmentWellName + WellSegmentNumber + WellSegmentVectors + BlockIjk + BlockVectors + BlockLgrLgrName + BlockLgrIjk + BlockLgrVectors + CalculatedVectors + ImportedVectors + +RicSummaryCurveCalculator - class RicSummaryCurveCalculator + CurrentCalculation + NewCalculation + DeleteCalculation + +RicSummaryCurveCreator - class RicSummaryCurveCreator + TargetPlot + UseAutoAppearanceAssignment + AppearanceApplyButton + CaseAppearanceType + VariableAppearanceType + WellAppearanceType + GroupAppearanceType + RegionAppearanceType + UseAutoPlotTitle + ApplySelection + Close + OK + SummaryCurveNameConfig + +RicWellPathsUnitSystemSettingsUi - class RicWellPathsUnitSystemSettingsUi + UnitSystem + +RifReaderSettings - class RifReaderSettings + importFaults + importSimulationNNCs + importAdvancedMswData + useResultIndexFile + skipWellData + includeFileAbsolutePathPrefix + +Rim3dWellLogCurveCollection - class Rim3dWellLogCurveCollection + Show3dWellLogCurves + PlaneWidthScaling + Show3dWellLogGrid + Show3dWellLogBackground + ArrayOf3dWellLogCurves + +Rim3dWellLogExtractionCurve - class Rim3dWellLogExtractionCurve + Show3dWellLogCurve + MinCurveValue + MaxCurveValue + DrawPlane + CurveColor + CurveCase + CurveTimeStep + 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 + my2dWellLogRftCurve + 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 + Style + +RimAnnotationTextAppearance - class RimAnnotationTextAppearance + FontSize + FontColor + BackgroundColor + AnchorLineColor + +RimBinaryExportSettings - class RimBinaryExportSettings + Filename + EclipseKeyword + UndefinedValue + +RimCaseCollection - class RimCaseCollection + Reservoirs + +RimCommandExecuteScript - class RimCommandExecuteScript + Name + ScriptText + IsEnabled + Execute + +RimCommandIssueFieldChanged - class RimCommandIssueFieldChanged + CommandName + ObjectName + FieldName + FieldValueToApply + +RimCommandObject - class RimCommandObject + +RimContourMapView - class RimEclipseContourMapView + WindowController + ShowWindow + WindowGeometry + NameConfig + UserDescription + CameraPosition + CameraPointOfInterest + PerspectiveProjection + GridZScale + ViewBackgroundColor + MaximumFrameRate + AnimationMode + CurrentTimeStep + MeshMode + SurfaceMode + ShowGridBox + DisableLighting + ShowZScale + RangeFilters + RangeFiltersControlled + CrossSections + GridCollection + OverlayInfoConfig + GridCellResult + GridCellEdgeResult + FaultResultSettings + StimPlanColors + VirtualPerforationResult + WellCollection + FaultCollection + AnnotationCollection + PropertyFilters + ShowMainGrid + ShowInactiveCells + ShowInvalidCells + ContourMapProjection + ShowAxisLines + ShowScaleLegend + +RimCsvUserData - class RimCsvUserData + ShortName + AutoShortyName + SummaryHeaderFilename + ImportedSummaryData + UseCustomIdentifier + SummaryType + IdentifierName + ParseOptions + +RimCurveNameConfig - class RimNameConfig + IsUsingAutoName + CustomCurveName + AutoCurveName + +RimDerivedEnsembleCaseCollection - class RimDerivedEnsembleCaseCollection + SummaryCases + SummaryCollectionName + NameCount + IsEnsemble + Ensemble1 + Ensemble2 + Operator + SwapEnsembles + CaseCount + +RimDialogData - class RimDialogData + ExportCarfin + ExportCompletionData + MultipleFractionsData + HoloLenseExportToFolderData + ExportwellPathsData + ExportLgr + ExportSectorModel + MockModelSettings + +RimEclipseContourMapProjection - class RimEclipseContourMapProjection + Name + IsChecked + SampleSpacing + ResultAggregation + ContourLines + ContourLabels + SmoothContourLines + WeightByParameter + WeightingResult + +RimEllipseFractureTemplate - class RimEllipseFractureTemplate + Id + UserDescription + NameAndUnit + UnitSystem + Orientation + AzimuthAngle + SkinFactor + PerforationLength + PerforationEfficiency + WellDiameter + ConductivityType + FractureContainmentField + NonDarcyFlowType + UserDefinedDFactor + FractureWidthType + FractureWidth + BetaFactorType + InertialCoefficient + PermeabilityType + RelativePermeability + EffectivePermeability + RelativeGasDensity + GasViscosity + dFactorDisplayField + dFactorSummaryText + HeightScaleFactor + WidthScaleFactor + DFactorScaleFactor + ConductivityFactor + ScaleApplyButton + HalfLength + Height + Width + Permeability + +RimEnsembleCurveFilter - class RimEnsembleCurveFilter + Active + EnsembleParameter + MinValue + MaxValue + Categories + DeleteEnsembleFilter + +RimEnsembleCurveFilterCollection - class RimEnsembleCurveFilterCollection + Active + CurveFilters + NewEnsembleFilter + +RimEnsembleCurveSet - class RimEnsembleCurveSet + EnsembleCurveSet + IsActive + SummaryGroup + SelectedVariableDisplayVar + VarListFilter + FilterResultSelection + SummaryAddress + SelectAddress + ColorMode + Color + EnsembleParameter + PlotAxis + LegendConfig + CurveFilters + Statistics + UserDefinedName + AutoGeneratedName + AutoName + SummaryAddressNameTools + +RimEnsembleCurveSetCollection - class RimEnsembleCurveSetCollection + EnsembleCurveSets + IsActive + YSourceStepping + +RimEnsembleStatistics - class RimEnsembleStatistics + Active + HideEnsembleCurves + BasedOnFilteredCases + ShowP10Curve + ShowP50Curve + ShowP90Curve + ShowMeanCurve + ShowCurveLabels + WarningLabel + Color + +RimExportInputSettings - class RimExportInputSettings + Filename + Keyword + +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 + NameConfig + UserDescription + CameraPosition + CameraPointOfInterest + PerspectiveProjection + GridZScale + ViewBackgroundColor + MaximumFrameRate + AnimationMode + CurrentTimeStep + MeshMode + SurfaceMode + ShowGridBox + DisableLighting + ShowZScale + RangeFilters + RangeFiltersControlled + CrossSections + GridCollection + OverlayInfoConfig + GridCellResult + TensorResults + PropertyFilters + ContourMapProjection + ShowAxisLines + ShowScaleLegend + +RimGridCrossPlot - class RimGridCrossPlot + WindowController + ShowWindow + WindowGeometry + ShowInfoBox + ShowLegend + LegendFontSize + NameConfig + xAxisProperties + yAxisProperties + CrossPlotCurve + +RimGridCrossPlotCollection - class RimGridCrossPlotCollection + GridCrossPlots + +RimGridCrossPlotCurveSetNameConfig - class RimGridCrossPlotDataSetNameConfig + IsUsingAutoName + CustomCurveName + AutoCurveName + AddCaseName + AddAxisVariables + AddTimeStep + AddGrouping + +RimGridCrossPlotNameConfig - class RimGridCrossPlotNameConfig + IsUsingAutoName + CustomCurveName + AutoCurveName + AddDataSetNames + +RimIdenticalGridCaseGroup - class RimIdenticalGridCaseGroup + UserDescription + GroupId + StatisticsCaseCollection + CaseCollection + +RimInputProperty - class RimEclipseInputProperty + ResultName + EclipseKeyword + FileName + ResolvedState + +RimInputPropertyCollection - class RimEclipseInputPropertyCollection + InputProperties + +RimInputReservoir - class RimEclipseInputCase + CaseUserDescription + CaseId + DefaultFormationNames + TimeStepFilter + IntersectionViewCollection + ReservoirViews + MatrixModelResults + FractureModelResults + FlipXAxis + FlipYAxis + CachedFileNamesContainingFaults + ContourMaps + FilesContainingFaults + CaseName + GridFileName + InputPropertyCollection + AdditionalFileNamesProxy + AdditionalFileNames + +RimMeasurement - class RimMeasurement + +RimMswCompletionParameters - class RimMswCompletionParameters + RefMDType + RefMD + LinerDiameter + RoughnessFactor + PressureDrop + LengthAndDepth + EnforceMaxSegmentLength + MaxSegmentLength + +RimMultipleValveLocations - class RimMultipleValveLocations + LocationMode + RangeStart + RangeEnd + ValveSpacing + RangeValveCount + LocationOfValves + +RimNoCommonAreaNncCollection - class RimNoCommonAreaNncCollection + UserDescription + NoCommonAreaNncs + +RimNonDarcyPerforationParameters - class RimNonDarcyPerforationParameters + NonDarcyFlowType + UserDefinedDFactor + GridPermeabilityScalingFactor + WellRadius + RelativeGasDensity + GasViscosity + InertialCoefficientBeta0 + PermeabilityScalingFactor + PorosityScalingFactor + +RimObservedEclipseUserData - class RimObservedEclipseUserData + ShortName + AutoShortyName + SummaryHeaderFilename + ImportedSummaryData + UseCustomIdentifier + SummaryType + IdentifierName + +RimOilFieldEntry - class RimOilFieldEntry + OilFieldName + EdmId + Selected + wellsFilePath + Wells + +RimOilRegionEntry - class RimOilRegionEntry + OilRegionEntry + Fields + Selected + +RimPlotAxisAnnotation - class RimPlotAxisAnnotation + Active + Name + Value + AnnotationType + Associated3DCase + m_equilNum + +RimPlotCellFilterCollection - class RimPlotCellFilterCollection + Name + IsChecked + FilterMode + CellFilters + +RimPlotCellPropertyFilter - class RimPlotCellPropertyFilter + Name + IsChecked + FilterMode + ResultDefinition + LowerBound + UpperBound + +RimPolylineAppearance - class RimPolylineAppearance + LineFieldsHidden + Color + Thickness + Style + SphereFieldsHidden + SphereColor + SphereRadiusFactor + +RimPolylinesAnnotationInView - class RimPolylinesAnnotationInView + IsActive + SourceAnnotation + +RimPolylinesFromFileAnnotationInView - class RimPolylinesFromFileAnnotationInView + IsActive + SourceAnnotation + +RimReachCircleAnnotation - class RimReachCircleAnnotation + IsActive + CenterPointXyd + AnchorPointPick + Radius + Name + Appearance + +RimReachCircleAnnotationInView - class RimReachCircleAnnotationInView + IsActive + SourceAnnotation + +RimSaturationPressurePlot - class RimSaturationPressurePlot + WindowController + ShowWindow + WindowGeometry + ShowInfoBox + ShowLegend + LegendFontSize + NameConfig + xAxisProperties + yAxisProperties + CrossPlotCurve + +RimSaturationPressurePlotCollection - class RimSaturationPressurePlotCollection + SaturationPressurePlots + +RimStatisticalCalculation - class RimEclipseStatisticsCase + CaseUserDescription + CaseId + DefaultFormationNames + TimeStepFilter + IntersectionViewCollection + ReservoirViews + MatrixModelResults + FractureModelResults + FlipXAxis + FlipYAxis + CachedFileNamesContainingFaults + ContourMaps + FilesContainingFaults + CaseName + m_editingAllowed + SelectionSummary + 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 + NameAndUnit + UnitSystem + Orientation + AzimuthAngle + SkinFactor + PerforationLength + PerforationEfficiency + WellDiameter + ConductivityType + FractureContainmentField + NonDarcyFlowType + UserDefinedDFactor + FractureWidthType + FractureWidth + BetaFactorType + InertialCoefficient + PermeabilityType + RelativePermeability + EffectivePermeability + RelativeGasDensity + GasViscosity + dFactorDisplayField + dFactorSummaryText + HeightScaleFactor + WidthScaleFactor + DFactorScaleFactor + ConductivityFactor + ScaleApplyButton + StimPlanFileName + WellPathDepthAtFracture + BorderPolygonResultName + ActiveTimeStepIndex + ConductivityResultName + ShowStimPlanMesh + +RimStimPlanLegendConfig - class RimStimPlanLegendConfig + Name + Legend + +RimSummaryCalculation - class RimSummaryCalculation + Description + Expression + Unit + Variables + CalculatedValues + TimeSteps + +RimSummaryCalculationCollection - class RimSummaryCalculationCollection + Calculations + CalculationsSummaryCase + +RimSummaryCalculationVariable - class RimSummaryCalculationVariable + VariableName + PushButton + SummaryAddressUi + SummaryCase + SummaryAddress + +RimSummaryCurveCollection - class RimSummaryCurveCollection + CollectionCurves + IsActive + YSourceStepping + XSourceStepping + UnionSourceStepping + +RimSummaryCurveCollectionModifier - class RimSummaryPlotSourceStepping + CurveCase + IncludeEnsembleCasesForCaseStepping + WellName + GroupName + Region + Quantities + Ensemble + Placeholder + +RimTensorResults - class RimTensorResults + LegendDefinition + ResultVariable + ResultVariableUI + ShowTensors + Principal1 + Principal2 + Principal3 + Threshold + VectorColor + ScaleMethod + SizeScale + RangeType + +RimTernaryLegendConfig - class RimTernaryLegendConfig + ShowTernaryLegend + Precision + RangeType + m_applyLocalMinMax + m_applyGlobalMinMax + m_applyFullRangeMinMax + ternaryRangeSummary + UserDefinedMaxSoil + UserDefinedMinSoil + UserDefinedMaxSgas + UserDefinedMinSgas + UserDefinedMaxSwat + UserDefinedMinSwat + +RimTextAnnotation - class RimTextAnnotation + AnchorPointXyd + AnchorPointPick + LabelPointXyd + LabelPointPick + Text + IsActive + TextAppearance + NameProxy + +RimTextAnnotationInView - class RimTextAnnotationInView + IsActive + SourceAnnotation + +RimTimeStepFilter - class RimTimeStepFilter + FilterType + FirstTimeStep + LastTimeStep + Interval + TimeStepsFromFile + DateFormat + TimeStepIndicesToImport + TimeStepIndicesUi + ApplyReloadOfCase + +RimUserDefinedPolylinesAnnotationInView - class RimUserDefinedPolylinesAnnotationInView + IsActive + SourceAnnotation + +RimViewLinkerCollection - class RimViewLinkerCollection + Active + ViewLinkers + +RimViewNameConfig - class RimViewNameConfig + IsUsingAutoName + CustomCurveName + AutoCurveName + AddCaseName + AddAggregationType + AddProperty + AddSampleSpacing + +RimVirtualPerforationResults - class RimVirtualPerforationResults + ShowConnectionFactors + ShowClosedConnections + GeometryScaleFactor + LegendDefinition + +RimWellLogExtractionCurve - class RimWellLogExtractionCurve + Show + CurveName + CurveDescription + LegendDescription + AutoName + Color + Thickness + CurveInterpolation + LineStyle + PointSymbol + SymbolEdgeColor + SymbolSkipPxDist + ShowLegend + SymbolSize + ShowErrorBars + TrajectoryType + CurveWellPath + SimulationWellName + BranchDetection + Branch + CurveCase + CurveEclipseResult + CurveGeomechResult + CurveTimeStep + AddCaseNameToCurveName + AddPropertyToCurveName + AddWellNameToCurveName + AddTimestepToCurveName + AddDateToCurveName + +RimWellLogExtractionCurveNameConfig - class RimWellLogExtractionCurveNameConfig + IsUsingAutoName + CustomCurveName + AutoCurveName + AddCaseName + AddProperty + AddWellName + AddTimeStep + AddDate + +RimWellLogFileCurveNameConfig - class RimWellLogFileCurveNameConfig + IsUsingAutoName + CustomCurveName + AutoCurveName + +RimWellLogPlotNameConfig - class RimWellLogPlotNameConfig + IsUsingAutoName + CustomCurveName + AutoCurveName + AddCaseName + AddWellName + AddTimeStep + AddAirGap + AddWaterDepth + +RimWellLogRftCurveNameConfig - class RimWellLogRftCurveNameConfig + IsUsingAutoName + CustomCurveName + AutoCurveName + +RimWellPathEntry - class RimWellPathEntry + Name + Selected + WellPathType + surveyType + requestUrl + wellPathFilePath + +RimWellPathImport - class RimWellPathImport + WellTypeSurvey + WellTypePlans + UtmMode + UtmNorth + UtmSouth + UtmEast + UtmWest + Regions + +RiuCreateMultipleFractionsUi - class RiuCreateMultipleFractionsUi + SourceCase + MinDistanceFromWellTd + MaxFracturesPerWell + Options + FractureCreationSummary + +RiuMultipleFractionsOptions - class RicCreateMultipleFracturesOptionItemUi + TopKLayer + BaseKLayer + Template + MinSpacing + +ScaleLegend - class RimScaleLegendConfig + ShowLegend + NumberOfLevels + Precision + ColorRangeMode + RangeType + UserDefinedMax + UserDefinedMin + ResultVariableUsage + +ScriptLocation - class RimScriptCollection + ScriptDirectory + CalcScripts + SubDirectories + SearchSubFolders + +SimWellFracture - class RimSimWellFracture + Name + IsChecked + FractureDef + EditTemplate + CreateEllipseTemplate + CreateStimPlanTemplate + AnchorPosition + ui_positionAtWellpath + Azimuth + PerforationLength + PerforationEfficiency + WellDiameter + Dip + Tilt + FractureUnit + TimeIndexToPlot + WellPathAzimuth + WellFractureAzimuthDiff + WellFractureAzimithAngleWarning + MeasuredDepth + Cell_IJK + Branch + +SimWellFractureCollection - class RimSimWellFractureCollection + Fractures + +SummaryAddress - class RimSummaryAddress + SummaryVarType + SummaryQuantityName + SummaryRegion + SummaryRegion2 + SummaryWellGroup + SummaryWell + SummaryWellSegment + SummaryLgr + SummaryCellI + SummaryCellJ + SummaryCellK + SummaryAquifer + IsErrorResult + +SummaryCaseCollection - class RimSummaryCaseMainCollection + SummaryCases + SummaryCaseCollections + +SummaryCaseSubCollection - class RimSummaryCaseCollection + SummaryCases + SummaryCollectionName + NameCount + IsEnsemble + +SummaryCrossPlot - class RimSummaryCrossPlot + WindowController + ShowWindow + WindowGeometry + PlotDescription + ShowPlotTitle + ShowLegend + LegendFontSize + IsUsingAutoName + SummaryCurveFilters + SummaryCurveCollection + EnsembleCurveSetCollection + SummaryCurves + GridTimeHistoryCurves + AsciiDataCurves + LeftYAxisProperties + RightYAxisProperties + BottomAxisProperties + TimeAxisProperties + AutoZoom + +SummaryCrossPlotCollection - class RimSummaryCrossPlotCollection + SummaryCrossPlots + +SummaryCurve - class RimSummaryCurve + Show + CurveName + CurveDescription + LegendDescription + AutoName + Color + Thickness + CurveInterpolation + LineStyle + PointSymbol + SymbolEdgeColor + SymbolSkipPxDist + ShowLegend + SymbolSize + ShowErrorBars + SummaryCase + SelectedVariableDisplayVar + VarListFilter + FilterResultSelection + SummaryAddress + SelectAddress + SummaryCaseX + SelectedVariableDisplayVarX + VarListFilterX + FilterResultSelectionX + SummaryAddressX + SelectAddressX + PlotAxis + SummaryCurveNameConfig + isTopZWithinCategory + +SummaryCurveAutoName - class RimSummaryCurveAutoName + VectorName + Unit + RegionNumber + WellGroupName + WellName + WellSegmentNumber + LgrName + Completion + Aquifer + CaseName + +SummaryCurveFilter - class RimSummaryCurveFilter_OBSOLETE + SummaryCases + VarListFilter + FilterResultSelection + FilteredCurves + ApplySelection + AutoApplyFilterChanges + IsActive + UseAutoAppearanceAssignment + CaseAppearanceType + VariableAppearanceType + WellAppearanceType + GroupAppearanceType + RegionAppearanceType + PlotAxis + ShowLegend + SummaryCurveNameConfig + +SummaryFilterSettings - class RimSummaryFilter + SummaryFilterType + SummaryCompleteVarStringFilter + SummaryVarQuantityFilter + SummaryRegionNumberFilter + SummaryRegionNumber2Filter + SummaryWellGroupNameFilter + SummaryWellNameFilter + SummaryWellSegmentNumberFilter + SummaryLgrNameFilter + SummaryCellIJKFilter + +SummaryObservedDataFile - class RimSummaryObservedDataFile + ShortName + AutoShortyName + SummaryHeaderFilename + ImportedSummaryData + UseCustomIdentifier + SummaryType + IdentifierName + +SummaryPageDownloadEntity - class SummaryPageDownloadEntity + Name + RequestUrl + ResponseFilename + +SummaryPlot - class RimSummaryPlot + WindowController + ShowWindow + WindowGeometry + PlotDescription + ShowPlotTitle + ShowLegend + LegendFontSize + IsUsingAutoName + SummaryCurveFilters + SummaryCurveCollection + EnsembleCurveSetCollection + SummaryCurves + GridTimeHistoryCurves + AsciiDataCurves + LeftYAxisProperties + RightYAxisProperties + BottomAxisProperties + TimeAxisProperties + AutoZoom + +SummaryPlotCollection - class RimSummaryPlotCollection + SummaryPlots + +SummaryTimeAxisProperties - class RimSummaryTimeAxisProperties + Active + ShowTitle + Title + AutoZoom + TimeMode + TimeUnit + VisibleRangeMax + VisibleRangeMin + VisibleTimeModeRangeMax + VisibleTimeModeRangeMin + TitlePosition + FontSize + ValuesFontSize + +SummaryYAxisProperties - class RimPlotAxisProperties + Active + Name + AutoTitle + DisplayLongName + DisplayShortName + DisplayUnitText + CustomTitle + VisibleRangeMax + VisibleRangeMin + NumberFormat + Decimals + ScaleFactor + AutoZoom + LogarithmicScale + AxisInverted + TitlePosition + FontSize + ValuesFontSize + Annotations + +TC2 - class TC2 + ta + da + ia + ba + +TestCommand1 - class TestCommand1 + TextArgument + DoubleArgument + IntArgument + BoolArgument + +TofAccumulatedPhaseFractionsPlot - class RimTofAccumulatedPhaseFractionsPlot + WindowController + ShowWindow + WindowGeometry + PlotDescription + ShowPlotTitle + MaxTof + +TotalWellAllocationPlot - class RimTotalWellAllocationPlot + WindowController + ShowWindow + WindowGeometry + PlotDescription + ShowPlotTitle + +UserDefinedPolylinesAnnotation - class RimUserDefinedPolylinesAnnotation + IsActive + ClosePolyline + ShowLines + ShowSpheres + Appearance + Name + EnablePicking + Targets + +ValveTemplate - class RimValveTemplate + Name + UnitSystem + CompletionType + UserLabel + OrificeDiameter + FlowCoefficient + AICDParameters + +ValveTemplateCollection - class RimValveTemplateCollection + ValveDefinitions + ValveUnits + +View3dOverlayInfoConfig - class Rim3dOverlayInfoConfig + Active + ShowAnimProgress + ShowInfoText + ShowResultInfo + ShowHistogram + ShowVolumeWeightedMean + ShowVersionInfo + StatisticsTimeRange + StatisticsCellRange + +ViewController - class RimViewController + Active + Name + ManagedView + SyncCamera + ShowCursor + SyncTimeStep + SyncCellResult + SyncLegendDefinitions + SyncVisibleCells + SyncRangeFilters + SyncPropertyFilters + +ViewLinker - class RimViewLinker + Name + MainView + ManagedViews + +Well - class RimSimWellInView + WellName + ShowWell + ShowWellLabel + ShowWellHead + ShowWellPipe + ShowWellSpheres + WellHeadScaleFactor + WellPipeRadiusScale + WellPipeColor + 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 + +WellFlowRateCurve - class RimWellFlowRateCurve + Show + CurveName + CurveDescription + LegendDescription + AutoName + Color + Thickness + CurveInterpolation + LineStyle + PointSymbol + SymbolEdgeColor + SymbolSkipPxDist + ShowLegend + SymbolSize + ShowErrorBars + +WellLogFile - class RimWellLogFile + WellName + Date + FileName + Name + WellLogFileChannels + WellFlowCondition + InvalidDateMessage + +WellLogFileChannel - class RimWellLogFileChannel + Name + +WellLogFileCurve - class RimWellLogFileCurve + Show + CurveName + CurveDescription + LegendDescription + AutoName + Color + Thickness + CurveInterpolation + LineStyle + PointSymbol + SymbolEdgeColor + SymbolSkipPxDist + ShowLegend + SymbolSize + ShowErrorBars + CurveWellPath + CurveWellLogChannel + WellLogFile + +WellLogPlot - class RimWellLogPlot + WindowController + ShowWindow + WindowGeometry + PlotDescription + CommonDataSource + DepthType + DepthUnit + MinimumDepth + MaximumDepth + ShowDepthGridLines + AutoScaleDepthEnabled + ShowTitleInPlot + ShowTrackLegends + TrackLegendsHorizontal + Tracks + NameConfig + +WellLogPlotCollection - class RimWellLogPlotCollection + WellLogPlots + +WellLogPlotTrack - class RimWellLogTrack + TrackDescription + Show + Curves + VisibleXRangeMin + VisibleXRangeMax + AutoScaleX + LogarithmicScaleX + ShowXGridLines + ExplicitTickIntervals + MajorTickIntervals + MinorTickIntervals + ShowFormations + ShowFormationLabels + FormationSource + FormationTrajectoryType + FormationWellPath + FormationWellPathForSourceWellPath + FormationSimulationWellName + FormationBranchIndex + FormationBranchDetection + FormationCase + FormationLevel + ShowFormationFluids + ShowWellPathAttributes + WellPathAttributesInLegend + ShowWellPathCompletions + WellPathCompletionsInLegend + ShowWellPathAttrBothSides + ShowWellPathAttrLabels + AttributesWellPathSource + AttributesCollection + Width + +WellLogRftCurve - class RimWellLogRftCurve + Show + CurveName + CurveDescription + LegendDescription + AutoName + Color + Thickness + CurveInterpolation + LineStyle + PointSymbol + SymbolEdgeColor + SymbolSkipPxDist + ShowLegend + SymbolSize + ShowErrorBars + CurveEclipseResultCase + TimeStep + WellName + BranchIndex + BranchDetection + WellLogChannelName + +WellPath - class RimFileWellPath + WellPathName + DatumElevation + UnitSystem + SimWellName + SimBranchIndex + ShowWellPathLabel + ShowWellPath + WellPathRadiusScale + WellPathColor + Completions + WellLogFiles + CollectionOf3dWellLogCurves + WellPathFormationKeyInFile + WellPathFormationFilePath + WellLogFile + WellPathAttributes + WellPathId + SourceSystem + UTMZone + WellPathUpdateDate + WellPathUpdateUser + WellPathSurveyType + WellPathFilepath + WellPathNumberInFile + +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 + WellPathName + DatumElevation + UnitSystem + SimWellName + SimBranchIndex + ShowWellPathLabel + ShowWellPath + WellPathRadiusScale + WellPathColor + Completions + WellLogFiles + CollectionOf3dWellLogCurves + WellPathFormationKeyInFile + WellPathFormationFilePath + WellLogFile + WellPathAttributes + +WellPathCompletion - class RimFishboneWellPath + Name + IsChecked + Coordinates + MeasuredDepth + DisplayCoordinates + +WellPathCompletionCollection - class RimFishboneWellPathCollection + Name + IsChecked + WellPaths + PipeProperties + +WellPathCompletions - class RimWellPathCompletions + Perforations + Fishbones + Fractures + WellNameForExport + WellGroupNameForExport + ReferenceDepthForExport + WellTypeForExport + DrainageRadiusForPI + GasInflowEq + AutoWellShutIn + AllowWellCrossFlow + WellBoreFluidPVTTable + HydrostaticDensity + FluidInPlaceRegion + +WellPathFracture - class RimWellPathFracture + Name + IsChecked + FractureDef + EditTemplate + CreateEllipseTemplate + CreateStimPlanTemplate + AnchorPosition + ui_positionAtWellpath + Azimuth + PerforationLength + PerforationEfficiency + WellDiameter + Dip + Tilt + FractureUnit + TimeIndexToPlot + WellPathAzimuth + WellFractureAzimuthDiff + WellFractureAzimithAngleWarning + MeasuredDepth + +WellPathFractureCollection - class RimWellPathFractureCollection + Name + IsChecked + Fractures + MswParameters + RefMDType + RefMD + +WellPathGeometryDef - class RimWellPathGeometryDef + ReferencePosUtmXyd + MdrkbAtFirstTarget + WellPathTargets + m_pickPointsEnabled + ReferencePos + WellStartType + ParentWell + KickoffDepthOrMD + +WellPathTarget - class RimWellPathTarget + IsEnabled + TargetPoint + Dogleg1 + Dogleg2 + TargetType + HasTangentConstraint + Azimuth + Inclination + +WellPathValve - class RimWellPathValve + Name + IsChecked + ValveTemplate + StartMeasuredDepth + ValveLocations + EditTemplate + CreateTemplate + +WellPaths - class RimWellPathCollection + Active + ShowWellPathLabel + WellPathLabelColor + GlobalWellPathVisibility + WellPathRadiusScale + WellPathVertexCount + WellPathClip + WellPathClipZDistance + WellPaths + +WellPltPlot - class RimWellPltPlot + WindowController + ShowWindow + WindowGeometry + PlotDescription + ShowPlotTitle + WellLog + WellName + SourcesInternal + Sources + TimeSteps + UseStandardConditionCurves + UseReservoirConditionCurves + Phases + +WellPltPlotCollection - class RimPltPlotCollection + PltPlots + +WellRftPlot - class RimWellRftPlot + WindowController + ShowWindow + WindowGeometry + PlotDescription + ShowPlotTitle + WellLog + WellName + BranchIndex + BranchDetection + Sources + TimeSteps + +WellRftPlotCollection - class RimRftPlotCollection + RftPlots + +Wells - class RimSimWellInViewCollection + Active + ShowWellsIntersectingVisibleCells + ShowWellHeadTristate + ShowWellLabelTristate + ShowWellPipe + ShowWellSpheres + WellHeadScale + WellPipeRadiusScale + CellCenterSphereScale + WellLabelColor + ShowConnectionStatusColors + WellColorForApply + WellPipeColors + WellPipeVertexCount + WellPipeCoordType + ShowWellCellsTristate + DefaultWellFenceDirection + WellCellTransparency + IsAutoDetectingBranches + WellHeadPosition + Wells + ShowWellCellFenceTristate + GlobalWellPipeVisibility + GlobalWellCellVisibility + ShowWellHead + ShowWellLabel + ShowWellFences + ShowWellCommunicationLines + +closeProject - class RicfCloseProject + +computeCaseGroupStatistics - class RicfComputeCaseGroupStatistics + caseIds + +createLgrForCompletions - class RicfCreateLgrForCompletions + caseId + timeStep + wellPathNames + refinementI + refinementJ + refinementK + splitType + +createMultipleFractures - class RicfCreateMultipleFractures + caseId + wellPathNames + minDistFromWellTd + maxFracturesPerWell + templateId + topLayer + baseLayer + spacing + action + +createSaturationPressurePlots - class RicfCreateSaturationPressurePlots + caseIds + +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 + viewNames + undefinedValue + +exportSimWellFractureCompletions - class RicfExportSimWellFractureCompletions + caseId + viewName + timeStep + simulationWellNames + fileSplit + compdatExport + +exportSnapshots - class RicfExportSnapshots + type + prefix + +exportVisibleCells - class RicfExportVisibleCells + caseId + viewName + exportKeyword + visibleActiveCellsValue + hiddenActiveCellsValue + inactiveCellsValue + +exportWellPathCompletions - class RicfExportWellPathCompletions + caseId + timeStep + wellPathNames + fileSplit + compdatExport + combinationMode + useNtgHorizontally + includePerforations + includeFishbones + includeFractures + excludeMainBoreForFishbones + performTransScaling + transScalingTimeStep + transScalingWBHPFromSummary + transScalingWBHP + +exportWellPaths - class RicfExportWellPaths + wellPathNames + mdStepSize + +loadCase - class RicfLoadCase + path + +openProject - class RicfOpenProject + path + +replaceCase - class RicfSingleCaseReplace + caseId + newGridFile + +replaceCaseImpl_no_support_for_command_file_text_parsing - class RicfMultiCaseReplace + +replaceSourceCases - class RicfReplaceSourceCases + caseGroupId + gridListFile + +runOctaveScript - class RicfRunOctaveScript + path + caseIds + +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 + +setStartDir - class RicfSetStartDir + path + +setTimeStep - class RicfSetTimeStep + caseId + timeStep + diff --git a/ApplicationCode/Adm/projectfilekeywords/2019.04/ri-objectKeywords.txt b/ApplicationCode/Adm/projectfilekeywords/2019.04/ri-objectKeywords.txt new file mode 100644 index 0000000000..726fdf769d --- /dev/null +++ b/ApplicationCode/Adm/projectfilekeywords/2019.04/ri-objectKeywords.txt @@ -0,0 +1,280 @@ +// ResInsight version string : 2019.04.0-dev.01 +// Report generated : Tue 30. Apr 10:17:11 2019 +// +// + +Annotations +AsciiDataCurve +CalcScript +CalculatedSummaryCase +CellEdgeResultSlot +CellFilter +CellPropertyFilter +CellPropertyFilters +CellRangeFilter +CellRangeFilterCollection +ChangeDataSourceFeatureUi +CmdAddItemExecData +CmdDeleteItemExecData +CmdFieldChangeExecData +CompletionTemplateCollection +CrossSection +CrossSectionCollection +Eclipse2dViewCollection +EclipseCase +EclipseGeometrySelectionItem +Fault +Faults +FileSummaryCase +FishbonesCollection +FishbonesMultipleSubs +FishbonesPipeProperties +FlowCharacteristicsPlot +FlowDiagSolution +FlowPlotCollection +FormationNames +FormationNamesCollectionObject +FractureContainment +FractureDefinitionCollection +GeoMech2dViewCollection +GeoMechGeometrySelectionItem +GeoMechPropertyFilter +GeoMechPropertyFilters +GeoMechResultDefinition +GeoMechResultSlot +GeoMechView +GridCollection +GridCrossPlotCurve +GridCrossPlotCurveSet +GridInfo +GridInfoCollection +GridSummaryCase +GridTimeHistoryCurve +Intersection2dView +Intersection2dViewCollection +IntersectionBox +Legend +MainPlotCollection +MdiWindowController +MockModelSettings +ModeledWellPath +MultiSnapshotDefinition +NoCommonAreaNNC +ObservedDataCollection +PdmDocument +PdmObjectCollection +PdmObjectGroup +Perforation +PerforationCollection +PolylineTarget +PolylinesFromFileAnnotation +PropertyFilter +ResInsightAnalysisModels +ResInsightGeoMechCase +ResInsightGeoMechModels +ResInsightOilField +ResInsightProject +ReservoirCellResultStorage +ReservoirView +ResultDefinition +ResultSlot +ResultStorageEntryInfo +RftAddress +RiaMemoryCleanup +RiaPreferences +RiaRegressionTest +RicCaseAndFileExportSettingsUi +RicCellRangeUi +RicDeleteItemExecData +RicExportCarfinUi +RicExportCompletionDataSettingsUi +RicExportEclipseInputGridUi +RicExportLgrUi +RicExportToLasFileObj +RicExportToLasFileResampleUi +RicExportWellPathsUi +RicHoloLensCreateSessionUi +RicHoloLensExportToFolderUi +RicHoloLensServerSettings +RicLinkVisibleViewsFeatureUi +RicPasteAsciiDataToSummaryPlotFeatureUi +RicSaturationPressureUi +RicSaveEclipseInputVisibleCellsUi +RicSelectSummaryPlotUI +RicSelectViewUI +RicSummaryAddressSelection +RicSummaryCurveCalculator +RicSummaryCurveCreator +RicWellPathsUnitSystemSettingsUi +RifReaderSettings +Rim3dWellLogCurveCollection +Rim3dWellLogExtractionCurve +Rim3dWellLogFileCurve +Rim3dWellLogRftCurve +RimAnnotationCollection +RimAnnotationCollectionBase +RimAnnotationGroupCollection +RimAnnotationLineAppearance +RimAnnotationTextAppearance +RimBinaryExportSettings +RimCaseCollection +RimCommandExecuteScript +RimCommandIssueFieldChanged +RimCommandObject +RimContourMapView +RimCsvUserData +RimCurveNameConfig +RimDerivedEnsembleCaseCollection +RimDialogData +RimEclipseContourMapProjection +RimEllipseFractureTemplate +RimEnsembleCurveFilter +RimEnsembleCurveFilterCollection +RimEnsembleCurveSet +RimEnsembleCurveSetCollection +RimEnsembleStatistics +RimExportInputSettings +RimFaultResultSlot +RimFractureExportSettings +RimGeoMechContourMapProjection +RimGeoMechContourMapView +RimGridCrossPlot +RimGridCrossPlotCollection +RimGridCrossPlotCurveSetNameConfig +RimGridCrossPlotNameConfig +RimIdenticalGridCaseGroup +RimInputProperty +RimInputPropertyCollection +RimInputReservoir +RimMeasurement +RimMswCompletionParameters +RimMultipleValveLocations +RimNoCommonAreaNncCollection +RimNonDarcyPerforationParameters +RimObservedEclipseUserData +RimOilFieldEntry +RimOilRegionEntry +RimPlotAxisAnnotation +RimPlotCellFilterCollection +RimPlotCellPropertyFilter +RimPolylineAppearance +RimPolylinesAnnotationInView +RimPolylinesFromFileAnnotationInView +RimReachCircleAnnotation +RimReachCircleAnnotationInView +RimSaturationPressurePlot +RimSaturationPressurePlotCollection +RimStatisticalCalculation +RimStatisticalCollection +RimStimPlanColors +RimStimPlanFractureTemplate +RimStimPlanLegendConfig +RimSummaryCalculation +RimSummaryCalculationCollection +RimSummaryCalculationVariable +RimSummaryCurveCollection +RimSummaryCurveCollectionModifier +RimTensorResults +RimTernaryLegendConfig +RimTextAnnotation +RimTextAnnotationInView +RimTimeStepFilter +RimUserDefinedPolylinesAnnotationInView +RimViewLinkerCollection +RimViewNameConfig +RimVirtualPerforationResults +RimWellLogExtractionCurve +RimWellLogExtractionCurveNameConfig +RimWellLogFileCurveNameConfig +RimWellLogPlotNameConfig +RimWellLogRftCurveNameConfig +RimWellPathEntry +RimWellPathImport +RiuCreateMultipleFractionsUi +RiuMultipleFractionsOptions +ScaleLegend +ScriptLocation +SimWellFracture +SimWellFractureCollection +SummaryAddress +SummaryCaseCollection +SummaryCaseSubCollection +SummaryCrossPlot +SummaryCrossPlotCollection +SummaryCurve +SummaryCurveAutoName +SummaryCurveFilter +SummaryFilterSettings +SummaryObservedDataFile +SummaryPageDownloadEntity +SummaryPlot +SummaryPlotCollection +SummaryTimeAxisProperties +SummaryYAxisProperties +TC2 +TestCommand1 +TofAccumulatedPhaseFractionsPlot +TotalWellAllocationPlot +UserDefinedPolylinesAnnotation +ValveTemplate +ValveTemplateCollection +View3dOverlayInfoConfig +ViewController +ViewLinker +Well +WellAllocationPlot +WellAllocationPlotLegend +WellFlowRateCurve +WellLogFile +WellLogFileChannel +WellLogFileCurve +WellLogPlot +WellLogPlotCollection +WellLogPlotTrack +WellLogRftCurve +WellPath +WellPathAicdParameters +WellPathAttribute +WellPathAttributes +WellPathBase +WellPathCompletion +WellPathCompletionCollection +WellPathCompletions +WellPathFracture +WellPathFractureCollection +WellPathGeometryDef +WellPathTarget +WellPathValve +WellPaths +WellPltPlot +WellPltPlotCollection +WellRftPlot +WellRftPlotCollection +Wells +closeProject +computeCaseGroupStatistics +createLgrForCompletions +createMultipleFractures +createSaturationPressurePlots +exportLgrForCompletions +exportMsw +exportMultiCaseSnapshots +exportProperty +exportPropertyInViews +exportSimWellFractureCompletions +exportSnapshots +exportVisibleCells +exportWellPathCompletions +exportWellPaths +loadCase +openProject +replaceCase +replaceCaseImpl_no_support_for_command_file_text_parsing +replaceSourceCases +runOctaveScript +scaleFractureTemplate +setExportFolder +setFractureContainment +setMainWindowSize +setStartDir +setTimeStep From 1f5d4030b9681c4998a770229a013cfb9b20c5a3 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 30 Apr 2019 12:36:53 +0200 Subject: [PATCH 003/396] #4384 Preferences : Missing default font sizes --- ApplicationCode/Application/RiaPreferences.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ApplicationCode/Application/RiaPreferences.cpp b/ApplicationCode/Application/RiaPreferences.cpp index c382da6224..540fa0db56 100644 --- a/ApplicationCode/Application/RiaPreferences.cpp +++ b/ApplicationCode/Application/RiaPreferences.cpp @@ -76,11 +76,11 @@ RiaPreferences::RiaPreferences(void) CAF_PDM_InitField(&defaultScaleFactorZ, "defaultScaleFactorZ", 5, "Default Z Scale Factor", "", "", ""); - CAF_PDM_InitFieldNoDefault(&defaultSceneFontSize, "fontSizeInScene", "Viewer Font Size", "", "", ""); - CAF_PDM_InitFieldNoDefault(&defaultAnnotationFontSize, "defaultAnnotationFontSize", "Annotation Font Size", "", "", ""); - CAF_PDM_InitFieldNoDefault(&defaultWellLabelFontSize, "wellLabelFontSize", "Well Label Font Size", "", "", ""); - CAF_PDM_InitFieldNoDefault(&defaultPlotFontSize, "defaultPlotFontSize", "Plot Font Size", "", "", ""); - defaultPlotFontSize = RiaFontCache::FONT_SIZE_8; + caf::AppEnum fontSize = RiaFontCache::FONT_SIZE_8; + CAF_PDM_InitField(&defaultSceneFontSize, "fontSizeInScene", fontSize, "Viewer Font Size", "", "", ""); + CAF_PDM_InitField(&defaultAnnotationFontSize, "defaultAnnotationFontSize", fontSize, "Annotation Font Size", "", "", ""); + CAF_PDM_InitField(&defaultWellLabelFontSize, "wellLabelFontSize", fontSize, "Well Label Font Size", "", "", ""); + CAF_PDM_InitField(&defaultPlotFontSize, "defaultPlotFontSize", fontSize, "Plot Font Size", "", "", ""); CAF_PDM_InitField(&showLasCurveWithoutTvdWarning, "showLasCurveWithoutTvdWarning", true, "Show LAS Curve Without TVD Warning", "", "", ""); showLasCurveWithoutTvdWarning.uiCapability()->setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN); From d0b5357ed4cff13a116de2fc61efb736409e16c6 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 3 May 2019 07:49:53 +0200 Subject: [PATCH 004/396] #4379 Documentation : Update command line parser for import of summary files --- ApplicationCode/Application/Tools/RiaArgumentParser.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ApplicationCode/Application/Tools/RiaArgumentParser.cpp b/ApplicationCode/Application/Tools/RiaArgumentParser.cpp index a0c054a30a..48c4adf2eb 100644 --- a/ApplicationCode/Application/Tools/RiaArgumentParser.cpp +++ b/ApplicationCode/Application/Tools/RiaArgumentParser.cpp @@ -59,8 +59,8 @@ bool RiaArgumentParser::parseArguments() progOpt.registerOption("last", "", "Open last used project."); progOpt.registerOption("project", "", "Open project file .", cvf::ProgramOptions::SINGLE_VALUE); progOpt.registerOption("case", - "", - "Import Eclipse case (do not include the .GRID/.EGRID extension.)", + "", + "If case or grid filename, import simulation grid data. If summary file name, import summary data", cvf::ProgramOptions::MULTI_VALUE); progOpt.registerOption("startdir", "", "Set startup directory.", cvf::ProgramOptions::SINGLE_VALUE); progOpt.registerOption("savesnapshots", From 9ae6b79271f4fd444fdb6595088d12156eac9a27 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 3 May 2019 09:15:18 +0200 Subject: [PATCH 005/396] #4387 System : Move clang-tidy and clang-format into ApplicationCode Prepare for format-on-save --- .../.clang-format | 0 .clang-tidy => ApplicationCode/.clang-tidy | 0 Fwk/AppFwk/cafTests/.clang-format | 90 +++++++++++++++++++ 3 files changed, 90 insertions(+) rename .clang-format => ApplicationCode/.clang-format (100%) rename .clang-tidy => ApplicationCode/.clang-tidy (100%) create mode 100644 Fwk/AppFwk/cafTests/.clang-format diff --git a/.clang-format b/ApplicationCode/.clang-format similarity index 100% rename from .clang-format rename to ApplicationCode/.clang-format diff --git a/.clang-tidy b/ApplicationCode/.clang-tidy similarity index 100% rename from .clang-tidy rename to ApplicationCode/.clang-tidy diff --git a/Fwk/AppFwk/cafTests/.clang-format b/Fwk/AppFwk/cafTests/.clang-format new file mode 100644 index 0000000000..04867544d7 --- /dev/null +++ b/Fwk/AppFwk/cafTests/.clang-format @@ -0,0 +1,90 @@ +--- +Language: Cpp +# BasedOnStyle: LLVM +AccessModifierOffset: -4 +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: true +AlignConsecutiveDeclarations: true +AlignEscapedNewlinesLeft: true +AlignOperands: true +AlignTrailingComments: false +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortIfStatementsOnASingleLine: true +AllowShortFunctionsOnASingleLine: Empty +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: true +BinPackArguments: false +BinPackParameters: false +BraceWrapping: + AfterClass: true + AfterControlStatement: true + AfterEnum: true + AfterFunction: true + AfterNamespace: true + AfterObjCDeclaration: false + AfterStruct: true + AfterUnion: true + BeforeCatch: true + BeforeElse: true + IndentBraces: false +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Custom +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: true +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +ColumnLimit: 130 +CommentPragmas: '^ IWYU pragma:' +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DerivePointerAlignment: false +DisableFormat: false +ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] +IncludeCategories: + - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + Priority: 2 + - Regex: '^(<|"(gtest|isl|json)/)' + Priority: 3 + - Regex: '.*' + Priority: 1 +IncludeIsMainRegex: '$' +IndentCaseLabels: true +IndentWidth: 4 +IndentWrappedFunctionNames: true +JavaScriptQuotes: Leave +KeepEmptyLinesAtTheStartOfBlocks: false +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: Inner +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 60 +PointerAlignment: Left +ReflowComments: true +SortIncludes: true +SpaceAfterCStyleCast: false +SpaceAfterTemplateKeyword: false +SpaceBeforeAssignmentOperators: true +SpaceBeforeParens: ControlStatements +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInContainerLiterals: false +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Cpp11 +TabWidth: 4 +UseTab: Never +... From 66e09e4688bb82ed4fa46c0399fb7697386af8be Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 3 May 2019 11:08:48 +0200 Subject: [PATCH 006/396] #4387 System : Update references to clang files --- ApplicationCode/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ApplicationCode/CMakeLists.txt b/ApplicationCode/CMakeLists.txt index a213bb7d5d..6285764a9c 100644 --- a/ApplicationCode/CMakeLists.txt +++ b/ApplicationCode/CMakeLists.txt @@ -319,8 +319,8 @@ set( EXE_FILES ${HEADER_FILES} ${REFERENCED_CMAKE_FILES} ../ResInsightVersion.cmake - ../.clang-format - ../.clang-tidy + .clang-format + .clang-tidy ) add_executable( ResInsight ${EXE_FILES} ) From 91022a7535cb4948e65a3051959578b6aff838d2 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 10 Apr 2019 10:57:18 +0200 Subject: [PATCH 007/396] Revert "#4308 System : Add virtual function childFieldChangedByUi" This reverts commit fbf9308e2bcead715b0db7a9db7687b89e03b3dd. --- .../cafPdmUiCore/cafPdmUiFieldHandle.cpp | 24 ++++--------------- .../cafPdmUiCore/cafPdmUiObjectHandle.h | 3 --- 2 files changed, 4 insertions(+), 23 deletions(-) diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiFieldHandle.cpp b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiFieldHandle.cpp index ba6f09c866..0cb0e16e0b 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiFieldHandle.cpp +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiFieldHandle.cpp @@ -58,27 +58,11 @@ void PdmUiFieldHandle::notifyFieldChanged(const QVariant& oldFieldValue, const Q PdmFieldHandle* fieldHandle = this->fieldHandle(); CAF_ASSERT(fieldHandle && fieldHandle->ownerObject()); - PdmObjectHandle* ownerObjectHandle = fieldHandle->ownerObject(); - + PdmUiObjectHandle* uiObjHandle = uiObj(fieldHandle->ownerObject()); + if (uiObjHandle) { - PdmUiObjectHandle* uiObjHandle = uiObj(ownerObjectHandle); - if (uiObjHandle) - { - uiObjHandle->fieldChangedByUi(fieldHandle, oldFieldValue, newFieldValue); - uiObjHandle->updateConnectedEditors(); - - } - } - - if (ownerObjectHandle->parentField() && ownerObjectHandle->parentField()->ownerObject()) - { - PdmUiObjectHandle* uiObjHandle = uiObj(ownerObjectHandle->parentField()->ownerObject()); - if (uiObjHandle) - { - uiObjHandle->childFieldChangedByUi(ownerObjectHandle->parentField()); - - // If updateConnectedEditors() is required, this has to be called in childFieldChangedByUi() - } + uiObjHandle->fieldChangedByUi(fieldHandle, oldFieldValue, newFieldValue); + uiObjHandle->updateConnectedEditors(); } // Update field editors diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiObjectHandle.h b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiObjectHandle.h index c7cc5165fd..7818894f66 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiObjectHandle.h +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiObjectHandle.h @@ -58,9 +58,6 @@ public: // Virtual /// Method to reimplement to catch when the field has changed due to setUiValue() virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) {} - /// Method to reimplement to catch when a field in a contained object has changed due to setUiValue() - virtual void childFieldChangedByUi(const caf::PdmFieldHandle* changedChildField) {} - /// Method to re-implement to supply option values for a specific field virtual QList calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly) { return QList(); } From 4c46573fc9de09f488984d06d5c31196f8142073 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 10 Apr 2019 10:57:18 +0200 Subject: [PATCH 008/396] Reintroduce "#4308 System : Add virtual function childFieldChangedByUi" This reverts commit 91022a7535cb4948e65a3051959578b6aff838d2. --- .../cafPdmUiCore/cafPdmUiFieldHandle.cpp | 24 +++++++++++++++---- .../cafPdmUiCore/cafPdmUiObjectHandle.h | 3 +++ 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiFieldHandle.cpp b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiFieldHandle.cpp index 0cb0e16e0b..ba6f09c866 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiFieldHandle.cpp +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiFieldHandle.cpp @@ -58,11 +58,27 @@ void PdmUiFieldHandle::notifyFieldChanged(const QVariant& oldFieldValue, const Q PdmFieldHandle* fieldHandle = this->fieldHandle(); CAF_ASSERT(fieldHandle && fieldHandle->ownerObject()); - PdmUiObjectHandle* uiObjHandle = uiObj(fieldHandle->ownerObject()); - if (uiObjHandle) + PdmObjectHandle* ownerObjectHandle = fieldHandle->ownerObject(); + { - uiObjHandle->fieldChangedByUi(fieldHandle, oldFieldValue, newFieldValue); - uiObjHandle->updateConnectedEditors(); + PdmUiObjectHandle* uiObjHandle = uiObj(ownerObjectHandle); + if (uiObjHandle) + { + uiObjHandle->fieldChangedByUi(fieldHandle, oldFieldValue, newFieldValue); + uiObjHandle->updateConnectedEditors(); + + } + } + + if (ownerObjectHandle->parentField() && ownerObjectHandle->parentField()->ownerObject()) + { + PdmUiObjectHandle* uiObjHandle = uiObj(ownerObjectHandle->parentField()->ownerObject()); + if (uiObjHandle) + { + uiObjHandle->childFieldChangedByUi(ownerObjectHandle->parentField()); + + // If updateConnectedEditors() is required, this has to be called in childFieldChangedByUi() + } } // Update field editors diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiObjectHandle.h b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiObjectHandle.h index 7818894f66..c7cc5165fd 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiObjectHandle.h +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiObjectHandle.h @@ -58,6 +58,9 @@ public: // Virtual /// Method to reimplement to catch when the field has changed due to setUiValue() virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) {} + /// Method to reimplement to catch when a field in a contained object has changed due to setUiValue() + virtual void childFieldChangedByUi(const caf::PdmFieldHandle* changedChildField) {} + /// Method to re-implement to supply option values for a specific field virtual QList calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly) { return QList(); } From 57b33b0d4c950fab5bc3eca556eede9caed2358d Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Mon, 6 May 2019 10:36:05 +0200 Subject: [PATCH 009/396] First implementation of Headless (#4392) * Revert "#4377 Octave : Use RiaLogging for error messages instead of QErrorMessage " This reverts commit f758a8edb2c789a90f6c13bef58904ac91f74e8b. * Revert "#4380 Preferences : Changing scene font size when geo mech view is open causes crash" This reverts commit df62a4139706b8bac38d104e3c5452439834fda2. * Revert "#4379 Documentation : Update command line parser for import of summary files" This reverts commit d0b5357ed4cff13a116de2fc61efb736409e16c6. * Unfinished WIP * Builds but crashes * Refactored code now builds and runs * ResInsight can now run the unittests headless * Can run some command files successfully * Build on Linux * Extra headless hack header * Moved PdmUiItem hack to cpp file * Fix headless crash in RimWellAllocationPlot * Handle error gracefully if ExportSnapshots command is executed from console * Add caf::QIconProvider and remove some hacks * Also made the greying out of disabled icons work for a couple of cases where it didn't. * Linux build fix * #4380 Reimplement fix df62a41397 by @magnesj on top of Headless code changes * #4379 Reintroduce kode from d0b5357ed4 by @magnesj * #4377 Restore f758a8edb2c in new Headless code --- .../Application/CMakeLists_files.cmake | 7 +- .../Application/RiaApplication.cpp | 2210 ++++------------- ApplicationCode/Application/RiaApplication.h | 298 +-- .../Application/RiaConsoleApplication.cpp | 366 +++ .../Application/RiaConsoleApplication.h | 52 + ApplicationCode/Application/RiaFontCache.h | 2 +- .../Application/RiaGuiApplication.cpp | 1708 +++++++++++++ .../Application/RiaGuiApplication.h | 174 ++ ApplicationCode/Application/RiaMain.cpp | 51 +- .../Application/RiaMemoryCleanup.cpp | 4 +- .../Application/RiaPreferences.cpp | 2 +- ApplicationCode/Application/RiaPreferences.h | 3 +- .../Application/Tools/RiaArgumentParser.cpp | 467 +--- .../Application/Tools/RiaArgumentParser.h | 10 +- .../Tools/RiaOptionItemFactory.cpp | 4 +- .../Tools/RiaRegressionTestRunner.cpp | 4 +- .../RicfCreateSaturationPressurePlots.cpp | 4 +- .../RicfExportMultiCaseSnapshots.cpp | 10 +- .../RicfExportSnapshots.cpp | 13 +- .../CommandFileInterface/RicfOpenProject.cpp | 14 +- .../RicCloseProjectFeature.cpp | 7 +- .../RicEditPreferencesFeature.cpp | 5 +- .../RicExitApplicationFeature.cpp | 4 +- .../ApplicationCommands/RicHelpFeatures.cpp | 2 +- .../RicOpenLastUsedFileFeature.cpp | 2 +- .../RicOpenProjectFeature.cpp | 4 +- .../RicSaveProjectAsFeature.cpp | 11 +- .../RicSaveProjectFeature.cpp | 4 +- .../RicShowPlotDataFeature.cpp | 8 +- .../RicShowPlotWindowFeature.cpp | 4 +- .../RicTileWindowsFeature.cpp | 14 +- .../RicSnapshotAllPlotsToFileFeature.cpp | 8 +- .../RicSnapshotAllViewsToFileFeature.cpp | 6 +- .../RicSnapshotViewToClipboardFeature.cpp | 4 +- .../RicSnapshotViewToFileFeature.cpp | 4 +- .../RicPlotProductionRateFeature.cpp | 4 +- .../Commands/FlowCommands/RicSelectViewUI.cpp | 4 +- ...icShowContributingWellsFromPlotFeature.cpp | 6 +- .../RicCreateGridCrossPlotDataSetFeature.cpp | 4 +- .../RicCreateGridCrossPlotFeature.cpp | 4 +- ...icCreateSaturationPressurePlotsFeature.cpp | 6 +- .../RicPasteGridCrossPlotDataSetFeature.cpp | 4 +- .../RicToggleMeasurementModeFeature.cpp | 11 +- .../Commands/RicCloseSummaryCaseFeature.cpp | 4 +- ...RicCloseSummaryCaseInCollectionFeature.cpp | 4 +- .../Commands/RicCreateTemporaryLgrFeature.cpp | 6 +- .../Commands/RicDeleteItemExec.cpp | 12 +- .../RicDeleteTemporaryLgrsFeature.cpp | 4 +- .../Commands/RicImportGeneralDataFeature.cpp | 28 +- .../Commands/RicImportGeneralDataFeature.h | 16 +- .../Commands/RicImportSummaryCasesFeature.cpp | 8 +- .../Commands/RicImportSummaryGroupFeature.cpp | 4 +- .../Commands/RicReloadCaseFeature.cpp | 4 +- .../Commands/RicSummaryCaseRestartDialog.cpp | 4 +- ApplicationCode/Commands/RicWellLogTools.cpp | 8 +- .../RicNewGridTimeHistoryCurveFeature.cpp | 15 +- .../RicNewSummaryCrossPlotCurveFeature.cpp | 6 +- .../RicNewSummaryCurveFeature.cpp | 9 +- .../RicNewSummaryEnsembleCurveSetFeature.cpp | 4 +- .../RicSummaryCurveCreator.cpp | 6 +- .../RicSummaryCurveCreatorDialog.cpp | 4 +- .../RicViewZoomAllFeature.cpp | 6 +- .../RicToggleItemsFeatureImpl.cpp | 4 +- .../RicDeleteWellLogPlotTrackFeature.cpp | 4 +- .../RicNewWellLogPlotFeatureImpl.cpp | 6 +- .../RicNewWellLogPlotTrackFeature.cpp | 4 +- .../RicWellLogPlotTrackFeatureImpl.cpp | 4 +- .../RicCreateWellTargetsPickEventHandler.cpp | 6 +- .../GridBox/RivGridBoxGenerator.cpp | 4 +- .../Intersections/RivIntersectionPartMgr.cpp | 4 +- .../Riv3dWellLogPlanePartMgr.cpp | 4 +- .../ModelVisualization/RivFaultPartMgr.cpp | 8 +- .../RivMeasurementPartMgr.cpp | 6 +- .../RivPolylineAnnotationPartMgr.cpp | 4 +- .../ModelVisualization/RivWellHeadPartMgr.cpp | 4 +- .../ModelVisualization/RivWellPathPartMgr.cpp | 4 +- .../RivWellSpheresPartMgr.cpp | 6 +- .../Annotations/RimAnnotationCollection.cpp | 6 +- .../RimAnnotationCollectionBase.cpp | 2 +- .../RimAnnotationInViewCollection.cpp | 12 +- .../Completions/RimValveTemplate.cpp | 6 +- .../Completions/RimWellPathValve.cpp | 6 +- .../Flow/RimFlowCharacteristicsPlot.cpp | 6 +- .../Flow/RimWellAllocationPlot.cpp | 6 +- .../RimGridCrossPlotDataSet.cpp | 2 +- .../Measurement/RiuMeasurementEventFilter.cpp | 6 +- .../Rim3dOverlayInfoConfig.cpp | 33 +- .../ProjectDataModel/Rim3dOverlayInfoConfig.h | 3 +- .../ProjectDataModel/Rim3dView.cpp | 11 +- ApplicationCode/ProjectDataModel/RimCase.cpp | 2 +- .../ProjectDataModel/RimCellFilter.cpp | 21 +- .../RimEclipsePropertyFilter.cpp | 7 +- .../RimEclipseResultDefinition.cpp | 2 +- .../ProjectDataModel/RimGeoMechCase.cpp | 2 +- .../ProjectDataModel/RimGridCollection.cpp | 10 +- .../ProjectDataModel/RimGridView.cpp | 7 +- .../RimIdenticalGridCaseGroup.cpp | 4 +- .../ProjectDataModel/RimIntersection.cpp | 2 +- .../ProjectDataModel/RimIntersectionBox.cpp | 8 +- .../RimIntersectionCollection.cpp | 2 + .../RimMdiWindowController.cpp | 8 +- .../RimPlotAxisProperties.cpp | 4 +- .../ProjectDataModel/RimPlotCurve.cpp | 4 +- .../ProjectDataModel/RimProject.cpp | 26 +- ApplicationCode/ProjectDataModel/RimProject.h | 3 +- .../RimRegularLegendConfig.cpp | 2 +- .../ProjectDataModel/RimRegularLegendConfig.h | 3 + .../ProjectDataModel/RimStimPlanColors.cpp | 5 + .../RimTernaryLegendConfig.cpp | 2 +- ApplicationCode/ProjectDataModel/RimTools.cpp | 8 +- .../ProjectDataModel/RimViewController.cpp | 6 +- .../ProjectDataModel/RimViewController.h | 2 +- .../ProjectDataModel/RimViewLinker.cpp | 34 +- .../ProjectDataModel/RimViewLinker.h | 11 +- .../ProjectDataModel/RimViewWindow.cpp | 3 + .../RimWellLogCurveCommonDataSource.cpp | 2 +- .../RimWellLogExtractionCurve.cpp | 2 +- .../ProjectDataModel/RimWellLogRftCurve.cpp | 2 +- .../ProjectDataModel/RimWellLogTrack.cpp | 2 +- .../Summary/RimEnsembleCurveSet.cpp | 17 +- .../Summary/RimObservedDataCollection.cpp | 4 +- .../Summary/RimSummaryCaseCollection.cpp | 4 +- .../Summary/RimSummaryCrossPlotCollection.cpp | 2 +- .../Summary/RimSummaryCurve.cpp | 19 +- .../Summary/RimSummaryPlotCollection.cpp | 4 +- .../Summary/RimSummaryPlotSourceStepping.cpp | 6 +- .../SocketInterface/RiaSocketTools.cpp | 4 +- .../UserInterface/CMakeLists_files.cmake | 2 + .../UserInterface/RiuCvfOverlayItemWidget.cpp | 6 +- .../UserInterface/RiuMainWindow.cpp | 12 +- .../RiuMdiMaximizeWindowGuard.cpp | 49 + .../UserInterface/RiuMdiMaximizeWindowGuard.h | 32 + .../UserInterface/RiuMdiSubWindow.cpp | 20 +- .../UserInterface/RiuPlotMainWindow.cpp | 4 +- .../UserInterface/RiuPlotMainWindowTools.cpp | 12 +- .../UserInterface/RiuPlotObjectPicker.cpp | 4 +- .../RiuRecentFileActionProvider.cpp | 4 +- .../UserInterface/RiuTreeViewEventFilter.cpp | 8 +- ApplicationCode/UserInterface/RiuViewer.cpp | 20 +- Fwk/AppFwk/cafCommand/cafCmdFeature.cpp | 7 +- Fwk/AppFwk/cafProjectDataModel/cafPdmObject.h | 7 +- .../cafPdmUiCore/CMakeLists.txt | 2 + .../cafInternalPdmUiFieldCapability.inl | 4 +- .../cafPdmUiCore/cafPdmUiItem.cpp | 146 +- .../cafPdmUiCore/cafPdmUiItem.h | 61 +- .../cafPdmUiCore/cafPdmUiTreeOrdering.cpp | 2 +- .../cafPdmUiCore/cafQIconProvider.cpp | 137 + .../cafPdmUiCore/cafQIconProvider.h | 73 + .../cafUserInterface/cafProgressInfo.cpp | 80 +- .../cafVizExtensions/cafFixedAtlasFont.h | 1 + 150 files changed, 4001 insertions(+), 2804 deletions(-) create mode 100644 ApplicationCode/Application/RiaConsoleApplication.cpp create mode 100644 ApplicationCode/Application/RiaConsoleApplication.h create mode 100644 ApplicationCode/Application/RiaGuiApplication.cpp create mode 100644 ApplicationCode/Application/RiaGuiApplication.h create mode 100644 ApplicationCode/UserInterface/RiuMdiMaximizeWindowGuard.cpp create mode 100644 ApplicationCode/UserInterface/RiuMdiMaximizeWindowGuard.h create mode 100644 Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafQIconProvider.cpp create mode 100644 Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafQIconProvider.h diff --git a/ApplicationCode/Application/CMakeLists_files.cmake b/ApplicationCode/Application/CMakeLists_files.cmake index f9828e8acf..c575b75c48 100644 --- a/ApplicationCode/Application/CMakeLists_files.cmake +++ b/ApplicationCode/Application/CMakeLists_files.cmake @@ -1,6 +1,8 @@ set (SOURCE_GROUP_HEADER_FILES ${CMAKE_CURRENT_LIST_DIR}/RiaApplication.h +${CMAKE_CURRENT_LIST_DIR}/RiaConsoleApplication.h +${CMAKE_CURRENT_LIST_DIR}/RiaGuiApplication.h ${CMAKE_CURRENT_LIST_DIR}/RiaCompletionTypeCalculationScheduler.h ${CMAKE_CURRENT_LIST_DIR}/RiaDefines.h ${CMAKE_CURRENT_LIST_DIR}/RiaFractureDefines.h @@ -17,6 +19,8 @@ ${CMAKE_CURRENT_LIST_DIR}/RiaEclipseFileNameTools.h set (SOURCE_GROUP_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/RiaApplication.cpp +${CMAKE_CURRENT_LIST_DIR}/RiaConsoleApplication.cpp +${CMAKE_CURRENT_LIST_DIR}/RiaGuiApplication.cpp ${CMAKE_CURRENT_LIST_DIR}/RiaCompletionTypeCalculationScheduler.cpp ${CMAKE_CURRENT_LIST_DIR}/RiaDefines.cpp ${CMAKE_CURRENT_LIST_DIR}/RiaFractureDefines.cpp @@ -42,7 +46,8 @@ ${SOURCE_GROUP_SOURCE_FILES} set (QT_MOC_HEADERS ${QT_MOC_HEADERS} -${CMAKE_CURRENT_LIST_DIR}/RiaApplication.h +${CMAKE_CURRENT_LIST_DIR}/RiaConsoleApplication.h +${CMAKE_CURRENT_LIST_DIR}/RiaGuiApplication.h ${CMAKE_CURRENT_LIST_DIR}/RiaCompletionTypeCalculationScheduler.h ${CMAKE_CURRENT_LIST_DIR}/RiaViewRedrawScheduler.h ) diff --git a/ApplicationCode/Application/RiaApplication.cpp b/ApplicationCode/Application/RiaApplication.cpp index 9f994bef10..9c9e7b37b4 100644 --- a/ApplicationCode/Application/RiaApplication.cpp +++ b/ApplicationCode/Application/RiaApplication.cpp @@ -1,8 +1,6 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011- Statoil ASA -// Copyright (C) 2013- Ceetron Solutions AS -// Copyright (C) 2011-2012 Ceetron AS +// Copyright (C) 2019- 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 @@ -17,24 +15,24 @@ // for more details. // ///////////////////////////////////////////////////////////////////////////////// - #include "RiaApplication.h" #include "RiaArgumentParser.h" #include "RiaBaseDefs.h" -#include "RiaColorTables.h" #include "RiaFilePathTools.h" #include "RiaFontCache.h" +#include "RiaGuiApplication.h" #include "RiaImportEclipseCaseTools.h" #include "RiaLogging.h" #include "RiaPreferences.h" #include "RiaProjectModifier.h" #include "RiaSocketServer.h" #include "RiaVersionInfo.h" -#include "RiaViewRedrawScheduler.h" #include "ExportCommands/RicSnapshotAllViewsToFileFeature.h" #include "HoloLensCommands/RicHoloLensSessionManager.h" +#include "RicfCommandFileExecutor.h" +#include "RicfMessages.h" #include "RicImportGeneralDataFeature.h" #include "Rim2dIntersectionViewCollection.h" @@ -84,38 +82,21 @@ #include "RimWellPltPlot.h" #include "RimWellRftPlot.h" -#include "Riu3dSelectionManager.h" -#include "RiuDockWidgetTools.h" -#include "RiuMainWindow.h" -#include "RiuMessagePanel.h" -#include "RiuPlotMainWindow.h" -#include "RiuProcessMonitor.h" -#include "RiuRecentFileActionProvider.h" -#include "RiuViewer.h" - -#include "cafAppEnum.h" -#include "cafEffectGenerator.h" -#include "cafFixedAtlasFont.h" #include "cafPdmSettings.h" -#include "cafPdmUiModelChangeDetector.h" -#include "cafPdmUiTreeView.h" #include "cafProgressInfo.h" -#include "cafQTreeViewStateSerializer.h" -#include "cafSelectionManager.h" #include "cafUiProcess.h" #include "cafUtils.h" #include "cvfProgramOptions.h" #include "cvfqtUtils.h" +#include #include -#include -#include -#include -#include -#include +#include -#ifndef WIN32 +#ifdef WIN32 +#include +#else #include // for usleep #endif // WIN32 @@ -123,104 +104,32 @@ #include "gtest/gtest.h" #endif // USE_UNIT_TESTS -namespace caf -{ -template<> -void AppEnum::setUp() -{ - addItem(RiaApplication::NAVIGATION_POLICY_CEETRON, "NAVIGATION_POLICY_CEETRON", "Ceetron"); - addItem(RiaApplication::NAVIGATION_POLICY_CAD, "NAVIGATION_POLICY_CAD", "CAD"); - addItem(RiaApplication::NAVIGATION_POLICY_GEOQUEST, "NAVIGATION_POLICY_GEOQUEST", "GEOQUEST"); - addItem(RiaApplication::NAVIGATION_POLICY_RMS, "NAVIGATION_POLICY_RMS", "RMS"); - setDefault(RiaApplication::NAVIGATION_POLICY_RMS); -} -} // namespace caf - -//================================================================================================== -/// -/// \class RiaApplication -/// -/// Application class -/// -//================================================================================================== +RiaApplication* RiaApplication::s_riaApplication = nullptr; //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool RiaApplication::notify(QObject* receiver, QEvent* event) +RiaApplication* RiaApplication::instance() { - // Pre-allocating a memory exhaustion message - // Doing som e trickery to avoid deadlock, as creating a messagebox actually triggers a call to this notify method. - - static QMessageBox* memoryExhaustedBox = nullptr; - static bool allocatingMessageBox = false; - if (!memoryExhaustedBox && !allocatingMessageBox) - { - allocatingMessageBox = true; - memoryExhaustedBox = new QMessageBox(QMessageBox::Critical, - "ResInsight Exhausted Memory", - "Memory is Exhausted!\n ResInsight could not allocate the memory needed, and is now " - "unstable and will probably crash soon."); - } - - bool done = true; - try - { - done = QApplication::notify(receiver, event); - } - catch (const std::bad_alloc&) - { - if (memoryExhaustedBox) memoryExhaustedBox->exec(); - std::cout << "ResInsight: Memory is Exhausted!\n ResInsight could not allocate the memory needed, and is now unstable " - "and will probably crash soon." - << std::endl; - // If we really want to crash instead of limping forward: - // throw; - } - - return done; + return s_riaApplication; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RiaApplication::RiaApplication(int& argc, char** argv) - : QApplication(argc, argv) - , m_socketServer(nullptr) +RiaApplication::RiaApplication() + : m_socketServer(nullptr) , m_workerProcess(nullptr) , m_preferences(nullptr) , m_runningWorkerProcess(false) - , m_mainWindow(nullptr) - , m_mainPlotWindow(nullptr) { + CAF_ASSERT(s_riaApplication == nullptr); + s_riaApplication = this; + // USed to get registry settings in the right place QCoreApplication::setOrganizationName(RI_COMPANY_NAME); QCoreApplication::setApplicationName(RI_APPLICATION_NAME); - // For idle processing - // m_idleTimerStarted = false; - installEventFilter(this); - - // cvf::Trace::enable(false); - - m_preferences = new RiaPreferences; - caf::PdmSettings::readFieldsFromApplicationStore(m_preferences); - applyPreferences(); - - if (useShaders()) - { - caf::EffectGenerator::setRenderingMode(caf::EffectGenerator::SHADER_BASED); - } - else - { - caf::EffectGenerator::setRenderingMode(caf::EffectGenerator::FIXED_FUNCTION); - } - - // Start with a project - m_project = new RimProject; - - setWindowIcon(QIcon(":/AppLogo48x48.png")); - #ifdef WIN32 m_startupDefaultDirectory = QDir::homePath(); #else @@ -228,18 +137,6 @@ RiaApplication::RiaApplication(int& argc, char** argv) #endif setLastUsedDialogDirectory("MULTICASEIMPORT", "/"); - - m_recentFileActionProvider = std::unique_ptr(new RiuRecentFileActionProvider); - - // Create main windows - // The plot window is created to be able to set expanded state on created objects, but hidden by default - getOrCreateAndShowMainWindow(); - getOrCreateMainPlotWindow(); - - RiaLogging::setLoggerInstance(new RiuMessagePanelLogger(m_mainWindow->messagePanel())); - RiaLogging::loggerInstance()->setLevel(RI_LL_DEBUG); - - m_socketServer = new RiaSocketServer(this); } //-------------------------------------------------------------------------------------------------- @@ -247,85 +144,7 @@ RiaApplication::RiaApplication(int& argc, char** argv) //-------------------------------------------------------------------------------------------------- RiaApplication::~RiaApplication() { - RiuDockWidgetTools::instance()->saveDockWidgetsState(); - - deleteMainPlotWindow(); - deleteMainWindow(); - delete m_preferences; - - RiaLogging::deleteLoggerInstance(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -RiaApplication* RiaApplication::instance() -{ - return static_cast qApp; -} - -//-------------------------------------------------------------------------------------------------- -/// Return -1 if unit test is not executed, returns 0 if test passed, returns 1 if tests failed -//-------------------------------------------------------------------------------------------------- -int RiaApplication::parseArgumentsAndRunUnitTestsIfRequested() -{ - cvf::ProgramOptions progOpt; - progOpt.registerOption("unittest", "", "Execute unit tests"); - progOpt.setOptionPrefix(cvf::ProgramOptions::DOUBLE_DASH); - - QStringList arguments = QCoreApplication::arguments(); - - bool parseOk = progOpt.parse(cvfqt::Utils::toStringVector(arguments)); - if (!parseOk) - { - return -1; - } - - // Unit testing - // -------------------------------------------------------- - if (cvf::Option o = progOpt.option("unittest")) - { - int testReturnValue = launchUnitTestsWithConsole(); - - return testReturnValue; - } - - return -1; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiaApplication::setWindowCaptionFromAppState() -{ - if (!m_mainWindow) return; - - // The stuff being done here should really be handled by Qt automatically as a result of - // setting applicationName and windowFilePath - // Was unable to make this work in Qt4.4.0! - - QString capt = RI_APPLICATION_NAME; -#ifdef _DEBUG - capt += " ##DEBUG##"; -#endif - - { - QString projFileName = m_project->fileName(); - if (projFileName.isEmpty()) projFileName = "Untitled project"; - - capt = projFileName + QString("[*]") + QString(" - ") + capt; - } - - m_mainWindow->setWindowTitle(capt); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiaApplication::processNonGuiEvents() -{ - processEvents(QEventLoop::ExcludeUserInputEvents); } //-------------------------------------------------------------------------------------------------- @@ -356,47 +175,180 @@ const char* RiaApplication::getVersionStringApp(bool includeCrtInfo) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -class RiaMdiMaximizeWindowGuard +bool RiaApplication::enableDevelopmentFeatures() { -public: - RiaMdiMaximizeWindowGuard() + QString environmentVar = QProcessEnvironment::systemEnvironment().value("RESINSIGHT_DEVEL", QString("0")); + return environmentVar.toInt() == 1; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaApplication::createMockModel() +{ + RiaImportEclipseCaseTools::openMockModel(RiaDefines::mockModelBasic()); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaApplication::createResultsMockModel() +{ + RiaImportEclipseCaseTools::openMockModel(RiaDefines::mockModelBasicWithResults()); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaApplication::createLargeResultsMockModel() +{ + RiaImportEclipseCaseTools::openMockModel(RiaDefines::mockModelLargeWithResults()); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaApplication::createMockModelCustomized() +{ + RiaImportEclipseCaseTools::openMockModel(RiaDefines::mockModelCustomized()); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaApplication::createInputMockModel() +{ + RiaImportEclipseCaseTools::openEclipseInputCaseFromFileNames(QStringList(RiaDefines::mockModelBasicInputCase())); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaApplication::setActiveReservoirView(Rim3dView* rv) +{ + m_activeReservoirView = rv; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +const Rim3dView* RiaApplication::activeReservoirView() const +{ + return m_activeReservoirView; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +Rim3dView* RiaApplication::activeReservoirView() +{ + return m_activeReservoirView; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimGridView* RiaApplication::activeGridView() +{ + return dynamic_cast(m_activeReservoirView.p()); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimProject* RiaApplication::project() +{ + return m_project; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RiaApplication::openFile(const QString& fileName) +{ + if (!caf::Utils::fileExists(fileName)) return false; + + bool loadingSucceded = false; + + QString lastUsedDialogTag; + + RiaDefines::ImportFileType fileType = RiaDefines::obtainFileTypeFromFileName(fileName); + + if (fileType == RiaDefines::RESINSIGHT_PROJECT_FILE) { + loadingSucceded = loadProject(fileName); + } + else if (fileType == RiaDefines::GEOMECH_ODB_FILE) + { + loadingSucceded = openOdbCaseFromFile(fileName); + lastUsedDialogTag = "GEOMECH_MODEL"; + } + else if (fileType & RiaDefines::ANY_ECLIPSE_FILE) + { + loadingSucceded = RicImportGeneralDataFeature::openEclipseFilesFromFileNames(QStringList{fileName}); + lastUsedDialogTag = RiaDefines::defaultDirectoryLabel(fileType); + } + + if (loadingSucceded) + { + if (!lastUsedDialogTag.isEmpty()) { - RiuMainWindow* mainWindow = RiaApplication::instance()->mainWindow(); - if (mainWindow) - { - mainWindow->enableShowFirstVisibleMdiWindowMaximized(false); - } + RiaApplication::instance()->setLastUsedDialogDirectory(lastUsedDialogTag, QFileInfo(fileName).absolutePath()); } + onFileSuccessfullyLoaded(fileName, fileType); + } + + return loadingSucceded; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RiaApplication::currentProjectPath() const +{ + QString projectFolder; + if (m_project) + { + QString projectFileName = m_project->fileName(); + + if (!projectFileName.isEmpty()) { - RiuPlotMainWindow* plotMainWindow = RiaApplication::instance()->mainPlotWindow(); - if (plotMainWindow) - { - plotMainWindow->enableShowFirstVisibleMdiWindowMaximized(false); - } + QFileInfo fi(projectFileName); + projectFolder = fi.absolutePath(); } } - ~RiaMdiMaximizeWindowGuard() - { - { - RiuMainWindow* mainWindow = RiaApplication::instance()->mainWindow(); - if (mainWindow) - { - mainWindow->enableShowFirstVisibleMdiWindowMaximized(true); - } - } + return projectFolder; +} - { - RiuPlotMainWindow* plotMainWindow = RiaApplication::instance()->mainPlotWindow(); - if (plotMainWindow) - { - plotMainWindow->enableShowFirstVisibleMdiWindowMaximized(true); - } - } +//-------------------------------------------------------------------------------------------------- +/// Create an absolute path from a path that is specified relative to the project directory +/// +/// If the path specified in \a projectRelativePath is already absolute, no changes will be made +//-------------------------------------------------------------------------------------------------- +QString RiaApplication::createAbsolutePathFromProjectRelativePath(QString projectRelativePath) +{ + // Check if path is already absolute + if (QDir::isAbsolutePath(projectRelativePath)) + { + return projectRelativePath; } -}; + + QString absolutePath; + if (m_project && !m_project->fileName().isEmpty()) + { + absolutePath = QFileInfo(m_project->fileName()).absolutePath(); + } + else + { + absolutePath = this->lastUsedDialogDirectory("BINARY_GRID"); + } + + QDir projectDir(absolutePath); + + return projectDir.absoluteFilePath(projectRelativePath); +} //-------------------------------------------------------------------------------------------------- /// @@ -409,8 +361,7 @@ bool RiaApplication::loadProject(const QString& projectFileName, closeProject(); - // When importing a project, do not maximize the first MDI window to be created - RiaMdiMaximizeWindowGuard maximizeWindowGuard; + onProjectBeingOpened(); RiaLogging::info(QString("Starting to open project file : '%1'").arg(projectFileName)); @@ -441,48 +392,20 @@ bool RiaApplication::loadProject(const QString& projectFileName, { closeProject(); - QString tmp = + QString errMsg = QString("Unknown project file version detected in file \n%1\n\nCould not open project.").arg(fullPathProjectFileName); - QMessageBox::warning(nullptr, "Error when opening project file", tmp); - - m_mainWindow->setPdmRoot(nullptr); + + onProjectOpeningError(errMsg); // Delete all object possibly generated by readFile() delete m_project; m_project = new RimProject; - onProjectOpenedOrClosed(); + onProjectOpened(); return true; } - - if (m_project->show3DWindow()) - { - m_mainWindow->show(); - } - else - { - m_mainWindow->hide(); - } - - if (m_project->showPlotWindow()) - { - if (!m_mainPlotWindow) - { - createMainPlotWindow(); - m_mainPlotWindow->show(); - } - else - { - m_mainPlotWindow->show(); - m_mainPlotWindow->raise(); - } - } - else if (mainPlotWindow()) - { - mainPlotWindow()->hide(); - } - + /////// // Load the external data, and initialize stuff that needs specific ordering @@ -667,14 +590,11 @@ bool RiaApplication::loadProject(const QString& projectFileName, oilField->annotationCollection()->loadDataAndUpdate(); } - loadAndUpdatePlotData(); - // NB! This function must be called before executing command objects, // because the tree view state is restored from project file and sets // current active view ( see restoreTreeViewState() ) // Default behavior for scripts is to use current active view for data read/write - onProjectOpenedOrClosed(); - processEvents(); + onProjectOpened(); // Loop over command objects and execute them for (size_t i = 0; i < m_project->commandObjects.size(); i++) @@ -704,174 +624,150 @@ bool RiaApplication::loadProject(const QString& projectFileName) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RiaApplication::loadAndUpdatePlotData() +bool RiaApplication::saveProjectAs(const QString& fileName, QString* errorMessage) { - RimWellLogPlotCollection* wlpColl = nullptr; - RimSummaryPlotCollection* spColl = nullptr; - RimSummaryCrossPlotCollection* scpColl = nullptr; - RimFlowPlotCollection* flowColl = nullptr; - RimRftPlotCollection* rftColl = nullptr; - RimPltPlotCollection* pltColl = nullptr; - RimGridCrossPlotCollection* gcpColl = nullptr; - RimSaturationPressurePlotCollection* sppColl = nullptr; + // Make sure we always store path with forward slash to avoid issues when opening the project file on Linux + m_project->fileName = RiaFilePathTools::toInternalSeparator(fileName); - if (m_project->mainPlotCollection() && m_project->mainPlotCollection()->wellLogPlotCollection()) + if (!m_project->writeFile()) { - wlpColl = m_project->mainPlotCollection()->wellLogPlotCollection(); - } - if (m_project->mainPlotCollection() && m_project->mainPlotCollection()->summaryPlotCollection()) - { - spColl = m_project->mainPlotCollection()->summaryPlotCollection(); - } - if (m_project->mainPlotCollection() && m_project->mainPlotCollection()->summaryCrossPlotCollection()) - { - scpColl = m_project->mainPlotCollection()->summaryCrossPlotCollection(); - } - if (m_project->mainPlotCollection() && m_project->mainPlotCollection()->flowPlotCollection()) - { - flowColl = m_project->mainPlotCollection()->flowPlotCollection(); - } - if (m_project->mainPlotCollection() && m_project->mainPlotCollection()->rftPlotCollection()) - { - rftColl = m_project->mainPlotCollection()->rftPlotCollection(); - } - if (m_project->mainPlotCollection() && m_project->mainPlotCollection()->pltPlotCollection()) - { - pltColl = m_project->mainPlotCollection()->pltPlotCollection(); - } - if (m_project->mainPlotCollection() && m_project->mainPlotCollection()->gridCrossPlotCollection()) - { - gcpColl = m_project->mainPlotCollection()->gridCrossPlotCollection(); - } - if (m_project->mainPlotCollection() && m_project->mainPlotCollection()->saturationPressurePlotCollection()) - { - sppColl = m_project->mainPlotCollection()->saturationPressurePlotCollection(); + CAF_ASSERT(errorMessage); + *errorMessage = + QString("Not possible to save project file. Make sure you have sufficient access rights.\n\nProject file location : %1") + .arg(fileName); + + return false; } - size_t plotCount = 0; - plotCount += wlpColl ? wlpColl->wellLogPlots().size() : 0; - plotCount += spColl ? spColl->summaryPlots().size() : 0; - plotCount += scpColl ? scpColl->summaryPlots().size() : 0; - plotCount += flowColl ? flowColl->plotCount() : 0; - plotCount += rftColl ? rftColl->rftPlots().size() : 0; - plotCount += pltColl ? pltColl->pltPlots().size() : 0; - plotCount += gcpColl ? gcpColl->gridCrossPlots().size() : 0; - plotCount += sppColl ? sppColl->plots().size() : 0; + m_preferences->lastUsedProjectFileName = fileName; + caf::PdmSettings::writeFieldsToApplicationStore(m_preferences); - if (plotCount > 0) - { - caf::ProgressInfo plotProgress(plotCount, "Loading Plot Data"); - if (wlpColl) - { - for (size_t wlpIdx = 0; wlpIdx < wlpColl->wellLogPlots().size(); ++wlpIdx) - { - wlpColl->wellLogPlots[wlpIdx]->loadDataAndUpdate(); - plotProgress.incrementProgress(); - } - } - - if (spColl) - { - for (size_t wlpIdx = 0; wlpIdx < spColl->summaryPlots().size(); ++wlpIdx) - { - spColl->summaryPlots[wlpIdx]->loadDataAndUpdate(); - plotProgress.incrementProgress(); - } - } - - if (scpColl) - { - for (auto plot : scpColl->summaryPlots()) - { - plot->loadDataAndUpdate(); - plotProgress.incrementProgress(); - } - } - - if (flowColl) - { - plotProgress.setNextProgressIncrement(flowColl->plotCount()); - flowColl->loadDataAndUpdate(); - plotProgress.incrementProgress(); - } - - if (rftColl) - { - for (const auto& rftPlot : rftColl->rftPlots()) - { - rftPlot->loadDataAndUpdate(); - plotProgress.incrementProgress(); - } - } - - if (pltColl) - { - for (const auto& pltPlot : pltColl->pltPlots()) - { - pltPlot->loadDataAndUpdate(); - plotProgress.incrementProgress(); - } - } - - if (gcpColl) - { - for (const auto& gcpPlot : gcpColl->gridCrossPlots()) - { - gcpPlot->loadDataAndUpdate(); - plotProgress.incrementProgress(); - } - } - - if (sppColl) - { - for (const auto& sppPlot : sppColl->plots()) - { - sppPlot->loadDataAndUpdate(); - plotProgress.incrementProgress(); - } - } - } + return true; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RiaApplication::storeTreeViewState() +bool RiaApplication::hasValidProjectFileExtension(const QString& fileName) { + if (fileName.contains(".rsp", Qt::CaseInsensitive) || fileName.contains(".rip", Qt::CaseInsensitive)) { - if (mainPlotWindow() && mainPlotWindow()->projectTreeView()) - { - caf::PdmUiTreeView* projectTreeView = mainPlotWindow()->projectTreeView(); - - QString treeViewState; - caf::QTreeViewStateSerializer::storeTreeViewStateToString(projectTreeView->treeView(), treeViewState); - - QModelIndex mi = projectTreeView->treeView()->currentIndex(); - - QString encodedModelIndexString; - caf::QTreeViewStateSerializer::encodeStringFromModelIndex(mi, encodedModelIndexString); - - project()->plotWindowTreeViewState = treeViewState; - project()->plotWindowCurrentModelIndexPath = encodedModelIndexString; - } + return true; } + return false; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaApplication::closeProject() +{ + onProjectBeingClosed(); + + terminateProcess(); + m_project->close(); + m_commandQueue.clear(); + + onProjectClosed(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RiaApplication::lastUsedDialogDirectory(const QString& dialogName) +{ + QString lastUsedDirectory = m_startupDefaultDirectory; + + auto it = m_fileDialogDefaultDirectories.find(dialogName); + if (it != m_fileDialogDefaultDirectories.end()) { - caf::PdmUiTreeView* projectTreeView = m_mainWindow->projectTreeView(); - if (projectTreeView) - { - QString treeViewState; - caf::QTreeViewStateSerializer::storeTreeViewStateToString(projectTreeView->treeView(), treeViewState); - - QModelIndex mi = projectTreeView->treeView()->currentIndex(); - - QString encodedModelIndexString; - caf::QTreeViewStateSerializer::encodeStringFromModelIndex(mi, encodedModelIndexString); - - project()->mainWindowTreeViewState = treeViewState; - project()->mainWindowCurrentModelIndexPath = encodedModelIndexString; - } + lastUsedDirectory = it->second; } + + return lastUsedDirectory; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RiaApplication::lastUsedDialogDirectoryWithFallback(const QString& dialogName, const QString& fallbackDirectory) +{ + QString lastUsedDirectory = m_startupDefaultDirectory; + if (!fallbackDirectory.isEmpty()) + { + lastUsedDirectory = fallbackDirectory; + } + + auto it = m_fileDialogDefaultDirectories.find(dialogName); + if (it != m_fileDialogDefaultDirectories.end()) + { + lastUsedDirectory = it->second; + } + + return lastUsedDirectory; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RiaApplication::lastUsedDialogDirectoryWithFallbackToProjectFolder(const QString& dialogName) +{ + return lastUsedDialogDirectoryWithFallback(dialogName, currentProjectPath()); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaApplication::setLastUsedDialogDirectory(const QString& dialogName, const QString& directory) +{ + m_fileDialogDefaultDirectories[dialogName] = directory; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RiaApplication::openOdbCaseFromFile(const QString& fileName, bool applyTimeStepFilter) +{ + if (!caf::Utils::fileExists(fileName)) return false; + + QFileInfo gridFileName(fileName); + QString caseName = gridFileName.completeBaseName(); + + RimGeoMechCase* geoMechCase = new RimGeoMechCase(); + geoMechCase->setFileName(fileName); + geoMechCase->caseUserDescription = caseName; + geoMechCase->setApplyTimeFilter(applyTimeStepFilter); + + RimGeoMechModels* geoMechModelCollection = + m_project->activeOilField() ? m_project->activeOilField()->geoMechModels() : nullptr; + + // Create the geoMech model container if it is not there already + if (geoMechModelCollection == nullptr) + { + geoMechModelCollection = new RimGeoMechModels(); + m_project->activeOilField()->geoMechModels = geoMechModelCollection; + } + + RimGeoMechView* riv = geoMechCase->createAndAddReservoirView(); + caf::ProgressInfo progress(11, "Loading Case"); + progress.setNextProgressIncrement(10); + + riv->loadDataAndUpdate(); + + if (!riv->geoMechCase()) + { + delete geoMechCase; + return false; + } + geoMechModelCollection->cases.push_back(geoMechCase); + + progress.incrementProgress(); + progress.setProgressDescription("Loading results information"); + + m_project->updateConnectedEditors(); + + return true; } //-------------------------------------------------------------------------------------------------- @@ -939,817 +835,7 @@ void RiaApplication::addWellLogsToModel(const QList& wellLogFilePaths) m_project->updateConnectedEditors(); } - RimWellLogFile* wellLogFile = oilField->wellPathCollection->addWellLogs(wellLogFilePaths); - oilField->wellPathCollection->updateConnectedEditors(); - - m_mainWindow->selectAsCurrentItem(wellLogFile); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool RiaApplication::saveProject() -{ - CVF_ASSERT(m_project.notNull()); - - if (!caf::Utils::fileExists(m_project->fileName())) - { - return saveProjectPromptForFileName(); - } - else - { - return saveProjectAs(m_project->fileName()); - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool RiaApplication::saveProjectPromptForFileName() -{ - // if (m_project.isNull()) return true; - - RiaApplication* app = RiaApplication::instance(); - - QString startPath; - if (!m_project->fileName().isEmpty()) - { - startPath = m_project->fileName(); - } - else - { - startPath = app->lastUsedDialogDirectory("BINARY_GRID"); - startPath += "/ResInsightProject.rsp"; - } - - QString fileName = - QFileDialog::getSaveFileName(nullptr, tr("Save File"), startPath, tr("Project Files (*.rsp);;All files(*.*)")); - if (fileName.isEmpty()) - { - return false; - } - - // Remember the directory to next time - app->setLastUsedDialogDirectory("BINARY_GRID", QFileInfo(fileName).absolutePath()); - - bool bSaveOk = saveProjectAs(fileName); - - setWindowCaptionFromAppState(); - - return bSaveOk; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool RiaApplication::hasValidProjectFileExtension(const QString& fileName) -{ - if (fileName.contains(".rsp", Qt::CaseInsensitive) || fileName.contains(".rip", Qt::CaseInsensitive)) - { - return true; - } - - return false; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool RiaApplication::askUserToSaveModifiedProject() -{ - if (m_preferences->showProjectChangedDialog() && caf::PdmUiModelChangeDetector::instance()->isModelChanged()) - { - QMessageBox msgBox; - msgBox.setIcon(QMessageBox::Question); - - QString questionText; - questionText = QString("The current project is modified.\n\nDo you want to save the changes?"); - - msgBox.setText(questionText); - msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); - - int ret = msgBox.exec(); - if (ret == QMessageBox::Cancel) - { - return false; - } - else if (ret == QMessageBox::Yes) - { - if (!saveProject()) - { - return false; - } - } - else - { - caf::PdmUiModelChangeDetector::instance()->reset(); - } - } - - return true; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool RiaApplication::saveProjectAs(const QString& fileName) -{ - // Make sure we always store path with forward slash to avoid issues when opening the project file on Linux - m_project->fileName = RiaFilePathTools::toInternalSeparator(fileName); - - storeTreeViewState(); - - if (!m_project->writeFile()) - { - QMessageBox::warning( - nullptr, - "Error when saving project file", - QString( - "Not possible to save project file. Make sure you have sufficient access rights.\n\nProject file location : %1") - .arg(fileName)); - - return false; - } - - m_preferences->lastUsedProjectFileName = fileName; - caf::PdmSettings::writeFieldsToApplicationStore(m_preferences); - - m_recentFileActionProvider->addFileName(fileName); - - caf::PdmUiModelChangeDetector::instance()->reset(); - - return true; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiaApplication::closeProject() -{ - RicHoloLensSessionManager::instance()->terminateSession(); - RicHoloLensSessionManager::refreshToolbarState(); - - RiaViewRedrawScheduler::instance()->clearViewsScheduledForUpdate(); - - terminateProcess(); - - RiaApplication::clearAllSelections(); - - m_mainWindow->cleanupGuiBeforeProjectClose(); - - if (m_mainPlotWindow) - { - m_mainPlotWindow->cleanupGuiBeforeProjectClose(); - } - - caf::EffectGenerator::clearEffectCache(); - m_project->close(); - - m_commandQueue.clear(); - - onProjectOpenedOrClosed(); - - // Make sure all project windows are closed down properly before returning - processEvents(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiaApplication::onProjectOpenedOrClosed() -{ - if (m_mainWindow) - { - m_mainWindow->initializeGuiNewProjectLoaded(); - } - if (m_mainPlotWindow) - { - m_mainPlotWindow->initializeGuiNewProjectLoaded(); - } - - setWindowCaptionFromAppState(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -QString RiaApplication::currentProjectPath() const -{ - QString projectFolder; - if (m_project) - { - QString projectFileName = m_project->fileName(); - - if (!projectFileName.isEmpty()) - { - QFileInfo fi(projectFileName); - projectFolder = fi.absolutePath(); - } - } - - return projectFolder; -} - -//-------------------------------------------------------------------------------------------------- -/// Create an absolute path from a path that is specified relative to the project directory -/// -/// If the path specified in \a projectRelativePath is already absolute, no changes will be made -//-------------------------------------------------------------------------------------------------- -QString RiaApplication::createAbsolutePathFromProjectRelativePath(QString projectRelativePath) -{ - // Check if path is already absolute - if (QDir::isAbsolutePath(projectRelativePath)) - { - return projectRelativePath; - } - - QString absolutePath; - if (m_project && !m_project->fileName().isEmpty()) - { - absolutePath = QFileInfo(m_project->fileName()).absolutePath(); - } - else - { - absolutePath = this->lastUsedDialogDirectory("BINARY_GRID"); - } - - QDir projectDir(absolutePath); - - return projectDir.absoluteFilePath(projectRelativePath); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool RiaApplication::openOdbCaseFromFile(const QString& fileName, bool applyTimeStepFilter) -{ - if (!caf::Utils::fileExists(fileName)) return false; - - QFileInfo gridFileName(fileName); - QString caseName = gridFileName.completeBaseName(); - - RimGeoMechCase* geoMechCase = new RimGeoMechCase(); - geoMechCase->setFileName(fileName); - geoMechCase->caseUserDescription = caseName; - geoMechCase->setApplyTimeFilter(applyTimeStepFilter); - - RimGeoMechModels* geoMechModelCollection = - m_project->activeOilField() ? m_project->activeOilField()->geoMechModels() : nullptr; - - // Create the geoMech model container if it is not there already - if (geoMechModelCollection == nullptr) - { - geoMechModelCollection = new RimGeoMechModels(); - m_project->activeOilField()->geoMechModels = geoMechModelCollection; - } - - RimGeoMechView* riv = geoMechCase->createAndAddReservoirView(); - caf::ProgressInfo progress(11, "Loading Case"); - progress.setNextProgressIncrement(10); - - riv->loadDataAndUpdate(); - - if (!riv->geoMechCase()) - { - delete geoMechCase; - return false; - } - geoMechModelCollection->cases.push_back(geoMechCase); - - // if (!riv->cellResult()->hasResult()) - //{ - // riv->cellResult()->setResultVariable(RiaDefines::undefinedResultName()); - //} - progress.incrementProgress(); - progress.setProgressDescription("Loading results information"); - - m_project->updateConnectedEditors(); - - m_mainWindow->selectAsCurrentItem(riv->cellResult()); - - return true; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiaApplication::createMockModel() -{ - RiaImportEclipseCaseTools::openMockModel(RiaDefines::mockModelBasic()); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiaApplication::createResultsMockModel() -{ - RiaImportEclipseCaseTools::openMockModel(RiaDefines::mockModelBasicWithResults()); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiaApplication::createLargeResultsMockModel() -{ - RiaImportEclipseCaseTools::openMockModel(RiaDefines::mockModelLargeWithResults()); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiaApplication::createMockModelCustomized() -{ - RiaImportEclipseCaseTools::openMockModel(RiaDefines::mockModelCustomized()); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiaApplication::createInputMockModel() -{ - RiaImportEclipseCaseTools::openEclipseInputCaseFromFileNames(QStringList(RiaDefines::mockModelBasicInputCase())); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -const Rim3dView* RiaApplication::activeReservoirView() const -{ - return m_activeReservoirView; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -Rim3dView* RiaApplication::activeReservoirView() -{ - return m_activeReservoirView; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -RimGridView* RiaApplication::activeGridView() -{ - return dynamic_cast(m_activeReservoirView.p()); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -RimViewWindow* RiaApplication::activePlotWindow() const -{ - RimViewWindow* viewWindow = nullptr; - - if (m_mainPlotWindow) - { - QList subwindows = m_mainPlotWindow->subWindowList(QMdiArea::StackingOrder); - if (subwindows.size() > 0) - { - viewWindow = RiuInterfaceToViewWindow::viewWindowFromWidget(subwindows.back()->widget()); - } - } - - return viewWindow; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiaApplication::setActiveReservoirView(Rim3dView* rv) -{ - m_activeReservoirView = rv; - - RiuDockWidgetTools::instance()->changeDockWidgetVisibilityBasedOnView(rv); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool RiaApplication::useShaders() const -{ - if (!m_preferences->useShaders) return false; - - bool isShadersSupported = caf::Viewer::isShadersSupported(); - if (!isShadersSupported) return false; - - return true; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -RiaApplication::RINavigationPolicy RiaApplication::navigationPolicy() const -{ - return m_preferences->navigationPolicy(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool RiaApplication::showPerformanceInfo() const -{ - return m_preferences->showHud; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool RiaApplication::parseArguments() -{ - bool result = RiaArgumentParser::parseArguments(); - if (!result) - { - closeAllWindows(); - processEvents(); - } - - return result; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -int RiaApplication::launchUnitTests() -{ -#ifdef USE_UNIT_TESTS - - caf::ProgressInfoBlocker progressBlocker; - cvf::Assert::setReportMode(cvf::Assert::CONSOLE); - -#if QT_VERSION < 0x050000 - int argc = QCoreApplication::argc(); - char** argv = QCoreApplication::argv(); -#else - int argc = QCoreApplication::arguments().size(); - QStringList arguments = QCoreApplication::arguments(); - std::vector argumentsStd; - for (QString qstring : arguments) - { - argumentsStd.push_back(qstring.toStdString()); - } - std::vector argVector; - for (std::string& string : argumentsStd) - { - argVector.push_back(&string.front()); - } - char** argv = argVector.data(); -#endif - - testing::InitGoogleTest(&argc, argv); - - // Use this macro in main() to run all tests. It returns 0 if all - // tests are successful, or 1 otherwise. - // - // RUN_ALL_TESTS() should be invoked after the command line has been - // parsed by InitGoogleTest(). - - return RUN_ALL_TESTS(); - -#else - return -1; -#endif -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -int RiaApplication::launchUnitTestsWithConsole() -{ - // Following code is taken from cvfAssert.cpp -#ifdef WIN32 - { - // Allocate a new console for this app - // Only one console can be associated with an app, so should fail if a console is already present. - AllocConsole(); - - FILE* consoleFilePointer; - - freopen_s(&consoleFilePointer, "CONOUT$", "w", stdout); - freopen_s(&consoleFilePointer, "CONOUT$", "w", stderr); - - // Make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog point to console as well - std::ios::sync_with_stdio(); - } -#endif - - return launchUnitTests(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -RiuMainWindow* RiaApplication::getOrCreateAndShowMainWindow() -{ - if (!m_mainWindow) - { - createMainWindow(); - } - return m_mainWindow; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -RiuMainWindow* RiaApplication::mainWindow() -{ - return m_mainWindow; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -RiuPlotMainWindow* RiaApplication::getOrCreateMainPlotWindow() -{ - if (!m_mainPlotWindow) - { - createMainPlotWindow(); - m_mainPlotWindow->initializeGuiNewProjectLoaded(); - loadAndUpdatePlotData(); - } - return m_mainPlotWindow; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiaApplication::createMainWindow() -{ - CVF_ASSERT(m_mainWindow == nullptr); - m_mainWindow = new RiuMainWindow; - QString platform = cvf::System::is64Bit() ? "(64bit)" : "(32bit)"; - m_mainWindow->setWindowTitle("ResInsight " + platform); - m_mainWindow->setDefaultWindowSize(); - m_mainWindow->setDefaultToolbarVisibility(); - m_mainWindow->loadWinGeoAndDockToolBarLayout(); - m_mainWindow->showWindow(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiaApplication::deleteMainWindow() -{ - if (m_mainWindow) - { - delete m_mainWindow; - m_mainWindow = nullptr; - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiaApplication::createMainPlotWindow() -{ - CVF_ASSERT(m_mainPlotWindow == nullptr); - - m_mainPlotWindow = new RiuPlotMainWindow; - - m_mainPlotWindow->setWindowTitle("Plots - ResInsight"); - m_mainPlotWindow->setDefaultWindowSize(); - m_mainPlotWindow->loadWinGeoAndDockToolBarLayout(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiaApplication::deleteMainPlotWindow() -{ - if (m_mainPlotWindow) - { - m_mainPlotWindow->deleteLater(); - m_mainPlotWindow = nullptr; - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -RiuPlotMainWindow* RiaApplication::getOrCreateAndShowMainPlotWindow() -{ - if (!m_mainPlotWindow) - { - createMainPlotWindow(); - m_mainPlotWindow->initializeGuiNewProjectLoaded(); - loadAndUpdatePlotData(); - } - - if (m_mainPlotWindow->isMinimized()) - { - m_mainPlotWindow->showNormal(); - m_mainPlotWindow->update(); - } - else - { - m_mainPlotWindow->show(); - } - - m_mainPlotWindow->raise(); - m_mainPlotWindow->activateWindow(); - return m_mainPlotWindow; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -RiuPlotMainWindow* RiaApplication::mainPlotWindow() -{ - return m_mainPlotWindow; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -RiuMainWindowBase* RiaApplication::mainWindowByID(int mainWindowID) -{ - if (mainWindowID == 0) - return m_mainWindow; - else if (mainWindowID == 1) - return m_mainPlotWindow; - else - return nullptr; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -RimViewWindow* RiaApplication::activeViewWindow() -{ - RimViewWindow* viewWindow = nullptr; - - QWidget* mainWindowWidget = RiaApplication::activeWindow(); - - if (dynamic_cast(mainWindowWidget)) - { - viewWindow = RiaApplication::instance()->activeReservoirView(); - } - else if (dynamic_cast(mainWindowWidget)) - { - RiuPlotMainWindow* mainPlotWindow = dynamic_cast(mainWindowWidget); - - QList subwindows = mainPlotWindow->subWindowList(QMdiArea::StackingOrder); - if (subwindows.size() > 0) - { - viewWindow = RiuInterfaceToViewWindow::viewWindowFromWidget(subwindows.back()->widget()); - } - } - - return viewWindow; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool RiaApplication::isMain3dWindowVisible() const -{ - return m_mainWindow && m_mainWindow->isVisible(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool RiaApplication::isMainPlotWindowVisible() const -{ - return m_mainPlotWindow && m_mainPlotWindow->isVisible(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiaApplication::closeMainWindowIfOpenButHidden() -{ - if (m_mainWindow && !m_mainWindow->isVisible()) - { - m_mainWindow->close(); - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiaApplication::closeMainPlotWindowIfOpenButHidden() -{ - if (m_mainPlotWindow && !m_mainPlotWindow->isVisible()) - { - m_mainPlotWindow->close(); - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiaApplication::addToRecentFiles(const QString& fileName) -{ - CVF_ASSERT(m_recentFileActionProvider && - "The provider needs to be created before any attempts to use the recent file actions"); - m_recentFileActionProvider->addFileName(fileName); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -std::vector RiaApplication::recentFileActions() const -{ - CVF_ASSERT(m_recentFileActionProvider && - "The provider needs to be created before any attempts to use the recent file actions"); - return m_recentFileActionProvider->actions(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiaApplication::setStartDir(const QString& startDir) -{ - m_startupDefaultDirectory = startDir; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -std::vector RiaApplication::readFileListFromTextFile(QString listFileName) -{ - std::vector fileList; - - QFile file(listFileName); - if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) - { - return fileList; - } - - QTextStream in(&file); - QString line = in.readLine(); - while (!line.isNull()) - { - line = line.trimmed(); - if (!line.isEmpty()) - { - fileList.push_back(line); - } - - line = in.readLine(); - } - - return fileList; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiaApplication::waitUntilCommandObjectsHasBeenProcessed() -{ - // Wait until all command objects have completed - bool mutexLockedSuccessfully = m_commandQueueLock.tryLock(); - - while (!mutexLockedSuccessfully) - { - processEvents(); - - mutexLockedSuccessfully = m_commandQueueLock.tryLock(); - } - m_commandQueueLock.unlock(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiaApplication::saveMainWinGeoAndDockToolBarLayout() -{ - if (isMain3dWindowVisible()) - { - m_mainWindow->saveWinGeoAndDockToolBarLayout(); - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiaApplication::savePlotWinGeoAndDockToolBarLayout() -{ - if (isMainPlotWindowVisible()) - { - m_mainPlotWindow->saveWinGeoAndDockToolBarLayout(); - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool RiaApplication::enableDevelopmentFeatures() -{ - QString environmentVar = QProcessEnvironment::systemEnvironment().value("RESINSIGHT_DEVEL", QString("0")); - return environmentVar.toInt() == 1; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiaApplication::clearAllSelections() -{ - Riu3dSelectionManager::instance()->deleteAllItems(Riu3dSelectionManager::RUI_APPLICATION_GLOBAL); - Riu3dSelectionManager::instance()->deleteAllItems(Riu3dSelectionManager::RUI_TEMPORARY); - caf::SelectionManager::instance()->clearAll(); } //-------------------------------------------------------------------------------------------------- @@ -1803,52 +889,6 @@ QStringList RiaApplication::octaveArguments() const return arguments; } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiaApplication::slotWorkerProcessFinished(int exitCode, QProcess::ExitStatus exitStatus) -{ - m_mainWindow->processMonitor()->stopMonitorWorkProcess(); - - // Execute delete later so that other slots that are hooked up - // get a chance to run before we delete the object - if (m_workerProcess) - { - m_workerProcess->close(); - } - m_workerProcess = nullptr; - - // Either the work process crashed or was aborted by the user - if (exitStatus == QProcess::CrashExit) - { - // MFLog::error("Simulation execution crashed or was aborted."); - m_runningWorkerProcess = false; - return; - } - - executeCommandObjects(); - - // Exit code != 0 means we have an error - if (exitCode != 0) - { - // MFLog::error(QString("Simulation execution failed (exit code %1).").arg(exitCode)); - m_runningWorkerProcess = false; - return; - } - - // If multiple cases are present, invoke launchProcess() which will set next current case, and run script on this case - if (!m_currentCaseIds.empty()) - { - launchProcess(m_currentProgram, m_currentArguments); - } - else - { - // Disable concept of current case - m_socketServer->setCurrentCaseId(-1); - m_runningWorkerProcess = false; - } -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -1871,7 +911,7 @@ bool RiaApplication::launchProcess(const QString& program, const QStringList& ar } m_runningWorkerProcess = true; - m_workerProcess = new caf::UiProcess(this); + m_workerProcess = new caf::UiProcess(QCoreApplication::instance()); QProcessEnvironment penv = QProcessEnvironment::systemEnvironment(); @@ -1902,11 +942,11 @@ bool RiaApplication::launchProcess(const QString& program, const QStringList& ar m_workerProcess->setProcessEnvironment(penv); - connect(m_workerProcess, + QCoreApplication::instance()->connect(m_workerProcess, SIGNAL(finished(int, QProcess::ExitStatus)), SLOT(slotWorkerProcessFinished(int, QProcess::ExitStatus))); - m_mainWindow->processMonitor()->startMonitorWorkProcess(m_workerProcess); + startMonitoringWorkProgress(m_workerProcess); m_workerProcess->start(program, arguments); @@ -1919,9 +959,9 @@ bool RiaApplication::launchProcess(const QString& program, const QStringList& ar m_workerProcess = nullptr; m_runningWorkerProcess = false; - m_mainWindow->processMonitor()->stopMonitorWorkProcess(); + stopMonitoringWorkProgress(); - QMessageBox::warning(m_mainWindow, "Script execution", "Failed to start script executable located at\n" + program); +// QMessageBox::warning(m_mainWindow, "Script execution", "Failed to start script executable located at\n" + program); return false; } @@ -1930,9 +970,9 @@ bool RiaApplication::launchProcess(const QString& program, const QStringList& ar } else { - QMessageBox::warning(nullptr, - "Script execution", - "An Octave process is still running. Please stop this process before executing a new script."); + //QMessageBox::warning(nullptr, + // "Script execution", + // "An Octave process is still running. Please stop this process before executing a new script."); return false; } } @@ -1953,221 +993,6 @@ bool RiaApplication::launchProcessForMultipleCases(const QString& progr return launchProcess(m_currentProgram, m_currentArguments); } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -RiaPreferences* RiaApplication::preferences() -{ - return m_preferences; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiaApplication::applyPreferences(const RiaPreferences* oldPreferences) -{ - if (m_activeReservoirView && m_activeReservoirView->viewer()) - { - m_activeReservoirView->viewer()->updateNavigationPolicy(); - m_activeReservoirView->viewer()->enablePerfInfoHud(m_preferences->showHud()); - } - - if (useShaders()) - { - caf::EffectGenerator::setRenderingMode(caf::EffectGenerator::SHADER_BASED); - } - else - { - caf::EffectGenerator::setRenderingMode(caf::EffectGenerator::FIXED_FUNCTION); - } - - if (m_mainWindow && m_mainWindow->projectTreeView()) - { - m_mainWindow->projectTreeView()->enableAppendOfClassNameToUiItemText(m_preferences->appendClassNameToUiText()); - if (mainPlotWindow()) - mainPlotWindow()->projectTreeView()->enableAppendOfClassNameToUiItemText(m_preferences->appendClassNameToUiText()); - } - - // The creation of a font is time consuming, so make sure you really need your own font - // instead of using the application font - std::map fontSizes = m_preferences->defaultFontSizes(); - - m_defaultSceneFont = RiaFontCache::getFont(fontSizes[RiaDefines::SCENE_FONT]); - m_defaultAnnotationFont = RiaFontCache::getFont(fontSizes[RiaDefines::ANNOTATION_FONT]); - m_defaultWellLabelFont = RiaFontCache::getFont(fontSizes[RiaDefines::WELL_LABEL_FONT]); - - if (this->project()) - { - this->project()->setScriptDirectories(m_preferences->scriptDirectories()); - this->project()->updateConnectedEditors(); - - RimWellPathCollection* wellPathCollection = this->project()->activeOilField()->wellPathCollection(); - - std::vector allViewWindows; - project()->descendantsIncludingThisOfType(allViewWindows); - - bool existingViewsWithDifferentMeshLines = false; - bool existingViewsWithCustomColors = false; - bool existingViewsWithCustomZScale = false; - bool existingObjectsWithCustomFonts = false; - if (oldPreferences) - { - for (auto viewWindow : allViewWindows) - { - auto rim3dView = dynamic_cast(viewWindow); - if (rim3dView) - { - if (rim3dView->meshMode() != oldPreferences->defaultMeshModeType()) - { - existingViewsWithDifferentMeshLines = true; - } - if (rim3dView->backgroundColor() != oldPreferences->defaultViewerBackgroundColor()) - { - existingViewsWithCustomColors = true; - } - if (rim3dView->scaleZ() != static_cast(oldPreferences->defaultScaleFactorZ)) - { - existingViewsWithCustomZScale = true; - } - - RimGridView* gridView = dynamic_cast(rim3dView); - if (gridView && gridView->annotationCollection()) - { - RiaFontCache::FontSize oldFontSize = oldPreferences->defaultAnnotationFontSize(); - existingObjectsWithCustomFonts = gridView->annotationCollection()->hasTextAnnotationsWithCustomFontSize(oldFontSize); - } - RimEclipseView* eclipseView = dynamic_cast(rim3dView); - if (eclipseView) - { - if (eclipseView->wellCollection()->wellLabelColor() != oldPreferences->defaultWellLabelColor()) - { - existingViewsWithCustomColors = true; - } - } - } - - for (auto fontTypeSizePair : fontSizes) - { - RiaFontCache::FontSize oldFontSizeEnum = oldPreferences->defaultFontSizes()[fontTypeSizePair.first]; - if (oldFontSizeEnum != fontTypeSizePair.second) - { - int oldFontSize = RiaFontCache::pointSizeFromFontSizeEnum(oldFontSizeEnum); - if (viewWindow->hasCustomFontSizes(fontTypeSizePair.first, oldFontSize)) - { - existingObjectsWithCustomFonts = true; - } - } - } - } - - if (oldPreferences->defaultWellLabelColor() != wellPathCollection->wellPathLabelColor()) - { - existingViewsWithCustomColors = true; - } - } - - bool applySettingsToAllViews = false; - if (existingViewsWithCustomColors || existingViewsWithCustomZScale || - existingViewsWithDifferentMeshLines || existingObjectsWithCustomFonts) - { - QStringList changedData; - if (existingViewsWithDifferentMeshLines) changedData << "Mesh Visibility"; - if (existingViewsWithCustomColors) changedData << "Colors"; - if (existingViewsWithCustomZScale) changedData << "Z-Scale"; - if (existingObjectsWithCustomFonts) changedData << "Fonts Sizes"; - - QString listString = changedData.takeLast(); - if (!changedData.empty()) - { - listString = changedData.join(", ") + " and " + listString; - } - - QMessageBox::StandardButton reply; - reply = QMessageBox::question(m_mainWindow, - QString("Apply %1 to Existing Views or Plots?").arg(listString), - QString("You have changed default %1 and have existing views or plots with different settings.\n").arg(listString) + - QString("Do you want to apply the new default settings to all existing views?"), - QMessageBox::Ok | QMessageBox::Cancel); - applySettingsToAllViews = (reply == QMessageBox::Ok); - } - - for (auto viewWindow : allViewWindows) - { - for (auto fontTypeSizePair : fontSizes) - { - RiaFontCache::FontSize oldFontSizeEnum = oldPreferences->defaultFontSizes()[fontTypeSizePair.first]; - if (oldFontSizeEnum != fontTypeSizePair.second) - { - int oldFontSize = RiaFontCache::pointSizeFromFontSizeEnum(oldFontSizeEnum); - int newFontSize = RiaFontCache::pointSizeFromFontSizeEnum(fontTypeSizePair.second); - viewWindow->applyFontSize(fontTypeSizePair.first, oldFontSize, newFontSize, applySettingsToAllViews); - } - - } - - auto rim3dView = dynamic_cast(viewWindow); - if (rim3dView) - { - if (oldPreferences && (applySettingsToAllViews || rim3dView->meshMode() == oldPreferences->defaultMeshModeType())) - { - rim3dView->meshMode = m_preferences->defaultMeshModeType(); - } - - if (oldPreferences && (applySettingsToAllViews || rim3dView->backgroundColor() == oldPreferences->defaultViewerBackgroundColor())) - { - rim3dView->setBackgroundColor(m_preferences->defaultViewerBackgroundColor()); - rim3dView->applyBackgroundColorAndFontChanges(); - } - - if (oldPreferences && (applySettingsToAllViews || rim3dView->scaleZ == static_cast(oldPreferences->defaultScaleFactorZ()))) - { - rim3dView->scaleZ = static_cast(m_preferences->defaultScaleFactorZ()); - rim3dView->updateScaling(); - if (rim3dView == activeViewWindow()) - { - RiuMainWindow::instance()->updateScaleValue(); - } - } - - RimEclipseView* eclipseView = dynamic_cast(rim3dView); - if (eclipseView) - { - if (oldPreferences && (applySettingsToAllViews || eclipseView->wellCollection()->wellLabelColor() == oldPreferences->defaultWellLabelColor())) - { - eclipseView->wellCollection()->wellLabelColor = m_preferences->defaultWellLabelColor(); - } - eclipseView->scheduleReservoirGridGeometryRegen(); - } - rim3dView->scheduleCreateDisplayModelAndRedraw(); - } - } - - if (oldPreferences) - { - bool matchingColor = wellPathCollection->wellPathLabelColor() == oldPreferences->defaultWellLabelColor(); - if (applySettingsToAllViews || matchingColor) - { - wellPathCollection->wellPathLabelColor = oldPreferences->defaultWellLabelColor(); - } - - if (oldPreferences->defaultPlotFontSize() != m_preferences->defaultPlotFontSize()) - { - m_mainWindow->applyFontSizesToDockedPlots(); - } - } - - std::vector uiEditorsToUpdate; - caf::SelectionManager::instance()->selectedItems(uiEditorsToUpdate); - - for (caf::PdmUiItem* uiItem : uiEditorsToUpdate) - { - uiItem->updateConnectedEditors(); - } - } - - caf::PdmUiItem::enableExtraDebugText(m_preferences->appendFieldKeywordToToolTipText()); -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -2194,210 +1019,48 @@ void RiaApplication::waitForProcess() const #else usleep(100000); #endif - processEvents(); + QCoreApplication::processEvents(); } } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiaPreferences* RiaApplication::preferences() +{ + return m_preferences; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QString RiaApplication::lastUsedDialogDirectory(const QString& dialogName) -{ - QString lastUsedDirectory = m_startupDefaultDirectory; - - auto it = m_fileDialogDefaultDirectories.find(dialogName); - if (it != m_fileDialogDefaultDirectories.end()) - { - lastUsedDirectory = it->second; - } - - return lastUsedDirectory; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -QString RiaApplication::lastUsedDialogDirectoryWithFallback(const QString& dialogName, const QString& fallbackDirectory) -{ - QString lastUsedDirectory = m_startupDefaultDirectory; - if (!fallbackDirectory.isEmpty()) - { - lastUsedDirectory = fallbackDirectory; - } - - auto it = m_fileDialogDefaultDirectories.find(dialogName); - if (it != m_fileDialogDefaultDirectories.end()) - { - lastUsedDirectory = it->second; - } - - return lastUsedDirectory; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -QString RiaApplication::lastUsedDialogDirectoryWithFallbackToProjectFolder(const QString& dialogName) -{ - return lastUsedDialogDirectoryWithFallback(dialogName, currentProjectPath()); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiaApplication::setLastUsedDialogDirectory(const QString& dialogName, const QString& directory) -{ - m_fileDialogDefaultDirectories[dialogName] = directory; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool RiaApplication::openFile(const QString& fileName) -{ - if (!caf::Utils::fileExists(fileName)) return false; - - bool loadingSucceded = false; - - QString lastUsedDialogTag; - - RiaDefines::ImportFileType fileType = RiaDefines::obtainFileTypeFromFileName(fileName); - - if (fileType == RiaDefines::RESINSIGHT_PROJECT_FILE) - { - loadingSucceded = loadProject(fileName); - } - else if (fileType == RiaDefines::GEOMECH_ODB_FILE) - { - loadingSucceded = openOdbCaseFromFile(fileName); - if (loadingSucceded) lastUsedDialogTag = "GEOMECH_MODEL"; - } - else if ( fileType & RiaDefines::ANY_ECLIPSE_FILE) - { - loadingSucceded = RicImportGeneralDataFeature::openEclipseFilesFromFileNames(QStringList{ fileName }); - if (loadingSucceded) - { - lastUsedDialogTag = RiaDefines::defaultDirectoryLabel(fileType); - - if (fileType & RiaDefines::ECLIPSE_SUMMARY_FILE) - { - getOrCreateAndShowMainPlotWindow(); - } - } - } - - if (loadingSucceded) - { - if (!lastUsedDialogTag.isEmpty()) - { - RiaApplication::instance()->setLastUsedDialogDirectory(lastUsedDialogTag, QFileInfo(fileName).absolutePath()); - } - if (!RiaApplication::hasValidProjectFileExtension(fileName)) - { - caf::PdmUiModelChangeDetector::instance()->setModelChanged(); - } - } - - return loadingSucceded; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiaApplication::runMultiCaseSnapshots(const QString& templateProjectFileName, - std::vector gridFileNames, - const QString& snapshotFolderName) -{ - if (!m_mainWindow) return; - - m_mainWindow->hideAllDockWindows(); - - const size_t numGridFiles = gridFileNames.size(); - for (size_t i = 0; i < numGridFiles; i++) - { - QString gridFn = gridFileNames[i]; - - RiaProjectModifier modifier; - modifier.setReplaceCaseFirstOccurrence(gridFn); - - bool loadOk = loadProject(templateProjectFileName, PLA_NONE, &modifier); - if (loadOk) - { - RicSnapshotAllViewsToFileFeature::exportSnapshotOfAllViewsIntoFolder(snapshotFolderName); - } - } - - m_mainWindow->loadWinGeoAndDockToolBarLayout(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -cvf::Font* RiaApplication::defaultSceneFont() -{ - CVF_ASSERT(m_defaultSceneFont.notNull()); - +void RiaApplication::applyPreferences(const RiaPreferences* oldPreferences) +{ // The creation of a font is time consuming, so make sure you really need your own font // instead of using the application font + std::map fontSizes = m_preferences->defaultFontSizes(); - return m_defaultSceneFont.p(); + m_defaultSceneFont = RiaFontCache::getFont(fontSizes[RiaDefines::SCENE_FONT]); + m_defaultAnnotationFont = RiaFontCache::getFont(fontSizes[RiaDefines::ANNOTATION_FONT]); + m_defaultWellLabelFont = RiaFontCache::getFont(fontSizes[RiaDefines::WELL_LABEL_FONT]); + + if (this->project()) + { + this->project()->setScriptDirectories(m_preferences->scriptDirectories()); + this->project()->updateConnectedEditors(); + } } + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -cvf::Font* RiaApplication::defaultAnnotationFont() +QString RiaApplication::commandLineParameterHelp() { - CVF_ASSERT(m_defaultAnnotationFont.notNull()); - - return m_defaultAnnotationFont.p(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -cvf::Font* RiaApplication::defaultWellLabelFont() -{ - CVF_ASSERT(m_defaultWellLabelFont.notNull()); - - return m_defaultWellLabelFont.p(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -RimProject* RiaApplication::project() -{ - return m_project; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiaApplication::showFormattedTextInMessageBox(const QString& text) -{ - QString helpText = text; - - QMessageBox msgBox; - msgBox.setIcon(QMessageBox::Information); - msgBox.setWindowTitle("ResInsight"); - - helpText.replace("&", "&"); - helpText.replace("<", "<"); - helpText.replace(">", ">"); - - helpText = QString("
%1
").arg(helpText); - msgBox.setText(helpText); - - msgBox.exec(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -QString RiaApplication::commandLineParameterHelp() const -{ - return m_helpText; + QString helpText = QString("\n%1 v. %2\n").arg(RI_APPLICATION_NAME).arg(RiaApplication::getVersionStringApp(false)); + helpText += "Copyright Equinor ASA, Ceetron Solution AS, Ceetron AS\n\n"; + return helpText; } //-------------------------------------------------------------------------------------------------- @@ -2423,6 +1086,23 @@ QVariant RiaApplication::cacheDataObject(const QString& key) const return QVariant(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaApplication::executeCommandFile(const QString& commandFile) +{ + QFile file(commandFile); + RicfMessages messages; + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) + { + // TODO : Error logging? + return; + } + + QTextStream in(&file); + RicfCommandFileExecutor::instance()->executeCommands(in); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -2476,7 +1156,161 @@ void RiaApplication::executeCommandObjects() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RiaApplication::setHelpText(const QString& helpText) +void RiaApplication::waitUntilCommandObjectsHasBeenProcessed() { - m_helpText = helpText; + // Wait until all command objects have completed + bool mutexLockedSuccessfully = m_commandQueueLock.tryLock(); + + while (!mutexLockedSuccessfully) + { + handleEvents(); + + mutexLockedSuccessfully = m_commandQueueLock.tryLock(); + } + m_commandQueueLock.unlock(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +int RiaApplication::launchUnitTests() +{ +#ifdef USE_UNIT_TESTS + + caf::ProgressInfoBlocker progressBlocker; + cvf::Assert::setReportMode(cvf::Assert::CONSOLE); + +#if QT_VERSION < 0x050000 + int argc = QCoreApplication::argc(); + char** argv = QCoreApplication::argv(); +#else + int argc = QCoreApplication::arguments().size(); + QStringList arguments = QCoreApplication::arguments(); + std::vector argumentsStd; + for (QString qstring : arguments) + { + argumentsStd.push_back(qstring.toStdString()); + } + std::vector argVector; + for (std::string& string : argumentsStd) + { + argVector.push_back(&string.front()); + } + char** argv = argVector.data(); +#endif + + testing::InitGoogleTest(&argc, argv); + + // Use this macro in main() to run all tests. It returns 0 if all + // tests are successful, or 1 otherwise. + // + // RUN_ALL_TESTS() should be invoked after the command line has been + // parsed by InitGoogleTest(). + + return RUN_ALL_TESTS(); + +#else + return -1; +#endif +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +const QString RiaApplication::startDir() const +{ + return m_startupDefaultDirectory; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaApplication::setStartDir(const QString& startDir) +{ + m_startupDefaultDirectory = startDir; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RiaApplication::readFileListFromTextFile(QString listFileName) +{ + std::vector fileList; + + QFile file(listFileName); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) + { + return fileList; + } + + QTextStream in(&file); + QString line = in.readLine(); + while (!line.isNull()) + { + line = line.trimmed(); + if (!line.isEmpty()) + { + fileList.push_back(line); + } + + line = in.readLine(); + } + + return fileList; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::Font* RiaApplication::defaultSceneFont() +{ + CVF_ASSERT(m_defaultSceneFont.notNull()); + + // The creation of a font is time consuming, so make sure you really need your own font + // instead of using the application font + + return m_defaultSceneFont.p(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::Font* RiaApplication::defaultAnnotationFont() +{ + CVF_ASSERT(m_defaultAnnotationFont.notNull()); + + return m_defaultAnnotationFont.p(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::Font* RiaApplication::defaultWellLabelFont() +{ + CVF_ASSERT(m_defaultWellLabelFont.notNull()); + + return m_defaultWellLabelFont.p(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaApplication::initialize() +{ + m_preferences = new RiaPreferences; + caf::PdmSettings::readFieldsFromApplicationStore(m_preferences); + + applyPreferences(nullptr); + + // Start with a project + m_project = new RimProject; + m_project->initScriptDirectories(m_preferences->scriptDirectories()); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +int RiaApplication::launchUnitTestsWithConsole() +{ + return launchUnitTests(); } diff --git a/ApplicationCode/Application/RiaApplication.h b/ApplicationCode/Application/RiaApplication.h index 4efbe370d5..7b69dbe5f5 100644 --- a/ApplicationCode/Application/RiaApplication.h +++ b/ApplicationCode/Application/RiaApplication.h @@ -3,34 +3,34 @@ // Copyright (C) 2011- Statoil ASA // Copyright (C) 2013- Ceetron Solutions AS // Copyright (C) 2011-2012 Ceetron AS -// +// // 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 +// +// See the GNU General Public License at // for more details. // -///////////////////////////////////////////////////////////////////////////////// - +////////////////////////////////////////////////////////////////////////////////// #pragma once -#include -#include -#include +#include "RiaDefines.h" -#include "cafPdmObject.h" #include "cafPdmField.h" +#include "cafPdmObject.h" #include "cvfBase.h" -#include "cvfObject.h" #include "cvfFont.h" +#include "cvfObject.h" -#include "RiaFontCache.h" +#include +#include +#include +#include #include #include @@ -66,210 +66,164 @@ class RiaArgumentParser; namespace caf { - class UiProcess; +class UiProcess; +} + +namespace cvf +{ +class ProgramOptions; } //================================================================================================== -// -// -// +/// Base class for all ResInsight applications. I.e. console and GUI +/// //================================================================================================== -class RiaApplication : public QApplication +class RiaApplication { - Q_OBJECT - public: - enum RINavigationPolicy - { - NAVIGATION_POLICY_CEETRON, - NAVIGATION_POLICY_CAD, - NAVIGATION_POLICY_GEOQUEST, - NAVIGATION_POLICY_RMS - }; - enum ProjectLoadAction { - PLA_NONE = 0, + PLA_NONE = 0, PLA_CALCULATE_STATISTICS = 1 }; - typedef RiaFontCache::FontSize FontSize; + enum ApplicationStatus + { + KEEP_GOING = 0, + EXIT_COMPLETED, + EXIT_WITH_ERROR + }; public: - RiaApplication(int& argc, char** argv); - ~RiaApplication() override; + static RiaApplication* instance(); + RiaApplication(); + virtual ~RiaApplication(); + + static const char* getVersionStringApp(bool includeCrtInfo); + static bool enableDevelopmentFeatures(); - static RiaApplication* instance(); + void setActiveReservoirView(Rim3dView*); + Rim3dView* activeReservoirView(); + const Rim3dView* activeReservoirView() const; + RimGridView* activeGridView(); - int parseArgumentsAndRunUnitTestsIfRequested(); - bool parseArguments(); + RimProject* project(); - void setActiveReservoirView(Rim3dView*); - Rim3dView* activeReservoirView(); - const Rim3dView* activeReservoirView() const; - RimGridView* activeGridView(); + void createMockModel(); + void createResultsMockModel(); + void createLargeResultsMockModel(); + void createMockModelCustomized(); + void createInputMockModel(); - RimViewWindow* activePlotWindow() const; + bool openFile(const QString& fileName); - RimProject* project(); + QString currentProjectPath() const; + QString createAbsolutePathFromProjectRelativePath(QString projectRelativePath); + bool loadProject(const QString& projectFileName); + bool loadProject(const QString& projectFileName, ProjectLoadAction loadAction, RiaProjectModifier* projectModifier); + bool saveProjectAs(const QString& fileName, QString* errorMessage); + static bool hasValidProjectFileExtension(const QString& fileName); + void closeProject(); - void createMockModel(); - void createResultsMockModel(); - void createLargeResultsMockModel(); - void createMockModelCustomized(); - void createInputMockModel(); + QString lastUsedDialogDirectory(const QString& dialogName); + QString lastUsedDialogDirectoryWithFallbackToProjectFolder(const QString& dialogName); + QString lastUsedDialogDirectoryWithFallback(const QString& dialogName, const QString& fallbackDirectory); + void setLastUsedDialogDirectory(const QString& dialogName, const QString& directory); - QString lastUsedDialogDirectory(const QString& dialogName); - QString lastUsedDialogDirectoryWithFallbackToProjectFolder(const QString& dialogName); - QString lastUsedDialogDirectoryWithFallback(const QString& dialogName, const QString& fallbackDirectory); - void setLastUsedDialogDirectory(const QString& dialogName, const QString& directory); + bool openOdbCaseFromFile(const QString& fileName, bool applyTimeStepFilter = false); - bool openFile(const QString& fileName); + void addWellPathsToModel(QList wellPathFilePaths); + void addWellPathFormationsToModel(QList wellPathFilePaths); + void addWellLogsToModel(const QList& wellLogFilePaths); - bool openOdbCaseFromFile(const QString& fileName, bool applyTimeStepFilter = false); + QString scriptDirectories() const; + QString scriptEditorPath() const; - QString currentProjectPath() const; - QString createAbsolutePathFromProjectRelativePath(QString projectRelativePath); - bool loadProject(const QString& projectFileName); - bool loadProject(const QString& projectFileName, ProjectLoadAction loadAction, RiaProjectModifier* projectModifier); - bool saveProject(); - bool saveProjectAs(const QString& fileName); - bool saveProjectPromptForFileName(); - static bool hasValidProjectFileExtension(const QString& fileName); - - bool askUserToSaveModifiedProject(); - void closeProject(); - - void addWellPathsToModel(QList wellPathFilePaths); - void addWellPathFormationsToModel(QList wellPathFilePaths); - void addWellLogsToModel(const QList& wellLogFilePaths); + QString octavePath() const; + QStringList octaveArguments() const; - void runMultiCaseSnapshots(const QString& templateProjectFileName, std::vector gridFileNames, const QString& snapshotFolderName); + bool launchProcess(const QString& program, const QStringList& arguments); + bool launchProcessForMultipleCases(const QString& program, const QStringList& arguments, const std::vector& caseIds); + void terminateProcess(); + void waitForProcess() const; - void processNonGuiEvents(); + RiaPreferences* preferences(); + void applyPreferences(const RiaPreferences* oldPreferences = nullptr); - static const char* getVersionStringApp(bool includeCrtInfo); + static QString commandLineParameterHelp(); - bool useShaders() const; + void setCacheDataObject(const QString& key, const QVariant& dataObject); + QVariant cacheDataObject(const QString& key) const; - bool showPerformanceInfo() const; + void executeCommandFile(const QString& commandFile); + void addCommandObject(RimCommandObject* commandObject); + void executeCommandObjects(); + void waitUntilCommandObjectsHasBeenProcessed(); - RINavigationPolicy navigationPolicy() const; - QString scriptDirectories() const; - QString scriptEditorPath() const; - - QString octavePath() const; - QStringList octaveArguments() const; + int launchUnitTests(); - bool launchProcess(const QString& program, const QStringList& arguments); - bool launchProcessForMultipleCases(const QString& program, const QStringList& arguments, const std::vector& caseIds); - void terminateProcess(); - void waitForProcess() const; - - RiaPreferences* preferences(); - void applyPreferences(const RiaPreferences* oldPreferences = nullptr); - - cvf::Font* defaultSceneFont(); - cvf::Font* defaultAnnotationFont(); - cvf::Font* defaultWellLabelFont(); - - QString commandLineParameterHelp() const; - void showFormattedTextInMessageBox(const QString& text); - - void setCacheDataObject(const QString& key, const QVariant& dataObject); - QVariant cacheDataObject(const QString& key) const; - - void addCommandObject(RimCommandObject* commandObject); - void executeCommandObjects(); - - int launchUnitTests(); - int launchUnitTestsWithConsole(); - - RiuMainWindow* getOrCreateAndShowMainWindow(); - RiuMainWindow* mainWindow(); - - RiuPlotMainWindow* getOrCreateMainPlotWindow(); - RiuPlotMainWindow* getOrCreateAndShowMainPlotWindow(); - RiuPlotMainWindow* mainPlotWindow(); - RiuMainWindowBase* mainWindowByID(int mainWindowID); - - static RimViewWindow* activeViewWindow(); - - bool isMain3dWindowVisible() const; - bool isMainPlotWindowVisible() const; - - void closeMainWindowIfOpenButHidden(); - void closeMainPlotWindowIfOpenButHidden(); - - void addToRecentFiles(const QString& fileName); - std::vector recentFileActions() const; - - void setStartDir(const QString& startDir); + const QString startDir() const; + void setStartDir(const QString& startDir); static std::vector readFileListFromTextFile(QString listFileName); - void waitUntilCommandObjectsHasBeenProcessed(); - void saveMainWinGeoAndDockToolBarLayout(); - void savePlotWinGeoAndDockToolBarLayout(); + cvf::Font* defaultSceneFont(); + cvf::Font* defaultAnnotationFont(); + cvf::Font* defaultWellLabelFont(); - static bool enableDevelopmentFeatures(); - static void clearAllSelections(); + // Public implementation specific overrides + virtual void initialize(); + virtual ApplicationStatus handleArguments(cvf::ProgramOptions* progOpt) = 0; + virtual int launchUnitTestsWithConsole(); + virtual void addToRecentFiles(const QString& fileName) {} + virtual void showInformationMessage(const QString& infoText) = 0; + virtual void showErrorMessage(const QString& errMsg) = 0; + virtual void cleanupBeforeProgramExit() {} -private: - void onProjectOpenedOrClosed(); - void setWindowCaptionFromAppState(); +protected: + // Protected implementation specific overrides + virtual void handleEvents(QEventLoop::ProcessEventsFlags flags = QEventLoop::AllEvents) = 0; + virtual void onChangedActiveReservoirView() {} + virtual void onFileSuccessfullyLoaded(const QString& fileName, RiaDefines::ImportFileType fileType) {} + virtual void onProjectBeingOpened() {} + virtual void onProjectOpened() = 0; + virtual void onProjectOpeningError(const QString& errMsg) = 0; + virtual void onProjectBeingClosed() {} + virtual void onProjectClosed() = 0; + virtual void startMonitoringWorkProgress(caf::UiProcess* uiProcess) {} + virtual void stopMonitoringWorkProgress() {} - void createMainWindow(); - void deleteMainWindow(); +protected: + cvf::ref m_defaultSceneFont; + cvf::ref m_defaultAnnotationFont; + cvf::ref m_defaultWellLabelFont; - void createMainPlotWindow(); - void deleteMainPlotWindow(); - - void loadAndUpdatePlotData(); - - void storeTreeViewState(); + caf::PdmPointer m_activeReservoirView; + caf::PdmPointer m_project; - friend RiaArgumentParser; - void setHelpText(const QString& helpText); - - bool notify(QObject *, QEvent *) override; - -private slots: - void slotWorkerProcessFinished(int exitCode, QProcess::ExitStatus exitStatus); - -private: - caf::PdmPointer m_activeReservoirView; - caf::PdmPointer m_project; - - RiaSocketServer* m_socketServer; - - caf::UiProcess* m_workerProcess; + RiaSocketServer* m_socketServer; + caf::UiProcess* m_workerProcess; // Execute for all settings - std::list m_currentCaseIds; - QString m_currentProgram; - QStringList m_currentArguments; + std::list m_currentCaseIds; + QString m_currentProgram; + QStringList m_currentArguments; - RiaPreferences* m_preferences; + RiaPreferences* m_preferences; - std::map m_fileDialogDefaultDirectories; - QString m_startupDefaultDirectory; + std::map m_fileDialogDefaultDirectories; + QString m_startupDefaultDirectory; - cvf::ref m_defaultSceneFont; - cvf::ref m_defaultAnnotationFont; - cvf::ref m_defaultWellLabelFont; + QMap m_sessionCache; // Session cache used to store username/passwords per session - QMap m_sessionCache; // Session cache used to store username/passwords per session + std::list m_commandQueue; + QMutex m_commandQueueLock; - std::list m_commandQueue; - QMutex m_commandQueueLock; + bool m_runningWorkerProcess; - QString m_helpText; - - bool m_runningWorkerProcess; - - RiuMainWindow* m_mainWindow; - RiuPlotMainWindow* m_mainPlotWindow; - - std::unique_ptr m_recentFileActionProvider; +private: + static RiaApplication* s_riaApplication; }; + + + diff --git a/ApplicationCode/Application/RiaConsoleApplication.cpp b/ApplicationCode/Application/RiaConsoleApplication.cpp new file mode 100644 index 0000000000..aa52cba81a --- /dev/null +++ b/ApplicationCode/Application/RiaConsoleApplication.cpp @@ -0,0 +1,366 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 "RiaConsoleApplication.h" + +#include "RiaArgumentParser.h" +#include "RiaLogging.h" +#include "RiaPreferences.h" +#include "RiaProjectModifier.h" +#include "RiaSocketServer.h" + +#include "RicImportGeneralDataFeature.h" + +#include "cvfProgramOptions.h" +#include "cvfqtUtils.h" + +#include + +#ifdef WIN32 +#include +#endif + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiaConsoleApplication* RiaConsoleApplication::instance() +{ + RiaConsoleApplication* currentConsoleApp = dynamic_cast(RiaApplication::instance()); + CAF_ASSERT(currentConsoleApp && "Should never be called from a method that isn't within the Console context"); + return currentConsoleApp; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiaConsoleApplication::RiaConsoleApplication(int& argc, char** argv) + : QCoreApplication(argc, argv) + , RiaApplication() +{ + installEventFilter(this); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiaConsoleApplication::~RiaConsoleApplication() +{ + RiaLogging::deleteLoggerInstance(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaConsoleApplication::initialize() +{ +#ifdef _WIN32 +#pragma warning(push) // Saves the current warning state. +#pragma warning(disable : 4996) // Temporarily disables warning 4996. + if (AttachConsole(ATTACH_PARENT_PROCESS) || AllocConsole()) + { + freopen("CONOUT$", "w", stdout); + freopen("CONOUT$", "w", stderr); + } +#pragma warning(pop) +#endif + + RiaApplication::initialize(); + + RiaLogging::setLoggerInstance(new RiaStdOutLogger); + RiaLogging::loggerInstance()->setLevel(RI_LL_DEBUG); + + m_socketServer = new RiaSocketServer(this); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiaApplication::ApplicationStatus RiaConsoleApplication::handleArguments(cvf::ProgramOptions* progOpt) +{ + CVF_ASSERT(progOpt); + + // Handling of the actual command line options + // -------------------------------------------------------- + if (cvf::Option o = progOpt->option("ignoreArgs")) + { + return KEEP_GOING; + } + + // Unit testing + // -------------------------------------------------------- + if (cvf::Option o = progOpt->option("unittest")) + { + int testReturnValue = launchUnitTestsWithConsole(); + + return testReturnValue == 0 ? RiaApplication::EXIT_COMPLETED : RiaApplication::EXIT_WITH_ERROR; + } + + if (cvf::Option o = progOpt->option("startdir")) + { + CVF_ASSERT(o.valueCount() == 1); + setStartDir(cvfqt::Utils::toQString(o.value(0))); + } + + QString projectFileName; + + if (progOpt->hasOption("last")) + { + projectFileName = preferences()->lastUsedProjectFileName; + } + + if (cvf::Option o = progOpt->option("project")) + { + CVF_ASSERT(o.valueCount() == 1); + projectFileName = cvfqt::Utils::toQString(o.value(0)); + } + + if (!projectFileName.isEmpty()) + { + cvf::ref projectModifier; + RiaApplication::ProjectLoadAction projectLoadAction = RiaApplication::PLA_NONE; + + if (cvf::Option o = progOpt->option("replaceCase")) + { + if (projectModifier.isNull()) projectModifier = new RiaProjectModifier; + + if (o.valueCount() == 1) + { + // One argument is available, use replace case for first occurrence in the project + + QString gridFileName = cvfqt::Utils::toQString(o.safeValue(0)); + projectModifier->setReplaceCaseFirstOccurrence(gridFileName); + } + else + { + size_t optionIdx = 0; + while (optionIdx < o.valueCount()) + { + const int caseId = o.safeValue(optionIdx++).toInt(-1); + QString gridFileName = cvfqt::Utils::toQString(o.safeValue(optionIdx++)); + + if (caseId != -1 && !gridFileName.isEmpty()) + { + projectModifier->setReplaceCase(caseId, gridFileName); + } + } + } + } + + if (cvf::Option o = progOpt->option("replaceSourceCases")) + { + if (projectModifier.isNull()) projectModifier = new RiaProjectModifier; + + if (o.valueCount() == 1) + { + // One argument is available, use replace case for first occurrence in the project + + std::vector gridFileNames = readFileListFromTextFile(cvfqt::Utils::toQString(o.safeValue(0))); + projectModifier->setReplaceSourceCasesFirstOccurrence(gridFileNames); + } + else + { + size_t optionIdx = 0; + while (optionIdx < o.valueCount()) + { + const int groupId = o.safeValue(optionIdx++).toInt(-1); + std::vector gridFileNames = + readFileListFromTextFile(cvfqt::Utils::toQString(o.safeValue(optionIdx++))); + + if (groupId != -1 && !gridFileNames.empty()) + { + projectModifier->setReplaceSourceCasesById(groupId, gridFileNames); + } + } + } + + projectLoadAction = RiaApplication::PLA_CALCULATE_STATISTICS; + } + + if (cvf::Option o = progOpt->option("replacePropertiesFolder")) + { + if (projectModifier.isNull()) projectModifier = new RiaProjectModifier; + + if (o.valueCount() == 1) + { + QString propertiesFolder = cvfqt::Utils::toQString(o.safeValue(0)); + projectModifier->setReplacePropertiesFolderFirstOccurrence(propertiesFolder); + } + else + { + size_t optionIdx = 0; + while (optionIdx < o.valueCount()) + { + const int caseId = o.safeValue(optionIdx++).toInt(-1); + QString propertiesFolder = cvfqt::Utils::toQString(o.safeValue(optionIdx++)); + + if (caseId != -1 && !propertiesFolder.isEmpty()) + { + projectModifier->setReplacePropertiesFolder(caseId, propertiesFolder); + } + } + } + } + + loadProject(projectFileName, projectLoadAction, projectModifier.p()); + } + + if (cvf::Option o = progOpt->option("case")) + { + QStringList caseNames = cvfqt::Utils::toQStringList(o.values()); + RicImportGeneralDataFeature::OpenCaseResults results = + RicImportGeneralDataFeature::openEclipseFilesFromFileNames(caseNames); + } + + if (cvf::Option o = progOpt->option("commandFile")) + { + QString commandFile = cvfqt::Utils::toQString(o.safeValue(0)); + if (!progOpt->hasOption("startdir")) + { + QFileInfo commandFileInfo(commandFile); + QString commandDir = commandFileInfo.absolutePath(); + setStartDir(commandDir); + } + + cvf::Option projectOption = progOpt->option("commandFileProject"); + cvf::Option caseOption = progOpt->option("commandFileReplaceCases"); + if (projectOption && caseOption) + { + projectFileName = cvfqt::Utils::toQString(projectOption.value(0)); + + std::vector caseIds; + std::vector caseListFiles; + + if (caseOption.valueCount() == 1) + { + caseListFiles.push_back(cvfqt::Utils::toQString(caseOption.safeValue(0))); + } + else + { + size_t optionIdx = 0; + while (optionIdx < caseOption.valueCount()) + { + const int caseId = caseOption.safeValue(optionIdx++).toInt(-1); + QString caseListFile = cvfqt::Utils::toQString(caseOption.safeValue(optionIdx++)); + + if (caseId != -1 && !caseListFile.isEmpty()) + { + caseIds.push_back(caseId); + caseListFiles.push_back(caseListFile); + } + } + } + + if (caseIds.empty() && !caseListFiles.empty()) + { + QString caseListFile = caseListFiles[0]; + std::vector caseFiles = readFileListFromTextFile(caseListFile); + for (const QString& caseFile : caseFiles) + { + RiaProjectModifier projectModifier; + projectModifier.setReplaceCaseFirstOccurrence(caseFile); + loadProject(projectFileName, RiaApplication::PLA_NONE, &projectModifier); + executeCommandFile(commandFile); + } + } + else + { + CVF_ASSERT(caseIds.size() == caseListFiles.size()); + + std::vector> allCaseFiles; + size_t maxFiles = 0; + + for (size_t i = 0; i < caseIds.size(); ++i) + { + std::vector caseFiles = readFileListFromTextFile(caseListFiles[i]); + allCaseFiles.push_back(caseFiles); + maxFiles = std::max(caseFiles.size(), maxFiles); + } + + for (size_t i = 0; i < caseIds.size(); ++i) + { + RiaProjectModifier projectModifier; + for (size_t j = 0; j < maxFiles; ++j) + { + if (allCaseFiles[i].size() > j) + { + projectModifier.setReplaceCase(caseIds[i], allCaseFiles[i][j]); + } + } + + loadProject(projectFileName, RiaApplication::PLA_NONE, &projectModifier); + executeCommandFile(commandFile); + } + } + } + else + { + executeCommandFile(commandFile); + } + return EXIT_COMPLETED; + } + + return KEEP_GOING; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaConsoleApplication::showInformationMessage(const QString& text) +{ + RiaLogging::info(text); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaConsoleApplication::showErrorMessage(const QString& errMsg) +{ + RiaLogging::error(errMsg); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaConsoleApplication::handleEvents(QEventLoop::ProcessEventsFlags flags /*= QEventLoop::AllEvents*/) +{ + processEvents(flags); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaConsoleApplication::onProjectOpeningError(const QString& errMsg) +{ + showErrorMessage(errMsg); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaConsoleApplication::onProjectOpened() +{ + processEvents(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaConsoleApplication::onProjectClosed() +{ + processEvents(); +} + diff --git a/ApplicationCode/Application/RiaConsoleApplication.h b/ApplicationCode/Application/RiaConsoleApplication.h new file mode 100644 index 0000000000..ab7cf5565f --- /dev/null +++ b/ApplicationCode/Application/RiaConsoleApplication.h @@ -0,0 +1,52 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 "RiaApplication.h" + +#include + +namespace cvf +{ +class ProgramOptions; +} + +class RiaConsoleApplication : public QCoreApplication, public RiaApplication +{ + Q_OBJECT + +public: + static RiaConsoleApplication* instance(); + + RiaConsoleApplication(int& argc, char** argv); + ~RiaConsoleApplication() override; + + // Public RiaApplication overrides + void initialize() override; + ApplicationStatus handleArguments(cvf::ProgramOptions* progOpt) override; + void showInformationMessage(const QString& text) override; + void showErrorMessage(const QString& errMsg) override; + +protected: + // Protected implementation specific overrides + void handleEvents(QEventLoop::ProcessEventsFlags flags = QEventLoop::AllEvents) override; + void onProjectOpeningError(const QString& errMsg) override; + void onProjectOpened(); + void onProjectClosed(); +}; + diff --git a/ApplicationCode/Application/RiaFontCache.h b/ApplicationCode/Application/RiaFontCache.h index 2ee45ba949..dbd0b7e5fe 100644 --- a/ApplicationCode/Application/RiaFontCache.h +++ b/ApplicationCode/Application/RiaFontCache.h @@ -18,6 +18,7 @@ #pragma once +#include "cafFixedAtlasFont.h" #include "cvfBase.h" #include "cvfObject.h" @@ -25,7 +26,6 @@ namespace caf { -class FixedAtlasFont; template class AppEnum; } diff --git a/ApplicationCode/Application/RiaGuiApplication.cpp b/ApplicationCode/Application/RiaGuiApplication.cpp new file mode 100644 index 0000000000..b69a1facb0 --- /dev/null +++ b/ApplicationCode/Application/RiaGuiApplication.cpp @@ -0,0 +1,1708 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS +// +// 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 "RiaGuiApplication.h" + +#include "RiaArgumentParser.h" +#include "RiaBaseDefs.h" +#include "RiaColorTables.h" +#include "RiaFilePathTools.h" +#include "RiaFontCache.h" +#include "RiaImportEclipseCaseTools.h" +#include "RiaLogging.h" +#include "RiaPreferences.h" +#include "RiaProjectModifier.h" +#include "RiaRegressionTestRunner.h" +#include "RiaSocketServer.h" +#include "RiaVersionInfo.h" +#include "RiaViewRedrawScheduler.h" + +#include "ExportCommands/RicSnapshotAllPlotsToFileFeature.h" +#include "ExportCommands/RicSnapshotAllViewsToFileFeature.h" +#include "ExportCommands/RicSnapshotViewToFileFeature.h" +#include "HoloLensCommands/RicHoloLensSessionManager.h" +#include "RicImportGeneralDataFeature.h" + +#include "Rim2dIntersectionViewCollection.h" +#include "RimAnnotationCollection.h" +#include "RimAnnotationInViewCollection.h" +#include "RimAnnotationTextAppearance.h" +#include "RimCellRangeFilterCollection.h" +#include "RimCommandObject.h" +#include "RimEclipseCaseCollection.h" +#include "RimEclipseView.h" +#include "RimFlowPlotCollection.h" +#include "RimFormationNamesCollection.h" +#include "RimFractureTemplateCollection.h" +#include "RimGeoMechCase.h" +#include "RimGeoMechCellColors.h" +#include "RimGeoMechModels.h" +#include "RimGeoMechView.h" +#include "RimGridCrossPlot.h" +#include "RimGridCrossPlotCollection.h" +#include "RimIdenticalGridCaseGroup.h" +#include "RimMainPlotCollection.h" +#include "RimObservedData.h" +#include "RimObservedDataCollection.h" +#include "RimOilField.h" +#include "RimPltPlotCollection.h" +#include "RimProject.h" +#include "RimRftPlotCollection.h" +#include "RimSaturationPressurePlot.h" +#include "RimSaturationPressurePlotCollection.h" +#include "RimSimWellInViewCollection.h" +#include "RimStimPlanColors.h" +#include "RimSummaryCase.h" +#include "RimSummaryCaseCollection.h" +#include "RimSummaryCaseMainCollection.h" +#include "RimSummaryCrossPlotCollection.h" +#include "RimSummaryPlot.h" +#include "RimSummaryPlotCollection.h" +#include "RimTextAnnotation.h" +#include "RimTextAnnotationInView.h" +#include "RimViewLinker.h" +#include "RimViewLinkerCollection.h" +#include "RimWellLogFile.h" +#include "RimWellLogPlot.h" +#include "RimWellLogPlotCollection.h" +#include "RimWellPathCollection.h" +#include "RimWellPathFracture.h" +#include "RimWellPltPlot.h" +#include "RimWellRftPlot.h" + +#include "Riu3dSelectionManager.h" +#include "RiuDockWidgetTools.h" +#include "RiuMainWindow.h" +#include "RiuMdiMaximizeWindowGuard.h" +#include "RiuMessagePanel.h" +#include "RiuPlotMainWindow.h" +#include "RiuProcessMonitor.h" +#include "RiuRecentFileActionProvider.h" +#include "RiuViewer.h" + +#include "cafAppEnum.h" +#include "cafEffectGenerator.h" +#include "cafFixedAtlasFont.h" +#include "cafPdmSettings.h" +#include "cafPdmUiModelChangeDetector.h" +#include "cafPdmUiTreeView.h" +#include "cafProgressInfo.h" +#include "cafQTreeViewStateSerializer.h" +#include "cafSelectionManager.h" +#include "cafUiProcess.h" +#include "cafUtils.h" + +#include "cvfProgramOptions.h" +#include "cvfqtUtils.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifndef WIN32 +#include // for usleep +#endif // WIN32 + +#ifdef USE_UNIT_TESTS +#include "gtest/gtest.h" +#endif // USE_UNIT_TESTS + +namespace caf +{ +template<> +void AppEnum::setUp() +{ + addItem(RiaGuiApplication::NAVIGATION_POLICY_CEETRON, "NAVIGATION_POLICY_CEETRON", "Ceetron"); + addItem(RiaGuiApplication::NAVIGATION_POLICY_CAD, "NAVIGATION_POLICY_CAD", "CAD"); + addItem(RiaGuiApplication::NAVIGATION_POLICY_GEOQUEST, "NAVIGATION_POLICY_GEOQUEST", "GEOQUEST"); + addItem(RiaGuiApplication::NAVIGATION_POLICY_RMS, "NAVIGATION_POLICY_RMS", "RMS"); + setDefault(RiaGuiApplication::NAVIGATION_POLICY_RMS); +} +} // namespace caf + +//================================================================================================== +/// +/// \class RiaGuiApplication +/// +/// Application class +/// +//================================================================================================== + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RiaGuiApplication::isRunning() +{ + return dynamic_cast(RiaApplication::instance()) != nullptr; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiaGuiApplication* RiaGuiApplication::instance() +{ + RiaGuiApplication* currentGuiApp = dynamic_cast(RiaApplication::instance()); + CAF_ASSERT(currentGuiApp && "Should never be called from a method that isn't within the GUI context"); + return currentGuiApp; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiaGuiApplication::RiaGuiApplication(int& argc, char** argv) + : QApplication(argc, argv) + , RiaApplication() + , m_mainWindow(nullptr) + , m_mainPlotWindow(nullptr) +{ + // For idle processing + // m_idleTimerStarted = false; + installEventFilter(this); + + setWindowIcon(QIcon(":/AppLogo48x48.png")); + + m_recentFileActionProvider = std::unique_ptr(new RiuRecentFileActionProvider); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiaGuiApplication::~RiaGuiApplication() +{ + RiuDockWidgetTools::instance()->saveDockWidgetsState(); + + deleteMainPlotWindow(); + deleteMainWindow(); + + RiaLogging::deleteLoggerInstance(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RiaGuiApplication::saveProject() +{ + CVF_ASSERT(m_project.notNull()); + + if (!caf::Utils::fileExists(m_project->fileName())) + { + return saveProjectPromptForFileName(); + } + else + { + return saveProjectAs(m_project->fileName()); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RiaGuiApplication::saveProjectPromptForFileName() +{ + // if (m_project.isNull()) return true; + + RiaGuiApplication* app = RiaGuiApplication::instance(); + + QString startPath; + if (!m_project->fileName().isEmpty()) + { + startPath = m_project->fileName(); + } + else + { + startPath = app->lastUsedDialogDirectory("BINARY_GRID"); + startPath += "/ResInsightProject.rsp"; + } + + QString fileName = + QFileDialog::getSaveFileName(nullptr, tr("Save File"), startPath, tr("Project Files (*.rsp);;All files(*.*)")); + if (fileName.isEmpty()) + { + return false; + } + + // Remember the directory to next time + app->setLastUsedDialogDirectory("BINARY_GRID", QFileInfo(fileName).absolutePath()); + + bool bSaveOk = saveProjectAs(fileName); + + setWindowCaptionFromAppState(); + + return bSaveOk; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RiaGuiApplication::askUserToSaveModifiedProject() +{ + if (m_preferences->showProjectChangedDialog() && caf::PdmUiModelChangeDetector::instance()->isModelChanged()) + { + QMessageBox msgBox; + msgBox.setIcon(QMessageBox::Question); + + QString questionText; + questionText = QString("The current project is modified.\n\nDo you want to save the changes?"); + + msgBox.setText(questionText); + msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); + + int ret = msgBox.exec(); + if (ret == QMessageBox::Cancel) + { + return false; + } + else if (ret == QMessageBox::Yes) + { + if (!saveProject()) + { + return false; + } + } + else + { + caf::PdmUiModelChangeDetector::instance()->reset(); + } + } + + return true; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RiaGuiApplication::saveProjectAs(const QString& fileName) +{ + storeTreeViewState(); + QString errMsg; + if (!RiaApplication::saveProjectAs(fileName, &errMsg)) + { + QMessageBox::warning(nullptr, "Error when saving project file", errMsg); + return false; + } + + m_recentFileActionProvider->addFileName(fileName); + caf::PdmUiModelChangeDetector::instance()->reset(); + return true; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaGuiApplication::loadAndUpdatePlotData() +{ + RimWellLogPlotCollection* wlpColl = nullptr; + RimSummaryPlotCollection* spColl = nullptr; + RimSummaryCrossPlotCollection* scpColl = nullptr; + RimFlowPlotCollection* flowColl = nullptr; + RimRftPlotCollection* rftColl = nullptr; + RimPltPlotCollection* pltColl = nullptr; + RimGridCrossPlotCollection* gcpColl = nullptr; + RimSaturationPressurePlotCollection* sppColl = nullptr; + + if (m_project->mainPlotCollection() && m_project->mainPlotCollection()->wellLogPlotCollection()) + { + wlpColl = m_project->mainPlotCollection()->wellLogPlotCollection(); + } + if (m_project->mainPlotCollection() && m_project->mainPlotCollection()->summaryPlotCollection()) + { + spColl = m_project->mainPlotCollection()->summaryPlotCollection(); + } + if (m_project->mainPlotCollection() && m_project->mainPlotCollection()->summaryCrossPlotCollection()) + { + scpColl = m_project->mainPlotCollection()->summaryCrossPlotCollection(); + } + if (m_project->mainPlotCollection() && m_project->mainPlotCollection()->flowPlotCollection()) + { + flowColl = m_project->mainPlotCollection()->flowPlotCollection(); + } + if (m_project->mainPlotCollection() && m_project->mainPlotCollection()->rftPlotCollection()) + { + rftColl = m_project->mainPlotCollection()->rftPlotCollection(); + } + if (m_project->mainPlotCollection() && m_project->mainPlotCollection()->pltPlotCollection()) + { + pltColl = m_project->mainPlotCollection()->pltPlotCollection(); + } + if (m_project->mainPlotCollection() && m_project->mainPlotCollection()->gridCrossPlotCollection()) + { + gcpColl = m_project->mainPlotCollection()->gridCrossPlotCollection(); + } + if (m_project->mainPlotCollection() && m_project->mainPlotCollection()->saturationPressurePlotCollection()) + { + sppColl = m_project->mainPlotCollection()->saturationPressurePlotCollection(); + } + + size_t plotCount = 0; + plotCount += wlpColl ? wlpColl->wellLogPlots().size() : 0; + plotCount += spColl ? spColl->summaryPlots().size() : 0; + plotCount += scpColl ? scpColl->summaryPlots().size() : 0; + plotCount += flowColl ? flowColl->plotCount() : 0; + plotCount += rftColl ? rftColl->rftPlots().size() : 0; + plotCount += pltColl ? pltColl->pltPlots().size() : 0; + plotCount += gcpColl ? gcpColl->gridCrossPlots().size() : 0; + plotCount += sppColl ? sppColl->plots().size() : 0; + + if (plotCount > 0) + { + caf::ProgressInfo plotProgress(plotCount, "Loading Plot Data"); + if (wlpColl) + { + for (size_t wlpIdx = 0; wlpIdx < wlpColl->wellLogPlots().size(); ++wlpIdx) + { + wlpColl->wellLogPlots[wlpIdx]->loadDataAndUpdate(); + plotProgress.incrementProgress(); + } + } + + if (spColl) + { + for (size_t wlpIdx = 0; wlpIdx < spColl->summaryPlots().size(); ++wlpIdx) + { + spColl->summaryPlots[wlpIdx]->loadDataAndUpdate(); + plotProgress.incrementProgress(); + } + } + + if (scpColl) + { + for (auto plot : scpColl->summaryPlots()) + { + plot->loadDataAndUpdate(); + plotProgress.incrementProgress(); + } + } + + if (flowColl) + { + plotProgress.setNextProgressIncrement(flowColl->plotCount()); + flowColl->loadDataAndUpdate(); + plotProgress.incrementProgress(); + } + + if (rftColl) + { + for (const auto& rftPlot : rftColl->rftPlots()) + { + rftPlot->loadDataAndUpdate(); + plotProgress.incrementProgress(); + } + } + + if (pltColl) + { + for (const auto& pltPlot : pltColl->pltPlots()) + { + pltPlot->loadDataAndUpdate(); + plotProgress.incrementProgress(); + } + } + + if (gcpColl) + { + for (const auto& gcpPlot : gcpColl->gridCrossPlots()) + { + gcpPlot->loadDataAndUpdate(); + plotProgress.incrementProgress(); + } + } + + if (sppColl) + { + for (const auto& sppPlot : sppColl->plots()) + { + sppPlot->loadDataAndUpdate(); + plotProgress.incrementProgress(); + } + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaGuiApplication::storeTreeViewState() +{ + { + if (mainPlotWindow() && mainPlotWindow()->projectTreeView()) + { + caf::PdmUiTreeView* projectTreeView = mainPlotWindow()->projectTreeView(); + + QString treeViewState; + caf::QTreeViewStateSerializer::storeTreeViewStateToString(projectTreeView->treeView(), treeViewState); + + QModelIndex mi = projectTreeView->treeView()->currentIndex(); + + QString encodedModelIndexString; + caf::QTreeViewStateSerializer::encodeStringFromModelIndex(mi, encodedModelIndexString); + + project()->plotWindowTreeViewState = treeViewState; + project()->plotWindowCurrentModelIndexPath = encodedModelIndexString; + } + } + + { + caf::PdmUiTreeView* projectTreeView = m_mainWindow->projectTreeView(); + if (projectTreeView) + { + QString treeViewState; + caf::QTreeViewStateSerializer::storeTreeViewStateToString(projectTreeView->treeView(), treeViewState); + + QModelIndex mi = projectTreeView->treeView()->currentIndex(); + + QString encodedModelIndexString; + caf::QTreeViewStateSerializer::encodeStringFromModelIndex(mi, encodedModelIndexString); + + project()->mainWindowTreeViewState = treeViewState; + project()->mainWindowCurrentModelIndexPath = encodedModelIndexString; + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaGuiApplication::setWindowCaptionFromAppState() +{ + if (!m_mainWindow) return; + + // The stuff being done here should really be handled by Qt automatically as a result of + // setting applicationName and windowFilePath + // Was unable to make this work in Qt4.4.0! + + QString capt = RI_APPLICATION_NAME; +#ifdef _DEBUG + capt += " ##DEBUG##"; +#endif + + { + QString projFileName = m_project->fileName(); + if (projFileName.isEmpty()) projFileName = "Untitled project"; + + capt = projFileName + QString("[*]") + QString(" - ") + capt; + } + + m_mainWindow->setWindowTitle(capt); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimViewWindow* RiaGuiApplication::activePlotWindow() const +{ + RimViewWindow* viewWindow = nullptr; + + if (m_mainPlotWindow) + { + QList subwindows = m_mainPlotWindow->subWindowList(QMdiArea::StackingOrder); + if (subwindows.size() > 0) + { + viewWindow = RiuInterfaceToViewWindow::viewWindowFromWidget(subwindows.back()->widget()); + } + } + + return viewWindow; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RiaGuiApplication::useShaders() const +{ + if (!m_preferences->useShaders) return false; + + bool isShadersSupported = caf::Viewer::isShadersSupported(); + if (!isShadersSupported) return false; + + return true; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiaGuiApplication::RINavigationPolicy RiaGuiApplication::navigationPolicy() const +{ + return m_preferences->navigationPolicy(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RiaGuiApplication::showPerformanceInfo() const +{ + return m_preferences->showHud; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaGuiApplication::initialize() +{ + RiaApplication::initialize(); + + applyGuiPreferences(nullptr); + + // Create main windows + // The plot window is created to be able to set expanded state on created objects, but hidden by default + getOrCreateAndShowMainWindow(); + getOrCreateMainPlotWindow(); + RiaLogging::setLoggerInstance(new RiuMessagePanelLogger(m_mainWindow->messagePanel())); + RiaLogging::loggerInstance()->setLevel(RI_LL_DEBUG); + + m_socketServer = new RiaSocketServer(this); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiaApplication::ApplicationStatus RiaGuiApplication::handleArguments(cvf::ProgramOptions* progOpt) +{ + CVF_ASSERT(progOpt); + + // Handling of the actual command line options + // -------------------------------------------------------- + if (cvf::Option o = progOpt->option("ignoreArgs")) + { + return KEEP_GOING; + } + + // Unit testing + // -------------------------------------------------------- + if (cvf::Option o = progOpt->option("unittest")) + { + int testReturnValue = launchUnitTestsWithConsole(); + + return testReturnValue == 0 ? RiaApplication::EXIT_COMPLETED : RiaApplication::EXIT_WITH_ERROR; + } + + if (cvf::Option o = progOpt->option("regressiontest")) + { + CVF_ASSERT(o.valueCount() == 1); + QString regressionTestPath = cvfqt::Utils::toQString(o.value(0)); + + // Use a logger writing to stdout instead of message panel + // This is useful when executing regression tests on a build server, and this is the reason for creating the logger when + // parsing the command line options + auto stdLogger = new RiaStdOutLogger; + stdLogger->setLevel(RI_LL_DEBUG); + + RiaLogging::setLoggerInstance(stdLogger); + + RiaRegressionTestRunner::instance()->executeRegressionTests(regressionTestPath, QStringList()); + return EXIT_COMPLETED; + } + + if (cvf::Option o = progOpt->option("updateregressiontestbase")) + { + CVF_ASSERT(o.valueCount() == 1); + QString regressionTestPath = cvfqt::Utils::toQString(o.value(0)); + RiaRegressionTestRunner::instance()->updateRegressionTest(regressionTestPath); + return EXIT_COMPLETED; + } + + if (cvf::Option o = progOpt->option("startdir")) + { + CVF_ASSERT(o.valueCount() == 1); + setStartDir(cvfqt::Utils::toQString(o.value(0))); + } + + if (cvf::Option o = progOpt->option("size")) + { + RiuMainWindow* mainWnd = RiuMainWindow::instance(); + int width = o.safeValue(0).toInt(-1); + int height = o.safeValue(1).toInt(-1); + if (mainWnd && width > 0 && height > 0) + { + mainWnd->resize(width, height); + } + } + + QString projectFileName; + + if (progOpt->hasOption("last")) + { + projectFileName = preferences()->lastUsedProjectFileName; + } + + if (cvf::Option o = progOpt->option("project")) + { + CVF_ASSERT(o.valueCount() == 1); + projectFileName = cvfqt::Utils::toQString(o.value(0)); + } + + if (!projectFileName.isEmpty()) + { + if (cvf::Option o = progOpt->option("multiCaseSnapshots")) + { + QString gridListFile = cvfqt::Utils::toQString(o.safeValue(0)); + std::vector gridFiles = readFileListFromTextFile(gridListFile); + runMultiCaseSnapshots(projectFileName, gridFiles, "multiCaseSnapshots"); + + return EXIT_COMPLETED; + } + } + + if (!projectFileName.isEmpty()) + { + cvf::ref projectModifier; + RiaApplication::ProjectLoadAction projectLoadAction = RiaApplication::PLA_NONE; + + if (cvf::Option o = progOpt->option("replaceCase")) + { + if (projectModifier.isNull()) projectModifier = new RiaProjectModifier; + + if (o.valueCount() == 1) + { + // One argument is available, use replace case for first occurrence in the project + + QString gridFileName = cvfqt::Utils::toQString(o.safeValue(0)); + projectModifier->setReplaceCaseFirstOccurrence(gridFileName); + } + else + { + size_t optionIdx = 0; + while (optionIdx < o.valueCount()) + { + const int caseId = o.safeValue(optionIdx++).toInt(-1); + QString gridFileName = cvfqt::Utils::toQString(o.safeValue(optionIdx++)); + + if (caseId != -1 && !gridFileName.isEmpty()) + { + projectModifier->setReplaceCase(caseId, gridFileName); + } + } + } + } + + if (cvf::Option o = progOpt->option("replaceSourceCases")) + { + if (projectModifier.isNull()) projectModifier = new RiaProjectModifier; + + if (o.valueCount() == 1) + { + // One argument is available, use replace case for first occurrence in the project + + std::vector gridFileNames = readFileListFromTextFile(cvfqt::Utils::toQString(o.safeValue(0))); + projectModifier->setReplaceSourceCasesFirstOccurrence(gridFileNames); + } + else + { + size_t optionIdx = 0; + while (optionIdx < o.valueCount()) + { + const int groupId = o.safeValue(optionIdx++).toInt(-1); + std::vector gridFileNames = + readFileListFromTextFile(cvfqt::Utils::toQString(o.safeValue(optionIdx++))); + + if (groupId != -1 && !gridFileNames.empty()) + { + projectModifier->setReplaceSourceCasesById(groupId, gridFileNames); + } + } + } + + projectLoadAction = RiaApplication::PLA_CALCULATE_STATISTICS; + } + + if (cvf::Option o = progOpt->option("replacePropertiesFolder")) + { + if (projectModifier.isNull()) projectModifier = new RiaProjectModifier; + + if (o.valueCount() == 1) + { + QString propertiesFolder = cvfqt::Utils::toQString(o.safeValue(0)); + projectModifier->setReplacePropertiesFolderFirstOccurrence(propertiesFolder); + } + else + { + size_t optionIdx = 0; + while (optionIdx < o.valueCount()) + { + const int caseId = o.safeValue(optionIdx++).toInt(-1); + QString propertiesFolder = cvfqt::Utils::toQString(o.safeValue(optionIdx++)); + + if (caseId != -1 && !propertiesFolder.isEmpty()) + { + projectModifier->setReplacePropertiesFolder(caseId, propertiesFolder); + } + } + } + } + + loadProject(projectFileName, projectLoadAction, projectModifier.p()); + } + + if (cvf::Option o = progOpt->option("case")) + { + QStringList caseNames = cvfqt::Utils::toQStringList(o.values()); + RicImportGeneralDataFeature::OpenCaseResults results = + RicImportGeneralDataFeature::openEclipseFilesFromFileNames(caseNames); + if (results && !results.eclipseSummaryFiles.empty()) + { + getOrCreateAndShowMainPlotWindow(); + } + } + + if (cvf::Option o = progOpt->option("savesnapshots")) + { + bool snapshotViews = false; + bool snapshotPlots = false; + + QStringList snapshotItemTexts = cvfqt::Utils::toQStringList(o.values()); + if (snapshotItemTexts.empty()) + { + // No options will keep backwards compatibility before we introduced snapshot of plots + snapshotViews = true; + } + + for (const QString& s : snapshotItemTexts) + { + if (s.toLower() == "all") + { + snapshotViews = true; + snapshotPlots = true; + } + else if (s.toLower() == "views") + { + snapshotViews = true; + } + else if (s.toLower() == "plots") + { + snapshotPlots = true; + } + } + + if (project() != nullptr && !project()->fileName().isEmpty()) + { + if (snapshotViews) + { + RiuMainWindow* mainWnd = RiuMainWindow::instance(); + CVF_ASSERT(mainWnd); + mainWnd->hideAllDockWindows(); + + // 2016-11-09 : Location of snapshot folder was previously located in 'snapshot' folder + // relative to current working folder. Now harmonized to behave as RiuMainWindow::slotSnapshotAllViewsToFile() + QString absolutePathToSnapshotDir = createAbsolutePathFromProjectRelativePath("snapshots"); + RicSnapshotAllViewsToFileFeature::exportSnapshotOfAllViewsIntoFolder(absolutePathToSnapshotDir); + + mainWnd->loadWinGeoAndDockToolBarLayout(); + } + + if (snapshotPlots) + { + if (mainPlotWindow()) + { + mainPlotWindow()->hideAllDockWindows(); + + // Will be saved relative to current directory + RicSnapshotAllPlotsToFileFeature::saveAllPlots(); + + mainPlotWindow()->loadWinGeoAndDockToolBarLayout(); + } + } + } + + return EXIT_COMPLETED; + } + + if (cvf::Option o = progOpt->option("commandFile")) + { + QString commandFile = cvfqt::Utils::toQString(o.safeValue(0)); + + if (!progOpt->hasOption("startdir")) + { + QFileInfo commandFileInfo(commandFile); + QString commandDir = commandFileInfo.absolutePath(); + setStartDir(commandDir); + } + + cvf::Option projectOption = progOpt->option("commandFileProject"); + cvf::Option caseOption = progOpt->option("commandFileReplaceCases"); + if (projectOption && caseOption) + { + projectFileName = cvfqt::Utils::toQString(projectOption.value(0)); + + std::vector caseIds; + std::vector caseListFiles; + + if (caseOption.valueCount() == 1) + { + caseListFiles.push_back(cvfqt::Utils::toQString(caseOption.safeValue(0))); + } + else + { + size_t optionIdx = 0; + while (optionIdx < caseOption.valueCount()) + { + const int caseId = caseOption.safeValue(optionIdx++).toInt(-1); + QString caseListFile = cvfqt::Utils::toQString(caseOption.safeValue(optionIdx++)); + + if (caseId != -1 && !caseListFile.isEmpty()) + { + caseIds.push_back(caseId); + caseListFiles.push_back(caseListFile); + } + } + } + + if (caseIds.empty() && !caseListFiles.empty()) + { + QString caseListFile = caseListFiles[0]; + std::vector caseFiles = readFileListFromTextFile(caseListFile); + for (const QString& caseFile : caseFiles) + { + RiaProjectModifier projectModifier; + projectModifier.setReplaceCaseFirstOccurrence(caseFile); + loadProject(projectFileName, RiaApplication::PLA_NONE, &projectModifier); + executeCommandFile(commandFile); + } + } + else + { + CVF_ASSERT(caseIds.size() == caseListFiles.size()); + + std::vector> allCaseFiles; + size_t maxFiles = 0; + + for (size_t i = 0; i < caseIds.size(); ++i) + { + std::vector caseFiles = readFileListFromTextFile(caseListFiles[i]); + allCaseFiles.push_back(caseFiles); + maxFiles = std::max(caseFiles.size(), maxFiles); + } + + for (size_t i = 0; i < caseIds.size(); ++i) + { + RiaProjectModifier projectModifier; + for (size_t j = 0; j < maxFiles; ++j) + { + if (allCaseFiles[i].size() > j) + { + projectModifier.setReplaceCase(caseIds[i], allCaseFiles[i][j]); + } + } + + loadProject(projectFileName, RiaApplication::PLA_NONE, &projectModifier); + executeCommandFile(commandFile); + } + } + } + else + { + executeCommandFile(commandFile); + } + return EXIT_COMPLETED; + } + + return KEEP_GOING; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +int RiaGuiApplication::launchUnitTestsWithConsole() +{ + // Following code is taken from cvfAssert.cpp +#ifdef WIN32 + { + // Allocate a new console for this app + // Only one console can be associated with an app, so should fail if a console is already present. + AllocConsole(); + + FILE* consoleFilePointer; + + freopen_s(&consoleFilePointer, "CONOUT$", "w", stdout); + freopen_s(&consoleFilePointer, "CONOUT$", "w", stderr); + + // Make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog point to console as well + std::ios::sync_with_stdio(); + } +#endif + + return launchUnitTests(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiuMainWindow* RiaGuiApplication::getOrCreateAndShowMainWindow() +{ + if (!m_mainWindow) + { + createMainWindow(); + } + return m_mainWindow; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiuMainWindow* RiaGuiApplication::mainWindow() +{ + return m_mainWindow; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiuPlotMainWindow* RiaGuiApplication::getOrCreateMainPlotWindow() +{ + if (!m_mainPlotWindow) + { + createMainPlotWindow(); + m_mainPlotWindow->initializeGuiNewProjectLoaded(); + loadAndUpdatePlotData(); + } + return m_mainPlotWindow; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaGuiApplication::createMainWindow() +{ + CVF_ASSERT(m_mainWindow == nullptr); + m_mainWindow = new RiuMainWindow; + QString platform = cvf::System::is64Bit() ? "(64bit)" : "(32bit)"; + m_mainWindow->setWindowTitle("ResInsight " + platform); + m_mainWindow->setDefaultWindowSize(); + m_mainWindow->setDefaultToolbarVisibility(); + m_mainWindow->loadWinGeoAndDockToolBarLayout(); + m_mainWindow->showWindow(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaGuiApplication::deleteMainWindow() +{ + if (m_mainWindow) + { + delete m_mainWindow; + m_mainWindow = nullptr; + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaGuiApplication::createMainPlotWindow() +{ + CVF_ASSERT(m_mainPlotWindow == nullptr); + + m_mainPlotWindow = new RiuPlotMainWindow; + + m_mainPlotWindow->setWindowTitle("Plots - ResInsight"); + m_mainPlotWindow->setDefaultWindowSize(); + m_mainPlotWindow->loadWinGeoAndDockToolBarLayout(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaGuiApplication::deleteMainPlotWindow() +{ + if (m_mainPlotWindow) + { + m_mainPlotWindow->deleteLater(); + m_mainPlotWindow = nullptr; + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiuPlotMainWindow* RiaGuiApplication::getOrCreateAndShowMainPlotWindow() +{ + if (!m_mainPlotWindow) + { + createMainPlotWindow(); + m_mainPlotWindow->initializeGuiNewProjectLoaded(); + loadAndUpdatePlotData(); + } + + if (m_mainPlotWindow->isMinimized()) + { + m_mainPlotWindow->showNormal(); + m_mainPlotWindow->update(); + } + else + { + m_mainPlotWindow->show(); + } + + m_mainPlotWindow->raise(); + m_mainPlotWindow->activateWindow(); + return m_mainPlotWindow; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiuPlotMainWindow* RiaGuiApplication::mainPlotWindow() +{ + return m_mainPlotWindow; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiuMainWindowBase* RiaGuiApplication::mainWindowByID(int mainWindowID) +{ + if (mainWindowID == 0) + return m_mainWindow; + else if (mainWindowID == 1) + return m_mainPlotWindow; + else + return nullptr; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimViewWindow* RiaGuiApplication::activeViewWindow() +{ + RimViewWindow* viewWindow = nullptr; + + QWidget* mainWindowWidget = RiaGuiApplication::activeWindow(); + + if (dynamic_cast(mainWindowWidget)) + { + viewWindow = RiaGuiApplication::instance()->activeReservoirView(); + } + else if (dynamic_cast(mainWindowWidget)) + { + RiuPlotMainWindow* mainPlotWindow = dynamic_cast(mainWindowWidget); + + QList subwindows = mainPlotWindow->subWindowList(QMdiArea::StackingOrder); + if (subwindows.size() > 0) + { + viewWindow = RiuInterfaceToViewWindow::viewWindowFromWidget(subwindows.back()->widget()); + } + } + + return viewWindow; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RiaGuiApplication::isMain3dWindowVisible() const +{ + return m_mainWindow && m_mainWindow->isVisible(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RiaGuiApplication::isMainPlotWindowVisible() const +{ + return m_mainPlotWindow && m_mainPlotWindow->isVisible(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaGuiApplication::closeMainWindowIfOpenButHidden() +{ + if (m_mainWindow && !m_mainWindow->isVisible()) + { + m_mainWindow->close(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaGuiApplication::closeMainPlotWindowIfOpenButHidden() +{ + if (m_mainPlotWindow && !m_mainPlotWindow->isVisible()) + { + m_mainPlotWindow->close(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaGuiApplication::addToRecentFiles(const QString& fileName) +{ + CVF_ASSERT(m_recentFileActionProvider && + "The provider needs to be created before any attempts to use the recent file actions"); + m_recentFileActionProvider->addFileName(fileName); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RiaGuiApplication::recentFileActions() const +{ + CVF_ASSERT(m_recentFileActionProvider && + "The provider needs to be created before any attempts to use the recent file actions"); + return m_recentFileActionProvider->actions(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaGuiApplication::saveMainWinGeoAndDockToolBarLayout() +{ + if (isMain3dWindowVisible()) + { + m_mainWindow->saveWinGeoAndDockToolBarLayout(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaGuiApplication::savePlotWinGeoAndDockToolBarLayout() +{ + if (isMainPlotWindowVisible()) + { + m_mainPlotWindow->saveWinGeoAndDockToolBarLayout(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaGuiApplication::clearAllSelections() +{ + Riu3dSelectionManager::instance()->deleteAllItems(Riu3dSelectionManager::RUI_APPLICATION_GLOBAL); + Riu3dSelectionManager::instance()->deleteAllItems(Riu3dSelectionManager::RUI_TEMPORARY); + caf::SelectionManager::instance()->clearAll(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaGuiApplication::showInformationMessage(const QString& text) +{ + QString helpText = text; + + QMessageBox msgBox; + msgBox.setIcon(QMessageBox::Information); + msgBox.setWindowTitle("ResInsight"); + + helpText.replace("&", "&"); + helpText.replace("<", "<"); + helpText.replace(">", ">"); + + helpText = QString("
%1
").arg(helpText); + msgBox.setText(helpText); + + msgBox.exec(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaGuiApplication::showErrorMessage(const QString& errMsg) +{ + QErrorMessage errDialog(mainWindow()); + errDialog.showMessage(errMsg); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaGuiApplication::handleEvents(QEventLoop::ProcessEventsFlags flags) +{ + processEvents(flags); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaGuiApplication::onChangedActiveReservoirView() +{ + RiuDockWidgetTools::instance()->changeDockWidgetVisibilityBasedOnView(activeReservoirView()); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaGuiApplication::onFileSuccessfullyLoaded(const QString& fileName, RiaDefines::ImportFileType fileType) +{ + if (fileType & RiaDefines::ANY_ECLIPSE_FILE) + { + getOrCreateAndShowMainPlotWindow(); + } + + if (!RiaGuiApplication::hasValidProjectFileExtension(fileName)) + { + caf::PdmUiModelChangeDetector::instance()->setModelChanged(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaGuiApplication::onProjectBeingOpened() +{ + // When importing a project, do not maximize the first MDI window to be created + m_maximizeWindowGuard.reset(new RiuMdiMaximizeWindowGuard); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaGuiApplication::onProjectOpeningError(const QString& errMsg) +{ + QMessageBox::warning(nullptr, "Error when opening project file", errMsg); + m_mainWindow->setPdmRoot(nullptr); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaGuiApplication::onProjectOpened() +{ + if (m_project->show3DWindow()) + { + m_mainWindow->show(); + } + else + { + m_mainWindow->hide(); + } + + if (m_project->showPlotWindow()) + { + if (!m_mainPlotWindow) + { + createMainPlotWindow(); + m_mainPlotWindow->show(); + } + else + { + m_mainPlotWindow->show(); + m_mainPlotWindow->raise(); + } + } + else if (mainPlotWindow()) + { + mainPlotWindow()->hide(); + } + + loadAndUpdatePlotData(); + + if (m_mainWindow) + { + m_mainWindow->initializeGuiNewProjectLoaded(); + } + if (m_mainPlotWindow) + { + m_mainPlotWindow->initializeGuiNewProjectLoaded(); + } + + setWindowCaptionFromAppState(); + + m_maximizeWindowGuard.reset(); + + processEvents(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaGuiApplication::onProjectBeingClosed() +{ + RicHoloLensSessionManager::instance()->terminateSession(); + RicHoloLensSessionManager::refreshToolbarState(); + + RiaViewRedrawScheduler::instance()->clearViewsScheduledForUpdate(); + + RiaGuiApplication::clearAllSelections(); + + m_mainWindow->cleanupGuiBeforeProjectClose(); + + if (m_mainPlotWindow) + { + m_mainPlotWindow->cleanupGuiBeforeProjectClose(); + } + + caf::EffectGenerator::clearEffectCache(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaGuiApplication::onProjectClosed() +{ + if (m_mainWindow) + { + m_mainWindow->initializeGuiNewProjectLoaded(); + } + if (m_mainPlotWindow) + { + m_mainPlotWindow->initializeGuiNewProjectLoaded(); + } + + setWindowCaptionFromAppState(); + + processEvents(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaGuiApplication::cleanupBeforeProgramExit() +{ + closeAllWindows(); + handleEvents(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaGuiApplication::applyGuiPreferences(const RiaPreferences* oldPreferences) +{ + if (m_activeReservoirView && m_activeReservoirView->viewer()) + { + m_activeReservoirView->viewer()->updateNavigationPolicy(); + m_activeReservoirView->viewer()->enablePerfInfoHud(m_preferences->showHud()); + } + + if (useShaders()) + { + caf::EffectGenerator::setRenderingMode(caf::EffectGenerator::SHADER_BASED); + } + else + { + caf::EffectGenerator::setRenderingMode(caf::EffectGenerator::FIXED_FUNCTION); + } + + if (m_mainWindow && m_mainWindow->projectTreeView()) + { + m_mainWindow->projectTreeView()->enableAppendOfClassNameToUiItemText(m_preferences->appendClassNameToUiText()); + if (mainPlotWindow()) + mainPlotWindow()->projectTreeView()->enableAppendOfClassNameToUiItemText(m_preferences->appendClassNameToUiText()); + } + + std::map fontSizes = m_preferences->defaultFontSizes(); + + if (this->project()) + { + std::vector allViewWindows; + project()->descendantsIncludingThisOfType(allViewWindows); + + RimWellPathCollection* wellPathCollection = this->project()->activeOilField()->wellPathCollection(); + + bool existingViewsWithDifferentMeshLines = false; + bool existingViewsWithCustomColors = false; + bool existingViewsWithCustomZScale = false; + bool existingObjectsWithCustomFonts = false; + if (oldPreferences) + { + for (auto viewWindow : allViewWindows) + { + auto rim3dView = dynamic_cast(viewWindow); + if (rim3dView) + { + if (rim3dView->meshMode() != oldPreferences->defaultMeshModeType()) + { + existingViewsWithDifferentMeshLines = true; + } + if (rim3dView->backgroundColor() != oldPreferences->defaultViewerBackgroundColor()) + { + existingViewsWithCustomColors = true; + } + if (rim3dView->scaleZ() != static_cast(oldPreferences->defaultScaleFactorZ)) + { + existingViewsWithCustomZScale = true; + } + + RimGridView* gridView = dynamic_cast(rim3dView); + if (gridView && gridView->annotationCollection()) + { + RiaFontCache::FontSize oldFontSize = oldPreferences->defaultAnnotationFontSize(); + existingObjectsWithCustomFonts = + gridView->annotationCollection()->hasTextAnnotationsWithCustomFontSize(oldFontSize); + } + RimEclipseView* eclipseView = dynamic_cast(rim3dView); + if (eclipseView) + { + if (eclipseView->wellCollection()->wellLabelColor() != oldPreferences->defaultWellLabelColor()) + { + existingViewsWithCustomColors = true; + } + } + } + + for (auto fontTypeSizePair : fontSizes) + { + RiaFontCache::FontSize oldFontSizeEnum = oldPreferences->defaultFontSizes()[fontTypeSizePair.first]; + if (oldFontSizeEnum != fontTypeSizePair.second) + { + int oldFontSize = RiaFontCache::pointSizeFromFontSizeEnum(oldFontSizeEnum); + if (viewWindow->hasCustomFontSizes(fontTypeSizePair.first, oldFontSize)) + { + existingObjectsWithCustomFonts = true; + } + } + } + } + + if (oldPreferences->defaultWellLabelColor() != wellPathCollection->wellPathLabelColor()) + { + existingViewsWithCustomColors = true; + } + } + + bool applySettingsToAllViews = false; + if (existingViewsWithCustomColors || existingViewsWithCustomZScale || existingViewsWithDifferentMeshLines || + existingObjectsWithCustomFonts) + { + QStringList changedData; + if (existingViewsWithDifferentMeshLines) changedData << "Mesh Visibility"; + if (existingViewsWithCustomColors) changedData << "Colors"; + if (existingViewsWithCustomZScale) changedData << "Z-Scale"; + if (existingObjectsWithCustomFonts) changedData << "Fonts Sizes"; + + QString listString = changedData.takeLast(); + if (!changedData.empty()) + { + listString = changedData.join(", ") + " and " + listString; + } + + QMessageBox::StandardButton reply; + reply = QMessageBox::question( + m_mainWindow, + QString("Apply %1 to Existing Views or Plots?").arg(listString), + QString("You have changed default %1 and have existing views or plots with different settings.\n") + .arg(listString) + + QString("Do you want to apply the new default settings to all existing views?"), + QMessageBox::Ok | QMessageBox::Cancel); + applySettingsToAllViews = (reply == QMessageBox::Ok); + } + + for (auto viewWindow : allViewWindows) + { + for (auto fontTypeSizePair : fontSizes) + { + RiaFontCache::FontSize oldFontSizeEnum = oldPreferences->defaultFontSizes()[fontTypeSizePair.first]; + if (oldFontSizeEnum != fontTypeSizePair.second) + { + int oldFontSize = RiaFontCache::pointSizeFromFontSizeEnum(oldFontSizeEnum); + int newFontSize = RiaFontCache::pointSizeFromFontSizeEnum(fontTypeSizePair.second); + viewWindow->applyFontSize(fontTypeSizePair.first, oldFontSize, newFontSize, applySettingsToAllViews); + } + } + + auto rim3dView = dynamic_cast(viewWindow); + if (rim3dView) + { + if (oldPreferences && (applySettingsToAllViews || rim3dView->meshMode() == oldPreferences->defaultMeshModeType())) + { + rim3dView->meshMode = m_preferences->defaultMeshModeType(); + } + + if (oldPreferences && + (applySettingsToAllViews || rim3dView->backgroundColor() == oldPreferences->defaultViewerBackgroundColor())) + { + rim3dView->setBackgroundColor(m_preferences->defaultViewerBackgroundColor()); + rim3dView->applyBackgroundColorAndFontChanges(); + } + + if (oldPreferences && + (applySettingsToAllViews || rim3dView->scaleZ == static_cast(oldPreferences->defaultScaleFactorZ()))) + { + rim3dView->scaleZ = static_cast(m_preferences->defaultScaleFactorZ()); + rim3dView->updateScaling(); + if (rim3dView == activeViewWindow()) + { + RiuMainWindow::instance()->updateScaleValue(); + } + } + + RimEclipseView* eclipseView = dynamic_cast(rim3dView); + if (eclipseView) + { + if (oldPreferences && (applySettingsToAllViews || eclipseView->wellCollection()->wellLabelColor() == + oldPreferences->defaultWellLabelColor())) + { + eclipseView->wellCollection()->wellLabelColor = m_preferences->defaultWellLabelColor(); + } + eclipseView->scheduleReservoirGridGeometryRegen(); + } + rim3dView->scheduleCreateDisplayModelAndRedraw(); + } + } + + if (oldPreferences) + { + bool matchingColor = wellPathCollection->wellPathLabelColor() == oldPreferences->defaultWellLabelColor(); + if (applySettingsToAllViews || matchingColor) + { + wellPathCollection->wellPathLabelColor = oldPreferences->defaultWellLabelColor(); + } + + if (oldPreferences->defaultPlotFontSize() != m_preferences->defaultPlotFontSize()) + { + m_mainWindow->applyFontSizesToDockedPlots(); + } + } + + std::vector uiEditorsToUpdate; + caf::SelectionManager::instance()->selectedItems(uiEditorsToUpdate); + + for (caf::PdmUiItem* uiItem : uiEditorsToUpdate) + { + uiItem->updateConnectedEditors(); + } + } + caf::PdmUiItem::enableExtraDebugText(m_preferences->appendFieldKeywordToToolTipText()); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaGuiApplication::startMonitoringWorkProgress(caf::UiProcess* uiProcess) +{ + m_mainWindow->processMonitor()->startMonitorWorkProcess(m_workerProcess); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaGuiApplication::stopMonitoringWorkProgress() +{ + m_mainWindow->processMonitor()->stopMonitorWorkProcess(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaGuiApplication::slotWorkerProcessFinished(int exitCode, QProcess::ExitStatus exitStatus) +{ + m_mainWindow->processMonitor()->stopMonitorWorkProcess(); + + // Execute delete later so that other slots that are hooked up + // get a chance to run before we delete the object + if (m_workerProcess) + { + m_workerProcess->close(); + } + m_workerProcess = nullptr; + + // Either the work process crashed or was aborted by the user + if (exitStatus == QProcess::CrashExit) + { + // MFLog::error("Simulation execution crashed or was aborted."); + m_runningWorkerProcess = false; + return; + } + + executeCommandObjects(); + + // Exit code != 0 means we have an error + if (exitCode != 0) + { + // MFLog::error(QString("Simulation execution failed (exit code %1).").arg(exitCode)); + m_runningWorkerProcess = false; + return; + } + + // If multiple cases are present, invoke launchProcess() which will set next current case, and run script on this case + if (!m_currentCaseIds.empty()) + { + launchProcess(m_currentProgram, m_currentArguments); + } + else + { + // Disable concept of current case + m_socketServer->setCurrentCaseId(-1); + m_runningWorkerProcess = false; + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaGuiApplication::runMultiCaseSnapshots(const QString& templateProjectFileName, + std::vector gridFileNames, + const QString& snapshotFolderName) +{ + if (!m_mainWindow) return; + + m_mainWindow->hideAllDockWindows(); + + const size_t numGridFiles = gridFileNames.size(); + for (size_t i = 0; i < numGridFiles; i++) + { + QString gridFn = gridFileNames[i]; + + RiaProjectModifier modifier; + modifier.setReplaceCaseFirstOccurrence(gridFn); + + bool loadOk = loadProject(templateProjectFileName, PLA_NONE, &modifier); + if (loadOk) + { + RicSnapshotAllViewsToFileFeature::exportSnapshotOfAllViewsIntoFolder(snapshotFolderName); + } + } + + m_mainWindow->loadWinGeoAndDockToolBarLayout(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RiaGuiApplication::notify(QObject* receiver, QEvent* event) +{ + // Pre-allocating a memory exhaustion message + // Doing som e trickery to avoid deadlock, as creating a messagebox actually triggers a call to this notify method. + + static QMessageBox* memoryExhaustedBox = nullptr; + static bool allocatingMessageBox = false; + if (!memoryExhaustedBox && !allocatingMessageBox) + { + allocatingMessageBox = true; + memoryExhaustedBox = new QMessageBox(QMessageBox::Critical, + "ResInsight Exhausted Memory", + "Memory is Exhausted!\n ResInsight could not allocate the memory needed, and is now " + "unstable and will probably crash soon."); + } + + bool done = true; + try + { + done = QApplication::notify(receiver, event); + } + catch (const std::bad_alloc&) + { + if (memoryExhaustedBox) memoryExhaustedBox->exec(); + std::cout << "ResInsight: Memory is Exhausted!\n ResInsight could not allocate the memory needed, and is now unstable " + "and will probably crash soon." + << std::endl; + // If we really want to crash instead of limping forward: + // throw; + } + + return done; +} diff --git a/ApplicationCode/Application/RiaGuiApplication.h b/ApplicationCode/Application/RiaGuiApplication.h new file mode 100644 index 0000000000..5b1ae44b22 --- /dev/null +++ b/ApplicationCode/Application/RiaGuiApplication.h @@ -0,0 +1,174 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 "RiaApplication.h" +#include "RiaDefines.h" + +#include "cafPdmObject.h" +#include "cafPdmField.h" +#include "cvfBase.h" +#include "cvfObject.h" + +#include +#include +#include +#include + +#include +#include + +class QAction; + +class Drawable; + +class RIProcess; + +class RiaPreferences; +class RiaProjectModifier; +class RiaSocketServer; + +class RigEclipseCaseData; + +class RimCommandObject; +class RimEclipseCase; +class RimEclipseView; +class RimGridView; +class RimProject; +class RimSummaryPlot; +class Rim3dView; +class RimViewWindow; +class RimWellLogPlot; +class RimWellAllocationPlot; + +class RiuMainWindow; +class RiuMainWindowBase; +class RiuMdiMaximizeWindowGuard; +class RiuPlotMainWindow; +class RiuRecentFileActionProvider; +class RiaArgumentParser; + +//================================================================================================== +// +// +// +//================================================================================================== +class RiaGuiApplication : public QApplication, public RiaApplication +{ + Q_OBJECT + +public: + enum RINavigationPolicy + { + NAVIGATION_POLICY_CEETRON, + NAVIGATION_POLICY_CAD, + NAVIGATION_POLICY_GEOQUEST, + NAVIGATION_POLICY_RMS + }; + +public: + static bool isRunning(); + static RiaGuiApplication* instance(); + + RiaGuiApplication(int& argc, char** argv); + ~RiaGuiApplication() override; + + bool saveProject(); + bool saveProjectPromptForFileName(); + bool askUserToSaveModifiedProject(); + bool saveProjectAs(const QString& fileName); + + void runMultiCaseSnapshots(const QString& templateProjectFileName, std::vector gridFileNames, const QString& snapshotFolderName); + bool useShaders() const; + bool showPerformanceInfo() const; + + RINavigationPolicy navigationPolicy() const; + + RiuMainWindow* getOrCreateAndShowMainWindow(); + RiuMainWindow* mainWindow(); + RimViewWindow* activePlotWindow() const; + + RiuPlotMainWindow* getOrCreateMainPlotWindow(); + RiuPlotMainWindow* getOrCreateAndShowMainPlotWindow(); + RiuPlotMainWindow* mainPlotWindow(); + RiuMainWindowBase* mainWindowByID(int mainWindowID); + + static RimViewWindow* activeViewWindow(); + + bool isMain3dWindowVisible() const; + bool isMainPlotWindowVisible() const; + + void closeMainWindowIfOpenButHidden(); + void closeMainPlotWindowIfOpenButHidden(); + + std::vector recentFileActions() const; + + void saveMainWinGeoAndDockToolBarLayout(); + void savePlotWinGeoAndDockToolBarLayout(); + + static void clearAllSelections(); + void applyGuiPreferences(const RiaPreferences* oldPreferences = nullptr); + + // Public RiaApplication overrides + void initialize() override; + ApplicationStatus handleArguments(cvf::ProgramOptions* progOpt) override; + int launchUnitTestsWithConsole() override; + void addToRecentFiles(const QString& fileName) override; + void showInformationMessage(const QString& text) override; + void showErrorMessage(const QString& errMsg) override; + void cleanupBeforeProgramExit() override; +protected: + // Protected RiaApplication overrides + void handleEvents(QEventLoop::ProcessEventsFlags flags = QEventLoop::AllEvents) override; + void onChangedActiveReservoirView() override; + void onFileSuccessfullyLoaded(const QString& fileName, RiaDefines::ImportFileType fileType) override; + void onProjectBeingOpened() override; + void onProjectOpeningError(const QString& errMsg); + void onProjectOpened() override; + void onProjectBeingClosed() override; + void onProjectClosed() override; + void startMonitoringWorkProgress(caf::UiProcess* uiProcess) override; + void stopMonitoringWorkProgress() override; + +private: + void setWindowCaptionFromAppState(); + + void createMainWindow(); + void deleteMainWindow(); + + void createMainPlotWindow(); + void deleteMainPlotWindow(); + + void loadAndUpdatePlotData(); + + void storeTreeViewState(); + + bool notify(QObject *, QEvent *) override; + +private slots: + void slotWorkerProcessFinished(int exitCode, QProcess::ExitStatus exitStatus); + +private: + RiuMainWindow* m_mainWindow; + RiuPlotMainWindow* m_mainPlotWindow; + + std::unique_ptr m_recentFileActionProvider; + + std::unique_ptr m_maximizeWindowGuard; +}; diff --git a/ApplicationCode/Application/RiaMain.cpp b/ApplicationCode/Application/RiaMain.cpp index 6d1ec7ba41..48234621b0 100644 --- a/ApplicationCode/Application/RiaMain.cpp +++ b/ApplicationCode/Application/RiaMain.cpp @@ -16,30 +16,62 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RiaApplication.h" +#include "RiaArgumentParser.h" +#include "RiaConsoleApplication.h" +#include "RiaGuiApplication.h" #include "RiaLogging.h" +#include "cvfProgramOptions.h" +#include "cvfqtUtils.h" + +RiaApplication* createApplication(int &argc, char *argv[]) +{ + for (int i = 1; i < argc; ++i) + { + if (!qstrcmp(argv[i], "--console") || !qstrcmp(argv[i], "--unittest")) + { + return new RiaConsoleApplication(argc, argv); + } + } + return new RiaGuiApplication(argc, argv); +} + int main(int argc, char *argv[]) { RiaLogging::loggerInstance()->setLevel(RI_LL_DEBUG); - RiaApplication app(argc, argv); + std::unique_ptr app (createApplication(argc, argv)); + app->initialize(); + cvf::ProgramOptions progOpt; + + bool result = RiaArgumentParser::parseArguments(&progOpt); + + if (!result) + { + const cvf::String usageText = progOpt.usageText(110, 30); + app->showInformationMessage(RiaApplication::commandLineParameterHelp() + cvfqt::Utils::toQString(usageText)); + app->cleanupBeforeProgramExit(); + } + QLocale::setDefault(QLocale(QLocale::English, QLocale::UnitedStates)); setlocale(LC_NUMERIC,"C"); - int unitTestResult = app.parseArgumentsAndRunUnitTestsIfRequested(); - if (unitTestResult > -1) + RiaApplication::ApplicationStatus status = app->handleArguments(&progOpt); + if (status == RiaApplication::EXIT_COMPLETED) { - return unitTestResult; + return 0; } - - if (app.parseArguments()) + else if (status == RiaApplication::EXIT_WITH_ERROR) + { + return 1; + } + else if (status == RiaApplication::KEEP_GOING) { int exitCode = 0; try { - exitCode = app.exec(); + exitCode = QCoreApplication::instance()->exec(); } catch (std::exception& exep ) { @@ -55,6 +87,7 @@ int main(int argc, char *argv[]) return exitCode; } - return 0; + CVF_ASSERT(false && "Unknown ApplicationStatus"); + return -1; } diff --git a/ApplicationCode/Application/RiaMemoryCleanup.cpp b/ApplicationCode/Application/RiaMemoryCleanup.cpp index 48c3af41ce..f1ef6698c9 100644 --- a/ApplicationCode/Application/RiaMemoryCleanup.cpp +++ b/ApplicationCode/Application/RiaMemoryCleanup.cpp @@ -223,13 +223,13 @@ QList RiaMemoryCleanup::calculateValueOptions(const caf: std::vector eclipseCases = proj->eclipseCases(); for (RimEclipseCase* c : eclipseCases) { - options.push_back(caf::PdmOptionItemInfo(c->caseUserDescription(), c, false, c->uiIcon())); + options.push_back(caf::PdmOptionItemInfo(c->caseUserDescription(), c, false, c->uiIconProvider())); } std::vector geoMechCases = proj->geoMechCases(); for (RimGeoMechCase* c : geoMechCases) { - options.push_back(caf::PdmOptionItemInfo(c->caseUserDescription(), c, false, c->uiIcon())); + options.push_back(caf::PdmOptionItemInfo(c->caseUserDescription(), c, false, c->uiIconProvider())); } } } diff --git a/ApplicationCode/Application/RiaPreferences.cpp b/ApplicationCode/Application/RiaPreferences.cpp index 540fa0db56..51048614f3 100644 --- a/ApplicationCode/Application/RiaPreferences.cpp +++ b/ApplicationCode/Application/RiaPreferences.cpp @@ -49,7 +49,7 @@ CAF_PDM_SOURCE_INIT(RiaPreferences, "RiaPreferences"); //-------------------------------------------------------------------------------------------------- RiaPreferences::RiaPreferences(void) { - CAF_PDM_InitField(&navigationPolicy, "navigationPolicy", caf::AppEnum(RiaApplication::NAVIGATION_POLICY_RMS), "Navigation Mode", "", "", ""); + CAF_PDM_InitField(&navigationPolicy, "navigationPolicy", caf::AppEnum(RiaGuiApplication::NAVIGATION_POLICY_RMS), "Navigation Mode", "", "", ""); CAF_PDM_InitFieldNoDefault(&scriptDirectories, "scriptDirectory", "Shared Script Folder(s)", "", "", ""); scriptDirectories.uiCapability()->setUiEditorTypeName(caf::PdmUiFilePathEditor::uiEditorTypeName()); diff --git a/ApplicationCode/Application/RiaPreferences.h b/ApplicationCode/Application/RiaPreferences.h index d7c8139153..3c7fe59dea 100644 --- a/ApplicationCode/Application/RiaPreferences.h +++ b/ApplicationCode/Application/RiaPreferences.h @@ -22,6 +22,7 @@ #pragma once #include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RiaDefines.h" #include "RiaFontCache.h" @@ -65,7 +66,7 @@ public: std::map defaultFontSizes() const; public: // Pdm Fields - caf::PdmField > navigationPolicy; + caf::PdmField > navigationPolicy; caf::PdmField scriptDirectories; caf::PdmField scriptEditorExecutable; diff --git a/ApplicationCode/Application/Tools/RiaArgumentParser.cpp b/ApplicationCode/Application/Tools/RiaArgumentParser.cpp index 48c4adf2eb..82910e652e 100644 --- a/ApplicationCode/Application/Tools/RiaArgumentParser.cpp +++ b/ApplicationCode/Application/Tools/RiaArgumentParser.cpp @@ -17,7 +17,6 @@ ///////////////////////////////////////////////////////////////////////////////// #include "RiaArgumentParser.h" - #include "RiaApplication.h" #include "RiaBaseDefs.h" #include "RiaEclipseFileNameTools.h" @@ -50,489 +49,77 @@ #include #include + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool RiaArgumentParser::parseArguments() +bool RiaArgumentParser::parseArguments(cvf::ProgramOptions* progOpt) { - cvf::ProgramOptions progOpt; - progOpt.registerOption("last", "", "Open last used project."); - progOpt.registerOption("project", "", "Open project file .", cvf::ProgramOptions::SINGLE_VALUE); - progOpt.registerOption("case", + CVF_ASSERT(progOpt); + progOpt->registerOption("console", "", "Run as a console application without Graphics"); + progOpt->registerOption("last", "", "Open last used project."); + progOpt->registerOption("project", "", "Open project file .", cvf::ProgramOptions::SINGLE_VALUE); + progOpt->registerOption("case", "", "If case or grid filename, import simulation grid data. If summary file name, import summary data", cvf::ProgramOptions::MULTI_VALUE); - progOpt.registerOption("startdir", "", "Set startup directory.", cvf::ProgramOptions::SINGLE_VALUE); - progOpt.registerOption("savesnapshots", + progOpt->registerOption("startdir", "", "Set startup directory.", cvf::ProgramOptions::SINGLE_VALUE); + progOpt->registerOption("savesnapshots", "all|views|plots", "Save snapshot of all views or plots to project file location sub folder 'snapshots'. Option 'all' " "will include both views and plots. Application closes after snapshots have been written.", cvf::ProgramOptions::OPTIONAL_MULTI_VALUE); - progOpt.registerOption( + progOpt->registerOption( "size", " ", "Set size of the main application window.", cvf::ProgramOptions::MULTI_VALUE); - progOpt.registerOption( + progOpt->registerOption( "replaceCase", "[] ", "Replace grid in or first case with . Repeat parameter for multiple replace operations.", cvf::ProgramOptions::MULTI_VALUE, cvf::ProgramOptions::COMBINE_REPEATED); - progOpt.registerOption("replaceSourceCases", + progOpt->registerOption("replaceSourceCases", "[] ", "Replace source cases in or first grid case group with the grid files listed in the " " file. Repeat parameter for multiple replace operations.", cvf::ProgramOptions::MULTI_VALUE, cvf::ProgramOptions::COMBINE_REPEATED); - progOpt.registerOption("replacePropertiesFolder", + progOpt->registerOption("replacePropertiesFolder", "[] ", "Replace the folder containing property files for an eclipse input case.", cvf::ProgramOptions::MULTI_VALUE); - progOpt.registerOption("multiCaseSnapshots", + progOpt->registerOption("multiCaseSnapshots", "", "For each grid file listed in the file, replace the first case in the project and save " "snapshot of all views.", cvf::ProgramOptions::SINGLE_VALUE); - progOpt.registerOption("commandFile", "", "Execute the command file.", cvf::ProgramOptions::SINGLE_VALUE); - progOpt.registerOption( + progOpt->registerOption("commandFile", "", "Execute the command file.", cvf::ProgramOptions::SINGLE_VALUE); + progOpt->registerOption( "commandFileProject", "", "Project to use if performing case looping for command file. Used in conjunction with 'commandFileReplaceCases'.", cvf::ProgramOptions::SINGLE_VALUE); - progOpt.registerOption("commandFileReplaceCases", + progOpt->registerOption("commandFileReplaceCases", "[] ", "Supply list of cases to replace in project, performing command file for each case.", cvf::ProgramOptions::SINGLE_VALUE); - progOpt.registerOption("help", "", "Displays help text."); - progOpt.registerOption("?", "", "Displays help text."); - progOpt.registerOption("regressiontest", "", "System command", cvf::ProgramOptions::SINGLE_VALUE); - progOpt.registerOption("updateregressiontestbase", "", "System command", cvf::ProgramOptions::SINGLE_VALUE); - progOpt.registerOption("unittest", "", "System command"); - progOpt.registerOption("ignoreArgs", "", "Ignore all arguments. Mostly for testing purposes"); + progOpt->registerOption("help", "", "Displays help text."); + progOpt->registerOption("?", "", "Displays help text."); + progOpt->registerOption("regressiontest", "", "System command", cvf::ProgramOptions::SINGLE_VALUE); + progOpt->registerOption("updateregressiontestbase", "", "System command", cvf::ProgramOptions::SINGLE_VALUE); + progOpt->registerOption("unittest", "", "System command"); + progOpt->registerOption("ignoreArgs", "", "Ignore all arguments. Mostly for testing purposes"); - progOpt.setOptionPrefix(cvf::ProgramOptions::DOUBLE_DASH); - - QString helpText = QString("\n%1 v. %2\n").arg(RI_APPLICATION_NAME).arg(RiaApplication::getVersionStringApp(false)); - helpText += "Copyright Equinor ASA, Ceetron Solution AS, Ceetron AS\n\n"; - - const cvf::String usageText = progOpt.usageText(110, 30); - helpText += cvfqt::Utils::toQString(usageText); - - RiaApplication::instance()->setHelpText(helpText); + progOpt->setOptionPrefix(cvf::ProgramOptions::DOUBLE_DASH); QStringList arguments = QCoreApplication::arguments(); - - bool parseOk = progOpt.parse(cvfqt::Utils::toStringVector(arguments)); + + bool parseOk = progOpt->parse(cvfqt::Utils::toStringVector(arguments)); // If positional parameter functionality is to be supported, the test for existence of positionalParameters must be removed // This is based on a pull request by @andlaus https://github.com/OPM/ResInsight/pull/162 - if (!parseOk || progOpt.hasOption("help") || progOpt.hasOption("?") || !progOpt.positionalParameters().empty()) + if (!parseOk || progOpt->hasOption("help") || progOpt->hasOption("?") || !progOpt->positionalParameters().empty()) { -#if defined(_MSC_VER) && defined(_WIN32) - RiaApplication::instance()->showFormattedTextInMessageBox(helpText); -#else - fprintf(stdout, "%s\n", helpText.toLatin1().data()); - fflush(stdout); -#endif return false; } - - // Handling of the actual command line options - // -------------------------------------------------------- - - if (cvf::Option o = progOpt.option("ignoreArgs")) - { - return true; - } - - if (cvf::Option o = progOpt.option("regressiontest")) - { - CVF_ASSERT(o.valueCount() == 1); - QString regressionTestPath = cvfqt::Utils::toQString(o.value(0)); - - // Use a logger writing to stdout instead of message panel - // This is useful when executing regression tests on a build server, and this is the reason for creating the logger when - // parsing the command line options - auto stdLogger = new RiaStdOutLogger; - stdLogger->setLevel(RI_LL_DEBUG); - - RiaLogging::setLoggerInstance(stdLogger); - - RiaRegressionTestRunner::instance()->executeRegressionTests(regressionTestPath, QStringList()); - return false; - } - - if (cvf::Option o = progOpt.option("updateregressiontestbase")) - { - CVF_ASSERT(o.valueCount() == 1); - QString regressionTestPath = cvfqt::Utils::toQString(o.value(0)); - RiaRegressionTestRunner::instance()->updateRegressionTest(regressionTestPath); - return false; - } - - if (cvf::Option o = progOpt.option("startdir")) - { - CVF_ASSERT(o.valueCount() == 1); - RiaApplication::instance()->setStartDir(cvfqt::Utils::toQString(o.value(0))); - } - - if (cvf::Option o = progOpt.option("size")) - { - RiuMainWindow* mainWnd = RiuMainWindow::instance(); - int width = o.safeValue(0).toInt(-1); - int height = o.safeValue(1).toInt(-1); - if (mainWnd && width > 0 && height > 0) - { - mainWnd->resize(width, height); - } - } - - QString projectFileName; - - if (progOpt.hasOption("last")) - { - projectFileName = RiaApplication::instance()->preferences()->lastUsedProjectFileName; - } - - if (cvf::Option o = progOpt.option("project")) - { - CVF_ASSERT(o.valueCount() == 1); - projectFileName = cvfqt::Utils::toQString(o.value(0)); - } - - if (!projectFileName.isEmpty()) - { - if (cvf::Option o = progOpt.option("multiCaseSnapshots")) - { - QString gridListFile = cvfqt::Utils::toQString(o.safeValue(0)); - std::vector gridFiles = RiaApplication::readFileListFromTextFile(gridListFile); - RiaApplication::instance()->runMultiCaseSnapshots(projectFileName, gridFiles, "multiCaseSnapshots"); - - return false; - } - } - - if (!projectFileName.isEmpty()) - { - cvf::ref projectModifier; - RiaApplication::ProjectLoadAction projectLoadAction = RiaApplication::PLA_NONE; - - if (cvf::Option o = progOpt.option("replaceCase")) - { - if (projectModifier.isNull()) projectModifier = new RiaProjectModifier; - - if (o.valueCount() == 1) - { - // One argument is available, use replace case for first occurrence in the project - - QString gridFileName = cvfqt::Utils::toQString(o.safeValue(0)); - projectModifier->setReplaceCaseFirstOccurrence(gridFileName); - } - else - { - size_t optionIdx = 0; - while (optionIdx < o.valueCount()) - { - const int caseId = o.safeValue(optionIdx++).toInt(-1); - QString gridFileName = cvfqt::Utils::toQString(o.safeValue(optionIdx++)); - - if (caseId != -1 && !gridFileName.isEmpty()) - { - projectModifier->setReplaceCase(caseId, gridFileName); - } - } - } - } - - if (cvf::Option o = progOpt.option("replaceSourceCases")) - { - if (projectModifier.isNull()) projectModifier = new RiaProjectModifier; - - if (o.valueCount() == 1) - { - // One argument is available, use replace case for first occurrence in the project - - std::vector gridFileNames = - RiaApplication::readFileListFromTextFile(cvfqt::Utils::toQString(o.safeValue(0))); - projectModifier->setReplaceSourceCasesFirstOccurrence(gridFileNames); - } - else - { - size_t optionIdx = 0; - while (optionIdx < o.valueCount()) - { - const int groupId = o.safeValue(optionIdx++).toInt(-1); - std::vector gridFileNames = - RiaApplication::readFileListFromTextFile(cvfqt::Utils::toQString(o.safeValue(optionIdx++))); - - if (groupId != -1 && !gridFileNames.empty()) - { - projectModifier->setReplaceSourceCasesById(groupId, gridFileNames); - } - } - } - - projectLoadAction = RiaApplication::PLA_CALCULATE_STATISTICS; - } - - if (cvf::Option o = progOpt.option("replacePropertiesFolder")) - { - if (projectModifier.isNull()) projectModifier = new RiaProjectModifier; - - if (o.valueCount() == 1) - { - QString propertiesFolder = cvfqt::Utils::toQString(o.safeValue(0)); - projectModifier->setReplacePropertiesFolderFirstOccurrence(propertiesFolder); - } - else - { - size_t optionIdx = 0; - while (optionIdx < o.valueCount()) - { - const int caseId = o.safeValue(optionIdx++).toInt(-1); - QString propertiesFolder = cvfqt::Utils::toQString(o.safeValue(optionIdx++)); - - if (caseId != -1 && !propertiesFolder.isEmpty()) - { - projectModifier->setReplacePropertiesFolder(caseId, propertiesFolder); - } - } - } - } - - RiaApplication::instance()->loadProject(projectFileName, projectLoadAction, projectModifier.p()); - } - - if (cvf::Option o = progOpt.option("case")) - { - QStringList caseNames = cvfqt::Utils::toQStringList(o.values()); - for (const QString& caseName : caseNames) - { - openCaseFromCommandLineParameter(caseName); - } - } - - if (cvf::Option o = progOpt.option("savesnapshots")) - { - bool snapshotViews = false; - bool snapshotPlots = false; - - QStringList snapshotItemTexts = cvfqt::Utils::toQStringList(o.values()); - if (snapshotItemTexts.empty()) - { - // No options will keep backwards compatibility before we introduced snapshot of plots - snapshotViews = true; - } - - for (const QString& s : snapshotItemTexts) - { - if (s.toLower() == "all") - { - snapshotViews = true; - snapshotPlots = true; - } - else if (s.toLower() == "views") - { - snapshotViews = true; - } - else if (s.toLower() == "plots") - { - snapshotPlots = true; - } - } - - if (RiaApplication::instance()->project() != nullptr && !RiaApplication::instance()->project()->fileName().isEmpty()) - { - if (snapshotViews) - { - RiuMainWindow* mainWnd = RiuMainWindow::instance(); - CVF_ASSERT(mainWnd); - mainWnd->hideAllDockWindows(); - - // 2016-11-09 : Location of snapshot folder was previously located in 'snapshot' folder - // relative to current working folder. Now harmonized to behave as RiuMainWindow::slotSnapshotAllViewsToFile() - QString absolutePathToSnapshotDir = - RiaApplication::instance()->createAbsolutePathFromProjectRelativePath("snapshots"); - RicSnapshotAllViewsToFileFeature::exportSnapshotOfAllViewsIntoFolder(absolutePathToSnapshotDir); - - mainWnd->loadWinGeoAndDockToolBarLayout(); - } - - if (snapshotPlots) - { - if (RiaApplication::instance()->mainPlotWindow()) - { - RiaApplication::instance()->mainPlotWindow()->hideAllDockWindows(); - - // Will be saved relative to current directory - RicSnapshotAllPlotsToFileFeature::saveAllPlots(); - - RiaApplication::instance()->mainPlotWindow()->loadWinGeoAndDockToolBarLayout(); - } - } - } - - // Returning false will exit the application - return false; - } - - if (cvf::Option o = progOpt.option("commandFile")) - { - QString commandFile = cvfqt::Utils::toQString(o.safeValue(0)); - - cvf::Option projectOption = progOpt.option("commandFileProject"); - cvf::Option caseOption = progOpt.option("commandFileReplaceCases"); - if (projectOption && caseOption) - { - projectFileName = cvfqt::Utils::toQString(projectOption.value(0)); - - std::vector caseIds; - std::vector caseListFiles; - - if (caseOption.valueCount() == 1) - { - caseListFiles.push_back(cvfqt::Utils::toQString(caseOption.safeValue(0))); - } - else - { - size_t optionIdx = 0; - while (optionIdx < caseOption.valueCount()) - { - const int caseId = caseOption.safeValue(optionIdx++).toInt(-1); - QString caseListFile = cvfqt::Utils::toQString(caseOption.safeValue(optionIdx++)); - - if (caseId != -1 && !caseListFile.isEmpty()) - { - caseIds.push_back(caseId); - caseListFiles.push_back(caseListFile); - } - } - } - - if (caseIds.empty() && !caseListFiles.empty()) - { - QString caseListFile = caseListFiles[0]; - std::vector caseFiles = RiaApplication::readFileListFromTextFile(caseListFile); - for (const QString& caseFile : caseFiles) - { - RiaProjectModifier projectModifier; - projectModifier.setReplaceCaseFirstOccurrence(caseFile); - RiaApplication::instance()->loadProject(projectFileName, RiaApplication::PLA_NONE, &projectModifier); - executeCommandFile(commandFile); - } - } - else - { - CVF_ASSERT(caseIds.size() == caseListFiles.size()); - - std::vector> allCaseFiles; - size_t maxFiles = 0; - - for (size_t i = 0; i < caseIds.size(); ++i) - { - std::vector caseFiles = RiaApplication::readFileListFromTextFile(caseListFiles[i]); - allCaseFiles.push_back(caseFiles); - maxFiles = std::max(caseFiles.size(), maxFiles); - } - - for (size_t i = 0; i < caseIds.size(); ++i) - { - RiaProjectModifier projectModifier; - for (size_t j = 0; j < maxFiles; ++j) - { - if (allCaseFiles[i].size() > j) - { - projectModifier.setReplaceCase(caseIds[i], allCaseFiles[i][j]); - } - } - - RiaApplication::instance()->loadProject(projectFileName, RiaApplication::PLA_NONE, &projectModifier); - executeCommandFile(commandFile); - } - } - } - else - { - executeCommandFile(commandFile); - } - return false; - } - return true; } - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiaArgumentParser::executeCommandFile(const QString& commandFile) -{ - QFile file(commandFile); - RicfMessages messages; - if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) - { - // TODO : Error logging? - return; - } - - QTextStream in(&file); - RicfCommandFileExecutor::instance()->executeCommands(in); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool RiaArgumentParser::openCaseFromCommandLineParameter(const QString& parameter) -{ - if (RiaEclipseFileNameTools::isProjectFile(parameter)) - { - return RiaApplication::instance()->loadProject(parameter); - } - - QStringList gridFileNames; - QStringList summarySpecFileNames; - - if (RiaEclipseFileNameTools::isGridFile(parameter)) - { - QFileInfo fi(parameter); - - gridFileNames.push_back(fi.absoluteFilePath()); - } - else if (RiaEclipseFileNameTools::isSummarySpecFile(parameter)) - { - QFileInfo fi(parameter); - - summarySpecFileNames.push_back(fi.absoluteFilePath()); - } - else - { - RiaEclipseFileNameTools fileNameTools(parameter); - - { - QString gridFileName = fileNameTools.findRelatedGridFile(); - if (!gridFileName.isEmpty()) - { - gridFileNames.push_back(gridFileName); - } - } - - QString summarySpecFileName = fileNameTools.findRelatedSummarySpecFile(); - if (!summarySpecFileName.isEmpty()) - { - summarySpecFileNames.push_back(summarySpecFileName); - } - } - - bool openCaseResult = true; - - // Open summary cases first. Then, the open of grid file will not open an already open summary case file - if (!summarySpecFileNames.empty()) - { - openCaseResult &= RicImportSummaryCasesFeature::createAndAddSummaryCasesFromFiles(summarySpecFileNames); - RiaApplication::instance()->getOrCreateAndShowMainPlotWindow(); - } - - for (const auto& f : gridFileNames) - { - openCaseResult &= RiaImportEclipseCaseTools::openEclipseCasesFromFile(QStringList({f}), nullptr, true); - } - - return openCaseResult; -} diff --git a/ApplicationCode/Application/Tools/RiaArgumentParser.h b/ApplicationCode/Application/Tools/RiaArgumentParser.h index 6a0d6dc212..a7e249da44 100644 --- a/ApplicationCode/Application/Tools/RiaArgumentParser.h +++ b/ApplicationCode/Application/Tools/RiaArgumentParser.h @@ -20,6 +20,10 @@ #include +namespace cvf +{ +class ProgramOptions; +} //================================================================================================== // // @@ -28,10 +32,6 @@ class RiaArgumentParser { public: - static bool parseArguments(); - -private: - static void executeCommandFile(const QString& commandFile); - static bool openCaseFromCommandLineParameter(const QString& parameter); + static bool parseArguments(cvf::ProgramOptions* progOpt); }; diff --git a/ApplicationCode/Application/Tools/RiaOptionItemFactory.cpp b/ApplicationCode/Application/Tools/RiaOptionItemFactory.cpp index c8b275cc04..9e7dd835a2 100644 --- a/ApplicationCode/Application/Tools/RiaOptionItemFactory.cpp +++ b/ApplicationCode/Application/Tools/RiaOptionItemFactory.cpp @@ -43,7 +43,7 @@ void RiaOptionItemFactory::appendOptionItemFromViewNameAndCaseName(Rim3dView* vi QString displayName = caseName + " : " + view->name(); - QIcon icon = view->uiCapability()->uiIcon(); + caf::QIconProvider iconProvider = view->uiCapability()->uiIconProvider(); - optionItems->push_back(caf::PdmOptionItemInfo(displayName, view, false, icon)); + optionItems->push_back(caf::PdmOptionItemInfo(displayName, view, false, iconProvider)); } diff --git a/ApplicationCode/Application/Tools/RiaRegressionTestRunner.cpp b/ApplicationCode/Application/Tools/RiaRegressionTestRunner.cpp index 3b8e34ec07..0fcdc3ec02 100644 --- a/ApplicationCode/Application/Tools/RiaRegressionTestRunner.cpp +++ b/ApplicationCode/Application/Tools/RiaRegressionTestRunner.cpp @@ -18,7 +18,7 @@ #include "RiaRegressionTestRunner.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RiaGitDiff.h" #include "RiaImageCompareReporter.h" #include "RiaImageFileCompare.h" @@ -504,7 +504,7 @@ void RiaRegressionTestRunner::resizeMaximizedPlotWindows() RimProject* proj = RiaApplication::instance()->project(); if (!proj) return; - RiuPlotMainWindow* plotMainWindow = RiaApplication::instance()->mainPlotWindow(); + RiuPlotMainWindow* plotMainWindow = RiaGuiApplication::instance()->mainPlotWindow(); if (!plotMainWindow) return; std::vector viewWindows; diff --git a/ApplicationCode/CommandFileInterface/RicfCreateSaturationPressurePlots.cpp b/ApplicationCode/CommandFileInterface/RicfCreateSaturationPressurePlots.cpp index 2d2a98c323..622c4272a6 100644 --- a/ApplicationCode/CommandFileInterface/RicfCreateSaturationPressurePlots.cpp +++ b/ApplicationCode/CommandFileInterface/RicfCreateSaturationPressurePlots.cpp @@ -21,7 +21,7 @@ #include "GridCrossPlotCommands/RicCreateSaturationPressurePlotsFeature.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RiaLogging.h" #include "RimEclipseResultCase.h" @@ -79,5 +79,5 @@ void RicfCreateSaturationPressurePlots::execute() RimSaturationPressurePlotCollection* collection = project->mainPlotCollection()->saturationPressurePlotCollection(); collection->updateAllRequiredEditors(); - RiaApplication::instance()->getOrCreateAndShowMainPlotWindow(); + RiaGuiApplication::instance()->getOrCreateAndShowMainPlotWindow(); } diff --git a/ApplicationCode/CommandFileInterface/RicfExportMultiCaseSnapshots.cpp b/ApplicationCode/CommandFileInterface/RicfExportMultiCaseSnapshots.cpp index 55df684399..c56bc5da49 100644 --- a/ApplicationCode/CommandFileInterface/RicfExportMultiCaseSnapshots.cpp +++ b/ApplicationCode/CommandFileInterface/RicfExportMultiCaseSnapshots.cpp @@ -20,7 +20,7 @@ #include "RicfCommandFileExecutor.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RiaLogging.h" #include "RiaProjectModifier.h" @@ -39,6 +39,12 @@ RicfExportMultiCaseSnapshots::RicfExportMultiCaseSnapshots() //-------------------------------------------------------------------------------------------------- void RicfExportMultiCaseSnapshots::execute() { + RiaGuiApplication* app = RiaGuiApplication::instance(); + if (!app) + { + RiaLogging::error("exportMultiCaseSnapshots: Requires GUI Application"); + return; + } if (m_gridListFile().isNull()) { RiaLogging::error("exportMultiCaseSnapshots: Required parameter gridListFile."); @@ -53,5 +59,5 @@ void RicfExportMultiCaseSnapshots::execute() } std::vector listFileNames = RiaApplication::readFileListFromTextFile(m_gridListFile()); - RiaApplication::instance()->runMultiCaseSnapshots(lastProjectPath, listFileNames, RicfCommandFileExecutor::instance()->getExportPath(RicfCommandFileExecutor::SNAPSHOTS)); + app->runMultiCaseSnapshots(lastProjectPath, listFileNames, RicfCommandFileExecutor::instance()->getExportPath(RicfCommandFileExecutor::SNAPSHOTS)); } diff --git a/ApplicationCode/CommandFileInterface/RicfExportSnapshots.cpp b/ApplicationCode/CommandFileInterface/RicfExportSnapshots.cpp index 633bc85a49..bc3f8a6a46 100644 --- a/ApplicationCode/CommandFileInterface/RicfExportSnapshots.cpp +++ b/ApplicationCode/CommandFileInterface/RicfExportSnapshots.cpp @@ -23,7 +23,8 @@ #include "ExportCommands/RicSnapshotAllPlotsToFileFeature.h" #include "ExportCommands/RicSnapshotAllViewsToFileFeature.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" +#include "RiaLogging.h" #include "RiuMainWindow.h" @@ -57,10 +58,16 @@ RicfExportSnapshots::RicfExportSnapshots() //-------------------------------------------------------------------------------------------------- void RicfExportSnapshots::execute() { + if (!RiaGuiApplication::isRunning()) + { + RiaLogging::error(QString("RicfExportSnapshot: Command cannot run without a GUI")); + return; + } + RiuMainWindow* mainWnd = RiuMainWindow::instance(); CVF_ASSERT(mainWnd); mainWnd->hideAllDockWindows(); - RiaApplication::instance()->processEvents(); + RiaGuiApplication::instance()->processEvents(); QString absolutePathToSnapshotDir = RicfCommandFileExecutor::instance()->getExportPath(RicfCommandFileExecutor::SNAPSHOTS); if (absolutePathToSnapshotDir.isNull()) @@ -77,5 +84,5 @@ void RicfExportSnapshots::execute() } mainWnd->loadWinGeoAndDockToolBarLayout(); - RiaApplication::instance()->processEvents(); + RiaGuiApplication::instance()->processEvents(); } diff --git a/ApplicationCode/CommandFileInterface/RicfOpenProject.cpp b/ApplicationCode/CommandFileInterface/RicfOpenProject.cpp index 2a0d3461fe..bffdbff2ab 100644 --- a/ApplicationCode/CommandFileInterface/RicfOpenProject.cpp +++ b/ApplicationCode/CommandFileInterface/RicfOpenProject.cpp @@ -24,6 +24,9 @@ #include "RiaLogging.h" #include "RiaRegressionTestRunner.h" +#include +#include + CAF_PDM_SOURCE_INIT(RicfOpenProject, "openProject"); //-------------------------------------------------------------------------------------------------- @@ -39,7 +42,14 @@ RicfOpenProject::RicfOpenProject() //-------------------------------------------------------------------------------------------------- void RicfOpenProject::execute() { - bool ok = RiaApplication::instance()->loadProject(m_path); + QString projectPath = m_path; + QFileInfo projectPathInfo(projectPath); + if (!projectPathInfo.exists()) + { + QDir startDir(RiaApplication::instance()->startDir()); + projectPath = startDir.absoluteFilePath(m_path); + } + bool ok = RiaApplication::instance()->loadProject(projectPath); if (!ok) { RiaLogging::error(QString("openProject: Unable to open project at %1").arg(m_path())); @@ -51,5 +61,5 @@ void RicfOpenProject::execute() RiaRegressionTestRunner::regressionTestConfigureProject(); } - RicfCommandFileExecutor::instance()->setLastProjectPath(m_path); + RicfCommandFileExecutor::instance()->setLastProjectPath(projectPath); } diff --git a/ApplicationCode/Commands/ApplicationCommands/RicCloseProjectFeature.cpp b/ApplicationCode/Commands/ApplicationCommands/RicCloseProjectFeature.cpp index 30c1fd1612..00b940fedf 100644 --- a/ApplicationCode/Commands/ApplicationCommands/RicCloseProjectFeature.cpp +++ b/ApplicationCode/Commands/ApplicationCommands/RicCloseProjectFeature.cpp @@ -18,7 +18,7 @@ #include "RicCloseProjectFeature.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include @@ -39,9 +39,8 @@ void RicCloseProjectFeature::onActionTriggered(bool isChecked) { this->disableModelChangeContribution(); - RiaApplication* app = RiaApplication::instance(); - - if (!app->askUserToSaveModifiedProject()) return; + RiaGuiApplication* app = RiaGuiApplication::instance(); + if (!app || !app->askUserToSaveModifiedProject()) return; app->closeProject(); } diff --git a/ApplicationCode/Commands/ApplicationCommands/RicEditPreferencesFeature.cpp b/ApplicationCode/Commands/ApplicationCommands/RicEditPreferencesFeature.cpp index ff94eeeda4..e3639c0ddb 100644 --- a/ApplicationCode/Commands/ApplicationCommands/RicEditPreferencesFeature.cpp +++ b/ApplicationCode/Commands/ApplicationCommands/RicEditPreferencesFeature.cpp @@ -18,7 +18,7 @@ #include "RicEditPreferencesFeature.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RiaPreferences.h" #include "RiuPropertyViewTabWidget.h" @@ -44,7 +44,7 @@ void RicEditPreferencesFeature::onActionTriggered(bool isChecked) { this->disableModelChangeContribution(); - RiaApplication* app = RiaApplication::instance(); + RiaGuiApplication* app = RiaGuiApplication::instance(); QStringList tabNames = app->preferences()->tabNames(); @@ -57,6 +57,7 @@ void RicEditPreferencesFeature::onActionTriggered(bool isChecked) // Write preferences using QSettings and apply them to the application caf::PdmSettings::writeFieldsToApplicationStore(app->preferences()); app->applyPreferences(oldPreferences.get()); + app->applyGuiPreferences(oldPreferences.get()); } else { diff --git a/ApplicationCode/Commands/ApplicationCommands/RicExitApplicationFeature.cpp b/ApplicationCode/Commands/ApplicationCommands/RicExitApplicationFeature.cpp index 5233b6f6a1..09bc949b34 100644 --- a/ApplicationCode/Commands/ApplicationCommands/RicExitApplicationFeature.cpp +++ b/ApplicationCode/Commands/ApplicationCommands/RicExitApplicationFeature.cpp @@ -18,7 +18,7 @@ #include "RicExitApplicationFeature.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RiuMainWindow.h" #include @@ -41,7 +41,7 @@ void RicExitApplicationFeature::onActionTriggered(bool isChecked) { this->disableModelChangeContribution(); - RiaApplication* app = RiaApplication::instance(); + RiaGuiApplication* app = RiaGuiApplication::instance(); if (!app->askUserToSaveModifiedProject()) return; // Hide all windows first to make sure they get closed properly diff --git a/ApplicationCode/Commands/ApplicationCommands/RicHelpFeatures.cpp b/ApplicationCode/Commands/ApplicationCommands/RicHelpFeatures.cpp index 9d3d560719..89c91f7c5e 100644 --- a/ApplicationCode/Commands/ApplicationCommands/RicHelpFeatures.cpp +++ b/ApplicationCode/Commands/ApplicationCommands/RicHelpFeatures.cpp @@ -147,7 +147,7 @@ void RicHelpCommandLineFeature::onActionTriggered(bool isChecked) RiaApplication* app = RiaApplication::instance(); QString text = app->commandLineParameterHelp(); - app->showFormattedTextInMessageBox(text); + app->showInformationMessage(text); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/Commands/ApplicationCommands/RicOpenLastUsedFileFeature.cpp b/ApplicationCode/Commands/ApplicationCommands/RicOpenLastUsedFileFeature.cpp index 70c7580d35..82815def1c 100644 --- a/ApplicationCode/Commands/ApplicationCommands/RicOpenLastUsedFileFeature.cpp +++ b/ApplicationCode/Commands/ApplicationCommands/RicOpenLastUsedFileFeature.cpp @@ -40,7 +40,7 @@ bool RicOpenLastUsedFileFeature::isCommandEnabled() //-------------------------------------------------------------------------------------------------- void RicOpenLastUsedFileFeature::onActionTriggered(bool isChecked) { - RiaApplication* app = RiaApplication::instance(); + RiaGuiApplication* app = RiaGuiApplication::instance(); if (!app->askUserToSaveModifiedProject()) return; diff --git a/ApplicationCode/Commands/ApplicationCommands/RicOpenProjectFeature.cpp b/ApplicationCode/Commands/ApplicationCommands/RicOpenProjectFeature.cpp index 6cd939a452..1cba9fc3cd 100644 --- a/ApplicationCode/Commands/ApplicationCommands/RicOpenProjectFeature.cpp +++ b/ApplicationCode/Commands/ApplicationCommands/RicOpenProjectFeature.cpp @@ -18,7 +18,7 @@ #include "RicOpenProjectFeature.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RiuMainWindow.h" @@ -41,7 +41,7 @@ bool RicOpenProjectFeature::isCommandEnabled() //-------------------------------------------------------------------------------------------------- void RicOpenProjectFeature::onActionTriggered(bool isChecked) { - RiaApplication* app = RiaApplication::instance(); + RiaGuiApplication* app = RiaGuiApplication::instance(); if (!app->askUserToSaveModifiedProject()) return; diff --git a/ApplicationCode/Commands/ApplicationCommands/RicSaveProjectAsFeature.cpp b/ApplicationCode/Commands/ApplicationCommands/RicSaveProjectAsFeature.cpp index a8616fb13e..1b2efee34a 100644 --- a/ApplicationCode/Commands/ApplicationCommands/RicSaveProjectAsFeature.cpp +++ b/ApplicationCode/Commands/ApplicationCommands/RicSaveProjectAsFeature.cpp @@ -20,7 +20,7 @@ #include "RicSaveProjectFeature.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include @@ -42,9 +42,12 @@ void RicSaveProjectAsFeature::onActionTriggered(bool isChecked) { this->disableModelChangeContribution(); - RiaApplication* app = RiaApplication::instance(); - - app->saveProjectPromptForFileName(); + RiaGuiApplication* app = RiaGuiApplication::instance(); + if (app) + { + app->saveProjectPromptForFileName(); + } + } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/Commands/ApplicationCommands/RicSaveProjectFeature.cpp b/ApplicationCode/Commands/ApplicationCommands/RicSaveProjectFeature.cpp index 8a5c33c660..8690066de4 100644 --- a/ApplicationCode/Commands/ApplicationCommands/RicSaveProjectFeature.cpp +++ b/ApplicationCode/Commands/ApplicationCommands/RicSaveProjectFeature.cpp @@ -18,7 +18,7 @@ #include "RicSaveProjectFeature.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include @@ -39,7 +39,7 @@ void RicSaveProjectFeature::onActionTriggered(bool isChecked) { this->disableModelChangeContribution(); - RiaApplication* app = RiaApplication::instance(); + RiaGuiApplication* app = RiaGuiApplication::instance(); app->saveProject(); } diff --git a/ApplicationCode/Commands/ApplicationCommands/RicShowPlotDataFeature.cpp b/ApplicationCode/Commands/ApplicationCommands/RicShowPlotDataFeature.cpp index 032cb6e252..eafbaca629 100644 --- a/ApplicationCode/Commands/ApplicationCommands/RicShowPlotDataFeature.cpp +++ b/ApplicationCode/Commands/ApplicationCommands/RicShowPlotDataFeature.cpp @@ -18,7 +18,7 @@ #include "RicShowPlotDataFeature.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RimGridCrossPlot.h" #include "RimGridCrossPlotCurve.h" @@ -211,7 +211,7 @@ void RicShowPlotDataFeature::onActionTriggered(bool isChecked) return; } - RiuPlotMainWindow* plotwindow = RiaApplication::instance()->mainPlotWindow(); + RiuPlotMainWindow* plotwindow = RiaGuiApplication::instance()->mainPlotWindow(); CVF_ASSERT(plotwindow); for (RimSummaryPlot* summaryPlot : selectedSummaryPlots) @@ -248,7 +248,7 @@ void RicShowPlotDataFeature::setupActionLook(QAction* actionToSetup) //-------------------------------------------------------------------------------------------------- void RicShowPlotDataFeature::showTabbedTextWindow(RiuTabbedTextProvider* textProvider) { - RiuPlotMainWindow* plotwindow = RiaApplication::instance()->mainPlotWindow(); + RiuPlotMainWindow* plotwindow = RiaGuiApplication::instance()->mainPlotWindow(); CVF_ASSERT(plotwindow); RiuTabbedTextDialog* textWidget = new RiuTabbedTextDialog(textProvider); @@ -263,7 +263,7 @@ void RicShowPlotDataFeature::showTabbedTextWindow(RiuTabbedTextProvider* textPro //-------------------------------------------------------------------------------------------------- void RicShowPlotDataFeature::showTextWindow(const QString& title, const QString& text) { - RiuPlotMainWindow* plotwindow = RiaApplication::instance()->mainPlotWindow(); + RiuPlotMainWindow* plotwindow = RiaGuiApplication::instance()->mainPlotWindow(); CVF_ASSERT(plotwindow); RiuTextDialog* textWiget = new RiuTextDialog(); diff --git a/ApplicationCode/Commands/ApplicationCommands/RicShowPlotWindowFeature.cpp b/ApplicationCode/Commands/ApplicationCommands/RicShowPlotWindowFeature.cpp index 92f6ca31f8..a296d53e20 100644 --- a/ApplicationCode/Commands/ApplicationCommands/RicShowPlotWindowFeature.cpp +++ b/ApplicationCode/Commands/ApplicationCommands/RicShowPlotWindowFeature.cpp @@ -18,7 +18,7 @@ #include "RicShowPlotWindowFeature.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include @@ -39,7 +39,7 @@ void RicShowPlotWindowFeature::onActionTriggered(bool isChecked) { this->disableModelChangeContribution(); - RiaApplication::instance()->getOrCreateAndShowMainPlotWindow(); + RiaGuiApplication::instance()->getOrCreateAndShowMainPlotWindow(); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/Commands/ApplicationCommands/RicTileWindowsFeature.cpp b/ApplicationCode/Commands/ApplicationCommands/RicTileWindowsFeature.cpp index fb105f5fb1..a898152d6c 100644 --- a/ApplicationCode/Commands/ApplicationCommands/RicTileWindowsFeature.cpp +++ b/ApplicationCode/Commands/ApplicationCommands/RicTileWindowsFeature.cpp @@ -19,12 +19,12 @@ #include "RicTileWindowsFeature.h" +#include "RiaGuiApplication.h" #include "RiuMainWindow.h" #include "RiuPlotMainWindow.h" #include #include -#include "RiaApplication.h" CAF_CMD_SOURCE_INIT(RicTileWindowsFeature, "RicTileWindowsFeature"); @@ -80,9 +80,9 @@ void RicTileWindowsFeature::setupActionLook(QAction* actionToSetup) //-------------------------------------------------------------------------------------------------- bool RicTileWindowsFeature::isCommandChecked() { - if (RiaApplication::instance()->mainWindow()) + if (RiaGuiApplication::instance()->mainWindow()) { - return RiaApplication::instance()->mainWindow()->subWindowsAreTiled(); + return RiaGuiApplication::instance()->mainWindow()->subWindowsAreTiled(); } return false; } @@ -94,7 +94,7 @@ CAF_CMD_SOURCE_INIT(RicTilePlotWindowsFeature, "RicTilePlotWindowsFeature"); //-------------------------------------------------------------------------------------------------- bool RicTilePlotWindowsFeature::isCommandEnabled() { - RiuPlotMainWindow* mainPlotWindow = RiaApplication::instance()->mainPlotWindow(); + RiuPlotMainWindow* mainPlotWindow = RiaGuiApplication::instance()->mainPlotWindow(); if (mainPlotWindow) { return mainPlotWindow->isAnyMdiSubWindowVisible(); @@ -108,7 +108,7 @@ bool RicTilePlotWindowsFeature::isCommandEnabled() //-------------------------------------------------------------------------------------------------- void RicTilePlotWindowsFeature::onActionTriggered(bool isChecked) { - RiuPlotMainWindow* mainPlotWindow = RiaApplication::instance()->mainPlotWindow(); + RiuPlotMainWindow* mainPlotWindow = RiaGuiApplication::instance()->mainPlotWindow(); if (mainPlotWindow) { if (!mainPlotWindow->subWindowsAreTiled()) @@ -137,9 +137,9 @@ void RicTilePlotWindowsFeature::setupActionLook(QAction* actionToSetup) //-------------------------------------------------------------------------------------------------- bool RicTilePlotWindowsFeature::isCommandChecked() { - if (RiaApplication::instance()->mainPlotWindow()) + if (RiaGuiApplication::instance()->mainPlotWindow()) { - return RiaApplication::instance()->mainPlotWindow()->subWindowsAreTiled(); + return RiaGuiApplication::instance()->mainPlotWindow()->subWindowsAreTiled(); } return false; } diff --git a/ApplicationCode/Commands/ExportCommands/RicSnapshotAllPlotsToFileFeature.cpp b/ApplicationCode/Commands/ExportCommands/RicSnapshotAllPlotsToFileFeature.cpp index 548cbaccde..cfb961ee61 100644 --- a/ApplicationCode/Commands/ExportCommands/RicSnapshotAllPlotsToFileFeature.cpp +++ b/ApplicationCode/Commands/ExportCommands/RicSnapshotAllPlotsToFileFeature.cpp @@ -18,7 +18,7 @@ #include "RicSnapshotAllPlotsToFileFeature.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RiaLogging.h" #include "RimMainPlotCollection.h" @@ -48,7 +48,7 @@ CAF_CMD_SOURCE_INIT(RicSnapshotAllPlotsToFileFeature, "RicSnapshotAllPlotsToFile //-------------------------------------------------------------------------------------------------- void RicSnapshotAllPlotsToFileFeature::saveAllPlots() { - RiaApplication* app = RiaApplication::instance(); + RiaGuiApplication* app = RiaGuiApplication::instance(); RiuPlotMainWindow* mainPlotWindow = app->mainPlotWindow(); if (!mainPlotWindow) return; @@ -119,9 +119,9 @@ bool RicSnapshotAllPlotsToFileFeature::isCommandEnabled() void RicSnapshotAllPlotsToFileFeature::onActionTriggered(bool isChecked) { QWidget* currentActiveWidget = nullptr; - if (RiaApplication::activeViewWindow()) + if (RiaGuiApplication::activeViewWindow()) { - currentActiveWidget = RiaApplication::activeViewWindow()->viewWidget(); + currentActiveWidget = RiaGuiApplication::activeViewWindow()->viewWidget(); } RicSnapshotAllPlotsToFileFeature::saveAllPlots(); diff --git a/ApplicationCode/Commands/ExportCommands/RicSnapshotAllViewsToFileFeature.cpp b/ApplicationCode/Commands/ExportCommands/RicSnapshotAllViewsToFileFeature.cpp index 2d880c5cef..ceac51fa33 100644 --- a/ApplicationCode/Commands/ExportCommands/RicSnapshotAllViewsToFileFeature.cpp +++ b/ApplicationCode/Commands/ExportCommands/RicSnapshotAllViewsToFileFeature.cpp @@ -18,7 +18,7 @@ #include "RicSnapshotAllViewsToFileFeature.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RiaLogging.h" #include "RiaViewRedrawScheduler.h" @@ -151,9 +151,9 @@ bool RicSnapshotAllViewsToFileFeature::isCommandEnabled() void RicSnapshotAllViewsToFileFeature::onActionTriggered(bool isChecked) { QWidget* currentActiveWidget = nullptr; - if (RiaApplication::activeViewWindow()) + if (RiaGuiApplication::activeViewWindow()) { - currentActiveWidget = RiaApplication::activeViewWindow()->viewWidget(); + currentActiveWidget = RiaGuiApplication::activeViewWindow()->viewWidget(); } RicSnapshotAllViewsToFileFeature::saveAllViews(); diff --git a/ApplicationCode/Commands/ExportCommands/RicSnapshotViewToClipboardFeature.cpp b/ApplicationCode/Commands/ExportCommands/RicSnapshotViewToClipboardFeature.cpp index 79e7002aa0..ff5afcbc47 100644 --- a/ApplicationCode/Commands/ExportCommands/RicSnapshotViewToClipboardFeature.cpp +++ b/ApplicationCode/Commands/ExportCommands/RicSnapshotViewToClipboardFeature.cpp @@ -19,7 +19,7 @@ #include "RicSnapshotViewToClipboardFeature.h" #include "RicGridStatisticsDialog.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RiaLogging.h" #include "RimMainPlotCollection.h" @@ -82,7 +82,7 @@ void RicSnapshotViewToClipboardFeature::onActionTriggered(bool isChecked) { this->disableModelChangeContribution(); - RimViewWindow* viewWindow = RiaApplication::activeViewWindow(); + RimViewWindow* viewWindow = RiaGuiApplication::activeViewWindow(); if (viewWindow) { diff --git a/ApplicationCode/Commands/ExportCommands/RicSnapshotViewToFileFeature.cpp b/ApplicationCode/Commands/ExportCommands/RicSnapshotViewToFileFeature.cpp index c0e8520031..4faa429f7e 100644 --- a/ApplicationCode/Commands/ExportCommands/RicSnapshotViewToFileFeature.cpp +++ b/ApplicationCode/Commands/ExportCommands/RicSnapshotViewToFileFeature.cpp @@ -18,7 +18,7 @@ #include "RicSnapshotViewToFileFeature.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RiaLogging.h" #include "RimMainPlotCollection.h" @@ -135,7 +135,7 @@ void RicSnapshotViewToFileFeature::onActionTriggered(bool isChecked) // If this is done after the file save dialog is displayed (and closed) // app->activeViewWindow() returns nullptr on Linux - RimViewWindow* viewWindow = RiaApplication::activeViewWindow(); + RimViewWindow* viewWindow = RiaGuiApplication::activeViewWindow(); if (!viewWindow) { RiaLogging::error("No view window is available, nothing to do"); diff --git a/ApplicationCode/Commands/FlowCommands/RicPlotProductionRateFeature.cpp b/ApplicationCode/Commands/FlowCommands/RicPlotProductionRateFeature.cpp index a0d32c9007..8b9d0aa85a 100644 --- a/ApplicationCode/Commands/FlowCommands/RicPlotProductionRateFeature.cpp +++ b/ApplicationCode/Commands/FlowCommands/RicPlotProductionRateFeature.cpp @@ -18,7 +18,7 @@ #include "RicPlotProductionRateFeature.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RiaPreferences.h" #include "RifEclipseSummaryAddress.h" @@ -184,7 +184,7 @@ void RicPlotProductionRateFeature::onActionTriggered(bool isChecked) if (summaryPlotToSelect) { - RiuPlotMainWindow* mainPlotWindow = RiaApplication::instance()->getOrCreateAndShowMainPlotWindow(); + RiuPlotMainWindow* mainPlotWindow = RiaGuiApplication::instance()->getOrCreateAndShowMainPlotWindow(); if (mainPlotWindow) { mainPlotWindow->selectAsCurrentItem(summaryPlotToSelect); diff --git a/ApplicationCode/Commands/FlowCommands/RicSelectViewUI.cpp b/ApplicationCode/Commands/FlowCommands/RicSelectViewUI.cpp index e5c54e2a43..19ff6609ab 100644 --- a/ApplicationCode/Commands/FlowCommands/RicSelectViewUI.cpp +++ b/ApplicationCode/Commands/FlowCommands/RicSelectViewUI.cpp @@ -104,10 +104,10 @@ QList RicSelectViewUI::calculateValueOptions(const caf:: { for (Rim3dView* v : m_currentCase->views()) { - QIcon icon = v->uiCapability()->uiIcon(); + caf::QIconProvider iconProvider = v->uiCapability()->uiIconProvider(); QString displayName = v->name(); - options.push_back(caf::PdmOptionItemInfo(displayName, v, false, icon)); + options.push_back(caf::PdmOptionItemInfo(displayName, v, false, iconProvider)); } } } diff --git a/ApplicationCode/Commands/FlowCommands/RicShowContributingWellsFromPlotFeature.cpp b/ApplicationCode/Commands/FlowCommands/RicShowContributingWellsFromPlotFeature.cpp index dc275d9442..e19fdbf96c 100644 --- a/ApplicationCode/Commands/FlowCommands/RicShowContributingWellsFromPlotFeature.cpp +++ b/ApplicationCode/Commands/FlowCommands/RicShowContributingWellsFromPlotFeature.cpp @@ -18,7 +18,7 @@ #include "RicShowContributingWellsFromPlotFeature.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RicShowContributingWellsFeatureImpl.h" @@ -36,7 +36,7 @@ CAF_CMD_SOURCE_INIT(RicShowContributingWellsFromPlotFeature, "RicShowContributin bool RicShowContributingWellsFromPlotFeature::isCommandEnabled() { RimWellAllocationPlot* wellAllocationPlot = - dynamic_cast(RiaApplication::instance()->activePlotWindow()); + dynamic_cast(RiaGuiApplication::instance()->activePlotWindow()); if (wellAllocationPlot) return true; @@ -49,7 +49,7 @@ bool RicShowContributingWellsFromPlotFeature::isCommandEnabled() void RicShowContributingWellsFromPlotFeature::onActionTriggered(bool isChecked) { RimWellAllocationPlot* wellAllocationPlot = - dynamic_cast(RiaApplication::instance()->activePlotWindow()); + dynamic_cast(RiaGuiApplication::instance()->activePlotWindow()); if (!wellAllocationPlot) return; diff --git a/ApplicationCode/Commands/GridCrossPlotCommands/RicCreateGridCrossPlotDataSetFeature.cpp b/ApplicationCode/Commands/GridCrossPlotCommands/RicCreateGridCrossPlotDataSetFeature.cpp index dd64da706d..e5bda407be 100644 --- a/ApplicationCode/Commands/GridCrossPlotCommands/RicCreateGridCrossPlotDataSetFeature.cpp +++ b/ApplicationCode/Commands/GridCrossPlotCommands/RicCreateGridCrossPlotDataSetFeature.cpp @@ -17,7 +17,7 @@ ///////////////////////////////////////////////////////////////////////////////// #include "RicCreateGridCrossPlotDataSetFeature.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RimGridCrossPlot.h" #include "RimGridCrossPlotDataSet.h" @@ -49,7 +49,7 @@ void RicCreateGridCrossPlotDataSetFeature::onActionTriggered(bool isChecked) RimGridCrossPlotDataSet* dataSet = crossPlot->createDataSet(); dataSet->loadDataAndUpdate(true); - RiaApplication::instance()->getOrCreateMainPlotWindow(); + RiaGuiApplication::instance()->getOrCreateMainPlotWindow(); RiuPlotMainWindowTools::selectAsCurrentItem(dataSet); } diff --git a/ApplicationCode/Commands/GridCrossPlotCommands/RicCreateGridCrossPlotFeature.cpp b/ApplicationCode/Commands/GridCrossPlotCommands/RicCreateGridCrossPlotFeature.cpp index b25e39c465..b0702b4986 100644 --- a/ApplicationCode/Commands/GridCrossPlotCommands/RicCreateGridCrossPlotFeature.cpp +++ b/ApplicationCode/Commands/GridCrossPlotCommands/RicCreateGridCrossPlotFeature.cpp @@ -17,7 +17,7 @@ ///////////////////////////////////////////////////////////////////////////////// #include "RicCreateGridCrossPlotFeature.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RimEclipseView.h" #include "RimGridCrossPlot.h" @@ -71,7 +71,7 @@ void RicCreateGridCrossPlotFeature::onActionTriggered(bool isChecked) plot->updateConnectedEditors(); collection->updateAllRequiredEditors(); - RiaApplication::instance()->getOrCreateAndShowMainPlotWindow(); + RiaGuiApplication::instance()->getOrCreateAndShowMainPlotWindow(); RiuPlotMainWindowTools::selectAsCurrentItem(dataSet); } diff --git a/ApplicationCode/Commands/GridCrossPlotCommands/RicCreateSaturationPressurePlotsFeature.cpp b/ApplicationCode/Commands/GridCrossPlotCommands/RicCreateSaturationPressurePlotsFeature.cpp index a290bccfe6..3018c39ee9 100644 --- a/ApplicationCode/Commands/GridCrossPlotCommands/RicCreateSaturationPressurePlotsFeature.cpp +++ b/ApplicationCode/Commands/GridCrossPlotCommands/RicCreateSaturationPressurePlotsFeature.cpp @@ -19,7 +19,7 @@ #include "RicCreateSaturationPressurePlotsFeature.h" #include "RicSaturationPressureUi.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RiaLogging.h" #include "RiaPorosityModel.h" @@ -147,7 +147,7 @@ void RicCreateSaturationPressurePlotsFeature::onActionTriggered(bool isChecked) RicSaturationPressureUi saturationPressureUi; saturationPressureUi.setSelectedCase(eclipseCases[0]); - RiuPlotMainWindow* plotwindow = RiaApplication::instance()->mainPlotWindow(); + RiuPlotMainWindow* plotwindow = RiaGuiApplication::instance()->mainPlotWindow(); caf::PdmUiPropertyViewDialog propertyDialog( plotwindow, &saturationPressureUi, "Select Case to create Pressure Saturation plots", ""); @@ -182,7 +182,7 @@ void RicCreateSaturationPressurePlotsFeature::onActionTriggered(bool isChecked) } collection->updateAllRequiredEditors(); - RiaApplication::instance()->getOrCreateAndShowMainPlotWindow(); + RiaGuiApplication::instance()->getOrCreateAndShowMainPlotWindow(); if (objectToSelect) { diff --git a/ApplicationCode/Commands/GridCrossPlotCommands/RicPasteGridCrossPlotDataSetFeature.cpp b/ApplicationCode/Commands/GridCrossPlotCommands/RicPasteGridCrossPlotDataSetFeature.cpp index 999937fab3..ff6d4339f6 100644 --- a/ApplicationCode/Commands/GridCrossPlotCommands/RicPasteGridCrossPlotDataSetFeature.cpp +++ b/ApplicationCode/Commands/GridCrossPlotCommands/RicPasteGridCrossPlotDataSetFeature.cpp @@ -18,7 +18,7 @@ #include "RicPasteGridCrossPlotDataSetFeature.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RimGridCrossPlot.h" #include "RimGridCrossPlotDataSet.h" #include "RiuPlotMainWindowTools.h" @@ -70,7 +70,7 @@ void RicPasteGridCrossPlotDataSetFeature::onActionTriggered(bool isChecked) } - RiaApplication::instance()->getOrCreateMainPlotWindow(); + RiaGuiApplication::instance()->getOrCreateMainPlotWindow(); crossPlot->updateAllRequiredEditors(); crossPlot->loadDataAndUpdate(); diff --git a/ApplicationCode/Commands/MeasurementCommands/RicToggleMeasurementModeFeature.cpp b/ApplicationCode/Commands/MeasurementCommands/RicToggleMeasurementModeFeature.cpp index 07074bc241..a4e426d3e7 100644 --- a/ApplicationCode/Commands/MeasurementCommands/RicToggleMeasurementModeFeature.cpp +++ b/ApplicationCode/Commands/MeasurementCommands/RicToggleMeasurementModeFeature.cpp @@ -18,7 +18,7 @@ #include "RicToggleMeasurementModeFeature.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "Rim3dView.h" #include "RimMeasurement.h" @@ -110,7 +110,10 @@ bool RicToggleMeasurementModeFeature::isCommandChecked() //-------------------------------------------------------------------------------------------------- RimMeasurement* RicToggleMeasurementModeFeature::measurement() const { - return RiaApplication::instance()->project()->measurement(); + RiaGuiApplication* app = RiaGuiApplication::instance(); + CAF_ASSERT(app && app->project()); + + return app->project()->measurement(); } //-------------------------------------------------------------------------------------------------- @@ -118,7 +121,9 @@ RimMeasurement* RicToggleMeasurementModeFeature::measurement() const //-------------------------------------------------------------------------------------------------- Rim3dView* RicToggleMeasurementModeFeature::activeView() const { - auto view = RiaApplication::instance()->activeReservoirView(); + RiaApplication* app = RiaApplication::instance(); + CAF_ASSERT(app); + auto view = app->activeReservoirView(); return view; } diff --git a/ApplicationCode/Commands/RicCloseSummaryCaseFeature.cpp b/ApplicationCode/Commands/RicCloseSummaryCaseFeature.cpp index 9766037dd6..17ad88711d 100644 --- a/ApplicationCode/Commands/RicCloseSummaryCaseFeature.cpp +++ b/ApplicationCode/Commands/RicCloseSummaryCaseFeature.cpp @@ -18,7 +18,7 @@ #include "RicCloseSummaryCaseFeature.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RiaSummaryTools.h" #include "RimMainPlotCollection.h" @@ -70,7 +70,7 @@ void RicCloseSummaryCaseFeature::deleteSummaryCases(std::vector summaryCaseMainCollection->updateAllRequiredEditors(); - RiuPlotMainWindow* mainPlotWindow = RiaApplication::instance()->mainPlotWindow(); + RiuPlotMainWindow* mainPlotWindow = RiaGuiApplication::instance()->mainPlotWindow(); mainPlotWindow->updateSummaryPlotToolBar(); caf::AsyncPdmObjectVectorDeleter summaryCaseDeleter(cases); diff --git a/ApplicationCode/Commands/RicCloseSummaryCaseInCollectionFeature.cpp b/ApplicationCode/Commands/RicCloseSummaryCaseInCollectionFeature.cpp index 7a6429ee31..9d83e2adb4 100644 --- a/ApplicationCode/Commands/RicCloseSummaryCaseInCollectionFeature.cpp +++ b/ApplicationCode/Commands/RicCloseSummaryCaseInCollectionFeature.cpp @@ -18,7 +18,7 @@ #include "RicCloseSummaryCaseInCollectionFeature.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RicCloseSummaryCaseFeature.h" @@ -94,7 +94,7 @@ void RicCloseSummaryCaseInCollectionFeature::onActionTriggered(bool isChecked) RicCloseSummaryCaseFeature::deleteSummaryCases(collectionSummaryCases); } - RiuPlotMainWindow* mainPlotWindow = RiaApplication::instance()->mainPlotWindow(); + RiuPlotMainWindow* mainPlotWindow = RiaGuiApplication::instance()->mainPlotWindow(); mainPlotWindow->updateSummaryPlotToolBar(); } diff --git a/ApplicationCode/Commands/RicCreateTemporaryLgrFeature.cpp b/ApplicationCode/Commands/RicCreateTemporaryLgrFeature.cpp index d13090c4f7..6a429bf347 100644 --- a/ApplicationCode/Commands/RicCreateTemporaryLgrFeature.cpp +++ b/ApplicationCode/Commands/RicCreateTemporaryLgrFeature.cpp @@ -18,7 +18,7 @@ #include "RicCreateTemporaryLgrFeature.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RiaCellDividingTools.h" #include "RiaCompletionTypeCalculationScheduler.h" #include "RiaLogging.h" @@ -110,7 +110,9 @@ void RicCreateTemporaryLgrFeature::createLgrsForWellPaths(std::vectorclearAllSelections(); deleteAllCachedData(eclipseCase); RiaApplication::instance()->project()->mainPlotCollection()->deleteAllCachedData(); diff --git a/ApplicationCode/Commands/RicDeleteItemExec.cpp b/ApplicationCode/Commands/RicDeleteItemExec.cpp index a4f10ee4bb..a5d12b5883 100644 --- a/ApplicationCode/Commands/RicDeleteItemExec.cpp +++ b/ApplicationCode/Commands/RicDeleteItemExec.cpp @@ -21,7 +21,7 @@ #include "RicDeleteItemExec.h" #include "RicDeleteItemExecData.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "Rim3dView.h" #include "RimAnnotationCollection.h" @@ -204,7 +204,7 @@ void RicDeleteItemExec::redo() { wellLogPlot->calculateAvailableDepthRange(); wellLogPlot->updateDepthZoom(); - RiuPlotMainWindow* mainPlotWindow = RiaApplication::instance()->mainPlotWindow(); + RiuPlotMainWindow* mainPlotWindow = RiaGuiApplication::instance()->mainPlotWindow(); mainPlotWindow->updateWellLogPlotToolBar(); } @@ -213,7 +213,7 @@ void RicDeleteItemExec::redo() if (wellLogPlotTrack) { wellLogPlotTrack->calculateXZoomRangeAndUpdateQwt(); - RiuPlotMainWindow* mainPlotWindow = RiaApplication::instance()->mainPlotWindow(); + RiuPlotMainWindow* mainPlotWindow = RiaGuiApplication::instance()->mainPlotWindow(); mainPlotWindow->updateWellLogPlotToolBar(); } @@ -232,7 +232,7 @@ void RicDeleteItemExec::redo() project->updateConnectedEditors(); } } - RiuPlotMainWindow* mainPlotWindow = RiaApplication::instance()->mainPlotWindow(); + RiuPlotMainWindow* mainPlotWindow = RiaGuiApplication::instance()->mainPlotWindow(); mainPlotWindow->updateWellLogPlotToolBar(); } @@ -273,7 +273,7 @@ void RicDeleteItemExec::redo() if (summaryPlotCollection) { summaryPlotCollection->updateSummaryNameHasChanged(); - RiuPlotMainWindow* mainPlotWindow = RiaApplication::instance()->mainPlotWindow(); + RiuPlotMainWindow* mainPlotWindow = RiaGuiApplication::instance()->mainPlotWindow(); mainPlotWindow->updateSummaryPlotToolBar(); } @@ -281,7 +281,7 @@ void RicDeleteItemExec::redo() parentObj->firstAncestorOrThisOfType(summaryCrossPlotCollection); if (summaryCrossPlotCollection) { - RiuPlotMainWindow* mainPlotWindow = RiaApplication::instance()->mainPlotWindow(); + RiuPlotMainWindow* mainPlotWindow = RiaGuiApplication::instance()->mainPlotWindow(); mainPlotWindow->updateSummaryPlotToolBar(); } diff --git a/ApplicationCode/Commands/RicDeleteTemporaryLgrsFeature.cpp b/ApplicationCode/Commands/RicDeleteTemporaryLgrsFeature.cpp index 14630fe89f..55c3332ada 100644 --- a/ApplicationCode/Commands/RicDeleteTemporaryLgrsFeature.cpp +++ b/ApplicationCode/Commands/RicDeleteTemporaryLgrsFeature.cpp @@ -19,7 +19,7 @@ #include "RicDeleteTemporaryLgrsFeature.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RimEclipseCase.h" #include "RimGridCollection.h" @@ -37,7 +37,7 @@ CAF_CMD_SOURCE_INIT(RicDeleteTemporaryLgrsFeature, "RicDeleteTemporaryLgrsFeatur //-------------------------------------------------------------------------------------------------- void RicDeleteTemporaryLgrsFeature::deleteAllTemporaryLgrs(RimEclipseCase* eclipseCase) { - RiaApplication::clearAllSelections(); + RiaGuiApplication::clearAllSelections(); if (eclipseCase) { diff --git a/ApplicationCode/Commands/RicImportGeneralDataFeature.cpp b/ApplicationCode/Commands/RicImportGeneralDataFeature.cpp index 2e1a485996..d84ee40e6d 100644 --- a/ApplicationCode/Commands/RicImportGeneralDataFeature.cpp +++ b/ApplicationCode/Commands/RicImportGeneralDataFeature.cpp @@ -40,7 +40,7 @@ CAF_CMD_SOURCE_INIT(RicImportGeneralDataFeature, "RicImportGeneralDataFeature"); //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool RicImportGeneralDataFeature::openEclipseFilesFromFileNames(const QStringList& fileNames) +RicImportGeneralDataFeature::OpenCaseResults RicImportGeneralDataFeature::openEclipseFilesFromFileNames(const QStringList& fileNames) { CVF_ASSERT(!fileNames.empty()); @@ -66,23 +66,35 @@ bool RicImportGeneralDataFeature::openEclipseFilesFromFileNames(const QStringLis } } - bool allSucceeded = true; + OpenCaseResults results; if (!eclipseCaseFiles.empty()) { - allSucceeded = allSucceeded && openEclipseCaseFromFileNames(eclipseCaseFiles); - RiaApplication::instance()->setLastUsedDialogDirectory(defaultDirectoryLabel(ECLIPSE_EGRID_FILE), defaultDir); + if (!openEclipseCaseFromFileNames(eclipseCaseFiles)) + { + return OpenCaseResults(); + } + results.eclipseCaseFiles = eclipseCaseFiles; + RiaApplication::instance()->setLastUsedDialogDirectory(defaultDirectoryLabel(ECLIPSE_EGRID_FILE), defaultDir); } if (!eclipseInputFiles.empty()) { - allSucceeded = allSucceeded && openInputEclipseCaseFromFileNames(eclipseInputFiles); - RiaApplication::instance()->setLastUsedDialogDirectory(defaultDirectoryLabel(ECLIPSE_INPUT_FILE), defaultDir); + if (!openInputEclipseCaseFromFileNames(eclipseInputFiles)) + { + return OpenCaseResults(); + } + results.eclipseInputFiles = eclipseInputFiles; + RiaApplication::instance()->setLastUsedDialogDirectory(defaultDirectoryLabel(ECLIPSE_INPUT_FILE), defaultDir); } if (!eclipseSummaryFiles.empty()) { - allSucceeded = allSucceeded && openSummaryCaseFromFileNames(eclipseSummaryFiles); + if (!openSummaryCaseFromFileNames(eclipseSummaryFiles)) + { + return OpenCaseResults(); + } + results.eclipseSummaryFiles = eclipseSummaryFiles; RiaApplication::instance()->setLastUsedDialogDirectory(defaultDirectoryLabel(ECLIPSE_SUMMARY_FILE), defaultDir); } - return allSucceeded; + return results; } diff --git a/ApplicationCode/Commands/RicImportGeneralDataFeature.h b/ApplicationCode/Commands/RicImportGeneralDataFeature.h index 3cfc15a085..5211b60ceb 100644 --- a/ApplicationCode/Commands/RicImportGeneralDataFeature.h +++ b/ApplicationCode/Commands/RicImportGeneralDataFeature.h @@ -22,6 +22,8 @@ #include "cafCmdFeature.h" +#include + #include //================================================================================================== @@ -32,7 +34,19 @@ class RicImportGeneralDataFeature : public caf::CmdFeature CAF_CMD_HEADER_INIT; public: - static bool openEclipseFilesFromFileNames(const QStringList& fileNames); + struct OpenCaseResults + { + QStringList eclipseCaseFiles; + QStringList eclipseInputFiles; + QStringList eclipseSummaryFiles; + + operator bool() const + { + return !(eclipseCaseFiles.empty() && eclipseInputFiles.empty() && eclipseSummaryFiles.empty()); + } + }; + + static OpenCaseResults openEclipseFilesFromFileNames(const QStringList& fileNames); protected: diff --git a/ApplicationCode/Commands/RicImportSummaryCasesFeature.cpp b/ApplicationCode/Commands/RicImportSummaryCasesFeature.cpp index f7ea9c8141..64877e509c 100644 --- a/ApplicationCode/Commands/RicImportSummaryCasesFeature.cpp +++ b/ApplicationCode/Commands/RicImportSummaryCasesFeature.cpp @@ -20,7 +20,7 @@ #include "SummaryPlotCommands/RicNewSummaryCurveFeature.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RiaLogging.h" #include "RiaPreferences.h" @@ -73,7 +73,7 @@ bool RicImportSummaryCasesFeature::isCommandEnabled() //-------------------------------------------------------------------------------------------------- void RicImportSummaryCasesFeature::onActionTriggered(bool isChecked) { - RiaApplication* app = RiaApplication::instance(); + RiaGuiApplication* app = RiaGuiApplication::instance(); QString pathCacheName = "INPUT_FILES"; QStringList fileNames = runRecursiveSummaryCaseFileSearchDialog("Import Summary Cases", pathCacheName); @@ -89,7 +89,7 @@ void RicImportSummaryCasesFeature::onActionTriggered(bool isChecked) addCasesToGroupIfRelevant(cases); for (const auto& rimCase : cases) - RiaApplication::instance()->addToRecentFiles(rimCase->summaryHeaderFilename()); + app->addToRecentFiles(rimCase->summaryHeaderFilename()); RiuPlotMainWindow* mainPlotWindow = app->getOrCreateAndShowMainPlotWindow(); if (mainPlotWindow && !cases.empty()) @@ -123,7 +123,7 @@ void RicImportSummaryCasesFeature::setupActionLook(QAction* actionToSetup) bool RicImportSummaryCasesFeature::createAndAddSummaryCasesFromFiles(const QStringList& fileNames, std::vector* newCases) { - RiaApplication* app = RiaApplication::instance(); + RiaGuiApplication* app = RiaGuiApplication::instance(); std::vector temp; std::vector* cases = newCases ? newCases : &temp; diff --git a/ApplicationCode/Commands/RicImportSummaryGroupFeature.cpp b/ApplicationCode/Commands/RicImportSummaryGroupFeature.cpp index 0f98bf2eec..f204d66164 100644 --- a/ApplicationCode/Commands/RicImportSummaryGroupFeature.cpp +++ b/ApplicationCode/Commands/RicImportSummaryGroupFeature.cpp @@ -18,7 +18,7 @@ #include "RicImportSummaryGroupFeature.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RiaPreferences.h" #include "RicImportSummaryCasesFeature.h" @@ -60,7 +60,7 @@ bool RicImportSummaryGroupFeature::isCommandEnabled() //-------------------------------------------------------------------------------------------------- void RicImportSummaryGroupFeature::onActionTriggered(bool isChecked) { - RiaApplication* app = RiaApplication::instance(); + RiaGuiApplication* app = RiaGuiApplication::instance(); QString pathCacheName = "INPUT_FILES"; QStringList fileNames = RicImportSummaryCasesFeature::runRecursiveSummaryCaseFileSearchDialog("Import Summary Case Group", pathCacheName); diff --git a/ApplicationCode/Commands/RicReloadCaseFeature.cpp b/ApplicationCode/Commands/RicReloadCaseFeature.cpp index 42d5afaaba..ec1a37da94 100644 --- a/ApplicationCode/Commands/RicReloadCaseFeature.cpp +++ b/ApplicationCode/Commands/RicReloadCaseFeature.cpp @@ -19,7 +19,7 @@ #include "RicReloadCaseFeature.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RimEclipseCase.h" #include "RimReloadCaseTools.h" @@ -60,7 +60,7 @@ void RicReloadCaseFeature::onActionTriggered(bool isChecked) std::vector selectedEclipseCases; caf::SelectionManager::instance()->objectsByType(&selectedEclipseCases); - RiaApplication::clearAllSelections(); + RiaGuiApplication::clearAllSelections(); for (RimEclipseCase* selectedCase : selectedEclipseCases) { diff --git a/ApplicationCode/Commands/RicSummaryCaseRestartDialog.cpp b/ApplicationCode/Commands/RicSummaryCaseRestartDialog.cpp index 8d71986717..c3fb449eb6 100644 --- a/ApplicationCode/Commands/RicSummaryCaseRestartDialog.cpp +++ b/ApplicationCode/Commands/RicSummaryCaseRestartDialog.cpp @@ -21,7 +21,7 @@ #include "ExportCommands/RicSnapshotViewToFileFeature.h" #include "ExportCommands/RicSnapshotFilenameGenerator.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RiaFilePathTools.h" #include "RiaLogging.h" #include "RiaQDateTimeTools.h" @@ -611,7 +611,7 @@ void RicSummaryCaseRestartDialog::slotCopyFileNameToClipboard() { QAction* a = dynamic_cast(sender()); - QClipboard* cb = RiaApplication::clipboard(); + QClipboard* cb = RiaGuiApplication::clipboard(); if (cb) { QString fullFileName = a->data().toString(); diff --git a/ApplicationCode/Commands/RicWellLogTools.cpp b/ApplicationCode/Commands/RicWellLogTools.cpp index 007303aa6d..948f7d9e18 100644 --- a/ApplicationCode/Commands/RicWellLogTools.cpp +++ b/ApplicationCode/Commands/RicWellLogTools.cpp @@ -18,7 +18,7 @@ #include "RicWellLogTools.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RimCase.h" #include "RimEclipseResultCase.h" @@ -205,7 +205,7 @@ RimWellLogExtractionCurve* RicWellLogTools::addExtractionCurve(RimWellLogTrack* plotTrack->updateConnectedEditors(); RiaApplication::instance()->project()->updateConnectedEditors(); - RiaApplication::instance()->getOrCreateMainPlotWindow(); + RiaGuiApplication::instance()->getOrCreateMainPlotWindow(); RiuPlotMainWindowTools::selectAsCurrentItem(curve); if (showPlotWindow) @@ -257,7 +257,7 @@ RimWellLogRftCurve* RicWellLogTools::addRftCurve(RimWellLogTrack* plotTrack, con plotTrack->updateConnectedEditors(); RiaApplication::instance()->project()->updateConnectedEditors(); - RiaApplication::instance()->getOrCreateMainPlotWindow(); + RiaGuiApplication::instance()->getOrCreateMainPlotWindow(); RiuPlotMainWindowTools::selectAsCurrentItem(curve); if (showPlotWindow) @@ -286,7 +286,7 @@ RimWellLogFileCurve* RicWellLogTools::addFileCurve(RimWellLogTrack* plotTrack, b plotTrack->updateConnectedEditors(); RiaApplication::instance()->project()->updateConnectedEditors(); - RiaApplication::instance()->getOrCreateMainPlotWindow(); + RiaGuiApplication::instance()->getOrCreateMainPlotWindow(); RiuPlotMainWindowTools::selectAsCurrentItem(curve); if (showPlotWindow) diff --git a/ApplicationCode/Commands/SummaryPlotCommands/RicNewGridTimeHistoryCurveFeature.cpp b/ApplicationCode/Commands/SummaryPlotCommands/RicNewGridTimeHistoryCurveFeature.cpp index 605c2ce330..7cff27f7a5 100644 --- a/ApplicationCode/Commands/SummaryPlotCommands/RicNewGridTimeHistoryCurveFeature.cpp +++ b/ApplicationCode/Commands/SummaryPlotCommands/RicNewGridTimeHistoryCurveFeature.cpp @@ -18,7 +18,7 @@ #include "RicNewGridTimeHistoryCurveFeature.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RiaSummaryTools.h" #include "RigFemResultAddress.h" @@ -82,14 +82,16 @@ void RicNewGridTimeHistoryCurveFeature::createCurveFromSelectionItem(const RiuSe //-------------------------------------------------------------------------------------------------- RimSummaryPlot* RicNewGridTimeHistoryCurveFeature::userSelectedSummaryPlot() { + RiaGuiApplication* app = RiaGuiApplication::instance(); + const QString lastUsedSummaryPlotKey("lastUsedSummaryPlotKey"); RimSummaryPlotCollection* summaryPlotColl = RiaSummaryTools::summaryPlotCollection(); RimSummaryPlot* defaultSelectedPlot = nullptr; { - QString lastUsedPlotRef = RiaApplication::instance()->cacheDataObject(lastUsedSummaryPlotKey).toString(); - RimSummaryPlot* lastUsedPlot = dynamic_cast(caf::PdmReferenceHelper::objectFromReference(RiaApplication::instance()->project(), lastUsedPlotRef)); + QString lastUsedPlotRef = app->cacheDataObject(lastUsedSummaryPlotKey).toString(); + RimSummaryPlot* lastUsedPlot = dynamic_cast(caf::PdmReferenceHelper::objectFromReference(app->project(), lastUsedPlotRef)); if (lastUsedPlot) { defaultSelectedPlot = lastUsedPlot; @@ -97,7 +99,7 @@ RimSummaryPlot* RicNewGridTimeHistoryCurveFeature::userSelectedSummaryPlot() if (!defaultSelectedPlot) { - defaultSelectedPlot = dynamic_cast( RiaApplication::instance()->activePlotWindow() ); + defaultSelectedPlot = dynamic_cast( app->activePlotWindow() ); } if (!defaultSelectedPlot && summaryPlotColl->summaryPlots().size() > 0) @@ -136,8 +138,8 @@ RimSummaryPlot* RicNewGridTimeHistoryCurveFeature::userSelectedSummaryPlot() summaryPlot = featureUi.selectedSummaryPlot(); } - QString refFromProjectToView = caf::PdmReferenceHelper::referenceFromRootToObject(RiaApplication::instance()->project(), summaryPlot); - RiaApplication::instance()->setCacheDataObject(lastUsedSummaryPlotKey, refFromProjectToView); + QString refFromProjectToView = caf::PdmReferenceHelper::referenceFromRootToObject(app->project(), summaryPlot); + app->setCacheDataObject(lastUsedSummaryPlotKey, refFromProjectToView); return summaryPlot; } @@ -147,7 +149,6 @@ RimSummaryPlot* RicNewGridTimeHistoryCurveFeature::userSelectedSummaryPlot() //-------------------------------------------------------------------------------------------------- QString RicNewGridTimeHistoryCurveFeature::suggestedNewPlotName() { - QString resultName; { Rim3dView* activeView = RiaApplication::instance()->activeReservoirView(); diff --git a/ApplicationCode/Commands/SummaryPlotCommands/RicNewSummaryCrossPlotCurveFeature.cpp b/ApplicationCode/Commands/SummaryPlotCommands/RicNewSummaryCrossPlotCurveFeature.cpp index e61d1e9961..b6d1fda69a 100644 --- a/ApplicationCode/Commands/SummaryPlotCommands/RicNewSummaryCrossPlotCurveFeature.cpp +++ b/ApplicationCode/Commands/SummaryPlotCommands/RicNewSummaryCrossPlotCurveFeature.cpp @@ -18,7 +18,7 @@ #include "RicNewSummaryCrossPlotCurveFeature.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RiaSummaryTools.h" #include "RimMainPlotCollection.h" @@ -76,9 +76,9 @@ void RicNewSummaryCrossPlotCurveFeature::onActionTriggered(bool isChecked) plot->updateConnectedEditors(); - RiaApplication::instance()->getOrCreateAndShowMainPlotWindow()->selectAsCurrentItem(newCurve); + RiaGuiApplication::instance()->getOrCreateAndShowMainPlotWindow()->selectAsCurrentItem(newCurve); - RiuPlotMainWindow* mainPlotWindow = RiaApplication::instance()->mainPlotWindow(); + RiuPlotMainWindow* mainPlotWindow = RiaGuiApplication::instance()->mainPlotWindow(); mainPlotWindow->updateSummaryPlotToolBar(); } } diff --git a/ApplicationCode/Commands/SummaryPlotCommands/RicNewSummaryCurveFeature.cpp b/ApplicationCode/Commands/SummaryPlotCommands/RicNewSummaryCurveFeature.cpp index 5f418670d1..9f82c5683b 100644 --- a/ApplicationCode/Commands/SummaryPlotCommands/RicNewSummaryCurveFeature.cpp +++ b/ApplicationCode/Commands/SummaryPlotCommands/RicNewSummaryCurveFeature.cpp @@ -18,7 +18,7 @@ #include "RicNewSummaryCurveFeature.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RiaColorTables.h" #include "RiaSummaryTools.h" @@ -117,7 +117,8 @@ bool RicNewSummaryCurveFeature::isCommandEnabled() //-------------------------------------------------------------------------------------------------- void RicNewSummaryCurveFeature::onActionTriggered(bool isChecked) { - RimProject* project = RiaApplication::instance()->project(); + RiaGuiApplication* app = RiaGuiApplication::instance(); + RimProject* project = app->project(); CVF_ASSERT(project); RimSummaryPlot* plot = selectedSummaryPlot(); @@ -133,9 +134,9 @@ void RicNewSummaryCurveFeature::onActionTriggered(bool isChecked) plot->updateConnectedEditors(); - RiaApplication::instance()->getOrCreateAndShowMainPlotWindow()->selectAsCurrentItem(newCurve); + app->getOrCreateAndShowMainPlotWindow()->selectAsCurrentItem(newCurve); - RiuPlotMainWindow* mainPlotWindow = RiaApplication::instance()->mainPlotWindow(); + RiuPlotMainWindow* mainPlotWindow = app->mainPlotWindow(); mainPlotWindow->updateSummaryPlotToolBar(); } } diff --git a/ApplicationCode/Commands/SummaryPlotCommands/RicNewSummaryEnsembleCurveSetFeature.cpp b/ApplicationCode/Commands/SummaryPlotCommands/RicNewSummaryEnsembleCurveSetFeature.cpp index 503fbc9a30..e9c3a40001 100644 --- a/ApplicationCode/Commands/SummaryPlotCommands/RicNewSummaryEnsembleCurveSetFeature.cpp +++ b/ApplicationCode/Commands/SummaryPlotCommands/RicNewSummaryEnsembleCurveSetFeature.cpp @@ -18,7 +18,7 @@ #include "RicNewSummaryEnsembleCurveSetFeature.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RiaColorTables.h" #include "RiaSummaryTools.h" @@ -77,7 +77,7 @@ RimEnsembleCurveSet* RicNewSummaryEnsembleCurveSetFeature::addDefaultCurveSet(Ri //-------------------------------------------------------------------------------------------------- void RicNewSummaryEnsembleCurveSetFeature::createPlotForCurveSetAndUpdate(RimSummaryCaseCollection* ensemble) { - RiaApplication* app = RiaApplication::instance(); + RiaGuiApplication* app = RiaGuiApplication::instance(); RimProject* proj = app->project(); RimSummaryPlotCollection* summaryPlotCollection = proj->mainPlotCollection->summaryPlotCollection(); diff --git a/ApplicationCode/Commands/SummaryPlotCommands/RicSummaryCurveCreator.cpp b/ApplicationCode/Commands/SummaryPlotCommands/RicSummaryCurveCreator.cpp index c587144e89..c703834067 100644 --- a/ApplicationCode/Commands/SummaryPlotCommands/RicSummaryCurveCreator.cpp +++ b/ApplicationCode/Commands/SummaryPlotCommands/RicSummaryCurveCreator.cpp @@ -18,7 +18,7 @@ #include "RicSummaryCurveCreator.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RiaColorTables.h" #include "RiaCurveSetDefinition.h" #include "RiaSummaryCurveDefinition.h" @@ -231,7 +231,7 @@ void RicSummaryCurveCreator::fieldChangedByUi(const caf::PdmFieldHandle* changed caf::PdmField* field = dynamic_cast*>(m_targetPlot->uiCapability()->objectToggleField()); field->setValueWithFieldChanged(true); - RiuPlotMainWindow* mainPlotWindow = RiaApplication::instance()->mainPlotWindow(); + RiuPlotMainWindow* mainPlotWindow = RiaGuiApplication::instance()->mainPlotWindow(); mainPlotWindow->updateSummaryPlotToolBar(); } else if (changedField == &m_useAutoAppearanceAssignment && m_useAutoAppearanceAssignment) @@ -912,7 +912,7 @@ void RicSummaryCurveCreator::createNewPlot() m_targetPlot = newSummaryPlot; updateTargetPlot(); - RiuPlotMainWindow* mainPlotWindow = RiaApplication::instance()->mainPlotWindow(); + RiuPlotMainWindow* mainPlotWindow = RiaGuiApplication::instance()->mainPlotWindow(); mainPlotWindow->updateSummaryPlotToolBar(); } } diff --git a/ApplicationCode/Commands/SummaryPlotCommands/RicSummaryCurveCreatorDialog.cpp b/ApplicationCode/Commands/SummaryPlotCommands/RicSummaryCurveCreatorDialog.cpp index e15fd2c1ff..ec796b262d 100644 --- a/ApplicationCode/Commands/SummaryPlotCommands/RicSummaryCurveCreatorDialog.cpp +++ b/ApplicationCode/Commands/SummaryPlotCommands/RicSummaryCurveCreatorDialog.cpp @@ -18,7 +18,7 @@ #include "RicSummaryCurveCreatorDialog.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RicSummaryCurveCreator.h" #include "RicSummaryCurveCreatorSplitterUi.h" @@ -81,7 +81,7 @@ void RicSummaryCurveCreatorDialog::updateFromDefaultCases(const std::vectormainPlotWindow(); + RiuPlotMainWindow* plotwindow = RiaGuiApplication::instance()->mainPlotWindow(); if (plotwindow) { plotwindow->cleanUpTemporaryWidgets(); diff --git a/ApplicationCode/Commands/SummaryPlotCommands/RicViewZoomAllFeature.cpp b/ApplicationCode/Commands/SummaryPlotCommands/RicViewZoomAllFeature.cpp index eb04c5f3f1..b28fadff96 100644 --- a/ApplicationCode/Commands/SummaryPlotCommands/RicViewZoomAllFeature.cpp +++ b/ApplicationCode/Commands/SummaryPlotCommands/RicViewZoomAllFeature.cpp @@ -18,7 +18,7 @@ #include "RicViewZoomAllFeature.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "Rim3dView.h" #include "RimViewWindow.h" @@ -47,11 +47,11 @@ void RicViewZoomAllFeature::onActionTriggered(bool isChecked) { this->disableModelChangeContribution(); - QWidget* topLevelWidget = RiaApplication::activeWindow(); + QWidget* topLevelWidget = RiaGuiApplication::activeWindow(); if (dynamic_cast(topLevelWidget)) { - RimViewWindow* viewWindow = RiaApplication::instance()->activeReservoirView(); + RimViewWindow* viewWindow = RiaGuiApplication::instance()->activeReservoirView(); if (viewWindow) { viewWindow->zoomAll(); diff --git a/ApplicationCode/Commands/ToggleCommands/RicToggleItemsFeatureImpl.cpp b/ApplicationCode/Commands/ToggleCommands/RicToggleItemsFeatureImpl.cpp index 5b5ec4b58e..f6fe0062b9 100644 --- a/ApplicationCode/Commands/ToggleCommands/RicToggleItemsFeatureImpl.cpp +++ b/ApplicationCode/Commands/ToggleCommands/RicToggleItemsFeatureImpl.cpp @@ -21,7 +21,7 @@ #include "RiuMainWindow.h" #include "RiuPlotMainWindow.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "cafPdmUiFieldHandle.h" #include "cafPdmUiItem.h" @@ -161,7 +161,7 @@ caf::PdmUiTreeOrdering* RicToggleItemsFeatureImpl::findTreeItemFromSelectedUiIte QModelIndex modIndex = RiuMainWindow::instance()->projectTreeView()->findModelIndex(uiItem); if(!modIndex.isValid()) { - RiuPlotMainWindow* mainPlotWindow = RiaApplication::instance()->mainPlotWindow(); + RiuPlotMainWindow* mainPlotWindow = RiaGuiApplication::instance()->mainPlotWindow(); if(mainPlotWindow) { modIndex = mainPlotWindow->projectTreeView()->findModelIndex(uiItem); diff --git a/ApplicationCode/Commands/WellLogCommands/RicDeleteWellLogPlotTrackFeature.cpp b/ApplicationCode/Commands/WellLogCommands/RicDeleteWellLogPlotTrackFeature.cpp index a93e145ed1..62b9cc6969 100644 --- a/ApplicationCode/Commands/WellLogCommands/RicDeleteWellLogPlotTrackFeature.cpp +++ b/ApplicationCode/Commands/WellLogCommands/RicDeleteWellLogPlotTrackFeature.cpp @@ -20,7 +20,7 @@ #include "RicDeleteWellLogPlotTrackFeature.h" #include "RicWellLogPlotCurveFeatureImpl.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RiuPlotMainWindow.h" #include "RiuWellLogPlot.h" #include "RiuWellLogTrack.h" @@ -67,7 +67,7 @@ void RicDeleteWellLogPlotTrackFeature::onActionTriggered(bool isChecked) std::vector selection; caf::SelectionManager::instance()->objectsByType(&selection); - RiuPlotMainWindow* plotWindow = RiaApplication::instance()->getOrCreateMainPlotWindow(); + RiuPlotMainWindow* plotWindow = RiaGuiApplication::instance()->getOrCreateMainPlotWindow(); std::set alteredWellLogPlots; for (size_t i = 0; i < selection.size(); i++) diff --git a/ApplicationCode/Commands/WellLogCommands/RicNewWellLogPlotFeatureImpl.cpp b/ApplicationCode/Commands/WellLogCommands/RicNewWellLogPlotFeatureImpl.cpp index 09e7ce1e6c..fd07356a46 100644 --- a/ApplicationCode/Commands/WellLogCommands/RicNewWellLogPlotFeatureImpl.cpp +++ b/ApplicationCode/Commands/WellLogCommands/RicNewWellLogPlotFeatureImpl.cpp @@ -25,7 +25,7 @@ #include "RimWellLogPlotCollection.h" #include "RimWellLogTrack.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "cvfAssert.h" @@ -40,7 +40,7 @@ RimWellLogPlot* RicNewWellLogPlotFeatureImpl::createWellLogPlot(bool showAfterCr CVF_ASSERT(wellLogPlotColl); // Make sure the summary plot window is created - RiaApplication::instance()->getOrCreateMainPlotWindow(); + RiaGuiApplication::instance()->getOrCreateMainPlotWindow(); RimWellLogPlot* plot = new RimWellLogPlot(); plot->setAsPlotMdiWindow(); @@ -58,7 +58,7 @@ RimWellLogPlot* RicNewWellLogPlotFeatureImpl::createWellLogPlot(bool showAfterCr if (showAfterCreation) { - RiaApplication::instance()->getOrCreateAndShowMainPlotWindow(); + RiaGuiApplication::instance()->getOrCreateAndShowMainPlotWindow(); } return plot; diff --git a/ApplicationCode/Commands/WellLogCommands/RicNewWellLogPlotTrackFeature.cpp b/ApplicationCode/Commands/WellLogCommands/RicNewWellLogPlotTrackFeature.cpp index 8ff17fb6d4..4ba04fe539 100644 --- a/ApplicationCode/Commands/WellLogCommands/RicNewWellLogPlotTrackFeature.cpp +++ b/ApplicationCode/Commands/WellLogCommands/RicNewWellLogPlotTrackFeature.cpp @@ -19,7 +19,7 @@ #include "RicNewWellLogPlotTrackFeature.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RiuPlotMainWindow.h" #include "RiuWellLogPlot.h" #include "RiuWellLogTrack.h" @@ -66,7 +66,7 @@ void RicNewWellLogPlotTrackFeature::onActionTriggered(bool isChecked) RimWellLogTrack* plotTrack = new RimWellLogTrack; wellLogPlot->addTrack(plotTrack); plotTrack->setDescription(QString("Track %1").arg(wellLogPlot->trackCount())); - RiuPlotMainWindow* plotWindow = RiaApplication::instance()->getOrCreateMainPlotWindow(); + RiuPlotMainWindow* plotWindow = RiaGuiApplication::instance()->getOrCreateMainPlotWindow(); RiuWellLogPlot* viewWidget = dynamic_cast(wellLogPlot->viewWidget()); RicWellLogTools::addExtractionCurve(plotTrack, nullptr, nullptr, nullptr, -1, true); diff --git a/ApplicationCode/Commands/WellLogCommands/RicWellLogPlotTrackFeatureImpl.cpp b/ApplicationCode/Commands/WellLogCommands/RicWellLogPlotTrackFeatureImpl.cpp index 8494551d41..1d1531d784 100644 --- a/ApplicationCode/Commands/WellLogCommands/RicWellLogPlotTrackFeatureImpl.cpp +++ b/ApplicationCode/Commands/WellLogCommands/RicWellLogPlotTrackFeatureImpl.cpp @@ -19,7 +19,7 @@ #include "RicWellLogPlotTrackFeatureImpl.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RiuPlotMainWindow.h" #include "RiuWellLogPlot.h" #include "RiuWellLogTrack.h" @@ -94,7 +94,7 @@ void RicWellLogPlotTrackFeatureImpl::moveTracksToWellLogPlot(RimWellLogPlot* dst { CVF_ASSERT(dstWellLogPlot); - RiuPlotMainWindow* plotWindow = RiaApplication::instance()->getOrCreateMainPlotWindow(); + RiuPlotMainWindow* plotWindow = RiaGuiApplication::instance()->getOrCreateMainPlotWindow(); std::set srcPlots; diff --git a/ApplicationCode/Commands/WellPathCommands/RicCreateWellTargetsPickEventHandler.cpp b/ApplicationCode/Commands/WellPathCommands/RicCreateWellTargetsPickEventHandler.cpp index 6fe26379df..0e1db7957d 100644 --- a/ApplicationCode/Commands/WellPathCommands/RicCreateWellTargetsPickEventHandler.cpp +++ b/ApplicationCode/Commands/WellPathCommands/RicCreateWellTargetsPickEventHandler.cpp @@ -18,7 +18,7 @@ #include "RicCreateWellTargetsPickEventHandler.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RiaOffshoreSphericalCoords.h" #include "RigFemPart.h" @@ -70,7 +70,7 @@ RicCreateWellTargetsPickEventHandler::~RicCreateWellTargetsPickEventHandler() {} //-------------------------------------------------------------------------------------------------- void RicCreateWellTargetsPickEventHandler::registerAsPickEventHandler() { - RiaApplication::instance()->setOverrideCursor(Qt::CrossCursor); + RiaGuiApplication::instance()->setOverrideCursor(Qt::CrossCursor); Ric3dViewPickEventHandler::registerAsPickEventHandler(); } @@ -79,7 +79,7 @@ void RicCreateWellTargetsPickEventHandler::registerAsPickEventHandler() //-------------------------------------------------------------------------------------------------- void RicCreateWellTargetsPickEventHandler::notifyUnregistered() { - RiaApplication::instance()->restoreOverrideCursor(); + RiaGuiApplication::instance()->restoreOverrideCursor(); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ModelVisualization/GridBox/RivGridBoxGenerator.cpp b/ApplicationCode/ModelVisualization/GridBox/RivGridBoxGenerator.cpp index 4f90045efd..7ef170c384 100644 --- a/ApplicationCode/ModelVisualization/GridBox/RivGridBoxGenerator.cpp +++ b/ApplicationCode/ModelVisualization/GridBox/RivGridBoxGenerator.cpp @@ -20,7 +20,7 @@ #include "RivGridBoxGenerator.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RiaColorTools.h" #include "RivPartPriority.h" @@ -639,7 +639,7 @@ void RivGridBoxGenerator::createLegend(EdgeType edge, cvf::Collection cvf::ref geo = new cvf::DrawableText; - cvf::Font* standardFont = RiaApplication::instance()->defaultSceneFont(); + cvf::Font* standardFont = RiaGuiApplication::instance()->defaultSceneFont(); geo->setFont(standardFont); geo->setTextColor(m_gridLegendColor); diff --git a/ApplicationCode/ModelVisualization/Intersections/RivIntersectionPartMgr.cpp b/ApplicationCode/ModelVisualization/Intersections/RivIntersectionPartMgr.cpp index e639ce69de..cfbc8ba406 100644 --- a/ApplicationCode/ModelVisualization/Intersections/RivIntersectionPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/Intersections/RivIntersectionPartMgr.cpp @@ -19,7 +19,7 @@ #include "RivIntersectionPartMgr.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RiaOffshoreSphericalCoords.h" #include "RiaPreferences.h" @@ -607,7 +607,7 @@ void RivIntersectionPartMgr::createFaultLabelParts(const std::vectorshowFaultLabel())) return; cvf::Color3f faultLabelColor = faultInViewColl->faultLabelColor(); - cvf::Font* font = RiaApplication::instance()->defaultSceneFont(); + cvf::Font* font = RiaGuiApplication::instance()->defaultSceneFont(); std::vector lineVertices; diff --git a/ApplicationCode/ModelVisualization/Riv3dWellLogPlanePartMgr.cpp b/ApplicationCode/ModelVisualization/Riv3dWellLogPlanePartMgr.cpp index 0a35d826a5..43d74a1ca3 100644 --- a/ApplicationCode/ModelVisualization/Riv3dWellLogPlanePartMgr.cpp +++ b/ApplicationCode/ModelVisualization/Riv3dWellLogPlanePartMgr.cpp @@ -18,7 +18,7 @@ #include "Riv3dWellLogPlanePartMgr.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "Rim3dView.h" #include "Rim3dWellLogCurveCollection.h" @@ -258,7 +258,7 @@ void Riv3dWellLogPlanePartMgr::appendDrawSurfaceToModel(cvf::ModelBasicList* if (normals.notNull()) { normals->setSingleColor(borderColor); - if (RiaApplication::instance()->useShaders()) + if (RiaGuiApplication::instance()->useShaders()) { normals->setUniformNames("u_transformationMatrix", "u_color"); } diff --git a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp index c165a4badd..e807dca51b 100644 --- a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp @@ -19,7 +19,7 @@ #include "RivFaultPartMgr.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RiaPreferences.h" #include "RigCaseCellResultsData.h" @@ -482,7 +482,9 @@ void RivFaultPartMgr::createLabelWithAnchorLine(const cvf::Part* part) // Fault label if (!m_rimFault->name().isEmpty()) { - cvf::Font* font = RiaApplication::instance()->defaultWellLabelFont(); + RiaGuiApplication* app = RiaGuiApplication::instance(); + + cvf::Font* font = app->defaultWellLabelFont(); cvf::ref drawableText = new cvf::DrawableText; drawableText->setFont(font); @@ -491,7 +493,7 @@ void RivFaultPartMgr::createLabelWithAnchorLine(const cvf::Part* part) drawableText->setDrawBackground(false); drawableText->setVerticalAlignment(cvf::TextDrawer::CENTER); - cvf::Color3f defWellLabelColor = RiaApplication::instance()->preferences()->defaultWellLabelColor(); + cvf::Color3f defWellLabelColor = app->preferences()->defaultWellLabelColor(); { { RimFaultInViewCollection* parentObject; diff --git a/ApplicationCode/ModelVisualization/RivMeasurementPartMgr.cpp b/ApplicationCode/ModelVisualization/RivMeasurementPartMgr.cpp index 968d25c131..7cd159337c 100644 --- a/ApplicationCode/ModelVisualization/RivMeasurementPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivMeasurementPartMgr.cpp @@ -186,11 +186,13 @@ void RivMeasurementPartMgr::buildPolyLineParts(const cvf::Camera* camera, negativeXDir = true; } - auto backgroundColor = RiaApplication::instance()->preferences()->defaultViewerBackgroundColor; + RiaGuiApplication* app = RiaGuiApplication::instance(); + + auto backgroundColor = app->preferences()->defaultViewerBackgroundColor; auto fontColor = cvf::Color3f::BLACK; QString text = m_measurement->label(); auto labelPosition = pointsInDisplay.back(); - auto font = RiaApplication::instance()->defaultWellLabelFont(); + auto font = app->defaultWellLabelFont(); cvf::ref drawableText = new cvf::DrawableText; drawableText->setFont(font); diff --git a/ApplicationCode/ModelVisualization/RivPolylineAnnotationPartMgr.cpp b/ApplicationCode/ModelVisualization/RivPolylineAnnotationPartMgr.cpp index b23c0ba61e..c71f46c251 100644 --- a/ApplicationCode/ModelVisualization/RivPolylineAnnotationPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivPolylineAnnotationPartMgr.cpp @@ -18,7 +18,7 @@ #include "RivPolylineAnnotationPartMgr.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RiaBoundingBoxTools.h" #include "Rim3dView.h" @@ -134,7 +134,7 @@ void RivPolylineAnnotationPartMgr::buildPolylineAnnotationParts(const caf::Displ } cvf::ref vectorDrawable; - if (RiaApplication::instance()->useShaders()) + if (RiaGuiApplication::instance()->useShaders()) { // NOTE: Drawable vectors must be rendered using shaders when the rest of the application is rendered using // shaders Drawing vectors using fixed function when rest of the application uses shaders causes visual artifacts diff --git a/ApplicationCode/ModelVisualization/RivWellHeadPartMgr.cpp b/ApplicationCode/ModelVisualization/RivWellHeadPartMgr.cpp index 5e5572c7bf..b5bea8e798 100644 --- a/ApplicationCode/ModelVisualization/RivWellHeadPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivWellHeadPartMgr.cpp @@ -22,7 +22,7 @@ #include "RivWellHeadPartMgr.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RigActiveCellInfo.h" #include "RigCell.h" @@ -297,7 +297,7 @@ void RivWellHeadPartMgr::buildWellHeadParts(size_t frameIndex, if (well->showWellLabel() && !well->name().isEmpty()) { - cvf::Font* font = RiaApplication::instance()->defaultWellLabelFont(); + cvf::Font* font = RiaGuiApplication::instance()->defaultWellLabelFont(); cvf::ref drawableText = new cvf::DrawableText; drawableText->setFont(font); diff --git a/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp b/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp index dafe176eca..5fa0838605 100644 --- a/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp @@ -21,7 +21,7 @@ #include "RivWellPathPartMgr.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RigEclipseCaseData.h" #include "RigMainGrid.h" @@ -612,7 +612,7 @@ void RivWellPathPartMgr::buildWellPathParts(const caf::DisplayCoordTransform* di if (wellPathCollection->showWellPathLabel() && m_rimWellPath->showWellPathLabel() && !m_rimWellPath->name().isEmpty()) { - cvf::Font* font = RiaApplication::instance()->defaultWellLabelFont(); + cvf::Font* font = RiaGuiApplication::instance()->defaultWellLabelFont(); cvf::ref drawableText = new cvf::DrawableText; drawableText->setFont(font); diff --git a/ApplicationCode/ModelVisualization/RivWellSpheresPartMgr.cpp b/ApplicationCode/ModelVisualization/RivWellSpheresPartMgr.cpp index 112c4a2e09..70de4f30a6 100644 --- a/ApplicationCode/ModelVisualization/RivWellSpheresPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivWellSpheresPartMgr.cpp @@ -18,7 +18,7 @@ #include "RivWellSpheresPartMgr.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RigMainGrid.h" #include "RigSimWellData.h" @@ -137,7 +137,7 @@ cvf::ref RivWellSpheresPartMgr::createPart(std::vector vectorDrawable; - if (RiaApplication::instance()->useShaders()) + if (RiaGuiApplication::instance()->useShaders()) { // NOTE: Drawable vectors must be rendered using shaders when the rest of the application is rendered using shaders // Drawing vectors using fixed function when rest of the application uses shaders causes visual artifacts @@ -169,7 +169,7 @@ cvf::ref RivWellSpheresPartMgr::createPart(std::vectorsetDrawable(vectorDrawable.p()); cvf::ref eff = new cvf::Effect; - if (RiaApplication::instance()->useShaders()) + if (RiaGuiApplication::instance()->useShaders()) { if (m_rimReservoirView->viewer()) { diff --git a/ApplicationCode/ProjectDataModel/Annotations/RimAnnotationCollection.cpp b/ApplicationCode/ProjectDataModel/Annotations/RimAnnotationCollection.cpp index 539ef7056f..157c094638 100644 --- a/ApplicationCode/ProjectDataModel/Annotations/RimAnnotationCollection.cpp +++ b/ApplicationCode/ProjectDataModel/Annotations/RimAnnotationCollection.cpp @@ -62,9 +62,9 @@ RimAnnotationCollection::RimAnnotationCollection() m_userDefinedPolylineAnnotations->uiCapability()->setUiName(RimAnnotationGroupCollection::USED_DEFINED_POLYLINE_ANNOTATION_UI_NAME); m_polylineFromFileAnnotations->uiCapability()->setUiName(RimAnnotationGroupCollection::POLYLINE_FROM_FILE_ANNOTATION_UI_NAME); - m_reachCircleAnnotations->uiCapability()->setUiIcon(QIcon(":/ReachCircle16x16.png")); - m_userDefinedPolylineAnnotations->uiCapability()->setUiIcon(QIcon(":/PolylinesFromFile16x16.png")); - m_polylineFromFileAnnotations->uiCapability()->setUiIcon(QIcon(":/PolylinesFromFile16x16.png")); + m_reachCircleAnnotations->uiCapability()->setUiIcon(":/ReachCircle16x16.png"); + m_userDefinedPolylineAnnotations->uiCapability()->setUiIcon(":/PolylinesFromFile16x16.png"); + m_polylineFromFileAnnotations->uiCapability()->setUiIcon(":/PolylinesFromFile16x16.png"); } diff --git a/ApplicationCode/ProjectDataModel/Annotations/RimAnnotationCollectionBase.cpp b/ApplicationCode/ProjectDataModel/Annotations/RimAnnotationCollectionBase.cpp index b97bfeb79f..427c15b55c 100644 --- a/ApplicationCode/ProjectDataModel/Annotations/RimAnnotationCollectionBase.cpp +++ b/ApplicationCode/ProjectDataModel/Annotations/RimAnnotationCollectionBase.cpp @@ -51,7 +51,7 @@ RimAnnotationCollectionBase::RimAnnotationCollectionBase() m_textAnnotations.uiCapability()->setUiHidden(true); m_textAnnotations = new RimAnnotationGroupCollection(); m_textAnnotations->uiCapability()->setUiName(RimAnnotationGroupCollection::TEXT_ANNOTATION_UI_NAME); - m_textAnnotations->uiCapability()->setUiIcon(QIcon(":/TextAnnotation16x16.png")); + m_textAnnotations->uiCapability()->setUiIcon(":/TextAnnotation16x16.png"); } diff --git a/ApplicationCode/ProjectDataModel/Annotations/RimAnnotationInViewCollection.cpp b/ApplicationCode/ProjectDataModel/Annotations/RimAnnotationInViewCollection.cpp index 25749f21f6..c121b77cb9 100644 --- a/ApplicationCode/ProjectDataModel/Annotations/RimAnnotationInViewCollection.cpp +++ b/ApplicationCode/ProjectDataModel/Annotations/RimAnnotationInViewCollection.cpp @@ -105,10 +105,10 @@ RimAnnotationInViewCollection::RimAnnotationInViewCollection() m_globalUserDefinedPolylineAnnotations->uiCapability()->setUiName("Global User Defined Polylines Annotations"); m_globalPolylineFromFileAnnotations->uiCapability()->setUiName("Global Polylines From File Annotations"); - m_globalTextAnnotations->uiCapability()->setUiIcon(QIcon(":/TextAnnotation16x16.png")); - m_globalReachCircleAnnotations->uiCapability()->setUiIcon(QIcon(":/ReachCircle16x16.png")); - m_globalUserDefinedPolylineAnnotations->uiCapability()->setUiIcon(QIcon(":/PolylinesFromFile16x16.png")); - m_globalPolylineFromFileAnnotations->uiCapability()->setUiIcon(QIcon(":/PolylinesFromFile16x16.png")); + m_globalTextAnnotations->uiCapability()->setUiIcon(":/TextAnnotation16x16.png"); + m_globalReachCircleAnnotations->uiCapability()->setUiIcon(":/ReachCircle16x16.png"); + m_globalUserDefinedPolylineAnnotations->uiCapability()->setUiIcon(":/PolylinesFromFile16x16.png"); + m_globalPolylineFromFileAnnotations->uiCapability()->setUiIcon(":/PolylinesFromFile16x16.png"); } //-------------------------------------------------------------------------------------------------- @@ -296,6 +296,10 @@ void RimAnnotationInViewCollection::defineUiOrdering(QString uiConfigName, caf:: //-------------------------------------------------------------------------------------------------- void RimAnnotationInViewCollection::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) { + if (changedField == &m_isActive) + { + updateUiIconFromToggleField(); + } scheduleRedrawOfRelevantViews(); } diff --git a/ApplicationCode/ProjectDataModel/Completions/RimValveTemplate.cpp b/ApplicationCode/ProjectDataModel/Completions/RimValveTemplate.cpp index a258489f66..7b9eafb093 100644 --- a/ApplicationCode/ProjectDataModel/Completions/RimValveTemplate.cpp +++ b/ApplicationCode/ProjectDataModel/Completions/RimValveTemplate.cpp @@ -256,15 +256,15 @@ void RimValveTemplate::defineUiTreeOrdering(caf::PdmUiTreeOrdering& uiTreeOrderi this->setName(fullLabel()); if (m_type() == RiaDefines::ICV) { - this->setUiIcon(QIcon(":/ICVValve16x16.png")); + this->setUiIcon(":/ICVValve16x16.png"); } else if (m_type() == RiaDefines::ICD) { - this->setUiIcon(QIcon(":/ICDValve16x16.png")); + this->setUiIcon(":/ICDValve16x16.png"); } else if (m_type() == RiaDefines::AICD) { - this->setUiIcon(QIcon(":/AICDValve16x16.png")); + this->setUiIcon(":/AICDValve16x16.png"); } } diff --git a/ApplicationCode/ProjectDataModel/Completions/RimWellPathValve.cpp b/ApplicationCode/ProjectDataModel/Completions/RimWellPathValve.cpp index 395f587b36..38362dda41 100644 --- a/ApplicationCode/ProjectDataModel/Completions/RimWellPathValve.cpp +++ b/ApplicationCode/ProjectDataModel/Completions/RimWellPathValve.cpp @@ -184,13 +184,13 @@ void RimWellPathValve::applyValveLabelAndIcon() { if (componentType() == RiaDefines::ICV) { - this->setUiIcon(QIcon(":/ICVValve16x16.png")); + this->setUiIcon(":/ICVValve16x16.png"); QString fullName = QString("%1: %2").arg(componentLabel()).arg(m_measuredDepth()); this->setName(fullName); } else if (componentType() == RiaDefines::ICD) { - this->setUiIcon(QIcon(":/ICDValve16x16.png")); + this->setUiIcon(":/ICDValve16x16.png"); QString fullName = QString("%1 %2: %3 - %4") .arg(m_multipleValveLocations->valveLocations().size()) .arg(componentLabel()) @@ -200,7 +200,7 @@ void RimWellPathValve::applyValveLabelAndIcon() } else if (componentType() == RiaDefines::AICD) { - this->setUiIcon(QIcon(":/AICDValve16x16.png")); + this->setUiIcon(":/AICDValve16x16.png"); QString fullName = QString("%1 %2: %3 - %4") .arg(m_multipleValveLocations->valveLocations().size()) .arg(componentLabel()) diff --git a/ApplicationCode/ProjectDataModel/Flow/RimFlowCharacteristicsPlot.cpp b/ApplicationCode/ProjectDataModel/Flow/RimFlowCharacteristicsPlot.cpp index af080c629a..2d0cb446e4 100644 --- a/ApplicationCode/ProjectDataModel/Flow/RimFlowCharacteristicsPlot.cpp +++ b/ApplicationCode/ProjectDataModel/Flow/RimFlowCharacteristicsPlot.cpp @@ -188,7 +188,7 @@ QList RimFlowCharacteristicsPlot::calculateValueOptions( { if (c->defaultFlowDiagSolution()) { - options.push_back(caf::PdmOptionItemInfo(c->caseUserDescription(), c, false, c->uiIcon())); + options.push_back(caf::PdmOptionItemInfo(c->caseUserDescription(), c, false, c->uiIconProvider())); } } } @@ -199,7 +199,7 @@ QList RimFlowCharacteristicsPlot::calculateValueOptions( { for (RimEclipseView* view : m_case()->reservoirViews()) { - options.push_back(caf::PdmOptionItemInfo(view->name(), view, false, view->uiIcon())); + options.push_back(caf::PdmOptionItemInfo(view->name(), view, false, view->uiIconProvider())); } } } @@ -212,7 +212,7 @@ QList RimFlowCharacteristicsPlot::calculateValueOptions( options.push_back(caf::PdmOptionItemInfo("None", nullptr)); for (RimFlowDiagSolution* flowSol : flowSols) { - options.push_back(caf::PdmOptionItemInfo(flowSol->userDescription(), flowSol, false, flowSol->uiIcon())); + options.push_back(caf::PdmOptionItemInfo(flowSol->userDescription(), flowSol, false, flowSol->uiIconProvider())); } } } diff --git a/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.cpp b/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.cpp index fae3b985bb..9adf531010 100644 --- a/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.cpp +++ b/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.cpp @@ -98,7 +98,7 @@ RimWellAllocationPlot::RimWellAllocationPlot() m_accumulatedWellFlowPlot->setDepthUnit(RiaDefines::UNIT_NONE); m_accumulatedWellFlowPlot->setDepthType(RimWellLogPlot::CONNECTION_NUMBER); m_accumulatedWellFlowPlot->setTrackLegendsVisible(false); - m_accumulatedWellFlowPlot->uiCapability()->setUiIcon(QIcon(":/WellFlowPlot16x16.png")); + m_accumulatedWellFlowPlot->uiCapability()->setUiIcon(":/WellFlowPlot16x16.png"); CAF_PDM_InitFieldNoDefault(&m_totalWellAllocationPlot, "TotalWellFlowPlot", "Total Well Flow", "", "", ""); m_totalWellAllocationPlot.uiCapability()->setUiHidden(true); @@ -594,7 +594,7 @@ QList RimWellAllocationPlot::calculateValueOptions(const { std::set sortedWellNames = this->findSortedWellNames(); - QIcon simWellIcon(":/Well.png"); + caf::QIconProvider simWellIcon(":/Well.png"); for ( const QString& wname: sortedWellNames ) { options.push_back(caf::PdmOptionItemInfo(wname, wname, false, simWellIcon)); @@ -630,7 +630,7 @@ QList RimWellAllocationPlot::calculateValueOptions(const for (RimEclipseResultCase* c : cases) { - options.push_back(caf::PdmOptionItemInfo(c->caseUserDescription(), c, false, c->uiIcon())); + options.push_back(caf::PdmOptionItemInfo(c->caseUserDescription(), c, false, c->uiIconProvider())); } } } diff --git a/ApplicationCode/ProjectDataModel/GridCrossPlots/RimGridCrossPlotDataSet.cpp b/ApplicationCode/ProjectDataModel/GridCrossPlots/RimGridCrossPlotDataSet.cpp index b491074dae..f9a800902b 100644 --- a/ApplicationCode/ProjectDataModel/GridCrossPlots/RimGridCrossPlotDataSet.cpp +++ b/ApplicationCode/ProjectDataModel/GridCrossPlots/RimGridCrossPlotDataSet.cpp @@ -927,7 +927,7 @@ QList RimGridCrossPlotDataSet::calculateValueOptions(con for (RimEclipseView* view : eclipseCase->reservoirViews.childObjects()) { CVF_ASSERT(view && "Really always should have a valid view pointer in ReservoirViews"); - options.push_back(caf::PdmOptionItemInfo(view->name(), view, false, view->uiIcon())); + options.push_back(caf::PdmOptionItemInfo(view->name(), view, false, view->uiIconProvider())); } } } diff --git a/ApplicationCode/ProjectDataModel/Measurement/RiuMeasurementEventFilter.cpp b/ApplicationCode/ProjectDataModel/Measurement/RiuMeasurementEventFilter.cpp index 18badfd7be..51ddd7c61f 100644 --- a/ApplicationCode/ProjectDataModel/Measurement/RiuMeasurementEventFilter.cpp +++ b/ApplicationCode/ProjectDataModel/Measurement/RiuMeasurementEventFilter.cpp @@ -18,7 +18,7 @@ #include "RiuMeasurementEventFilter.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RimMeasurement.h" @@ -39,7 +39,7 @@ RiuMeasurementEventFilter::RiuMeasurementEventFilter(RimMeasurement* parent) //-------------------------------------------------------------------------------------------------- void RiuMeasurementEventFilter::registerFilter() { - RiaApplication::instance()->installEventFilter(this); + RiaGuiApplication::instance()->installEventFilter(this); } //-------------------------------------------------------------------------------------------------- @@ -47,7 +47,7 @@ void RiuMeasurementEventFilter::registerFilter() //-------------------------------------------------------------------------------------------------- void RiuMeasurementEventFilter::unregisterFilter() { - RiaApplication::instance()->removeEventFilter(this); + RiaGuiApplication::instance()->removeEventFilter(this); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp b/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp index b9d8221bf8..e5874c4ddd 100644 --- a/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp +++ b/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp @@ -116,7 +116,6 @@ Rim3dOverlayInfoConfig::Rim3dOverlayInfoConfig() m_isVisCellStatUpToDate = false; - m_gridStatisticsDialog = std::unique_ptr(new RicGridStatisticsDialog(nullptr)); } //-------------------------------------------------------------------------------------------------- @@ -228,14 +227,27 @@ QString Rim3dOverlayInfoConfig::resultInfoText(const HistogramData& histData) return ""; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RicGridStatisticsDialog* Rim3dOverlayInfoConfig::getOrCreateGridStatisticsDialog() +{ + if (!m_gridStatisticsDialog) + { + m_gridStatisticsDialog.reset(new RicGridStatisticsDialog(nullptr)); + } + CVF_ASSERT(m_gridStatisticsDialog); + return m_gridStatisticsDialog.get(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QImage Rim3dOverlayInfoConfig::statisticsDialogScreenShotImage() { - if (m_gridStatisticsDialog->isVisible()) + if (getOrCreateGridStatisticsDialog()->isVisible()) { - return m_gridStatisticsDialog->screenShotImage(); + return getOrCreateGridStatisticsDialog()->screenShotImage(); } return QImage(); } @@ -862,16 +874,17 @@ void Rim3dOverlayInfoConfig::showStatisticsInfoDialog(bool raise) { if (m_viewDef) { + RicGridStatisticsDialog* dialog = getOrCreateGridStatisticsDialog(); // Show dialog before setting data due to text edit auto height setting - m_gridStatisticsDialog->resize(600, 800); - m_gridStatisticsDialog->show(); + dialog->resize(600, 800); + dialog->show(); - m_gridStatisticsDialog->setLabel("Grid statistics"); - m_gridStatisticsDialog->updateFromRimView(m_viewDef); + dialog->setLabel("Grid statistics"); + dialog->updateFromRimView(m_viewDef); if (raise) { - m_gridStatisticsDialog->raise(); + dialog->raise(); } } } @@ -916,7 +929,7 @@ void Rim3dOverlayInfoConfig::update3DInfo() updateEclipse3DInfo(reservoirView); // Update statistics dialog - m_gridStatisticsDialog->updateFromRimView(reservoirView); + getOrCreateGridStatisticsDialog()->updateFromRimView(reservoirView); } RimGeoMechView* geoMechView = dynamic_cast(m_viewDef.p()); @@ -927,7 +940,7 @@ void Rim3dOverlayInfoConfig::update3DInfo() updateGeoMech3DInfo(geoMechView); // Update statistics dialog - m_gridStatisticsDialog->updateFromRimView(geoMechView); + getOrCreateGridStatisticsDialog()->updateFromRimView(geoMechView); } update3DInfoIn2dViews(); diff --git a/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.h b/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.h index 5097e378b9..5ca19d68b1 100644 --- a/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.h +++ b/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.h @@ -80,6 +80,7 @@ public: QString caseInfoText(); QString resultInfoText(const HistogramData& histData); + RicGridStatisticsDialog* getOrCreateGridStatisticsDialog(); void showStatisticsInfoDialog(bool raise = true); QImage statisticsDialogScreenShotImage(); @@ -101,7 +102,7 @@ public: ALL_CELLS, VISIBLE_CELLS }; - + private: void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override; caf::PdmFieldHandle* objectToggleField() override; diff --git a/ApplicationCode/ProjectDataModel/Rim3dView.cpp b/ApplicationCode/ProjectDataModel/Rim3dView.cpp index 1d957e811f..4caf61695b 100644 --- a/ApplicationCode/ProjectDataModel/Rim3dView.cpp +++ b/ApplicationCode/ProjectDataModel/Rim3dView.cpp @@ -19,7 +19,7 @@ #include "Rim3dView.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RiaFieldHandleTools.h" #include "RiaPreferences.h" #include "RiaViewRedrawScheduler.h" @@ -181,7 +181,7 @@ QString Rim3dView::name() const QWidget* Rim3dView::createViewWidget(QWidget* mainWindowParent) { QGLFormat glFormat; - glFormat.setDirectRendering(RiaApplication::instance()->useShaders()); + glFormat.setDirectRendering(RiaGuiApplication::instance()->useShaders()); m_viewer = new RiuViewer(glFormat, mainWindowParent); m_viewer->setOwnerReservoirView(this); @@ -207,7 +207,7 @@ void Rim3dView::updateViewWidgetAfterCreation() this->resetLegendsInViewer(); m_viewer->updateNavigationPolicy(); - m_viewer->enablePerfInfoHud(RiaApplication::instance()->showPerformanceInfo()); + m_viewer->enablePerfInfoHud(RiaGuiApplication::instance()->showPerformanceInfo()); m_viewer->mainCamera()->setViewMatrix(m_cameraPosition); m_viewer->setPointOfInterest(m_cameraPointOfInterest()); @@ -409,7 +409,10 @@ void Rim3dView::createDisplayModelAndRedraw() } } - RiuMainWindow::instance()->refreshAnimationActions(); + if (RiuMainWindow::instance()) + { + RiuMainWindow::instance()->refreshAnimationActions(); + } } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimCase.cpp b/ApplicationCode/ProjectDataModel/RimCase.cpp index c0f221c39b..6ef3cd59fa 100644 --- a/ApplicationCode/ProjectDataModel/RimCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimCase.cpp @@ -153,7 +153,7 @@ QList RimCase::calculateValueOptions(const caf::PdmField { for(RimFormationNames* fnames : proj->activeOilField()->formationNamesCollection()->formationNamesList()) { - options.push_back(caf::PdmOptionItemInfo(fnames->fileNameWoPath(), fnames, false, fnames->uiCapability()->uiIcon())); + options.push_back(caf::PdmOptionItemInfo(fnames->fileNameWoPath(), fnames, false, fnames->uiCapability()->uiIconProvider())); } } diff --git a/ApplicationCode/ProjectDataModel/RimCellFilter.cpp b/ApplicationCode/ProjectDataModel/RimCellFilter.cpp index 746c0f25b8..ad940b7a02 100644 --- a/ApplicationCode/ProjectDataModel/RimCellFilter.cpp +++ b/ApplicationCode/ProjectDataModel/RimCellFilter.cpp @@ -18,6 +18,8 @@ #include "RimCellFilter.h" +#include "RiaGuiApplication.h" + #include namespace caf @@ -69,9 +71,13 @@ caf::PdmFieldHandle* RimCellFilter::userDescriptionField() void RimCellFilter::updateIconState() { // Reset dynamic icon - this->setUiIcon(QIcon()); + this->setUiIcon(caf::QIconProvider()); // Get static one - QIcon icon = this->uiIcon(); + caf::QIconProvider iconProvider = this->uiIconProvider(); + + if (iconProvider.isNull()) return; + + QIcon icon = iconProvider.icon(); // Get a pixmap, and modify it @@ -93,14 +99,9 @@ void RimCellFilter::updateIconState() painter.drawPixmap(0,0, sign); } - if (!isActive || isActive.uiCapability()->isUiReadOnly()) - { - QIcon temp(icPixmap); - icPixmap = temp.pixmap(16, 16, QIcon::Disabled); - } - - QIcon newIcon(icPixmap); - this->setUiIcon(newIcon); + iconProvider.setPixmap(icPixmap); + iconProvider.setActive(isActive && !isActive.uiCapability()->isUiReadOnly()); + this->setUiIcon(iconProvider); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimEclipsePropertyFilter.cpp b/ApplicationCode/ProjectDataModel/RimEclipsePropertyFilter.cpp index 9945b71931..de8ff5b5f8 100644 --- a/ApplicationCode/ProjectDataModel/RimEclipsePropertyFilter.cpp +++ b/ApplicationCode/ProjectDataModel/RimEclipsePropertyFilter.cpp @@ -22,6 +22,7 @@ #include "RiaDefines.h" #include "RiaFieldHandleTools.h" +#include "RiaGuiApplication.h" #include "RigCaseCellResultsData.h" #include "RigEclipseCaseData.h" @@ -90,7 +91,11 @@ RimEclipsePropertyFilter::RimEclipsePropertyFilter() CAF_PDM_InitField(&m_useCategorySelection, "CategorySelection", false, "Category Selection", "", "", ""); m_upperBound.uiCapability()->setUiEditorTypeName(caf::PdmUiDoubleSliderEditor::uiEditorTypeName()); - updateIconState(); + // HEADLESS HACK + if (RiaGuiApplication::isRunning()) + { + updateIconState(); + } m_minimumResultValue = cvf::UNDEFINED_DOUBLE; m_maximumResultValue = cvf::UNDEFINED_DOUBLE; diff --git a/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.cpp b/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.cpp index 08cf81b8a7..898003a450 100644 --- a/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.cpp +++ b/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.cpp @@ -684,7 +684,7 @@ QList RimEclipseResultDefinition::calculateValueOptions( QString("%1 (#%2)").arg(otherCase->caseUserDescription()).arg(otherCase->caseId()), otherCase, false, - otherCase->uiIcon())); + otherCase->uiIconProvider())); } } } diff --git a/ApplicationCode/ProjectDataModel/RimGeoMechCase.cpp b/ApplicationCode/ProjectDataModel/RimGeoMechCase.cpp index 1ee043ed2a..9d1bde616e 100644 --- a/ApplicationCode/ProjectDataModel/RimGeoMechCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimGeoMechCase.cpp @@ -814,7 +814,7 @@ QList RimGeoMechCase::calculateValueOptions(const caf::P { for (size_t i = 0; i < m_elementPropertyFileNames.v().size(); i++) { - options.push_back(caf::PdmOptionItemInfo(m_elementPropertyFileNames.v().at(i).path(), (int)i, true, QIcon())); + options.push_back(caf::PdmOptionItemInfo(m_elementPropertyFileNames.v().at(i).path(), (int)i, true)); } } diff --git a/ApplicationCode/ProjectDataModel/RimGridCollection.cpp b/ApplicationCode/ProjectDataModel/RimGridCollection.cpp index b8643e1593..c0ddf91a37 100644 --- a/ApplicationCode/ProjectDataModel/RimGridCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimGridCollection.cpp @@ -260,18 +260,18 @@ RimGridCollection::RimGridCollection() m_mainGrid = new RimGridInfo(); m_mainGrid->setUiName("Main Grid"); m_mainGrid->uiCapability()->setUiTreeHidden(true); - m_mainGrid->setUiIcon(QIcon(":/MainGrid16x16.png")); + m_mainGrid->setUiIcon(":/MainGrid16x16.png"); CAF_PDM_InitFieldNoDefault(&m_persistentLgrs, "PersistentLgrs", "Persistent LGRs", "", "", ""); m_persistentLgrs = new RimGridInfoCollection(); m_persistentLgrs->setUiName(persistentGridUiName()); - m_persistentLgrs->setUiIcon(QIcon(":/LGR16x16.png")); + m_persistentLgrs->setUiIcon(":/LGR16x16.png"); CAF_PDM_InitFieldNoDefault(&m_temporaryLgrs, "TemporaryLgrs", "Temporary LGRs", "", "", ""); m_temporaryLgrs.xmlCapability()->disableIO(); m_temporaryLgrs = new RimGridInfoCollection(); m_temporaryLgrs->setUiName(temporaryGridUiName()); - m_temporaryLgrs->setUiIcon(QIcon(":/TempLGR16x16.png")); + m_temporaryLgrs->setUiIcon(":/TempLGR16x16.png"); } //-------------------------------------------------------------------------------------------------- @@ -390,7 +390,7 @@ void RimGridCollection::syncFromMainEclipseGrid() auto gridInfo = new RimGridInfo(); gridInfo->setName(gridName); gridInfo->setEclipseGridIndex((int)gridIndex); - gridInfo->setUiIcon(QIcon(":/TempLGR16x16.png")); + gridInfo->setUiIcon(":/TempLGR16x16.png"); m_temporaryLgrs->addGridInfo(gridInfo); } } @@ -405,7 +405,7 @@ void RimGridCollection::syncFromMainEclipseGrid() auto gridInfo = new RimGridInfo(); gridInfo->setName(gridName); gridInfo->setEclipseGridIndex((int)gridIndex); - gridInfo->setUiIcon(QIcon(":/LGR16x16.png")); + gridInfo->setUiIcon(":/LGR16x16.png"); m_persistentLgrs->addGridInfo(gridInfo); } } diff --git a/ApplicationCode/ProjectDataModel/RimGridView.cpp b/ApplicationCode/ProjectDataModel/RimGridView.cpp index 8d860691f1..39b930891c 100644 --- a/ApplicationCode/ProjectDataModel/RimGridView.cpp +++ b/ApplicationCode/ProjectDataModel/RimGridView.cpp @@ -295,7 +295,7 @@ bool RimGridView::hasCustomFontSizes(RiaDefines::FontSettingType fontSettingType bool hasCustomFonts = Rim3dView::hasCustomFontSizes(fontSettingType, defaultFontSize); if (fontSettingType == RiaDefines::ANNOTATION_FONT) { - auto annotations = annotationCollection(); + auto annotations = annotationCollection(); if (annotations) { RiaFontCache::FontSize defaultFontSizeEnum = RiaFontCache::fontSizeEnumFromPointSize(defaultFontSize); @@ -316,7 +316,7 @@ bool RimGridView::applyFontSize(RiaDefines::FontSettingType fontSettingType, bool anyChange = Rim3dView::applyFontSize(fontSettingType, oldFontSize, fontSize, forceChange); if (fontSettingType == RiaDefines::ANNOTATION_FONT) { - auto annotations = annotationCollection(); + auto annotations = annotationCollection(); if (annotations) { RiaFontCache::FontSize oldFontSizeEnum = RiaFontCache::fontSizeEnumFromPointSize(oldFontSize); @@ -325,8 +325,7 @@ bool RimGridView::applyFontSize(RiaDefines::FontSettingType fontSettingType, if (applyFontSizes) { - anyChange = - annotations->applyFontSizeToAllTextAnnotations(oldFontSizeEnum, newFontSizeEnum, forceChange) || anyChange; + anyChange = annotations->applyFontSizeToAllTextAnnotations(oldFontSizeEnum, newFontSizeEnum, forceChange) || anyChange; } } } diff --git a/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp b/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp index 2686fcca33..304c011c0c 100644 --- a/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp +++ b/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp @@ -64,11 +64,11 @@ RimIdenticalGridCaseGroup::RimIdenticalGridCaseGroup() caseCollection = new RimCaseCollection; caseCollection->uiCapability()->setUiName("Source Cases"); - caseCollection->uiCapability()->setUiIcon(QIcon(":/Cases16x16.png")); + caseCollection->uiCapability()->setUiIcon(":/Cases16x16.png"); statisticsCaseCollection = new RimCaseCollection; statisticsCaseCollection->uiCapability()->setUiName("Derived Statistics"); - statisticsCaseCollection->uiCapability()->setUiIcon(QIcon(":/Histograms16x16.png")); + statisticsCaseCollection->uiCapability()->setUiIcon(":/Histograms16x16.png"); m_mainGrid = nullptr; diff --git a/ApplicationCode/ProjectDataModel/RimIntersection.cpp b/ApplicationCode/ProjectDataModel/RimIntersection.cpp index 71b23f6ce3..d96febc8bc 100644 --- a/ApplicationCode/ProjectDataModel/RimIntersection.cpp +++ b/ApplicationCode/ProjectDataModel/RimIntersection.cpp @@ -316,7 +316,7 @@ QList RimIntersection::calculateValueOptions(const caf:: { caf::PdmChildArrayField& simWells = coll->wells; - QIcon simWellIcon(":/Well.png"); + caf::QIconProvider simWellIcon(":/Well.png"); for (RimSimWellInView* eclWell : simWells) { options.push_back(caf::PdmOptionItemInfo(eclWell->name(), eclWell, false, simWellIcon)); diff --git a/ApplicationCode/ProjectDataModel/RimIntersectionBox.cpp b/ApplicationCode/ProjectDataModel/RimIntersectionBox.cpp index c4e5e061ac..0154fda7ac 100644 --- a/ApplicationCode/ProjectDataModel/RimIntersectionBox.cpp +++ b/ApplicationCode/ProjectDataModel/RimIntersectionBox.cpp @@ -543,21 +543,21 @@ void RimIntersectionBox::updateVisibility() if (m_singlePlaneState == PLANE_STATE_X) { m_maxXCoord.uiCapability()->setUiReadOnly(true); - this->setUiIcon(QIcon(QString(":/IntersectionXPlane16x16.png"))); + this->setUiIcon(QString(":/IntersectionXPlane16x16.png")); } else if (m_singlePlaneState == PLANE_STATE_Y) { m_maxYCoord.uiCapability()->setUiReadOnly(true); - this->setUiIcon(QIcon(QString(":/IntersectionYPlane16x16.png"))); + this->setUiIcon(QString(":/IntersectionYPlane16x16.png")); } else if (m_singlePlaneState == PLANE_STATE_Z) { m_maxDepth.uiCapability()->setUiReadOnly(true); - this->setUiIcon(QIcon(QString(":/IntersectionZPlane16x16.png"))); + this->setUiIcon(QString(":/IntersectionZPlane16x16.png")); } else { - this->setUiIcon(QIcon(QString(":/IntersectionBox16x16.png"))); + this->setUiIcon(QString(":/IntersectionBox16x16.png")); } } diff --git a/ApplicationCode/ProjectDataModel/RimIntersectionCollection.cpp b/ApplicationCode/ProjectDataModel/RimIntersectionCollection.cpp index 0739e526dc..5df6fc282e 100644 --- a/ApplicationCode/ProjectDataModel/RimIntersectionCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimIntersectionCollection.cpp @@ -279,6 +279,8 @@ void RimIntersectionCollection::fieldChangedByUi(const caf::PdmFieldHandle* chan { if (changedField == &isActive) { + updateUiIconFromToggleField(); + Rim3dView* rimView = nullptr; firstAncestorOrThisOfType(rimView); if (rimView) diff --git a/ApplicationCode/ProjectDataModel/RimMdiWindowController.cpp b/ApplicationCode/ProjectDataModel/RimMdiWindowController.cpp index 84f9fb340a..1eda8128c5 100644 --- a/ApplicationCode/ProjectDataModel/RimMdiWindowController.cpp +++ b/ApplicationCode/ProjectDataModel/RimMdiWindowController.cpp @@ -18,7 +18,7 @@ #include "RimMdiWindowController.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RimProject.h" #include "RimViewWindow.h" #include "RiuMainWindowBase.h" @@ -122,7 +122,11 @@ QWidget* RimMdiWindowController::viewWidget() //-------------------------------------------------------------------------------------------------- RiuMainWindowBase* RimMdiWindowController::getMainWindow() { - return RiaApplication::instance()->mainWindowByID(m_mainWindowID); + if (RiaGuiApplication::isRunning()) + { + return RiaGuiApplication::instance()->mainWindowByID(m_mainWindowID); + } + return nullptr; } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimPlotAxisProperties.cpp b/ApplicationCode/ProjectDataModel/RimPlotAxisProperties.cpp index a0bedafe20..8af080fb59 100644 --- a/ApplicationCode/ProjectDataModel/RimPlotAxisProperties.cpp +++ b/ApplicationCode/ProjectDataModel/RimPlotAxisProperties.cpp @@ -218,8 +218,8 @@ void RimPlotAxisProperties::setNameAndAxis(const QString& name, QwtPlot::Axis ax m_name = name; m_axis = axis; - if (axis == QwtPlot::yRight) this->setUiIcon(QIcon(":/RightAxis16x16.png")); - if (axis == QwtPlot::xBottom) this->setUiIcon(QIcon(":/BottomAxis16x16.png")); + if (axis == QwtPlot::yRight) this->setUiIcon(":/RightAxis16x16.png"); + if (axis == QwtPlot::xBottom) this->setUiIcon(":/BottomAxis16x16.png"); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimPlotCurve.cpp b/ApplicationCode/ProjectDataModel/RimPlotCurve.cpp index 321bb7022e..ac53bc2d33 100644 --- a/ApplicationCode/ProjectDataModel/RimPlotCurve.cpp +++ b/ApplicationCode/ProjectDataModel/RimPlotCurve.cpp @@ -18,6 +18,7 @@ #include "RimPlotCurve.h" +#include "RiaGuiApplication.h" #include "RimEnsembleCurveSet.h" #include "RimEnsembleCurveSetCollection.h" #include "RimNameConfig.h" @@ -494,12 +495,13 @@ void RimPlotCurve::updateUiIconFromPlotSymbol() { if (m_pointSymbol() != RiuQwtSymbol::NoSymbol) { + CVF_ASSERT(RiaGuiApplication::isRunning()); QColor curveColor(m_curveColor.value().rByte(), m_curveColor.value().gByte(), m_curveColor.value().bByte()); QSizeF iconSize(24, 24); QwtGraphic graphic = m_qwtPlotCurve->legendIcon(0, iconSize); QPixmap pixmap = graphic.toPixmap(); - setUiIcon(QIcon(pixmap)); + setUiIcon(caf::QIconProvider(pixmap)); } } diff --git a/ApplicationCode/ProjectDataModel/RimProject.cpp b/ApplicationCode/ProjectDataModel/RimProject.cpp index 7cf0922fd1..7319f60e6e 100644 --- a/ApplicationCode/ProjectDataModel/RimProject.cpp +++ b/ApplicationCode/ProjectDataModel/RimProject.cpp @@ -20,7 +20,7 @@ #include "RimProject.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RiaCompletionTypeCalculationScheduler.h" #include "RiaFieldHandleTools.h" #include "RiaFilePathTools.h" @@ -89,6 +89,7 @@ #include "cafPdmUiTreeOrdering.h" #include "cvfBoundingBox.h" +#include #include #include @@ -173,15 +174,13 @@ RimProject::RimProject(void) scriptCollection = new RimScriptCollection(); scriptCollection->directory.uiCapability()->setUiHidden(true); scriptCollection->uiCapability()->setUiName("Scripts"); - scriptCollection->uiCapability()->setUiIcon(QIcon(":/octave.png")); + scriptCollection->uiCapability()->setUiIcon(":/octave.png"); mainPlotCollection = new RimMainPlotCollection(); // For now, create a default first oilfield that contains the rest of the project oilFields.push_back(new RimOilField); - initScriptDirectories(); - this->setUiHidden(true); } @@ -238,14 +237,11 @@ void RimProject::close() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimProject::initScriptDirectories() +void RimProject::initScriptDirectories(const QString& scriptDirectories) { // // TODO : Must store content of scripts in project file and notify user if stored content is different from disk on execute and edit // - RiaApplication* app = RiaApplication::instance(); - QString scriptDirectories = app->scriptDirectories(); - this->setScriptDirectories(scriptDirectories); // Find largest used caseId read from file and make sure all cases have a valid caseId @@ -318,8 +314,6 @@ void RimProject::initScriptDirectories() //-------------------------------------------------------------------------------------------------- void RimProject::initAfterRead() { - initScriptDirectories(); - // Create an empty oil field in case the project did not contain one if (oilFields.size() < 1) { @@ -384,16 +378,12 @@ void RimProject::initAfterRead() //-------------------------------------------------------------------------------------------------- void RimProject::setupBeforeSave() { - m_show3DWindow = RiuMainWindow::instance()->isVisible(); + RiaGuiApplication* guiApp = RiaGuiApplication::instance(); - if (RiaApplication::instance()->mainPlotWindow() && - RiaApplication::instance()->mainPlotWindow()->isVisible()) + if (guiApp) { - m_showPlotWindow = true; - } - else - { - m_showPlotWindow = false; + m_show3DWindow = guiApp->mainWindow()->isVisible(); + m_showPlotWindow = guiApp->mainPlotWindow() && guiApp->mainPlotWindow()->isVisible(); } m_projectFileVersionString = STRPRODUCTVER; diff --git a/ApplicationCode/ProjectDataModel/RimProject.h b/ApplicationCode/ProjectDataModel/RimProject.h index 244185af1c..16d4c4fbb7 100644 --- a/ApplicationCode/ProjectDataModel/RimProject.h +++ b/ApplicationCode/ProjectDataModel/RimProject.h @@ -105,6 +105,8 @@ public: caf::PdmField plotWindowCurrentModelIndexPath; void setScriptDirectories(const QString& scriptDirectories); + void initScriptDirectories(const QString& scriptDirectories); + QString projectFileVersionString() const; bool isProjectFileVersionEqualOrOlderThan(const QString& otherProjectFileVersion) const; void close(); @@ -173,7 +175,6 @@ public: protected: // Overridden methods - void initScriptDirectories(); void initAfterRead() override; void setupBeforeSave() override; diff --git a/ApplicationCode/ProjectDataModel/RimRegularLegendConfig.cpp b/ApplicationCode/ProjectDataModel/RimRegularLegendConfig.cpp index 75de5fa02f..a7e20afe76 100644 --- a/ApplicationCode/ProjectDataModel/RimRegularLegendConfig.cpp +++ b/ApplicationCode/ProjectDataModel/RimRegularLegendConfig.cpp @@ -20,7 +20,7 @@ #include "RimRegularLegendConfig.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RiaColorTables.h" #include "RiaPreferences.h" diff --git a/ApplicationCode/ProjectDataModel/RimRegularLegendConfig.h b/ApplicationCode/ProjectDataModel/RimRegularLegendConfig.h index 9dd94da5f2..3183bddcbc 100644 --- a/ApplicationCode/ProjectDataModel/RimRegularLegendConfig.h +++ b/ApplicationCode/ProjectDataModel/RimRegularLegendConfig.h @@ -146,6 +146,9 @@ private: static cvf::Color3ubArray colorArrayFromColorType(ColorRangesType colorType); + caf::OverlayScalarMapperLegend* getOrCreateScalarMapperLegend(); + caf::CategoryLegend* getOrCreateCategoryLegend(); + private: cvf::ref m_linDiscreteScalarMapper; cvf::ref m_logDiscreteScalarMapper; diff --git a/ApplicationCode/ProjectDataModel/RimStimPlanColors.cpp b/ApplicationCode/ProjectDataModel/RimStimPlanColors.cpp index 66be397e33..e1fc02609d 100644 --- a/ApplicationCode/ProjectDataModel/RimStimPlanColors.cpp +++ b/ApplicationCode/ProjectDataModel/RimStimPlanColors.cpp @@ -197,6 +197,11 @@ void RimStimPlanColors::fieldChangedByUi(const caf::PdmFieldHandle* changedField sourceView->scheduleCreateDisplayModelAndRedraw(); } + if (changedField == objectToggleField()) + { + updateUiIconFromToggleField(); + } + if (changedField == &m_resultNameAndUnit) { updateStimPlanTemplates(); diff --git a/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.cpp b/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.cpp index 28af25dd0b..ae974cca5b 100644 --- a/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.cpp +++ b/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.cpp @@ -19,7 +19,7 @@ #include "RimTernaryLegendConfig.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RiaColorTables.h" #include "RiaPreferences.h" diff --git a/ApplicationCode/ProjectDataModel/RimTools.cpp b/ApplicationCode/ProjectDataModel/RimTools.cpp index 3ea9fe7429..c460076770 100644 --- a/ApplicationCode/ProjectDataModel/RimTools.cpp +++ b/ApplicationCode/ProjectDataModel/RimTools.cpp @@ -238,7 +238,7 @@ void RimTools::wellPathOptionItems(QList* options) { caf::PdmChildArrayField& wellPaths = wellPathColl->wellPaths; - QIcon wellIcon(":/Well.png"); + caf::QIconProvider wellIcon(":/Well.png"); for (RimWellPath* wellPath : wellPaths) { options->push_back(caf::PdmOptionItemInfo(wellPath->name(), wellPath, false, wellIcon)); @@ -257,7 +257,7 @@ void RimTools::wellPathWithFormationsOptionItems(QList* std::vector wellPaths; RimTools::wellPathWithFormations(&wellPaths); - QIcon wellIcon(":/Well.png"); + caf::QIconProvider wellIcon(":/Well.png"); for (RimWellPath* wellPath : wellPaths) { options->push_back(caf::PdmOptionItemInfo(wellPath->name(), wellPath, false, wellIcon)); @@ -300,7 +300,7 @@ void RimTools::caseOptionItems(QList* options) for (RimCase* c : cases) { - options->push_back(caf::PdmOptionItemInfo(c->caseUserDescription(), c, false, c->uiIcon())); + options->push_back(caf::PdmOptionItemInfo(c->caseUserDescription(), c, false, c->uiIconProvider())); } } } @@ -324,7 +324,7 @@ void RimTools::eclipseCaseOptionItems(QList* options) RimEclipseCase* eclipseCase = dynamic_cast(c); if (eclipseCase) { - options->push_back(caf::PdmOptionItemInfo(c->caseUserDescription(), c, false, c->uiIcon())); + options->push_back(caf::PdmOptionItemInfo(c->caseUserDescription(), c, false, c->uiIconProvider())); } } } diff --git a/ApplicationCode/ProjectDataModel/RimViewController.cpp b/ApplicationCode/ProjectDataModel/RimViewController.cpp index 8cce4e56e8..d79eb0e380 100644 --- a/ApplicationCode/ProjectDataModel/RimViewController.cpp +++ b/ApplicationCode/ProjectDataModel/RimViewController.cpp @@ -506,8 +506,10 @@ void RimViewController::defineUiOrdering(QString uiConfigName, caf::PdmUiOrderin //-------------------------------------------------------------------------------------------------- void RimViewController::updateDisplayNameAndIcon() { - RimViewLinker::findNameAndIconFromView(&m_name.v(), &m_originalIcon, managedView()); - RimViewLinker::applyIconEnabledState(this, m_originalIcon, !m_isActive()); + caf::QIconProvider iconProvider; + RimViewLinker::findNameAndIconFromView(&m_name.v(), &iconProvider, managedView()); + iconProvider.setActive(m_isActive()); + setUiIcon(iconProvider); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimViewController.h b/ApplicationCode/ProjectDataModel/RimViewController.h index a254b14939..c4cd5ba54b 100644 --- a/ApplicationCode/ProjectDataModel/RimViewController.h +++ b/ApplicationCode/ProjectDataModel/RimViewController.h @@ -22,6 +22,7 @@ #include "cafPdmField.h" #include "cafPdmObject.h" #include "cafPdmPtrField.h" +#include "cafQIconProvider.h" #include "cvfBase.h" #include "cvfObject.h" @@ -130,6 +131,5 @@ private: caf::PdmField m_syncVisibleCells; caf::PdmField m_syncPropertyFilters; - QIcon m_originalIcon; cvf::ref m_caseToCaseCellMapper; }; diff --git a/ApplicationCode/ProjectDataModel/RimViewLinker.cpp b/ApplicationCode/ProjectDataModel/RimViewLinker.cpp index 13f59b9ca7..90ee7d3f1a 100644 --- a/ApplicationCode/ProjectDataModel/RimViewLinker.cpp +++ b/ApplicationCode/ProjectDataModel/RimViewLinker.cpp @@ -46,6 +46,7 @@ #include "RiuViewer.h" #include "cafPdmUiTreeOrdering.h" +#include "cafQIconProvider.h" #include "cvfCamera.h" #include "cvfMatrix4.h" #include "cvfScene.h" @@ -396,31 +397,14 @@ bool RimViewLinker::isActive() const return viewLinkerCollection->isActive(); } -//-------------------------------------------------------------------------------------------------- -/// Hande icon update locally as PdmUiItem::updateUiIconFromState works only for static icons -//-------------------------------------------------------------------------------------------------- -void RimViewLinker::applyIconEnabledState(caf::PdmObject* obj, const QIcon& icon, bool disable) -{ - QPixmap icPixmap; - icPixmap = icon.pixmap(16, 16, QIcon::Normal); - - if (disable) - { - QIcon temp(icPixmap); - icPixmap = temp.pixmap(16, 16, QIcon::Disabled); - } - - QIcon newIcon(icPixmap); - obj->setUiIcon(newIcon); -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimViewLinker::updateUiNameAndIcon() { - RimViewLinker::findNameAndIconFromView(&m_name.v(), &m_originalIcon, m_masterView); - RimViewLinker::applyIconEnabledState(this, m_originalIcon, false); + caf::QIconProvider iconProvider; + RimViewLinker::findNameAndIconFromView(&m_name.v(), &iconProvider, m_masterView); + setUiIcon(iconProvider); } //-------------------------------------------------------------------------------------------------- @@ -448,7 +432,7 @@ void RimViewLinker::scheduleCreateDisplayModelAndRedrawForDependentViews() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimViewLinker::findNameAndIconFromView(QString* name, QIcon* icon, RimGridView* view) +void RimViewLinker::findNameAndIconFromView(QString* name, caf::QIconProvider* icon, RimGridView* view) { CVF_ASSERT(name && icon); @@ -461,20 +445,20 @@ void RimViewLinker::findNameAndIconFromView(QString* name, QIcon* icon, RimGridV if (dynamic_cast(rimCase)) { - *icon = QIcon(":/GeoMechCase48x48.png"); + *icon = caf::QIconProvider(":/GeoMechCase48x48.png"); } else if (dynamic_cast(rimCase)) { - *icon = QIcon(":/Case48x48.png"); + *icon = caf::QIconProvider(":/Case48x48.png"); } else if (dynamic_cast(rimCase)) { - *icon = QIcon(":/EclipseInput48x48.png"); + *icon = caf::QIconProvider(":/EclipseInput48x48.png"); } } else { - *icon = QIcon(); + *icon = caf::QIconProvider(); } } diff --git a/ApplicationCode/ProjectDataModel/RimViewLinker.h b/ApplicationCode/ProjectDataModel/RimViewLinker.h index a63002c683..4592ce844c 100644 --- a/ApplicationCode/ProjectDataModel/RimViewLinker.h +++ b/ApplicationCode/ProjectDataModel/RimViewLinker.h @@ -29,9 +29,14 @@ #include "cvfBase.h" #include "cvfVector3.h" +namespace caf +{ +class QIconProvider; +} + namespace cvf { - class BoundingBox; +class BoundingBox; } class RimViewController; @@ -83,8 +88,7 @@ public: void addViewControllers(caf::PdmUiTreeOrdering& uiTreeOrdering) const; - static void applyIconEnabledState(caf::PdmObject* obj, const QIcon& icon, bool disable); - static void findNameAndIconFromView(QString* name, QIcon* icon, RimGridView* view); + static void findNameAndIconFromView(QString* name, caf::QIconProvider* icon, RimGridView* view); void updateCursorPosition(const RimGridView* sourceView, const cvf::Vec3d& domainCoord); @@ -103,5 +107,4 @@ private: caf::PdmChildArrayField m_viewControllers; caf::PdmPtrField m_masterView; caf::PdmField m_name; - QIcon m_originalIcon; }; diff --git a/ApplicationCode/ProjectDataModel/RimViewWindow.cpp b/ApplicationCode/ProjectDataModel/RimViewWindow.cpp index afe9046da0..4f4b9511b7 100644 --- a/ApplicationCode/ProjectDataModel/RimViewWindow.cpp +++ b/ApplicationCode/ProjectDataModel/RimViewWindow.cpp @@ -19,6 +19,7 @@ #include "RimViewWindow.h" #include "RiaFieldHandleTools.h" +#include "RiaGuiApplication.h" #include "RimMdiWindowController.h" @@ -99,6 +100,8 @@ void RimViewWindow::handleMdiWindowClosed() //-------------------------------------------------------------------------------------------------- void RimViewWindow::updateMdiWindowVisibility() { + if (!RiaGuiApplication::isRunning()) return; + if (m_windowController()) { m_windowController->updateViewerWidget(); diff --git a/ApplicationCode/ProjectDataModel/RimWellLogCurveCommonDataSource.cpp b/ApplicationCode/ProjectDataModel/RimWellLogCurveCommonDataSource.cpp index e93eccd56d..a1028d32b9 100644 --- a/ApplicationCode/ProjectDataModel/RimWellLogCurveCommonDataSource.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellLogCurveCommonDataSource.cpp @@ -603,7 +603,7 @@ QList RimWellLogCurveCommonDataSource::calculateValueOpt { std::set sortedWellNames = eclipseCase->sortedSimWellNames(); - QIcon simWellIcon(":/Well.png"); + caf::QIconProvider simWellIcon(":/Well.png"); for (const QString& wname : sortedWellNames) { options.push_back(caf::PdmOptionItemInfo(wname, wname, false, simWellIcon)); diff --git a/ApplicationCode/ProjectDataModel/RimWellLogExtractionCurve.cpp b/ApplicationCode/ProjectDataModel/RimWellLogExtractionCurve.cpp index ad45826220..dd9bd3ae34 100644 --- a/ApplicationCode/ProjectDataModel/RimWellLogExtractionCurve.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellLogExtractionCurve.cpp @@ -582,7 +582,7 @@ QList RimWellLogExtractionCurve::calculateValueOptions(c { std::set sortedWellNames = this->sortedSimWellNames(); - QIcon simWellIcon(":/Well.png"); + caf::QIconProvider simWellIcon(":/Well.png"); for ( const QString& wname: sortedWellNames ) { options.push_back(caf::PdmOptionItemInfo(wname, wname, false, simWellIcon)); diff --git a/ApplicationCode/ProjectDataModel/RimWellLogRftCurve.cpp b/ApplicationCode/ProjectDataModel/RimWellLogRftCurve.cpp index c114e6301b..d13b486e66 100644 --- a/ApplicationCode/ProjectDataModel/RimWellLogRftCurve.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellLogRftCurve.cpp @@ -403,7 +403,7 @@ QList RimWellLogRftCurve::calculateValueOptions(const ca std::set wellNames = reader->wellNames(); for (const QString& name : wellNames) { - options.push_back(caf::PdmOptionItemInfo(name, name, false, QIcon(":/Well.png"))); + options.push_back(caf::PdmOptionItemInfo(name, name, false, caf::QIconProvider(":/Well.png"))); } } } diff --git a/ApplicationCode/ProjectDataModel/RimWellLogTrack.cpp b/ApplicationCode/ProjectDataModel/RimWellLogTrack.cpp index 13d8347f29..007fe1257e 100644 --- a/ApplicationCode/ProjectDataModel/RimWellLogTrack.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellLogTrack.cpp @@ -240,7 +240,7 @@ void RimWellLogTrack::simWellOptionItems(QList* options, sortedWellNames = eclipseCase->eclipseCaseData()->findSortedWellNames(); } - QIcon simWellIcon(":/Well.png"); + caf::QIconProvider simWellIcon(":/Well.png"); for (const QString& wname : sortedWellNames) { options->push_back(caf::PdmOptionItemInfo(wname, wname, false, simWellIcon)); diff --git a/ApplicationCode/ProjectDataModel/Summary/RimEnsembleCurveSet.cpp b/ApplicationCode/ProjectDataModel/Summary/RimEnsembleCurveSet.cpp index 8f1995599a..3e67f0314c 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimEnsembleCurveSet.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimEnsembleCurveSet.cpp @@ -18,7 +18,7 @@ #include "RimEnsembleCurveSet.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RiaColorTables.h" #include "RiaStatisticsTools.h" @@ -597,7 +597,7 @@ void RimEnsembleCurveSet::fieldChangedByUi(const caf::PdmFieldHandle* changedFie plot->updatePlotTitle(); plot->updateConnectedEditors(); - RiuPlotMainWindow* mainPlotWindow = RiaApplication::instance()->mainPlotWindow(); + RiuPlotMainWindow* mainPlotWindow = RiaGuiApplication::instance()->mainPlotWindow(); mainPlotWindow->updateSummaryPlotToolBar(); } } @@ -686,9 +686,13 @@ void RimEnsembleCurveSet::defineUiTreeOrdering(caf::PdmUiTreeOrdering& uiTreeOrd uiTreeOrdering.skipRemainingChildren(true); // Reset dynamic icon - this->setUiIcon(QIcon()); + this->setUiIcon(caf::QIconProvider()); // Get static one - QIcon icon = this->uiIcon(); + caf::QIconProvider iconProvider = this->uiIconProvider(); + + if (iconProvider.isNull()) return; + + QIcon icon = iconProvider.icon(); RimEnsembleCurveSetCollection* coll = nullptr; this->firstAncestorOrThisOfType(coll); @@ -698,11 +702,10 @@ void RimEnsembleCurveSet::defineUiTreeOrdering(caf::PdmUiTreeOrdering& uiTreeOrd QPainter painter(&combined); QPixmap updownpixmap(":/StepUpDownCorner16x16.png"); painter.drawPixmap(0,0,updownpixmap); - - icon = QIcon(combined); + iconProvider.setPixmap(combined); } - this->setUiIcon(icon); + this->setUiIcon(iconProvider); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/Summary/RimObservedDataCollection.cpp b/ApplicationCode/ProjectDataModel/Summary/RimObservedDataCollection.cpp index 7e09a7401e..d5f51a5b76 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimObservedDataCollection.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimObservedDataCollection.cpp @@ -19,7 +19,7 @@ #include "RimObservedDataCollection.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RiaLogging.h" #include "SummaryPlotCommands/RicPasteAsciiDataToSummaryPlotFeatureUi.h" @@ -108,7 +108,7 @@ void updateNewSummaryObjectCreated(caf::PdmObject* object) caf::PdmUiObjectEditorHandle::updateUiAllObjectEditors(); - RiuPlotMainWindow* mpw = RiaApplication::instance()->mainPlotWindow(); + RiuPlotMainWindow* mpw = RiaGuiApplication::instance()->mainPlotWindow(); if (mpw) mpw->updateSummaryPlotToolBar(); } diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCaseCollection.cpp b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCaseCollection.cpp index 10a6d23a92..61f6f1c795 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCaseCollection.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCaseCollection.cpp @@ -576,8 +576,8 @@ QString RimSummaryCaseCollection::nameAndItemCount() const //-------------------------------------------------------------------------------------------------- void RimSummaryCaseCollection::updateIcon() { - if (m_isEnsemble) setUiIcon(QIcon(":/SummaryEnsemble16x16.png")); - else setUiIcon(QIcon(":/SummaryGroup16x16.png")); + if (m_isEnsemble) setUiIcon(":/SummaryEnsemble16x16.png"); + else setUiIcon(":/SummaryGroup16x16.png"); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCrossPlotCollection.cpp b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCrossPlotCollection.cpp index b1a519cdfc..8efab09409 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCrossPlotCollection.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCrossPlotCollection.cpp @@ -76,7 +76,7 @@ void RimSummaryCrossPlotCollection::summaryPlotItemInfos(QListuiCapability()->uiIcon(); + caf::QIconProvider icon = plot->uiCapability()->uiIconProvider(); QString displayName = plot->description(); optionInfos->push_back(caf::PdmOptionItemInfo(displayName, plot, false, icon)); diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurve.cpp b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurve.cpp index b946580ce7..9b07f1e12b 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurve.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurve.cpp @@ -18,7 +18,7 @@ #include "RimSummaryCurve.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RiaDefines.h" #include "RifReaderEclipseSummary.h" @@ -584,9 +584,12 @@ void RimSummaryCurve::defineUiTreeOrdering(caf::PdmUiTreeOrdering& uiTreeOrderin RimPlotCurve::defineUiTreeOrdering(uiTreeOrdering, uiConfigName); // Reset dynamic icon - this->setUiIcon(QIcon()); + this->setUiIcon(caf::QIconProvider()); // Get static one - QIcon icon = this->uiIcon(); + caf::QIconProvider iconProvider = this->uiIconProvider(); + if (iconProvider.isNull()) return; + + QIcon icon = iconProvider.icon(); RimSummaryCurveCollection* coll = nullptr; this->firstAncestorOrThisOfType(coll); @@ -596,11 +599,9 @@ void RimSummaryCurve::defineUiTreeOrdering(caf::PdmUiTreeOrdering& uiTreeOrderin QPainter painter(&combined); QPixmap updownpixmap(":/StepUpDownCorner16x16.png"); painter.drawPixmap(0,0,updownpixmap); - - icon = QIcon(combined); + iconProvider.setPixmap(combined); + setUiIcon(iconProvider); } - - this->setUiIcon(icon); } //-------------------------------------------------------------------------------------------------- @@ -872,7 +873,7 @@ void RimSummaryCurve::fieldChangedByUi(const caf::PdmFieldHandle* changedField, plot->updatePlotTitle(); plot->updateConnectedEditors(); - RiuPlotMainWindow* mainPlotWindow = RiaApplication::instance()->mainPlotWindow(); + RiuPlotMainWindow* mainPlotWindow = RiaGuiApplication::instance()->mainPlotWindow(); mainPlotWindow->updateSummaryPlotToolBar(); if (m_showCurve() == true) @@ -1030,7 +1031,7 @@ void RimSummaryCurve::fieldChangedByUi(const caf::PdmFieldHandle* changedField, plot->updatePlotTitle(); plot->updateConnectedEditors(); - RiuPlotMainWindow* mainPlotWindow = RiaApplication::instance()->mainPlotWindow(); + RiuPlotMainWindow* mainPlotWindow = RiaGuiApplication::instance()->mainPlotWindow(); mainPlotWindow->updateSummaryPlotToolBar(); } diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlotCollection.cpp b/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlotCollection.cpp index 44fad92fd8..d646c7826d 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlotCollection.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlotCollection.cpp @@ -88,10 +88,8 @@ void RimSummaryPlotCollection::summaryPlotItemInfos(QListuiCapability()->uiIcon(); QString displayName = plot->description(); - - optionInfos->push_back(caf::PdmOptionItemInfo(displayName, plot, false, icon)); + optionInfos->push_back(caf::PdmOptionItemInfo(displayName, plot, false, plot->uiCapability()->uiIconProvider())); } } diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlotSourceStepping.cpp b/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlotSourceStepping.cpp index bef4ebd249..0712440fcb 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlotSourceStepping.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlotSourceStepping.cpp @@ -18,7 +18,7 @@ #include "RimSummaryPlotSourceStepping.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RiaSummaryCurveAnalyzer.h" #include "RiaSummaryCurveDefinition.h" @@ -364,7 +364,7 @@ void RimSummaryPlotSourceStepping::fieldChangedByUi(const caf::PdmFieldHandle* c ensembleCurveColl->updateConnectedEditors(); } - RiuPlotMainWindow* mainPlotWindow = RiaApplication::instance()->getOrCreateMainPlotWindow(); + RiuPlotMainWindow* mainPlotWindow = RiaGuiApplication::instance()->getOrCreateMainPlotWindow(); bool forceUpdateOfFieldsInToolbar = true; mainPlotWindow->updateSummaryPlotToolBar(forceUpdateOfFieldsInToolbar); @@ -580,7 +580,7 @@ void RimSummaryPlotSourceStepping::fieldChangedByUi(const caf::PdmFieldHandle* c curveCollection->updateConnectedEditors(); } - RiuPlotMainWindow* mainPlotWindow = RiaApplication::instance()->mainPlotWindow(); + RiuPlotMainWindow* mainPlotWindow = RiaGuiApplication::instance()->mainPlotWindow(); mainPlotWindow->updateSummaryPlotToolBar(); } } diff --git a/ApplicationCode/SocketInterface/RiaSocketTools.cpp b/ApplicationCode/SocketInterface/RiaSocketTools.cpp index 54fec4968d..26ac13f5f6 100644 --- a/ApplicationCode/SocketInterface/RiaSocketTools.cpp +++ b/ApplicationCode/SocketInterface/RiaSocketTools.cpp @@ -130,13 +130,13 @@ bool RiaSocketTools::writeBlockData(RiaSocketServer* server, QTcpSocket* socket, { for (int i = 0; i < errorMessages.size(); i++) { - server->showErrorMessage(errorMessages[i]); + RiaApplication::instance()->showErrorMessage(errorMessages[i]); } // double totalTimeMS = timer.time() * 1000.0; // QString resultInfo = QString("Total time '%1 ms'").arg(totalTimeMS); // -// server->showMessage(resultInfo); +// RiaApplication::instance()->showErrorMessage(resultInfo); } return writeSucceded; diff --git a/ApplicationCode/UserInterface/CMakeLists_files.cmake b/ApplicationCode/UserInterface/CMakeLists_files.cmake index c56cbeb05d..7e4b0ae1b7 100644 --- a/ApplicationCode/UserInterface/CMakeLists_files.cmake +++ b/ApplicationCode/UserInterface/CMakeLists_files.cmake @@ -83,6 +83,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RiuQwtPlotTools.h ${CMAKE_CURRENT_LIST_DIR}/RiuWellPathComponentPlotItem.h ${CMAKE_CURRENT_LIST_DIR}/RiuMeasurementViewEventFilter.h ${CMAKE_CURRENT_LIST_DIR}/RiuDraggableOverlayFrame.h +${CMAKE_CURRENT_LIST_DIR}/RiuMdiMaximizeWindowGuard.h ) set (SOURCE_GROUP_SOURCE_FILES @@ -165,6 +166,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RiuQwtPlotItemGroup.cpp ${CMAKE_CURRENT_LIST_DIR}/RiuQwtPlotTools.cpp ${CMAKE_CURRENT_LIST_DIR}/RiuWellPathComponentPlotItem.cpp ${CMAKE_CURRENT_LIST_DIR}/RiuDraggableOverlayFrame.cpp +${CMAKE_CURRENT_LIST_DIR}/RiuMdiMaximizeWindowGuard.cpp ) list(APPEND CODE_HEADER_FILES diff --git a/ApplicationCode/UserInterface/RiuCvfOverlayItemWidget.cpp b/ApplicationCode/UserInterface/RiuCvfOverlayItemWidget.cpp index 03ef42752b..35f0bc0ad9 100644 --- a/ApplicationCode/UserInterface/RiuCvfOverlayItemWidget.cpp +++ b/ApplicationCode/UserInterface/RiuCvfOverlayItemWidget.cpp @@ -18,7 +18,7 @@ #include "RiuCvfOverlayItemWidget.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "cafTitledOverlayFrame.h" #include "cafViewer.h" @@ -66,7 +66,7 @@ void RiuCvfOverlayItemWidget::updateFromOverlayItem( caf::TitledOverlayFrame * i unsigned int height = item->renderSize().y(); QGLFormat glFormat; - glFormat.setDirectRendering(RiaApplication::instance()->useShaders()); + glFormat.setDirectRendering(RiaGuiApplication::instance()->useShaders()); // Enforce no border to avoid item->setBackgroundFrameColor(cvf::Color4f(0, 0, 0, 0)); @@ -88,7 +88,7 @@ void RiuCvfOverlayItemWidget::updateFromOverlayItem( caf::TitledOverlayFrame * i cvf::ref renderingSequence = new cvf::RenderSequence; renderingSequence->addRendering(rendering.p()); - if (RiaApplication::instance()->useShaders()) + if (RiaGuiApplication::instance()->useShaders()) { // Set up frame and render buffers diff --git a/ApplicationCode/UserInterface/RiuMainWindow.cpp b/ApplicationCode/UserInterface/RiuMainWindow.cpp index 2d70a0a69d..26d94e4cf8 100644 --- a/ApplicationCode/UserInterface/RiuMainWindow.cpp +++ b/ApplicationCode/UserInterface/RiuMainWindow.cpp @@ -20,7 +20,7 @@ #include "RiuMainWindow.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RiaBaseDefs.h" #include "RiaPreferences.h" #include "RiaRegressionTest.h" @@ -159,7 +159,11 @@ RiuMainWindow::RiuMainWindow() //-------------------------------------------------------------------------------------------------- RiuMainWindow* RiuMainWindow::instance() { - return RiaApplication::instance()->mainWindow(); + if (RiaGuiApplication::isRunning()) + { + return RiaGuiApplication::instance()->mainWindow(); + } + return nullptr; } //-------------------------------------------------------------------------------------------------- @@ -266,7 +270,7 @@ void RiuMainWindow::cleanupGuiBeforeProjectClose() //-------------------------------------------------------------------------------------------------- void RiuMainWindow::closeEvent(QCloseEvent* event) { - RiaApplication* app = RiaApplication::instance(); + RiaGuiApplication* app = RiaGuiApplication::instance(); app->saveMainWinGeoAndDockToolBarLayout(); @@ -461,7 +465,7 @@ void RiuMainWindow::createMenus() fileMenu->addAction(cmdFeatureMgr->action("RicSaveProjectFeature")); fileMenu->addAction(cmdFeatureMgr->action("RicSaveProjectAsFeature")); - std::vector recentFileActions = RiaApplication::instance()->recentFileActions(); + std::vector recentFileActions = RiaGuiApplication::instance()->recentFileActions(); for (auto act : recentFileActions) { fileMenu->addAction(act); diff --git a/ApplicationCode/UserInterface/RiuMdiMaximizeWindowGuard.cpp b/ApplicationCode/UserInterface/RiuMdiMaximizeWindowGuard.cpp new file mode 100644 index 0000000000..a1e89eddf8 --- /dev/null +++ b/ApplicationCode/UserInterface/RiuMdiMaximizeWindowGuard.cpp @@ -0,0 +1,49 @@ +#include "RiuMdiMaximizeWindowGuard.h" + +#include "RiaGuiApplication.h" +#include "RiuMainWindow.h" +#include "RiuPlotMainWindow.h" + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiuMdiMaximizeWindowGuard::RiuMdiMaximizeWindowGuard() +{ + { + RiuMainWindow* mainWindow = RiaGuiApplication::instance()->mainWindow(); + if (mainWindow) + { + mainWindow->enableShowFirstVisibleMdiWindowMaximized(false); + } + } + + { + RiuPlotMainWindow* plotMainWindow = RiaGuiApplication::instance()->mainPlotWindow(); + if (plotMainWindow) + { + plotMainWindow->enableShowFirstVisibleMdiWindowMaximized(false); + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiuMdiMaximizeWindowGuard::~RiuMdiMaximizeWindowGuard() +{ + { + RiuMainWindow* mainWindow = RiaGuiApplication::instance()->mainWindow(); + if (mainWindow) + { + mainWindow->enableShowFirstVisibleMdiWindowMaximized(true); + } + } + + { + RiuPlotMainWindow* plotMainWindow = RiaGuiApplication::instance()->mainPlotWindow(); + if (plotMainWindow) + { + plotMainWindow->enableShowFirstVisibleMdiWindowMaximized(true); + } + } +} diff --git a/ApplicationCode/UserInterface/RiuMdiMaximizeWindowGuard.h b/ApplicationCode/UserInterface/RiuMdiMaximizeWindowGuard.h new file mode 100644 index 0000000000..12d0038c96 --- /dev/null +++ b/ApplicationCode/UserInterface/RiuMdiMaximizeWindowGuard.h @@ -0,0 +1,32 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS +// +// 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 + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +class RiuMdiMaximizeWindowGuard +{ +public: + RiuMdiMaximizeWindowGuard(); + ~RiuMdiMaximizeWindowGuard(); +}; + + diff --git a/ApplicationCode/UserInterface/RiuMdiSubWindow.cpp b/ApplicationCode/UserInterface/RiuMdiSubWindow.cpp index 56ddd44deb..7999d79c25 100644 --- a/ApplicationCode/UserInterface/RiuMdiSubWindow.cpp +++ b/ApplicationCode/UserInterface/RiuMdiSubWindow.cpp @@ -18,7 +18,7 @@ #include "RiuMdiSubWindow.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "Rim3dView.h" #include "RimSummaryPlot.h" @@ -59,7 +59,7 @@ RimMdiWindowGeometry RiuMdiSubWindow::windowGeometry() const RimMdiWindowGeometry geo; int mainWinID = 0; - if (window() == RiaApplication::instance()->mainPlotWindow()) + if (window() == RiaGuiApplication::instance()->mainPlotWindow()) { mainWinID = 1; } @@ -132,13 +132,13 @@ void RiuMdiSubWindow::resizeEvent(QResizeEvent* resizeEvent) if (!m_blockTilingChanges) { - if (window() == RiaApplication::instance()->mainWindow()) + if (window() == RiaGuiApplication::instance()->mainWindow()) { - RiaApplication::instance()->mainWindow()->storeSubWindowTiling(false); + RiaGuiApplication::instance()->mainWindow()->storeSubWindowTiling(false); } - else if (window() == RiaApplication::instance()->mainPlotWindow()) + else if (window() == RiaGuiApplication::instance()->mainPlotWindow()) { - RiaApplication::instance()->mainPlotWindow()->storeSubWindowTiling(false); + RiaGuiApplication::instance()->mainPlotWindow()->storeSubWindowTiling(false); } } @@ -157,13 +157,13 @@ void RiuMdiSubWindow::moveEvent(QMoveEvent* moveEvent) if (!m_blockTilingChanges) { - if (window() == RiaApplication::instance()->mainWindow()) + if (window() == RiaGuiApplication::instance()->mainWindow()) { - RiaApplication::instance()->mainWindow()->storeSubWindowTiling(false); + RiaGuiApplication::instance()->mainWindow()->storeSubWindowTiling(false); } - else if (window() == RiaApplication::instance()->mainPlotWindow()) + else if (window() == RiaGuiApplication::instance()->mainPlotWindow()) { - RiaApplication::instance()->mainPlotWindow()->storeSubWindowTiling(false); + RiaGuiApplication::instance()->mainPlotWindow()->storeSubWindowTiling(false); } } diff --git a/ApplicationCode/UserInterface/RiuPlotMainWindow.cpp b/ApplicationCode/UserInterface/RiuPlotMainWindow.cpp index cc0fa9b57b..4e06f9b0e3 100644 --- a/ApplicationCode/UserInterface/RiuPlotMainWindow.cpp +++ b/ApplicationCode/UserInterface/RiuPlotMainWindow.cpp @@ -178,7 +178,7 @@ void RiuPlotMainWindow::cleanUpTemporaryWidgets() //-------------------------------------------------------------------------------------------------- void RiuPlotMainWindow::closeEvent(QCloseEvent* event) { - RiaApplication* app = RiaApplication::instance(); + RiaGuiApplication* app = RiaGuiApplication::instance(); app->savePlotWinGeoAndDockToolBarLayout(); @@ -260,7 +260,7 @@ void RiuPlotMainWindow::createMenus() fileMenu->addAction(cmdFeatureMgr->action("RicSaveProjectFeature")); fileMenu->addAction(cmdFeatureMgr->action("RicSaveProjectAsFeature")); - std::vector recentFileActions = RiaApplication::instance()->recentFileActions(); + std::vector recentFileActions = RiaGuiApplication::instance()->recentFileActions(); for (auto act : recentFileActions) { fileMenu->addAction(act); diff --git a/ApplicationCode/UserInterface/RiuPlotMainWindowTools.cpp b/ApplicationCode/UserInterface/RiuPlotMainWindowTools.cpp index 4248fdaf79..3a55288cd8 100644 --- a/ApplicationCode/UserInterface/RiuPlotMainWindowTools.cpp +++ b/ApplicationCode/UserInterface/RiuPlotMainWindowTools.cpp @@ -17,7 +17,7 @@ ///////////////////////////////////////////////////////////////////////////////// #include "RiuPlotMainWindowTools.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RiuPlotMainWindow.h" //-------------------------------------------------------------------------------------------------- @@ -25,7 +25,7 @@ //-------------------------------------------------------------------------------------------------- void RiuPlotMainWindowTools::showPlotMainWindow() { - RiaApplication::instance()->getOrCreateAndShowMainPlotWindow(); + RiaGuiApplication::instance()->getOrCreateAndShowMainPlotWindow(); } //-------------------------------------------------------------------------------------------------- @@ -33,7 +33,7 @@ void RiuPlotMainWindowTools::showPlotMainWindow() //-------------------------------------------------------------------------------------------------- void RiuPlotMainWindowTools::setActiveViewer(QWidget* subWindow) { - RiuPlotMainWindow* mpw = RiaApplication::instance()->mainPlotWindow(); + RiuPlotMainWindow* mpw = RiaGuiApplication::instance()->mainPlotWindow(); if (mpw) mpw->setActiveViewer(subWindow); } @@ -43,7 +43,7 @@ void RiuPlotMainWindowTools::setActiveViewer(QWidget* subWindow) //-------------------------------------------------------------------------------------------------- void RiuPlotMainWindowTools::setExpanded(const caf::PdmUiItem* uiItem, bool expanded /*= true*/) { - RiuPlotMainWindow* mpw = RiaApplication::instance()->mainPlotWindow(); + RiuPlotMainWindow* mpw = RiaGuiApplication::instance()->mainPlotWindow(); if (mpw) mpw->setExpanded(uiItem, expanded); } @@ -53,7 +53,7 @@ void RiuPlotMainWindowTools::setExpanded(const caf::PdmUiItem* uiItem, bool expa //-------------------------------------------------------------------------------------------------- void RiuPlotMainWindowTools::selectAsCurrentItem(const caf::PdmObject* object, bool allowActiveViewChange /*= true*/) { - RiuPlotMainWindow* mpw = RiaApplication::instance()->mainPlotWindow(); + RiuPlotMainWindow* mpw = RiaGuiApplication::instance()->mainPlotWindow(); if (mpw) mpw->selectAsCurrentItem(object, allowActiveViewChange); } @@ -63,7 +63,7 @@ void RiuPlotMainWindowTools::selectAsCurrentItem(const caf::PdmObject* object, b //-------------------------------------------------------------------------------------------------- void RiuPlotMainWindowTools::refreshToolbars() { - RiuPlotMainWindow* mpw = RiaApplication::instance()->mainPlotWindow(); + RiuPlotMainWindow* mpw = RiaGuiApplication::instance()->mainPlotWindow(); if (mpw) { diff --git a/ApplicationCode/UserInterface/RiuPlotObjectPicker.cpp b/ApplicationCode/UserInterface/RiuPlotObjectPicker.cpp index ca09f25809..409e99e7cd 100644 --- a/ApplicationCode/UserInterface/RiuPlotObjectPicker.cpp +++ b/ApplicationCode/UserInterface/RiuPlotObjectPicker.cpp @@ -18,7 +18,7 @@ #include "RiuPlotObjectPicker.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RiuPlotMainWindow.h" #include @@ -39,7 +39,7 @@ RiuPlotObjectPicker::RiuPlotObjectPicker(QWidget* widget, caf::PdmObject* associ //-------------------------------------------------------------------------------------------------- bool RiuPlotObjectPicker::eventFilter(QObject* watchedObject, QEvent* event) { - RiuPlotMainWindow* mainPlotWindow = RiaApplication::instance()->mainPlotWindow(); + RiuPlotMainWindow* mainPlotWindow = RiaGuiApplication::instance()->mainPlotWindow(); if (mainPlotWindow && m_associatedObject.notNull()) { if (event->type() == QEvent::MouseButtonPress) diff --git a/ApplicationCode/UserInterface/RiuRecentFileActionProvider.cpp b/ApplicationCode/UserInterface/RiuRecentFileActionProvider.cpp index aa7b62cb1e..a8b12763c9 100644 --- a/ApplicationCode/UserInterface/RiuRecentFileActionProvider.cpp +++ b/ApplicationCode/UserInterface/RiuRecentFileActionProvider.cpp @@ -18,7 +18,7 @@ #include "RiuRecentFileActionProvider.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RiaFilePathTools.h" #include @@ -125,7 +125,7 @@ void RiuRecentFileActionProvider::slotOpenRecentFile() { QString fileName = RiaFilePathTools::toInternalSeparator(action->data().toString()); - RiaApplication* app = RiaApplication::instance(); + RiaGuiApplication* app = RiaGuiApplication::instance(); if (RiaApplication::hasValidProjectFileExtension(fileName)) { if (!app->askUserToSaveModifiedProject()) return; diff --git a/ApplicationCode/UserInterface/RiuTreeViewEventFilter.cpp b/ApplicationCode/UserInterface/RiuTreeViewEventFilter.cpp index 957683e7fa..eeb6bdb8ab 100644 --- a/ApplicationCode/UserInterface/RiuTreeViewEventFilter.cpp +++ b/ApplicationCode/UserInterface/RiuTreeViewEventFilter.cpp @@ -21,7 +21,7 @@ #include "ToggleCommands/RicToggleItemsFeatureImpl.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RimCaseCollection.h" #include "RimEclipseCase.h" @@ -104,9 +104,9 @@ bool RiuTreeViewEventFilter::eventFilter(QObject *obj, QEvent *event) { toggleStateForSelection = false; } - else if (RiaApplication::instance()->mainPlotWindow() && - RiaApplication::instance()->mainPlotWindow()->projectTreeView() && - RiaApplication::instance()->mainPlotWindow()->projectTreeView()->isTreeItemEditWidgetActive()) + else if (RiaGuiApplication::instance()->mainPlotWindow() && + RiaGuiApplication::instance()->mainPlotWindow()->projectTreeView() && + RiaGuiApplication::instance()->mainPlotWindow()->projectTreeView()->isTreeItemEditWidgetActive()) { toggleStateForSelection = false; } diff --git a/ApplicationCode/UserInterface/RiuViewer.cpp b/ApplicationCode/UserInterface/RiuViewer.cpp index 70084ed0d2..f3db2871f5 100644 --- a/ApplicationCode/UserInterface/RiuViewer.cpp +++ b/ApplicationCode/UserInterface/RiuViewer.cpp @@ -93,9 +93,9 @@ RiuViewer::RiuViewer(const QGLFormat& format, QWidget* parent) : caf::Viewer(format, parent) , m_isNavigationRotationEnabled(true) { - cvf::Font* standardFont = RiaApplication::instance()->defaultSceneFont(); - QFont font = QApplication::font(); - font.setPointSize(RiaFontCache::pointSizeFromFontSizeEnum(RiaApplication::instance()->preferences()->defaultSceneFontSize())); + cvf::Font* standardFont = RiaGuiApplication::instance()->defaultSceneFont(); + QFont font = RiaGuiApplication::instance()->font(); + font.setPointSize(RiaFontCache::pointSizeFromFontSizeEnum(RiaGuiApplication::instance()->preferences()->defaultSceneFontSize())); m_axisCross = new cvf::OverlayAxisCross(m_mainCamera.p(), standardFont); m_axisCross->setAxisLabels("X", "Y", "Z"); @@ -559,7 +559,7 @@ void RiuViewer::removeAllColorLegends() //-------------------------------------------------------------------------------------------------- void RiuViewer::addColorLegendToBottomLeftCorner(caf::TitledOverlayFrame* addedLegend) { - RiaApplication* app = RiaApplication::instance(); + RiaGuiApplication* app = RiaGuiApplication::instance(); CVF_ASSERT(app); RiaPreferences* preferences = app->preferences(); cvf::Rendering* firstRendering = m_mainRendering.p(); @@ -689,21 +689,21 @@ void RiuViewer::enableNavigationRotation(bool enable) //-------------------------------------------------------------------------------------------------- void RiuViewer::updateNavigationPolicy() { - switch (RiaApplication::instance()->navigationPolicy()) + switch (RiaGuiApplication::instance()->navigationPolicy()) { - case RiaApplication::NAVIGATION_POLICY_CAD: + case RiaGuiApplication::NAVIGATION_POLICY_CAD: setNavigationPolicy(new RiuCadNavigation); break; - case RiaApplication::NAVIGATION_POLICY_CEETRON: + case RiaGuiApplication::NAVIGATION_POLICY_CEETRON: setNavigationPolicy(new caf::CeetronPlusNavigation); break; - case RiaApplication::NAVIGATION_POLICY_GEOQUEST: + case RiaGuiApplication::NAVIGATION_POLICY_GEOQUEST: setNavigationPolicy(new RiuGeoQuestNavigation); break; - case RiaApplication::NAVIGATION_POLICY_RMS: + case RiaGuiApplication::NAVIGATION_POLICY_RMS: setNavigationPolicy(new RiuRmsNavigation); break; @@ -1062,7 +1062,7 @@ void RiuViewer::clearHoverCursor() //-------------------------------------------------------------------------------------------------- void RiuViewer::updateFonts() { - cvf::Font* standardFont = RiaApplication::instance()->defaultSceneFont(); + cvf::Font* standardFont = RiaGuiApplication::instance()->defaultSceneFont(); m_mainRendering->removeOverlayItem(m_axisCross.p()); m_axisCross = new cvf::OverlayAxisCross(m_mainCamera.p(), standardFont); diff --git a/Fwk/AppFwk/cafCommand/cafCmdFeature.cpp b/Fwk/AppFwk/cafCommand/cafCmdFeature.cpp index d1133284ca..f6a3cf97b4 100644 --- a/Fwk/AppFwk/cafCommand/cafCmdFeature.cpp +++ b/Fwk/AppFwk/cafCommand/cafCmdFeature.cpp @@ -42,7 +42,7 @@ #include "cafPdmUiModelChangeDetector.h" #include - +#include namespace caf { @@ -106,7 +106,10 @@ QAction* CmdFeature::actionWithUserData(const QString& customText, const QVarian action->setData(userData); } - this->setupActionLook(action); + if (dynamic_cast(QCoreApplication::instance())) + { + this->setupActionLook(action); + } if (!customText.isEmpty()) { action->setText(customText); diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmObject.h b/Fwk/AppFwk/cafProjectDataModel/cafPdmObject.h index 2914a7ecfc..d263892418 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmObject.h +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmObject.h @@ -61,6 +61,7 @@ class QXmlStreamWriter; #include "cafInternalPdmXmlFieldCapability.h" #include "cafPdmUiFieldSpecialization.h" +#include "cafQIconProvider.h" namespace caf @@ -85,7 +86,7 @@ class PdmObjectCapability; this->isInheritedFromPdmUiObject(); \ this->isInheritedFromPdmXmlSerializable(); \ \ - static caf::PdmUiItemInfo objDescr(uiName, QIcon(QString(iconResourceName)), toolTip, whatsThis); \ + static caf::PdmUiItemInfo objDescr(uiName, QString(iconResourceName), toolTip, whatsThis); \ this->setUiItemInfo(&objDescr); \ } @@ -106,7 +107,7 @@ class PdmObjectCapability; AddXmlCapabilityToField(field); \ AddUiCapabilityToField(field); \ \ - static caf::PdmUiItemInfo objDescr(uiName, QIcon(QString(iconResourceName)), toolTip, whatsThis, keyword); \ + static caf::PdmUiItemInfo objDescr(uiName, QString(iconResourceName), toolTip, whatsThis, keyword); \ addFieldUi(field, keyword, default, &objDescr); \ } @@ -124,7 +125,7 @@ class PdmObjectCapability; AddXmlCapabilityToField(field); \ AddUiCapabilityToField(field); \ \ - static caf::PdmUiItemInfo objDescr(uiName, QIcon(QString(iconResourceName)), toolTip, whatsThis, keyword); \ + static caf::PdmUiItemInfo objDescr(uiName, QString(iconResourceName), toolTip, whatsThis, keyword); \ addFieldUiNoDefault(field, keyword, &objDescr); \ } diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/CMakeLists.txt b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/CMakeLists.txt index c400014550..5b4305ef87 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/CMakeLists.txt +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/CMakeLists.txt @@ -76,6 +76,8 @@ set( PROJECT_FILES cafPdmUiSelection3dEditorVisualizer.cpp cafQShortenedLabel.cpp cafQShortenedLabel.h + cafQIconProvider.cpp + cafQIconProvider.h ) diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafInternalPdmUiFieldCapability.inl b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafInternalPdmUiFieldCapability.inl index 34b98ff1db..ded2cc2fd1 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafInternalPdmUiFieldCapability.inl +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafInternalPdmUiFieldCapability.inl @@ -209,7 +209,7 @@ QList caf::PdmFieldUiCap::valueOptions(bool* useOp { if(!uiBasedQVariant.toString().isEmpty()) { - m_optionEntryCache.push_front(PdmOptionItemInfo(uiBasedQVariant.toString(), uiBasedQVariant, true, QIcon())); + m_optionEntryCache.push_front(PdmOptionItemInfo(uiBasedQVariant.toString(), uiBasedQVariant, true)); } } else // The field value is a list of values @@ -228,7 +228,7 @@ QList caf::PdmFieldUiCap::valueOptions(bool* useOp if(!isFound && !valuesSelectedInField[i].toString().isEmpty()) { - m_optionEntryCache.push_front(PdmOptionItemInfo(valuesSelectedInField[i].toString(), valuesSelectedInField[i], true, QIcon())); + m_optionEntryCache.push_front(PdmOptionItemInfo(valuesSelectedInField[i].toString(), valuesSelectedInField[i], true)); } } } diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiItem.cpp b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiItem.cpp index cca07972ea..4d17f8a3f2 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiItem.cpp +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiItem.cpp @@ -41,17 +41,79 @@ namespace caf { + + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -PdmOptionItemInfo::PdmOptionItemInfo(const QString& anOptionUiText, - const QVariant& aValue, - bool isReadOnly /* = false */, - QIcon anIcon /* = QIcon()*/) +PdmUiItemInfo::PdmUiItemInfo(const QString& uiName, + QIconProvider iconProvider /*= QIconProvider() */, + QString toolTip /*= ""*/, + QString whatsThis /*= ""*/, + QString extraDebugText /*= ""*/) + : m_uiName(uiName) + , m_iconProvider(iconProvider) + , m_toolTip(toolTip) + , m_whatsThis(whatsThis) + , m_extraDebugText(extraDebugText) + , m_editorTypeName("") + , m_isHidden(false) + , m_isTreeChildrenHidden(false) + , m_isReadOnly(false) + , m_labelAlignment(LEFT) + , m_isCustomContextMenuEnabled(false) +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +PdmUiItemInfo::PdmUiItemInfo(const QString& uiName, + QString iconResourceLocation /*= ""*/, + QString toolTip /*= ""*/, + QString whatsThis /*= ""*/, + QString extraDebugText /*= ""*/) + : m_uiName(uiName) + , m_iconProvider(iconResourceLocation) + , m_toolTip(toolTip) + , m_whatsThis(whatsThis) + , m_extraDebugText(extraDebugText) + , m_editorTypeName("") + , m_isHidden(false) + , m_isTreeChildrenHidden(false) + , m_isReadOnly(false) + , m_labelAlignment(LEFT) + , m_isCustomContextMenuEnabled(false) +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QIcon PdmUiItemInfo::icon() const +{ + return m_iconProvider.icon(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +const QIconProvider& PdmUiItemInfo::iconProvider() const +{ + return m_iconProvider; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +PdmOptionItemInfo::PdmOptionItemInfo(const QString& anOptionUiText, + const QVariant& aValue, + bool isReadOnly /* = false */, + const QIconProvider& anIcon /* = QIconProvider()*/) : m_optionUiText(anOptionUiText) , m_value(aValue) , m_isReadOnly(isReadOnly) - , m_icon(anIcon) + , m_iconProvider(anIcon) , m_level(0) { } @@ -62,10 +124,10 @@ PdmOptionItemInfo::PdmOptionItemInfo(const QString& anOptionUiText, PdmOptionItemInfo::PdmOptionItemInfo(const QString& anOptionUiText, caf::PdmObjectHandle* obj, bool isReadOnly /*= false*/, - QIcon anIcon /*= QIcon()*/) + const QIconProvider& anIcon /*= QIconProvider()*/) : m_optionUiText(anOptionUiText) , m_isReadOnly(isReadOnly) - , m_icon(anIcon) + , m_iconProvider(anIcon) , m_level(0) { m_value = QVariant::fromValue(caf::PdmPointer(obj)); @@ -75,7 +137,7 @@ PdmOptionItemInfo::PdmOptionItemInfo(const QString& anOptionUiText, /// //-------------------------------------------------------------------------------------------------- PdmOptionItemInfo - PdmOptionItemInfo::createHeader(const QString& anOptionUiText, bool isReadOnly /*= false*/, QIcon anIcon /*= QIcon()*/) + PdmOptionItemInfo::createHeader(const QString& anOptionUiText, bool isReadOnly /*= false*/, const QIconProvider& anIcon /*= QIconProvider()*/) { PdmOptionItemInfo header(anOptionUiText, QVariant(), isReadOnly, anIcon); @@ -127,7 +189,7 @@ bool PdmOptionItemInfo::isHeading() const //-------------------------------------------------------------------------------------------------- const QIcon PdmOptionItemInfo::icon() const { - return m_icon; + return m_iconProvider.icon(); } //-------------------------------------------------------------------------------------------------- @@ -188,23 +250,38 @@ void PdmUiItem::setUiName(const QString& uiName, const QString& uiConfigName /*= //-------------------------------------------------------------------------------------------------- const QIcon PdmUiItem::uiIcon(const QString& uiConfigName) const { - const PdmUiItemInfo* conInfo = configInfo(uiConfigName); - const PdmUiItemInfo* defInfo = defaultInfo(); - const PdmUiItemInfo* sttInfo = m_staticItemInfo; - - if (conInfo && !(conInfo->m_icon.isNull())) return conInfo->m_icon; - if (defInfo && !(defInfo->m_icon.isNull())) return defInfo->m_icon; - if (sttInfo && !(sttInfo->m_icon.isNull())) return sttInfo->m_icon; - - return QIcon(); + return uiIconProvider(uiConfigName).icon(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void PdmUiItem::setUiIcon(const QIcon& uiIcon, const QString& uiConfigName /*= ""*/) +const QIconProvider PdmUiItem::uiIconProvider(const QString& uiConfigName) const { - m_configItemInfos[uiConfigName].m_icon = uiIcon; + const PdmUiItemInfo* conInfo = configInfo(uiConfigName); + const PdmUiItemInfo* defInfo = defaultInfo(); + const PdmUiItemInfo* sttInfo = m_staticItemInfo; + + if (conInfo && !(conInfo->iconProvider().isNull())) return conInfo->iconProvider(); + if (defInfo && !(defInfo->iconProvider().isNull())) return defInfo->iconProvider(); + if (sttInfo && !(sttInfo->iconProvider().isNull())) return sttInfo->iconProvider(); + + return QIconProvider(); +} +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void PdmUiItem::setUiIcon(const QIconProvider& uiIconProvider, const QString& uiConfigName /*= ""*/) +{ + m_configItemInfos[uiConfigName].m_iconProvider = uiIconProvider; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void PdmUiItem::setUiIcon(const QString& uiIconResourceName, const QString& uiConfigName /*= ""*/) +{ + setUiIcon(caf::QIconProvider(uiIconResourceName), uiConfigName); } //-------------------------------------------------------------------------------------------------- @@ -575,32 +652,9 @@ PdmUiItem::PdmUiItem() //-------------------------------------------------------------------------------------------------- void PdmUiItem::updateUiIconFromState(bool isActive, const QString& uiConfigName) { - static const QString iconStorageConfigNamePostfix = "_Internally_StoredNormalIcon"; - const PdmUiItemInfo* conInfo = configInfo(uiConfigName + iconStorageConfigNamePostfix); - QIcon normalIcon; - - if (conInfo) - { - normalIcon = conInfo->m_icon; - } - else - { - normalIcon = this->uiIcon(uiConfigName); - } - - this->setUiIcon(normalIcon, uiConfigName + iconStorageConfigNamePostfix); - - if (isActive) - { - this->setUiIcon(normalIcon, uiConfigName); - m_configItemInfos.erase(uiConfigName + iconStorageConfigNamePostfix); - } - else - { - QIcon disabledIcon(normalIcon.pixmap(16, 16, QIcon::Disabled)); - this->setUiIcon(disabledIcon, uiConfigName); - this->setUiIcon(normalIcon, uiConfigName + iconStorageConfigNamePostfix); - } + QIconProvider normalIconProvider = this->uiIconProvider(uiConfigName); + normalIconProvider.setActive(isActive); + this->setUiIcon(normalIconProvider, uiConfigName); } //-------------------------------------------------------------------------------------------------- diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiItem.h b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiItem.h index f1bcc325fa..954f61b0ca 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiItem.h +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiItem.h @@ -38,9 +38,10 @@ #pragma once #include "cafPdmUiFieldSpecialization.h" +#include "cafQIconProvider.h" +#include #include -#include #include #include @@ -55,6 +56,13 @@ namespace caf class PdmUiItemInfo { public: + enum LabelPosType + { + LEFT, + TOP, + HIDDEN + }; + PdmUiItemInfo() : m_editorTypeName("") , m_isHidden(-1) @@ -64,26 +72,25 @@ public: , m_isCustomContextMenuEnabled(-1) {} - PdmUiItemInfo(const QString& uiName, QIcon icon = QIcon(), QString toolTip = "", QString whatsThis = "", QString extraDebugText = "") - : m_uiName(uiName) - , m_icon(icon) - , m_toolTip(toolTip) - , m_whatsThis(whatsThis) - , m_extraDebugText(extraDebugText) - , m_editorTypeName("") - , m_isHidden(false) - , m_isTreeChildrenHidden(false) - , m_isReadOnly(false) - , m_labelAlignment(LEFT) - , m_isCustomContextMenuEnabled(false) - { } + PdmUiItemInfo(const QString& uiName, + QString iconResourceLocation = "", + QString toolTip = "", + QString whatsThis = "", + QString extraDebugText = ""); - enum LabelPosType { LEFT, TOP, HIDDEN }; + PdmUiItemInfo(const QString& uiName, + QIconProvider iconProvider = QIconProvider(), + QString toolTip = "", + QString whatsThis = "", + QString extraDebugText = ""); + + QIcon icon() const; + const QIconProvider& iconProvider() const; private: friend class PdmUiItem; QString m_uiName; - QIcon m_icon; + QIconProvider m_iconProvider; QColor m_contentTextColor; ///< Color of a fields value text. Invalid by default. An Invalid color is not used. QString m_toolTip; QString m_whatsThis; @@ -104,10 +111,10 @@ private: class PdmOptionItemInfo { public: - PdmOptionItemInfo(const QString& anOptionUiText, const QVariant& aValue, bool isReadOnly = false, QIcon anIcon = QIcon()); - PdmOptionItemInfo(const QString& anOptionUiText, caf::PdmObjectHandle* obj, bool isReadOnly = false, QIcon anIcon = QIcon()); + PdmOptionItemInfo(const QString& anOptionUiText, const QVariant& aValue, bool isReadOnly = false, const QIconProvider& anIcon = QIconProvider()); + PdmOptionItemInfo(const QString& anOptionUiText, caf::PdmObjectHandle* obj, bool isReadOnly = false, const QIconProvider& anIcon = QIconProvider()); - static PdmOptionItemInfo createHeader(const QString& anOptionUiText, bool isReadOnly = false, QIcon anIcon = QIcon()); + static PdmOptionItemInfo createHeader(const QString& anOptionUiText, bool isReadOnly = false, const QIconProvider& anIcon = QIconProvider()); void setLevel(int level); @@ -128,11 +135,11 @@ public: std::vector& foundIndexes); private: - QString m_optionUiText; - QVariant m_value; - bool m_isReadOnly; - QIcon m_icon; - int m_level; + QString m_optionUiText; + QVariant m_value; + bool m_isReadOnly; + QIconProvider m_iconProvider; + int m_level; }; class PdmUiEditorHandle; @@ -217,8 +224,10 @@ public: const QString uiName(const QString& uiConfigName = "") const; void setUiName(const QString& uiName, const QString& uiConfigName = ""); - const QIcon uiIcon(const QString& uiConfigName = "") const; - void setUiIcon(const QIcon& uiIcon, const QString& uiConfigName = ""); + const QIcon uiIcon(const QString& uiConfigName = "") const; + const QIconProvider uiIconProvider(const QString& uiConfigName = "") const; + void setUiIcon(const QIconProvider& uiIcon, const QString& uiConfigName = ""); + void setUiIcon(const QString& uiIconResourceName, const QString& uiConfigName = ""); const QColor uiContentTextColor(const QString& uiConfigName = "") const; void setUiContentTextColor(const QColor& uiIcon, const QString& uiConfigName = ""); diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiTreeOrdering.cpp b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiTreeOrdering.cpp index 63c76662c9..f1f052624d 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiTreeOrdering.cpp +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiTreeOrdering.cpp @@ -179,7 +179,7 @@ PdmUiTreeOrdering::PdmUiTreeOrdering(const QString & title, const QString& iconR { m_uiItem = new PdmUiItem(); m_uiItem->setUiName(title); - m_uiItem->setUiIcon(QIcon(iconResourceName)); + m_uiItem->setUiIcon(QIconProvider(iconResourceName)); } //-------------------------------------------------------------------------------------------------- diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafQIconProvider.cpp b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafQIconProvider.cpp new file mode 100644 index 0000000000..bdc4f1c02c --- /dev/null +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafQIconProvider.cpp @@ -0,0 +1,137 @@ +#include "cafQIconProvider.h" + +#include "cafAssert.h" + +#include + +using namespace caf; + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QIconProvider::QIconProvider() + : m_active(true) +{ +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QIconProvider::QIconProvider(const QString& iconResourceString) + : m_active(true) + , m_iconResourceString(iconResourceString) +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QIconProvider::QIconProvider(const QPixmap& pixmap) + : m_iconPixmap(pixmap) +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QIconProvider::QIconProvider(const QIconProvider& rhs) + : m_icon(rhs.m_icon) + , m_active(rhs.m_active) + , m_iconResourceString(rhs.m_iconResourceString) +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QIconProvider& QIconProvider::operator=(const QIconProvider& rhs) +{ + m_icon = rhs.m_icon; + m_active = rhs.m_active; + m_iconResourceString = rhs.m_iconResourceString; + return *this; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QIcon QIconProvider::icon() const +{ + if (m_icon.isNull()) + { + m_icon = generateIcon(); + } + + if (!m_active) + { + QPixmap disabledPixmap = m_icon.pixmap(16, 16, QIcon::Disabled); + return QIcon(disabledPixmap); + } + + return m_icon; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool QIconProvider::isNull() const +{ + if (!isGuiApplication()) return true; + + if (m_iconPixmap.isNull() && m_iconResourceString.isEmpty()) return true; + + return icon().isNull(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QIconProvider::setActive(bool active) +{ + m_active = active; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QIconProvider::setIconResourceString(const QString& iconResourceString) +{ + m_iconResourceString = iconResourceString; + m_icon = QIcon(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QIconProvider::setPixmap(const QPixmap& pixmap) +{ + m_iconPixmap = pixmap; + m_icon = QIcon(); +} + +//-------------------------------------------------------------------------------------------------- +/// Generate the actual icon. Will generate a NULL-icon if a QtGuiApplication isn't running. +/// Override in a sub-class if you want to generate a custom icon procedurally +//-------------------------------------------------------------------------------------------------- +QIcon QIconProvider::generateIcon() const +{ + if (isGuiApplication()) + { + if (!m_iconPixmap.isNull()) + { + return QIcon(m_iconPixmap); + } + return QIcon(m_iconResourceString); + } + return QIcon(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool QIconProvider::isGuiApplication() +{ + return dynamic_cast(QCoreApplication::instance()) != nullptr; +} diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafQIconProvider.h b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafQIconProvider.h new file mode 100644 index 0000000000..c3ce820996 --- /dev/null +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafQIconProvider.h @@ -0,0 +1,73 @@ +//################################################################################################## +// +// Custom Visualization Core library +// Copyright (C) 2019- Ceetron Solutions AS +// +// This library may be used under the terms of either the GNU General Public License or +// the GNU Lesser General Public License as follows: +// +// GNU General Public License Usage +// This library 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. +// +// This library 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. +// +// GNU Lesser General Public License Usage +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This library 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 Lesser General Public License at <> +// for more details. +// +//################################################################################################## +#pragma once + +#include +#include +#include + +namespace caf +{ +//================================================================================================== +/// Utility class to provide QIcons when required. Qt crashes if a non-empty QIcon is created +/// ... without a GUI Application running. So create the icon on demand instead. +//================================================================================================== +class QIconProvider +{ +public: + QIconProvider(); + QIconProvider(const QString& iconResourceString); + QIconProvider(const QPixmap& pixmap); + QIconProvider(const QIconProvider& rhs); + QIconProvider& operator=(const QIconProvider& rhs); + + QIcon icon() const; + virtual bool isNull() const; + void setActive(bool active); + void setIconResourceString(const QString& iconResourceString); + void setPixmap(const QPixmap& pixmap); + +protected: + virtual QIcon generateIcon() const; + static bool isGuiApplication(); + +protected: + QString m_iconResourceString; + QPixmap m_iconPixmap; + mutable QIcon m_icon; + bool m_active; +}; +} diff --git a/Fwk/AppFwk/cafUserInterface/cafProgressInfo.cpp b/Fwk/AppFwk/cafUserInterface/cafProgressInfo.cpp index c232719a52..d730a475e2 100644 --- a/Fwk/AppFwk/cafUserInterface/cafProgressInfo.cpp +++ b/Fwk/AppFwk/cafUserInterface/cafProgressInfo.cpp @@ -40,6 +40,7 @@ #include "cafMemoryInspector.h" #include "cafProgressState.h" +#include #include #include #include @@ -115,7 +116,7 @@ namespace caf { { ProgressInfoStatic::start(maxProgressValue, title, delayShowingProgress); - if (qApp) + if (dynamic_cast(QCoreApplication::instance())) { QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); } @@ -128,7 +129,7 @@ namespace caf { { ProgressInfoStatic::finished(); - if (qApp) + if (dynamic_cast(QCoreApplication::instance())) { QApplication::restoreOverrideCursor(); } @@ -228,7 +229,7 @@ namespace caf { static QProgressDialog* progressDialog() { static QPointer progDialog; - if (progDialog.isNull()) + if (progDialog.isNull() && dynamic_cast(QCoreApplication::instance())) { progDialog = new QProgressDialog(nullptr, Qt::WindowTitleHint | Qt::WindowSystemMenuHint); @@ -467,19 +468,24 @@ namespace caf { std::vector& progressSpanStack_v = progressSpanStack(); std::vector& maxProgressStack_v = maxProgressStack(); + QProgressDialog* dialog = progressDialog(); + if (!maxProgressStack_v.size()) { //progressDialog()->setWindowModality(Qt::ApplicationModal); - progressDialog()->setMinimum(0); - progressDialog()->setWindowTitle(title); - progressDialog()->setCancelButton(nullptr); - if (delayShowingProgress) + if (dialog) { - progressDialog()->setMinimumDuration(1000); - } - else - { - progressDialog()->show(); + dialog->setMinimum(0); + dialog->setWindowTitle(title); + dialog->setCancelButton(nullptr); + if (delayShowingProgress) + { + dialog->setMinimumDuration(1000); + } + else + { + dialog->show(); + } } } @@ -489,10 +495,12 @@ namespace caf { titleStack().push_back(title); descriptionStack().push_back(""); - progressDialog()->setMaximum(static_cast(currentTotalMaxProgressValue())); - progressDialog()->setValue(static_cast(currentTotalProgress())); - progressDialog()->setLabelText(currentComposedLabel()); - + if (dialog) + { + dialog->setMaximum(static_cast(currentTotalMaxProgressValue())); + dialog->setValue(static_cast(currentTotalProgress())); + dialog->setLabelText(currentComposedLabel()); + } QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents); //if (progressDialog()) progressDialog()->repaint(); } @@ -506,7 +514,11 @@ namespace caf { descriptionStack().back() = description; - progressDialog()->setLabelText(currentComposedLabel()); + QProgressDialog* dialog = progressDialog(); + if (dialog) + { + dialog->setLabelText(currentComposedLabel()); + } QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents); //if (progressDialog()) progressDialog()->repaint(); @@ -546,8 +558,12 @@ namespace caf { totalProgress = totalMaxProgress; } - progressDialog()->setMaximum(totalMaxProgress); - progressDialog()->setValue(totalProgress); + QProgressDialog* dialog = progressDialog(); + if (dialog) + { + dialog->setMaximum(totalMaxProgress); + dialog->setValue(totalProgress); + } QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents); //if (progressDialog()) progressDialog()->repaint(); @@ -623,15 +639,19 @@ namespace caf { descriptionStack().pop_back(); // Update the text to reflect the "previous level" - progressDialog()->setLabelText(currentComposedLabel()); + QProgressDialog* dialog = progressDialog(); + if (dialog) + { + dialog->setLabelText(currentComposedLabel()); + } // If we are finishing the last level, clean up if (maxProgressStack_v.empty()) { - if (progressDialog() != nullptr) + if (dialog) { - progressDialog()->reset(); - progressDialog()->close(); + dialog->reset(); + dialog->close(); } } else @@ -649,11 +669,15 @@ namespace caf { { if (s_disabled) return false; - if (!qApp) return false; - - if (!progressDialog()) return false; - - return progressDialog()->thread() == QThread::currentThread(); + if (dynamic_cast(QCoreApplication::instance())) + { + QProgressDialog* dialog = progressDialog(); + if (dialog) + { + return dialog->thread() == QThread::currentThread(); + } + } + return false; } } // namespace caf diff --git a/Fwk/AppFwk/cafVizExtensions/cafFixedAtlasFont.h b/Fwk/AppFwk/cafVizExtensions/cafFixedAtlasFont.h index 2fbae0cabd..7cc7595a28 100644 --- a/Fwk/AppFwk/cafVizExtensions/cafFixedAtlasFont.h +++ b/Fwk/AppFwk/cafVizExtensions/cafFixedAtlasFont.h @@ -37,6 +37,7 @@ #pragma once +#include "cvfBase.h" #include "cvfObject.h" #include "cvfFont.h" #include "cvfGlyph.h" From 274dee70fa16f2513e2a29a88e6879d0c510a760 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Mon, 6 May 2019 10:40:05 +0200 Subject: [PATCH 010/396] Rename RiaApplication::handleEvents -> invokeProcessEvents --- ApplicationCode/Application/RiaApplication.cpp | 2 +- ApplicationCode/Application/RiaApplication.h | 2 +- ApplicationCode/Application/RiaConsoleApplication.cpp | 2 +- ApplicationCode/Application/RiaConsoleApplication.h | 2 +- ApplicationCode/Application/RiaGuiApplication.cpp | 4 ++-- ApplicationCode/Application/RiaGuiApplication.h | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/ApplicationCode/Application/RiaApplication.cpp b/ApplicationCode/Application/RiaApplication.cpp index 9c9e7b37b4..027e7d4a8e 100644 --- a/ApplicationCode/Application/RiaApplication.cpp +++ b/ApplicationCode/Application/RiaApplication.cpp @@ -1163,7 +1163,7 @@ void RiaApplication::waitUntilCommandObjectsHasBeenProcessed() while (!mutexLockedSuccessfully) { - handleEvents(); + invokeProcessEvents(); mutexLockedSuccessfully = m_commandQueueLock.tryLock(); } diff --git a/ApplicationCode/Application/RiaApplication.h b/ApplicationCode/Application/RiaApplication.h index 7b69dbe5f5..db3abccbcf 100644 --- a/ApplicationCode/Application/RiaApplication.h +++ b/ApplicationCode/Application/RiaApplication.h @@ -182,7 +182,7 @@ public: protected: // Protected implementation specific overrides - virtual void handleEvents(QEventLoop::ProcessEventsFlags flags = QEventLoop::AllEvents) = 0; + virtual void invokeProcessEvents(QEventLoop::ProcessEventsFlags flags = QEventLoop::AllEvents) = 0; virtual void onChangedActiveReservoirView() {} virtual void onFileSuccessfullyLoaded(const QString& fileName, RiaDefines::ImportFileType fileType) {} virtual void onProjectBeingOpened() {} diff --git a/ApplicationCode/Application/RiaConsoleApplication.cpp b/ApplicationCode/Application/RiaConsoleApplication.cpp index aa52cba81a..dc0d5c3038 100644 --- a/ApplicationCode/Application/RiaConsoleApplication.cpp +++ b/ApplicationCode/Application/RiaConsoleApplication.cpp @@ -335,7 +335,7 @@ void RiaConsoleApplication::showErrorMessage(const QString& errMsg) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RiaConsoleApplication::handleEvents(QEventLoop::ProcessEventsFlags flags /*= QEventLoop::AllEvents*/) +void RiaConsoleApplication::invokeProcessEvents(QEventLoop::ProcessEventsFlags flags /*= QEventLoop::AllEvents*/) { processEvents(flags); } diff --git a/ApplicationCode/Application/RiaConsoleApplication.h b/ApplicationCode/Application/RiaConsoleApplication.h index ab7cf5565f..006512a138 100644 --- a/ApplicationCode/Application/RiaConsoleApplication.h +++ b/ApplicationCode/Application/RiaConsoleApplication.h @@ -44,7 +44,7 @@ public: protected: // Protected implementation specific overrides - void handleEvents(QEventLoop::ProcessEventsFlags flags = QEventLoop::AllEvents) override; + void invokeProcessEvents(QEventLoop::ProcessEventsFlags flags = QEventLoop::AllEvents) override; void onProjectOpeningError(const QString& errMsg) override; void onProjectOpened(); void onProjectClosed(); diff --git a/ApplicationCode/Application/RiaGuiApplication.cpp b/ApplicationCode/Application/RiaGuiApplication.cpp index b69a1facb0..567d97dc4b 100644 --- a/ApplicationCode/Application/RiaGuiApplication.cpp +++ b/ApplicationCode/Application/RiaGuiApplication.cpp @@ -1230,7 +1230,7 @@ void RiaGuiApplication::showErrorMessage(const QString& errMsg) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RiaGuiApplication::handleEvents(QEventLoop::ProcessEventsFlags flags) +void RiaGuiApplication::invokeProcessEvents(QEventLoop::ProcessEventsFlags flags) { processEvents(flags); } @@ -1374,7 +1374,7 @@ void RiaGuiApplication::onProjectClosed() void RiaGuiApplication::cleanupBeforeProgramExit() { closeAllWindows(); - handleEvents(); + invokeProcessEvents(); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/Application/RiaGuiApplication.h b/ApplicationCode/Application/RiaGuiApplication.h index 5b1ae44b22..1824ac3183 100644 --- a/ApplicationCode/Application/RiaGuiApplication.h +++ b/ApplicationCode/Application/RiaGuiApplication.h @@ -135,7 +135,7 @@ public: void cleanupBeforeProgramExit() override; protected: // Protected RiaApplication overrides - void handleEvents(QEventLoop::ProcessEventsFlags flags = QEventLoop::AllEvents) override; + void invokeProcessEvents(QEventLoop::ProcessEventsFlags flags = QEventLoop::AllEvents) override; void onChangedActiveReservoirView() override; void onFileSuccessfullyLoaded(const QString& fileName, RiaDefines::ImportFileType fileType) override; void onProjectBeingOpened() override; From 30769d7f2a96f557803fc4c9551f5a9fff31de93 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Mon, 6 May 2019 11:08:59 +0200 Subject: [PATCH 011/396] Rename caf::PdmUiItem::setUiIcon(QString) to setUiIconFromResourceString --- .../Annotations/RimAnnotationCollection.cpp | 6 +++--- .../Annotations/RimAnnotationCollectionBase.cpp | 2 +- .../Annotations/RimAnnotationInViewCollection.cpp | 8 ++++---- .../ProjectDataModel/Completions/RimValveTemplate.cpp | 6 +++--- .../ProjectDataModel/Completions/RimWellPathValve.cpp | 6 +++--- .../ProjectDataModel/Flow/RimWellAllocationPlot.cpp | 2 +- ApplicationCode/ProjectDataModel/RimGridCollection.cpp | 10 +++++----- .../ProjectDataModel/RimIdenticalGridCaseGroup.cpp | 4 ++-- .../ProjectDataModel/RimIntersectionBox.cpp | 8 ++++---- .../ProjectDataModel/RimPlotAxisProperties.cpp | 4 ++-- ApplicationCode/ProjectDataModel/RimProject.cpp | 2 +- .../Summary/RimSummaryCaseCollection.cpp | 4 ++-- .../cafProjectDataModel/cafPdmUiCore/cafPdmUiItem.cpp | 2 +- .../cafProjectDataModel/cafPdmUiCore/cafPdmUiItem.h | 2 +- 14 files changed, 33 insertions(+), 33 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/Annotations/RimAnnotationCollection.cpp b/ApplicationCode/ProjectDataModel/Annotations/RimAnnotationCollection.cpp index 157c094638..27e9111fbc 100644 --- a/ApplicationCode/ProjectDataModel/Annotations/RimAnnotationCollection.cpp +++ b/ApplicationCode/ProjectDataModel/Annotations/RimAnnotationCollection.cpp @@ -62,9 +62,9 @@ RimAnnotationCollection::RimAnnotationCollection() m_userDefinedPolylineAnnotations->uiCapability()->setUiName(RimAnnotationGroupCollection::USED_DEFINED_POLYLINE_ANNOTATION_UI_NAME); m_polylineFromFileAnnotations->uiCapability()->setUiName(RimAnnotationGroupCollection::POLYLINE_FROM_FILE_ANNOTATION_UI_NAME); - m_reachCircleAnnotations->uiCapability()->setUiIcon(":/ReachCircle16x16.png"); - m_userDefinedPolylineAnnotations->uiCapability()->setUiIcon(":/PolylinesFromFile16x16.png"); - m_polylineFromFileAnnotations->uiCapability()->setUiIcon(":/PolylinesFromFile16x16.png"); + m_reachCircleAnnotations->uiCapability()->setUiIconFromResourceString(":/ReachCircle16x16.png"); + m_userDefinedPolylineAnnotations->uiCapability()->setUiIconFromResourceString(":/PolylinesFromFile16x16.png"); + m_polylineFromFileAnnotations->uiCapability()->setUiIconFromResourceString(":/PolylinesFromFile16x16.png"); } diff --git a/ApplicationCode/ProjectDataModel/Annotations/RimAnnotationCollectionBase.cpp b/ApplicationCode/ProjectDataModel/Annotations/RimAnnotationCollectionBase.cpp index 427c15b55c..ba68fba38a 100644 --- a/ApplicationCode/ProjectDataModel/Annotations/RimAnnotationCollectionBase.cpp +++ b/ApplicationCode/ProjectDataModel/Annotations/RimAnnotationCollectionBase.cpp @@ -51,7 +51,7 @@ RimAnnotationCollectionBase::RimAnnotationCollectionBase() m_textAnnotations.uiCapability()->setUiHidden(true); m_textAnnotations = new RimAnnotationGroupCollection(); m_textAnnotations->uiCapability()->setUiName(RimAnnotationGroupCollection::TEXT_ANNOTATION_UI_NAME); - m_textAnnotations->uiCapability()->setUiIcon(":/TextAnnotation16x16.png"); + m_textAnnotations->uiCapability()->setUiIconFromResourceString(":/TextAnnotation16x16.png"); } diff --git a/ApplicationCode/ProjectDataModel/Annotations/RimAnnotationInViewCollection.cpp b/ApplicationCode/ProjectDataModel/Annotations/RimAnnotationInViewCollection.cpp index c121b77cb9..fe3e7d6f82 100644 --- a/ApplicationCode/ProjectDataModel/Annotations/RimAnnotationInViewCollection.cpp +++ b/ApplicationCode/ProjectDataModel/Annotations/RimAnnotationInViewCollection.cpp @@ -105,10 +105,10 @@ RimAnnotationInViewCollection::RimAnnotationInViewCollection() m_globalUserDefinedPolylineAnnotations->uiCapability()->setUiName("Global User Defined Polylines Annotations"); m_globalPolylineFromFileAnnotations->uiCapability()->setUiName("Global Polylines From File Annotations"); - m_globalTextAnnotations->uiCapability()->setUiIcon(":/TextAnnotation16x16.png"); - m_globalReachCircleAnnotations->uiCapability()->setUiIcon(":/ReachCircle16x16.png"); - m_globalUserDefinedPolylineAnnotations->uiCapability()->setUiIcon(":/PolylinesFromFile16x16.png"); - m_globalPolylineFromFileAnnotations->uiCapability()->setUiIcon(":/PolylinesFromFile16x16.png"); + m_globalTextAnnotations->uiCapability()->setUiIconFromResourceString(":/TextAnnotation16x16.png"); + m_globalReachCircleAnnotations->uiCapability()->setUiIconFromResourceString(":/ReachCircle16x16.png"); + m_globalUserDefinedPolylineAnnotations->uiCapability()->setUiIconFromResourceString(":/PolylinesFromFile16x16.png"); + m_globalPolylineFromFileAnnotations->uiCapability()->setUiIconFromResourceString(":/PolylinesFromFile16x16.png"); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/Completions/RimValveTemplate.cpp b/ApplicationCode/ProjectDataModel/Completions/RimValveTemplate.cpp index 7b9eafb093..0e32e32b78 100644 --- a/ApplicationCode/ProjectDataModel/Completions/RimValveTemplate.cpp +++ b/ApplicationCode/ProjectDataModel/Completions/RimValveTemplate.cpp @@ -256,15 +256,15 @@ void RimValveTemplate::defineUiTreeOrdering(caf::PdmUiTreeOrdering& uiTreeOrderi this->setName(fullLabel()); if (m_type() == RiaDefines::ICV) { - this->setUiIcon(":/ICVValve16x16.png"); + this->setUiIconFromResourceString(":/ICVValve16x16.png"); } else if (m_type() == RiaDefines::ICD) { - this->setUiIcon(":/ICDValve16x16.png"); + this->setUiIconFromResourceString(":/ICDValve16x16.png"); } else if (m_type() == RiaDefines::AICD) { - this->setUiIcon(":/AICDValve16x16.png"); + this->setUiIconFromResourceString(":/AICDValve16x16.png"); } } diff --git a/ApplicationCode/ProjectDataModel/Completions/RimWellPathValve.cpp b/ApplicationCode/ProjectDataModel/Completions/RimWellPathValve.cpp index 38362dda41..9d5464c303 100644 --- a/ApplicationCode/ProjectDataModel/Completions/RimWellPathValve.cpp +++ b/ApplicationCode/ProjectDataModel/Completions/RimWellPathValve.cpp @@ -184,13 +184,13 @@ void RimWellPathValve::applyValveLabelAndIcon() { if (componentType() == RiaDefines::ICV) { - this->setUiIcon(":/ICVValve16x16.png"); + this->setUiIconFromResourceString(":/ICVValve16x16.png"); QString fullName = QString("%1: %2").arg(componentLabel()).arg(m_measuredDepth()); this->setName(fullName); } else if (componentType() == RiaDefines::ICD) { - this->setUiIcon(":/ICDValve16x16.png"); + this->setUiIconFromResourceString(":/ICDValve16x16.png"); QString fullName = QString("%1 %2: %3 - %4") .arg(m_multipleValveLocations->valveLocations().size()) .arg(componentLabel()) @@ -200,7 +200,7 @@ void RimWellPathValve::applyValveLabelAndIcon() } else if (componentType() == RiaDefines::AICD) { - this->setUiIcon(":/AICDValve16x16.png"); + this->setUiIconFromResourceString(":/AICDValve16x16.png"); QString fullName = QString("%1 %2: %3 - %4") .arg(m_multipleValveLocations->valveLocations().size()) .arg(componentLabel()) diff --git a/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.cpp b/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.cpp index 9adf531010..66bbe90973 100644 --- a/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.cpp +++ b/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.cpp @@ -98,7 +98,7 @@ RimWellAllocationPlot::RimWellAllocationPlot() m_accumulatedWellFlowPlot->setDepthUnit(RiaDefines::UNIT_NONE); m_accumulatedWellFlowPlot->setDepthType(RimWellLogPlot::CONNECTION_NUMBER); m_accumulatedWellFlowPlot->setTrackLegendsVisible(false); - m_accumulatedWellFlowPlot->uiCapability()->setUiIcon(":/WellFlowPlot16x16.png"); + m_accumulatedWellFlowPlot->uiCapability()->setUiIconFromResourceString(":/WellFlowPlot16x16.png"); CAF_PDM_InitFieldNoDefault(&m_totalWellAllocationPlot, "TotalWellFlowPlot", "Total Well Flow", "", "", ""); m_totalWellAllocationPlot.uiCapability()->setUiHidden(true); diff --git a/ApplicationCode/ProjectDataModel/RimGridCollection.cpp b/ApplicationCode/ProjectDataModel/RimGridCollection.cpp index c0ddf91a37..2817f24b0e 100644 --- a/ApplicationCode/ProjectDataModel/RimGridCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimGridCollection.cpp @@ -260,18 +260,18 @@ RimGridCollection::RimGridCollection() m_mainGrid = new RimGridInfo(); m_mainGrid->setUiName("Main Grid"); m_mainGrid->uiCapability()->setUiTreeHidden(true); - m_mainGrid->setUiIcon(":/MainGrid16x16.png"); + m_mainGrid->setUiIconFromResourceString(":/MainGrid16x16.png"); CAF_PDM_InitFieldNoDefault(&m_persistentLgrs, "PersistentLgrs", "Persistent LGRs", "", "", ""); m_persistentLgrs = new RimGridInfoCollection(); m_persistentLgrs->setUiName(persistentGridUiName()); - m_persistentLgrs->setUiIcon(":/LGR16x16.png"); + m_persistentLgrs->setUiIconFromResourceString(":/LGR16x16.png"); CAF_PDM_InitFieldNoDefault(&m_temporaryLgrs, "TemporaryLgrs", "Temporary LGRs", "", "", ""); m_temporaryLgrs.xmlCapability()->disableIO(); m_temporaryLgrs = new RimGridInfoCollection(); m_temporaryLgrs->setUiName(temporaryGridUiName()); - m_temporaryLgrs->setUiIcon(":/TempLGR16x16.png"); + m_temporaryLgrs->setUiIconFromResourceString(":/TempLGR16x16.png"); } //-------------------------------------------------------------------------------------------------- @@ -390,7 +390,7 @@ void RimGridCollection::syncFromMainEclipseGrid() auto gridInfo = new RimGridInfo(); gridInfo->setName(gridName); gridInfo->setEclipseGridIndex((int)gridIndex); - gridInfo->setUiIcon(":/TempLGR16x16.png"); + gridInfo->setUiIconFromResourceString(":/TempLGR16x16.png"); m_temporaryLgrs->addGridInfo(gridInfo); } } @@ -405,7 +405,7 @@ void RimGridCollection::syncFromMainEclipseGrid() auto gridInfo = new RimGridInfo(); gridInfo->setName(gridName); gridInfo->setEclipseGridIndex((int)gridIndex); - gridInfo->setUiIcon(":/LGR16x16.png"); + gridInfo->setUiIconFromResourceString(":/LGR16x16.png"); m_persistentLgrs->addGridInfo(gridInfo); } } diff --git a/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp b/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp index 304c011c0c..64adc6a1ca 100644 --- a/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp +++ b/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp @@ -64,11 +64,11 @@ RimIdenticalGridCaseGroup::RimIdenticalGridCaseGroup() caseCollection = new RimCaseCollection; caseCollection->uiCapability()->setUiName("Source Cases"); - caseCollection->uiCapability()->setUiIcon(":/Cases16x16.png"); + caseCollection->uiCapability()->setUiIconFromResourceString(":/Cases16x16.png"); statisticsCaseCollection = new RimCaseCollection; statisticsCaseCollection->uiCapability()->setUiName("Derived Statistics"); - statisticsCaseCollection->uiCapability()->setUiIcon(":/Histograms16x16.png"); + statisticsCaseCollection->uiCapability()->setUiIconFromResourceString(":/Histograms16x16.png"); m_mainGrid = nullptr; diff --git a/ApplicationCode/ProjectDataModel/RimIntersectionBox.cpp b/ApplicationCode/ProjectDataModel/RimIntersectionBox.cpp index 0154fda7ac..eba6656943 100644 --- a/ApplicationCode/ProjectDataModel/RimIntersectionBox.cpp +++ b/ApplicationCode/ProjectDataModel/RimIntersectionBox.cpp @@ -543,21 +543,21 @@ void RimIntersectionBox::updateVisibility() if (m_singlePlaneState == PLANE_STATE_X) { m_maxXCoord.uiCapability()->setUiReadOnly(true); - this->setUiIcon(QString(":/IntersectionXPlane16x16.png")); + this->setUiIconFromResourceString(QString(":/IntersectionXPlane16x16.png")); } else if (m_singlePlaneState == PLANE_STATE_Y) { m_maxYCoord.uiCapability()->setUiReadOnly(true); - this->setUiIcon(QString(":/IntersectionYPlane16x16.png")); + this->setUiIconFromResourceString(QString(":/IntersectionYPlane16x16.png")); } else if (m_singlePlaneState == PLANE_STATE_Z) { m_maxDepth.uiCapability()->setUiReadOnly(true); - this->setUiIcon(QString(":/IntersectionZPlane16x16.png")); + this->setUiIconFromResourceString(QString(":/IntersectionZPlane16x16.png")); } else { - this->setUiIcon(QString(":/IntersectionBox16x16.png")); + this->setUiIconFromResourceString(QString(":/IntersectionBox16x16.png")); } } diff --git a/ApplicationCode/ProjectDataModel/RimPlotAxisProperties.cpp b/ApplicationCode/ProjectDataModel/RimPlotAxisProperties.cpp index 8af080fb59..bacf9956da 100644 --- a/ApplicationCode/ProjectDataModel/RimPlotAxisProperties.cpp +++ b/ApplicationCode/ProjectDataModel/RimPlotAxisProperties.cpp @@ -218,8 +218,8 @@ void RimPlotAxisProperties::setNameAndAxis(const QString& name, QwtPlot::Axis ax m_name = name; m_axis = axis; - if (axis == QwtPlot::yRight) this->setUiIcon(":/RightAxis16x16.png"); - if (axis == QwtPlot::xBottom) this->setUiIcon(":/BottomAxis16x16.png"); + if (axis == QwtPlot::yRight) this->setUiIconFromResourceString(":/RightAxis16x16.png"); + if (axis == QwtPlot::xBottom) this->setUiIconFromResourceString(":/BottomAxis16x16.png"); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimProject.cpp b/ApplicationCode/ProjectDataModel/RimProject.cpp index 7319f60e6e..1696eb0d56 100644 --- a/ApplicationCode/ProjectDataModel/RimProject.cpp +++ b/ApplicationCode/ProjectDataModel/RimProject.cpp @@ -174,7 +174,7 @@ RimProject::RimProject(void) scriptCollection = new RimScriptCollection(); scriptCollection->directory.uiCapability()->setUiHidden(true); scriptCollection->uiCapability()->setUiName("Scripts"); - scriptCollection->uiCapability()->setUiIcon(":/octave.png"); + scriptCollection->uiCapability()->setUiIconFromResourceString(":/octave.png"); mainPlotCollection = new RimMainPlotCollection(); diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCaseCollection.cpp b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCaseCollection.cpp index 61f6f1c795..8ece76742b 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCaseCollection.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCaseCollection.cpp @@ -576,8 +576,8 @@ QString RimSummaryCaseCollection::nameAndItemCount() const //-------------------------------------------------------------------------------------------------- void RimSummaryCaseCollection::updateIcon() { - if (m_isEnsemble) setUiIcon(":/SummaryEnsemble16x16.png"); - else setUiIcon(":/SummaryGroup16x16.png"); + if (m_isEnsemble) setUiIconFromResourceString(":/SummaryEnsemble16x16.png"); + else setUiIconFromResourceString(":/SummaryGroup16x16.png"); } //-------------------------------------------------------------------------------------------------- diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiItem.cpp b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiItem.cpp index 4d17f8a3f2..6dad8102a2 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiItem.cpp +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiItem.cpp @@ -279,7 +279,7 @@ void PdmUiItem::setUiIcon(const QIconProvider& uiIconProvider, const QString& ui //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void PdmUiItem::setUiIcon(const QString& uiIconResourceName, const QString& uiConfigName /*= ""*/) +void PdmUiItem::setUiIconFromResourceString(const QString& uiIconResourceName, const QString& uiConfigName /*= ""*/) { setUiIcon(caf::QIconProvider(uiIconResourceName), uiConfigName); } diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiItem.h b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiItem.h index 954f61b0ca..7d7cde26e7 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiItem.h +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiItem.h @@ -227,7 +227,7 @@ public: const QIcon uiIcon(const QString& uiConfigName = "") const; const QIconProvider uiIconProvider(const QString& uiConfigName = "") const; void setUiIcon(const QIconProvider& uiIcon, const QString& uiConfigName = ""); - void setUiIcon(const QString& uiIconResourceName, const QString& uiConfigName = ""); + void setUiIconFromResourceString(const QString& uiIconResourceName, const QString& uiConfigName = ""); const QColor uiContentTextColor(const QString& uiConfigName = "") const; void setUiContentTextColor(const QColor& uiIcon, const QString& uiConfigName = ""); From fe0624e3047893adc83e5ec9b76ae89d5d5dd54a Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Mon, 6 May 2019 11:48:23 +0200 Subject: [PATCH 012/396] Fix build problems in cafTestApp following headless changes --- Fwk/AppFwk/cafTests/cafTestApplication/MainWindow.cpp | 4 ++-- Fwk/AppFwk/cafTests/cafTestApplication/ManyGroups.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Fwk/AppFwk/cafTests/cafTestApplication/MainWindow.cpp b/Fwk/AppFwk/cafTests/cafTestApplication/MainWindow.cpp index fb06147860..4da3ac2b31 100644 --- a/Fwk/AppFwk/cafTests/cafTestApplication/MainWindow.cpp +++ b/Fwk/AppFwk/cafTests/cafTestApplication/MainWindow.cpp @@ -148,7 +148,7 @@ public: options.push_back(caf::PdmOptionItemInfo(text, text)); text = "Second"; - options.push_back(caf::PdmOptionItemInfo::createHeader(text, false, QIcon(QString(":/images/win/textbold.png")))); + options.push_back(caf::PdmOptionItemInfo::createHeader(text, false, caf::QIconProvider(":/images/win/textbold.png"))); { text = "Second_a"; @@ -159,7 +159,7 @@ public: { text = "Second_b"; - caf::PdmOptionItemInfo itemInfo = caf::PdmOptionItemInfo(text, text, false, QIcon(QString(":/images/win/filenew.png"))); + caf::PdmOptionItemInfo itemInfo = caf::PdmOptionItemInfo(text, text, false, caf::QIconProvider(":/images/win/filenew.png")); itemInfo.setLevel(1); options.push_back(itemInfo); } diff --git a/Fwk/AppFwk/cafTests/cafTestApplication/ManyGroups.cpp b/Fwk/AppFwk/cafTests/cafTestApplication/ManyGroups.cpp index f7562e900b..ee6551e565 100644 --- a/Fwk/AppFwk/cafTests/cafTestApplication/ManyGroups.cpp +++ b/Fwk/AppFwk/cafTests/cafTestApplication/ManyGroups.cpp @@ -135,7 +135,7 @@ QList ManyGroups::calculateValueOptions(const caf::PdmFi options.push_back(caf::PdmOptionItemInfo(text, text)); text = "Second"; - options.push_back(caf::PdmOptionItemInfo::createHeader(text, false, QIcon(QString(":/images/win/textbold.png")))); + options.push_back(caf::PdmOptionItemInfo::createHeader(text, false, caf::QIconProvider(":/images/win/textbold.png"))); { text = "Second_a"; @@ -147,7 +147,7 @@ QList ManyGroups::calculateValueOptions(const caf::PdmFi { text = "Second_b"; caf::PdmOptionItemInfo itemInfo = - caf::PdmOptionItemInfo(text, text, false, QIcon(QString(":/images/win/filenew.png"))); + caf::PdmOptionItemInfo(text, text, false, caf::QIconProvider(":/images/win/filenew.png")); itemInfo.setLevel(1); options.push_back(itemInfo); } From 088b5513a7cdf397f7d0f0dc3b8381aa3d40b1aa Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 3 May 2019 11:11:39 +0200 Subject: [PATCH 013/396] #4388 AppFwk : Remove problematic setUiField() calls setUiField() call used to keep track of which fields that is retained when updating an editor. Replace this workflow with a set of the ones that are used, and use this set to clean up unused editors afterwards. --- .../cafPdmUiFieldEditorHelper.cpp | 2 +- .../cafPdmUiFieldEditorHelper.h | 2 +- .../cafPdmUiFormLayoutObjectEditor.cpp | 32 +++++++++---------- .../cafPdmUiFormLayoutObjectEditor.h | 1 + .../cafPdmUiTableViewQModel.cpp | 20 +++++------- .../cafPdmUiToolBarEditor.cpp | 4 +-- 6 files changed, 29 insertions(+), 32 deletions(-) diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiFieldEditorHelper.cpp b/Fwk/AppFwk/cafUserInterface/cafPdmUiFieldEditorHelper.cpp index 174afc9c6d..935051ad6b 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiFieldEditorHelper.cpp +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiFieldEditorHelper.cpp @@ -47,7 +47,7 @@ //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -caf::PdmUiFieldEditorHandle* caf::PdmUiFieldEditorHelper::fieldEditorForField(caf::PdmUiFieldHandle* field, const QString& uiConfigName) +caf::PdmUiFieldEditorHandle* caf::PdmUiFieldEditorHelper::createFieldEditorForField(caf::PdmUiFieldHandle* field, const QString& uiConfigName) { caf::PdmUiFieldEditorHandle* fieldEditor = nullptr; diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiFieldEditorHelper.h b/Fwk/AppFwk/cafUserInterface/cafPdmUiFieldEditorHelper.h index a0d01bd451..1e78a04722 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiFieldEditorHelper.h +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiFieldEditorHelper.h @@ -50,7 +50,7 @@ namespace caf class PdmUiFieldEditorHelper { public: - static PdmUiFieldEditorHandle* fieldEditorForField(PdmUiFieldHandle* fieldHandle, const QString& uiConfigName); + static PdmUiFieldEditorHandle* createFieldEditorForField(PdmUiFieldHandle* fieldHandle, const QString& uiConfigName); }; diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiFormLayoutObjectEditor.cpp b/Fwk/AppFwk/cafUserInterface/cafPdmUiFormLayoutObjectEditor.cpp index 232a09c136..1a91c54e0d 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiFormLayoutObjectEditor.cpp +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiFormLayoutObjectEditor.cpp @@ -176,16 +176,18 @@ int caf::PdmUiFormLayoutObjectEditor::recursivelyConfigureAndUpdateUiOrderingInG } else { - // Also assign required item space that isn't taken up by field and label - spareColumnsToAssign += minimumItemColumnSpan - (minimumLabelColumnSpan + minimumFieldColumnSpan); - + PdmUiFieldEditorHandle* fieldEditor = nullptr; PdmUiFieldHandle* field = dynamic_cast(currentItem); - PdmUiFieldEditorHandle* fieldEditor = findOrCreateFieldEditor(containerWidgetWithGridLayout, field, uiConfigName); + if (field) fieldEditor = findOrCreateFieldEditor(containerWidgetWithGridLayout, field, uiConfigName); if (fieldEditor) { - fieldEditor->setUiField(field); + // Mark this field as used in the editor + m_usedFields.insert(field->fieldHandle()); + + // Also assign required item space that isn't taken up by field and label + spareColumnsToAssign += minimumItemColumnSpan - (minimumLabelColumnSpan + minimumFieldColumnSpan); // Place the widget(s) into the correct parent and layout QWidget* fieldCombinedWidget = fieldEditor->combinedWidget(); @@ -390,11 +392,12 @@ caf::PdmUiFieldEditorHandle* caf::PdmUiFormLayoutObjectEditor::findOrCreateField if (it == m_fieldViews.end()) { - fieldEditor = PdmUiFieldEditorHelper::fieldEditorForField(field, uiConfigName); + fieldEditor = PdmUiFieldEditorHelper::createFieldEditorForField(field, uiConfigName); if (fieldEditor) { m_fieldViews[field->fieldHandle()] = fieldEditor; + fieldEditor->setUiField(field); fieldEditor->createWidgets(parent); } else @@ -497,11 +500,8 @@ void caf::PdmUiFormLayoutObjectEditor::configureAndUpdateUi(const QString& uiCon } // Set all fieldViews to be unvisited - std::map::iterator it; - for (it = m_fieldViews.begin(); it != m_fieldViews.end(); ++it) - { - it->second->setUiField(nullptr); - } + + m_usedFields.clear(); // Set all group Boxes to be unvisited m_newGroupBoxes.clear(); @@ -511,13 +511,13 @@ void caf::PdmUiFormLayoutObjectEditor::configureAndUpdateUi(const QString& uiCon // Remove all fieldViews not mentioned by the configuration from the layout std::vector fvhToRemoveFromMap; - for (it = m_fieldViews.begin(); it != m_fieldViews.end(); ++it) + for (auto oldFvIt = m_fieldViews.begin(); oldFvIt != m_fieldViews.end(); ++oldFvIt) { - if (it->second->uiField() == nullptr) + if (m_usedFields.count(oldFvIt->first) == 0) { - PdmUiFieldEditorHandle* fvh = it->second; - delete fvh; - fvhToRemoveFromMap.push_back(it->first); + // The old field editor is not present anymore, get rid of it + delete oldFvIt->second; + fvhToRemoveFromMap.push_back(oldFvIt->first); } } diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiFormLayoutObjectEditor.h b/Fwk/AppFwk/cafUserInterface/cafPdmUiFormLayoutObjectEditor.h index 586c094059..077a13556a 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiFormLayoutObjectEditor.h +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiFormLayoutObjectEditor.h @@ -110,6 +110,7 @@ private: private: std::map m_fieldViews; + std::set m_usedFields; ///< used temporarily to store the new(complete) set of used fields std::map > m_groupBoxes; std::map > m_newGroupBoxes; ///< used temporarily to store the new(complete) set of group boxes std::map > m_objectKeywordGroupUiNameExpandedState; diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiTableViewQModel.cpp b/Fwk/AppFwk/cafUserInterface/cafPdmUiTableViewQModel.cpp index a6162756c9..7362b06e6d 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiTableViewQModel.cpp +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiTableViewQModel.cpp @@ -396,12 +396,8 @@ void PdmUiTableViewQModel::setArrayFieldAndBuildEditors(PdmChildArrayFieldHandle const std::vector& uiItems = configForFirstObject.uiItems(); - // Set all fieldViews to be unvisited - std::map::iterator it; - for (it = m_fieldEditors.begin(); it != m_fieldEditors.end(); ++it) - { - it->second->setUiField(nullptr); - } + + std::set usedFieldKeywords; m_modelColumnIndexToFieldIndex.clear(); @@ -416,14 +412,15 @@ void PdmUiTableViewQModel::setArrayFieldAndBuildEditors(PdmChildArrayFieldHandle PdmUiFieldEditorHandle* fieldEditor = nullptr; // Find or create FieldEditor - it = m_fieldEditors.find(field->fieldHandle()->keyword()); + auto it = m_fieldEditors.find(field->fieldHandle()->keyword()); if (it == m_fieldEditors.end()) { - fieldEditor = PdmUiFieldEditorHelper::fieldEditorForField(field, configName); + fieldEditor = PdmUiFieldEditorHelper::createFieldEditorForField(field, configName); if (fieldEditor) { + fieldEditor->setUiField(field); m_fieldEditors[field->fieldHandle()->keyword()] = fieldEditor; } } @@ -434,7 +431,7 @@ void PdmUiTableViewQModel::setArrayFieldAndBuildEditors(PdmChildArrayFieldHandle if (fieldEditor) { - fieldEditor->setUiField(field); + usedFieldKeywords.insert(field->fieldHandle()->keyword()); //TODO: Create/update is not required at this point, as UI is recreated in getEditorWidgetAndTransferOwnership() // Can be moved, but a move will require changes in PdmUiFieldEditorHandle @@ -447,13 +444,12 @@ void PdmUiTableViewQModel::setArrayFieldAndBuildEditors(PdmChildArrayFieldHandle } } - // Remove all fieldViews not mentioned by the configuration from the layout std::vector< QString > fvhToRemoveFromMap; - for (it = m_fieldEditors.begin(); it != m_fieldEditors.end(); ++it) + for (auto it = m_fieldEditors.begin(); it != m_fieldEditors.end(); ++it) { - if (it->second->uiField() == nullptr) + if (usedFieldKeywords.count(it->first) == 0) { PdmUiFieldEditorHandle* fvh = it->second; delete fvh; diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiToolBarEditor.cpp b/Fwk/AppFwk/cafUserInterface/cafPdmUiToolBarEditor.cpp index 4967f6aeb3..5577cde98f 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiToolBarEditor.cpp +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiToolBarEditor.cpp @@ -147,7 +147,7 @@ void PdmUiToolBarEditor::configureAndUpdateUi(const QString& uiConfigName) } else { - fieldEditor = caf::PdmUiFieldEditorHelper::fieldEditorForField(field->uiCapability(), uiConfigName); + fieldEditor = caf::PdmUiFieldEditorHelper::createFieldEditorForField(field->uiCapability(), uiConfigName); addSpace = true; } @@ -156,6 +156,7 @@ void PdmUiToolBarEditor::configureAndUpdateUi(const QString& uiConfigName) if (fieldEditor) { m_fieldViews[field->keyword()] = fieldEditor; + fieldEditor->setUiField(uiFieldHandle); fieldEditor->createWidgets(nullptr); m_actions.push_back(m_toolbar->addWidget(fieldEditor->editorWidget())); @@ -166,7 +167,6 @@ void PdmUiToolBarEditor::configureAndUpdateUi(const QString& uiConfigName) m_toolbar->addWidget(widget); } - fieldEditor->setUiField(uiFieldHandle); fieldEditor->updateUi(uiConfigName); } } From f1d4de2090e79385b94f0d6e3e48859c1718a89a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Fri, 29 Mar 2019 14:30:05 +0100 Subject: [PATCH 014/396] Remove calls to setUiField that are unneccessary because of changes in AppFwk --- .../SummaryPlotCommands/RicSummaryCurveCreatorSplitterUi.cpp | 2 -- .../UserInterface/RiuSummaryCurveDefSelectionEditor.cpp | 2 -- 2 files changed, 4 deletions(-) diff --git a/ApplicationCode/Commands/SummaryPlotCommands/RicSummaryCurveCreatorSplitterUi.cpp b/ApplicationCode/Commands/SummaryPlotCommands/RicSummaryCurveCreatorSplitterUi.cpp index c16f6d062f..4d5383fe32 100644 --- a/ApplicationCode/Commands/SummaryPlotCommands/RicSummaryCurveCreatorSplitterUi.cpp +++ b/ApplicationCode/Commands/SummaryPlotCommands/RicSummaryCurveCreatorSplitterUi.cpp @@ -246,8 +246,6 @@ void RicSummaryCurveCreatorSplitterUi::configureAndUpdateFields(int widgetStartI if (fieldEditor) { - fieldEditor->setUiField(field); - // Place the widget(s) into the correct parent and layout QWidget* fieldCombinedWidget = fieldEditor->combinedWidget(); diff --git a/ApplicationCode/UserInterface/RiuSummaryCurveDefSelectionEditor.cpp b/ApplicationCode/UserInterface/RiuSummaryCurveDefSelectionEditor.cpp index cfb815d9b1..29a2186e8d 100644 --- a/ApplicationCode/UserInterface/RiuSummaryCurveDefSelectionEditor.cpp +++ b/ApplicationCode/UserInterface/RiuSummaryCurveDefSelectionEditor.cpp @@ -160,8 +160,6 @@ void RiuSummaryCurveDefSelectionEditor::configureAndUpdateFields(int widgetStart if (fieldEditor) { - fieldEditor->setUiField(field); - // Place the widget(s) into the correct parent and layout QWidget* fieldCombinedWidget = fieldEditor->combinedWidget(); From 01ac756314586f8925ca6a4b7dd0deca1ca816cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Fri, 29 Mar 2019 14:46:31 +0100 Subject: [PATCH 015/396] AppFwk: Added a parent editor concept, and adjusted the update regime to make embedded editors trigger update of the containing editor. Removed the update of the fields owner object, which causes trouble for table editors and some derived object editors. --- .../cafPdmUiCore/cafPdmUiEditorHandle.cpp | 15 +++++++++++++++ .../cafPdmUiCore/cafPdmUiEditorHandle.h | 7 +++++++ .../cafPdmUiCore/cafPdmUiFieldHandle.cpp | 2 +- .../cafPdmUiCore/cafPdmUiItem.cpp | 4 +++- 4 files changed, 26 insertions(+), 2 deletions(-) diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiEditorHandle.cpp b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiEditorHandle.cpp index 7c23842082..729e3113df 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiEditorHandle.cpp +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiEditorHandle.cpp @@ -85,6 +85,21 @@ void PdmUiEditorHandle::updateUi() emit uiUpdated(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void PdmUiEditorHandle::updateUiIncludingParent() +{ + if (m_parentEditor) + { + m_parentEditor->updateUiIncludingParent(); + } + else + { + this->updateUi(); + } +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiEditorHandle.h b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiEditorHandle.h index 2cbd04aa0a..c0252c9d91 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiEditorHandle.h +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiEditorHandle.h @@ -40,6 +40,7 @@ #include "cafPdmUiItem.h" #include +#include namespace caf { @@ -61,6 +62,8 @@ public: void updateUi(const QString& uiConfigName);; void updateUi(); + void updateUiIncludingParent(); + signals: void uiUpdated(); @@ -76,12 +79,16 @@ protected: void bindToPdmItem(PdmUiItem* item); PdmUiItem* pdmItem() { return m_pdmItem; } const PdmUiItem* pdmItem() const { return m_pdmItem; } +public: // PDM Internal + void setParentEditor(PdmUiEditorHandle* parentEditor) { m_parentEditor = parentEditor; } private: friend PdmUiItem::~PdmUiItem(); PdmUiItem* m_pdmItem; QString m_currentConfigName; + QPointer m_parentEditor; // Editor containing this editor. Will be asked to updateUi (instead of this) if it exists + bool m_isConfiguringUi; }; diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiFieldHandle.cpp b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiFieldHandle.cpp index ba6f09c866..378af2aefa 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiFieldHandle.cpp +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiFieldHandle.cpp @@ -81,7 +81,7 @@ void PdmUiFieldHandle::notifyFieldChanged(const QVariant& oldFieldValue, const Q } } - // Update field editors + // Update connected field editors or their parent editors, to make the ui reflect the change this->updateConnectedEditors(); PdmUiModelChangeDetector::instance()->setModelChanged(); diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiItem.cpp b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiItem.cpp index 6dad8102a2..27e3e76ab1 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiItem.cpp +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiItem.cpp @@ -613,7 +613,9 @@ void PdmUiItem::updateConnectedEditors() const std::set::iterator it; for (it = m_editors.begin(); it != m_editors.end(); ++it) { - (*it)->updateUi(); + (*it)->updateUiIncludingParent(); + //(*it)->updateUi(); + } } From 9e7467309d919f0ba151cb2e621dba1ce1619c42 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 3 May 2019 15:35:19 +0200 Subject: [PATCH 016/396] #4388 AppFwk : Set parent editor when field editor is created --- Fwk/AppFwk/cafUserInterface/cafPdmUiFormLayoutObjectEditor.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiFormLayoutObjectEditor.cpp b/Fwk/AppFwk/cafUserInterface/cafPdmUiFormLayoutObjectEditor.cpp index 1a91c54e0d..6d12638b09 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiFormLayoutObjectEditor.cpp +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiFormLayoutObjectEditor.cpp @@ -397,6 +397,7 @@ caf::PdmUiFieldEditorHandle* caf::PdmUiFormLayoutObjectEditor::findOrCreateField if (fieldEditor) { m_fieldViews[field->fieldHandle()] = fieldEditor; + fieldEditor->setParentEditor(this); fieldEditor->setUiField(field); fieldEditor->createWidgets(parent); } From 50ee79f6c3012435febb511f7d406202bcfc0e3e Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 6 May 2019 07:05:51 +0200 Subject: [PATCH 017/396] #4388 AppFwk : Always mark field as used when editor is created --- .../cafUserInterface/cafPdmUiFormLayoutObjectEditor.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiFormLayoutObjectEditor.cpp b/Fwk/AppFwk/cafUserInterface/cafPdmUiFormLayoutObjectEditor.cpp index 6d12638b09..e3061e72c6 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiFormLayoutObjectEditor.cpp +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiFormLayoutObjectEditor.cpp @@ -183,9 +183,6 @@ int caf::PdmUiFormLayoutObjectEditor::recursivelyConfigureAndUpdateUiOrderingInG if (fieldEditor) { - // Mark this field as used in the editor - m_usedFields.insert(field->fieldHandle()); - // Also assign required item space that isn't taken up by field and label spareColumnsToAssign += minimumItemColumnSpan - (minimumLabelColumnSpan + minimumFieldColumnSpan); @@ -420,6 +417,11 @@ caf::PdmUiFieldEditorHandle* caf::PdmUiFormLayoutObjectEditor::findOrCreateField fieldEditor = it->second; } + if (fieldEditor) + { + m_usedFields.insert(field->fieldHandle()); + } + return fieldEditor; } From a852d1a50ea2cfc560aefceaadf3d347967e4e80 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 3 May 2019 15:46:56 +0200 Subject: [PATCH 018/396] #4388 AppFwk : Rename and rewrite of PdmUiFieldHandle::notifyFieldChanged --- .../cafPdmUiCore/cafPdmUiEditorHandle.cpp | 12 ++++------ .../cafPdmUiCore/cafPdmUiEditorHandle.h | 6 ++--- .../cafPdmUiCore/cafPdmUiFieldHandle.cpp | 23 ++++++++++++++++--- .../cafPdmUiCore/cafPdmUiItem.cpp | 11 +++++++-- .../cafPdmUiCore/cafPdmUiItem.h | 2 ++ .../cafPdmUiFormLayoutObjectEditor.cpp | 2 +- 6 files changed, 40 insertions(+), 16 deletions(-) diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiEditorHandle.cpp b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiEditorHandle.cpp index 729e3113df..ae7b0604c3 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiEditorHandle.cpp +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiEditorHandle.cpp @@ -88,16 +88,14 @@ void PdmUiEditorHandle::updateUi() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void PdmUiEditorHandle::updateUiIncludingParent() +PdmUiEditorHandle* PdmUiEditorHandle::topMostContainingEditor() { - if (m_parentEditor) + if (m_containingEditor) { - m_parentEditor->updateUiIncludingParent(); - } - else - { - this->updateUi(); + return m_containingEditor->topMostContainingEditor(); } + + return this; } //-------------------------------------------------------------------------------------------------- diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiEditorHandle.h b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiEditorHandle.h index c0252c9d91..b8d76f2dc5 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiEditorHandle.h +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiEditorHandle.h @@ -62,7 +62,7 @@ public: void updateUi(const QString& uiConfigName);; void updateUi(); - void updateUiIncludingParent(); + PdmUiEditorHandle* topMostContainingEditor(); signals: void uiUpdated(); @@ -80,14 +80,14 @@ protected: PdmUiItem* pdmItem() { return m_pdmItem; } const PdmUiItem* pdmItem() const { return m_pdmItem; } public: // PDM Internal - void setParentEditor(PdmUiEditorHandle* parentEditor) { m_parentEditor = parentEditor; } + void setContainingEditor(PdmUiEditorHandle* containingEditor) { m_containingEditor = containingEditor; } private: friend PdmUiItem::~PdmUiItem(); PdmUiItem* m_pdmItem; QString m_currentConfigName; - QPointer m_parentEditor; // Editor containing this editor. Will be asked to updateUi (instead of this) if it exists + QPointer m_containingEditor; // Editor containing this editor. Will be asked to updateUi (instead of this) if it exists bool m_isConfiguringUi; }; diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiFieldHandle.cpp b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiFieldHandle.cpp index 378af2aefa..316edec709 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiFieldHandle.cpp +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiFieldHandle.cpp @@ -4,6 +4,7 @@ #include "cafPdmFieldHandle.h" #include "cafPdmUiModelChangeDetector.h" #include "cafPdmUiObjectHandle.h" +#include "cafPdmUiEditorHandle.h" namespace caf { @@ -61,12 +62,31 @@ void PdmUiFieldHandle::notifyFieldChanged(const QVariant& oldFieldValue, const Q PdmObjectHandle* ownerObjectHandle = fieldHandle->ownerObject(); { + bool noOwnerObject = true; + + // Object editors + PdmUiObjectHandle* uiObjHandle = uiObj(ownerObjectHandle); if (uiObjHandle) { uiObjHandle->fieldChangedByUi(fieldHandle, oldFieldValue, newFieldValue); uiObjHandle->updateConnectedEditors(); + noOwnerObject = false; + } + + // Field editors + + for (const auto& editorForThisField : m_editors) + { + PdmUiEditorHandle* editorContainingThisField = editorForThisField->topMostContainingEditor(); + + bool editorContainingThisFieldIsNotUpdated = !uiObjHandle->hasEditor(editorContainingThisField); + + if (noOwnerObject || editorContainingThisFieldIsNotUpdated) + { + editorContainingThisField->updateUi(); + } } } @@ -81,9 +101,6 @@ void PdmUiFieldHandle::notifyFieldChanged(const QVariant& oldFieldValue, const Q } } - // Update connected field editors or their parent editors, to make the ui reflect the change - this->updateConnectedEditors(); - PdmUiModelChangeDetector::instance()->setModelChanged(); } } diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiItem.cpp b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiItem.cpp index 27e3e76ab1..12b9a015c8 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiItem.cpp +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiItem.cpp @@ -613,8 +613,7 @@ void PdmUiItem::updateConnectedEditors() const std::set::iterator it; for (it = m_editors.begin(); it != m_editors.end(); ++it) { - (*it)->updateUiIncludingParent(); - //(*it)->updateUi(); + (*it)->updateUi(); } } @@ -673,6 +672,14 @@ std::vector PdmUiItem::connectedEditors() const return editors; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool PdmUiItem::hasEditor(PdmUiEditorHandle* editor) const +{ + return m_editors.count(editor) > 0; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiItem.h b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiItem.h index 7d7cde26e7..c11c4b4028 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiItem.h +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiItem.h @@ -276,6 +276,8 @@ public: std::vector connectedEditors() const; + bool hasEditor(PdmUiEditorHandle* editor) const; + static bool showExtraDebugText(); static void enableExtraDebugText(bool enable); diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiFormLayoutObjectEditor.cpp b/Fwk/AppFwk/cafUserInterface/cafPdmUiFormLayoutObjectEditor.cpp index e3061e72c6..6031c76d05 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiFormLayoutObjectEditor.cpp +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiFormLayoutObjectEditor.cpp @@ -394,7 +394,7 @@ caf::PdmUiFieldEditorHandle* caf::PdmUiFormLayoutObjectEditor::findOrCreateField if (fieldEditor) { m_fieldViews[field->fieldHandle()] = fieldEditor; - fieldEditor->setParentEditor(this); + fieldEditor->setContainingEditor(this); fieldEditor->setUiField(field); fieldEditor->createWidgets(parent); } From 911b69b56f27c30511b975228c1fe1447d4ca10d Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 6 May 2019 11:46:44 +0200 Subject: [PATCH 019/396] #4388 AppFwk : Make sure context menu policy is set correctly in all use cases --- .../cafPdmUiFieldEditorHandle.cpp | 34 ++++++++++++++----- .../cafPdmUiCore/cafPdmUiFieldEditorHandle.h | 3 ++ 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiFieldEditorHandle.cpp b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiFieldEditorHandle.cpp index ea7760cc9a..9f41be8f89 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiFieldEditorHandle.cpp +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiFieldEditorHandle.cpp @@ -80,14 +80,30 @@ void PdmUiFieldEditorHandle::setUiField(PdmUiFieldHandle * field) if (m_editorWidget) { - if (field && field->isCustomContextMenuEnabled()) - { - m_editorWidget->setContextMenuPolicy(Qt::CustomContextMenu); - } - else - { - m_editorWidget->setContextMenuPolicy(Qt::DefaultContextMenu); - } + // Required to be called here to be able to handle different context menu + // policy when switching between objects of same type. In this case, the + // PdmUiFieldEditorHandle::createWidgets() will not be run, as the field + // widgets are cached by the property editor + + updateContextMenuPolicy(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void PdmUiFieldEditorHandle::updateContextMenuPolicy() +{ + if (m_editorWidget.isNull()) return; + + PdmUiFieldHandle* field = uiField(); + if (field && field->isCustomContextMenuEnabled()) + { + m_editorWidget->setContextMenuPolicy(Qt::CustomContextMenu); + } + else + { + m_editorWidget->setContextMenuPolicy(Qt::DefaultContextMenu); } } @@ -110,6 +126,8 @@ void PdmUiFieldEditorHandle::createWidgets(QWidget * parent) if (m_editorWidget) { + updateContextMenuPolicy(); + connect(m_editorWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(customMenuRequested(QPoint))); } if (m_labelWidget) diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiFieldEditorHandle.h b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiFieldEditorHandle.h index 763c3746ad..0d74e69aac 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiFieldEditorHandle.h +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiFieldEditorHandle.h @@ -114,6 +114,9 @@ protected: // Virtual interface to override virtual QMargins calculateLabelContentMargins() const; virtual bool isMultiRowEditor() const; +private: + void updateContextMenuPolicy(); + private slots: void customMenuRequested(QPoint pos); From 07903a63247ce9e92815e2f41a742622f1ec5aef Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Mon, 6 May 2019 12:46:44 +0200 Subject: [PATCH 020/396] Headless: handle unknown command arguments better --- .../Application/RiaConsoleApplication.cpp | 11 +++++++++-- .../Application/RiaGuiApplication.cpp | 11 +++++++++-- ApplicationCode/Application/RiaMain.cpp | 17 +++++++++++++++-- .../Application/Tools/RiaArgumentParser.cpp | 2 ++ 4 files changed, 35 insertions(+), 6 deletions(-) diff --git a/ApplicationCode/Application/RiaConsoleApplication.cpp b/ApplicationCode/Application/RiaConsoleApplication.cpp index dc0d5c3038..23f965d6e8 100644 --- a/ApplicationCode/Application/RiaConsoleApplication.cpp +++ b/ApplicationCode/Application/RiaConsoleApplication.cpp @@ -105,8 +105,15 @@ RiaApplication::ApplicationStatus RiaConsoleApplication::handleArguments(cvf::Pr if (cvf::Option o = progOpt->option("unittest")) { int testReturnValue = launchUnitTestsWithConsole(); - - return testReturnValue == 0 ? RiaApplication::EXIT_COMPLETED : RiaApplication::EXIT_WITH_ERROR; + if (testReturnValue == 0) + { + return RiaApplication::EXIT_COMPLETED; + } + else + { + RiaLogging::error("Error running unit tests"); + return RiaApplication::EXIT_WITH_ERROR; + } } if (cvf::Option o = progOpt->option("startdir")) diff --git a/ApplicationCode/Application/RiaGuiApplication.cpp b/ApplicationCode/Application/RiaGuiApplication.cpp index 567d97dc4b..7b3e1d9d58 100644 --- a/ApplicationCode/Application/RiaGuiApplication.cpp +++ b/ApplicationCode/Application/RiaGuiApplication.cpp @@ -594,8 +594,15 @@ RiaApplication::ApplicationStatus RiaGuiApplication::handleArguments(cvf::Progra if (cvf::Option o = progOpt->option("unittest")) { int testReturnValue = launchUnitTestsWithConsole(); - - return testReturnValue == 0 ? RiaApplication::EXIT_COMPLETED : RiaApplication::EXIT_WITH_ERROR; + if (testReturnValue == 0) + { + return RiaApplication::EXIT_COMPLETED; + } + else + { + RiaLogging::error("Error running unit tests"); + return RiaApplication::EXIT_WITH_ERROR; + } } if (cvf::Option o = progOpt->option("regressiontest")) diff --git a/ApplicationCode/Application/RiaMain.cpp b/ApplicationCode/Application/RiaMain.cpp index 48234621b0..1b744fbdac 100644 --- a/ApplicationCode/Application/RiaMain.cpp +++ b/ApplicationCode/Application/RiaMain.cpp @@ -49,9 +49,22 @@ int main(int argc, char *argv[]) if (!result) { + std::vector unknownOptions = progOpt.unknownOptions(); + QStringList unknownOptionsText; + for (cvf::String option : unknownOptions) + { + unknownOptionsText += QString("Unknown option: %1").arg(cvfqt::Utils::toQString(option)); + } + const cvf::String usageText = progOpt.usageText(110, 30); - app->showInformationMessage(RiaApplication::commandLineParameterHelp() + cvfqt::Utils::toQString(usageText)); + app->showErrorMessage(RiaApplication::commandLineParameterHelp() + + cvfqt::Utils::toQString(usageText) + + unknownOptionsText.join('\n')); app->cleanupBeforeProgramExit(); + if (dynamic_cast(app.get()) == nullptr) + { + return 1; + } } QLocale::setDefault(QLocale(QLocale::English, QLocale::UnitedStates)); @@ -64,7 +77,7 @@ int main(int argc, char *argv[]) } else if (status == RiaApplication::EXIT_WITH_ERROR) { - return 1; + return 2; } else if (status == RiaApplication::KEEP_GOING) { diff --git a/ApplicationCode/Application/Tools/RiaArgumentParser.cpp b/ApplicationCode/Application/Tools/RiaArgumentParser.cpp index 82910e652e..0e4f44e70e 100644 --- a/ApplicationCode/Application/Tools/RiaArgumentParser.cpp +++ b/ApplicationCode/Application/Tools/RiaArgumentParser.cpp @@ -106,7 +106,9 @@ bool RiaArgumentParser::parseArguments(cvf::ProgramOptions* progOpt) progOpt->registerOption("?", "", "Displays help text."); progOpt->registerOption("regressiontest", "", "System command", cvf::ProgramOptions::SINGLE_VALUE); progOpt->registerOption("updateregressiontestbase", "", "System command", cvf::ProgramOptions::SINGLE_VALUE); +#ifdef USE_UNIT_TESTS progOpt->registerOption("unittest", "", "System command"); +#endif progOpt->registerOption("ignoreArgs", "", "Ignore all arguments. Mostly for testing purposes"); progOpt->setOptionPrefix(cvf::ProgramOptions::DOUBLE_DASH); From af1a5790a2ae3273c27a596c8805019bf9459934 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Mon, 6 May 2019 13:32:22 +0200 Subject: [PATCH 021/396] Fix crash in some unit tests from constructing a QPixmap without a QApplication --- .../cafPdmUiCore/cafQIconProvider.cpp | 20 +++++++++++++------ .../cafPdmUiCore/cafQIconProvider.h | 11 ++++++---- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafQIconProvider.cpp b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafQIconProvider.cpp index bdc4f1c02c..bbfdbe7430 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafQIconProvider.cpp +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafQIconProvider.cpp @@ -29,7 +29,7 @@ QIconProvider::QIconProvider(const QString& iconResourceString) /// //-------------------------------------------------------------------------------------------------- QIconProvider::QIconProvider(const QPixmap& pixmap) - : m_iconPixmap(pixmap) + : m_iconPixmap(new QPixmap(pixmap)) { } @@ -64,7 +64,7 @@ QIcon QIconProvider::icon() const m_icon = generateIcon(); } - if (!m_active) + if (!m_active && isGuiApplication()) { QPixmap disabledPixmap = m_icon.pixmap(16, 16, QIcon::Disabled); return QIcon(disabledPixmap); @@ -80,7 +80,7 @@ bool QIconProvider::isNull() const { if (!isGuiApplication()) return true; - if (m_iconPixmap.isNull() && m_iconResourceString.isEmpty()) return true; + if (!hasValidPixmap() && m_iconResourceString.isEmpty()) return true; return icon().isNull(); } @@ -107,7 +107,7 @@ void QIconProvider::setIconResourceString(const QString& iconResourceString) //-------------------------------------------------------------------------------------------------- void QIconProvider::setPixmap(const QPixmap& pixmap) { - m_iconPixmap = pixmap; + m_iconPixmap.reset(new QPixmap(pixmap)); m_icon = QIcon(); } @@ -119,9 +119,9 @@ QIcon QIconProvider::generateIcon() const { if (isGuiApplication()) { - if (!m_iconPixmap.isNull()) + if (hasValidPixmap()) { - return QIcon(m_iconPixmap); + return QIcon(*m_iconPixmap); } return QIcon(m_iconResourceString); } @@ -135,3 +135,11 @@ bool QIconProvider::isGuiApplication() { return dynamic_cast(QCoreApplication::instance()) != nullptr; } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool QIconProvider::hasValidPixmap() const +{ + return m_iconPixmap && !m_iconPixmap->isNull(); +} diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafQIconProvider.h b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafQIconProvider.h index c3ce820996..6b822fb0aa 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafQIconProvider.h +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafQIconProvider.h @@ -39,6 +39,8 @@ #include #include +#include + namespace caf { //================================================================================================== @@ -61,13 +63,14 @@ public: void setPixmap(const QPixmap& pixmap); protected: + bool hasValidPixmap() const; virtual QIcon generateIcon() const; static bool isGuiApplication(); protected: - QString m_iconResourceString; - QPixmap m_iconPixmap; - mutable QIcon m_icon; - bool m_active; + QString m_iconResourceString; + std::unique_ptr m_iconPixmap; + mutable QIcon m_icon; + bool m_active; }; } From 63ed79e0e8f4d22c8771d224877817599b4c9ab5 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Mon, 6 May 2019 13:49:23 +0200 Subject: [PATCH 022/396] Update UI icon of RimCellEdgeColors --- ApplicationCode/ProjectDataModel/RimCellEdgeColors.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ApplicationCode/ProjectDataModel/RimCellEdgeColors.cpp b/ApplicationCode/ProjectDataModel/RimCellEdgeColors.cpp index b948fcac4e..1e754d3157 100644 --- a/ApplicationCode/ProjectDataModel/RimCellEdgeColors.cpp +++ b/ApplicationCode/ProjectDataModel/RimCellEdgeColors.cpp @@ -148,6 +148,7 @@ void RimCellEdgeColors::loadResult() void RimCellEdgeColors::initAfterRead() { m_singleVarEdgeResultColors->initAfterRead(); + this->updateUiIconFromToggleField(); } //-------------------------------------------------------------------------------------------------- @@ -158,6 +159,11 @@ void RimCellEdgeColors::fieldChangedByUi(const caf::PdmFieldHandle* changedField loadResult(); if (m_reservoirView) m_reservoirView->createDisplayModelAndRedraw(); + + if (changedField == objectToggleField()) + { + updateUiIconFromToggleField(); + } } namespace caf From 29ec970b02aaeb5b1618b1dd49b57fc7c902ad0a Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Mon, 6 May 2019 15:03:24 +0200 Subject: [PATCH 023/396] Qt4 fix --- ApplicationCode/Application/RiaMain.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ApplicationCode/Application/RiaMain.cpp b/ApplicationCode/Application/RiaMain.cpp index 1b744fbdac..6fee7d145b 100644 --- a/ApplicationCode/Application/RiaMain.cpp +++ b/ApplicationCode/Application/RiaMain.cpp @@ -59,7 +59,7 @@ int main(int argc, char *argv[]) const cvf::String usageText = progOpt.usageText(110, 30); app->showErrorMessage(RiaApplication::commandLineParameterHelp() + cvfqt::Utils::toQString(usageText) + - unknownOptionsText.join('\n')); + unknownOptionsText.join("\n")); app->cleanupBeforeProgramExit(); if (dynamic_cast(app.get()) == nullptr) { From ac8ea73c36efc263f77b1054f1722cf6625b1e3e Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 6 May 2019 13:44:40 +0200 Subject: [PATCH 024/396] #4395 Robustness : Guard array out of bounds access --- .../ReservoirDataModel/RigFlowDiagResults.cpp | 11 ++++++++--- .../RiuFlowCharacteristicsPlot.cpp | 19 +++++++++++-------- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/ApplicationCode/ReservoirDataModel/RigFlowDiagResults.cpp b/ApplicationCode/ReservoirDataModel/RigFlowDiagResults.cpp index 8802675fd8..65bc42d058 100644 --- a/ApplicationCode/ReservoirDataModel/RigFlowDiagResults.cpp +++ b/ApplicationCode/ReservoirDataModel/RigFlowDiagResults.cpp @@ -118,6 +118,8 @@ const std::vector* RigFlowDiagResults::findOrCalculateResult(const RigFl //-------------------------------------------------------------------------------------------------- void RigFlowDiagResults::calculateNativeResultsIfNotPreviouslyAttempted(size_t timeStepIndex, RigFlowDiagResultAddress::PhaseSelection phaseSelection) { + if (timeStepIndex >= m_hasAtemptedNativeResults.size()) return; + auto it = m_hasAtemptedNativeResults[timeStepIndex].find(phaseSelection); if ( it == m_hasAtemptedNativeResults[timeStepIndex].end() || !it->second ) { @@ -701,10 +703,13 @@ double RigFlowDiagResults::maxAbsPairFlux(int timeStepIndex) calculateNativeResultsIfNotPreviouslyAttempted(timeStepIndex, RigFlowDiagResultAddress::PHASE_ALL); double maxFlux = 0.0; - for (const auto& commPair : m_injProdPairFluxCommunicationTimesteps[timeStepIndex][RigFlowDiagResultAddress::PHASE_ALL]) + if (timeStepIndex < m_injProdPairFluxCommunicationTimesteps.size()) { - if (fabs(commPair.second.first) > maxFlux ) maxFlux = fabs(commPair.second.first); - if (fabs(commPair.second.second) > maxFlux ) maxFlux = fabs(commPair.second.second); + for (const auto& commPair : m_injProdPairFluxCommunicationTimesteps[timeStepIndex][RigFlowDiagResultAddress::PHASE_ALL]) + { + if (fabs(commPair.second.first) > maxFlux ) maxFlux = fabs(commPair.second.first); + if (fabs(commPair.second.second) > maxFlux ) maxFlux = fabs(commPair.second.second); + } } return maxFlux; diff --git a/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.cpp b/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.cpp index d98cfc4df4..28dbb6bcc8 100644 --- a/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.cpp +++ b/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.cpp @@ -113,20 +113,23 @@ RiuFlowCharacteristicsPlot::~RiuFlowCharacteristicsPlot() //-------------------------------------------------------------------------------------------------- void RiuFlowCharacteristicsPlot::setLorenzCurve(const QStringList& dateTimeStrings, const std::vector& dateTimes, const std::vector& timeHistoryValues) { - initializeColors(dateTimes); - m_lorenzPlot->detachItems(QwtPlotItem::Rtti_PlotCurve, true); - for (size_t tsIdx = 0; tsIdx < dateTimes.size(); ++tsIdx) + if (!dateTimes.empty()) { - if (timeHistoryValues[tsIdx] == HUGE_VAL) continue; + initializeColors(dateTimes); - QDateTime dateTime = dateTimes[tsIdx]; - double timeHistoryValue = timeHistoryValues[tsIdx]; + for (size_t tsIdx = 0; tsIdx < dateTimes.size(); ++tsIdx) + { + if (timeHistoryValues[tsIdx] == HUGE_VAL) continue; - QString curveName = dateTimeStrings[static_cast(tsIdx)]; + QDateTime dateTime = dateTimes[tsIdx]; + double timeHistoryValue = timeHistoryValues[tsIdx]; - RiuFlowCharacteristicsPlot::addCurveWithLargeSymbol(m_lorenzPlot, curveName, m_dateToColorMap[dateTime], dateTime, timeHistoryValue); + QString curveName = dateTimeStrings[static_cast(tsIdx)]; + + RiuFlowCharacteristicsPlot::addCurveWithLargeSymbol(m_lorenzPlot, curveName, m_dateToColorMap[dateTime], dateTime, timeHistoryValue); + } } m_lorenzPlot->replot(); From 6ce3371df5a773b5b411c3a024aca77b95353111 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 8 May 2019 08:38:27 +0200 Subject: [PATCH 025/396] #4396 System : Add SSL information to about dialog --- .../ApplicationCommands/RicHelpFeatures.cpp | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/ApplicationCode/Commands/ApplicationCommands/RicHelpFeatures.cpp b/ApplicationCode/Commands/ApplicationCommands/RicHelpFeatures.cpp index 89c91f7c5e..7adff9751a 100644 --- a/ApplicationCode/Commands/ApplicationCommands/RicHelpFeatures.cpp +++ b/ApplicationCode/Commands/ApplicationCommands/RicHelpFeatures.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include CAF_CMD_SOURCE_INIT(RicHelpAboutFeature, "RicHelpAboutFeature"); @@ -90,6 +91,36 @@ void RicHelpAboutFeature::onActionTriggered(bool isChecked) dlg.addVersionEntry(" ", caf::Viewer::isShadersSupported() ? " Hardware OpenGL" : " Software OpenGL"); dlg.addVersionEntry(" ", QString(" Octave ") + QString(RESINSIGHT_OCTAVE_VERSION)); + bool isAbleToUseSsl = false; + bool isSslSupported = false; +#ifndef QT_NO_OPENSSL + isAbleToUseSsl = true; + isSslSupported = QSslSocket::supportsSsl(); +#endif + + { + QString txt; + + if (isAbleToUseSsl) + { + txt = " Use of SSL is available"; + if (isSslSupported) + { + txt += " and supported"; + } + else + { + txt += ", but not supported"; + } + } + else + { + txt = " SSL is not available"; + } + + dlg.addVersionEntry(" ", txt); + } + if (RiaApplication::enableDevelopmentFeatures()) { QString vendor("Unknown"); From 04091ad77d0580292c30796f7080618f80930f21 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 7 May 2019 07:15:25 +0200 Subject: [PATCH 026/396] #4266 Update libecl Use commit 0e1e780fd6f18ce93119061e36a4fca9711bc020 Excluded multibuild folder, as this caused git issues --- ThirdParty/Ert/.github/CODEOWNERS | 2 + .../Ert/.github/PULL_REQUEST_TEMPLATE.md | 9 +- ThirdParty/Ert/.gitignore | 3 +- ThirdParty/Ert/.gitmodules | 3 + ThirdParty/Ert/.travis.yml | 104 +- ThirdParty/Ert/CMakeLists.txt | 31 +- ThirdParty/Ert/README.md | 9 +- ThirdParty/Ert/WINDOWS.md | 27 + ThirdParty/Ert/Windows.txt | 90 - ThirdParty/Ert/applications/CMakeLists.txt | 24 +- ThirdParty/Ert/applications/ecl/convert.c | 2 +- ThirdParty/Ert/applications/ecl/ecl_pack.c | 2 +- .../Ert/applications/ecl/ecl_quantile.c | 3 +- ThirdParty/Ert/applications/ecl/ecl_unpack.c | 2 +- ThirdParty/Ert/applications/ecl/grdecl_grid.c | 2 +- ThirdParty/Ert/applications/ecl/grdecl_test.c | 2 +- ThirdParty/Ert/applications/ecl/grid_dump.c | 2 +- .../Ert/applications/ecl/grid_dump_ascii.c | 2 +- ThirdParty/Ert/applications/ecl/grid_info.c | 2 +- ThirdParty/Ert/applications/ecl/grid_layer.c | 2 +- ThirdParty/Ert/applications/ecl/key_list.c | 2 +- .../ecl/{kw_extract.c => kw_extract.cpp} | 2 +- ThirdParty/Ert/applications/ecl/kw_list.c | 2 +- ThirdParty/Ert/applications/ecl/load_test.c | 2 +- ThirdParty/Ert/applications/ecl/make_grid.c | 2 +- ThirdParty/Ert/applications/ecl/run_gravity.c | 2 +- ThirdParty/Ert/applications/ecl/select_test.c | 2 +- .../ecl/{sum_write.c => sum_write.cpp} | 12 +- .../Ert/applications/ecl/summary2csv2.c | 2 +- .../Ert/applications/ecl/view_restart.c | 2 +- ThirdParty/Ert/applications/ecl/view_rft.c | 2 +- .../ecl/{view_summary.c => view_summary.cpp} | 7 +- ThirdParty/Ert/applications/ecl/vprofile.c | 2 +- .../Ert/applications/man/man1/ecl_summary.1 | 5 +- .../Ert/applications/well/ri_well_test.c | 2 +- .../Ert/applications/well/segment_info.c | 2 +- .../Ert/applications/well/well_CF_dump.c | 2 +- ThirdParty/Ert/appveyor.yml | 1 - ThirdParty/Ert/bin/summary_resample | 6 +- ThirdParty/Ert/config.sh | 0 ThirdParty/Ert/debian/README.Debian | 4 - ThirdParty/Ert/debian/changelog | 2 +- ThirdParty/Ert/debian/copyright | 2 +- ThirdParty/Ert/docs/CMakeLists.txt | 38 - ThirdParty/Ert/docs/code/C/index.rst | 4 - .../docs/code/python/eclipse/API/index.rst | 9 - .../docs/code/python/examples/ert/index.rst | 3 - .../code/python/packages/geometry/index.rst | 2 - .../docs/code/python/packages/util/index.rst | 2 - .../docs/code/python/packages/well/index.rst | 2 - ThirdParty/Ert/docs/course/config/config.ert | 34 - .../docs/course/config/jobs/SNAKE_OIL_DIFF | 4 - .../Ert/docs/course/config/jobs/SNAKE_OIL_NPV | 4 - .../course/config/jobs/SNAKE_OIL_SIMULATOR | 4 - .../docs/course/config/jobs/snake_oil_diff.py | 24 - .../docs/course/config/jobs/snake_oil_npv.py | 103 - .../course/config/jobs/snake_oil_simulator.py | 185 -- .../parameters/snake_oil_parameters.txt | 11 - .../config/refcase/SNAKE_OIL_FIELD.SMSPEC | Bin 1416 -> 0 bytes .../config/refcase/SNAKE_OIL_FIELD.UNSMRY | Bin 455200 -> 0 bytes .../course/config/refcase/refcase_readme.txt | 1 - .../Ert/docs/course/config/refcase/seed.txt | 1 - .../config/refcase/snake_oil_params.txt | 10 - .../docs/course/config/refcase/time_map.txt | 2000 ----------------- .../Ert/docs/course/config/snake_oil.ert | 40 - .../course/config/templates/seed_template.txt | 1 - .../config/templates/snake_oil_template.txt | 10 - ThirdParty/Ert/docs/course/ex1/ex1.txt | 7 - ThirdParty/Ert/docs/course/ex1/sol1.py | 27 - ThirdParty/Ert/docs/course/ex2/ex2.txt | 1 - ThirdParty/Ert/docs/course/ex2/sol2.txt | 35 - ThirdParty/Ert/docs/course/ex3/ex3.txt | 2 - ThirdParty/Ert/docs/course/ex3/sol3.py | 17 - ThirdParty/Ert/docs/course/ex4/ex4.txt | 13 - ThirdParty/Ert/docs/course/ex4/sol4.py | 71 - ThirdParty/Ert/docs/doxygen.cfg.in | 42 - ThirdParty/Ert/docs/eclipse_restart_spe1.txt | 109 - .../docs/eclipse_restart_specification.txt | 268 --- ThirdParty/Ert/docs/nexus.plt | 51 - ThirdParty/Ert/install/install.py | 2 +- ThirdParty/Ert/lib/CMakeLists.txt | 93 +- ThirdParty/Ert/lib/ecl/EclFilename.cpp | 2 +- ThirdParty/Ert/lib/ecl/FortIO.cpp | 2 +- ThirdParty/Ert/lib/ecl/Smspec.cpp | 120 - ThirdParty/Ert/lib/ecl/ecl_box.cpp | 2 +- ThirdParty/Ert/lib/ecl/ecl_coarse_cell.cpp | 2 +- ThirdParty/Ert/lib/ecl/ecl_file.cpp | 7 +- ThirdParty/Ert/lib/ecl/ecl_file_kw.cpp | 4 +- ThirdParty/Ert/lib/ecl/ecl_file_view.cpp | 137 +- ThirdParty/Ert/lib/ecl/ecl_grav.cpp | 111 +- ThirdParty/Ert/lib/ecl/ecl_grav_calc.cpp | 2 +- ThirdParty/Ert/lib/ecl/ecl_grav_common.cpp | 2 +- ThirdParty/Ert/lib/ecl/ecl_grid.cpp | 60 +- ThirdParty/Ert/lib/ecl/ecl_grid_cache.cpp | 2 +- ThirdParty/Ert/lib/ecl/ecl_grid_dims.cpp | 2 +- ThirdParty/Ert/lib/ecl/ecl_init_file.cpp | 2 +- ThirdParty/Ert/lib/ecl/ecl_io_config.cpp | 2 +- ThirdParty/Ert/lib/ecl/ecl_kw.cpp | 2 +- ThirdParty/Ert/lib/ecl/ecl_kw_grdecl.cpp | 2 +- ThirdParty/Ert/lib/ecl/ecl_nnc_data.cpp | 2 +- ThirdParty/Ert/lib/ecl/ecl_nnc_export.cpp | 74 +- ThirdParty/Ert/lib/ecl/ecl_nnc_geometry.cpp | 10 +- ThirdParty/Ert/lib/ecl/ecl_region.cpp | 2 +- ThirdParty/Ert/lib/ecl/ecl_rft_cell.cpp | 8 +- ThirdParty/Ert/lib/ecl/ecl_rft_file.cpp | 120 +- ThirdParty/Ert/lib/ecl/ecl_rft_node.cpp | 103 +- ThirdParty/Ert/lib/ecl/ecl_rst_file.cpp | 2 +- ThirdParty/Ert/lib/ecl/ecl_rsthead.cpp | 12 +- ThirdParty/Ert/lib/ecl/ecl_smspec.cpp | 1070 ++++----- ThirdParty/Ert/lib/ecl/ecl_subsidence.cpp | 63 +- ThirdParty/Ert/lib/ecl/ecl_sum.cpp | 195 +- ThirdParty/Ert/lib/ecl/ecl_sum_data.cpp | 59 +- ThirdParty/Ert/lib/ecl/ecl_sum_file_data.cpp | 11 +- ThirdParty/Ert/lib/ecl/ecl_sum_index.cpp | 2 +- ThirdParty/Ert/lib/ecl/ecl_sum_tstep.cpp | 71 +- ThirdParty/Ert/lib/ecl/ecl_sum_vector.cpp | 62 +- ThirdParty/Ert/lib/ecl/ecl_type.cpp | 2 +- ThirdParty/Ert/lib/ecl/ecl_unsmry_loader.cpp | 2 +- ThirdParty/Ert/lib/ecl/ecl_util.cpp | 4 +- ThirdParty/Ert/lib/ecl/fault_block.cpp | 2 +- ThirdParty/Ert/lib/ecl/fault_block_layer.cpp | 4 +- ThirdParty/Ert/lib/ecl/fortio.c | 4 +- ThirdParty/Ert/lib/ecl/grid_dims.cpp | 2 +- ThirdParty/Ert/lib/ecl/layer.cpp | 2 +- ThirdParty/Ert/lib/ecl/nnc_info.cpp | 36 +- ThirdParty/Ert/lib/ecl/nnc_vector.cpp | 43 +- ThirdParty/Ert/lib/ecl/smspec_node.cpp | 1339 ++++++----- .../Ert/lib/ecl/tests/ecl_alloc_cpgrid.cpp | 2 +- .../ecl/tests/ecl_alloc_grid_dxv_dyv_dzv.cpp | 3 +- .../Ert/lib/ecl/tests/ecl_coarse_test.cpp | 2 +- ThirdParty/Ert/lib/ecl/tests/ecl_dualp.cpp | 2 +- ...=> ecl_fault_block_collection_equinor.cpp} | 4 +- .../lib/ecl/tests/ecl_fault_block_layer.cpp | 3 +- ....cpp => ecl_fault_block_layer_equinor.cpp} | 4 +- ThirdParty/Ert/lib/ecl/tests/ecl_file.cpp | 9 +- ..._file_statoil.cpp => ecl_file_equinor.cpp} | 14 +- .../Ert/lib/ecl/tests/ecl_file_view.cpp | 5 +- ThirdParty/Ert/lib/ecl/tests/ecl_fmt.cpp | 16 +- ThirdParty/Ert/lib/ecl/tests/ecl_fortio.cpp | 30 +- .../lib/ecl/tests/ecl_get_num_cpu_test.cpp | 2 +- .../Ert/lib/ecl/tests/ecl_grid_DEPTHZ.cpp | 10 +- .../Ert/lib/ecl/tests/ecl_grid_add_nnc.cpp | 13 +- .../Ert/lib/ecl/tests/ecl_grid_case.cpp | 2 +- .../lib/ecl/tests/ecl_grid_cell_contains.cpp | 2 +- .../tests/ecl_grid_cell_contains_wellpath.cpp | 2 +- .../Ert/lib/ecl/tests/ecl_grid_copy.cpp | 2 +- ..._statoil.cpp => ecl_grid_copy_equinor.cpp} | 4 +- .../Ert/lib/ecl/tests/ecl_grid_corner.cpp | 2 +- .../Ert/lib/ecl/tests/ecl_grid_create.cpp | 2 +- .../Ert/lib/ecl/tests/ecl_grid_dims.cpp | 2 +- .../Ert/lib/ecl/tests/ecl_grid_dx_dy_dz.cpp | 2 +- .../Ert/lib/ecl/tests/ecl_grid_export.cpp | 5 +- .../Ert/lib/ecl/tests/ecl_grid_ext_actnum.cpp | 11 +- .../Ert/lib/ecl/tests/ecl_grid_fwrite.cpp | 70 +- .../lib/ecl/tests/ecl_grid_init_fwrite.cpp | 8 +- .../lib/ecl/tests/ecl_grid_layer_contains.cpp | 2 +- .../Ert/lib/ecl/tests/ecl_grid_lgr_name.cpp | 4 +- .../lib/ecl/tests/ecl_grid_reset_actnum.cpp | 2 +- .../Ert/lib/ecl/tests/ecl_grid_simple.cpp | 2 +- .../lib/ecl/tests/ecl_grid_unit_system.cpp | 6 +- .../Ert/lib/ecl/tests/ecl_grid_volume.cpp | 2 +- .../Ert/lib/ecl/tests/ecl_init_file.cpp | 7 +- .../Ert/lib/ecl/tests/ecl_kw_cmp_string.cpp | 3 +- ThirdParty/Ert/lib/ecl/tests/ecl_kw_equal.cpp | 9 +- ThirdParty/Ert/lib/ecl/tests/ecl_kw_fread.cpp | 9 +- .../Ert/lib/ecl/tests/ecl_kw_grdecl.cpp | 5 +- ThirdParty/Ert/lib/ecl/tests/ecl_kw_init.cpp | 2 +- ThirdParty/Ert/lib/ecl/tests/ecl_layer.cpp | 2 +- ...ayer_statoil.cpp => ecl_layer_equinor.cpp} | 4 +- ThirdParty/Ert/lib/ecl/tests/ecl_lfs.cpp | 2 +- ThirdParty/Ert/lib/ecl/tests/ecl_lgr_name.cpp | 2 +- ThirdParty/Ert/lib/ecl/tests/ecl_lgr_test.cpp | 2 +- ...root.cpp => ecl_nnc_data_equinor_root.cpp} | 4 +- .../Ert/lib/ecl/tests/ecl_nnc_export.cpp | 22 +- .../lib/ecl/tests/ecl_nnc_export_get_tran.cpp | 2 +- .../ecl/tests/ecl_nnc_export_intersect.cpp | 117 + .../Ert/lib/ecl/tests/ecl_nnc_geometry.cpp | 6 +- .../Ert/lib/ecl/tests/ecl_nnc_index_list.cpp | 2 +- .../lib/ecl/tests/ecl_nnc_index_list_grid.cpp | 2 +- .../Ert/lib/ecl/tests/ecl_nnc_info_test.cpp | 21 +- ThirdParty/Ert/lib/ecl/tests/ecl_nnc_pair.cpp | 2 +- ThirdParty/Ert/lib/ecl/tests/ecl_nnc_test.cpp | 19 +- .../Ert/lib/ecl/tests/ecl_nnc_vector.cpp | 22 +- ThirdParty/Ert/lib/ecl/tests/ecl_region.cpp | 2 +- .../Ert/lib/ecl/tests/ecl_region2region.cpp | 2 +- .../Ert/lib/ecl/tests/ecl_restart_test.cpp | 2 +- ThirdParty/Ert/lib/ecl/tests/ecl_rft.cpp | 11 +- ThirdParty/Ert/lib/ecl/tests/ecl_rft_cell.cpp | 2 +- ThirdParty/Ert/lib/ecl/tests/ecl_rst_file.cpp | 11 +- ThirdParty/Ert/lib/ecl/tests/ecl_rsthead.cpp | 2 +- ThirdParty/Ert/lib/ecl/tests/ecl_smspec.cpp | 23 +- .../Ert/lib/ecl/tests/ecl_smspec_node.cpp | 207 +- .../tests/ecl_sum_alloc_resampled_test.cpp | 83 +- .../Ert/lib/ecl/tests/ecl_sum_case_exists.cpp | 2 +- .../tests/ecl_sum_data_intermediate_test.cpp | 174 +- .../tests/ecl_sum_report_step_compatible.cpp | 2 +- .../ecl/tests/ecl_sum_report_step_equal.cpp | 2 +- .../Ert/lib/ecl/tests/ecl_sum_restart.cpp | 167 ++ ThirdParty/Ert/lib/ecl/tests/ecl_sum_test.cpp | 2 +- .../Ert/lib/ecl/tests/ecl_sum_writer.cpp | 60 +- .../lib/ecl/tests/ecl_unsmry_loader_test.cpp | 15 +- .../Ert/lib/ecl/tests/ecl_util_filenames.cpp | 18 +- .../ecl/tests/ecl_util_make_date_no_shift.cpp | 2 +- .../ecl/tests/ecl_util_make_date_shift.cpp | 2 +- .../lib/ecl/tests/ecl_util_month_range.cpp | 2 +- .../lib/ecl/tests/ecl_util_path_access.cpp | 5 +- .../Ert/lib/ecl/tests/ecl_valid_basename.cpp | 2 +- .../Ert/lib/ecl/tests/eclxx_filename.cpp | 2 +- ThirdParty/Ert/lib/ecl/tests/eclxx_fortio.cpp | 15 +- ThirdParty/Ert/lib/ecl/tests/eclxx_kw.cpp | 5 +- ThirdParty/Ert/lib/ecl/tests/eclxx_smspec.cpp | 130 -- ThirdParty/Ert/lib/ecl/tests/eclxx_types.cpp | 2 +- ThirdParty/Ert/lib/ecl/tests/rft_test.cpp | 2 +- .../Ert/lib/ecl/tests/test_ecl_file_index.cpp | 5 +- .../Ert/lib/ecl/tests/test_ecl_nnc_data.cpp | 5 +- .../Ert/lib/ecl/tests/test_transactions.cpp | 9 +- .../lib/ecl/tests/well_branch_collection.cpp | 2 +- ThirdParty/Ert/lib/ecl/tests/well_conn.cpp | 2 +- ThirdParty/Ert/lib/ecl/tests/well_conn_CF.cpp | 2 +- .../lib/ecl/tests/well_conn_collection.cpp | 2 +- .../Ert/lib/ecl/tests/well_conn_load.cpp | 2 +- ThirdParty/Ert/lib/ecl/tests/well_dualp.cpp | 2 +- ThirdParty/Ert/lib/ecl/tests/well_info.cpp | 6 +- .../Ert/lib/ecl/tests/well_lgr_load.cpp | 2 +- ThirdParty/Ert/lib/ecl/tests/well_segment.cpp | 2 +- .../tests/well_segment_branch_conn_load.cpp | 2 +- .../lib/ecl/tests/well_segment_collection.cpp | 2 +- .../Ert/lib/ecl/tests/well_segment_conn.cpp | 2 +- .../lib/ecl/tests/well_segment_conn_load.cpp | 2 +- .../Ert/lib/ecl/tests/well_segment_load.cpp | 2 +- ThirdParty/Ert/lib/ecl/tests/well_state.cpp | 2 +- .../Ert/lib/ecl/tests/well_state_load.cpp | 2 +- .../tests/well_state_load_missing_RSEG.cpp | 2 +- ThirdParty/Ert/lib/ecl/tests/well_ts.cpp | 5 +- .../Ert/lib/ecl/well_branch_collection.cpp | 51 +- ThirdParty/Ert/lib/ecl/well_conn.cpp | 6 +- .../Ert/lib/ecl/well_conn_collection.cpp | 29 +- ThirdParty/Ert/lib/ecl/well_info.cpp | 22 +- ThirdParty/Ert/lib/ecl/well_rseg_loader.cpp | 3 +- ThirdParty/Ert/lib/ecl/well_segment.cpp | 35 +- .../Ert/lib/ecl/well_segment_collection.cpp | 55 +- ThirdParty/Ert/lib/ecl/well_state.cpp | 145 +- ThirdParty/Ert/lib/ecl/well_ts.cpp | 80 +- ThirdParty/Ert/lib/geometry/geo_pointset.cpp | 2 +- ThirdParty/Ert/lib/geometry/geo_polygon.cpp | 2 +- .../lib/geometry/geo_polygon_collection.cpp | 20 +- ThirdParty/Ert/lib/geometry/geo_region.cpp | 2 +- ThirdParty/Ert/lib/geometry/geo_surface.cpp | 2 +- ThirdParty/Ert/lib/geometry/geo_util.cpp | 2 +- .../Ert/lib/geometry/tests/geo_polygon.cpp | 2 +- .../geometry/tests/geo_polygon_collection.cpp | 2 +- .../Ert/lib/geometry/tests/geo_surface.cpp | 2 +- .../lib/geometry/tests/geo_util_xlines.cpp | 2 +- .../Ert/lib/include/ert/ecl/EclFilename.hpp | 2 +- ThirdParty/Ert/lib/include/ert/ecl/EclKW.hpp | 2 +- ThirdParty/Ert/lib/include/ert/ecl/FortIO.hpp | 2 +- ThirdParty/Ert/lib/include/ert/ecl/Smspec.hpp | 61 - .../Ert/lib/include/ert/ecl/ecl_box.hpp | 2 +- .../lib/include/ert/ecl/ecl_coarse_cell.hpp | 2 +- .../lib/include/ert/ecl/ecl_endian_flip.hpp | 2 +- .../Ert/lib/include/ert/ecl/ecl_file.hpp | 2 +- .../Ert/lib/include/ert/ecl/ecl_file_kw.hpp | 2 +- .../Ert/lib/include/ert/ecl/ecl_file_view.hpp | 6 +- .../Ert/lib/include/ert/ecl/ecl_grav.hpp | 2 +- .../Ert/lib/include/ert/ecl/ecl_grav_calc.hpp | 2 +- .../lib/include/ert/ecl/ecl_grav_common.hpp | 2 +- .../Ert/lib/include/ert/ecl/ecl_grid.hpp | 10 +- .../Ert/lib/include/ert/ecl/ecl_grid_dims.hpp | 2 +- .../Ert/lib/include/ert/ecl/ecl_init_file.hpp | 2 +- .../Ert/lib/include/ert/ecl/ecl_io_config.hpp | 2 +- ThirdParty/Ert/lib/include/ert/ecl/ecl_kw.hpp | 2 +- .../Ert/lib/include/ert/ecl/ecl_kw_grdecl.hpp | 2 +- .../Ert/lib/include/ert/ecl/ecl_nnc_data.hpp | 2 +- .../lib/include/ert/ecl/ecl_nnc_export.hpp | 5 +- .../lib/include/ert/ecl/ecl_nnc_geometry.hpp | 2 +- .../Ert/lib/include/ert/ecl/ecl_region.hpp | 2 +- .../Ert/lib/include/ert/ecl/ecl_rft_cell.hpp | 4 +- .../Ert/lib/include/ert/ecl/ecl_rft_file.hpp | 2 +- .../Ert/lib/include/ert/ecl/ecl_rft_node.hpp | 5 +- .../Ert/lib/include/ert/ecl/ecl_rst_file.hpp | 2 +- .../Ert/lib/include/ert/ecl/ecl_rsthead.hpp | 2 +- .../Ert/lib/include/ert/ecl/ecl_smspec.hpp | 73 +- .../lib/include/ert/ecl/ecl_subsidence.hpp | 8 +- .../Ert/lib/include/ert/ecl/ecl_sum.hpp | 20 +- .../Ert/lib/include/ert/ecl/ecl_sum_data.hpp | 10 +- .../Ert/lib/include/ert/ecl/ecl_sum_index.hpp | 2 +- .../Ert/lib/include/ert/ecl/ecl_sum_tstep.hpp | 19 +- .../lib/include/ert/ecl/ecl_sum_vector.hpp | 10 +- .../Ert/lib/include/ert/ecl/ecl_type.hpp | 2 +- .../Ert/lib/include/ert/ecl/ecl_units.hpp | 2 +- .../Ert/lib/include/ert/ecl/ecl_util.hpp | 2 +- .../Ert/lib/include/ert/ecl/fault_block.hpp | 2 +- .../lib/include/ert/ecl/fault_block_layer.hpp | 2 +- ThirdParty/Ert/lib/include/ert/ecl/fortio.h | 2 +- .../Ert/lib/include/ert/ecl/grid_dims.hpp | 2 +- ThirdParty/Ert/lib/include/ert/ecl/layer.hpp | 2 +- .../Ert/lib/include/ert/ecl/nnc_info.hpp | 22 +- .../Ert/lib/include/ert/ecl/nnc_vector.hpp | 19 +- .../Ert/lib/include/ert/ecl/smspec_node.h | 129 +- .../Ert/lib/include/ert/ecl/smspec_node.hpp | 190 +- .../ert/ecl_well/well_branch_collection.hpp | 4 +- .../lib/include/ert/ecl_well/well_conn.hpp | 2 +- .../ert/ecl_well/well_conn_collection.hpp | 2 +- .../lib/include/ert/ecl_well/well_const.hpp | 2 +- .../lib/include/ert/ecl_well/well_info.hpp | 2 +- .../include/ert/ecl_well/well_rseg_loader.hpp | 2 +- .../lib/include/ert/ecl_well/well_segment.hpp | 2 +- .../ert/ecl_well/well_segment_collection.hpp | 2 +- .../lib/include/ert/ecl_well/well_state.hpp | 2 +- .../Ert/lib/include/ert/ecl_well/well_ts.hpp | 4 +- .../lib/include/ert/geometry/geo_pointset.hpp | 2 +- .../lib/include/ert/geometry/geo_polygon.hpp | 2 +- .../ert/geometry/geo_polygon_collection.hpp | 2 +- .../lib/include/ert/geometry/geo_region.hpp | 2 +- .../lib/include/ert/geometry/geo_surface.hpp | 2 +- .../Ert/lib/include/ert/geometry/geo_util.hpp | 2 +- ThirdParty/Ert/lib/include/ert/util/atomic.h | 144 +- .../Ert/lib/include/ert/util/buffer.hpp | 2 +- .../Ert/lib/include/ert/util/ecl_version.hpp | 2 +- ThirdParty/Ert/lib/include/ert/util/hash.hpp | 2 +- .../Ert/lib/include/ert/util/hash_node.hpp | 2 +- .../Ert/lib/include/ert/util/hash_sll.hpp | 2 +- .../Ert/lib/include/ert/util/lookup_table.hpp | 2 +- ThirdParty/Ert/lib/include/ert/util/mzran.hpp | 2 +- .../Ert/lib/include/ert/util/node_ctype.hpp | 2 +- .../Ert/lib/include/ert/util/node_data.hpp | 2 +- .../Ert/lib/include/ert/util/parser.hpp | 2 +- .../Ert/lib/include/ert/util/path_stack.hpp | 2 +- .../Ert/lib/include/ert/util/perm_vector.hpp | 2 +- ThirdParty/Ert/lib/include/ert/util/rng.hpp | 2 +- .../Ert/lib/include/ert/util/ssize_t.hpp | 2 +- .../Ert/lib/include/ert/util/statistics.hpp | 2 +- .../Ert/lib/include/ert/util/string_util.hpp | 2 +- .../Ert/lib/include/ert/util/stringlist.hpp | 2 +- .../Ert/lib/include/ert/util/test_util.hpp | 2 +- .../lib/include/ert/util/test_work_area.hpp | 58 +- .../Ert/lib/include/ert/util/thread_pool1.h | 2 +- .../lib/include/ert/util/time_interval.hpp | 2 +- ThirdParty/Ert/lib/include/ert/util/timer.hpp | 2 +- .../ert/util/type_vector_functions.hpp | 2 +- ThirdParty/Ert/lib/include/ert/util/util.h | 13 +- ThirdParty/Ert/lib/include/ert/util/util.hpp | 2 +- .../Ert/lib/include/ert/util/util_endian.h | 2 +- .../Ert/lib/include/ert/util/util_unlink.h | 2 +- .../Ert/lib/include/ert/util/vector.hpp | 2 +- .../Ert/lib/include/ert/util/vector_util.hpp | 52 + .../detail/ecl/ecl_grid_cache.hpp | 2 +- .../detail/ecl/ecl_sum_file_data.hpp | 2 +- ThirdParty/Ert/lib/util/buffer.cpp | 28 +- ThirdParty/Ert/lib/util/cxx_string_util.cpp | 2 +- ThirdParty/Ert/lib/util/hash.cpp | 7 +- ThirdParty/Ert/lib/util/hash_node.cpp | 2 +- ThirdParty/Ert/lib/util/hash_sll.cpp | 2 +- ThirdParty/Ert/lib/util/lookup_table.cpp | 2 +- ThirdParty/Ert/lib/util/mzran.cpp | 2 +- ThirdParty/Ert/lib/util/node_ctype.cpp | 2 +- ThirdParty/Ert/lib/util/node_data.cpp | 2 +- ThirdParty/Ert/lib/util/parser.cpp | 2 +- ThirdParty/Ert/lib/util/path.cpp | 19 +- ThirdParty/Ert/lib/util/path_stack.cpp | 2 +- ThirdParty/Ert/lib/util/perm_vector.cpp | 2 +- ThirdParty/Ert/lib/util/rng.cpp | 2 +- ThirdParty/Ert/lib/util/statistics.cpp | 2 +- ThirdParty/Ert/lib/util/string_util.cpp | 2 +- ThirdParty/Ert/lib/util/stringlist.cpp | 2 +- ThirdParty/Ert/lib/util/test_util.cpp | 3 +- ThirdParty/Ert/lib/util/test_work_area.cpp | 403 ++-- .../Ert/lib/util/tests/ert_util_addr2line.cpp | 6 +- .../tests/ert_util_alloc_file_components.cpp | 31 +- .../lib/util/tests/ert_util_approx_equal.cpp | 2 +- .../lib/util/tests/ert_util_before_after.cpp | 2 +- .../lib/util/tests/ert_util_binary_split.cpp | 8 +- .../Ert/lib/util/tests/ert_util_buffer.cpp | 3 +- .../Ert/lib/util/tests/ert_util_chdir.cpp | 15 +- .../Ert/lib/util/tests/ert_util_clamp.cpp | 2 +- .../Ert/lib/util/tests/ert_util_copy_file.cpp | 5 +- .../Ert/lib/util/tests/ert_util_cwd_test.cpp | 7 +- .../Ert/lib/util/tests/ert_util_datetime.cpp | 2 +- .../lib/util/tests/ert_util_file_readable.cpp | 2 +- .../Ert/lib/util/tests/ert_util_filename.cpp | 3 +- .../Ert/lib/util/tests/ert_util_hash_test.cpp | 2 +- .../Ert/lib/util/tests/ert_util_mkdir_p.cpp | 5 +- .../lib/util/tests/ert_util_normal_path.cpp | 8 +- .../lib/util/tests/ert_util_parent_path.cpp | 2 +- .../util/tests/ert_util_path_stack_test.cpp | 2 +- .../Ert/lib/util/tests/ert_util_ping.cpp | 2 +- .../Ert/lib/util/tests/ert_util_realpath.cpp | 2 +- .../lib/util/tests/ert_util_relpath_test.cpp | 2 +- .../Ert/lib/util/tests/ert_util_rng.cpp | 2 +- .../Ert/lib/util/tests/ert_util_spawn.cpp | 11 +- .../lib/util/tests/ert_util_split_path.cpp | 2 +- .../lib/util/tests/ert_util_sscan_test.cpp | 2 +- .../lib/util/tests/ert_util_statistics.cpp | 4 +- .../lib/util/tests/ert_util_strcat_test.cpp | 9 +- .../lib/util/tests/ert_util_string_util.cpp | 3 +- .../util/tests/ert_util_stringlist_test.cpp | 86 +- .../util/tests/ert_util_strstr_int_format.cpp | 2 +- .../tests/ert_util_type_vector_functions.cpp | 2 +- .../util/tests/ert_util_type_vector_test.cpp | 44 +- .../lib/util/tests/ert_util_unique_ptr.cpp | 2 +- .../lib/util/tests/ert_util_vector_test.cpp | 2 +- .../Ert/lib/util/tests/ert_util_work_area.cpp | 44 +- ThirdParty/Ert/lib/util/tests/test_area.cpp | 34 + .../Ert/lib/util/tests/test_thread_pool.cpp | 2 +- ThirdParty/Ert/lib/util/timer.cpp | 2 +- .../Ert/lib/util/type_vector_functions.cpp | 2 +- ThirdParty/Ert/lib/util/util.c | 80 +- ThirdParty/Ert/lib/util/util_endian.cpp | 2 +- ThirdParty/Ert/lib/util/util_lfs.c | 2 +- ThirdParty/Ert/lib/util/util_unlink.cpp | 2 +- ThirdParty/Ert/lib/util/vector.cpp | 3 +- ThirdParty/Ert/lib/util/vector_template.cpp | 71 +- ThirdParty/Ert/lib/vector_template.h.in | 4 +- ThirdParty/Ert/lib/vector_template.hpp.in | 2 +- ThirdParty/Ert/python/CMakeLists.txt | 3 + ThirdParty/Ert/python/docs/CMakeLists.txt | 60 + .../Ert/{ => python}/docs/code/index.rst | 1 - .../docs/code/python/eclipse/index.rst | 0 .../code/python/examples/eclipse/index.rst | 0 .../docs/code/python/examples/geo/index.rst | 0 .../docs/code/python/examples/index.rst | 1 - .../{ => python}/docs/code/python/index.rst | 2 - .../docs/code/python/introduction/index.rst | 0 .../code/python/packages/eclipse/index.rst | 0 .../docs/code/python/packages/index.rst | 3 - ThirdParty/Ert/{ => python}/docs/conf.py.in | 30 +- .../docs/examples/avg_pressure.py | 3 +- .../Ert/{ => python}/docs/examples/cmp_nnc.py | 10 +- .../{ => python}/docs/examples/grid_info.py | 2 +- ThirdParty/Ert/{ => python}/docs/index.rst.in | 4 +- ThirdParty/Ert/python/docs/latex/capt-of.sty | 33 + ThirdParty/Ert/python/docs/latex/fncychap.sty | 701 ++++++ ThirdParty/Ert/python/docs/latex/framed.sty | 548 +++++ .../Ert/python/docs/latex/needspace.sty | 35 + ThirdParty/Ert/python/docs/latex/tabulary.sty | 451 ++++ ThirdParty/Ert/python/docs/latex/titlesec.sty | 1349 +++++++++++ ThirdParty/Ert/python/docs/latex/upquote.sty | 40 + ThirdParty/Ert/python/docs/latex/wrapfig.sty | 598 +++++ ThirdParty/Ert/python/ecl/__init__.py | 2 +- ThirdParty/Ert/python/ecl/ecl_type.py | 2 +- ThirdParty/Ert/python/ecl/ecl_util.py | 2 +- ThirdParty/Ert/python/ecl/eclfile/__init__.py | 2 +- .../Ert/python/ecl/eclfile/ecl_3d_file.py | 2 +- ThirdParty/Ert/python/ecl/eclfile/ecl_3dkw.py | 2 +- ThirdParty/Ert/python/ecl/eclfile/ecl_file.py | 2 +- .../Ert/python/ecl/eclfile/ecl_file_view.py | 2 +- .../Ert/python/ecl/eclfile/ecl_init_file.py | 2 +- ThirdParty/Ert/python/ecl/eclfile/ecl_kw.py | 2 +- .../python/ecl/eclfile/ecl_restart_file.py | 2 +- ThirdParty/Ert/python/ecl/eclfile/fortio.py | 2 +- .../Ert/python/ecl/gravimetry/__init__.py | 2 +- .../Ert/python/ecl/gravimetry/ecl_grav.py | 2 +- .../python/ecl/gravimetry/ecl_grav_calc.py | 2 +- .../python/ecl/gravimetry/ecl_subsidence.py | 14 +- ThirdParty/Ert/python/ecl/grid/__init__.py | 2 +- ThirdParty/Ert/python/ecl/grid/cell.py | 2 +- ThirdParty/Ert/python/ecl/grid/ecl_grid.py | 2 +- .../Ert/python/ecl/grid/ecl_grid_generator.py | 2 +- ThirdParty/Ert/python/ecl/grid/ecl_region.py | 2 +- .../Ert/python/ecl/grid/faults/fault.py | 2 +- .../Ert/python/ecl/grid/faults/fault_block.py | 2 +- .../ecl/grid/faults/fault_block_collection.py | 2 +- .../ecl/grid/faults/fault_block_layer.py | 2 +- .../ecl/grid/faults/fault_collection.py | 2 +- .../Ert/python/ecl/grid/faults/fault_line.py | 2 +- .../python/ecl/grid/faults/fault_segments.py | 2 +- .../Ert/python/ecl/grid/faults/layer.py | 2 +- ThirdParty/Ert/python/ecl/rft/__init__.py | 2 +- ThirdParty/Ert/python/ecl/rft/ecl_rft.py | 47 +- ThirdParty/Ert/python/ecl/rft/ecl_rft_cell.py | 2 +- .../Ert/python/ecl/rft/well_trajectory.py | 2 +- ThirdParty/Ert/python/ecl/summary/__init__.py | 2 +- ThirdParty/Ert/python/ecl/summary/ecl_cmp.py | 2 +- ThirdParty/Ert/python/ecl/summary/ecl_npv.py | 4 +- .../Ert/python/ecl/summary/ecl_smspec_node.py | 2 +- ThirdParty/Ert/python/ecl/summary/ecl_sum.py | 75 +- .../ecl/summary/ecl_sum_keyword_vector.py | 2 +- .../Ert/python/ecl/summary/ecl_sum_tstep.py | 2 +- .../python/ecl/summary/ecl_sum_var_type.py | 2 +- .../Ert/python/ecl/summary/ecl_sum_vector.py | 21 +- .../Ert/python/ecl/util/geometry/__init__.py | 2 +- .../Ert/python/ecl/util/geometry/cpolyline.py | 2 +- .../ecl/util/geometry/cpolyline_collection.py | 2 +- .../python/ecl/util/geometry/geo_pointset.py | 2 +- .../python/ecl/util/geometry/geo_region.py | 2 +- .../Ert/python/ecl/util/geometry/surface.py | 2 +- .../Ert/python/ecl/util/test/CMakeLists.txt | 1 - .../Ert/python/ecl/util/test/__init__.py | 1 - .../ecl/util/test/ecl_mock/ecl_sum_mock.py | 2 + .../python/ecl/util/test/ert_test_context.py | 2 +- .../python/ecl/util/test/import_test_case.py | 2 +- .../python/ecl/util/test/lint_test_case.py | 2 +- .../Ert/python/ecl/util/test/temp_area.py | 81 - .../Ert/python/ecl/util/test/test_area.py | 31 +- .../Ert/python/ecl/util/test/test_run.py | 2 +- .../Ert/python/ecl/util/util/__init__.py | 4 +- .../Ert/python/ecl/util/util/arg_pack.py | 2 +- .../Ert/python/ecl/util/util/bool_vector.py | 2 +- .../Ert/python/ecl/util/util/cthread_pool.py | 2 +- ThirdParty/Ert/python/ecl/util/util/ctime.py | 2 +- .../Ert/python/ecl/util/util/double_vector.py | 2 +- ThirdParty/Ert/python/ecl/util/util/hash.py | 2 +- .../Ert/python/ecl/util/util/int_vector.py | 2 +- .../Ert/python/ecl/util/util/lookup_table.py | 2 +- ThirdParty/Ert/python/ecl/util/util/matrix.py | 230 -- ThirdParty/Ert/python/ecl/util/util/rng.py | 2 +- .../Ert/python/ecl/util/util/stringlist.py | 2 +- .../Ert/python/ecl/util/util/time_vector.py | 2 +- .../Ert/python/ecl/util/util/util_func.py | 2 +- .../python/ecl/util/util/vector_template.py | 2 +- ThirdParty/Ert/python/ecl/well/well_info.py | 2 +- ThirdParty/Ert/python/ert/test/__init__.py | 1 - ThirdParty/Ert/python/tests/__init__.py | 28 +- .../tests/bin_tests/test_summary_resample.py | 3 +- .../Ert/python/tests/ecl_tests/CMakeLists.txt | 48 +- .../Ert/python/tests/ecl_tests/test_cell.py | 2 +- .../Ert/python/tests/ecl_tests/test_debug.py | 2 +- .../tests/ecl_tests/test_deprecation.py | 3 +- .../python/tests/ecl_tests/test_ecl_3dkw.py | 2 +- .../python/tests/ecl_tests/test_ecl_cmp.py | 10 +- .../python/tests/ecl_tests/test_ecl_file.py | 2 +- ...le_statoil.py => test_ecl_file_equinor.py} | 14 +- .../tests/ecl_tests/test_ecl_init_file.py | 10 +- .../Ert/python/tests/ecl_tests/test_ecl_kw.py | 2 +- ...l_kw_statoil.py => test_ecl_kw_equinor.py} | 12 +- .../tests/ecl_tests/test_ecl_restart_file.py | 16 +- .../python/tests/ecl_tests/test_ecl_sum.py | 18 +- .../tests/ecl_tests/test_ecl_sum_vector.py | 10 +- .../python/tests/ecl_tests/test_ecl_util.py | 2 +- ...atoil_faults.py => test_equinor_faults.py} | 12 +- .../tests/ecl_tests/test_fault_blocks.py | 2 +- ...tatoil.py => test_fault_blocks_equinor.py} | 10 +- .../Ert/python/tests/ecl_tests/test_faults.py | 2 +- .../tests/ecl_tests/test_fk_user_data.py | 2 +- .../Ert/python/tests/ecl_tests/test_fortio.py | 7 +- .../python/tests/ecl_tests/test_geertsma.py | 74 +- .../Ert/python/tests/ecl_tests/test_grdecl.py | 2 +- ...decl_statoil.py => test_grdecl_equinor.py} | 12 +- .../Ert/python/tests/ecl_tests/test_grid.py | 6 +- ...t_grid_statoil.py => test_grid_equinor.py} | 20 +- ..._coarse.py => test_grid_equinor_coarse.py} | 10 +- ...toil_dual.py => test_grid_equinor_dual.py} | 18 +- ...ase.py => test_grid_equinor_large_case.py} | 10 +- .../tests/ecl_tests/test_grid_generator.py | 2 +- .../tests/ecl_tests/test_grid_pandas.py | 2 +- .../tests/ecl_tests/test_kw_function.py | 2 +- .../Ert/python/tests/ecl_tests/test_layer.py | 2 +- .../Ert/python/tests/ecl_tests/test_npv.py | 8 +- .../Ert/python/tests/ecl_tests/test_region.py | 2 +- ...gion_statoil.py => test_region_equinor.py} | 10 +- .../python/tests/ecl_tests/test_removed.py | 4 +- .../python/tests/ecl_tests/test_restart.py | 14 +- .../tests/ecl_tests/test_restart_head.py | 12 +- .../Ert/python/tests/ecl_tests/test_rft.py | 30 +- .../python/tests/ecl_tests/test_rft_cell.py | 6 +- ...est_rft_statoil.py => test_rft_equinor.py} | 26 +- .../Ert/python/tests/ecl_tests/test_sum.py | 108 +- ...est_sum_statoil.py => test_sum_equinor.py} | 43 +- .../python/tests/global_tests/test_import.py | 2 +- .../python/tests/global_tests/test_pylint.py | 2 +- .../python/tests/legacy_tests/test_test.py | 1 - .../Ert/python/tests/util_tests/test_rng.py | 1 - .../python/tests/util_tests/test_vectors.py | 2 +- .../python/tests/util_tests/test_version.py | 2 +- .../python/tests/util_tests/test_work_area.py | 84 +- .../python/tests/well_tests/CMakeLists.txt | 2 + .../python/tests/well_tests/test_ecl_well.py | 28 +- .../python/tests/well_tests/test_ecl_well2.py | 8 +- .../python/tests/well_tests/test_ecl_well3.py | 10 +- .../well_tests/test_well_missing_ICON.py | 28 + ThirdParty/Ert/python/txt-doc/README.txt | 4 + .../Ert/python/{doc => txt-doc}/devel.txt | 14 +- .../Ert/python/{doc => txt-doc}/import.txt | 0 .../Ert/python/{doc => txt-doc}/install.txt | 0 .../Ert/{docs => python/txt-doc}/tips.txt | 8 +- ThirdParty/Ert/redhat/ecl.spec | 4 +- ThirdParty/Ert/requirements.txt | 4 + ThirdParty/Ert/script/download-pr | 4 +- ThirdParty/Ert/setup.py | 4 +- ThirdParty/Ert/test-data/README.txt | 8 +- .../local/ECLIPSE/cp_simple3/SHORT.SMSPEC | Bin 0 -> 64700 bytes .../local/ECLIPSE/cp_simple3/SHORT.UNSMRY | Bin 0 -> 301636 bytes .../ECLIPSE/cp_simple3/SIMPLE_SUMMARY3.DATA | 2 +- .../ECLIPSE/well/missing-ICON/ICON0.X0027 | Bin 0 -> 9280 bytes .../ECLIPSE/well/missing-ICON/ICON1.X0027 | Bin 0 -> 38168 bytes .../test-data/local/util/latex/report_OK.tex | 2 +- .../local/util/latex/report_error.tex | 2 +- 587 files changed, 8944 insertions(+), 7854 deletions(-) create mode 100644 ThirdParty/Ert/.github/CODEOWNERS create mode 100644 ThirdParty/Ert/.gitmodules create mode 100644 ThirdParty/Ert/WINDOWS.md delete mode 100644 ThirdParty/Ert/Windows.txt rename ThirdParty/Ert/applications/ecl/{kw_extract.c => kw_extract.cpp} (98%) rename ThirdParty/Ert/applications/ecl/{sum_write.c => sum_write.cpp} (96%) rename ThirdParty/Ert/applications/ecl/{view_summary.c => view_summary.cpp} (97%) create mode 100644 ThirdParty/Ert/config.sh delete mode 100644 ThirdParty/Ert/docs/CMakeLists.txt delete mode 100644 ThirdParty/Ert/docs/code/C/index.rst delete mode 100644 ThirdParty/Ert/docs/code/python/eclipse/API/index.rst delete mode 100644 ThirdParty/Ert/docs/code/python/examples/ert/index.rst delete mode 100644 ThirdParty/Ert/docs/code/python/packages/geometry/index.rst delete mode 100644 ThirdParty/Ert/docs/code/python/packages/util/index.rst delete mode 100644 ThirdParty/Ert/docs/code/python/packages/well/index.rst delete mode 100644 ThirdParty/Ert/docs/course/config/config.ert delete mode 100644 ThirdParty/Ert/docs/course/config/jobs/SNAKE_OIL_DIFF delete mode 100644 ThirdParty/Ert/docs/course/config/jobs/SNAKE_OIL_NPV delete mode 100644 ThirdParty/Ert/docs/course/config/jobs/SNAKE_OIL_SIMULATOR delete mode 100644 ThirdParty/Ert/docs/course/config/jobs/snake_oil_diff.py delete mode 100644 ThirdParty/Ert/docs/course/config/jobs/snake_oil_npv.py delete mode 100644 ThirdParty/Ert/docs/course/config/jobs/snake_oil_simulator.py delete mode 100644 ThirdParty/Ert/docs/course/config/parameters/snake_oil_parameters.txt delete mode 100644 ThirdParty/Ert/docs/course/config/refcase/SNAKE_OIL_FIELD.SMSPEC delete mode 100644 ThirdParty/Ert/docs/course/config/refcase/SNAKE_OIL_FIELD.UNSMRY delete mode 100644 ThirdParty/Ert/docs/course/config/refcase/refcase_readme.txt delete mode 100644 ThirdParty/Ert/docs/course/config/refcase/seed.txt delete mode 100644 ThirdParty/Ert/docs/course/config/refcase/snake_oil_params.txt delete mode 100644 ThirdParty/Ert/docs/course/config/refcase/time_map.txt delete mode 100644 ThirdParty/Ert/docs/course/config/snake_oil.ert delete mode 100644 ThirdParty/Ert/docs/course/config/templates/seed_template.txt delete mode 100644 ThirdParty/Ert/docs/course/config/templates/snake_oil_template.txt delete mode 100644 ThirdParty/Ert/docs/course/ex1/ex1.txt delete mode 100644 ThirdParty/Ert/docs/course/ex1/sol1.py delete mode 100644 ThirdParty/Ert/docs/course/ex2/ex2.txt delete mode 100644 ThirdParty/Ert/docs/course/ex2/sol2.txt delete mode 100644 ThirdParty/Ert/docs/course/ex3/ex3.txt delete mode 100644 ThirdParty/Ert/docs/course/ex3/sol3.py delete mode 100644 ThirdParty/Ert/docs/course/ex4/ex4.txt delete mode 100644 ThirdParty/Ert/docs/course/ex4/sol4.py delete mode 100644 ThirdParty/Ert/docs/doxygen.cfg.in delete mode 100644 ThirdParty/Ert/docs/eclipse_restart_spe1.txt delete mode 100644 ThirdParty/Ert/docs/eclipse_restart_specification.txt delete mode 100644 ThirdParty/Ert/docs/nexus.plt delete mode 100644 ThirdParty/Ert/lib/ecl/Smspec.cpp rename ThirdParty/Ert/lib/ecl/tests/{ecl_fault_block_collection_statoil.cpp => ecl_fault_block_collection_equinor.cpp} (95%) rename ThirdParty/Ert/lib/ecl/tests/{ecl_fault_block_layer_statoil.cpp => ecl_fault_block_layer_equinor.cpp} (95%) rename ThirdParty/Ert/lib/ecl/tests/{ecl_file_statoil.cpp => ecl_file_equinor.cpp} (90%) rename ThirdParty/Ert/lib/ecl/tests/{ecl_grid_copy_statoil.cpp => ecl_grid_copy_equinor.cpp} (91%) rename ThirdParty/Ert/lib/ecl/tests/{ecl_layer_statoil.cpp => ecl_layer_equinor.cpp} (96%) rename ThirdParty/Ert/lib/ecl/tests/{ecl_nnc_data_statoil_root.cpp => ecl_nnc_data_equinor_root.cpp} (97%) create mode 100644 ThirdParty/Ert/lib/ecl/tests/ecl_nnc_export_intersect.cpp create mode 100644 ThirdParty/Ert/lib/ecl/tests/ecl_sum_restart.cpp delete mode 100644 ThirdParty/Ert/lib/ecl/tests/eclxx_smspec.cpp delete mode 100644 ThirdParty/Ert/lib/include/ert/ecl/Smspec.hpp create mode 100644 ThirdParty/Ert/lib/include/ert/util/vector_util.hpp create mode 100644 ThirdParty/Ert/lib/util/tests/test_area.cpp create mode 100644 ThirdParty/Ert/python/docs/CMakeLists.txt rename ThirdParty/Ert/{ => python}/docs/code/index.rst (90%) rename ThirdParty/Ert/{ => python}/docs/code/python/eclipse/index.rst (100%) rename ThirdParty/Ert/{ => python}/docs/code/python/examples/eclipse/index.rst (100%) rename ThirdParty/Ert/{ => python}/docs/code/python/examples/geo/index.rst (100%) rename ThirdParty/Ert/{ => python}/docs/code/python/examples/index.rst (81%) rename ThirdParty/Ert/{ => python}/docs/code/python/index.rst (54%) rename ThirdParty/Ert/{ => python}/docs/code/python/introduction/index.rst (100%) rename ThirdParty/Ert/{ => python}/docs/code/python/packages/eclipse/index.rst (100%) rename ThirdParty/Ert/{ => python}/docs/code/python/packages/index.rst (86%) rename ThirdParty/Ert/{ => python}/docs/conf.py.in (93%) rename ThirdParty/Ert/{ => python}/docs/examples/avg_pressure.py (96%) rename ThirdParty/Ert/{ => python}/docs/examples/cmp_nnc.py (69%) rename ThirdParty/Ert/{ => python}/docs/examples/grid_info.py (94%) rename ThirdParty/Ert/{ => python}/docs/index.rst.in (87%) create mode 100644 ThirdParty/Ert/python/docs/latex/capt-of.sty create mode 100644 ThirdParty/Ert/python/docs/latex/fncychap.sty create mode 100644 ThirdParty/Ert/python/docs/latex/framed.sty create mode 100644 ThirdParty/Ert/python/docs/latex/needspace.sty create mode 100644 ThirdParty/Ert/python/docs/latex/tabulary.sty create mode 100644 ThirdParty/Ert/python/docs/latex/titlesec.sty create mode 100644 ThirdParty/Ert/python/docs/latex/upquote.sty create mode 100644 ThirdParty/Ert/python/docs/latex/wrapfig.sty delete mode 100644 ThirdParty/Ert/python/ecl/util/test/temp_area.py delete mode 100644 ThirdParty/Ert/python/ecl/util/util/matrix.py rename ThirdParty/Ert/python/tests/ecl_tests/{test_ecl_file_statoil.py => test_ecl_file_equinor.py} (97%) rename ThirdParty/Ert/python/tests/ecl_tests/{test_ecl_kw_statoil.py => test_ecl_kw_equinor.py} (91%) rename ThirdParty/Ert/python/tests/ecl_tests/{test_statoil_faults.py => test_equinor_faults.py} (94%) rename ThirdParty/Ert/python/tests/ecl_tests/{test_fault_blocks_statoil.py => test_fault_blocks_equinor.py} (85%) rename ThirdParty/Ert/python/tests/ecl_tests/{test_grdecl_statoil.py => test_grdecl_equinor.py} (93%) rename ThirdParty/Ert/python/tests/ecl_tests/{test_grid_statoil.py => test_grid_equinor.py} (94%) rename ThirdParty/Ert/python/tests/ecl_tests/{test_grid_statoil_coarse.py => test_grid_equinor_coarse.py} (84%) rename ThirdParty/Ert/python/tests/ecl_tests/{test_grid_statoil_dual.py => test_grid_equinor_dual.py} (84%) rename ThirdParty/Ert/python/tests/ecl_tests/{test_grid_statoil_large_case.py => test_grid_equinor_large_case.py} (78%) rename ThirdParty/Ert/python/tests/ecl_tests/{test_region_statoil.py => test_region_equinor.py} (96%) rename ThirdParty/Ert/python/tests/ecl_tests/{test_rft_statoil.py => test_rft_equinor.py} (81%) rename ThirdParty/Ert/python/tests/ecl_tests/{test_sum_statoil.py => test_sum_equinor.py} (93%) create mode 100644 ThirdParty/Ert/python/tests/well_tests/test_well_missing_ICON.py create mode 100644 ThirdParty/Ert/python/txt-doc/README.txt rename ThirdParty/Ert/python/{doc => txt-doc}/devel.txt (99%) rename ThirdParty/Ert/python/{doc => txt-doc}/import.txt (100%) rename ThirdParty/Ert/python/{doc => txt-doc}/install.txt (100%) rename ThirdParty/Ert/{docs => python/txt-doc}/tips.txt (99%) create mode 100644 ThirdParty/Ert/test-data/local/ECLIPSE/cp_simple3/SHORT.SMSPEC create mode 100644 ThirdParty/Ert/test-data/local/ECLIPSE/cp_simple3/SHORT.UNSMRY create mode 100644 ThirdParty/Ert/test-data/local/ECLIPSE/well/missing-ICON/ICON0.X0027 create mode 100644 ThirdParty/Ert/test-data/local/ECLIPSE/well/missing-ICON/ICON1.X0027 diff --git a/ThirdParty/Ert/.github/CODEOWNERS b/ThirdParty/Ert/.github/CODEOWNERS new file mode 100644 index 0000000000..a931a3003f --- /dev/null +++ b/ThirdParty/Ert/.github/CODEOWNERS @@ -0,0 +1,2 @@ +# These owners will be the default owners for everything in the repo. +* @markusdregi @lars-petter-hauge @andreabrambilla @pgdr @jokva @xjules diff --git a/ThirdParty/Ert/.github/PULL_REQUEST_TEMPLATE.md b/ThirdParty/Ert/.github/PULL_REQUEST_TEMPLATE.md index adf85eaeb6..3ea367d2a9 100644 --- a/ThirdParty/Ert/.github/PULL_REQUEST_TEMPLATE.md +++ b/ThirdParty/Ert/.github/PULL_REQUEST_TEMPLATE.md @@ -1,10 +1,5 @@ -**Task** -_Short description of the task_ - +**Issue** +Resolves # **Approach** _Short description of the approach_ - - -**Pre un-WIP checklist** -- [ ] Statoil tests pass locally diff --git a/ThirdParty/Ert/.gitignore b/ThirdParty/Ert/.gitignore index b835bff007..b92bed604e 100644 --- a/ThirdParty/Ert/.gitignore +++ b/ThirdParty/Ert/.gitignore @@ -11,8 +11,9 @@ python/lib64 /libenkf/src/.faultlist /develbranch/libenkf/src/.faultlist /build +/temp-build /libert_util/tests/data/latex_OK.pdf -/test-data/Statoil +/test-data/Equinor /python/python/ert/ecl/ecl_local.py /GPATH /GRTAGS diff --git a/ThirdParty/Ert/.gitmodules b/ThirdParty/Ert/.gitmodules new file mode 100644 index 0000000000..347fe93043 --- /dev/null +++ b/ThirdParty/Ert/.gitmodules @@ -0,0 +1,3 @@ +[submodule "multibuild"] + path = multibuild + url = https://github.com/matthew-brett/multibuild.git diff --git a/ThirdParty/Ert/.travis.yml b/ThirdParty/Ert/.travis.yml index 6fdc81f1a6..9bef0ca2d6 100644 --- a/ThirdParty/Ert/.travis.yml +++ b/ThirdParty/Ert/.travis.yml @@ -1,82 +1,70 @@ -language: c - -compiler: - - gcc - - clang +language: python +python: + - 2.7 + - 3.6 os: - linux - - osx -osx_image: xcode7.3 -sudo: false -dist: trusty +sudo: required +services: docker env: global: - ERT_SHOW_BACKTRACE=1 - - LD_LIBRARY_PATH="$(pwd)/install/lib64" + - MB_PYTHON_VERSION=$TRAVIS_PYTHON_VERSION matrix: - - PYTHON_VERSION=2.7 TEST_SUITE="-LE SLOW" # Run all tests not labeled as slow - - PYTHON_VERSION=2.7 TEST_SUITE="-L SLOW_1" # Run all tests labeled as SLOW in group 1 - - PYTHON_VERSION=2.7 TEST_SUITE="-L SLOW_2" # Run all tests labeled as SLOW in group 2 - - PYTHON_VERSION=3.6 # Run all tests + - TEST_SUITE="-LE SLOW" # Run all tests not labeled as slow + - TEST_SUITE="-L SLOW_1" # Run all tests labeled as SLOW in group 1 + - TEST_SUITE="-L SLOW_2" # Run all tests labeled as SLOW in group 2 matrix: fast_finish: true - exclude: + include: - os: osx - compiler: gcc - - os: linux - compiler: clang + language: generic + python: 2.7 + env: + - MB_PYTHON_VERSION=2.7 + - TEST_SUITE="" + - os: osx + language: generic + python: 3.6 + env: + - MB_PYTHON_VERSION=3.6 + - TEST_SUITE="" addons: apt: - sources: - - ubuntu-toolchain-r-test packages: - liblapack-dev - - valgrind - - gcc-4.8 - - g++-4.8 - - clang - - cmake - - cmake-data +before_install: + - unset -f pushd + - unset -f popd + - source multibuild/common_utils.sh + - source multibuild/travis_steps.sh + - before_install install: - - if [[ "$CC" == "gcc" ]]; then export CXX="g++-4.8"; fi - - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then - export CONDA_OS=MacOSX; - else - export CONDA_OS=Linux; - fi - - if [[ $PYTHON_VERSION == 2.7 ]]; then - export TRAVIS_PYTHON_VERSION="2.7"; - fi - - if [[ $PYTHON_VERSION == 3.6 ]]; then - export TRAVIS_PYTHON_VERSION="3.6"; - fi - # We do this conditionally because it saves us some downloading if the version is the same. - - if [[ "$TRAVIS_PYTHON_VERSION" == "2.7" ]]; then - wget https://repo.continuum.io/miniconda/Miniconda2-latest-${CONDA_OS}-x86_64.sh -O miniconda.sh; - else - wget https://repo.continuum.io/miniconda/Miniconda3-4.4.10-${CONDA_OS}-x86_64.sh -O miniconda.sh; - fi - - bash miniconda.sh -b -p $HOME/miniconda - - export CONDA_HOME="$HOME/miniconda" - - export PATH="$CONDA_HOME/bin:$PATH" - - hash -r - - python --version - pip install -r requirements.txt - - conda config --set always_yes yes --set changeps1 no - - conda update -q conda - - conda info -a # Useful for debugging any issues with conda - - wget https://raw.githubusercontent.com/Statoil/ert/master/travis/install_python_packages.py - - python install_python_packages.py - -before_script: - - wget https://raw.githubusercontent.com/Statoil/ert/master/travis/build_total.py script: - - python build_total.py ecl ${TEST_SUITE} + - mkdir build + - pushd build + - cmake .. -DBUILD_TESTS=ON + -DENABLE_PYTHON=ON + -DINSTALL_CWRAP=OFF + -DBUILD_APPLICATIONS=ON + -DINSTALL_ERT_LEGACY=ON + -DERT_USE_OPENMP=ON + -DCMAKE_C_FLAGS='-Werror=all' + -DCMAKE_CXX_FLAGS='-Werror -Wno-unused-result' + - make + - sudo make install + - which python + - export PYTHONPATH="/usr/local/lib/python$MB_PYTHON_VERSION/site-packages:/usr/local/lib/python$MB_PYTHON_VERSION/dist-packages:$PYTHONPATH" + - python -c "import sys; print('\n'.join(sys.path))" + - set -e; python -c "import ecl"; set +e + - ctest --output-on-failure $TEST_SUITE + - popd diff --git a/ThirdParty/Ert/CMakeLists.txt b/ThirdParty/Ert/CMakeLists.txt index 5e2e1e42b4..36417d18e7 100644 --- a/ThirdParty/Ert/CMakeLists.txt +++ b/ThirdParty/Ert/CMakeLists.txt @@ -11,7 +11,7 @@ endif() #----------------------------------------------------------------- set( ECL_VERSION_MAJOR 2 ) # Remember to update release notes whenever -set( ECL_VERSION_MINOR 3 ) # you change the ERT_VERSION_MINOR or MAJOR +set( ECL_VERSION_MINOR 4 ) # you change the ERT_VERSION_MINOR or MAJOR set( ECL_VERSION_MICRO git ) # with "new in Ert Version X.X.X"! # If the micro version is not integer, that should be interpreted as a @@ -51,23 +51,22 @@ option( ENABLE_PYTHON "Build and install the Python wrappers" option( BUILD_SHARED_LIBS "Build shared libraries" ON ) option( ERT_USE_OPENMP "Use OpenMP" OFF ) option( RST_DOC "Build RST documentation" OFF) -option( ERT_BUILD_CXX "Build some CXX wrappers" ON) option( USE_RPATH "Don't strip RPATH from libraries and binaries" OFF) option( INSTALL_ERT_LEGACY "Add ert legacy wrappers" OFF) -set(STATOIL_TESTDATA_ROOT "" CACHE PATH "Root to Statoil internal testdata") -if (EXISTS ${STATOIL_TESTDATA_ROOT}) - set( LINK "${CMAKE_CURRENT_SOURCE_DIR}/test-data/Statoil" ) +set(EQUINOR_TESTDATA_ROOT "" CACHE PATH "Root to Equinor internal testdata") +if (EXISTS ${EQUINOR_TESTDATA_ROOT}) + set( LINK "${CMAKE_CURRENT_SOURCE_DIR}/test-data/Equinor" ) if (EXISTS ${LINK}) EXECUTE_PROCESS( COMMAND ${CMAKE_COMMAND} -E remove "${LINK}") endif() - EXECUTE_PROCESS( COMMAND ${CMAKE_COMMAND} -E create_symlink "${STATOIL_TESTDATA_ROOT}" "${LINK}") - message(STATUS "Linking testdata: ${LINK} -> ${STATOIL_TESTDATA_ROOT}") + EXECUTE_PROCESS( COMMAND ${CMAKE_COMMAND} -E create_symlink "${EQUINOR_TESTDATA_ROOT}" "${LINK}") + message(STATUS "Linking testdata: ${LINK} -> ${EQUINOR_TESTDATA_ROOT}") - set(_statoil_test_data ${CMAKE_SOURCE_DIR}/test-data/Statoil) - set(_eclpath ${_statoil_test_data}/ECLIPSE) - set(_geopath ${_statoil_test_data}/Geometry) + set(_equinor_test_data ${CMAKE_SOURCE_DIR}/test-data/Equinor) + set(_eclpath ${_equinor_test_data}/ECLIPSE) + set(_geopath ${_equinor_test_data}/Geometry) endif() @@ -116,7 +115,7 @@ endif() # Treat warnings as errors if not on Windows if (NOT ERT_WINDOWS) set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -Wall -Wno-unknown-pragmas ") - set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-unknown-pragmas -Wno-unused-result -Wno-unused-parameter" ) + set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wfatal-errors -Wall -Wno-unknown-pragmas -Wno-unused-result -Wno-unused-parameter" ) endif() if (MSVC) @@ -339,11 +338,6 @@ if (ENABLE_PYTHON) # fails in the python/CMakeLists.txt file the ENABLE_PYTHON # will be set to OFF. add_subdirectory( python ) - - if(RST_DOC) - add_subdirectory( docs ) - endif() - endif() if (ENABLE_PYTHON) @@ -352,9 +346,6 @@ if (ENABLE_PYTHON) endif() endif() -if (INSTALL_ERT) - install(EXPORT ecl-config DESTINATION share/cmake/ecl) -endif() - +install(EXPORT ecl-config DESTINATION share/cmake/ecl) export(TARGETS ecl FILE eclConfig.cmake) export(PACKAGE ecl) diff --git a/ThirdParty/Ert/README.md b/ThirdParty/Ert/README.md index 07d72dec3a..37cb5a42dd 100644 --- a/ThirdParty/Ert/README.md +++ b/ThirdParty/Ert/README.md @@ -1,4 +1,4 @@ -# libecl [![Build Status](https://travis-ci.org/Statoil/libecl.svg?branch=master)](https://travis-ci.org/Statoil/libecl) +# libecl [![Build Status](https://travis-ci.org/Equinor/libecl.svg?branch=master)](https://travis-ci.org/Equinor/libecl) *libecl* is a package for reading and writing the result files from @@ -11,7 +11,7 @@ is a portability layer which ensures that most of the functionality is available on *Windows*. The main functionality is written in C/C++, and should typically be linked in in other compiled programs. *libecl* was initially developed as part of the [Ensemble Reservoir -Tool](http://github.com/Statoil/ert), other applications using +Tool](http://github.com/Equinor/ert), other applications using *libecl* are the reservoir simulator flow and Resinsight from the [OPM project](http://github.com/OPM/). @@ -30,7 +30,7 @@ configured with `-DCMAKE_INSTALL_PREFIX=/path/to/install`. *libecl* uses CMake as build system: ```bash -git clone https://github.com/Statoil/libecl +git clone https://github.com/Equinor/libecl cd libecl mkdir build cd build @@ -50,7 +50,7 @@ rudimentary "build system" which does a basic Python syntax check and configures files to correctly set up the interaction between the Python classes and the shared libraries built from the C code: ```bash -git clone https://github.com/Statoil/libecl +git clone https://github.com/Equinor/libecl cd libecl sudo pip install -r requirements.txt mkdir build @@ -78,5 +78,6 @@ fopt = summary.numpy_vector("FOPT") ``` +The installation with Python enabled is described in a [YouTube video](https://www.youtube.com/watch?v=Qqy1vA1PSk8) by Carl Fredrik Berg. [1]: The exact paths here will depend on your system and Python version. The example given is for a RedHat system with Python version 2.7. diff --git a/ThirdParty/Ert/WINDOWS.md b/ThirdParty/Ert/WINDOWS.md new file mode 100644 index 0000000000..2bfb46b95b --- /dev/null +++ b/ThirdParty/Ert/WINDOWS.md @@ -0,0 +1,27 @@ +# Compiling and Installing **_libecl_** on Windows + +## Prerequisits: +* Python 2.7 or 3.x https://www.python.org/ or https://anaconda.org/ +* Microsoft Visual Studio https://visualstudio.microsoft.com/downloads/ +* Local copy of **_libecl_** + +## Instructions: +1. Download or clone the **_libecl_** Github repository to your local disk. + +2. Python 2.7 or 3.x installation + - Download a python instalation or a python environment solution such as Anaconda. + +3. Download and install Microsoft Visual Studio . At a minimum **_libecl_** requires the VS Studio packages for cmake, msbuild, c and c++ compilers (CL.exe). + +4. Open a MSVC command prompt such as _x64 Native Tools Command Prompt for VS 2017_ from your start menu. In the open prompt, navigate to the **_libecl_** source directory you created in step 1. Use the Python package manager **pip** to install **_libecl_** requirements via `pip install -r requirements.txt`. If Python is not accessible from the prompt it may be necessary to add the Python environment location to your system path variable `PATH`. + +5. Execute the build commands with the desired CMAKE parameters from `README.md`. The cmake generator can be _`NMake Makefiles`_ , _`Ninja`_ or an appropriate version of _`MSVC`_. For the availble options type `cmake -G` in the MSVC command prompt. + + An example build and install is provided below where %VARIABLE% are user defined directory paths: +~~~~ + cmake -G "Visual Studio 15 2017 Win64" -DCMAKE_INSTALL_PREFIX=%INSTALLPATH% -DBUILD_SHARED_LIBS="ON" -DENABLE_PYTHON="ON" -DCMAKE_BUILD_TYPE="Release" %SOURCEPATH% + cmake --build %BUILDPATH% --config Release --target install +~~~~ +6. For **_libecl_** to be accessible in Python the `%INSTALLPATH%\lib\pythonX.Y\site-package` and Python subdirectories must be added to the `PATH` and `PYTHONPATH` variables. Where `pythonx.y` is the current Python version _e.g._ (`python2.7`, `python3.6` _etc._) . + +8. Open a Python interactive session and run `import ecl` to check that the install and paths are now set. \ No newline at end of file diff --git a/ThirdParty/Ert/Windows.txt b/ThirdParty/Ert/Windows.txt deleted file mode 100644 index 7eda76b091..0000000000 --- a/ThirdParty/Ert/Windows.txt +++ /dev/null @@ -1,90 +0,0 @@ -Preparations: -------------- - -1. Install the CMake build system from www.cmake.org - -2. Install the MinGW and MSYS packages from www.mingw.org - this a - collection of gnu tools built for windows. Observe that these tools - behave like they do on linux, but they are native windows - applications and the compilers produce native windows binaries, not - like Cygwin which is based on a portability layer. - - Make sure to install at least the C and Fortran compilers. - -3. Install lapack; download and install instructions can be found on - http://icl.cs.utk.edu/lapack-for-windows/ The text says that you - will need the Intel Fortran compiler, but the Fortran compiler from - MinGW works fine. The distribution contains a cmake CMakeLists.txt - file, and build with Cmake is easy altough time consuming. - - To make sure the system can find your libraries you should update - the windows PATH variable to include the location of your - libblas.dll and liblapack.dll files; if you fail to do this CMake - will fail to generate a valid set of makefiles for building libutil - and libecl. - - -Building libecl / libutil -------------------------- - -1. Go to the root directory of the ert distribution and create a - directory to hold the files created by the build - - e.g. 'tmp-build'. - -2. Open the cmake gui and give the path to the source (i.e. the root - of the ert distribution) and the path to the build directory. - -3. Press the [Configure] button and select the "MSys Makefiles" - option. Cmake will inspect your system and set build configuration - variables accordingly. Cmake will fail with a beep and large red - warnings. Scroll down to the variables: - - USE_LSF - USE_PTHREAD - USE_ZLIB - - and uncheck them. In addition you might want to modify some other - variables? Press the [Configure] button again, and then finally the - [Generate] button to create makefiles. - -4. Start up the MSys shell, go to the build directory, - e.g. 'tmp-build', and type: - - make ; make install - - :-) - - -Using from VisualStudio ------------------------ -The ERT code itself can unfortunately not be compiled with the -VisualStudio C++ compiler, however you can link against the ert -libraries. In that case you will need the dummy header file -VisualStudio/stdbool.h - - - -About the portabaility and features ------------------------------------ - -The libecl library is virtually unmodified for compiling on windows, -but the libutil library (in particular the util.c file) has quite many - - #ifdef HAVE_FEATUREXX - - #endif - -codeblocks. The symbols HAVE_FEATUREXX are defined during the CMake -configure process. The system inspection is linux centric in the sense -that the features it is checked for are mostly present/defined on -linux. If FEATUREXX is not present it is sometimes completely ignore, -e.g. pthreads, or a windows alternative is compiled in. In the case of -windows alternative it is just assumed that the feature in question is -present on the other (i.e. Windows) platform. - - - - - - - diff --git a/ThirdParty/Ert/applications/CMakeLists.txt b/ThirdParty/Ert/applications/CMakeLists.txt index d2a2ed6e8c..37b624e75f 100644 --- a/ThirdParty/Ert/applications/CMakeLists.txt +++ b/ThirdParty/Ert/applications/CMakeLists.txt @@ -1,10 +1,10 @@ project(libecl-applications) if (BUILD_APPLICATIONS) - add_executable(sum_write ecl/sum_write.c) + add_executable(sum_write ecl/sum_write.cpp) add_executable(make_grid ecl/make_grid.c) add_executable(grdecl_grid ecl/grdecl_grid.c) - add_executable(summary ecl/view_summary.c) + add_executable(summary ecl/view_summary.cpp) target_link_libraries(sum_write ecl) target_link_libraries(make_grid ecl) target_link_libraries(grdecl_grid ecl) @@ -13,16 +13,16 @@ if (BUILD_APPLICATIONS) list(APPEND apps make_grid grdecl_grid summary) - foreach (app ecl_pack - ecl_unpack - kw_extract - grid_info - grid_dump - grid_dump_ascii - select_test - load_test + foreach (app ecl_pack.c + ecl_unpack.c + kw_extract.cpp + grid_info.c + grid_dump.c + grid_dump_ascii.c + select_test.c + load_test.c ) - add_executable(${app} ecl/${app}.c) + add_executable(${app} ecl/${app}) target_link_libraries(${app} ecl) list(APPEND apps ${app}) if (ERT_LINUX) @@ -71,7 +71,7 @@ if (BUILD_APPLICATIONS) endif() if (BUILD_ECL_SUMMARY) - add_executable(ecl_summary ecl/view_summary.c) + add_executable(ecl_summary ecl/view_summary.cpp) target_link_libraries(ecl_summary ecl) list(APPEND apps ecl_summary) diff --git a/ThirdParty/Ert/applications/ecl/convert.c b/ThirdParty/Ert/applications/ecl/convert.c index 104a432b3f..f593c283f6 100644 --- a/ThirdParty/Ert/applications/ecl/convert.c +++ b/ThirdParty/Ert/applications/ecl/convert.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'convert.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/applications/ecl/ecl_pack.c b/ThirdParty/Ert/applications/ecl/ecl_pack.c index 9cd98fc5a3..337a327577 100644 --- a/ThirdParty/Ert/applications/ecl/ecl_pack.c +++ b/ThirdParty/Ert/applications/ecl/ecl_pack.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'ecl_pack.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/applications/ecl/ecl_quantile.c b/ThirdParty/Ert/applications/ecl/ecl_quantile.c index e98ea5d1e6..116006eef5 100644 --- a/ThirdParty/Ert/applications/ecl/ecl_quantile.c +++ b/ThirdParty/Ert/applications/ecl/ecl_quantile.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'ecl_quantile.c' is part of ERT - Ensemble based Reservoir Tool. @@ -812,7 +812,6 @@ void usage() { printf("All filenames in the configuration file will be interpreted relative to\n"); printf("the location of the configuration file, i.e. irrespective of the current\n"); printf("working directory when invoking the ecl_quantile program.\n\n"); - printf("ecl_quantile is written by Joakim Hove / joaho@statoil.com / 92 68 57 04.\n"); exit(0); } diff --git a/ThirdParty/Ert/applications/ecl/ecl_unpack.c b/ThirdParty/Ert/applications/ecl/ecl_unpack.c index fa08a9042f..87f9c2dae3 100644 --- a/ThirdParty/Ert/applications/ecl/ecl_unpack.c +++ b/ThirdParty/Ert/applications/ecl/ecl_unpack.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'ecl_unpack.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/applications/ecl/grdecl_grid.c b/ThirdParty/Ert/applications/ecl/grdecl_grid.c index f961118ef6..672bba80a1 100644 --- a/ThirdParty/Ert/applications/ecl/grdecl_grid.c +++ b/ThirdParty/Ert/applications/ecl/grdecl_grid.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Statoil ASA, Norway. + Copyright (C) 2012 Equinor ASA, Norway. The file 'grdecl_grid.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/applications/ecl/grdecl_test.c b/ThirdParty/Ert/applications/ecl/grdecl_test.c index 8e73a7db4c..2646a13083 100644 --- a/ThirdParty/Ert/applications/ecl/grdecl_test.c +++ b/ThirdParty/Ert/applications/ecl/grdecl_test.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Statoil ASA, Norway. + Copyright (C) 2012 Equinor ASA, Norway. The file 'grdecl_test.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/applications/ecl/grid_dump.c b/ThirdParty/Ert/applications/ecl/grid_dump.c index 8d405a2323..592d328ba1 100644 --- a/ThirdParty/Ert/applications/ecl/grid_dump.c +++ b/ThirdParty/Ert/applications/ecl/grid_dump.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'grid_info.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/applications/ecl/grid_dump_ascii.c b/ThirdParty/Ert/applications/ecl/grid_dump_ascii.c index e9e05964be..c639d7bc1a 100644 --- a/ThirdParty/Ert/applications/ecl/grid_dump_ascii.c +++ b/ThirdParty/Ert/applications/ecl/grid_dump_ascii.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Statoil ASA, Norway. + Copyright (C) 2012 Equinor ASA, Norway. The file 'grid_dump_ascii.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/applications/ecl/grid_info.c b/ThirdParty/Ert/applications/ecl/grid_info.c index 9754a109f0..c191e77cee 100644 --- a/ThirdParty/Ert/applications/ecl/grid_info.c +++ b/ThirdParty/Ert/applications/ecl/grid_info.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'grid_info.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/applications/ecl/grid_layer.c b/ThirdParty/Ert/applications/ecl/grid_layer.c index 05b5d2875e..8f6a11189d 100644 --- a/ThirdParty/Ert/applications/ecl/grid_layer.c +++ b/ThirdParty/Ert/applications/ecl/grid_layer.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'grid_layer.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/applications/ecl/key_list.c b/ThirdParty/Ert/applications/ecl/key_list.c index e1ab0bb831..6dbb6bb419 100644 --- a/ThirdParty/Ert/applications/ecl/key_list.c +++ b/ThirdParty/Ert/applications/ecl/key_list.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'key_list.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/applications/ecl/kw_extract.c b/ThirdParty/Ert/applications/ecl/kw_extract.cpp similarity index 98% rename from ThirdParty/Ert/applications/ecl/kw_extract.c rename to ThirdParty/Ert/applications/ecl/kw_extract.cpp index 9247ff073a..1b7db47b62 100644 --- a/ThirdParty/Ert/applications/ecl/kw_extract.c +++ b/ThirdParty/Ert/applications/ecl/kw_extract.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'kw_extract.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/applications/ecl/kw_list.c b/ThirdParty/Ert/applications/ecl/kw_list.c index 482c3c096c..7f159cfda0 100644 --- a/ThirdParty/Ert/applications/ecl/kw_list.c +++ b/ThirdParty/Ert/applications/ecl/kw_list.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'kw_list.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/applications/ecl/load_test.c b/ThirdParty/Ert/applications/ecl/load_test.c index 9a02887de2..669a8a90a1 100644 --- a/ThirdParty/Ert/applications/ecl/load_test.c +++ b/ThirdParty/Ert/applications/ecl/load_test.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'load_test.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/applications/ecl/make_grid.c b/ThirdParty/Ert/applications/ecl/make_grid.c index f3c7adfd4e..636608cf7b 100644 --- a/ThirdParty/Ert/applications/ecl/make_grid.c +++ b/ThirdParty/Ert/applications/ecl/make_grid.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Statoil ASA, Norway. + Copyright (C) 2012 Equinor ASA, Norway. The file 'make_grid.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/applications/ecl/run_gravity.c b/ThirdParty/Ert/applications/ecl/run_gravity.c index f2ea723750..d0b3c17fca 100644 --- a/ThirdParty/Ert/applications/ecl/run_gravity.c +++ b/ThirdParty/Ert/applications/ecl/run_gravity.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'run_gravity.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/applications/ecl/select_test.c b/ThirdParty/Ert/applications/ecl/select_test.c index 61acc18034..f23021f483 100644 --- a/ThirdParty/Ert/applications/ecl/select_test.c +++ b/ThirdParty/Ert/applications/ecl/select_test.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Statoil ASA, Norway. + Copyright (C) 2012 Equinor ASA, Norway. The file 'select_test.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/applications/ecl/sum_write.c b/ThirdParty/Ert/applications/ecl/sum_write.cpp similarity index 96% rename from ThirdParty/Ert/applications/ecl/sum_write.c rename to ThirdParty/Ert/applications/ecl/sum_write.cpp index 77234e4800..3bdf552d56 100644 --- a/ThirdParty/Ert/applications/ecl/sum_write.c +++ b/ThirdParty/Ert/applications/ecl/sum_write.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Statoil ASA, Norway. + Copyright (C) 2012 Equinor ASA, Norway. The file 'sum_write' is part of ERT - Ensemble based Reservoir Tool. ERT is free software: you can redistribute it and/or modify @@ -223,7 +223,7 @@ int main( int argc , char ** argv) { /* The return value from the ecl_sum_add_var() function is an - smspec_node_type instance (implemented in file smspec_node.c); + ecl::smspec_node instance (implemented in file smspec_node.c); which is essentially a struct holding header information about this varible. There are several options on how to handle the return value from the ecl_sum_add_var() function; which affect how @@ -243,8 +243,8 @@ int main( int argc , char ** argv) { */ - smspec_node_type * wwct_wellx = ecl_sum_add_var( ecl_sum , "WWCT" , NULL , 0 , "(1)" , 0.0); - smspec_node_type * wopr_wellx = ecl_sum_add_var( ecl_sum , "WOPR" , NULL , 0 , "Barrels" , 0.0); + const ecl::smspec_node * wwct_wellx = ecl_sum_add_var( ecl_sum , "WWCT" , NULL , 0 , "(1)" , 0.0); + const ecl::smspec_node * wopr_wellx = ecl_sum_add_var( ecl_sum , "WOPR" , NULL , 0 , "Barrels" , 0.0); { @@ -297,8 +297,8 @@ int main( int argc , char ** argv) { We can use the smspec_node value from the ecl_sum_add_var() function directly: */ - ecl_sum_tstep_set_from_node( tstep , wwct_wellx , sim_days ); - ecl_sum_tstep_set_from_node( tstep, wopr_wellx, sim_days * 100); + ecl_sum_tstep_set_from_node( tstep , *wwct_wellx , sim_days ); + ecl_sum_tstep_set_from_node( tstep, *wopr_wellx, sim_days * 100); } } } diff --git a/ThirdParty/Ert/applications/ecl/summary2csv2.c b/ThirdParty/Ert/applications/ecl/summary2csv2.c index 7655f1f02b..6ffae8c815 100644 --- a/ThirdParty/Ert/applications/ecl/summary2csv2.c +++ b/ThirdParty/Ert/applications/ecl/summary2csv2.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'summary2csv2.c' is part of ERT - Ensemble based Reservoir Tool. ERT is free software: you can redistribute it and/or modify diff --git a/ThirdParty/Ert/applications/ecl/view_restart.c b/ThirdParty/Ert/applications/ecl/view_restart.c index 7b18b622c6..16217677d5 100644 --- a/ThirdParty/Ert/applications/ecl/view_restart.c +++ b/ThirdParty/Ert/applications/ecl/view_restart.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'view_restart.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/applications/ecl/view_rft.c b/ThirdParty/Ert/applications/ecl/view_rft.c index 358c8bf2d5..ffe43131da 100644 --- a/ThirdParty/Ert/applications/ecl/view_rft.c +++ b/ThirdParty/Ert/applications/ecl/view_rft.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'view_rft.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/applications/ecl/view_summary.c b/ThirdParty/Ert/applications/ecl/view_summary.cpp similarity index 97% rename from ThirdParty/Ert/applications/ecl/view_summary.c rename to ThirdParty/Ert/applications/ecl/view_summary.cpp index 986f390db4..e139b44563 100644 --- a/ThirdParty/Ert/applications/ecl/view_summary.c +++ b/ThirdParty/Ert/applications/ecl/view_summary.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'view_summary.c' is part of ERT - Ensemble based Reservoir Tool. ERT is free software: you can redistribute it and/or modify @@ -110,10 +110,7 @@ void print_help_and_exit() { printf("\n"); printf("* If the extension corresponds to a unified file, summary.x will\n"); printf(" only look for unified files.\n"); - printf("\n"); - printf("\n"); - printf("Contact Joakim Hove / joaho@statoil.com / 92 68 57 04 for bugs\n"); - printf("and feature requests.\n"); + printf("\n"); exit(1); } diff --git a/ThirdParty/Ert/applications/ecl/vprofile.c b/ThirdParty/Ert/applications/ecl/vprofile.c index e6edb40b55..5264fcca97 100644 --- a/ThirdParty/Ert/applications/ecl/vprofile.c +++ b/ThirdParty/Ert/applications/ecl/vprofile.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'vprofile.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/applications/man/man1/ecl_summary.1 b/ThirdParty/Ert/applications/man/man1/ecl_summary.1 index 66b5ad9351..f881dc0efc 100644 --- a/ThirdParty/Ert/applications/man/man1/ecl_summary.1 +++ b/ThirdParty/Ert/applications/man/man1/ecl_summary.1 @@ -99,9 +99,6 @@ will only look for unformatted files. .IP only look for unified files. .PP -Contact Joakim Hove / joaho@statoil.com / 92 68 57 04 for bugs -and feature requests. -.PP The ecl_summary program is used to quickly extract summary vectors from ECLIPSE summary files. The program is invoked as: .PP @@ -183,6 +180,6 @@ will only look for unformatted files. .IP only look for unified files. .PP -Contact Joakim Hove / joaho@statoil.com / 92 68 57 04 for bugs +Contact Joakim Hove / joaho@equinor.com / 92 68 57 04 for bugs and feature requests. diff --git a/ThirdParty/Ert/applications/well/ri_well_test.c b/ThirdParty/Ert/applications/well/ri_well_test.c index 66e4b8d830..cc46160617 100644 --- a/ThirdParty/Ert/applications/well/ri_well_test.c +++ b/ThirdParty/Ert/applications/well/ri_well_test.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'well_CF_dump.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/applications/well/segment_info.c b/ThirdParty/Ert/applications/well/segment_info.c index 2a445c2637..0d6e403273 100644 --- a/ThirdParty/Ert/applications/well/segment_info.c +++ b/ThirdParty/Ert/applications/well/segment_info.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'segment_info.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/applications/well/well_CF_dump.c b/ThirdParty/Ert/applications/well/well_CF_dump.c index 433aab6559..1fe2749cdc 100644 --- a/ThirdParty/Ert/applications/well/well_CF_dump.c +++ b/ThirdParty/Ert/applications/well/well_CF_dump.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'well_CF_dump.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/appveyor.yml b/ThirdParty/Ert/appveyor.yml index 73887395f0..c1dddec4e4 100644 --- a/ThirdParty/Ert/appveyor.yml +++ b/ThirdParty/Ert/appveyor.yml @@ -19,7 +19,6 @@ build_script: - cmake %W64% -DBUILD_SHARED_LIBS=ON -DCMAKE_BUILD_TYPE=Release -DENABLE_PYTHON=ON - -DERT_BUILD_CXX=OFF -DBUILD_APPLICATIONS=ON - cmake --build . --config %configuration% --target install diff --git a/ThirdParty/Ert/bin/summary_resample b/ThirdParty/Ert/bin/summary_resample index eb6cf5521f..1a08006d2f 100644 --- a/ThirdParty/Ert/bin/summary_resample +++ b/ThirdParty/Ert/bin/summary_resample @@ -11,6 +11,7 @@ parser.add_argument("input_case", metavar="input_case", type=str) parser.add_argument("output_case", metavar="output_case", type=str) parser.add_argument("--num-timestep", type=int, default=50) parser.add_argument("--refcase", metavar="refcase", type=str) +parser.add_argument("--extrapolation", action="store_true") args = parser.parse_args() input_case = EclSum(args.input_case) @@ -23,5 +24,8 @@ else: end_time = input_case.get_end_time() time_points = TimeVector.create_linear(CTime(start_time), CTime(end_time), args.num_timestep) -output_case = input_case.resample(args.output_case, time_points) +output_case = input_case.resample(args.output_case, + time_points, + lower_extrapolation=args.extrapolation, + upper_extrapolation=args.extrapolation) output_case.fwrite( ) diff --git a/ThirdParty/Ert/config.sh b/ThirdParty/Ert/config.sh new file mode 100644 index 0000000000..e69de29bb2 diff --git a/ThirdParty/Ert/debian/README.Debian b/ThirdParty/Ert/debian/README.Debian index ce79dec2d5..4660ad0d8e 100644 --- a/ThirdParty/Ert/debian/README.Debian +++ b/ThirdParty/Ert/debian/README.Debian @@ -7,7 +7,3 @@ working with ECLIPSE output files. The package contains functionality for reading, and partly writing, ECLIPSE INIT/GRID/EGRID/RFT and summary and restart files. There is also some functionality for working with .grdecl formatted ECLIPSE input files. - - -- Joakim Hove Wed, 23 Jan 2013 13:41:00 +0100 - - -- Arne Morten Kvarving Wed, 16 Jan 2013 11:21:17 +0100 diff --git a/ThirdParty/Ert/debian/changelog b/ThirdParty/Ert/debian/changelog index f12cdfca3a..71b218f1f9 100644 --- a/ThirdParty/Ert/debian/changelog +++ b/ThirdParty/Ert/debian/changelog @@ -1,4 +1,4 @@ -ecl (2018.10-rfinal-1~xenial) xenial; urgency=low +ecl (2018.10-rc1-1~xenial) xenial; urgency=low * New release diff --git a/ThirdParty/Ert/debian/copyright b/ThirdParty/Ert/debian/copyright index a8797ba46b..94d51ad9e4 100644 --- a/ThirdParty/Ert/debian/copyright +++ b/ThirdParty/Ert/debian/copyright @@ -3,7 +3,7 @@ Upstream-Name: libert.ecl Source: https://github.com/Ensembles/ert Files: * -Copyright: 2013 Statoil +Copyright: 2013 Equinor License: GPL-3+ This package is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/ThirdParty/Ert/docs/CMakeLists.txt b/ThirdParty/Ert/docs/CMakeLists.txt deleted file mode 100644 index 833ce3a56e..0000000000 --- a/ThirdParty/Ert/docs/CMakeLists.txt +++ /dev/null @@ -1,38 +0,0 @@ -find_package(Sphinx REQUIRED) -if (SPHINX_FOUND) - set( ERT_DOC_EXTERNAL_ROOT "" CACHE PATH "Path to site local ERT documentation") - - file(MAKE_DIRECTORY "${PROJECT_BINARY_DIR}/doc-src") - file(MAKE_DIRECTORY "${PROJECT_BINARY_DIR}/doc-src/_static") - EXECUTE_PROCESS( COMMAND ${CMAKE_COMMAND} -E create_symlink "${CMAKE_CURRENT_SOURCE_DIR}/user" "${PROJECT_BINARY_DIR}/doc-src/user") - - if (ERT_DOC_EXTERNAL_ROOT) - EXECUTE_PROCESS( COMMAND ${CMAKE_COMMAND} -E create_symlink "${ERT_DOC_EXTERNAL_ROOT}" "${PROJECT_BINARY_DIR}/doc-src/external-doc") - message(STATUS "Adding documentation link ${PROJECT_BINARY_DIR}/doc-src/external-doc -> ${ERT_DOC_EXTERNAL_ROOT}") - set( ERT_DOC_LINK external-doc/index ) - else() - set( ERT_DOC_LINK "" ) - endif() - - configure_file(index.rst.in ${PROJECT_BINARY_DIR}/doc-src/index.rst) - configure_file(conf.py.in ${PROJECT_BINARY_DIR}/doc-src/conf.py) - - if (ENABLE_PYTHON) - add_custom_target(api-doc ALL - COMMAND ${CMAKE_COMMAND} -E create_symlink "${CMAKE_CURRENT_SOURCE_DIR}/code" "${PROJECT_BINARY_DIR}/doc-src/code" - COMMAND sphinx-apidoc -e -o doc-src/API/python/ecl ${PROJECT_BINARY_DIR}/${PYTHON_INSTALL_PREFIX} - DEPENDS ecl - WORKING_DIRECTORY ${PROJECT_BINARY_DIR}) - endif() - - add_custom_target(rst-doc ALL - COMMAND sphinx-build -b html -d doc-src/doctrees doc-src documentation/rst - WORKING_DIRECTORY ${PROJECT_BINARY_DIR} - DEPENDS api-doc - ) - -else() - message(STATUS "Sphinx documentation tool not found - documentation not generated") -endif() - -INSTALL( DIRECTORY ${PROJECT_BINARY_DIR}/documentation DESTINATION ${CMAKE_INSTALL_PREFIX} ) diff --git a/ThirdParty/Ert/docs/code/C/index.rst b/ThirdParty/Ert/docs/code/C/index.rst deleted file mode 100644 index 60f6a764b1..0000000000 --- a/ThirdParty/Ert/docs/code/C/index.rst +++ /dev/null @@ -1,4 +0,0 @@ -Low level C libraries -===================== - -How to use the C libraries diff --git a/ThirdParty/Ert/docs/code/python/eclipse/API/index.rst b/ThirdParty/Ert/docs/code/python/eclipse/API/index.rst deleted file mode 100644 index 4e61a4fb95..0000000000 --- a/ThirdParty/Ert/docs/code/python/eclipse/API/index.rst +++ /dev/null @@ -1,9 +0,0 @@ -The ert Python API -================== - -.. toctree:: - :maxdepth: 2 - - ../../API/python/ert - ../../API/python/ert_gui - diff --git a/ThirdParty/Ert/docs/code/python/examples/ert/index.rst b/ThirdParty/Ert/docs/code/python/examples/ert/index.rst deleted file mode 100644 index f7a37bfe3d..0000000000 --- a/ThirdParty/Ert/docs/code/python/examples/ert/index.rst +++ /dev/null @@ -1,3 +0,0 @@ -Working with full ert cases -=========================== - diff --git a/ThirdParty/Ert/docs/code/python/packages/geometry/index.rst b/ThirdParty/Ert/docs/code/python/packages/geometry/index.rst deleted file mode 100644 index 89c51ef2c5..0000000000 --- a/ThirdParty/Ert/docs/code/python/packages/geometry/index.rst +++ /dev/null @@ -1,2 +0,0 @@ -The ert.geo package -=================== diff --git a/ThirdParty/Ert/docs/code/python/packages/util/index.rst b/ThirdParty/Ert/docs/code/python/packages/util/index.rst deleted file mode 100644 index 83bd652b28..0000000000 --- a/ThirdParty/Ert/docs/code/python/packages/util/index.rst +++ /dev/null @@ -1,2 +0,0 @@ -The ert.util package -=================== diff --git a/ThirdParty/Ert/docs/code/python/packages/well/index.rst b/ThirdParty/Ert/docs/code/python/packages/well/index.rst deleted file mode 100644 index 9a3ea2c9a1..0000000000 --- a/ThirdParty/Ert/docs/code/python/packages/well/index.rst +++ /dev/null @@ -1,2 +0,0 @@ -The ert.well package -==================== diff --git a/ThirdParty/Ert/docs/course/config/config.ert b/ThirdParty/Ert/docs/course/config/config.ert deleted file mode 100644 index ec14cc6def..0000000000 --- a/ThirdParty/Ert/docs/course/config/config.ert +++ /dev/null @@ -1,34 +0,0 @@ -QUEUE_SYSTEM LOCAL - -JOBNAME SNAKE_OIL_%d -NUM_REALIZATIONS 25 - -DEFINE storage/ - -RUNPATH_FILE directory/test_runpath_list.txt -RUNPATH /runpath/realisation-%d/iter-%d -ENSPATH /ensemble -ECLBASE SNAKE_OIL_FIELD -SUMMARY * - -HISTORY_SOURCE REFCASE_HISTORY -REFCASE refcase/SNAKE_OIL_FIELD - -TIME_MAP refcase/time_map.txt - -INSTALL_JOB SNAKE_OIL_SIMULATOR jobs/SNAKE_OIL_SIMULATOR -INSTALL_JOB SNAKE_OIL_NPV jobs/SNAKE_OIL_NPV -INSTALL_JOB SNAKE_OIL_DIFF jobs/SNAKE_OIL_DIFF - -FORWARD_MODEL SNAKE_OIL_SIMULATOR -FORWARD_MODEL SNAKE_OIL_NPV -FORWARD_MODEL SNAKE_OIL_DIFF - -RUN_TEMPLATE templates/seed_template.txt seed.txt - -GEN_KW SNAKE_OIL_PARAM templates/snake_oil_template.txt snake_oil_params.txt parameters/snake_oil_parameters.txt -CUSTOM_KW SNAKE_OIL_NPV snake_oil_npv.txt -GEN_DATA SNAKE_OIL_OPR_DIFF INPUT_FORMAT:ASCII RESULT_FILE:snake_oil_opr_diff_%d.txt REPORT_STEPS:199 -GEN_DATA SNAKE_OIL_WPR_DIFF INPUT_FORMAT:ASCII RESULT_FILE:snake_oil_wpr_diff_%d.txt REPORT_STEPS:199 -GEN_DATA SNAKE_OIL_GPR_DIFF INPUT_FORMAT:ASCII RESULT_FILE:snake_oil_gpr_diff_%d.txt REPORT_STEPS:199 - diff --git a/ThirdParty/Ert/docs/course/config/jobs/SNAKE_OIL_DIFF b/ThirdParty/Ert/docs/course/config/jobs/SNAKE_OIL_DIFF deleted file mode 100644 index 98a867d959..0000000000 --- a/ThirdParty/Ert/docs/course/config/jobs/SNAKE_OIL_DIFF +++ /dev/null @@ -1,4 +0,0 @@ -STDOUT snake_oil_diff.stdout -STDERR snake_oil_diff.stderr - -EXECUTABLE snake_oil_diff.py \ No newline at end of file diff --git a/ThirdParty/Ert/docs/course/config/jobs/SNAKE_OIL_NPV b/ThirdParty/Ert/docs/course/config/jobs/SNAKE_OIL_NPV deleted file mode 100644 index 887830c756..0000000000 --- a/ThirdParty/Ert/docs/course/config/jobs/SNAKE_OIL_NPV +++ /dev/null @@ -1,4 +0,0 @@ -STDOUT snake_oil_npv.stdout -STDERR snake_oil_npv.stderr - -EXECUTABLE snake_oil_npv.py \ No newline at end of file diff --git a/ThirdParty/Ert/docs/course/config/jobs/SNAKE_OIL_SIMULATOR b/ThirdParty/Ert/docs/course/config/jobs/SNAKE_OIL_SIMULATOR deleted file mode 100644 index b4b7f9928f..0000000000 --- a/ThirdParty/Ert/docs/course/config/jobs/SNAKE_OIL_SIMULATOR +++ /dev/null @@ -1,4 +0,0 @@ -STDOUT snake_oil.stdout -STDERR snake_oil.stderr - -EXECUTABLE snake_oil_simulator.py \ No newline at end of file diff --git a/ThirdParty/Ert/docs/course/config/jobs/snake_oil_diff.py b/ThirdParty/Ert/docs/course/config/jobs/snake_oil_diff.py deleted file mode 100644 index 51ef5d472f..0000000000 --- a/ThirdParty/Ert/docs/course/config/jobs/snake_oil_diff.py +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env python -from ecl.ecl import EclSum - -def writeDiff(filename, vector1, vector2): - with open(filename, "w") as f: - for index in range(len(vector1)): - node1 = vector1[index] - node2 = vector2[index] - - diff = node1.value - node2.value - f.write("%f\n" % diff) - - -if __name__ == '__main__': - ecl_sum = EclSum("SNAKE_OIL_FIELD") - - report_step = 199 - writeDiff("snake_oil_opr_diff_%d.txt" % report_step, ecl_sum["WOPR:OP1"], ecl_sum["WOPR:OP2"]) - writeDiff("snake_oil_wpr_diff_%d.txt" % report_step, ecl_sum["WWPR:OP1"], ecl_sum["WWPR:OP2"]) - writeDiff("snake_oil_gpr_diff_%d.txt" % report_step, ecl_sum["WGPR:OP1"], ecl_sum["WGPR:OP2"]) - - - - diff --git a/ThirdParty/Ert/docs/course/config/jobs/snake_oil_npv.py b/ThirdParty/Ert/docs/course/config/jobs/snake_oil_npv.py deleted file mode 100644 index 126c917725..0000000000 --- a/ThirdParty/Ert/docs/course/config/jobs/snake_oil_npv.py +++ /dev/null @@ -1,103 +0,0 @@ -#!/usr/bin/env python -from ecl.ecl import EclSum - -OIL_PRICES = {"2010-01-01": 78.33, - "2010-02-01": 76.39, - "2010-03-01": 81.20, - "2010-04-01": 84.29, - "2010-05-01": 73.74, - "2010-06-01": 75.34, - "2010-07-01": 76.32, - "2010-08-01": 76.60, - "2010-09-01": 75.24, - "2010-10-01": 81.89, - "2010-11-01": 84.25, - "2010-12-01": 89.15, - "2011-01-01": 89.17, - "2011-02-01": 88.58, - "2011-03-01": 102.86, - "2011-04-01": 109.53, - "2011-05-01": 100.90, - "2011-06-01": 96.26, - "2011-07-01": 97.30, - "2011-08-01": 86.33, - "2011-09-01": 85.52, - "2011-10-01": 86.32, - "2011-11-01": 97.16, - "2011-12-01": 98.56, - "2012-01-01": 100.27, - "2012-02-01": 102.20, - "2012-03-01": 106.16, - "2012-04-01": 103.32, - "2012-05-01": 94.65, - "2012-06-01": 82.30, - "2012-07-01": 87.90, - "2012-08-01": 94.13, - "2012-09-01": 94.51, - "2012-10-01": 89.49, - "2012-11-01": 86.53, - "2012-12-01": 87.86, - "2013-01-01": 94.76, - "2013-02-01": 95.31, - "2013-03-01": 92.94, - "2013-04-01": 92.02, - "2013-05-01": 94.51, - "2013-06-01": 95.77, - "2013-07-01": 104.67, - "2013-08-01": 106.57, - "2013-09-01": 106.29, - "2013-10-01": 100.54, - "2013-11-01": 93.86, - "2013-12-01": 97.63, - "2014-01-01": 94.62, - "2014-02-01": 100.82, - "2014-03-01": 100.80, - "2014-04-01": 102.07, - "2014-05-01": 102.18, - "2014-06-01": 105.79, - "2014-07-01": 103.59, - "2014-08-01": 96.54, - "2014-09-01": 93.21, - "2014-10-01": 84.40, - "2014-11-01": 75.79, - "2014-12-01": 59.29, - "2015-01-01": 47.22, - "2015-02-01": 50.58, - "2015-03-01": 47.82, - "2015-04-01": 54.45, - "2015-05-01": 59.27, - "2015-06-01": 59.82, - "2015-07-01": 50.90, - "2015-08-01": 42.87, - "2015-09-01": 45.48} - -if __name__ == '__main__': - ecl_sum = EclSum("SNAKE_OIL_FIELD") - start_time = ecl_sum.getStartTime() - date_ranges = ecl_sum.timeRange(start_time, interval="1M") - production_sums = ecl_sum.blockedProduction("FOPT", date_ranges) - - npv = 0.0 - for index in range(0, len(date_ranges) - 1): - date = date_ranges[index + 1] # end of period - production_sum = production_sums[index] - - oil_price = OIL_PRICES[date.date().strftime("%Y-%m-%d")] - - production_value = oil_price * production_sum - npv += production_value - - with open("snake_oil_npv.txt", "w") as output_file: - output_file.write("NPV %s\n" % npv) - - if npv < 80000: - rating = "POOR" - elif 80000 <= npv < 100000: - rating = "AVERAGE" - elif 100000 <= npv < 120000: - rating = "GOOD" - else: - rating = "EXCELLENT" - - output_file.write("RATING %s\n" % rating) - diff --git a/ThirdParty/Ert/docs/course/config/jobs/snake_oil_simulator.py b/ThirdParty/Ert/docs/course/config/jobs/snake_oil_simulator.py deleted file mode 100644 index 40b4d4a6a1..0000000000 --- a/ThirdParty/Ert/docs/course/config/jobs/snake_oil_simulator.py +++ /dev/null @@ -1,185 +0,0 @@ -#!/usr/bin/env python -from datetime import datetime -import os -import sys - -from ecl.ecl import EclSum, EclSumTStep -from ecl.test import ExtendedTestCase - -try: - from synthesizer import OilSimulator -except ImportError as e: - share_lib_path = ExtendedTestCase.createShareRoot("lib") - - sys.path.insert(0, share_lib_path) - synthesizer_module = __import__("synthesizer") - OilSimulator = synthesizer_module.OilSimulator - sys.path.pop(0) - - -def globalIndex(i, j, k, nx=10, ny=10, nz=10): - return i + nx * (j - 1) + nx * ny * (k - 1) - - -def readParameters(filename): - params = {} - with open(filename, "r") as f: - for line in f: - key, value = line.split(":", 1) - params[key] = value.strip() - - return params - - -def runSimulator(simulator, history_simulator, time_step_count): - """ @rtype: EclSum """ - ecl_sum = EclSum.writer("SNAKE_OIL_FIELD", datetime(2010, 1, 1), 10, 10, 10) - - ecl_sum.addVariable("FOPT") - ecl_sum.addVariable("FOPR") - ecl_sum.addVariable("FGPT") - ecl_sum.addVariable("FGPR") - ecl_sum.addVariable("FWPT") - ecl_sum.addVariable("FWPR") - ecl_sum.addVariable("FGOR") - ecl_sum.addVariable("FWCT") - - ecl_sum.addVariable("FOPTH") - ecl_sum.addVariable("FOPRH") - ecl_sum.addVariable("FGPTH") - ecl_sum.addVariable("FGPRH") - ecl_sum.addVariable("FWPTH") - ecl_sum.addVariable("FWPRH") - ecl_sum.addVariable("FGORH") - ecl_sum.addVariable("FWCTH") - - ecl_sum.addVariable("WOPR", wgname="OP1") - ecl_sum.addVariable("WOPR", wgname="OP2") - ecl_sum.addVariable("WWPR", wgname="OP1") - ecl_sum.addVariable("WWPR", wgname="OP2") - ecl_sum.addVariable("WGPR", wgname="OP1") - ecl_sum.addVariable("WGPR", wgname="OP2") - ecl_sum.addVariable("WGOR", wgname="OP1") - ecl_sum.addVariable("WGOR", wgname="OP2") - ecl_sum.addVariable("WWCT", wgname="OP1") - ecl_sum.addVariable("WWCT", wgname="OP2") - - ecl_sum.addVariable("WOPRH", wgname="OP1") - ecl_sum.addVariable("WOPRH", wgname="OP2") - ecl_sum.addVariable("WWPRH", wgname="OP1") - ecl_sum.addVariable("WWPRH", wgname="OP2") - ecl_sum.addVariable("WGPRH", wgname="OP1") - ecl_sum.addVariable("WGPRH", wgname="OP2") - ecl_sum.addVariable("WGORH", wgname="OP1") - ecl_sum.addVariable("WGORH", wgname="OP2") - ecl_sum.addVariable("WWCTH", wgname="OP1") - ecl_sum.addVariable("WWCTH", wgname="OP2") - - ecl_sum.addVariable("BPR", num=globalIndex(5, 5, 5)) - ecl_sum.addVariable("BPR", num=globalIndex(1, 3, 8)) - - time_map = [] - mini_step_count = 10 - total_step_count = time_step_count * mini_step_count - - for report_step in range(time_step_count): - for mini_step in range(mini_step_count): - t_step = ecl_sum.addTStep(report_step + 1, sim_days=report_step * mini_step_count + mini_step) - - time_map.append(t_step.getSimTime().datetime().strftime("%d/%m/%Y")) - - simulator.step(scale=1.0 / total_step_count) - history_simulator.step(scale=1.0 / total_step_count) - - t_step["FOPR"] = simulator.fopr() - t_step["FOPT"] = simulator.fopt() - t_step["FGPR"] = simulator.fgpr() - t_step["FGPT"] = simulator.fgpt() - t_step["FWPR"] = simulator.fwpr() - t_step["FWPT"] = simulator.fwpt() - t_step["FGOR"] = simulator.fgor() - t_step["FWCT"] = simulator.fwct() - - t_step["WOPR:OP1"] = simulator.opr("OP1") - t_step["WOPR:OP2"] = simulator.opr("OP2") - - t_step["WGPR:OP1"] = simulator.gpr("OP1") - t_step["WGPR:OP2"] = simulator.gpr("OP2") - - t_step["WWPR:OP1"] = simulator.wpr("OP1") - t_step["WWPR:OP2"] = simulator.wpr("OP2") - - t_step["WGOR:OP1"] = simulator.gor("OP1") - t_step["WGOR:OP2"] = simulator.gor("OP2") - - t_step["WWCT:OP1"] = simulator.wct("OP1") - t_step["WWCT:OP2"] = simulator.wct("OP2") - - t_step["BPR:5,5,5"] = simulator.bpr("5,5,5") - t_step["BPR:1,3,8"] = simulator.bpr("1,3,8") - - t_step["FOPRH"] = history_simulator.fopr() - t_step["FOPTH"] = history_simulator.fopt() - t_step["FGPRH"] = history_simulator.fgpr() - t_step["FGPTH"] = history_simulator.fgpt() - t_step["FWPRH"] = history_simulator.fwpr() - t_step["FWPTH"] = history_simulator.fwpt() - t_step["FGORH"] = history_simulator.fgor() - t_step["FWCTH"] = history_simulator.fwct() - - t_step["WOPRH:OP1"] = history_simulator.opr("OP1") - t_step["WOPRH:OP2"] = history_simulator.opr("OP2") - - t_step["WGPRH:OP1"] = history_simulator.gpr("OP1") - t_step["WGPRH:OP2"] = history_simulator.gpr("OP2") - - t_step["WWPRH:OP1"] = history_simulator.wpr("OP1") - t_step["WWPRH:OP2"] = history_simulator.wpr("OP2") - - t_step["WGORH:OP1"] = history_simulator.gor("OP1") - t_step["WGORH:OP2"] = history_simulator.gor("OP2") - - t_step["WWCTH:OP1"] = history_simulator.wct("OP1") - t_step["WWCTH:OP2"] = history_simulator.wct("OP2") - - return ecl_sum, time_map - - -def roundedInt(value): - return int(round(float(value))) - - -if __name__ == '__main__': - seed = int(readParameters("seed.txt")["SEED"]) - parameters = readParameters("snake_oil_params.txt") - - op1_divergence_scale = float(parameters["OP1_DIVERGENCE_SCALE"]) - op2_divergence_scale = float(parameters["OP2_DIVERGENCE_SCALE"]) - op1_persistence = float(parameters["OP1_PERSISTENCE"]) - op2_persistence = float(parameters["OP2_PERSISTENCE"]) - op1_offset = float(parameters["OP1_OFFSET"]) - op2_offset = float(parameters["OP2_OFFSET"]) - bpr_138_persistence = float(parameters["BPR_138_PERSISTENCE"]) - bpr_555_persistence = float(parameters["BPR_555_PERSISTENCE"]) - - op1_octaves = roundedInt(parameters["OP1_OCTAVES"]) - op2_octaves = roundedInt(parameters["OP2_OCTAVES"]) - - simulator = OilSimulator() - simulator.addWell("OP1", seed * 997, persistence=op1_persistence, octaves=op1_octaves, divergence_scale=op1_divergence_scale, offset=op1_offset) - simulator.addWell("OP2", seed * 13, persistence=op2_persistence, octaves=op2_octaves, divergence_scale=op2_divergence_scale, offset=op2_offset) - simulator.addBlock("5,5,5", seed * 37, persistence=bpr_555_persistence) - simulator.addBlock("1,3,8", seed * 31, persistence=bpr_138_persistence) - - history_simulator = OilSimulator() - history_simulator.addWell("OP1", 222118781) - history_simulator.addWell("OP2", 118116362) - - report_step_count = 200 - ecl_sum, time_map = runSimulator(simulator, history_simulator, report_step_count) - - ecl_sum.fwrite() - - with open("time_map.txt", "w") as f: - for t in time_map: - f.write("%s\n" % t) diff --git a/ThirdParty/Ert/docs/course/config/parameters/snake_oil_parameters.txt b/ThirdParty/Ert/docs/course/config/parameters/snake_oil_parameters.txt deleted file mode 100644 index 64573d0058..0000000000 --- a/ThirdParty/Ert/docs/course/config/parameters/snake_oil_parameters.txt +++ /dev/null @@ -1,11 +0,0 @@ -OP1_PERSISTENCE UNIFORM 0.01 0.4 -OP1_OCTAVES UNIFORM 3 5 -OP1_DIVERGENCE_SCALE UNIFORM 0.25 1.25 -OP1_OFFSET UNIFORM -0.1 0.1 -OP2_PERSISTENCE UNIFORM 0.1 0.6 -OP2_OCTAVES UNIFORM 5 12 -OP2_DIVERGENCE_SCALE UNIFORM 0.5 1.5 -OP2_OFFSET UNIFORM -0.2 0.2 -BPR_555_PERSISTENCE UNIFORM 0.1 0.5 -BPR_138_PERSISTENCE UNIFORM 0.2 0.7 - diff --git a/ThirdParty/Ert/docs/course/config/refcase/SNAKE_OIL_FIELD.SMSPEC b/ThirdParty/Ert/docs/course/config/refcase/SNAKE_OIL_FIELD.SMSPEC deleted file mode 100644 index 5a29e043b2d3740b3774a9deda10d6ead8937467..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1416 zcmeHHF;2uV5ZrJQAaq4aN>g1y1=WcPlbBqDVn>co);-`__|ScYN6=F71b%SrdN(1Y zLZV55qt#?K-tlC!3IOEZbV2)|0N}jXXpfj<+^at>(jcv}Zj9}e!u!+O217ZFONSK7U=mE z;N%Tw;6O96wRIr#)0rssF1?d|dEV2z{p0WY(9cBrvz9twUl*g9SR&6j&fXE1Uwh7I Ao&W#< diff --git a/ThirdParty/Ert/docs/course/config/refcase/SNAKE_OIL_FIELD.UNSMRY b/ThirdParty/Ert/docs/course/config/refcase/SNAKE_OIL_FIELD.UNSMRY deleted file mode 100644 index dfa04f80027b57788211c785cd6a5203769ee63b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 455200 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¨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 z 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 WJ%7nEk$S+7J3C!R$^J5S{Cbw? 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

IDEVE%a% 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 diff --git a/ThirdParty/Ert/docs/course/config/refcase/refcase_readme.txt b/ThirdParty/Ert/docs/course/config/refcase/refcase_readme.txt deleted file mode 100644 index a3d0fe6058..0000000000 --- a/ThirdParty/Ert/docs/course/config/refcase/refcase_readme.txt +++ /dev/null @@ -1 +0,0 @@ -To create a refcase run the snake_oil_simulator.py job with the this as working directory. \ No newline at end of file diff --git a/ThirdParty/Ert/docs/course/config/refcase/seed.txt b/ThirdParty/Ert/docs/course/config/refcase/seed.txt deleted file mode 100644 index 0009f6e89a..0000000000 --- a/ThirdParty/Ert/docs/course/config/refcase/seed.txt +++ /dev/null @@ -1 +0,0 @@ -SEED:268776 \ No newline at end of file diff --git a/ThirdParty/Ert/docs/course/config/refcase/snake_oil_params.txt b/ThirdParty/Ert/docs/course/config/refcase/snake_oil_params.txt deleted file mode 100644 index 3868522924..0000000000 --- a/ThirdParty/Ert/docs/course/config/refcase/snake_oil_params.txt +++ /dev/null @@ -1,10 +0,0 @@ -OP1_PERSISTENCE:0.15 -OP1_OCTAVES:4 -OP1_DIVERGENCE_SCALE:0.5 -OP1_OFFSET:0.0 -OP2_PERSISTENCE:0.25 -OP2_OCTAVES:7.0 -OP2_DIVERGENCE_SCALE:1.0 -OP2_OFFSET:0.0 -BPR_555_PERSISTENCE:0.25 -BPR_138_PERSISTENCE:0.35 diff --git a/ThirdParty/Ert/docs/course/config/refcase/time_map.txt b/ThirdParty/Ert/docs/course/config/refcase/time_map.txt deleted file mode 100644 index d54b4293ae..0000000000 --- a/ThirdParty/Ert/docs/course/config/refcase/time_map.txt +++ /dev/null @@ -1,2000 +0,0 @@ -01/01/2010 -02/01/2010 -03/01/2010 -04/01/2010 -05/01/2010 -06/01/2010 -07/01/2010 -08/01/2010 -09/01/2010 -10/01/2010 -11/01/2010 -12/01/2010 -13/01/2010 -14/01/2010 -15/01/2010 -16/01/2010 -17/01/2010 -18/01/2010 -19/01/2010 -20/01/2010 -21/01/2010 -22/01/2010 -23/01/2010 -24/01/2010 -25/01/2010 -26/01/2010 -27/01/2010 -28/01/2010 -29/01/2010 -30/01/2010 -31/01/2010 -01/02/2010 -02/02/2010 -03/02/2010 -04/02/2010 -05/02/2010 -06/02/2010 -07/02/2010 -08/02/2010 -09/02/2010 -10/02/2010 -11/02/2010 -12/02/2010 -13/02/2010 -14/02/2010 -15/02/2010 -16/02/2010 -17/02/2010 -18/02/2010 -19/02/2010 -20/02/2010 -21/02/2010 -22/02/2010 -23/02/2010 -24/02/2010 -25/02/2010 -26/02/2010 -27/02/2010 -28/02/2010 -01/03/2010 -02/03/2010 -03/03/2010 -04/03/2010 -05/03/2010 -06/03/2010 -07/03/2010 -08/03/2010 -09/03/2010 -10/03/2010 -11/03/2010 -12/03/2010 -13/03/2010 -14/03/2010 -15/03/2010 -16/03/2010 -17/03/2010 -18/03/2010 -19/03/2010 -20/03/2010 -21/03/2010 -22/03/2010 -23/03/2010 -24/03/2010 -25/03/2010 -26/03/2010 -27/03/2010 -28/03/2010 -29/03/2010 -30/03/2010 -31/03/2010 -01/04/2010 -02/04/2010 -03/04/2010 -04/04/2010 -05/04/2010 -06/04/2010 -07/04/2010 -08/04/2010 -09/04/2010 -10/04/2010 -11/04/2010 -12/04/2010 -13/04/2010 -14/04/2010 -15/04/2010 -16/04/2010 -17/04/2010 -18/04/2010 -19/04/2010 -20/04/2010 -21/04/2010 -22/04/2010 -23/04/2010 -24/04/2010 -25/04/2010 -26/04/2010 -27/04/2010 -28/04/2010 -29/04/2010 -30/04/2010 -01/05/2010 -02/05/2010 -03/05/2010 -04/05/2010 -05/05/2010 -06/05/2010 -07/05/2010 -08/05/2010 -09/05/2010 -10/05/2010 -11/05/2010 -12/05/2010 -13/05/2010 -14/05/2010 -15/05/2010 -16/05/2010 -17/05/2010 -18/05/2010 -19/05/2010 -20/05/2010 -21/05/2010 -22/05/2010 -23/05/2010 -24/05/2010 -25/05/2010 -26/05/2010 -27/05/2010 -28/05/2010 -29/05/2010 -30/05/2010 -31/05/2010 -01/06/2010 -02/06/2010 -03/06/2010 -04/06/2010 -05/06/2010 -06/06/2010 -07/06/2010 -08/06/2010 -09/06/2010 -10/06/2010 -11/06/2010 -12/06/2010 -13/06/2010 -14/06/2010 -15/06/2010 -16/06/2010 -17/06/2010 -18/06/2010 -19/06/2010 -20/06/2010 -21/06/2010 -22/06/2010 -23/06/2010 -24/06/2010 -25/06/2010 -26/06/2010 -27/06/2010 -28/06/2010 -29/06/2010 -30/06/2010 -01/07/2010 -02/07/2010 -03/07/2010 -04/07/2010 -05/07/2010 -06/07/2010 -07/07/2010 -08/07/2010 -09/07/2010 -10/07/2010 -11/07/2010 -12/07/2010 -13/07/2010 -14/07/2010 -15/07/2010 -16/07/2010 -17/07/2010 -18/07/2010 -19/07/2010 -20/07/2010 -21/07/2010 -22/07/2010 -23/07/2010 -24/07/2010 -25/07/2010 -26/07/2010 -27/07/2010 -28/07/2010 -29/07/2010 -30/07/2010 -31/07/2010 -01/08/2010 -02/08/2010 -03/08/2010 -04/08/2010 -05/08/2010 -06/08/2010 -07/08/2010 -08/08/2010 -09/08/2010 -10/08/2010 -11/08/2010 -12/08/2010 -13/08/2010 -14/08/2010 -15/08/2010 -16/08/2010 -17/08/2010 -18/08/2010 -19/08/2010 -20/08/2010 -21/08/2010 -22/08/2010 -23/08/2010 -24/08/2010 -25/08/2010 -26/08/2010 -27/08/2010 -28/08/2010 -29/08/2010 -30/08/2010 -31/08/2010 -01/09/2010 -02/09/2010 -03/09/2010 -04/09/2010 -05/09/2010 -06/09/2010 -07/09/2010 -08/09/2010 -09/09/2010 -10/09/2010 -11/09/2010 -12/09/2010 -13/09/2010 -14/09/2010 -15/09/2010 -16/09/2010 -17/09/2010 -18/09/2010 -19/09/2010 -20/09/2010 -21/09/2010 -22/09/2010 -23/09/2010 -24/09/2010 -25/09/2010 -26/09/2010 -27/09/2010 -28/09/2010 -29/09/2010 -30/09/2010 -01/10/2010 -02/10/2010 -03/10/2010 -04/10/2010 -05/10/2010 -06/10/2010 -07/10/2010 -08/10/2010 -09/10/2010 -10/10/2010 -11/10/2010 -12/10/2010 -13/10/2010 -14/10/2010 -15/10/2010 -16/10/2010 -17/10/2010 -18/10/2010 -19/10/2010 -20/10/2010 -21/10/2010 -22/10/2010 -23/10/2010 -24/10/2010 -25/10/2010 -26/10/2010 -27/10/2010 -28/10/2010 -29/10/2010 -30/10/2010 -31/10/2010 -01/11/2010 -02/11/2010 -03/11/2010 -04/11/2010 -05/11/2010 -06/11/2010 -07/11/2010 -08/11/2010 -09/11/2010 -10/11/2010 -11/11/2010 -12/11/2010 -13/11/2010 -14/11/2010 -15/11/2010 -16/11/2010 -17/11/2010 -18/11/2010 -19/11/2010 -20/11/2010 -21/11/2010 -22/11/2010 -23/11/2010 -24/11/2010 -25/11/2010 -26/11/2010 -27/11/2010 -28/11/2010 -29/11/2010 -30/11/2010 -01/12/2010 -02/12/2010 -03/12/2010 -04/12/2010 -05/12/2010 -06/12/2010 -07/12/2010 -08/12/2010 -09/12/2010 -10/12/2010 -11/12/2010 -12/12/2010 -13/12/2010 -14/12/2010 -15/12/2010 -16/12/2010 -17/12/2010 -18/12/2010 -19/12/2010 -20/12/2010 -21/12/2010 -22/12/2010 -23/12/2010 -24/12/2010 -25/12/2010 -26/12/2010 -27/12/2010 -28/12/2010 -29/12/2010 -30/12/2010 -31/12/2010 -01/01/2011 -02/01/2011 -03/01/2011 -04/01/2011 -05/01/2011 -06/01/2011 -07/01/2011 -08/01/2011 -09/01/2011 -10/01/2011 -11/01/2011 -12/01/2011 -13/01/2011 -14/01/2011 -15/01/2011 -16/01/2011 -17/01/2011 -18/01/2011 -19/01/2011 -20/01/2011 -21/01/2011 -22/01/2011 -23/01/2011 -24/01/2011 -25/01/2011 -26/01/2011 -27/01/2011 -28/01/2011 -29/01/2011 -30/01/2011 -31/01/2011 -01/02/2011 -02/02/2011 -03/02/2011 -04/02/2011 -05/02/2011 -06/02/2011 -07/02/2011 -08/02/2011 -09/02/2011 -10/02/2011 -11/02/2011 -12/02/2011 -13/02/2011 -14/02/2011 -15/02/2011 -16/02/2011 -17/02/2011 -18/02/2011 -19/02/2011 -20/02/2011 -21/02/2011 -22/02/2011 -23/02/2011 -24/02/2011 -25/02/2011 -26/02/2011 -27/02/2011 -28/02/2011 -01/03/2011 -02/03/2011 -03/03/2011 -04/03/2011 -05/03/2011 -06/03/2011 -07/03/2011 -08/03/2011 -09/03/2011 -10/03/2011 -11/03/2011 -12/03/2011 -13/03/2011 -14/03/2011 -15/03/2011 -16/03/2011 -17/03/2011 -18/03/2011 -19/03/2011 -20/03/2011 -21/03/2011 -22/03/2011 -23/03/2011 -24/03/2011 -25/03/2011 -26/03/2011 -27/03/2011 -28/03/2011 -29/03/2011 -30/03/2011 -31/03/2011 -01/04/2011 -02/04/2011 -03/04/2011 -04/04/2011 -05/04/2011 -06/04/2011 -07/04/2011 -08/04/2011 -09/04/2011 -10/04/2011 -11/04/2011 -12/04/2011 -13/04/2011 -14/04/2011 -15/04/2011 -16/04/2011 -17/04/2011 -18/04/2011 -19/04/2011 -20/04/2011 -21/04/2011 -22/04/2011 -23/04/2011 -24/04/2011 -25/04/2011 -26/04/2011 -27/04/2011 -28/04/2011 -29/04/2011 -30/04/2011 -01/05/2011 -02/05/2011 -03/05/2011 -04/05/2011 -05/05/2011 -06/05/2011 -07/05/2011 -08/05/2011 -09/05/2011 -10/05/2011 -11/05/2011 -12/05/2011 -13/05/2011 -14/05/2011 -15/05/2011 -16/05/2011 -17/05/2011 -18/05/2011 -19/05/2011 -20/05/2011 -21/05/2011 -22/05/2011 -23/05/2011 -24/05/2011 -25/05/2011 -26/05/2011 -27/05/2011 -28/05/2011 -29/05/2011 -30/05/2011 -31/05/2011 -01/06/2011 -02/06/2011 -03/06/2011 -04/06/2011 -05/06/2011 -06/06/2011 -07/06/2011 -08/06/2011 -09/06/2011 -10/06/2011 -11/06/2011 -12/06/2011 -13/06/2011 -14/06/2011 -15/06/2011 -16/06/2011 -17/06/2011 -18/06/2011 -19/06/2011 -20/06/2011 -21/06/2011 -22/06/2011 -23/06/2011 -24/06/2011 -25/06/2011 -26/06/2011 -27/06/2011 -28/06/2011 -29/06/2011 -30/06/2011 -01/07/2011 -02/07/2011 -03/07/2011 -04/07/2011 -05/07/2011 -06/07/2011 -07/07/2011 -08/07/2011 -09/07/2011 -10/07/2011 -11/07/2011 -12/07/2011 -13/07/2011 -14/07/2011 -15/07/2011 -16/07/2011 -17/07/2011 -18/07/2011 -19/07/2011 -20/07/2011 -21/07/2011 -22/07/2011 -23/07/2011 -24/07/2011 -25/07/2011 -26/07/2011 -27/07/2011 -28/07/2011 -29/07/2011 -30/07/2011 -31/07/2011 -01/08/2011 -02/08/2011 -03/08/2011 -04/08/2011 -05/08/2011 -06/08/2011 -07/08/2011 -08/08/2011 -09/08/2011 -10/08/2011 -11/08/2011 -12/08/2011 -13/08/2011 -14/08/2011 -15/08/2011 -16/08/2011 -17/08/2011 -18/08/2011 -19/08/2011 -20/08/2011 -21/08/2011 -22/08/2011 -23/08/2011 -24/08/2011 -25/08/2011 -26/08/2011 -27/08/2011 -28/08/2011 -29/08/2011 -30/08/2011 -31/08/2011 -01/09/2011 -02/09/2011 -03/09/2011 -04/09/2011 -05/09/2011 -06/09/2011 -07/09/2011 -08/09/2011 -09/09/2011 -10/09/2011 -11/09/2011 -12/09/2011 -13/09/2011 -14/09/2011 -15/09/2011 -16/09/2011 -17/09/2011 -18/09/2011 -19/09/2011 -20/09/2011 -21/09/2011 -22/09/2011 -23/09/2011 -24/09/2011 -25/09/2011 -26/09/2011 -27/09/2011 -28/09/2011 -29/09/2011 -30/09/2011 -01/10/2011 -02/10/2011 -03/10/2011 -04/10/2011 -05/10/2011 -06/10/2011 -07/10/2011 -08/10/2011 -09/10/2011 -10/10/2011 -11/10/2011 -12/10/2011 -13/10/2011 -14/10/2011 -15/10/2011 -16/10/2011 -17/10/2011 -18/10/2011 -19/10/2011 -20/10/2011 -21/10/2011 -22/10/2011 -23/10/2011 -24/10/2011 -25/10/2011 -26/10/2011 -27/10/2011 -28/10/2011 -29/10/2011 -30/10/2011 -31/10/2011 -01/11/2011 -02/11/2011 -03/11/2011 -04/11/2011 -05/11/2011 -06/11/2011 -07/11/2011 -08/11/2011 -09/11/2011 -10/11/2011 -11/11/2011 -12/11/2011 -13/11/2011 -14/11/2011 -15/11/2011 -16/11/2011 -17/11/2011 -18/11/2011 -19/11/2011 -20/11/2011 -21/11/2011 -22/11/2011 -23/11/2011 -24/11/2011 -25/11/2011 -26/11/2011 -27/11/2011 -28/11/2011 -29/11/2011 -30/11/2011 -01/12/2011 -02/12/2011 -03/12/2011 -04/12/2011 -05/12/2011 -06/12/2011 -07/12/2011 -08/12/2011 -09/12/2011 -10/12/2011 -11/12/2011 -12/12/2011 -13/12/2011 -14/12/2011 -15/12/2011 -16/12/2011 -17/12/2011 -18/12/2011 -19/12/2011 -20/12/2011 -21/12/2011 -22/12/2011 -23/12/2011 -24/12/2011 -25/12/2011 -26/12/2011 -27/12/2011 -28/12/2011 -29/12/2011 -30/12/2011 -31/12/2011 -01/01/2012 -02/01/2012 -03/01/2012 -04/01/2012 -05/01/2012 -06/01/2012 -07/01/2012 -08/01/2012 -09/01/2012 -10/01/2012 -11/01/2012 -12/01/2012 -13/01/2012 -14/01/2012 -15/01/2012 -16/01/2012 -17/01/2012 -18/01/2012 -19/01/2012 -20/01/2012 -21/01/2012 -22/01/2012 -23/01/2012 -24/01/2012 -25/01/2012 -26/01/2012 -27/01/2012 -28/01/2012 -29/01/2012 -30/01/2012 -31/01/2012 -01/02/2012 -02/02/2012 -03/02/2012 -04/02/2012 -05/02/2012 -06/02/2012 -07/02/2012 -08/02/2012 -09/02/2012 -10/02/2012 -11/02/2012 -12/02/2012 -13/02/2012 -14/02/2012 -15/02/2012 -16/02/2012 -17/02/2012 -18/02/2012 -19/02/2012 -20/02/2012 -21/02/2012 -22/02/2012 -23/02/2012 -24/02/2012 -25/02/2012 -26/02/2012 -27/02/2012 -28/02/2012 -29/02/2012 -01/03/2012 -02/03/2012 -03/03/2012 -04/03/2012 -05/03/2012 -06/03/2012 -07/03/2012 -08/03/2012 -09/03/2012 -10/03/2012 -11/03/2012 -12/03/2012 -13/03/2012 -14/03/2012 -15/03/2012 -16/03/2012 -17/03/2012 -18/03/2012 -19/03/2012 -20/03/2012 -21/03/2012 -22/03/2012 -23/03/2012 -24/03/2012 -25/03/2012 -26/03/2012 -27/03/2012 -28/03/2012 -29/03/2012 -30/03/2012 -31/03/2012 -01/04/2012 -02/04/2012 -03/04/2012 -04/04/2012 -05/04/2012 -06/04/2012 -07/04/2012 -08/04/2012 -09/04/2012 -10/04/2012 -11/04/2012 -12/04/2012 -13/04/2012 -14/04/2012 -15/04/2012 -16/04/2012 -17/04/2012 -18/04/2012 -19/04/2012 -20/04/2012 -21/04/2012 -22/04/2012 -23/04/2012 -24/04/2012 -25/04/2012 -26/04/2012 -27/04/2012 -28/04/2012 -29/04/2012 -30/04/2012 -01/05/2012 -02/05/2012 -03/05/2012 -04/05/2012 -05/05/2012 -06/05/2012 -07/05/2012 -08/05/2012 -09/05/2012 -10/05/2012 -11/05/2012 -12/05/2012 -13/05/2012 -14/05/2012 -15/05/2012 -16/05/2012 -17/05/2012 -18/05/2012 -19/05/2012 -20/05/2012 -21/05/2012 -22/05/2012 -23/05/2012 -24/05/2012 -25/05/2012 -26/05/2012 -27/05/2012 -28/05/2012 -29/05/2012 -30/05/2012 -31/05/2012 -01/06/2012 -02/06/2012 -03/06/2012 -04/06/2012 -05/06/2012 -06/06/2012 -07/06/2012 -08/06/2012 -09/06/2012 -10/06/2012 -11/06/2012 -12/06/2012 -13/06/2012 -14/06/2012 -15/06/2012 -16/06/2012 -17/06/2012 -18/06/2012 -19/06/2012 -20/06/2012 -21/06/2012 -22/06/2012 -23/06/2012 -24/06/2012 -25/06/2012 -26/06/2012 -27/06/2012 -28/06/2012 -29/06/2012 -30/06/2012 -01/07/2012 -02/07/2012 -03/07/2012 -04/07/2012 -05/07/2012 -06/07/2012 -07/07/2012 -08/07/2012 -09/07/2012 -10/07/2012 -11/07/2012 -12/07/2012 -13/07/2012 -14/07/2012 -15/07/2012 -16/07/2012 -17/07/2012 -18/07/2012 -19/07/2012 -20/07/2012 -21/07/2012 -22/07/2012 -23/07/2012 -24/07/2012 -25/07/2012 -26/07/2012 -27/07/2012 -28/07/2012 -29/07/2012 -30/07/2012 -31/07/2012 -01/08/2012 -02/08/2012 -03/08/2012 -04/08/2012 -05/08/2012 -06/08/2012 -07/08/2012 -08/08/2012 -09/08/2012 -10/08/2012 -11/08/2012 -12/08/2012 -13/08/2012 -14/08/2012 -15/08/2012 -16/08/2012 -17/08/2012 -18/08/2012 -19/08/2012 -20/08/2012 -21/08/2012 -22/08/2012 -23/08/2012 -24/08/2012 -25/08/2012 -26/08/2012 -27/08/2012 -28/08/2012 -29/08/2012 -30/08/2012 -31/08/2012 -01/09/2012 -02/09/2012 -03/09/2012 -04/09/2012 -05/09/2012 -06/09/2012 -07/09/2012 -08/09/2012 -09/09/2012 -10/09/2012 -11/09/2012 -12/09/2012 -13/09/2012 -14/09/2012 -15/09/2012 -16/09/2012 -17/09/2012 -18/09/2012 -19/09/2012 -20/09/2012 -21/09/2012 -22/09/2012 -23/09/2012 -24/09/2012 -25/09/2012 -26/09/2012 -27/09/2012 -28/09/2012 -29/09/2012 -30/09/2012 -01/10/2012 -02/10/2012 -03/10/2012 -04/10/2012 -05/10/2012 -06/10/2012 -07/10/2012 -08/10/2012 -09/10/2012 -10/10/2012 -11/10/2012 -12/10/2012 -13/10/2012 -14/10/2012 -15/10/2012 -16/10/2012 -17/10/2012 -18/10/2012 -19/10/2012 -20/10/2012 -21/10/2012 -22/10/2012 -23/10/2012 -24/10/2012 -25/10/2012 -26/10/2012 -27/10/2012 -28/10/2012 -29/10/2012 -30/10/2012 -31/10/2012 -01/11/2012 -02/11/2012 -03/11/2012 -04/11/2012 -05/11/2012 -06/11/2012 -07/11/2012 -08/11/2012 -09/11/2012 -10/11/2012 -11/11/2012 -12/11/2012 -13/11/2012 -14/11/2012 -15/11/2012 -16/11/2012 -17/11/2012 -18/11/2012 -19/11/2012 -20/11/2012 -21/11/2012 -22/11/2012 -23/11/2012 -24/11/2012 -25/11/2012 -26/11/2012 -27/11/2012 -28/11/2012 -29/11/2012 -30/11/2012 -01/12/2012 -02/12/2012 -03/12/2012 -04/12/2012 -05/12/2012 -06/12/2012 -07/12/2012 -08/12/2012 -09/12/2012 -10/12/2012 -11/12/2012 -12/12/2012 -13/12/2012 -14/12/2012 -15/12/2012 -16/12/2012 -17/12/2012 -18/12/2012 -19/12/2012 -20/12/2012 -21/12/2012 -22/12/2012 -23/12/2012 -24/12/2012 -25/12/2012 -26/12/2012 -27/12/2012 -28/12/2012 -29/12/2012 -30/12/2012 -31/12/2012 -01/01/2013 -02/01/2013 -03/01/2013 -04/01/2013 -05/01/2013 -06/01/2013 -07/01/2013 -08/01/2013 -09/01/2013 -10/01/2013 -11/01/2013 -12/01/2013 -13/01/2013 -14/01/2013 -15/01/2013 -16/01/2013 -17/01/2013 -18/01/2013 -19/01/2013 -20/01/2013 -21/01/2013 -22/01/2013 -23/01/2013 -24/01/2013 -25/01/2013 -26/01/2013 -27/01/2013 -28/01/2013 -29/01/2013 -30/01/2013 -31/01/2013 -01/02/2013 -02/02/2013 -03/02/2013 -04/02/2013 -05/02/2013 -06/02/2013 -07/02/2013 -08/02/2013 -09/02/2013 -10/02/2013 -11/02/2013 -12/02/2013 -13/02/2013 -14/02/2013 -15/02/2013 -16/02/2013 -17/02/2013 -18/02/2013 -19/02/2013 -20/02/2013 -21/02/2013 -22/02/2013 -23/02/2013 -24/02/2013 -25/02/2013 -26/02/2013 -27/02/2013 -28/02/2013 -01/03/2013 -02/03/2013 -03/03/2013 -04/03/2013 -05/03/2013 -06/03/2013 -07/03/2013 -08/03/2013 -09/03/2013 -10/03/2013 -11/03/2013 -12/03/2013 -13/03/2013 -14/03/2013 -15/03/2013 -16/03/2013 -17/03/2013 -18/03/2013 -19/03/2013 -20/03/2013 -21/03/2013 -22/03/2013 -23/03/2013 -24/03/2013 -25/03/2013 -26/03/2013 -27/03/2013 -28/03/2013 -29/03/2013 -30/03/2013 -31/03/2013 -01/04/2013 -02/04/2013 -03/04/2013 -04/04/2013 -05/04/2013 -06/04/2013 -07/04/2013 -08/04/2013 -09/04/2013 -10/04/2013 -11/04/2013 -12/04/2013 -13/04/2013 -14/04/2013 -15/04/2013 -16/04/2013 -17/04/2013 -18/04/2013 -19/04/2013 -20/04/2013 -21/04/2013 -22/04/2013 -23/04/2013 -24/04/2013 -25/04/2013 -26/04/2013 -27/04/2013 -28/04/2013 -29/04/2013 -30/04/2013 -01/05/2013 -02/05/2013 -03/05/2013 -04/05/2013 -05/05/2013 -06/05/2013 -07/05/2013 -08/05/2013 -09/05/2013 -10/05/2013 -11/05/2013 -12/05/2013 -13/05/2013 -14/05/2013 -15/05/2013 -16/05/2013 -17/05/2013 -18/05/2013 -19/05/2013 -20/05/2013 -21/05/2013 -22/05/2013 -23/05/2013 -24/05/2013 -25/05/2013 -26/05/2013 -27/05/2013 -28/05/2013 -29/05/2013 -30/05/2013 -31/05/2013 -01/06/2013 -02/06/2013 -03/06/2013 -04/06/2013 -05/06/2013 -06/06/2013 -07/06/2013 -08/06/2013 -09/06/2013 -10/06/2013 -11/06/2013 -12/06/2013 -13/06/2013 -14/06/2013 -15/06/2013 -16/06/2013 -17/06/2013 -18/06/2013 -19/06/2013 -20/06/2013 -21/06/2013 -22/06/2013 -23/06/2013 -24/06/2013 -25/06/2013 -26/06/2013 -27/06/2013 -28/06/2013 -29/06/2013 -30/06/2013 -01/07/2013 -02/07/2013 -03/07/2013 -04/07/2013 -05/07/2013 -06/07/2013 -07/07/2013 -08/07/2013 -09/07/2013 -10/07/2013 -11/07/2013 -12/07/2013 -13/07/2013 -14/07/2013 -15/07/2013 -16/07/2013 -17/07/2013 -18/07/2013 -19/07/2013 -20/07/2013 -21/07/2013 -22/07/2013 -23/07/2013 -24/07/2013 -25/07/2013 -26/07/2013 -27/07/2013 -28/07/2013 -29/07/2013 -30/07/2013 -31/07/2013 -01/08/2013 -02/08/2013 -03/08/2013 -04/08/2013 -05/08/2013 -06/08/2013 -07/08/2013 -08/08/2013 -09/08/2013 -10/08/2013 -11/08/2013 -12/08/2013 -13/08/2013 -14/08/2013 -15/08/2013 -16/08/2013 -17/08/2013 -18/08/2013 -19/08/2013 -20/08/2013 -21/08/2013 -22/08/2013 -23/08/2013 -24/08/2013 -25/08/2013 -26/08/2013 -27/08/2013 -28/08/2013 -29/08/2013 -30/08/2013 -31/08/2013 -01/09/2013 -02/09/2013 -03/09/2013 -04/09/2013 -05/09/2013 -06/09/2013 -07/09/2013 -08/09/2013 -09/09/2013 -10/09/2013 -11/09/2013 -12/09/2013 -13/09/2013 -14/09/2013 -15/09/2013 -16/09/2013 -17/09/2013 -18/09/2013 -19/09/2013 -20/09/2013 -21/09/2013 -22/09/2013 -23/09/2013 -24/09/2013 -25/09/2013 -26/09/2013 -27/09/2013 -28/09/2013 -29/09/2013 -30/09/2013 -01/10/2013 -02/10/2013 -03/10/2013 -04/10/2013 -05/10/2013 -06/10/2013 -07/10/2013 -08/10/2013 -09/10/2013 -10/10/2013 -11/10/2013 -12/10/2013 -13/10/2013 -14/10/2013 -15/10/2013 -16/10/2013 -17/10/2013 -18/10/2013 -19/10/2013 -20/10/2013 -21/10/2013 -22/10/2013 -23/10/2013 -24/10/2013 -25/10/2013 -26/10/2013 -27/10/2013 -28/10/2013 -29/10/2013 -30/10/2013 -31/10/2013 -01/11/2013 -02/11/2013 -03/11/2013 -04/11/2013 -05/11/2013 -06/11/2013 -07/11/2013 -08/11/2013 -09/11/2013 -10/11/2013 -11/11/2013 -12/11/2013 -13/11/2013 -14/11/2013 -15/11/2013 -16/11/2013 -17/11/2013 -18/11/2013 -19/11/2013 -20/11/2013 -21/11/2013 -22/11/2013 -23/11/2013 -24/11/2013 -25/11/2013 -26/11/2013 -27/11/2013 -28/11/2013 -29/11/2013 -30/11/2013 -01/12/2013 -02/12/2013 -03/12/2013 -04/12/2013 -05/12/2013 -06/12/2013 -07/12/2013 -08/12/2013 -09/12/2013 -10/12/2013 -11/12/2013 -12/12/2013 -13/12/2013 -14/12/2013 -15/12/2013 -16/12/2013 -17/12/2013 -18/12/2013 -19/12/2013 -20/12/2013 -21/12/2013 -22/12/2013 -23/12/2013 -24/12/2013 -25/12/2013 -26/12/2013 -27/12/2013 -28/12/2013 -29/12/2013 -30/12/2013 -31/12/2013 -01/01/2014 -02/01/2014 -03/01/2014 -04/01/2014 -05/01/2014 -06/01/2014 -07/01/2014 -08/01/2014 -09/01/2014 -10/01/2014 -11/01/2014 -12/01/2014 -13/01/2014 -14/01/2014 -15/01/2014 -16/01/2014 -17/01/2014 -18/01/2014 -19/01/2014 -20/01/2014 -21/01/2014 -22/01/2014 -23/01/2014 -24/01/2014 -25/01/2014 -26/01/2014 -27/01/2014 -28/01/2014 -29/01/2014 -30/01/2014 -31/01/2014 -01/02/2014 -02/02/2014 -03/02/2014 -04/02/2014 -05/02/2014 -06/02/2014 -07/02/2014 -08/02/2014 -09/02/2014 -10/02/2014 -11/02/2014 -12/02/2014 -13/02/2014 -14/02/2014 -15/02/2014 -16/02/2014 -17/02/2014 -18/02/2014 -19/02/2014 -20/02/2014 -21/02/2014 -22/02/2014 -23/02/2014 -24/02/2014 -25/02/2014 -26/02/2014 -27/02/2014 -28/02/2014 -01/03/2014 -02/03/2014 -03/03/2014 -04/03/2014 -05/03/2014 -06/03/2014 -07/03/2014 -08/03/2014 -09/03/2014 -10/03/2014 -11/03/2014 -12/03/2014 -13/03/2014 -14/03/2014 -15/03/2014 -16/03/2014 -17/03/2014 -18/03/2014 -19/03/2014 -20/03/2014 -21/03/2014 -22/03/2014 -23/03/2014 -24/03/2014 -25/03/2014 -26/03/2014 -27/03/2014 -28/03/2014 -29/03/2014 -30/03/2014 -31/03/2014 -01/04/2014 -02/04/2014 -03/04/2014 -04/04/2014 -05/04/2014 -06/04/2014 -07/04/2014 -08/04/2014 -09/04/2014 -10/04/2014 -11/04/2014 -12/04/2014 -13/04/2014 -14/04/2014 -15/04/2014 -16/04/2014 -17/04/2014 -18/04/2014 -19/04/2014 -20/04/2014 -21/04/2014 -22/04/2014 -23/04/2014 -24/04/2014 -25/04/2014 -26/04/2014 -27/04/2014 -28/04/2014 -29/04/2014 -30/04/2014 -01/05/2014 -02/05/2014 -03/05/2014 -04/05/2014 -05/05/2014 -06/05/2014 -07/05/2014 -08/05/2014 -09/05/2014 -10/05/2014 -11/05/2014 -12/05/2014 -13/05/2014 -14/05/2014 -15/05/2014 -16/05/2014 -17/05/2014 -18/05/2014 -19/05/2014 -20/05/2014 -21/05/2014 -22/05/2014 -23/05/2014 -24/05/2014 -25/05/2014 -26/05/2014 -27/05/2014 -28/05/2014 -29/05/2014 -30/05/2014 -31/05/2014 -01/06/2014 -02/06/2014 -03/06/2014 -04/06/2014 -05/06/2014 -06/06/2014 -07/06/2014 -08/06/2014 -09/06/2014 -10/06/2014 -11/06/2014 -12/06/2014 -13/06/2014 -14/06/2014 -15/06/2014 -16/06/2014 -17/06/2014 -18/06/2014 -19/06/2014 -20/06/2014 -21/06/2014 -22/06/2014 -23/06/2014 -24/06/2014 -25/06/2014 -26/06/2014 -27/06/2014 -28/06/2014 -29/06/2014 -30/06/2014 -01/07/2014 -02/07/2014 -03/07/2014 -04/07/2014 -05/07/2014 -06/07/2014 -07/07/2014 -08/07/2014 -09/07/2014 -10/07/2014 -11/07/2014 -12/07/2014 -13/07/2014 -14/07/2014 -15/07/2014 -16/07/2014 -17/07/2014 -18/07/2014 -19/07/2014 -20/07/2014 -21/07/2014 -22/07/2014 -23/07/2014 -24/07/2014 -25/07/2014 -26/07/2014 -27/07/2014 -28/07/2014 -29/07/2014 -30/07/2014 -31/07/2014 -01/08/2014 -02/08/2014 -03/08/2014 -04/08/2014 -05/08/2014 -06/08/2014 -07/08/2014 -08/08/2014 -09/08/2014 -10/08/2014 -11/08/2014 -12/08/2014 -13/08/2014 -14/08/2014 -15/08/2014 -16/08/2014 -17/08/2014 -18/08/2014 -19/08/2014 -20/08/2014 -21/08/2014 -22/08/2014 -23/08/2014 -24/08/2014 -25/08/2014 -26/08/2014 -27/08/2014 -28/08/2014 -29/08/2014 -30/08/2014 -31/08/2014 -01/09/2014 -02/09/2014 -03/09/2014 -04/09/2014 -05/09/2014 -06/09/2014 -07/09/2014 -08/09/2014 -09/09/2014 -10/09/2014 -11/09/2014 -12/09/2014 -13/09/2014 -14/09/2014 -15/09/2014 -16/09/2014 -17/09/2014 -18/09/2014 -19/09/2014 -20/09/2014 -21/09/2014 -22/09/2014 -23/09/2014 -24/09/2014 -25/09/2014 -26/09/2014 -27/09/2014 -28/09/2014 -29/09/2014 -30/09/2014 -01/10/2014 -02/10/2014 -03/10/2014 -04/10/2014 -05/10/2014 -06/10/2014 -07/10/2014 -08/10/2014 -09/10/2014 -10/10/2014 -11/10/2014 -12/10/2014 -13/10/2014 -14/10/2014 -15/10/2014 -16/10/2014 -17/10/2014 -18/10/2014 -19/10/2014 -20/10/2014 -21/10/2014 -22/10/2014 -23/10/2014 -24/10/2014 -25/10/2014 -26/10/2014 -27/10/2014 -28/10/2014 -29/10/2014 -30/10/2014 -31/10/2014 -01/11/2014 -02/11/2014 -03/11/2014 -04/11/2014 -05/11/2014 -06/11/2014 -07/11/2014 -08/11/2014 -09/11/2014 -10/11/2014 -11/11/2014 -12/11/2014 -13/11/2014 -14/11/2014 -15/11/2014 -16/11/2014 -17/11/2014 -18/11/2014 -19/11/2014 -20/11/2014 -21/11/2014 -22/11/2014 -23/11/2014 -24/11/2014 -25/11/2014 -26/11/2014 -27/11/2014 -28/11/2014 -29/11/2014 -30/11/2014 -01/12/2014 -02/12/2014 -03/12/2014 -04/12/2014 -05/12/2014 -06/12/2014 -07/12/2014 -08/12/2014 -09/12/2014 -10/12/2014 -11/12/2014 -12/12/2014 -13/12/2014 -14/12/2014 -15/12/2014 -16/12/2014 -17/12/2014 -18/12/2014 -19/12/2014 -20/12/2014 -21/12/2014 -22/12/2014 -23/12/2014 -24/12/2014 -25/12/2014 -26/12/2014 -27/12/2014 -28/12/2014 -29/12/2014 -30/12/2014 -31/12/2014 -01/01/2015 -02/01/2015 -03/01/2015 -04/01/2015 -05/01/2015 -06/01/2015 -07/01/2015 -08/01/2015 -09/01/2015 -10/01/2015 -11/01/2015 -12/01/2015 -13/01/2015 -14/01/2015 -15/01/2015 -16/01/2015 -17/01/2015 -18/01/2015 -19/01/2015 -20/01/2015 -21/01/2015 -22/01/2015 -23/01/2015 -24/01/2015 -25/01/2015 -26/01/2015 -27/01/2015 -28/01/2015 -29/01/2015 -30/01/2015 -31/01/2015 -01/02/2015 -02/02/2015 -03/02/2015 -04/02/2015 -05/02/2015 -06/02/2015 -07/02/2015 -08/02/2015 -09/02/2015 -10/02/2015 -11/02/2015 -12/02/2015 -13/02/2015 -14/02/2015 -15/02/2015 -16/02/2015 -17/02/2015 -18/02/2015 -19/02/2015 -20/02/2015 -21/02/2015 -22/02/2015 -23/02/2015 -24/02/2015 -25/02/2015 -26/02/2015 -27/02/2015 -28/02/2015 -01/03/2015 -02/03/2015 -03/03/2015 -04/03/2015 -05/03/2015 -06/03/2015 -07/03/2015 -08/03/2015 -09/03/2015 -10/03/2015 -11/03/2015 -12/03/2015 -13/03/2015 -14/03/2015 -15/03/2015 -16/03/2015 -17/03/2015 -18/03/2015 -19/03/2015 -20/03/2015 -21/03/2015 -22/03/2015 -23/03/2015 -24/03/2015 -25/03/2015 -26/03/2015 -27/03/2015 -28/03/2015 -29/03/2015 -30/03/2015 -31/03/2015 -01/04/2015 -02/04/2015 -03/04/2015 -04/04/2015 -05/04/2015 -06/04/2015 -07/04/2015 -08/04/2015 -09/04/2015 -10/04/2015 -11/04/2015 -12/04/2015 -13/04/2015 -14/04/2015 -15/04/2015 -16/04/2015 -17/04/2015 -18/04/2015 -19/04/2015 -20/04/2015 -21/04/2015 -22/04/2015 -23/04/2015 -24/04/2015 -25/04/2015 -26/04/2015 -27/04/2015 -28/04/2015 -29/04/2015 -30/04/2015 -01/05/2015 -02/05/2015 -03/05/2015 -04/05/2015 -05/05/2015 -06/05/2015 -07/05/2015 -08/05/2015 -09/05/2015 -10/05/2015 -11/05/2015 -12/05/2015 -13/05/2015 -14/05/2015 -15/05/2015 -16/05/2015 -17/05/2015 -18/05/2015 -19/05/2015 -20/05/2015 -21/05/2015 -22/05/2015 -23/05/2015 -24/05/2015 -25/05/2015 -26/05/2015 -27/05/2015 -28/05/2015 -29/05/2015 -30/05/2015 -31/05/2015 -01/06/2015 -02/06/2015 -03/06/2015 -04/06/2015 -05/06/2015 -06/06/2015 -07/06/2015 -08/06/2015 -09/06/2015 -10/06/2015 -11/06/2015 -12/06/2015 -13/06/2015 -14/06/2015 -15/06/2015 -16/06/2015 -17/06/2015 -18/06/2015 -19/06/2015 -20/06/2015 -21/06/2015 -22/06/2015 -23/06/2015 diff --git a/ThirdParty/Ert/docs/course/config/snake_oil.ert b/ThirdParty/Ert/docs/course/config/snake_oil.ert deleted file mode 100644 index 72fef586d0..0000000000 --- a/ThirdParty/Ert/docs/course/config/snake_oil.ert +++ /dev/null @@ -1,40 +0,0 @@ -QUEUE_SYSTEM LOCAL - -JOBNAME SNAKE_OIL_%d -NUM_REALIZATIONS 25 - -DEFINE storage/ - -STORE_SEED SEED -LOAD_SEED SEED - -RUNPATH_FILE directory/test_runpath_list.txt -RUNPATH /runpath/realisation-%d/iter-%d -ENSPATH /ensemble -ECLBASE SNAKE_OIL_FIELD -SUMMARY * - -HISTORY_SOURCE REFCASE_HISTORY -REFCASE refcase/SNAKE_OIL_FIELD - -TIME_MAP refcase/time_map.txt -OBS_CONFIG observations/observations.txt - -INSTALL_JOB SNAKE_OIL_SIMULATOR jobs/SNAKE_OIL_SIMULATOR -INSTALL_JOB SNAKE_OIL_NPV jobs/SNAKE_OIL_NPV -INSTALL_JOB SNAKE_OIL_DIFF jobs/SNAKE_OIL_DIFF - -FORWARD_MODEL SNAKE_OIL_SIMULATOR -FORWARD_MODEL SNAKE_OIL_NPV -FORWARD_MODEL SNAKE_OIL_DIFF - -RUN_TEMPLATE templates/seed_template.txt seed.txt -GEN_KW SNAKE_OIL_PARAM templates/snake_oil_template.txt snake_oil_params.txt parameters/snake_oil_parameters.txt -CUSTOM_KW SNAKE_OIL_NPV snake_oil_npv.txt -GEN_DATA SNAKE_OIL_OPR_DIFF INPUT_FORMAT:ASCII RESULT_FILE:snake_oil_opr_diff_%d.txt REPORT_STEPS:199 -GEN_DATA SNAKE_OIL_WPR_DIFF INPUT_FORMAT:ASCII RESULT_FILE:snake_oil_wpr_diff_%d.txt REPORT_STEPS:199 -GEN_DATA SNAKE_OIL_GPR_DIFF INPUT_FORMAT:ASCII RESULT_FILE:snake_oil_gpr_diff_%d.txt REPORT_STEPS:199 - -LOG_LEVEL 3 -LOG_FILE log/log.txt -UPDATE_LOG_PATH log/update diff --git a/ThirdParty/Ert/docs/course/config/templates/seed_template.txt b/ThirdParty/Ert/docs/course/config/templates/seed_template.txt deleted file mode 100644 index a0bca49fbd..0000000000 --- a/ThirdParty/Ert/docs/course/config/templates/seed_template.txt +++ /dev/null @@ -1 +0,0 @@ -SEED: \ No newline at end of file diff --git a/ThirdParty/Ert/docs/course/config/templates/snake_oil_template.txt b/ThirdParty/Ert/docs/course/config/templates/snake_oil_template.txt deleted file mode 100644 index ad2c648a0b..0000000000 --- a/ThirdParty/Ert/docs/course/config/templates/snake_oil_template.txt +++ /dev/null @@ -1,10 +0,0 @@ -OP1_PERSISTENCE: -OP1_OCTAVES: -OP1_DIVERGENCE_SCALE: -OP1_OFFSET: -OP2_PERSISTENCE: -OP2_OCTAVES: -OP2_DIVERGENCE_SCALE: -OP2_OFFSET: -BPR_555_PERSISTENCE: -BPR_138_PERSISTENCE: diff --git a/ThirdParty/Ert/docs/course/ex1/ex1.txt b/ThirdParty/Ert/docs/course/ex1/ex1.txt deleted file mode 100644 index dadcc397eb..0000000000 --- a/ThirdParty/Ert/docs/course/ex1/ex1.txt +++ /dev/null @@ -1,7 +0,0 @@ -1. Create a small Python script which will load a ERT configuration - file and instantiate a EnkfMain object. - -2. Query the EnKFMain instance and print on standard out: - - a) How many realisations there are. - b) List all GEN_KW keywords, and their internal keys. diff --git a/ThirdParty/Ert/docs/course/ex1/sol1.py b/ThirdParty/Ert/docs/course/ex1/sol1.py deleted file mode 100644 index 5c30971e1b..0000000000 --- a/ThirdParty/Ert/docs/course/ex1/sol1.py +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env python -import sys -import time -from ert.enkf import EnKFMain -from ert.enkf.enums import ErtImplType - - -# This will instantiate the EnkFMain object and create a handle to -# "everything" ert related for this instance. -ert = EnKFMain( sys.argv[1] ) - - -# Ask the EnKFMain instance how many realisations it has. Observe that -# the answer to this question is just the value of the -# NUM_REALISATIONS setting in the configuration file. -print("This instance has %d realisations" % ert.getEnsembleSize()) - - -# Get the ensemble configuration object, and ask for all GEN_KW keys: -ens_config = ert.ensembleConfig( ) -for key in ens_config.getKeylistFromImplType(ErtImplType.GEN_KW): - config_node = ens_config[key] - - # "Downcast" to GEN_KW configuration. - gen_kw_config = config_node.getModelConfig( ) - print("%s : %s" % (key , gen_kw_config.getKeyWords( ))) - diff --git a/ThirdParty/Ert/docs/course/ex2/ex2.txt b/ThirdParty/Ert/docs/course/ex2/ex2.txt deleted file mode 100644 index 32daa87560..0000000000 --- a/ThirdParty/Ert/docs/course/ex2/ex2.txt +++ /dev/null @@ -1 +0,0 @@ -Implement the [] operator for the gen_data class in GenData.py diff --git a/ThirdParty/Ert/docs/course/ex2/sol2.txt b/ThirdParty/Ert/docs/course/ex2/sol2.txt deleted file mode 100644 index e6b4474389..0000000000 --- a/ThirdParty/Ert/docs/course/ex2/sol2.txt +++ /dev/null @@ -1,35 +0,0 @@ -The [] operator for python objects is implemeted with the -__getitem__() and __setitem__() methods. - -1. The __setitem__ and __getitem__ methods should clearly be based on - C functions which set and get an item based on an index. Going to - libenkf/src/gen_data.c we see that two such functions already exist: - - double gen_data_iget_double(const gen_data_type * gen_data, int index); - void gen_data_iset_double(gen_data_type * gen_data, int index, double value); - - -2. We must add bindings from Python to these C functions. Add the - following lines to at the top of the declaration of class GenData: - - _iset = EnkfPrototype("void gen_data_iset_double(gen_data, int , double)") - _iget = EnkfPrototype("double gen_data_iget_double(gen_data, int )") - - -3. Create (simple) Python methods: - - def __getitem__(self , index): - if index < len(self): - return self._iget( index ) - else: - raise IndexError("Invalid index:%d - valid range: [0,%d)" % (index , len(self))) - - - def __setitem__(self , index, value): - if index < len(self): - self._iset( index , value ) - else: - raise IndexError("Invalid index:%d - valid range: [0,%d)" % (index , len(self))) - - - diff --git a/ThirdParty/Ert/docs/course/ex3/ex3.txt b/ThirdParty/Ert/docs/course/ex3/ex3.txt deleted file mode 100644 index e5c6750107..0000000000 --- a/ThirdParty/Ert/docs/course/ex3/ex3.txt +++ /dev/null @@ -1,2 +0,0 @@ -Iterate through all the forward models which have been installed and -get the configuration file and executable. diff --git a/ThirdParty/Ert/docs/course/ex3/sol3.py b/ThirdParty/Ert/docs/course/ex3/sol3.py deleted file mode 100644 index 044a865719..0000000000 --- a/ThirdParty/Ert/docs/course/ex3/sol3.py +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env python -import sys -import time -from ert.enkf import EnKFMain - - -# This will instantiate the EnkFMain object and create a handle to -# "everything" ert related for this instance. -ert = EnKFMain( sys.argv[1] ) -site_config = ert.siteConfig( ) - -jobs = site_config.get_installed_jobs( ) -for job in jobs: - print job.name() - print " config : %s" % job.get_config_file() - print " executable: %s" % job.get_executable( ) - print diff --git a/ThirdParty/Ert/docs/course/ex4/ex4.txt b/ThirdParty/Ert/docs/course/ex4/ex4.txt deleted file mode 100644 index 38b16f1939..0000000000 --- a/ThirdParty/Ert/docs/course/ex4/ex4.txt +++ /dev/null @@ -1,13 +0,0 @@ -Create a small script which: - -1. Loads the configuration file. - -2. Initializes the realisations and creates runpath folders. - -3. Submit simulations. - -4. Wait for simulations to complete. - -5. Fetch and print GEN_DATA results - use the GenData[] operator. - - diff --git a/ThirdParty/Ert/docs/course/ex4/sol4.py b/ThirdParty/Ert/docs/course/ex4/sol4.py deleted file mode 100644 index d62277c6c2..0000000000 --- a/ThirdParty/Ert/docs/course/ex4/sol4.py +++ /dev/null @@ -1,71 +0,0 @@ -#!/usr/bin/env python -import sys -import time -from ert.enkf import EnKFMain, RunArg, NodeId -from ert.enkf.data import EnkfNode -from ert.job_queue import JobQueueManager - -ert = EnKFMain( sys.argv[1] ) -fs_manager = ert.getEnkfFsManager( ) -fs = fs_manager.getCurrentFileSystem( ) - - -# Initialize the realisations. -for iens in range( ert.getEnsembleSize()): - realisation = ert.getRealisation( iens ) - realisation.initialize( fs ) - - -# Fetch out the job_queue from the SiteConfig object. In addition we -# create a JobQueueManager objects which wraps the queue. The purpose -# of this manager object is to let the queue run nonblocking in the -# background. -site_config = ert.siteConfig( ) -queue_manager = JobQueueManager( site_config.getJobQueue( ) ) -queue_manager.startQueue( ert.getEnsembleSize( ) , verbose = False ) - - -# Create list of RunArg instances which hold metadata for one running -# realisation, create the directory where the simulation should run -# and submit the simulation. -path_fmt = "/tmp/run%d" -arg_list = [ RunArg.createEnsembleExperimentRunArg(fs, iens, path_fmt % iens) for iens in range(ert.getEnsembleSize()) ] -for arg in arg_list: - ert.createRunPath( arg ) - ert.submitSimulation( arg ) - - -while True: - print("Waiting:%d Running:%d Complete:%d/%d" % (queue_manager.getNumWaiting( ), queue_manager.getNumRunning( ) , queue_manager.getNumSuccess() , queue_manager.getNumFailed( ))) - if not queue_manager.isRunning( ): - break - - time.sleep( 5 ) - -ens_config = ert.ensembleConfig( ) -data_config = ens_config["SNAKE_OIL_OPR_DIFF"] -param_config = ens_config["SNAKE_OIL_PARAM"] -for iens in range(ert.getEnsembleSize( )): - data_id = NodeId( realization_number = iens, - report_step = 199 ) - enkf_node1 = EnkfNode( data_config ) - enkf_node1.load( fs , data_id ) - gen_data = enkf_node1.asGenData( ) - data = gen_data.getData( ) - - - param_id = NodeId( realization_number = iens, - report_step = 0 ) - - enkf_node2 = EnkfNode( param_config ) - enkf_node2.load( fs , param_id ) - gen_kw = enkf_node2.asGenKw( ) - - print sum(data) - for v in gen_kw: - print v - - # Using the __getitem__() of GenData which was implemented - # previously. - for d in gen_data: - print d diff --git a/ThirdParty/Ert/docs/doxygen.cfg.in b/ThirdParty/Ert/docs/doxygen.cfg.in deleted file mode 100644 index 969caa1615..0000000000 --- a/ThirdParty/Ert/docs/doxygen.cfg.in +++ /dev/null @@ -1,42 +0,0 @@ -# This is a slightly modified standard doxygen config file - -DOXYFILE_ENCODING = UTF-8 -PROJECT_NAME = "Ert" -PROJECT_NUMBER = ${ERT_VERSION_MAJOR}.${ERT_VERSION_MINOR} -PROJECT_BRIEF = "ERT is a software initially developed by Statoil which main feature is to handle several ECLIPSE simulations in an Ensemble setting. --- http://ert.nr.no/ert" -PROJECT_LOGO = -OUTPUT_DIRECTORY = ${PROJECT_BINARY_DIR}/documentation/doxy -CREATE_SUBDIRS = NO -STRIP_FROM_PATH = -STRIP_FROM_INC_PATH = -TAB_SIZE = 2 - -EXTRACT_ALL = YES -EXTRACT_PACKAGE = YES -EXTRACT_PRIVATE = NO -EXTRACT_STATIC = NO - -CASE_SENSE_NAMES = YES - -QUIET = NO -WARNINGS = YES -WARN_IF_UNDOCUMENTED = NO -WARN_IF_DOC_ERROR = NO -WARN_NO_PARAMDOC = NO -WARN_FORMAT = "$file:$line: $text" - -INPUT = ${DOXYGEN_INPUT} - -RECURSIVE = YES -EXCLUDE_PATTERNS = */test/* */build/* */test-data/* */docs/* */python*/ - -HAVE_DOT = ${DOXYGEN_HAVE_DOT} -DOT_GRAPH_MAX_NODES = 1000 -GENERATE_HTML = YES -CLASS_DIAGRAMS = YES -INCLUDE_GRAPH = YES -INCLUDED_BY_GRAPH = NO -CALL_GRAPH = YES - -DOT_IMAGE_FORMAT = png -INTERACTIVE_SVG = NO diff --git a/ThirdParty/Ert/docs/eclipse_restart_spe1.txt b/ThirdParty/Ert/docs/eclipse_restart_spe1.txt deleted file mode 100644 index fd08813163..0000000000 --- a/ThirdParty/Ert/docs/eclipse_restart_spe1.txt +++ /dev/null @@ -1,109 +0,0 @@ -This files contains additional information about the structure of restart files generated in ECLIPSE. - -This applies to the case spe1 in the opm-data repository. - -INTEHEAD: -0: Value based on computer time in which the file was written -67: Timestep -68: Report step -219: Report step-1 -Values not described her or in ecl_kw_magic, are constant during simulation. - -LOGIHEAD -1: Set to true if RV values are calculated. -86: does not impact solution -Values not described her or in ecl_kw_magic, are constant during simulation. - -DOUBHEAD: -0: days -21: EQUIL, item 1 -157: Reservoir mean pressure -158: A double related to RS, but does not impact solution -159: possibly related to RV, 0 if RV not set -160: Start of simulation, 735979 days after year 0 -161: A whole number, value = 735979 + days -(735979 / 365.25 = 2015.00007. 735979 = Number of days since year 0) -Values not described her or in ecl_kw_magic, are constant during simulation. - -IWEL: -Changes during eclipse simulation. Reset to start values at restart stage does not impact solution. Related to the values: -index: 7 -index: 8 -index: 23 -index: 141 -index: 154 -index: 178 -All values except 7, 8, 23 , 141 154 and 178 are constant during simulation. -Known IWELS in addition to ecl_kw_magic: -0: PROD, X -1: PROD, Y -2: COMPDAT, 'PROD', item 4 -3: COMPDAT, 'PROD', item 5 -4: Number of completion connections -7, Uncertain -8: Uncertain -15: 1 = Oil production, 3 = Gas production -155: INJ, X -156: INJ, Y -157: COMPDAT, 'INJ', item 4 -158: COMPDAT, 'INJ', item 5 -159: Number of completion connections -168: Uncertain - -SWEL: -Mostly SWEL will contain the values: -0 -1 -+/-100000002004087734272, which are either missing entries in the .DATA file or settings. -Otherwise: -0: WCONPROD, item 4, noentry = 100000002004087734272 -2: WCONPROD, item 6, noentry = 100000002004087734272 -6: WCONPROD, item 9 -9: WELSPECS, 'PROD', item 5 -54: same as index: 2 -55: same as index: 6 -122: WCONINJ, item 6 -124: WCONINJ, item 5 -128: WCONINJ, item 7 -131: WELSPECS, 'INJ', item 5 -176: same as index: 124 -177: same as index: 128 -During simulation spe1, SWEL is constant. - -ICON: -1: I coordinate -2: J coordinate -3: K coordinate -4: Number of cells IF: I, J, K is are max. -During simulation spe1, ICON is constant. - - -These KS are unchanged during simulation (spe1): -LOGIHEAD -IGRP -SGRP -SWEL -ZWLS -ICON -SCON - - -KW that does not need to be present (can be removed): -XGRP -ZGRP -XWEL -IWLS -XCON -DLYTIM -HIDDEN -REGDIMS -FIPFAMNA -REGRPT - -note about STARTSOL: -ECLIPSE may cause if error or bugs anything unknwon or unecessary is added after STARTSOL -In spe1, there are some extra KWs after ENDSOL, and the TEMP and RV words, which should be removed. -If RV is calculated, Logihead indx: 1 should be set to true, if RV is not calculated, logihead,indx 1 should be set to false and RV should not be printed to solution. - - - diff --git a/ThirdParty/Ert/docs/eclipse_restart_specification.txt b/ThirdParty/Ert/docs/eclipse_restart_specification.txt deleted file mode 100644 index 6630d4225f..0000000000 --- a/ThirdParty/Ert/docs/eclipse_restart_specification.txt +++ /dev/null @@ -1,268 +0,0 @@ -Source: -kw_magic: K -Schlum : S -Decrypt : D - -INTEHEAD -INDEX SOURCE VALUE -0 S/D ISNUM = Time encoded number -1 D 201601 -2 K/S units type = 1 (METRIC), 2 (FIELD), 3 (LAB), 4 (PVT-M) -3 D CONSTANT, -2345 -4 D CONSTANT, -2345 -5 D CONSTANT, -2345 -6 D CONSTANT, -2345 -7 D CONSTANT, -2345 -8 K/S NX, cells in x dimension -9 K/S NY, cells in y dimension -10 K/S NZ, cells in z dimenstion -11 K/S NACTIV, number of active cells -12 - - -13 - - -14 K/S IPHS, intehead phase indicator -15 D CONSTANT, -2345 -16 K/S NWELLS=number of wells -17 K/S NCWMAX=maximum number of completions per wells -18 - - -19 K/S NWGMAX=maximum number of wells in any well group -20 K/S NGMAXZ=maximum number of groups in field -21 D CONSTANT, 0 -22 D CONSTANT, 0 -23 D CONSTANT, 0 -24 K/S NWELZ=number of data elements per well in IWEL array -25 K/S NSWELZ=number of data elements per well in SWEL array -26 K/S NXWELZ=number of data elements per well in XWEL array -27 K/S NZWELZ=number of data elements per well in ZWEL array -28 - - -29 - - -30 D CONSTANT, 1 -31 D CONSTANT, -2345 -32 K/S NICONZ=number of elements in ICON array -33 K/S NSCONZ=number of elements in SCON array -34 K/S NXCONZ=number of elements in XCON array -35 D CONSTANT, -2345 -36 K/S NIGRPZ=number of data elements per group in IGRP array -37 S NSGRPZ=number of data elements per group in SGRP array -38 S NXGRPZ=number of data elements per group in XGRP array -39 S NZGRPZ=number of data elements per group in ZGRP array -40 D CONSTANT, 0 -41 S NCAMAX=maximum number of analytic aquifer connections -42 S NIAAQZ=number of data elements per aquifer in IAAQ array -43 S NSAAQZ=number of data elements per aquifer in SAAQ array -44 S NXAAQZ=number of data elements per aquifer in XAAQ array -45 S NICAQZ=number of data elements per aquifer in ICAQ array -46 S NSCAQZ=number of data elements per aquifer in SCAQ array -47 S NXCAQZ=number of data elements per aquifer in XCAQ array -48 D CONSTANT, 0 -49 - - -50 D CONSTANT, 1 -51 - - -52 D CONSTANT, 0 -53 D CONSTANT, 0 -54 D CONSTANT, 0 -55 - - -56 D CONSTANT, 0 -57 D CONSTANT, 0 -58 D CONSTANT, 0 -59 D CONSTANT, 0 -60 D CONSTANT, 0 -61 D CONSTANT, 0 -62 D CONSTANT, 0 -63 D CONSTANT, 0 -64 K/S IDAY -65 K/S IMON -66 K/S IYEAR -67 D Timestep -68 D Reportstep -69 D CONSTANT, 0 -70 D CONSTANT, 1 -71 D CONSTANT, 0 -72 D CONSTANT, 0 -73 D CONSTANT, 0 -74 - - -75 D CONSTANT, 0 -76 - - -77 D CONSTANT, 10 -78 D CONSTANT 0 -79 - - -80 D CONSTANT, 12 -81 D CONSTANT, 1 -82 - - -83 D CONSTANT, 1 -84 D CONSTANT, -2345 -85 D CONSTANT, -2345 -86 - - -87 D CONSTANT, 8 -88 - - -89 - - -90 D CONSTANT, 2 -91 D CONSTANT, 3 -92 D CONSTANT, 1 -93 D CONSTANT, 2 -94 K/S IPROG, simulation program identifier -95 D CONSTANT, 0 -96 - - -97 D CONSTANT, 0 -98 D CONSTANT, -17 -99 - - -100 D 0 -101 D 1 -102 D 0 -103 D 1 -104 D 0 -105 D NX -106 D NY -107 D Number of cells -108 - - -109 D CONSTANT, 1 -110 D CONSTANT, 1 -111 D CONSTANT, 1 -112 D CONSTANT, 1 -113 - - -114 - - -115 - - -116 D CONSTANT, 25 -117 D CONSTANT, 1 -118 D CONSTANT, 0 -119 D CONSTANT, 0 -120 D CONSTANT, 0 -121 D CONSTANT, 0 -122 D CONSTANT, 0 -123 D CONSTANT, 1 -124 D CONSTANT, 1 -125 D CONSTANT, 1 -126 D CONSTANT, 0 -127 D CONSTANT, 0 -128 - - -129 D CONSTANT, 0 -130 D CONSTANT, 0 -131 D CONSTANT, 0 -132 D CONSTANT, 0 -133 D CONSTAND, 14 -134 D CONSTAND, 11 -135 D CONSTAND, 10 -136 D CONSTAND, 17 -137 D CONSTANT, 2 -138 D CONSTANT, 1 -139 D CONSTANT, 1 -140 D CONSTANT, 1 -141 D CONSTANT, 1 -142 - - -143 D CONSTANT, 1 -144 D CONSTANT, 1 -145 D CONSTANT, 1 -146 D CONSTANT, 1 -147 D CONSTANT, 1 -148 D CONSTANT, 1 -149 - - -150 D CONSTANT, 122 -151 D CONSTANT, 0 -152 D CONSTANT, 0 -153 D CONSTANT, 0 -154 D CONSTANT, 0 -155 D CONSTANT, 0 -156 D CONSTANT, 0 -157 D CONSTANT, 50 -158 D CONSTANT, 10 -159 D CONSTANT, 4 -160 D CONSTANT, 5 -161 D CONSTANT, 9 -162 D CONSTANT, 0 -163 - - -164 D CONSTANT; 8 -165 D CONSTANT; 8 -166 D CONSTANT; 12 -167 D CONSTANT; 1 -168 D CONSTANT; 25 -169 D CONSTANT; 1 -170 D CONSTANT, -1073741823 -171 D CONSTANT, -1073741823 -172 D CONSTANT, -1073741823 -173 D CONSTANT, -1073741823 -174 D CONSTANT, 0 -175 D CONSTANT, 1 -176 D CONSTANT, 1 -177 D CONSTANT, 1 -178 D CONSTANT, 22 -179 - - -180 D CONSTANT, 10 -181 D CONSTANT, 1 -182 D CONSTANT, 1 -183 D CONSTANT, 1 -184 D CONSTANT, 1 -185 - - -186 D CONSTANT, 116 -187 D CONSTANT, -1073741823 -188 D CONSTANT, -1073741823 -189 D CONSTANT, 0 -190 D CONSTANT, 0 -191 D CONSTANT, 130 -192 D CONSTANT, 58 -193 D CONSTANT, 180 -194 D CONSTANT, 10 -195 D CONSTANT, 0 -196 D CONSTANT, 25 -197 D CONSTANT, 155 -198 D CONSTANT, 0 -199 D CONSTANT, 0 -200 D CONSTANT, 1 -201 - - -202 D CONSTANT, 116 -203 D CONSTANT, 0 -204 D CONSTANT, 0 -205 D CONSTANT, 0 -206 D CONSTANT, 0 -207 D CONSTANT, 0 -208 D CONSTANT, 0 -209 D CONSTANT, 1 -210 D CONSTANT, 0 -211 - - -212 D CONSTANT, 0 -213 D CONSTANT, 0 -214 D CONSTANT, 1 -215 D CONSTANT, 0 -216 D CONSTANT, 0 -217 D CONSTANT, 1 -218 D CONSTANT, 0 -219 D Reportstep - 1 -220 D CONSTANT, 12 -221 D CONSTANT, 0 -222 D CONSTANT, 0 -223 D CONSTANT, 10 -224 D CONSTANT, 13 -225 D CONSTANT, 1 -226 D CONSTANT, 0 -227 D CONSTANT, 0 -228 D CONSTANT, 0 -229 D CONSTANT, 0 -230 D CONSTANT, 2 -231 D CONSTANT, 0 -232 D CONSTANT, 0 -233 D CONSTANT, 3600 -234 D CONSTANT, 1 -235 D CONSTANT, 0 -236 D CONSTANT, 1 -237 D CONSTANT, 10 -238 D CONSTANT, 1 -239 D CONSTANT, 10 -240 - - -241 D CONSTANT, 1 -242 - - - -287 D Number of cells - -302-410 D CONSTANT, -2345 - - - - - -DOUBHEAD - - - - - - - - diff --git a/ThirdParty/Ert/docs/nexus.plt b/ThirdParty/Ert/docs/nexus.plt deleted file mode 100644 index 88b482631b..0000000000 --- a/ThirdParty/Ert/docs/nexus.plt +++ /dev/null @@ -1,51 +0,0 @@ - - -bbbbPLOT__BIN_ : Header - verify file type -562*b : Header - skipped -264*b : Header - skipped -i : num_classes -iii : Day Month Year -i : nx -i : ny -i : nz -i : ncomp (number of phases???) -8b : ??? -num_classes *8b : The class names -8*b : Skipped -num_classes *i : The number of variables in each class (var_in_class[]) -8*b : Skipped - -for c in classes: - 4*b : TIME var name - for v in vars[c]: - 4*b : The variable names - 8*b : Skipped - -----> : This is the position of first timestep - -while classname != STOP: - 8*b : classname - 8*b : skipped - f : timestep (cast to int) - f : time - f : num_items (cast to int) - f : max_items (cast to int) - f : max_perfs (cast to int) - - if classame in ["WELLBORE","WELLYR"]: - 8*b : skipped - for item in num_items: - 8*b : skipped - 8*b : skipped - 8*b : ncon = atoi( ) - 48*b : skipped - for con in ncon: - 8*b : con_num (ignored) - 8*b : layer_name (ignored) - var_in_class*f : The real data - 16*b : skipped - else: - 8*b : skipped - 72*b : skipped - var_in_class*f : The real data - 8*b : skipped diff --git a/ThirdParty/Ert/install/install.py b/ThirdParty/Ert/install/install.py index 6358d54de7..1a60337933 100644 --- a/ThirdParty/Ert/install/install.py +++ b/ThirdParty/Ert/install/install.py @@ -1,4 +1,4 @@ -# Copyright (C) 2011 Statoil ASA, Norway. +# Copyright (C) 2011 Equinor ASA, Norway. # # The file 'ecl.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/lib/CMakeLists.txt b/ThirdParty/Ert/lib/CMakeLists.txt index b0fb796a1c..079eb127de 100644 --- a/ThirdParty/Ert/lib/CMakeLists.txt +++ b/ThirdParty/Ert/lib/CMakeLists.txt @@ -54,12 +54,6 @@ if (ZLIB_FOUND) list(APPEND opt_srcs util/util_zlib.cpp) endif () -if (ERT_BUILD_CXX) - list(APPEND opt_srcs ecl/FortIO.cpp - ecl/Smspec.cpp - ecl/EclFilename.cpp -) -endif () configure_file(build_config.h.in include/ert/util/build_config.h) configure_file(ert_api_config.h.in include/ert/util/ert_api_config.h) @@ -145,6 +139,8 @@ add_library(ecl util/rng.cpp ecl/well_segment_collection.cpp ecl/well_branch_collection.cpp ecl/well_rseg_loader.cpp + ecl/FortIO.cpp + ecl/EclFilename.cpp geometry/geo_surface.cpp geometry/geo_util.cpp @@ -183,13 +179,6 @@ target_include_directories(ecl ${CMAKE_CURRENT_BINARY_DIR}/include ) - -if (NOT INSTALL_ERT) - # set git info to zero, to avoid recompile of libecl files at every commit - set(GIT_COMMIT 0) - set(GIT_COMMIT_SHORT 0) -endif() - target_compile_definitions(ecl PRIVATE -DGIT_COMMIT=${GIT_COMMIT} -DGIT_COMMIT_SHORT=${GIT_COMMIT_SHORT} @@ -211,7 +200,7 @@ endif () set_target_properties(ecl PROPERTIES VERSION ${ECL_VERSION_MAJOR}.${ECL_VERSION_MINOR} SOVERSION ${ECL_VERSION_MAJOR}) -if (INSTALL_ERT) + install(TARGETS ecl EXPORT ecl-config ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} @@ -219,25 +208,11 @@ install(TARGETS ecl RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) install(DIRECTORY include/ DESTINATION include - PATTERN *.h -) -install(DIRECTORY include/ - DESTINATION include - PATTERN *.hpp EXCLUDE ) install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/include/ DESTINATION include - PATTERN *.h ) -if (ERT_BUILD_CXX) - install(DIRECTORY include/ - DESTINATION include - PATTERN *.hpp -) -endif () -endif() - if (NOT BUILD_TESTS) return () endif () @@ -277,6 +252,7 @@ foreach (name ert_util_alloc_file_components ert_util_datetime ert_util_normal_path ert_util_mkdir_p + test_area ) add_executable(${name} util/tests/${name}.cpp) @@ -353,11 +329,14 @@ foreach (name ecl_alloc_cpgrid ecl_grid_copy ecl_grid_create ecl_grid_DEPTHZ + ecl_grid_fwrite ecl_grid_unit_system ecl_grid_export ecl_grid_init_fwrite ecl_grid_reset_actnum ecl_grid_ext_actnum + ecl_nnc_export_intersect + ecl_sum_restart ecl_sum_data_intermediate_test ecl_grid_cell_contains ecl_unsmry_loader_test @@ -436,26 +415,24 @@ foreach (name geo_util_xlines geo_polygon geo_polygon_collection) add_test(NAME ${name} COMMAND ${name}) endforeach () -if (ERT_BUILD_CXX) - foreach (test ert_util_unique_ptr) - add_executable(${test} util/tests/${test}.cpp) - target_link_libraries(${test} ecl) - add_test(NAME ${test} COMMAND ${test}) - endforeach() +foreach (test ert_util_unique_ptr) + add_executable(${test} util/tests/${test}.cpp) + target_link_libraries(${test} ecl) + add_test(NAME ${test} COMMAND ${test}) +endforeach() - foreach (test eclxx_kw eclxx_fortio eclxx_smspec eclxx_filename eclxx_types) - add_executable(${test} ecl/tests/${test}.cpp) - target_link_libraries(${test} ecl) - add_test(NAME ${test} COMMAND ${test}) - endforeach () -endif () +foreach (test eclxx_kw eclxx_fortio eclxx_filename eclxx_types) + add_executable(${test} ecl/tests/${test}.cpp) + target_link_libraries(${test} ecl) + add_test(NAME ${test} COMMAND ${test}) +endforeach () foreach(name ecl_coarse_test ecl_grid_layer_contains ecl_restart_test ecl_nnc_export ecl_nnc_export_get_tran - ecl_nnc_data_statoil_root + ecl_nnc_data_equinor_root ecl_sum_case_exists ecl_grid_lgr_name ecl_region @@ -467,19 +444,19 @@ foreach(name ecl_coarse_test ecl_grid_dims ecl_nnc_test ecl_lgr_test - ecl_layer_statoil + ecl_layer_equinor ecl_dualp ecl_grid_dx_dy_dz ecl_sum_test ecl_sum_report_step_equal ecl_sum_report_step_compatible - ecl_file_statoil + ecl_file_equinor ecl_fmt ecl_rsthead ecl_smspec ecl_rft - ecl_grid_copy_statoil - ecl_fault_block_layer_statoil + ecl_grid_copy_equinor + ecl_fault_block_layer_equinor well_state_load well_state_load_missing_RSEG well_segment_load @@ -497,7 +474,7 @@ foreach(name ecl_coarse_test endforeach() -if (NOT STATOIL_TESTDATA_ROOT) +if (NOT EQUINOR_TESTDATA_ROOT) return () endif() @@ -531,7 +508,7 @@ add_test(NAME ecl_nnc_export7 COMMAND ecl_nnc_export ${_eclpath}/TYRIHANS/BASE20 add_test(NAME ecl_nnc_export_get_tran COMMAND ecl_nnc_export_get_tran ${_eclpath}/Troll/MSW_LGR/2BRANCHES-CCEWELLPATH-NEW-SCH-TUNED-AR3) -add_test(NAME ecl_nnc_data_statoil_root COMMAND ecl_nnc_data_statoil_root +add_test(NAME ecl_nnc_data_equinor_root COMMAND ecl_nnc_data_equinor_root ${_eclpath}/Troll/MSW_LGR/2BRANCHES-CCEWELLPATH-NEW-SCH-TUNED-AR3 ${_eclpath}/flow-nnc/Simple4/SIMPLE_SUMMARY4 ${_eclpath}/flow-nnc/Gullfaks/GF_ACT_NEW_TEMP) @@ -572,7 +549,7 @@ add_test(NAME ecl_grid_simple COMMAND ecl_grid_simple ${_eclpath}/Gurbat/ECLIPSE add_test(NAME ecl_grid_ecl2015_2 COMMAND ecl_grid_simple ${_eclpath}/Eclipse2015_NNC_BUG/FF15_2015B2_LGRM_RDI15_HIST_RDIREAL1_20142.EGRID) -add_test(NAME ecl_grid_export_statoil +add_test(NAME ecl_grid_export_equinor COMMAND ecl_grid_export ${_eclpath}/Gurbat/ECLIPSE.EGRID) add_test(NAME ecl_grid_volume1 COMMAND ecl_grid_volume ${_eclpath}/Gurbat/ECLIPSE) @@ -600,7 +577,7 @@ add_test(NAME ecl_nnc_test3 COMMAND ecl_nnc_test ${_eclpath}/Troll/MSW_LGR/2BRAN add_test(NAME ecl_nnc_test4 COMMAND ecl_nnc_test ${_eclpath}/DualPoro/DUAL_DIFF.EGRID ) add_test(NAME ecl_nnc_test5 COMMAND ecl_nnc_test ${_eclpath}/nestedLGRcase/TESTCASE_NESTEDLGR.EGRID) -add_test(NAME ecl_layer_statoil COMMAND ecl_layer_statoil +add_test(NAME ecl_layer_equinor COMMAND ecl_layer_equinor ${_eclpath}/Mariner/MARINER.EGRID ${_eclpath}/Mariner/faultblock.grdecl) @@ -622,8 +599,8 @@ add_test(NAME ecl_sum_report_step_compatible4 COMMAND ecl_sum_report_step_compat add_test(NAME ecl_sum_report_step_compatible5 COMMAND ecl_sum_report_step_compatible ${_eclpath}/Gurbat/ECLIPSE ${_eclpath}/modGurbat/enkf/ECLIPSE TRUE) add_test(NAME ecl_sum_report_step_compatible6 COMMAND ecl_sum_report_step_equal ${_eclpath}/Snorre/SNORRE ${_eclpath}/Snorre2/SNORRE2 FALSE) -add_test(NAME ecl_file_statoil - COMMAND ecl_file_statoil ${_eclpath}/Gurbat/ECLIPSE.UNRST ECLIPSE.UNRST) +add_test(NAME ecl_file_equinor + COMMAND ecl_file_equinor ${_eclpath}/Gurbat/ECLIPSE.UNRST ECLIPSE.UNRST) add_test(NAME ecl_fmt COMMAND ecl_fmt ${_eclpath}/Gurbat/ECLIPSE.UNRST @@ -645,12 +622,12 @@ add_test(NAME ecl_rft_plt COMMAND ecl_rft ${_eclpath}/RFT/TEST1_1A.RFT PLT) add_test(NAME ecl_rft_mswplt COMMAND ecl_rft ${_eclpath}/RFT/RFT2.RFT MSW-PLT) add_test(NAME ecl_rft_alloc COMMAND ecl_rft ${_eclpath}/RFT/NORNE_ATW2013_RFTPLT_V2.RFT SIMPLE) -add_test(NAME ecl_grid_copy_statoil1 COMMAND ecl_grid_copy_statoil ${_eclpath}/Gurbat/ECLIPSE.EGRID) -add_test(NAME ecl_grid_copy_statoil2 COMMAND ecl_grid_copy_statoil ${_eclpath}/Mariner/MARINER.EGRID) -add_test(NAME ecl_grid_copy_statoil3 COMMAND ecl_grid_copy_statoil ${_eclpath}/LGCcase/LGC_TESTCASE2.EGRID) -add_test(NAME ecl_grid_copy_statoil4 COMMAND ecl_grid_copy_statoil ${_eclpath}/10kcase/TEST10K_FLT_LGR_NNC.EGRID) +add_test(NAME ecl_grid_copy_equinor1 COMMAND ecl_grid_copy_equinor ${_eclpath}/Gurbat/ECLIPSE.EGRID) +add_test(NAME ecl_grid_copy_equinor2 COMMAND ecl_grid_copy_equinor ${_eclpath}/Mariner/MARINER.EGRID) +add_test(NAME ecl_grid_copy_equinor3 COMMAND ecl_grid_copy_equinor ${_eclpath}/LGCcase/LGC_TESTCASE2.EGRID) +add_test(NAME ecl_grid_copy_equinor4 COMMAND ecl_grid_copy_equinor ${_eclpath}/10kcase/TEST10K_FLT_LGR_NNC.EGRID) -add_test(NAME ecl_fault_block_layer_statoil COMMAND ecl_fault_block_layer_statoil +add_test(NAME ecl_fault_block_layer_equinor COMMAND ecl_fault_block_layer_equinor ${_eclpath}/Mariner/MARINER.EGRID ${_eclpath}/Mariner/faultblock.grdecl) @@ -684,7 +661,9 @@ add_test(NAME well_segment_load add_test(NAME well_segment_branch_conn_load COMMAND well_segment_branch_conn_load ${_eclpath}/MSWcase/MSW_CASE.X0021) -add_test(NAME well_info COMMAND well_info ${_eclpath}/Gurbat/ECLIPSE.EGRID) +add_test(NAME well_info1 COMMAND well_info ${_eclpath}/Gurbat/ECLIPSE.EGRID) +add_test(NAME well_info2 COMMAND well_info ${_eclpath}/well_info_rio/BMS8_TMPL_1-BMS8_105DST_EMBED_T0_1.EGRID + ${_eclpath}/well_info_rio/BMS8_TMPL_1-BMS8_105DST_EMBED_T0_1.UNRST) add_test(NAME well_conn_CF COMMAND well_conn_CF ${_eclpath}/Gurbat/ECLIPSE.X0060) diff --git a/ThirdParty/Ert/lib/ecl/EclFilename.cpp b/ThirdParty/Ert/lib/ecl/EclFilename.cpp index 225ad52b46..f5db772659 100644 --- a/ThirdParty/Ert/lib/ecl/EclFilename.cpp +++ b/ThirdParty/Ert/lib/ecl/EclFilename.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2017 Statoil ASA, Norway. + Copyright (C) 2017 Equinor ASA, Norway. This file is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/FortIO.cpp b/ThirdParty/Ert/lib/ecl/FortIO.cpp index c76985f173..edc5f1f92c 100644 --- a/ThirdParty/Ert/lib/ecl/FortIO.cpp +++ b/ThirdParty/Ert/lib/ecl/FortIO.cpp @@ -1,5 +1,5 @@ /* - Copyright 2015 Statoil ASA. + Copyright 2015 Equinor ASA. This file is part of the Open Porous Media project (OPM). diff --git a/ThirdParty/Ert/lib/ecl/Smspec.cpp b/ThirdParty/Ert/lib/ecl/Smspec.cpp deleted file mode 100644 index ba81341bef..0000000000 --- a/ThirdParty/Ert/lib/ecl/Smspec.cpp +++ /dev/null @@ -1,120 +0,0 @@ -#include -#include - -namespace ERT { - - smspec_node::smspec_node( const smspec_node& rhs ) : - node( smspec_node_alloc_copy( rhs.node.get() ) ) - {} - - smspec_node::smspec_node( smspec_node&& rhs ) : - node( std::move( rhs.node ) ) - {} - - smspec_node& smspec_node::operator=( const smspec_node& rhs ) { - this->node.reset( smspec_node_alloc_copy( rhs.node.get() ) ); - return *this; - } - - smspec_node& smspec_node::operator=( smspec_node&& rhs ) { - this->node = std::move( rhs.node ); - return *this; - } - - int smspec_node::cmp( const smspec_node& node1, const smspec_node& node2) { - return smspec_node_cmp( node1.get() , node2.get() ); - } - - static const int dummy_dims[ 3 ] = { -1, -1, -1 }; - const auto default_join = ":"; - - static int global_index( const int dims[ 3 ], const int ijk[ 3 ] ) { - /* num is offset 1 global index */ - return 1 + ijk[ 0 ] + ( ijk[ 1 ] * dims[ 0 ] ) + ( ijk[ 2 ] * dims[ 1 ] * dims[ 0 ] ); - } - - smspec_node::smspec_node( - ecl_smspec_var_type var_type, - const std::string& name, - const std::string& kw - ) : smspec_node( var_type, name.c_str(), kw.c_str(), "", default_join, dummy_dims, 0 ) - {} - - smspec_node::smspec_node( const std::string& keyword ) : - smspec_node( ecl_smspec_identify_var_type( keyword.c_str() ), - "", - keyword.c_str(), - "", - default_join, - dummy_dims, - 0 ) - {} - - smspec_node::smspec_node( - const std::string& keyword, - const int dims[ 3 ], - const int ijk[ 3 ] ) : - smspec_node( - ECL_SMSPEC_BLOCK_VAR, "", keyword.c_str(), "", default_join, dims, global_index( dims, ijk ) - ) - {} - - smspec_node::smspec_node( - const std::string& keyword, - const std::string& wellname, - const int dims[ 3 ], - const int ijk[ 3 ] ) : - smspec_node( - ECL_SMSPEC_COMPLETION_VAR, wellname.c_str(), keyword.c_str(), "", default_join, dims, global_index( dims, ijk ) - ) - {} - - smspec_node::smspec_node( - const std::string& keyword, - const int dims[ 3 ], - int region ) : - smspec_node( - ECL_SMSPEC_REGION_VAR, "", keyword.c_str(), "", default_join, dims, region - ) - {} - - smspec_node::smspec_node( - ecl_smspec_var_type type, - const char* wgname, - const char* keyword, - const char* unit, - const char* join, - const int grid_dims[ 3 ], - int num, int index, float default_value ) : - node( smspec_node_alloc( type, wgname, keyword, unit, - join, grid_dims, num, index, default_value ) ) - {} - - int smspec_node::type() const { - return smspec_node_get_var_type( this->node.get() ); - } - - const char* smspec_node::wgname() const { - return smspec_node_get_wgname( this->node.get() ); - } - - const char* smspec_node::keyword() const { - return smspec_node_get_keyword( this->node.get() ); - } - - const char* smspec_node::key1() const { - return smspec_node_get_gen_key1( this->node.get() ); - } - - int smspec_node::num() const { - return smspec_node_get_num( this->node.get() ); - } - - smspec_node_type* smspec_node::get() { - return this->node.get(); - } - - const smspec_node_type* smspec_node::get() const { - return this->node.get(); - } -} diff --git a/ThirdParty/Ert/lib/ecl/ecl_box.cpp b/ThirdParty/Ert/lib/ecl/ecl_box.cpp index 292e7a78b5..de0c5b3e68 100644 --- a/ThirdParty/Ert/lib/ecl/ecl_box.cpp +++ b/ThirdParty/Ert/lib/ecl/ecl_box.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'ecl_box.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/ecl_coarse_cell.cpp b/ThirdParty/Ert/lib/ecl/ecl_coarse_cell.cpp index 44fb620c58..09cd1a0d6b 100644 --- a/ThirdParty/Ert/lib/ecl/ecl_coarse_cell.cpp +++ b/ThirdParty/Ert/lib/ecl/ecl_coarse_cell.cpp @@ -1,5 +1,5 @@ /* - Copyright (c) 2012 statoil asa, norway. + Copyright (c) 2012 equinor asa, norway. The file 'ecl_coarse_cell.c' is part of ert - ensemble based reservoir tool. diff --git a/ThirdParty/Ert/lib/ecl/ecl_file.cpp b/ThirdParty/Ert/lib/ecl/ecl_file.cpp index 6384912bf6..d99e468623 100644 --- a/ThirdParty/Ert/lib/ecl/ecl_file.cpp +++ b/ThirdParty/Ert/lib/ecl/ecl_file.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'ecl_file.c' is part of ERT - Ensemble based Reservoir Tool. @@ -534,10 +534,13 @@ static void ecl_file_scan( ecl_file_type * ecl_file ) { if (read_status == ECL_KW_READ_OK) { ecl_file_kw_type * file_kw = ecl_file_kw_alloc( work_kw , current_offset); + if (ecl_file_kw_fskip_data( file_kw , ecl_file->fortio )) ecl_file_view_add_kw( ecl_file->global_view , file_kw ); - else + else { + ecl_file_kw_free( file_kw ); break; + } } } } diff --git a/ThirdParty/Ert/lib/ecl/ecl_file_kw.cpp b/ThirdParty/Ert/lib/ecl/ecl_file_kw.cpp index 5d5065c370..4bc20c32cc 100644 --- a/ThirdParty/Ert/lib/ecl/ecl_file_kw.cpp +++ b/ThirdParty/Ert/lib/ecl/ecl_file_kw.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'ecl_file_kw.c' is part of ERT - Ensemble based Reservoir Tool. @@ -91,7 +91,7 @@ static void inv_map_assert_sort( inv_map_type * map ) { size_t_vector_permute( map->file_kw_ptr , perm ); map->sorted = true; - free( perm ); + perm_vector_free( perm ); } } diff --git a/ThirdParty/Ert/lib/ecl/ecl_file_view.cpp b/ThirdParty/Ert/lib/ecl/ecl_file_view.cpp index 0a6e0a7622..f8fdd15999 100644 --- a/ThirdParty/Ert/lib/ecl/ecl_file_view.cpp +++ b/ThirdParty/Ert/lib/ecl/ecl_file_view.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2016 Statoil ASA, Norway. + Copyright (C) 2016 Equinor ASA, Norway. The file 'ecl_file_view.c' is part of ERT - Ensemble based Reservoir Tool. @@ -19,9 +19,7 @@ #include #include - -#include -#include +#include #include #include @@ -33,13 +31,13 @@ struct ecl_file_view_struct { - vector_type * kw_list; /* This is a vector of ecl_file_kw instances corresponding to the content of the file. */ - hash_type * kw_index; /* A hash table with integer vectors of indices - see comment below. */ + std::vector kw_list; + std::map> kw_index; std::vector distinct_kw; /* A list of the keywords occuring in the file - each string occurs ONLY ONCE. */ fortio_type * fortio; /* The same fortio instance pointer as in the ecl_file styructure. */ bool owner; /* Is this map the owner of the ecl_file_kw instances; only true for the global_map. */ inv_map_type * inv_map; /* Shared reference owned by the ecl_file structure. */ - vector_type * child_list; + std::vector child_list; int * flags; }; @@ -75,9 +73,6 @@ const char * ecl_file_view_get_src_file( const ecl_file_view_type * file_view ) ecl_file_view_type * ecl_file_view_alloc( fortio_type * fortio , int * flags , inv_map_type * inv_map , bool owner ) { ecl_file_view_type * ecl_file_view = new ecl_file_view_type(); - ecl_file_view->kw_list = vector_alloc_new(); - ecl_file_view->kw_index = hash_alloc(); - ecl_file_view->child_list = vector_alloc_new(); ecl_file_view->owner = owner; ecl_file_view->fortio = fortio; ecl_file_view->inv_map = inv_map; @@ -87,9 +82,8 @@ ecl_file_view_type * ecl_file_view_alloc( fortio_type * fortio , int * flags , i } int ecl_file_view_get_global_index( const ecl_file_view_type * ecl_file_view , const char * kw , int ith) { - const int_vector_type * index_vector = (const int_vector_type*)hash_get(ecl_file_view->kw_index , kw); - int global_index = int_vector_iget( index_vector , ith); - return global_index; + const auto& index_vector = ecl_file_view->kw_index.at(kw); + return index_vector[ith]; } @@ -105,34 +99,28 @@ int ecl_file_view_get_global_index( const ecl_file_view_type * ecl_file_view , c void ecl_file_view_make_index( ecl_file_view_type * ecl_file_view ) { ecl_file_view->distinct_kw.clear(); - hash_clear( ecl_file_view->kw_index ); + ecl_file_view->kw_index.clear(); { - int i; - for (i=0; i < vector_get_size( ecl_file_view->kw_list ); i++) { - const ecl_file_kw_type * file_kw = (const ecl_file_kw_type*)vector_iget_const( ecl_file_view->kw_list , i); - const char * header = ecl_file_kw_get_header( file_kw ); - if ( !hash_has_key( ecl_file_view->kw_index , header )) { - int_vector_type * index_vector = int_vector_alloc( 0 , -1 ); - hash_insert_hash_owned_ref( ecl_file_view->kw_index , header , index_vector , int_vector_free__); + int global_index = 0; + for (const auto& file_kw : ecl_file_view->kw_list) { + const std::string& header = ecl_file_kw_get_header( file_kw ); + if (ecl_file_view->kw_index.find(header) == ecl_file_view->kw_index.end()) ecl_file_view->distinct_kw.push_back(header); - } - { - int_vector_type * index_vector = (int_vector_type*)hash_get( ecl_file_view->kw_index , header); - int_vector_append( index_vector , i); - } + auto& index_vector = ecl_file_view->kw_index[header]; + index_vector.push_back(global_index); + global_index++; } } } bool ecl_file_view_has_kw( const ecl_file_view_type * ecl_file_view, const char * kw) { - return hash_has_key( ecl_file_view->kw_index , kw ); + return (ecl_file_view->kw_index.find(kw) != ecl_file_view->kw_index.end()); } ecl_file_kw_type * ecl_file_view_iget_file_kw( const ecl_file_view_type * ecl_file_view , int global_index) { - ecl_file_kw_type * file_kw = (ecl_file_kw_type*)vector_iget( ecl_file_view->kw_list , global_index); - return file_kw; + return ecl_file_view->kw_list[global_index]; } ecl_file_kw_type * ecl_file_view_iget_named_file_kw( const ecl_file_view_type * ecl_file_view , const char * kw, int ith) { @@ -188,12 +176,12 @@ void ecl_file_view_index_fload_kw(const ecl_file_view_type * ecl_file_view, cons int ecl_file_view_find_kw_value( const ecl_file_view_type * ecl_file_view , const char * kw , const void * value) { int global_index = -1; if ( ecl_file_view_has_kw( ecl_file_view , kw)) { - const int_vector_type * index_list = (const int_vector_type*)hash_get( ecl_file_view->kw_index , kw ); - int index = 0; - while (index < int_vector_size( index_list )) { - const ecl_kw_type * ecl_kw = ecl_file_view_iget_kw( ecl_file_view , int_vector_iget( index_list , index )); + const auto& index_list = ecl_file_view->kw_index.at(kw); + size_t index = 0; + while (index < index_list.size()) { + const ecl_kw_type * ecl_kw = ecl_file_view_iget_kw( ecl_file_view , index_list[index]); if (ecl_kw_data_equal( ecl_kw , value )) { - global_index = int_vector_iget( index_list , index ); + global_index = index_list[index]; break; } index++; @@ -212,7 +200,7 @@ int ecl_file_view_get_num_distinct_kw( const ecl_file_view_type * ecl_file_view } int ecl_file_view_get_size( const ecl_file_view_type * ecl_file_view ) { - return vector_get_size( ecl_file_view->kw_list ); + return ecl_file_view->kw_list.size(); } @@ -249,9 +237,9 @@ int ecl_file_view_iget_named_size( const ecl_file_view_type * ecl_file_view , co void ecl_file_view_replace_kw( ecl_file_view_type * ecl_file_view , ecl_kw_type * old_kw , ecl_kw_type * new_kw , bool insert_copy) { - int index = 0; - while (index < vector_get_size( ecl_file_view->kw_list )) { - ecl_file_kw_type * ikw = (ecl_file_kw_type*)vector_iget( ecl_file_view->kw_list , index ); + size_t index = 0; + while (index < ecl_file_view->kw_list.size() ) { + auto * ikw = ecl_file_view->kw_list[index]; if (ecl_file_kw_ptr_eq( ikw , old_kw)) { /* Found it; observe that the vector_iset() function will @@ -276,11 +264,8 @@ bool ecl_file_view_load_all( ecl_file_view_type * ecl_file_view ) { bool loadOK = false; if (fortio_assert_stream_open( ecl_file_view->fortio )) { - int index; - for (index = 0; index < vector_get_size( ecl_file_view->kw_list); index++) { - ecl_file_kw_type * ikw = (ecl_file_kw_type*)vector_iget( ecl_file_view->kw_list , index ); - ecl_file_kw_get_kw( ikw , ecl_file_view->fortio , ecl_file_view->inv_map); - } + for (ecl_file_kw_type * file_kw : ecl_file_view->kw_list) + ecl_file_kw_get_kw( file_kw, ecl_file_view->fortio , ecl_file_view->inv_map); loadOK = true; } @@ -296,16 +281,18 @@ bool ecl_file_view_load_all( ecl_file_view_type * ecl_file_view ) { void ecl_file_view_add_kw( ecl_file_view_type * ecl_file_view , ecl_file_kw_type * file_kw) { - if (ecl_file_view->owner) - vector_append_owned_ref( ecl_file_view->kw_list , file_kw , ecl_file_kw_free__ ); - else - vector_append_ref( ecl_file_view->kw_list , file_kw); + ecl_file_view->kw_list.push_back( file_kw ); } void ecl_file_view_free( ecl_file_view_type * ecl_file_view ) { - vector_free( ecl_file_view->child_list ); - hash_free( ecl_file_view->kw_index ); - vector_free( ecl_file_view->kw_list ); + + for (auto& child_ptr : ecl_file_view->child_list) + ecl_file_view_free(child_ptr); + + if (ecl_file_view->owner) { + for (auto& kw_ptr : ecl_file_view->kw_list) + ecl_file_kw_free( kw_ptr ); + } delete ecl_file_view; } @@ -317,16 +304,15 @@ void ecl_file_view_free__( void * arg ) { int ecl_file_view_get_num_named_kw(const ecl_file_view_type * ecl_file_view , const char * kw) { - if (hash_has_key(ecl_file_view->kw_index , kw)) { - const int_vector_type * index_vector = (const int_vector_type*)hash_get(ecl_file_view->kw_index , kw); - return int_vector_size( index_vector ); + if (ecl_file_view_has_kw(ecl_file_view, kw)) { + const auto& index_vector = ecl_file_view->kw_index.at(kw); + return index_vector.size(); } else return 0; } void ecl_file_view_fwrite( const ecl_file_view_type * ecl_file_view , fortio_type * target , int offset) { - int index; - for (index = offset; index < vector_get_size( ecl_file_view->kw_list ); index++) { + for (size_t index = offset; index < ecl_file_view->kw_list.size(); index++) { ecl_kw_type * ecl_kw = ecl_file_view_iget_kw( ecl_file_view , index ); ecl_kw_fwrite( ecl_kw , target ); } @@ -336,18 +322,17 @@ void ecl_file_view_fwrite( const ecl_file_view_type * ecl_file_view , fortio_typ int ecl_file_view_iget_occurence( const ecl_file_view_type * ecl_file_view , int global_index) { - const ecl_file_kw_type * file_kw = (const ecl_file_kw_type*)vector_iget_const( ecl_file_view->kw_list , global_index); + const ecl_file_kw_type * file_kw = ecl_file_view->kw_list[global_index]; const char * header = ecl_file_kw_get_header( file_kw ); - const int_vector_type * index_vector = (const int_vector_type*)hash_get( ecl_file_view->kw_index , header ); - const int * index_data = int_vector_get_const_ptr( index_vector ); + const auto& index_vector = ecl_file_view->kw_index.at(header); int occurence = -1; { /* Manual reverse lookup. */ - int i; - for (i=0; i < int_vector_size( index_vector ); i++) - if (index_data[i] == global_index) + for (size_t i=0; i < index_vector.size(); i++) { + if (index_vector[i] == global_index) occurence = i; + } } if (occurence < 0) util_abort("%s: internal error ... \n" , __func__); @@ -356,9 +341,7 @@ int ecl_file_view_iget_occurence( const ecl_file_view_type * ecl_file_view , int } void ecl_file_view_fprintf_kw_list(const ecl_file_view_type * ecl_file_view , FILE * stream) { - int i; - for (i=0; i < vector_get_size( ecl_file_view->kw_list ); i++) { - const ecl_file_kw_type * file_kw = (const ecl_file_kw_type*)vector_iget_const( ecl_file_view->kw_list , i ); + for (auto& file_kw : ecl_file_view->kw_list) { char * type_name = ecl_type_alloc_name(ecl_file_kw_get_data_type(file_kw)); fprintf(stream , "%-8s %7d:%s\n", ecl_file_kw_get_header( file_kw ) , @@ -375,21 +358,21 @@ ecl_file_view_type * ecl_file_view_alloc_blockview2(const ecl_file_view_type * e ecl_file_view_type * block_map = ecl_file_view_alloc( ecl_file_view->fortio , ecl_file_view->flags , ecl_file_view->inv_map , false); - int kw_index = 0; + size_t kw_index = 0; if (start_kw) kw_index = ecl_file_view_get_global_index( ecl_file_view , start_kw , occurence ); { - ecl_file_kw_type * file_kw = (ecl_file_kw_type*)vector_iget( ecl_file_view->kw_list , kw_index ); + ecl_file_kw_type * file_kw = ecl_file_view->kw_list[kw_index]; while (true) { ecl_file_view_add_kw( block_map , file_kw ); kw_index++; - if (kw_index == vector_get_size( ecl_file_view->kw_list )) + if (kw_index == ecl_file_view->kw_list.size()) break; else { if (end_kw) { - file_kw = (ecl_file_kw_type*)vector_iget(ecl_file_view->kw_list , kw_index); + file_kw = ecl_file_view->kw_list[kw_index]; if (strcmp( end_kw , ecl_file_kw_get_header( file_kw )) == 0) break; } @@ -408,21 +391,21 @@ ecl_file_view_type * ecl_file_view_alloc_blockview(const ecl_file_view_type * ec } -ecl_file_view_type * ecl_file_view_add_blockview(const ecl_file_view_type * file_view , const char * header, int occurence) { +ecl_file_view_type * ecl_file_view_add_blockview(ecl_file_view_type * file_view , const char * header, int occurence) { ecl_file_view_type * child = ecl_file_view_alloc_blockview2(file_view, header, header, occurence); if (child) - vector_append_owned_ref( file_view->child_list , child , ecl_file_view_free__ ); + file_view->child_list.push_back(child); return child; } -ecl_file_view_type * ecl_file_view_add_blockview2(const ecl_file_view_type * ecl_file_view , const char * start_kw, const char * end_kw, int occurence) { +ecl_file_view_type * ecl_file_view_add_blockview2(ecl_file_view_type * ecl_file_view , const char * start_kw, const char * end_kw, int occurence) { ecl_file_view_type * child = ecl_file_view_alloc_blockview2(ecl_file_view, start_kw , end_kw , occurence); if (child) - vector_append_owned_ref( ecl_file_view->child_list , child , ecl_file_view_free__ ); + ecl_file_view->child_list.push_back(child); return child; } @@ -593,10 +576,10 @@ double ecl_file_view_iget_restart_sim_days(const ecl_file_view_type * ecl_file_v int ecl_file_view_find_sim_time(const ecl_file_view_type * ecl_file_view , time_t sim_time) { int seqnum_index = -1; if ( ecl_file_view_has_kw( ecl_file_view , INTEHEAD_KW)) { - const int_vector_type * intehead_index_list = (const int_vector_type *)hash_get( ecl_file_view->kw_index , INTEHEAD_KW ); - int index = 0; - while (index < int_vector_size( intehead_index_list )) { - const ecl_kw_type * intehead_kw = ecl_file_view_iget_kw( ecl_file_view , int_vector_iget( intehead_index_list , index )); + const auto& intehead_index_list = ecl_file_view->kw_index.at(INTEHEAD_KW); + size_t index = 0; + while (index < intehead_index_list.size()) { + const ecl_kw_type * intehead_kw = ecl_file_view_iget_kw( ecl_file_view , intehead_index_list[index] ); if (ecl_rsthead_date( intehead_kw ) == sim_time) { seqnum_index = index; break; @@ -832,6 +815,8 @@ void ecl_file_view_end_transaction( ecl_file_view_type * file_view, ecl_file_tra ecl_file_kw_type * file_kw = ecl_file_view_iget_file_kw(file_view, i); ecl_file_kw_end_transaction(file_kw, ref_count[i]); } + free(transaction->ref_count); + free(transaction); } diff --git a/ThirdParty/Ert/lib/ecl/ecl_grav.cpp b/ThirdParty/Ert/lib/ecl/ecl_grav.cpp index 42e96c240b..2503317369 100644 --- a/ThirdParty/Ert/lib/ecl/ecl_grav.cpp +++ b/ThirdParty/Ert/lib/ecl/ecl_grav.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. This file is part of ERT - Ensemble based Reservoir Tool. @@ -20,9 +20,11 @@ #include #include +#include +#include +#include + #include -#include -#include #include #include @@ -69,12 +71,10 @@ struct ecl_grav_struct { const ecl_file_type * init_file; /* The init file - a shared reference owned by calling scope. */ ecl::ecl_grid_cache * grid_cache; /* An internal specialized structure to facilitate fast grid lookup. */ bool * aquifer_cell; /* Numerical aquifer cells should be ignored. */ - hash_type * surveys; /* A hash table containg ecl_grav_survey_type instances; one instance - for each interesting time. */ - hash_type * std_density; /* Hash table indexed with "SWAT" , "SGAS" and "SOIL"; each element - is a double_vector() instance which is indexed by PVTNUM - values. Used to lookup standard condition mass densities. Must - be suuplied by user __BEFORE__ adding a FIP based survey. */ + + std::unordered_map surveys; + std::unordered_map default_density; + std::unordered_map> std_density; }; @@ -90,10 +90,10 @@ struct ecl_grav_survey_struct { UTIL_TYPE_ID_DECLARATION; const ecl::ecl_grid_cache * grid_cache; const bool * aquifer_cell; - char * name; /* Name of the survey - arbitrary string. */ - double * porv; /* Reference shared by the ecl_grav_phase structures - i.e. it must not be updated. */ - vector_type * phase_list; /* ecl_grav_phase_type objects - one for each phase present in the model. */ - hash_type * phase_map; /* The same objects as in the phase_list vector - accessible by the "SWAT", "SGAS" and "SOIL" keys. */ + char * name; /* Name of the survey - arbitrary string. */ + double * porv; /* Reference shared by the ecl_grav_phase structures - i.e. it must not be updated. */ + std::vector phase_list; /* ecl_grav_phase_type objects - one for each phase present in the model. */ + std::unordered_map phase_map; /* The same objects as in the phase_list vector - accessible by the "SWAT", "SGAS" and "SOIL" keys. */ }; @@ -106,9 +106,9 @@ struct ecl_grav_phase_struct { UTIL_TYPE_ID_DECLARATION; const ecl::ecl_grid_cache * grid_cache; const bool * aquifer_cell; - double * fluid_mass; /* The total fluid in place (mass) of this phase - for each active cell.*/ - double * work; /* Temporary used in the summation over all cells. */ - ecl_phase_enum phase; + double * fluid_mass; /* The total fluid in place (mass) of this phase - for each active cell.*/ + double * work; /* Temporary used in the summation over all cells. */ + ecl_phase_enum phase; }; @@ -213,7 +213,7 @@ static ecl_grav_phase_type * ecl_grav_phase_alloc( ecl_grav_type * ecl_grav , const ecl::ecl_grid_cache * grid_cache = ecl_grav->grid_cache; const char * sat_kw_name = ecl_util_get_phase_name( phase ); { - ecl_grav_phase_type * grav_phase = (ecl_grav_phase_type*)util_malloc( sizeof * grav_phase ); + ecl_grav_phase_type * grav_phase = new ecl_grav_phase_type(); const int size = grid_cache->size(); UTIL_TYPE_ID_INIT( grav_phase , ECL_GRAV_PHASE_TYPE_ID ); @@ -225,7 +225,7 @@ static ecl_grav_phase_type * ecl_grav_phase_alloc( ecl_grav_type * ecl_grav , if (calc_type == GRAV_CALC_FIP) { ecl_kw_type * pvtnum_kw = ecl_file_iget_named_kw( init_file , PVTNUM_KW , 0 ); - double_vector_type * std_density = (double_vector_type*)hash_get( ecl_grav->std_density , ecl_util_get_phase_name( phase )); + const std::vector std_density = ecl_grav->std_density[std::string(ecl_util_get_phase_name(phase))]; ecl_kw_type * fip_kw; if ( phase == ECL_OIL_PHASE) @@ -240,7 +240,7 @@ static ecl_grav_phase_type * ecl_grav_phase_alloc( ecl_grav_type * ecl_grav , for (iactive=0; iactive < size; iactive++) { double fip = ecl_kw_iget_as_double( fip_kw , iactive ); int pvtnum = ecl_kw_iget_int( pvtnum_kw , iactive ); - grav_phase->fluid_mass[ iactive ] = fip * double_vector_safe_iget( std_density , pvtnum ); + grav_phase->fluid_mass[ iactive ] = fip * std_density[pvtnum]; } } } else { @@ -307,23 +307,18 @@ static ecl_grav_phase_type * ecl_grav_phase_alloc( ecl_grav_type * ecl_grav , static void ecl_grav_phase_free( ecl_grav_phase_type * grav_phase ) { free( grav_phase->work ); free( grav_phase->fluid_mass ); - free( grav_phase ); + delete grav_phase; } -static UTIL_SAFE_CAST_FUNCTION( ecl_grav_phase , ECL_GRAV_PHASE_TYPE_ID ) -static void ecl_grav_phase_free__( void * __grav_phase) { - ecl_grav_phase_type * grav_phase = ecl_grav_phase_safe_cast( __grav_phase ); - ecl_grav_phase_free( grav_phase ); -} /*****************************************************************/ static void ecl_grav_survey_add_phase( ecl_grav_survey_type * survey, ecl_phase_enum phase , ecl_grav_phase_type * grav_phase ) { - vector_append_owned_ref( survey->phase_list , grav_phase , ecl_grav_phase_free__ ); - hash_insert_ref( survey->phase_map , ecl_util_get_phase_name( phase ) , grav_phase ); + survey->phase_list.push_back(grav_phase); + survey->phase_map[std::string(ecl_util_get_phase_name(phase))] = grav_phase; } @@ -349,13 +344,11 @@ static void ecl_grav_survey_add_phases( ecl_grav_type * ecl_grav , ecl_grav_surv static ecl_grav_survey_type * ecl_grav_survey_alloc_empty(const ecl_grav_type * ecl_grav , const char * name , grav_calc_type calc_type) { - ecl_grav_survey_type * survey = (ecl_grav_survey_type*)util_malloc( sizeof * survey ); + ecl_grav_survey_type * survey = new ecl_grav_survey_type(); UTIL_TYPE_ID_INIT( survey , ECL_GRAV_SURVEY_ID ); survey->grid_cache = ecl_grav->grid_cache; survey->aquifer_cell = ecl_grav->aquifer_cell; survey->name = util_alloc_string_copy( name ); - survey->phase_list = vector_alloc_new(); - survey->phase_map = hash_alloc(); if (calc_type & GRAV_CALC_USE_PORV) survey->porv = (double*)util_calloc( ecl_grav->grid_cache->size() , sizeof * survey->porv ); @@ -365,8 +358,6 @@ static ecl_grav_survey_type * ecl_grav_survey_alloc_empty(const ecl_grav_type * return survey; } -static UTIL_SAFE_CAST_FUNCTION( ecl_grav_survey , ECL_GRAV_SURVEY_ID ) - /** Check that the rporv values are in the right ballpark. For ECLIPSE @@ -530,15 +521,12 @@ static ecl_grav_survey_type * ecl_grav_survey_alloc_RFIP(ecl_grav_type * ecl_gra static void ecl_grav_survey_free( ecl_grav_survey_type * grav_survey ) { free( grav_survey->name ); free( grav_survey->porv ); - vector_free( grav_survey->phase_list ); - hash_free( grav_survey->phase_map ); - free( grav_survey ); + for (auto * phase : grav_survey->phase_list) + ecl_grav_phase_free( phase ); + + delete grav_survey; } -static void ecl_grav_survey_free__( void * __grav_survey ) { - ecl_grav_survey_type * grav_survey = ecl_grav_survey_safe_cast( __grav_survey ); - ecl_grav_survey_free( grav_survey ); -} @@ -546,13 +534,12 @@ static double ecl_grav_survey_eval( const ecl_grav_survey_type * base_survey, const ecl_grav_survey_type * monitor_survey , ecl_region_type * region , double utm_x , double utm_y , double depth, int phase_mask) { - int phase_nr; double deltag = 0; - for (phase_nr = 0; phase_nr < vector_get_size( base_survey->phase_list ); phase_nr++) { - ecl_grav_phase_type * base_phase = (ecl_grav_phase_type*)vector_iget( base_survey->phase_list , phase_nr ); + for (std::size_t phase_nr = 0; phase_nr < base_survey->phase_list.size(); phase_nr++) { + ecl_grav_phase_type * base_phase = base_survey->phase_list[phase_nr]; if (base_phase->phase & phase_mask) { if (monitor_survey != NULL) { - const ecl_grav_phase_type * monitor_phase = (const ecl_grav_phase_type*)vector_iget_const( monitor_survey->phase_list , phase_nr ); + const ecl_grav_phase_type * monitor_phase = monitor_survey->phase_list[phase_nr]; deltag += ecl_grav_phase_eval( base_phase , monitor_phase , region , utm_x , utm_y , depth ); } else deltag += ecl_grav_phase_eval( base_phase , NULL , region , utm_x , utm_y , depth ); @@ -570,20 +557,19 @@ static double ecl_grav_survey_eval( const ecl_grav_survey_type * base_survey, */ ecl_grav_type * ecl_grav_alloc( const ecl_grid_type * ecl_grid, const ecl_file_type * init_file) { - ecl_grav_type * ecl_grav = (ecl_grav_type*)util_malloc( sizeof * ecl_grav ); + ecl_grav_type * ecl_grav = new ecl_grav_type(); + ecl_grav->init_file = init_file; ecl_grav->grid_cache = new ecl::ecl_grid_cache(ecl_grid); ecl_grav->aquifer_cell = ecl_grav_common_alloc_aquifer_cell( *(ecl_grav->grid_cache) , ecl_grav->init_file ); - ecl_grav->surveys = hash_alloc(); - ecl_grav->std_density = hash_alloc(); return ecl_grav; } static void ecl_grav_add_survey__( ecl_grav_type * grav , const char * name , ecl_grav_survey_type * survey) { - hash_insert_hash_owned_ref( grav->surveys , name , survey , ecl_grav_survey_free__ ); + grav->surveys[name] = survey; } @@ -618,17 +604,15 @@ static ecl_grav_survey_type * ecl_grav_get_survey( const ecl_grav_type * grav , if (name == NULL) return NULL; // Calling scope must determine if this is OK? else { - if (hash_has_key( grav->surveys , name)) - return (ecl_grav_survey_type*)hash_get( grav->surveys , name ); + if (grav->surveys.count(name) > 0) + return grav->surveys.at(name); else { - hash_iter_type * survey_iter = hash_iter_alloc( grav->surveys ); fprintf(stderr,"Survey name:%s not registered. Available surveys are: \n\n " , name); - while (!hash_iter_is_complete( survey_iter )) { - const char * survey = hash_iter_get_next_key( survey_iter ); - fprintf(stderr,"%s ",survey); - } + + for (const auto& survey_pair : grav->surveys) + fprintf(stderr,"%s ",survey_pair.first.c_str()); + fprintf(stderr,"\n\n"); - hash_iter_free( survey_iter ); exit(1); } } @@ -660,8 +644,7 @@ double ecl_grav_eval( const ecl_grav_type * grav , const char * base, const char void ecl_grav_new_std_density( ecl_grav_type * grav , ecl_phase_enum phase , double default_density) { const char * phase_key = ecl_util_get_phase_name( phase ); - if (!hash_has_key( grav->std_density , phase_key )) - hash_insert_hash_owned_ref( grav->std_density , phase_key , double_vector_alloc( 0 , default_density ) , double_vector_free__ ); + grav->default_density[std::string(phase_key)] = default_density; } /** @@ -680,8 +663,10 @@ void ecl_grav_new_std_density( ecl_grav_type * grav , ecl_phase_enum phase , dou void ecl_grav_add_std_density( ecl_grav_type * grav , ecl_phase_enum phase , int pvtnum , double density) { - double_vector_type * std_density = (double_vector_type*)hash_get( grav->std_density , ecl_util_get_phase_name( phase )); - double_vector_iset( std_density , pvtnum , density ); + std::vector& std_density = grav->std_density[ std::string(ecl_util_get_phase_name(phase)) ]; + if (std_density.size() <= static_cast(pvtnum)) + std_density.resize(pvtnum + 1, grav->default_density[ std::string(ecl_util_get_phase_name(phase)) ]); + std_density[pvtnum] = density; } @@ -689,7 +674,9 @@ void ecl_grav_add_std_density( ecl_grav_type * grav , ecl_phase_enum phase , int void ecl_grav_free( ecl_grav_type * ecl_grav ) { delete ecl_grav->grid_cache; free( ecl_grav->aquifer_cell ); - hash_free( ecl_grav->surveys ); - hash_free( ecl_grav->std_density ); - free( ecl_grav ); + + for (const auto& survey_pair : ecl_grav->surveys) + ecl_grav_survey_free( survey_pair.second ); + + delete ecl_grav; } diff --git a/ThirdParty/Ert/lib/ecl/ecl_grav_calc.cpp b/ThirdParty/Ert/lib/ecl/ecl_grav_calc.cpp index 240fc64a87..1c758a4701 100644 --- a/ThirdParty/Ert/lib/ecl/ecl_grav_calc.cpp +++ b/ThirdParty/Ert/lib/ecl/ecl_grav_calc.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'ecl_grav.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/ecl_grav_common.cpp b/ThirdParty/Ert/lib/ecl/ecl_grav_common.cpp index 9f63c9583c..8b33bc0fc5 100644 --- a/ThirdParty/Ert/lib/ecl/ecl_grav_common.cpp +++ b/ThirdParty/Ert/lib/ecl/ecl_grav_common.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'ecl_grav_common.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/ecl_grid.cpp b/ThirdParty/Ert/lib/ecl/ecl_grid.cpp index c01ece639a..2b59611a63 100644 --- a/ThirdParty/Ert/lib/ecl/ecl_grid.cpp +++ b/ThirdParty/Ert/lib/ecl/ecl_grid.cpp @@ -1,5 +1,5 @@ /* - Copyright (c) 2011 statoil asa, norway. + Copyright (c) 2011 equinor asa, norway. The file 'ecl_grid.c' is part of ert - ensemble based reservoir tool. @@ -21,12 +21,14 @@ #include #include #include + #include +#include +#include #include #include #include -#include #include #include @@ -726,7 +728,7 @@ struct ecl_grid_struct { char * parent_name; /* the name of the parent for a nested lgr - for the main grid, and also a lgr descending directly from the main grid this will be NULL. */ - hash_type * children; /* a table of lgr children for this grid. */ + std::unordered_map children; const ecl_grid_type * parent_grid; /* the parent grid for this (lgr) - NULL for the main grid. */ const ecl_grid_type * global_grid; /* the global grid - NULL for the main grid. */ @@ -739,7 +741,7 @@ struct ecl_grid_struct { */ vector_type * LGR_list; /* a vector of ecl_grid instances for LGRs - the index corresponds to the order LGRs are read from file*/ int_vector_type * lgr_index_map; /* a vector that maps LGR-nr for EGRID files to index into the LGR_list.*/ - hash_type * LGR_hash; /* a hash of pointers to ecl_grid instances - for name based lookup of lgr. */ + std::unordered_map LGR_hash; /* a hash of pointers to ecl_grid instances - for name based lookup of lgr. */ int parent_box[6]; /* integers i1,i2, j1,j2, k1,k2 of the parent grid region containing this lgr. the indices are inclusive - zero offset */ /* not used yet .. */ @@ -1534,7 +1536,7 @@ static ecl_grid_type * ecl_grid_alloc_empty(ecl_grid_type * global_grid, int nz, int lgr_nr, bool init_valid) { - ecl_grid_type * grid = (ecl_grid_type*)util_malloc(sizeof * grid ); + ecl_grid_type * grid = new ecl_grid_type(); UTIL_TYPE_ID_INIT(grid , ECL_GRID_ID); grid->total_active = 0; grid->total_active_fracture = 0; @@ -1586,16 +1588,13 @@ static ecl_grid_type * ecl_grid_alloc_empty(ecl_grid_type * global_grid, if (ECL_GRID_MAINGRID_LGR_NR == lgr_nr) { /* this is the main grid */ grid->LGR_list = vector_alloc_new(); grid->lgr_index_map = int_vector_alloc(0,0); - grid->LGR_hash = hash_alloc(); } else { grid->LGR_list = NULL; grid->lgr_index_map = NULL; - grid->LGR_hash = NULL; } grid->name = NULL; grid->parent_name = NULL; grid->parent_grid = NULL; - grid->children = hash_alloc(); grid->coarse_cells = vector_alloc_new(); grid->eclipse_version = 0; @@ -2104,13 +2103,15 @@ static void ecl_grid_init_mapaxes( ecl_grid_type * ecl_grid , bool apply_mapaxes static void ecl_grid_add_lgr( ecl_grid_type * main_grid , ecl_grid_type * lgr_grid) { vector_append_owned_ref( main_grid->LGR_list , lgr_grid , ecl_grid_free__); + if ( lgr_grid->lgr_nr >= int_vector_size(main_grid->lgr_index_map) ) + int_vector_resize( main_grid->lgr_index_map, lgr_grid->lgr_nr+1 , 0); int_vector_iset(main_grid->lgr_index_map, lgr_grid->lgr_nr, vector_get_size(main_grid->LGR_list)-1); - hash_insert_ref( main_grid->LGR_hash , lgr_grid->name , lgr_grid); + main_grid->LGR_hash[lgr_grid->name] = lgr_grid; } static void ecl_grid_install_lgr_common(ecl_grid_type * host_grid , ecl_grid_type * lgr_grid) { - hash_insert_ref( host_grid->children , lgr_grid->name , lgr_grid); + host_grid->children[lgr_grid->name] = lgr_grid; lgr_grid->parent_grid = host_grid; } @@ -3027,12 +3028,12 @@ static ecl_grid_type * ecl_grid_alloc_EGRID__( ecl_grid_type * main_grid , const */ const int * actnum_data = NULL; if (ext_actnum) - actnum_data = ext_actnum; + actnum_data = ext_actnum; else { - if (ecl_file_get_num_named_kw(ecl_file, ACTNUM_KW) > grid_nr) { - actnum_kw = ecl_file_iget_named_kw(ecl_file, ACTNUM_KW, grid_nr); - actnum_data = ecl_kw_get_int_ptr(actnum_kw); - } + if (ecl_file_get_num_named_kw(ecl_file , ACTNUM_KW) > grid_nr) { + actnum_kw = ecl_file_iget_named_kw( ecl_file , ACTNUM_KW , grid_nr); + actnum_data = ecl_kw_get_int_ptr(actnum_kw); + } } if (grid_nr == 0) { @@ -4625,17 +4626,15 @@ void ecl_grid_free(ecl_grid_type * grid) { if (ECL_GRID_MAINGRID_LGR_NR == grid->lgr_nr) { /* This is the main grid. */ vector_free( grid->LGR_list ); int_vector_free( grid->lgr_index_map); - hash_free( grid->LGR_hash ); } if (grid->coord_kw != NULL) ecl_kw_free( grid->coord_kw ); vector_free( grid->coarse_cells ); - hash_free( grid->children ); free( grid->parent_name ); free( grid->visited ); free( grid->name ); - free( grid ); + delete grid; } @@ -5284,7 +5283,7 @@ ecl_grid_type * ecl_grid_get_lgr(const ecl_grid_type * main_grid, const char * _ __assert_main_grid( main_grid ); { char * lgr_name = util_alloc_strip_copy( __lgr_name ); - ecl_grid_type * lgr_grid = (ecl_grid_type*)hash_get(main_grid->LGR_hash , lgr_name); + ecl_grid_type * lgr_grid = main_grid->LGR_hash.at(lgr_name); free(lgr_name); return lgr_grid; } @@ -5303,7 +5302,7 @@ bool ecl_grid_has_lgr(const ecl_grid_type * main_grid, const char * __lgr_name) __assert_main_grid( main_grid ); { char * lgr_name = util_alloc_strip_copy( __lgr_name ); - bool has_lgr = hash_has_key( main_grid->LGR_hash , lgr_name ); + bool has_lgr = main_grid->LGR_hash.count(lgr_name ) > 0; free(lgr_name); return has_lgr; } @@ -5425,7 +5424,10 @@ const ecl_grid_type * ecl_grid_get_global_grid( const ecl_grid_type * grid ) { stringlist_type * ecl_grid_alloc_lgr_name_list(const ecl_grid_type * ecl_grid) { __assert_main_grid( ecl_grid ); { - return hash_alloc_stringlist( ecl_grid->LGR_hash ); + stringlist_type * s = stringlist_alloc_new(); + for (const auto& lgr_pair : ecl_grid->LGR_hash) + stringlist_append_copy(s, lgr_pair.first.c_str()); + return s; } } @@ -5892,14 +5894,12 @@ static bool ecl_grid_test_lgr_consistency2( const ecl_grid_type * parent , const bool ecl_grid_test_lgr_consistency( const ecl_grid_type * ecl_grid ) { - hash_iter_type * lgr_iter = hash_iter_alloc( ecl_grid->children ); bool consistent = true; - while (!hash_iter_is_complete( lgr_iter )) { - const ecl_grid_type * lgr = (const ecl_grid_type*)hash_iter_get_next_value( lgr_iter ); + for (const auto& lgr_pair : ecl_grid->children) { + const ecl_grid_type * lgr = lgr_pair.second; consistent &= ecl_grid_test_lgr_consistency2( ecl_grid , lgr ); consistent &= ecl_grid_test_lgr_consistency( lgr ); } - hash_iter_free( lgr_iter ); return consistent; } @@ -6208,6 +6208,8 @@ static void ecl_grid_fwrite_GRID__( const ecl_grid_type * grid , int coords_size } } } + ecl_kw_free(coords_kw); + ecl_kw_free(corners_kw); } } @@ -6217,7 +6219,7 @@ void ecl_grid_fwrite_GRID2( const ecl_grid_type * grid , const char * filename, bool fmt_file = false; fortio_type * fortio = fortio_open_writer( filename , fmt_file , ECL_ENDIAN_FLIP ); - if (hash_get_size( grid->children ) > 0) + if (grid->children.size() > 0) coords_size = 7; if (grid->coarsening_active) @@ -6852,6 +6854,12 @@ static void ecl_grid_fwrite_EGRID__( ecl_grid_type * grid , fortio_type * fortio void ecl_grid_fwrite_EGRID2( ecl_grid_type * grid , const char * filename, ert_ecl_unit_enum output_unit) { bool fmt_file = false; + { + bool is_fmt; + + if (ecl_util_get_file_type( filename , &is_fmt, NULL ) != ECL_OTHER_FILE) + fmt_file = is_fmt; + } fortio_type * fortio = fortio_open_writer( filename , fmt_file , ECL_ENDIAN_FLIP ); ecl_grid_fwrite_EGRID__( grid , fortio, output_unit); diff --git a/ThirdParty/Ert/lib/ecl/ecl_grid_cache.cpp b/ThirdParty/Ert/lib/ecl/ecl_grid_cache.cpp index 46dd0d9db5..7b2e394537 100644 --- a/ThirdParty/Ert/lib/ecl/ecl_grid_cache.cpp +++ b/ThirdParty/Ert/lib/ecl/ecl_grid_cache.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'ecl_grid_cache.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/ecl_grid_dims.cpp b/ThirdParty/Ert/lib/ecl/ecl_grid_dims.cpp index 8df249dcf1..f5fbeb2d69 100644 --- a/ThirdParty/Ert/lib/ecl/ecl_grid_dims.cpp +++ b/ThirdParty/Ert/lib/ecl/ecl_grid_dims.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'ecl_grid_dims.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/ecl_init_file.cpp b/ThirdParty/Ert/lib/ecl/ecl_init_file.cpp index f8b1bc656f..dbca59ab56 100644 --- a/ThirdParty/Ert/lib/ecl/ecl_init_file.cpp +++ b/ThirdParty/Ert/lib/ecl/ecl_init_file.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Statoil ASA, Norway. + Copyright (C) 2012 Equinor ASA, Norway. The file 'ecl_init_file.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/ecl_io_config.cpp b/ThirdParty/Ert/lib/ecl/ecl_io_config.cpp index 9ad54c46be..893ff6f985 100644 --- a/ThirdParty/Ert/lib/ecl/ecl_io_config.cpp +++ b/ThirdParty/Ert/lib/ecl/ecl_io_config.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'ecl_io_config.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/ecl_kw.cpp b/ThirdParty/Ert/lib/ecl/ecl_kw.cpp index b71c0c0ac6..abf24340ea 100644 --- a/ThirdParty/Ert/lib/ecl/ecl_kw.cpp +++ b/ThirdParty/Ert/lib/ecl/ecl_kw.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'ecl_kw.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/ecl_kw_grdecl.cpp b/ThirdParty/Ert/lib/ecl/ecl_kw_grdecl.cpp index 5d76c7f36d..3e60d55dc0 100644 --- a/ThirdParty/Ert/lib/ecl/ecl_kw_grdecl.cpp +++ b/ThirdParty/Ert/lib/ecl/ecl_kw_grdecl.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'ecl_kw_grdecl.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/ecl_nnc_data.cpp b/ThirdParty/Ert/lib/ecl/ecl_nnc_data.cpp index 1e9f813927..434dfc4664 100644 --- a/ThirdParty/Ert/lib/ecl/ecl_nnc_data.cpp +++ b/ThirdParty/Ert/lib/ecl/ecl_nnc_data.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2017 Statoil ASA, Norway. + Copyright (C) 2017 Equinor ASA, Norway. The file 'ecl_file_view.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/ecl_nnc_export.cpp b/ThirdParty/Ert/lib/ecl/ecl_nnc_export.cpp index 79cec6dabb..af05f4c3ac 100644 --- a/ThirdParty/Ert/lib/ecl/ecl_nnc_export.cpp +++ b/ThirdParty/Ert/lib/ecl/ecl_nnc_export.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'ecl_nnc_export.c' is part of ERT - Ensemble based Reservoir Tool. @@ -17,7 +17,7 @@ */ #include -#include +#include #include #include @@ -26,11 +26,47 @@ #include -int ecl_nnc_export_get_size( const ecl_grid_type * grid ) { - return ecl_grid_get_num_nnc( grid ); + +/** + * Return true if the NNC information is stored in the Intersect format, false otherwise. + * In the Intersect format, the NNC information stored in the grid is unrealiable. + * The correct NNC data is stored in the init file instead + */ +bool ecl_nnc_intersect_format(const ecl_grid_type * grid, const ecl_file_type * init_file) { + if( !ecl_file_has_kw(init_file, NNC1_KW) || + !ecl_file_has_kw(init_file, NNC2_KW) || + !ecl_file_has_kw(init_file, TRANNNC_KW)) + return false; + // In the specific case we are treating, there should be just 1 occurrence of the kw + const auto nnc1_num = ecl_kw_get_size(ecl_file_iget_named_kw(init_file, NNC1_KW, 0)); + const auto nnc2_num = ecl_kw_get_size(ecl_file_iget_named_kw(init_file, NNC2_KW, 0)); + const auto tran_num = ecl_kw_get_size(ecl_file_iget_named_kw(init_file, TRANNNC_KW, 0)); + return nnc1_num == tran_num && nnc2_num == tran_num; } +int ecl_nnc_export_get_size( const ecl_grid_type * grid , const ecl_file_type * init_file ) { + return ecl_nnc_intersect_format(grid, init_file) ? + ecl_kw_get_size(ecl_file_iget_named_kw(init_file, TRANNNC_KW, 0)) : // Intersect format + ecl_grid_get_num_nnc( grid ); // Eclipse format +} + +static int ecl_nnc_export_intersect__(const ecl_file_type * init_file , ecl_nnc_type * nnc_data, int * nnc_offset) { + const auto nnc1_kw = ecl_file_iget_named_kw(init_file, NNC1_KW, 0); + const auto nnc2_kw = ecl_file_iget_named_kw(init_file, NNC2_KW, 0); + const auto tran_kw = ecl_file_iget_named_kw(init_file, TRANNNC_KW, 0); + + auto nnc_index = *nnc_offset; + for(int i = 0; i < ecl_kw_get_size(tran_kw); ++i) { + auto const nnc1 = ecl_kw_iget_int(nnc1_kw, i); + auto const nnc2 = ecl_kw_iget_int(nnc2_kw, i); + auto const tran = ecl_kw_iget_as_double(tran_kw, i); + nnc_data[nnc_index] = ecl_nnc_type{0, nnc1, 0, nnc2, i, tran}; + ++nnc_index; + } + *nnc_offset = nnc_index; + return ecl_kw_get_size(tran_kw); // Assume all valid +} static int ecl_nnc_export__( const ecl_grid_type * grid , int lgr_index1 , const ecl_file_type * init_file , ecl_nnc_type * nnc_data, int * nnc_offset) { @@ -50,8 +86,8 @@ static int ecl_nnc_export__( const ecl_grid_type * grid , int lgr_index1 , cons int lgr_index2; for (lgr_index2=0; lgr_index2 < nnc_info_get_size( nnc_info ); lgr_index2++) { const nnc_vector_type * nnc_vector = nnc_info_iget_vector( nnc_info , lgr_index2 ); - const int_vector_type * grid2_index_list = nnc_vector_get_grid_index_list( nnc_vector ); - const int_vector_type * nnc_index_list = nnc_vector_get_nnc_index_list( nnc_vector ); + const std::vector& grid2_index_list = nnc_vector_get_grid_index_list( nnc_vector ); + const std::vector& nnc_index_list = nnc_vector_get_nnc_index_list( nnc_vector ); int lgr_nr2 = nnc_vector_get_lgr_nr( nnc_vector ); const ecl_kw_type * tran_kw = ecl_nnc_export_get_tranx_kw(global_grid , init_file , lgr_nr1 , lgr_nr2 ); @@ -63,8 +99,8 @@ static int ecl_nnc_export__( const ecl_grid_type * grid , int lgr_index1 , cons nnc.global_index1 = global_index1; for (index2 = 0; index2 < nnc_vector_get_size( nnc_vector ); index2++) { - nnc.global_index2 = int_vector_iget( grid2_index_list , index2 ); - nnc.input_index = int_vector_iget( nnc_index_list, index2 ); + nnc.global_index2 = grid2_index_list[index2]; + nnc.input_index = nnc_index_list[index2]; if(tran_kw) { nnc.trans = ecl_kw_iget_as_double(tran_kw, nnc.input_index); valid_trans++; @@ -86,15 +122,21 @@ static int ecl_nnc_export__( const ecl_grid_type * grid , int lgr_index1 , cons int ecl_nnc_export( const ecl_grid_type * grid , const ecl_file_type * init_file , ecl_nnc_type * nnc_data) { int nnc_index = 0; int total_valid_trans = 0; - total_valid_trans = ecl_nnc_export__( grid , 0 , init_file , nnc_data , &nnc_index ); - { - int lgr_index; - for (lgr_index = 0; lgr_index < ecl_grid_get_num_lgr(grid); lgr_index++) { - ecl_grid_type * igrid = ecl_grid_iget_lgr( grid , lgr_index ); - total_valid_trans += ecl_nnc_export__( igrid , lgr_index , init_file , nnc_data , &nnc_index ); - } + if(ecl_nnc_intersect_format(grid, init_file)) { + // Intersect format + total_valid_trans = ecl_nnc_export_intersect__(init_file, nnc_data, &nnc_index); + } + else { + // Eclipse format + total_valid_trans = ecl_nnc_export__( grid , 0 , init_file , nnc_data , &nnc_index ); + { + for (int lgr_index = 0; lgr_index < ecl_grid_get_num_lgr(grid); lgr_index++) { + ecl_grid_type * igrid = ecl_grid_iget_lgr( grid , lgr_index ); + total_valid_trans += ecl_nnc_export__( igrid , lgr_index , init_file , nnc_data , &nnc_index ); + } + } + nnc_index = ecl_grid_get_num_nnc( grid ); } - nnc_index = ecl_nnc_export_get_size( grid ); ecl_nnc_sort( nnc_data , nnc_index ); return total_valid_trans; } diff --git a/ThirdParty/Ert/lib/ecl/ecl_nnc_geometry.cpp b/ThirdParty/Ert/lib/ecl/ecl_nnc_geometry.cpp index 36899a4824..a3f620e42c 100644 --- a/ThirdParty/Ert/lib/ecl/ecl_nnc_geometry.cpp +++ b/ThirdParty/Ert/lib/ecl/ecl_nnc_geometry.cpp @@ -1,5 +1,5 @@ /* - Copyright (c) 2017 statoil asa, norway. + Copyright (c) 2017 equinor asa, norway. The file 'ecl_nnc_geometry.c' is part of ert - ensemble based reservoir tool. @@ -61,8 +61,8 @@ static void ecl_nnc_geometry_add_pairs( const ecl_nnc_geometry_type * nnc_geo , for (int lgr_index2 = 0; lgr_index2 < nnc_info_get_size( nnc_info ); lgr_index2++) { const nnc_vector_type * nnc_vector = nnc_info_iget_vector( nnc_info , lgr_index2 ); - const int_vector_type * grid2_index_list = nnc_vector_get_grid_index_list( nnc_vector ); - const int_vector_type * nnc_index_list = nnc_vector_get_nnc_index_list( nnc_vector ); + const std::vector& grid2_index_list = nnc_vector_get_grid_index_list( nnc_vector ); + const std::vector& nnc_index_list = nnc_vector_get_nnc_index_list( nnc_vector ); int lgr_nr2 = nnc_vector_get_lgr_nr( nnc_vector ); for (int index2 = 0; index2 < nnc_vector_get_size( nnc_vector ); index2++) { @@ -70,8 +70,8 @@ static void ecl_nnc_geometry_add_pairs( const ecl_nnc_geometry_type * nnc_geo , pair.grid_nr1 = lgr_nr1; pair.global_index1 = global_index1; pair.grid_nr2 = lgr_nr2; - pair.global_index2 = int_vector_iget( grid2_index_list , index2 ); - pair.input_index = int_vector_iget( nnc_index_list, index2 ); + pair.global_index2 = grid2_index_list[index2]; + pair.input_index = nnc_index_list[index2]; nnc_geo->data->push_back(pair); } } diff --git a/ThirdParty/Ert/lib/ecl/ecl_region.cpp b/ThirdParty/Ert/lib/ecl/ecl_region.cpp index db63184266..ad92928efa 100644 --- a/ThirdParty/Ert/lib/ecl/ecl_region.cpp +++ b/ThirdParty/Ert/lib/ecl/ecl_region.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'ecl_region.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/ecl_rft_cell.cpp b/ThirdParty/Ert/lib/ecl/ecl_rft_cell.cpp index b5c023689f..e70833514f 100644 --- a/ThirdParty/Ert/lib/ecl/ecl_rft_cell.cpp +++ b/ThirdParty/Ert/lib/ecl/ecl_rft_cell.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'ecl_rft_cell.c' is part of ERT - Ensemble based Reservoir Tool. @@ -366,3 +366,9 @@ int ecl_rft_cell_cmp__( const void * arg1 , const void * arg2) { const ecl_rft_cell_type * cell2 = ecl_rft_cell_safe_cast_const( arg2 ); return ecl_rft_cell_cmp( cell1 , cell2 ); } + + +bool ecl_rft_cell_lt( const ecl_rft_cell_type * cell1 , const ecl_rft_cell_type * cell2) { + return (ecl_rft_cell_cmp(cell1, cell2) < 0); +} + diff --git a/ThirdParty/Ert/lib/ecl/ecl_rft_file.cpp b/ThirdParty/Ert/lib/ecl/ecl_rft_file.cpp index 553cb1c56d..adbb0e81b3 100644 --- a/ThirdParty/Ert/lib/ecl/ecl_rft_file.cpp +++ b/ThirdParty/Ert/lib/ecl/ecl_rft_file.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'ecl_rft_file.c' is part of ERT - Ensemble based Reservoir Tool. @@ -25,10 +25,12 @@ #include #endif +#include +#include +#include +#include + #include -#include -#include -#include #include #include @@ -55,19 +57,19 @@ struct ecl_rft_file_struct { UTIL_TYPE_ID_DECLARATION; - char * filename; - vector_type * data; /* This vector just contains all the rft nodes in one long vector. */ - hash_type * well_index; /* This indexes well names into the data vector - very similar to the scheme used in ecl_file. */ + std::string filename; + std::vector data; /* This vector just contains all the rft nodes in one long vector. */ + std::map> well_index; }; static ecl_rft_file_type * ecl_rft_file_alloc_empty(const char * filename) { - ecl_rft_file_type * rft_vector = (ecl_rft_file_type*)util_malloc(sizeof * rft_vector ); + ecl_rft_file_type * rft_vector = new ecl_rft_file_type(); + UTIL_TYPE_ID_INIT( rft_vector , ECL_RFT_FILE_ID ); - rft_vector->data = vector_alloc_new(); - rft_vector->filename = util_alloc_string_copy(filename); - rft_vector->well_index = hash_alloc(); + rft_vector->filename = std::string(filename); + return rft_vector; } @@ -82,8 +84,8 @@ UTIL_SAFE_CAST_FUNCTION( ecl_rft_file , ECL_RFT_FILE_ID ); UTIL_IS_INSTANCE_FUNCTION( ecl_rft_file , ECL_RFT_FILE_ID ); -static void ecl_rft_file_add_node(ecl_rft_file_type * rft_vector , const ecl_rft_node_type * rft_node) { - vector_append_owned_ref( rft_vector->data , rft_node , ecl_rft_node_free__); +static void ecl_rft_file_add_node(ecl_rft_file_type * rft_vector , ecl_rft_node_type * rft_node) { + rft_vector->data.push_back(rft_node); } @@ -100,15 +102,12 @@ ecl_rft_file_type * ecl_rft_file_alloc(const char * filename) { if (rft_view) { ecl_rft_node_type * rft_node = ecl_rft_node_alloc( rft_view ); - if (rft_node != NULL) { + if (rft_node) { const char * well_name = ecl_rft_node_get_well_name( rft_node ); ecl_rft_file_add_node(rft_vector , rft_node); - if (!hash_has_key( rft_vector->well_index , well_name)) - hash_insert_hash_owned_ref( rft_vector->well_index , well_name , int_vector_alloc( 0 , 0 ) , int_vector_free__); - { - int_vector_type * index_list = (int_vector_type*)hash_get( rft_vector->well_index , well_name ); - int_vector_append(index_list , global_index); - } + + auto& index_vector = rft_vector->well_index[well_name]; + index_vector.push_back(global_index); global_index++; } } else @@ -194,10 +193,10 @@ bool ecl_rft_file_case_has_rft( const char * case_input ) { void ecl_rft_file_free(ecl_rft_file_type * rft_vector) { - vector_free(rft_vector->data); - hash_free( rft_vector->well_index ); - free(rft_vector->filename); - free(rft_vector); + for (auto node_ptr : rft_vector->data) + ecl_rft_node_free( node_ptr ); + + delete rft_vector; } @@ -223,12 +222,11 @@ void ecl_rft_file_free__(void * arg) { int ecl_rft_file_get_size__( const ecl_rft_file_type * rft_file, const char * well_pattern , time_t recording_time) { if ((well_pattern == NULL) && (recording_time < 0)) - return vector_get_size( rft_file->data ); + return rft_file->data.size(); else { int match_count = 0; - int i; - for ( i=0; i < vector_get_size( rft_file->data ); i++) { - const ecl_rft_node_type * rft = (const ecl_rft_node_type*)vector_iget_const( rft_file->data , i); + for (size_t i=0; i < rft_file->data.size(); i++) { + const ecl_rft_node_type * rft = rft_file->data[i]; if (well_pattern) { if (util_fnmatch( well_pattern , ecl_rft_node_get_well_name( rft )) != 0) @@ -260,7 +258,7 @@ int ecl_rft_file_get_size( const ecl_rft_file_type * rft_file) { const char * ecl_rft_file_get_filename( const ecl_rft_file_type * rft_file ) { - return rft_file->filename; + return rft_file->filename.c_str(); } @@ -274,7 +272,7 @@ const char * ecl_rft_file_get_filename( const ecl_rft_file_type * rft_file ) { */ ecl_rft_node_type * ecl_rft_file_iget_node( const ecl_rft_file_type * rft_file , int index) { - return (ecl_rft_node_type*)vector_iget( rft_file->data , index ); + return rft_file->data[index]; } @@ -306,30 +304,32 @@ ecl_rft_node_type * ecl_rft_file_iget_node( const ecl_rft_file_type * rft_file , ecl_rft_node_type * ecl_rft_file_iget_well_rft( const ecl_rft_file_type * rft_file , const char * well, int index) { - const int_vector_type * index_vector = (const int_vector_type*)hash_get(rft_file->well_index , well); - return ecl_rft_file_iget_node( rft_file , int_vector_iget(index_vector , index)); + const auto& index_vector = rft_file->well_index.at(well); + return ecl_rft_file_iget_node( rft_file , index_vector[index]); } static int ecl_rft_file_get_node_index_time_rft( const ecl_rft_file_type * rft_file , const char * well , time_t recording_time) { + const auto& pair_iter = rft_file->well_index.find(well); + if (pair_iter == rft_file->well_index.end()) + return -1; + int global_index = -1; - if (hash_has_key( rft_file->well_index , well)) { - const int_vector_type * index_vector = (const int_vector_type*)hash_get(rft_file->well_index , well); - int well_index = 0; - while (true) { - if (well_index == int_vector_size( index_vector )) + size_t well_index = 0; + const auto& index_vector = pair_iter->second; + while (true) { + if (well_index == index_vector.size()) + break; + + { + const ecl_rft_node_type * node = ecl_rft_file_iget_node( rft_file , index_vector[well_index]); + if (ecl_rft_node_get_date( node ) == recording_time) { + global_index = index_vector[well_index]; break; - - { - const ecl_rft_node_type * node = ecl_rft_file_iget_node( rft_file , int_vector_iget( index_vector , well_index )); - if (ecl_rft_node_get_date( node ) == recording_time) { - global_index = int_vector_iget( index_vector , well_index ); - break; - } } - - well_index++; } + + well_index++; } return global_index; } @@ -355,7 +355,7 @@ ecl_rft_node_type * ecl_rft_file_get_well_time_rft( const ecl_rft_file_type * rf bool ecl_rft_file_has_well( const ecl_rft_file_type * rft_file , const char * well) { - return hash_has_key(rft_file->well_index , well); + return (rft_file->well_index.find(well) != rft_file->well_index.end()); } @@ -364,8 +364,11 @@ bool ecl_rft_file_has_well( const ecl_rft_file_type * rft_file , const char * we */ int ecl_rft_file_get_well_occurences( const ecl_rft_file_type * rft_file , const char * well) { - const int_vector_type * index_vector = (const int_vector_type*)hash_get(rft_file->well_index , well); - return int_vector_size( index_vector ); + const auto& pair_iter = rft_file->well_index.find(well); + if (pair_iter == rft_file->well_index.end()) + return 0; + else + return pair_iter->second.size(); } @@ -373,13 +376,18 @@ int ecl_rft_file_get_well_occurences( const ecl_rft_file_type * rft_file , const Returns the number of distinct wells in RFT file. */ int ecl_rft_file_get_num_wells( const ecl_rft_file_type * rft_file ) { - return hash_get_size( rft_file->well_index ); + return rft_file->well_index.size(); } stringlist_type * ecl_rft_file_alloc_well_list(const ecl_rft_file_type * rft_file ) { - return hash_alloc_stringlist( rft_file->well_index ); + stringlist_type * well_list = stringlist_alloc_new(); + + for (const auto& pair : rft_file->well_index) + stringlist_append_copy(well_list, pair.first.c_str()); + + return well_list; } @@ -396,7 +404,8 @@ void ecl_rft_file_update(const char * rft_file_name, ecl_rft_node_type ** nodes, if (storage_index == -1) { ecl_rft_file_add_node(rft_file, new_node); } else { - vector_iset_owned_ref(rft_file->data, storage_index, new_node,ecl_rft_node_free__); + ecl_rft_node_free(rft_file->data[storage_index]); + rft_file->data[storage_index] = new_node; } } }else{ @@ -410,7 +419,6 @@ void ecl_rft_file_update(const char * rft_file_name, ecl_rft_node_type ** nodes, { bool fmt_file = false; fortio_type * fortio = fortio_open_writer( rft_file_name , fmt_file , ECL_ENDIAN_FLIP ); - int node_index; /** The sorting here works directly on the internal node storage @@ -421,9 +429,9 @@ void ecl_rft_file_update(const char * rft_file_name, ecl_rft_node_type ** nodes, avoided for the rest of this function. */ - vector_sort(rft_file->data,(vector_cmp_ftype *) ecl_rft_node_cmp); - for(node_index=0; node_index < vector_get_size( rft_file->data ); node_index++) { - const ecl_rft_node_type *new_node = (const ecl_rft_node_type*)vector_iget_const(rft_file->data, node_index); + std::sort(rft_file->data.begin(), rft_file->data.end(), ecl_rft_node_lt); + for(size_t node_index=0; node_index < rft_file->data.size(); node_index++) { + const ecl_rft_node_type *new_node = rft_file->data[node_index]; ecl_rft_node_fwrite(new_node, fortio, unit_set); } diff --git a/ThirdParty/Ert/lib/ecl/ecl_rft_node.cpp b/ThirdParty/Ert/lib/ecl/ecl_rft_node.cpp index 7290dccb73..48d4c58130 100644 --- a/ThirdParty/Ert/lib/ecl/ecl_rft_node.cpp +++ b/ThirdParty/Ert/lib/ecl/ecl_rft_node.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'ecl_rft_node.c' is part of ERT - Ensemble based Reservoir Tool. @@ -23,10 +23,11 @@ #include #include +#include +#include +#include + #include -#include -#include -#include #include #include @@ -57,16 +58,14 @@ #define ECL_RFT_NODE_ID 887195 struct ecl_rft_node_struct { UTIL_TYPE_ID_DECLARATION; - char * well_name; /* Name of the well. */ + std::string well_name; ecl_rft_enum data_type; /* What type of data: RFT|PLT|SEGMENT */ time_t recording_date; /* When was the RFT recorded - date.*/ double days; /* When was the RFT recorded - days after simulaton start. */ bool MSW; - bool sort_perm_in_sync ; - int_vector_type * sort_perm; - vector_type *cells; + std::vector cells; }; @@ -106,15 +105,13 @@ static ecl_rft_enum translate_from_sting_to_ecl_rft_enum(const char * data_type_ ecl_rft_node_type * ecl_rft_node_alloc_new(const char * well_name, const char * data_type_string, const time_t recording_date, const double days){ ecl_rft_enum data_type = translate_from_sting_to_ecl_rft_enum(data_type_string); - ecl_rft_node_type * rft_node = (ecl_rft_node_type*)util_malloc(sizeof * rft_node ); + ecl_rft_node_type * rft_node = new ecl_rft_node_type(); + UTIL_TYPE_ID_INIT( rft_node , ECL_RFT_NODE_ID ); - rft_node->well_name = util_alloc_string_copy(well_name); - rft_node->cells = vector_alloc_new(); + rft_node->well_name = std::string(well_name); rft_node->recording_date = recording_date; rft_node->days = days; rft_node->data_type = data_type; - rft_node->sort_perm = NULL; - rft_node->sort_perm_in_sync = false; return rft_node; } @@ -130,13 +127,10 @@ static ecl_rft_node_type * ecl_rft_node_alloc_empty(const char * data_type_strin } { - ecl_rft_node_type * rft_node = (ecl_rft_node_type*)util_malloc(sizeof * rft_node ); - UTIL_TYPE_ID_INIT( rft_node , ECL_RFT_NODE_ID ); + ecl_rft_node_type * rft_node = new ecl_rft_node_type(); - rft_node->cells = vector_alloc_new(); + UTIL_TYPE_ID_INIT( rft_node , ECL_RFT_NODE_ID ); rft_node->data_type = data_type; - rft_node->sort_perm = NULL; - rft_node->sort_perm_in_sync = false; return rft_node; } @@ -148,8 +142,11 @@ UTIL_IS_INSTANCE_FUNCTION( ecl_rft_node , ECL_RFT_NODE_ID ); void ecl_rft_node_append_cell( ecl_rft_node_type * rft_node , ecl_rft_cell_type * cell) { - vector_append_owned_ref( rft_node->cells , cell , ecl_rft_cell_free__ ); - rft_node->sort_perm_in_sync = false; + if (rft_node->MSW) { + auto pos_iter = std::upper_bound(rft_node->cells.begin(), rft_node->cells.end(), cell, ecl_rft_cell_lt); + rft_node->cells.insert(pos_iter, cell); + } else + rft_node->cells.push_back( cell ); } @@ -273,8 +270,11 @@ ecl_rft_node_type * ecl_rft_node_alloc(const ecl_file_view_type * rft_view) { if (rft_node != NULL) { ecl_kw_type * date_kw = ecl_file_view_iget_named_kw( rft_view , DATE_KW , 0); - rft_node->well_name = (char*)util_alloc_strip_copy( (const char*)ecl_kw_iget_ptr(welletc , WELLETC_NAME_INDEX)); - + { + char * tmp = util_alloc_strip_copy( (const char*) ecl_kw_iget_ptr(welletc, WELLETC_NAME_INDEX)); + rft_node->well_name = std::string( tmp ); + free(tmp); + } /* Time information. */ { int * time = ecl_kw_get_int_ptr( date_kw ); @@ -293,18 +293,15 @@ ecl_rft_node_type * ecl_rft_node_alloc(const ecl_file_view_type * rft_view) { const char * ecl_rft_node_get_well_name(const ecl_rft_node_type * rft_node) { - return rft_node->well_name; + return rft_node->well_name.c_str(); } void ecl_rft_node_free(ecl_rft_node_type * rft_node) { + for (auto cell_ptr : rft_node->cells) + ecl_rft_cell_free( cell_ptr ); - free(rft_node->well_name); - vector_free( rft_node->cells ); - if (rft_node->sort_perm) - int_vector_free( rft_node->sort_perm ); - - free(rft_node); + delete rft_node; } void ecl_rft_node_free__(void * void_node) { @@ -316,7 +313,7 @@ void ecl_rft_node_free__(void * void_node) { -int ecl_rft_node_get_size(const ecl_rft_node_type * rft_node) { return vector_get_size( rft_node->cells ); } +int ecl_rft_node_get_size(const ecl_rft_node_type * rft_node) { return rft_node->cells.size(); } time_t ecl_rft_node_get_date(const ecl_rft_node_type * rft_node) { return rft_node->recording_date; } ecl_rft_enum ecl_rft_node_get_type(const ecl_rft_node_type * rft_node) { return rft_node->data_type; } @@ -325,32 +322,13 @@ ecl_rft_enum ecl_rft_node_get_type(const ecl_rft_node_type * rft_node) { return /* various functions to access properties at the cell level */ const ecl_rft_cell_type * ecl_rft_node_iget_cell( const ecl_rft_node_type * rft_node , int index) { - return (const ecl_rft_cell_type*)vector_iget_const( rft_node->cells , index ); + return rft_node->cells[index]; } -static void ecl_rft_node_create_sort_perm( ecl_rft_node_type * rft_node ) { - if (rft_node->sort_perm) - int_vector_free( rft_node->sort_perm ); - - rft_node->sort_perm = vector_alloc_sort_perm( rft_node->cells , ecl_rft_cell_cmp__ ); - rft_node->sort_perm_in_sync = true; -} - -void ecl_rft_node_inplace_sort_cells( ecl_rft_node_type * rft_node ) { - vector_sort( rft_node->cells , ecl_rft_cell_cmp__ ); - rft_node->sort_perm_in_sync = false; // The permutation is no longer sorted; however the vector itself is sorted .... -} const ecl_rft_cell_type * ecl_rft_node_iget_cell_sorted( ecl_rft_node_type * rft_node , int index) { - if (ecl_rft_node_is_RFT( rft_node )) - return ecl_rft_node_iget_cell( rft_node , index ); - else { - if (!rft_node->sort_perm_in_sync) - ecl_rft_node_create_sort_perm( rft_node ); - - return (const ecl_rft_cell_type*)vector_iget_const( rft_node->cells , int_vector_iget( rft_node->sort_perm , index )); - } + return rft_node->cells[index]; } @@ -396,14 +374,14 @@ static void assert_type_and_index( const ecl_rft_node_type * rft_node , ecl_rft_ if (rft_node->data_type != target_type) util_abort("%s: wrong type \n",__func__); - if ((index < 0) || (index >= vector_get_size( rft_node->cells ))) + if ((index < 0) || (index >= static_cast(rft_node->cells.size()))) util_abort("%s: invalid index:%d \n",__func__ , index); } double ecl_rft_node_iget_sgas( const ecl_rft_node_type * rft_node , int index) { assert_type_and_index( rft_node , RFT , index ); { - const ecl_rft_cell_type * cell = (const ecl_rft_cell_type*)vector_iget_const( rft_node->cells , index ); + const ecl_rft_cell_type * cell = ecl_rft_node_iget_cell(rft_node, index); return ecl_rft_cell_get_sgas( cell ); } } @@ -412,7 +390,7 @@ double ecl_rft_node_iget_sgas( const ecl_rft_node_type * rft_node , int index) { double ecl_rft_node_iget_swat( const ecl_rft_node_type * rft_node , int index) { assert_type_and_index( rft_node , RFT , index ); { - const ecl_rft_cell_type * cell = (const ecl_rft_cell_type*)vector_iget_const( rft_node->cells , index ); + const ecl_rft_cell_type * cell = rft_node->cells[index]; return ecl_rft_cell_get_swat( cell ); } } @@ -424,7 +402,7 @@ double ecl_rft_node_get_days(const ecl_rft_node_type * rft_node ){ double ecl_rft_node_iget_soil( const ecl_rft_node_type * rft_node , int index) { assert_type_and_index( rft_node , RFT , index ); { - const ecl_rft_cell_type * cell = (const ecl_rft_cell_type*)vector_iget_const( rft_node->cells , index ); + const ecl_rft_cell_type * cell = rft_node->cells[index]; return ecl_rft_cell_get_soil( cell ); } } @@ -435,7 +413,7 @@ double ecl_rft_node_iget_soil( const ecl_rft_node_type * rft_node , int index) { double ecl_rft_node_iget_orat( const ecl_rft_node_type * rft_node , int index) { assert_type_and_index( rft_node , PLT , index ); { - const ecl_rft_cell_type * cell = (const ecl_rft_cell_type*)vector_iget_const( rft_node->cells , index ); + const ecl_rft_cell_type * cell = rft_node->cells[index]; return ecl_rft_cell_get_orat( cell ); } } @@ -444,7 +422,7 @@ double ecl_rft_node_iget_orat( const ecl_rft_node_type * rft_node , int index) { double ecl_rft_node_iget_wrat( const ecl_rft_node_type * rft_node , int index) { assert_type_and_index( rft_node , PLT , index ); { - const ecl_rft_cell_type * cell = (const ecl_rft_cell_type*)vector_iget_const( rft_node->cells , index); + const ecl_rft_cell_type * cell = rft_node->cells[index]; return ecl_rft_cell_get_wrat( cell ); } } @@ -453,7 +431,7 @@ double ecl_rft_node_iget_wrat( const ecl_rft_node_type * rft_node , int index) { double ecl_rft_node_iget_grat( const ecl_rft_node_type * rft_node , int index) { assert_type_and_index( rft_node , PLT , index ); { - const ecl_rft_cell_type * cell = (const ecl_rft_cell_type*)vector_iget_const( rft_node->cells , index); + const ecl_rft_cell_type * cell = rft_node->cells[index]; return ecl_rft_cell_get_grat( cell ); } } @@ -591,10 +569,9 @@ void ecl_rft_node_fwrite(const ecl_rft_node_type * rft_node, fortio_type * forti ecl_kw_type * pressure = ecl_kw_alloc(PRESSURE_KW, size_cells, ECL_FLOAT); ecl_kw_type * swat = ecl_kw_alloc(SWAT_KW, size_cells, ECL_FLOAT); ecl_kw_type * sgas = ecl_kw_alloc(SGAS_KW, size_cells, ECL_FLOAT); - int i; - for(i =0;icells , i); + for(int i =0;icells[i]; ecl_kw_iset_int(conipos, i, ecl_rft_cell_get_i(cell)+1); ecl_kw_iset_int(conjpos, i, ecl_rft_cell_get_j(cell)+1); ecl_kw_iset_int(conkpos, i, ecl_rft_cell_get_k(cell)+1); @@ -636,4 +613,6 @@ int ecl_rft_node_cmp( const ecl_rft_node_type * n1 , const ecl_rft_node_type * n } - +bool ecl_rft_node_lt(const ecl_rft_node_type * n1, const ecl_rft_node_type * n2) { + return (ecl_rft_node_cmp(n1, n2) < 0); +} diff --git a/ThirdParty/Ert/lib/ecl/ecl_rst_file.cpp b/ThirdParty/Ert/lib/ecl/ecl_rst_file.cpp index 4c3e903f6e..484e11b237 100644 --- a/ThirdParty/Ert/lib/ecl/ecl_rst_file.cpp +++ b/ThirdParty/Ert/lib/ecl/ecl_rst_file.cpp @@ -1,6 +1,6 @@ /* - Copyright (C) 2012 Statoil ASA, Norway. + Copyright (C) 2012 Equinor ASA, Norway. The file 'ecl_rst_file.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/ecl_rsthead.cpp b/ThirdParty/Ert/lib/ecl/ecl_rsthead.cpp index 3c002cb9c5..d7bbb00e38 100644 --- a/ThirdParty/Ert/lib/ecl/ecl_rsthead.cpp +++ b/ThirdParty/Ert/lib/ecl/ecl_rsthead.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'ecl_rsthead.c' is part of ERT - Ensemble based Reservoir Tool. @@ -88,10 +88,7 @@ ecl_rsthead_type * ecl_rsthead_alloc_from_kw( int report_step , const ecl_kw_typ // The only derived quantity rsthead->sim_time = rsthead_date( rsthead->day , rsthead->month , rsthead->year ); } - - if (doubhead_kw) - rsthead->sim_days = ecl_kw_iget_double( doubhead_kw , DOUBHEAD_DAYS_INDEX ); - + rsthead->sim_days = ecl_kw_iget_double( doubhead_kw , DOUBHEAD_DAYS_INDEX ); if (logihead_kw) rsthead->dualp = ecl_kw_iget_bool( logihead_kw , LOGIHEAD_DUALP_INDEX); @@ -112,15 +109,12 @@ ecl_rsthead_type * ecl_rsthead_alloc_from_kw( int report_step , const ecl_kw_typ ecl_rsthead_type * ecl_rsthead_alloc( const ecl_file_view_type * rst_view, int report_step) { const ecl_kw_type * intehead_kw = ecl_file_view_iget_named_kw( rst_view , INTEHEAD_KW , 0); - const ecl_kw_type * doubhead_kw = NULL; + const ecl_kw_type * doubhead_kw = ecl_file_view_iget_named_kw( rst_view , DOUBHEAD_KW , 0); const ecl_kw_type * logihead_kw = NULL; if (ecl_file_view_has_kw(rst_view, LOGIHEAD_KW)) logihead_kw = ecl_file_view_iget_named_kw( rst_view , LOGIHEAD_KW , 0); - if (ecl_file_view_has_kw(rst_view, DOUBHEAD_KW)) - doubhead_kw = ecl_file_view_iget_named_kw(rst_view, DOUBHEAD_KW, 0); - if (ecl_file_view_has_kw( rst_view , SEQNUM_KW)) { const ecl_kw_type * seqnum_kw = ecl_file_view_iget_named_kw( rst_view , SEQNUM_KW , 0); report_step = ecl_kw_iget_int( seqnum_kw , 0); diff --git a/ThirdParty/Ert/lib/ecl/ecl_smspec.cpp b/ThirdParty/Ert/lib/ecl/ecl_smspec.cpp index dbefb53bd9..ea0a095368 100644 --- a/ThirdParty/Ert/lib/ecl/ecl_smspec.cpp +++ b/ThirdParty/Ert/lib/ecl/ecl_smspec.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'ecl_smspec.c' is part of ERT - Ensemble based Reservoir Tool. @@ -22,12 +22,18 @@ #include #include +#include +#include +#include +#include +#include +#include + #include #include -#include -#include #include #include +#include "detail/util/path.hpp" #include #include @@ -52,7 +58,7 @@ ------------------------------- 1. The function smspec_node_alloc() must be updated to return a valid - smspec_node_type instance when called with the new var_type. + ecl::smspec_node instance when called with the new var_type. 2. Update the function ecl_smpec_install_gen_key() to install smpec_index instances of this particular type. The format of the general key is @@ -95,7 +101,7 @@ #define ECL_SMSPEC_ID 806647 #define PARAMS_GLOBAL_DEFAULT -99 - +typedef std::map node_map; struct ecl_smspec_struct { UTIL_TYPE_ID_DECLARATION; @@ -104,31 +110,33 @@ struct ecl_smspec_struct { smspec_node instances. The actual smspec_node instances are owned by the smspec_nodes vector; */ - hash_type * well_var_index; /* Indexes for all well variables: {well1: {var1: index1 , var2: index2} , well2: {var1: index1 , var2: index2}} */ - hash_type * well_completion_var_index; /* Indexes for completion indexes .*/ - hash_type * group_var_index; /* Indexes for group variables.*/ - hash_type * field_var_index; - hash_type * region_var_index; /* The stored index is an offset. */ - hash_type * misc_var_index; /* Variables like 'TCPU' and 'NEWTON'. */ - hash_type * block_var_index; /* Block variables like BPR */ - hash_type * gen_var_index; /* This is "everything" - things can either be found as gen_var("WWCT:OP_X") or as well_var("WWCT" , "OP_X") */ + node_map field_var_index; + node_map misc_var_index; /* Variables like 'TCPU' and 'NEWTON'. */ + node_map gen_var_index /* This is "everything" - things can either be found as gen_var("WWCT:OP_X") or as well_var("WWCT" , "OP_X") */; + + std::map well_var_index; /* Indexes for all well variables: + {well1: {var1: index1 , var2: index2} , well2: {var1: index1 , var2: index2}} */ + std::map group_var_index; /* Indexes for group variables.*/ + std::map region_var_index; /* The stored index is an offset. */ + std::map block_var_index; /* Block variables like BPR */ + std::map> well_completion_var_index; /* Indexes for completion indexes .*/ - vector_type * smspec_nodes; + std::vector> smspec_nodes; bool write_mode; bool need_nums; - int_vector_type * index_map; - + std::vector index_map; + std::map inv_index_map; + int params_size; /*-----------------------------------------------------------------*/ int time_seconds; int grid_dims[3]; /* Grid dimensions - in DIMENS[1,2,3] */ int num_regions; int Nwells , param_offset; - int params_size; - const char * key_join_string; /* The string used to join keys when building gen_key keys - typically ":" - + std::string key_join_string; /* The string used to join keys when building gen_key keys - typically ":" - but arbitrary - NOT necessary to be able to invert the joining. */ - char * header_file; /* FULL path to the currenbtly loaded header_file. */ + std::string header_file; /* FULL path to the currenbtly loaded header_file. */ bool formatted; /* Has this summary instance been loaded from a formatted (i.e. FSMSPEC file) or unformatted (i.e. SMSPEC) file. */ time_t sim_start_time; /* When did the simulation start - worldtime. */ @@ -138,9 +146,9 @@ struct ecl_smspec_struct { int month_index; /* time information. */ int year_index; bool has_lgr; - float_vector_type * params_default; + std::vector params_default; - char * restart_case; + std::string restart_case; ert_ecl_unit_enum unit_system; int restart_step; }; @@ -201,33 +209,6 @@ Completion var: VAR_TYPE:WELL_NAME:NUM */ -/** - The special_vars list is used to associate keywords with special - types, when the kewyord name is in conflict with the default vector - naming convention; all the variables mentioned in the list below - are given the type ECL_SMSPEC_MISC_VAR. - - For instance the keyword 'NEWTON' starts with 'N' and is - classified as a NETWORK type variable. However it should rather - be classified as a MISC type variable. (What a fucking mess). - - The special_vars list is used in the functions - ecl_smspec_identify_special_var() and ecl_smspec_identify_var_type(). -*/ - -static const char* special_vars[] = {"NEWTON", - "NAIMFRAC", - "NLINEARS", - "NLINSMIN", - "NLINSMAX", - "ELAPSED", - "MAXDPR", - "MAXDSO", - "MAXDSG", - "MAXDSW", - "STEPTYPE", - "WNEWTON"}; - /* @@ -248,33 +229,69 @@ static const char* smspec_required_keywords[] = { DIMENS_KW }; +namespace { + +const ecl::smspec_node * ecl_smspec_get_var_node( const node_map& mp, const char * var) { + const auto it = mp.find(var); + if (it == mp.end()) + return nullptr; + + return it->second; + } + + const ecl::smspec_node * ecl_smspec_get_str_key_var_node( const std::map& mp , const char * key , const char * var) { + const auto key_it = mp.find(key); + if (key_it == mp.end()) + return nullptr; + + const node_map& var_map = key_it->second; + return ecl_smspec_get_var_node(var_map, var); + } + + const ecl::smspec_node * ecl_smspec_get_int_key_var_node(const std::map& mp , int key , const char * var) { + const auto key_it = mp.find(key); + if (key_it == mp.end()) + return nullptr; + + const auto& var_map = key_it->second; + return ecl_smspec_get_var_node(var_map, var); + } + +} //end namespace + +int ecl_smspec_num_nodes( const ecl_smspec_type * smspec) { + return smspec->smspec_nodes.size(); +} + +/* + When loading a summary case from file many of the nodes can be ignored, in + that case the size of PARAMS vector in the data files is larger than the + number of internalized nodes. Therefor we need to maintain the + params_size member. +*/ + +int ecl_smspec_get_params_size( const ecl_smspec_type * smspec ) { + return smspec->params_size; +} + + /*****************************************************************/ ecl_smspec_type * ecl_smspec_alloc_empty(bool write_mode , const char * key_join_string) { - ecl_smspec_type *ecl_smspec; - ecl_smspec = (ecl_smspec_type*)util_malloc(sizeof *ecl_smspec ); + ecl_smspec_type * ecl_smspec = new ecl_smspec_type(); UTIL_TYPE_ID_INIT(ecl_smspec , ECL_SMSPEC_ID); - ecl_smspec->well_var_index = hash_alloc(); - ecl_smspec->well_completion_var_index = hash_alloc(); - ecl_smspec->group_var_index = hash_alloc(); - ecl_smspec->field_var_index = hash_alloc(); - ecl_smspec->region_var_index = hash_alloc(); - ecl_smspec->misc_var_index = hash_alloc(); - ecl_smspec->block_var_index = hash_alloc(); - ecl_smspec->gen_var_index = hash_alloc(); ecl_smspec->sim_start_time = -1; ecl_smspec->key_join_string = key_join_string; - ecl_smspec->header_file = NULL; - - ecl_smspec->smspec_nodes = vector_alloc_new(); + ecl_smspec->header_file = ""; ecl_smspec->time_index = -1; ecl_smspec->day_index = -1; ecl_smspec->year_index = -1; ecl_smspec->month_index = -1; ecl_smspec->time_seconds = -1; + ecl_smspec->params_size = -1; /* The unit system is given as an integer in the INTEHEAD keyword. The INTEHEAD @@ -283,10 +300,7 @@ ecl_smspec_type * ecl_smspec_alloc_empty(bool write_mode , const char * key_join */ ecl_smspec->unit_system = ECL_METRIC_UNITS; - ecl_smspec->index_map = int_vector_alloc(0,0); - ecl_smspec->restart_case = NULL; ecl_smspec->restart_step = -1; - ecl_smspec->params_default = float_vector_alloc(0 , PARAMS_GLOBAL_DEFAULT); ecl_smspec->write_mode = write_mode; ecl_smspec->need_nums = false; @@ -296,19 +310,19 @@ ecl_smspec_type * ecl_smspec_alloc_empty(bool write_mode , const char * key_join int * ecl_smspec_alloc_mapping( const ecl_smspec_type * self, const ecl_smspec_type * other) { int params_size = ecl_smspec_get_params_size( self ); - int * mapping = (int*)util_malloc( params_size * sizeof * mapping ); + int * mapping = (int*) util_malloc( params_size * sizeof * mapping ); for (int i = 0; i < params_size; i++) mapping[i] = -1; for (int i=0; i < ecl_smspec_num_nodes( self ); i++) { - const smspec_node_type * self_node = ecl_smspec_iget_node( self , i ); - int self_index = smspec_node_get_params_index( self_node ); - const char * key = smspec_node_get_gen_key1( self_node ); + const ecl::smspec_node& self_node = ecl_smspec_iget_node_w_node_index( self , i ); + int self_index = self_node.get_params_index(); + const char * key = self_node.get_gen_key1(); if (ecl_smspec_has_general_var( other , key)) { - const smspec_node_type * other_node = ecl_smspec_get_general_var_node( other , key); - int other_index = smspec_node_get_params_index(other_node); + const ecl::smspec_node& other_node = ecl_smspec_get_general_var_node( other , key); + int other_index = other_node.get_params_index(); mapping[ self_index ] = other_index; } } @@ -324,14 +338,25 @@ int * ecl_smspec_alloc_mapping( const ecl_smspec_type * self, const ecl_smspec_t */ -const smspec_node_type * ecl_smspec_iget_node( const ecl_smspec_type * smspec , int index ) { - return (const smspec_node_type*)vector_safe_iget_const( smspec->smspec_nodes , index ); +const ecl::smspec_node& ecl_smspec_iget_node_w_node_index( const ecl_smspec_type * smspec , int node_index ) { + const auto& node = smspec->smspec_nodes[node_index]; + return *node.get(); } -int ecl_smspec_num_nodes( const ecl_smspec_type * smspec) { - return vector_get_size( smspec->smspec_nodes ); + +/* + The ecl_smspec_iget_node() function is only retained for compatibility; should be + replaced with calls to the more explicit: ecl_smspec_iget_node_w_node_index(). +*/ + +const ecl::smspec_node& ecl_smspec_iget_node(const ecl_smspec_type * smspec, int index) { + return ecl_smspec_iget_node_w_node_index(smspec, index); } +const ecl::smspec_node& ecl_smspec_iget_node_w_params_index( const ecl_smspec_type * smspec , int params_index ) { + int node_index = smspec->inv_index_map.at(params_index); + return ecl_smspec_iget_node_w_node_index(smspec, node_index); +} /** * Returns an ecl data type for which all names will fit. If the maximum name @@ -341,8 +366,8 @@ int ecl_smspec_num_nodes( const ecl_smspec_type * smspec) { static ecl_data_type get_wgnames_type(const ecl_smspec_type * smspec) { size_t max_len = 0; for(int i = 0; i < ecl_smspec_num_nodes(smspec); ++i) { - const smspec_node_type * node = ecl_smspec_iget_node(smspec, i); - const char * name = smspec_node_get_wgname( node ); + const ecl::smspec_node& node = ecl_smspec_iget_node_w_node_index(smspec, i); + const char * name = smspec_node_get_wgname( &node ); if(name) max_len = util_size_t_max(max_len, strlen(name)); } @@ -367,11 +392,11 @@ static void ecl_smspec_fwrite_RESTART(const ecl_smspec_type * smspec, fortio_typ for (int i=0; i < SUMMARY_RESTART_SIZE; i++) ecl_kw_iset_string8( restart_kw , i , ""); - if (smspec->restart_case != NULL) { - int restart_case_len = strlen(smspec->restart_case); + if (smspec->restart_case.size() > 0) { + size_t restart_case_len = smspec->restart_case.size(); - int offset = 0; - for (int i = 0; i < SUMMARY_RESTART_SIZE ; i++) { + size_t offset = 0; + for (size_t i = 0; i < SUMMARY_RESTART_SIZE ; i++) { if (offset < restart_case_len) ecl_kw_iset_string8( restart_kw , i , &smspec->restart_case[ offset ]); offset += ECL_STRING8_LENGTH; @@ -433,7 +458,7 @@ static void ecl_smspec_fortio_fwrite( const ecl_smspec_type * smspec , fortio_ty nums_kw = ecl_kw_alloc( NUMS_KW , num_nodes , ECL_INT); for (int i=0; i < ecl_smspec_num_nodes( smspec ); i++) { - const smspec_node_type * smspec_node = ecl_smspec_iget_node( smspec , i ); + const ecl::smspec_node& smspec_node = ecl_smspec_iget_node_w_node_index( smspec , i ); /* It is possible to add variables with deferred initialisation with the ecl_sum_add_blank_var() function. Before these @@ -453,23 +478,23 @@ static void ecl_smspec_fortio_fwrite( const ecl_smspec_type * smspec , fortio_ty ignored when/if this smspec file is read in at a later stage. */ - if (smspec_node_get_var_type( smspec_node ) == ECL_SMSPEC_INVALID_VAR) { + if (smspec_node.get_var_type() == ECL_SMSPEC_INVALID_VAR) { ecl_kw_iset_string8( keywords_kw , i , "WWCT" ); ecl_kw_iset_string8( units_kw , i , "????????"); ecl_kw_iset_string_ptr( wgnames_kw , i , DUMMY_WELL); } else { - ecl_kw_iset_string8( keywords_kw , i , smspec_node_get_keyword( smspec_node )); - ecl_kw_iset_string8( units_kw , i , smspec_node_get_unit( smspec_node )); + ecl_kw_iset_string8( keywords_kw , i , smspec_node_get_keyword( &smspec_node )); + ecl_kw_iset_string8( units_kw , i , smspec_node_get_unit( &smspec_node )); { const char * wgname = DUMMY_WELL; - if (smspec_node_get_wgname( smspec_node )) - wgname = smspec_node_get_wgname( smspec_node ); + if (smspec_node_get_wgname( &smspec_node )) + wgname = smspec_node_get_wgname( &smspec_node ); ecl_kw_iset_string_ptr( wgnames_kw , i , wgname); } } if (nums_kw != NULL) - ecl_kw_iset_int( nums_kw , i , smspec_node_get_num( smspec_node )); + ecl_kw_iset_int( nums_kw , i , smspec_node.get_num()); } ecl_kw_fwrite( keywords_kw , fortio ); ecl_kw_fwrite( wgnames_kw , fortio ); @@ -512,7 +537,7 @@ static ecl_smspec_type * ecl_smspec_alloc_writer__( const char * key_join_string */ if (restart_case) { if (strlen(restart_case) <= (SUMMARY_RESTART_SIZE * ECL_STRING8_LENGTH)) { - ecl_smspec->restart_case = util_alloc_string_copy( restart_case ); + ecl_smspec->restart_case = restart_case; ecl_smspec->restart_step = restart_step; } } @@ -522,33 +547,16 @@ static ecl_smspec_type * ecl_smspec_alloc_writer__( const char * key_join_string ecl_smspec->sim_start_time = sim_start; { - smspec_node_type * time_node; - if (time_in_days) { - time_node = smspec_node_alloc( ECL_SMSPEC_MISC_VAR , - NULL , - "TIME" , - "DAYS" , - key_join_string , - ecl_smspec->grid_dims , - 0 , - -1 , - 0 ); - ecl_smspec->time_seconds = 3600 * 24; - } else { - time_node = smspec_node_alloc( ECL_SMSPEC_MISC_VAR , - NULL , - "TIME" , - "HOURS" , - key_join_string , - ecl_smspec->grid_dims , - 0 , - -1 , - 0 ); - ecl_smspec->time_seconds = 3600; - } + const ecl::smspec_node * time_node; - ecl_smspec_add_node( ecl_smspec , time_node ); - ecl_smspec->time_index = smspec_node_get_params_index( time_node ); + if (time_in_days) { + ecl_smspec->time_seconds = 3600 * 24; + time_node = ecl_smspec_add_node(ecl_smspec, "TIME", "DAYS", 0); + } else { + ecl_smspec->time_seconds = 3600; + time_node = ecl_smspec_add_node(ecl_smspec, "TIME", "HOURS", 0); + } + ecl_smspec->time_index = time_node->get_params_index(); } return ecl_smspec; } @@ -564,131 +572,8 @@ ecl_smspec_type * ecl_smspec_alloc_writer(const char * key_join_string, time_t s UTIL_SAFE_CAST_FUNCTION( ecl_smspec , ECL_SMSPEC_ID ) - -/** - Goes through the special_vars static table to check if @var is one - the special variables which does not follow normal naming - convention. If the test eavulates to true the function will return - ECL_SMSPEC_MISC_VAR, otherwise the function will return - ECL_SMSPEC_INVALID_VAR and the variable type will be determined - from the var name according to standard naming conventions. - - It is important that this function is called before the standard - method. -*/ - -static ecl_smspec_var_type ecl_smspec_identify_special_var( const char * var ) { - ecl_smspec_var_type var_type = ECL_SMSPEC_INVALID_VAR; - - int num_special = sizeof( special_vars ) / sizeof( special_vars[0] ); - int i; - for (i=0; i < num_special; i++) { - if (strcmp( var , special_vars[i]) == 0) { - var_type = ECL_SMSPEC_MISC_VAR; - break; - } - } - - return var_type; -} - - -/* - See table 3.4 in the ECLIPSE file format reference manual. - - Observe that the combined ecl_sum style keys like e.g. WWCT:OP1 - should be formatted with the keyword first, so that this function - will identify both 'WWCT' and 'WWCT:OP_1' as a ECL_SMSPEC_WELL_VAR - instance. -*/ - - ecl_smspec_var_type ecl_smspec_identify_var_type(const char * var) { - ecl_smspec_var_type var_type = ecl_smspec_identify_special_var( var ); - if (var_type == ECL_SMSPEC_INVALID_VAR) { - switch(var[0]) { - case('A'): - var_type = ECL_SMSPEC_AQUIFER_VAR; - break; - case('B'): - var_type = ECL_SMSPEC_BLOCK_VAR; - break; - case('C'): - var_type = ECL_SMSPEC_COMPLETION_VAR; - break; - case('F'): - var_type = ECL_SMSPEC_FIELD_VAR; - break; - case('G'): - var_type = ECL_SMSPEC_GROUP_VAR; - break; - case('L'): - switch(var[1]) { - case('B'): - var_type = ECL_SMSPEC_LOCAL_BLOCK_VAR; - break; - case('C'): - var_type = ECL_SMSPEC_LOCAL_COMPLETION_VAR; - break; - case('W'): - var_type = ECL_SMSPEC_LOCAL_WELL_VAR; - break; - default: - /* - The documentation explicitly mentions keywords starting with - LB, LC and LW as special types, but keywords starting with - L[^BCW] are also valid. These come in the misceallaneous - category; at least the LLINEAR keyword is an example of such - a keyword. - */ - var_type = ECL_SMSPEC_MISC_VAR; - } - break; - case('N'): - var_type = ECL_SMSPEC_NETWORK_VAR; - break; - case('R'): - { - /* - The distinction between region-to-region variables and plain - region variables is less than clear: The current - interpretation is that the cases: - - 1. Any variable matching: - - a) Starts with 'R' - b) Has 'F' as the third character - - 2. The variable "RNLF" - - Get variable type ECL_SMSPEC_REGION_2_REGION_VAR. The rest - get the type ECL_SMSPEC_REGION_VAR. - */ - - if (util_string_equal( var , "RNLF")) - var_type = ECL_SMSPEC_REGION_2_REGION_VAR; - else if (var[2] == 'F') - var_type = ECL_SMSPEC_REGION_2_REGION_VAR; - else - var_type = ECL_SMSPEC_REGION_VAR; - - } - break; - case('S'): - var_type = ECL_SMSPEC_SEGMENT_VAR; - break; - case('W'): - var_type = ECL_SMSPEC_WELL_VAR; - break; - default: - /* - It is unfortunately impossible to recognize an error situation - - the rest just goes in "other" variables. - */ - var_type = ECL_SMSPEC_MISC_VAR; - } - } - return var_type; + return ecl::smspec_node::identify_var_type(var); } @@ -789,23 +674,23 @@ static int ecl_smspec_get_global_grid_index(const ecl_smspec_type * smspec , int defined through the format strings used in this function. */ -static void ecl_smspec_install_gen_keys( ecl_smspec_type * smspec , smspec_node_type * smspec_node ) { +static void ecl_smspec_install_gen_keys( ecl_smspec_type * smspec , const ecl::smspec_node& smspec_node ) { /* Insert the default general mapping. */ { - const char * gen_key1 = smspec_node_get_gen_key1( smspec_node ); - if (gen_key1 != NULL) - hash_insert_ref(smspec->gen_var_index , gen_key1 , smspec_node); + const char * gen_key1 = smspec_node.get_gen_key1(); + if (gen_key1) + smspec->gen_var_index[gen_key1] = &smspec_node; } /* Insert the (optional) extra mapping for block related variables and region_2_region variables: */ { - const char * gen_key2 = smspec_node_get_gen_key2( smspec_node ); - if (gen_key2 != NULL) - hash_insert_ref(smspec->gen_var_index , gen_key2 , smspec_node); + const char * gen_key2 = smspec_node.get_gen_key2(); + if (gen_key2) + smspec->gen_var_index[gen_key2] = &smspec_node; } } -static void ecl_smspec_install_special_keys( ecl_smspec_type * ecl_smspec , smspec_node_type * smspec_node) { +static void ecl_smspec_install_special_keys( ecl_smspec_type * ecl_smspec , const ecl::smspec_node& smspec_node) { /** This large switch is for installing keys which have custom lookup paths, in addition to the lookup based on general keys. Examples @@ -814,85 +699,35 @@ static void ecl_smspec_install_special_keys( ecl_smspec_type * ecl_smspec , smsp ecl_smspec_get_well_var_index( smspec , well_name , var ); */ - const char * well = smspec_node_get_wgname( smspec_node ); + const char * well = smspec_node_get_wgname( &smspec_node ); const char * group = well; - const int num = smspec_node_get_num(smspec_node); - const char * keyword = smspec_node_get_keyword(smspec_node); - ecl_smspec_var_type var_type = smspec_node_get_var_type( smspec_node ); + const int num = smspec_node_get_num(&smspec_node); + const char * keyword = smspec_node_get_keyword(&smspec_node); + ecl_smspec_var_type var_type = smspec_node_get_var_type(&smspec_node ); switch(var_type) { case(ECL_SMSPEC_COMPLETION_VAR): - if (well) - { - /* Three level indexing: variable -> well -> string(cell_nr)*/ - if (!hash_has_key(ecl_smspec->well_completion_var_index , well)) - hash_insert_hash_owned_ref(ecl_smspec->well_completion_var_index , well , hash_alloc() , hash_free__); - { - hash_type * cell_hash = (hash_type*)hash_get(ecl_smspec->well_completion_var_index , well); - char cell_str[16]; - sprintf(cell_str , "%d" , num); - if (!hash_has_key(cell_hash , cell_str)) - hash_insert_hash_owned_ref(cell_hash , cell_str , hash_alloc() , hash_free__); - { - hash_type * var_hash = (hash_type*)hash_get(cell_hash , cell_str); - hash_insert_ref(var_hash , keyword , smspec_node ); - } - } - } + ecl_smspec->well_completion_var_index[well][num][keyword] = &smspec_node; break; case(ECL_SMSPEC_FIELD_VAR): - /* - Field variable - */ - hash_insert_ref( ecl_smspec->field_var_index , keyword , smspec_node ); + ecl_smspec->field_var_index[keyword] = &smspec_node; break; case(ECL_SMSPEC_GROUP_VAR): - if (group) - { - if (!hash_has_key(ecl_smspec->group_var_index , group)) - hash_insert_hash_owned_ref(ecl_smspec->group_var_index , group, hash_alloc() , hash_free__); - { - hash_type * var_hash = (hash_type*)hash_get(ecl_smspec->group_var_index , group); - hash_insert_ref(var_hash , keyword , smspec_node ); - } - } + ecl_smspec->group_var_index[group][keyword] = &smspec_node; break; case(ECL_SMSPEC_REGION_VAR): - if (!hash_has_key(ecl_smspec->region_var_index , keyword)) - hash_insert_hash_owned_ref( ecl_smspec->region_var_index , keyword , hash_alloc() , hash_free__); - { - hash_type * var_hash = (hash_type*)hash_get(ecl_smspec->region_var_index , keyword); - char num_str[16]; - sprintf( num_str , "%d" , num); - hash_insert_ref(var_hash , num_str , smspec_node); - } + ecl_smspec->region_var_index[num][keyword] = &smspec_node; ecl_smspec->num_regions = util_int_max(ecl_smspec->num_regions , num); break; case (ECL_SMSPEC_WELL_VAR): - if (well) - { - if (!hash_has_key(ecl_smspec->well_var_index , well)) - hash_insert_hash_owned_ref(ecl_smspec->well_var_index , well , hash_alloc() , hash_free__); - { - hash_type * var_hash = (hash_type*)hash_get(ecl_smspec->well_var_index , well); - hash_insert_ref(var_hash , keyword , smspec_node ); - } - } + ecl_smspec->well_var_index[well][keyword] = &smspec_node; break; case(ECL_SMSPEC_MISC_VAR): /* Misc variable - i.e. date or CPU time ... */ - hash_insert_ref(ecl_smspec->misc_var_index , keyword , smspec_node ); + ecl_smspec->misc_var_index[keyword] = &smspec_node; break; case(ECL_SMSPEC_BLOCK_VAR): - /* A block variable */ - if (!hash_has_key(ecl_smspec->block_var_index , keyword)) - hash_insert_hash_owned_ref(ecl_smspec->block_var_index , keyword , hash_alloc() , hash_free__); - { - hash_type * block_hash = (hash_type*)hash_get(ecl_smspec->block_var_index , keyword); - char block_nr[16]; - sprintf( block_nr , "%d" , num ); - hash_insert_ref(block_hash , block_nr , smspec_node); - } + ecl_smspec->block_var_index[num][keyword] = &smspec_node; break; /** The variables below are ONLY accesable through the gen_key @@ -913,9 +748,7 @@ static void ecl_smspec_install_special_keys( ecl_smspec_type * ecl_smspec , smsp case(ECL_SMSPEC_AQUIFER_VAR): break; default: - smspec_node_fprintf(smspec_node, stderr); - util_abort("%: Internal error - should never be here ?? \n",__func__); - break; + throw std::invalid_argument("Internal error - should not be here \n"); } } @@ -1006,14 +839,14 @@ bool ecl_smspec_needs_num( ecl_smspec_var_type var_type ) { bool ecl_smspec_equal(const ecl_smspec_type * self, const ecl_smspec_type * other) { - if (vector_get_size( self->smspec_nodes ) != vector_get_size( other->smspec_nodes)) + if (self->smspec_nodes.size() != other->smspec_nodes.size()) return false; - for (int i=0; i < vector_get_size( self->smspec_nodes ); i++) { - const smspec_node_type * node1 = (const smspec_node_type*)vector_iget_const(self->smspec_nodes, i); - const smspec_node_type * node2 = (const smspec_node_type*)vector_iget_const(other->smspec_nodes, i); + for (size_t i=0; i < self->smspec_nodes.size(); i++) { + const ecl::smspec_node* node1 = self->smspec_nodes[i].get(); + const ecl::smspec_node* node2 = other->smspec_nodes[i].get(); - if (!smspec_node_equal(node1, node2)) + if (node1->cmp(*node2) != 0) return false; } @@ -1035,7 +868,6 @@ static void ecl_smspec_load_restart( ecl_smspec_type * ecl_smspec , const ecl_fi restart_base = util_alloc_strip_copy( tmp_base ); if (strlen(restart_base)) { /* We ignore the empty ones. */ - char * path; char * smspec_header; /* @@ -1050,6 +882,7 @@ static void ecl_smspec_load_restart( ecl_smspec_type * ecl_smspec , const ecl_fi This code block will translate '/' -> '\' in the restart keyword which is read from the summary file. */ + #ifdef ERT_WINDOWS for (int i=0; i < strlen(restart_base); i++) { if (restart_base[i] == UTIL_POSIX_PATH_SEP_CHAR) @@ -1057,20 +890,22 @@ static void ecl_smspec_load_restart( ecl_smspec_type * ecl_smspec , const ecl_fi } #endif - util_alloc_file_components( ecl_smspec->header_file , &path , NULL , NULL ); - smspec_header = ecl_util_alloc_exfilename( path , restart_base , ECL_SUMMARY_HEADER_FILE , ecl_smspec->formatted , 0); - if (!util_same_file(smspec_header , ecl_smspec->header_file)) /* Restart from the current case is ignored. */ { - if (util_is_abs_path(restart_base)) - ecl_smspec->restart_case = util_alloc_string_copy( restart_base ); - else { - char * tmp_path = util_alloc_filename( path , restart_base , NULL ); - ecl_smspec->restart_case = util_alloc_abs_path(tmp_path); - free( tmp_path ); + std::string path = ecl::util::path::dirname( ecl_smspec->header_file ); + smspec_header = ecl_util_alloc_exfilename( path.c_str() , restart_base , ECL_SUMMARY_HEADER_FILE , ecl_smspec->formatted , 0); + if (smspec_header) { + if (!util_same_file(smspec_header , ecl_smspec->header_file.c_str())) /* Restart from the current case is ignored. */ { + if (util_is_abs_path(restart_base)) + ecl_smspec->restart_case = restart_base; + else { + char * tmp_path = util_alloc_filename( path.c_str() , restart_base , NULL ); + char * abs_path = util_alloc_abs_path(tmp_path); + ecl_smspec->restart_case = abs_path; + free( abs_path ); + free( tmp_path ); + } } + free( smspec_header ); } - - free( path ); - free( smspec_header ); } free( restart_base ); } @@ -1078,62 +913,139 @@ static void ecl_smspec_load_restart( ecl_smspec_type * ecl_smspec , const ecl_fi -void ecl_smspec_index_node( ecl_smspec_type * ecl_smspec , smspec_node_type * smspec_node) { - ecl_smspec_install_gen_keys( ecl_smspec , smspec_node ); - ecl_smspec_install_special_keys( ecl_smspec , smspec_node ); - if (smspec_node_need_nums( smspec_node )) + + + + +static const ecl::smspec_node * ecl_smspec_insert_node(ecl_smspec_type * ecl_smspec, std::unique_ptr smspec_node){ + int params_index = smspec_node->get_params_index(); + + /* This indexing must be used when writing. */ + ecl_smspec->index_map.push_back(params_index); + ecl_smspec->params_default.resize( params_index+1, PARAMS_GLOBAL_DEFAULT ); + ecl_smspec->params_default[params_index] = smspec_node->get_default(); + ecl_smspec->inv_index_map.insert( std::make_pair(params_index, ecl_smspec->smspec_nodes.size())); + + ecl_smspec_install_gen_keys( ecl_smspec, *smspec_node.get() ); + ecl_smspec_install_special_keys( ecl_smspec, *smspec_node.get() ); + + if (smspec_node->need_nums()) ecl_smspec->need_nums = true; + + ecl_smspec->smspec_nodes.push_back(std::move(smspec_node)); + + if (params_index > ecl_smspec->params_size) + ecl_smspec->params_size = params_index + 1; + + if (static_cast(ecl_smspec->smspec_nodes.size()) > ecl_smspec->params_size) + ecl_smspec->params_size = ecl_smspec->smspec_nodes.size(); + + const auto& node = ecl_smspec->smspec_nodes.back(); + return node.get(); } -static void ecl_smspec_set_params_size( ecl_smspec_type * ecl_smspec , int params_size) { - ecl_smspec->params_size = params_size; - float_vector_iset( ecl_smspec->params_default , ecl_smspec->params_size - 1 , PARAMS_GLOBAL_DEFAULT); +const ecl::smspec_node * ecl_smspec_add_node(ecl_smspec_type * ecl_smspec, const char * keyword, int num, const char * unit, float default_value) { + int params_index = ecl_smspec->smspec_nodes.size(); + return ecl_smspec_insert_node(ecl_smspec, std::unique_ptr( new ecl::smspec_node(params_index, + keyword, + num, + unit, + ecl_smspec->grid_dims, + default_value, + ecl_smspec->key_join_string.c_str()))); +} + +//copy given node with a new index +const ecl::smspec_node * ecl_smspec_add_node(ecl_smspec_type * ecl_smspec, const ecl::smspec_node& node) { + int params_index = ecl_smspec->smspec_nodes.size(); + return ecl_smspec_insert_node(ecl_smspec, std::unique_ptr( new ecl::smspec_node(node, params_index))); +} + + +const ecl::smspec_node * ecl_smspec_add_node(ecl_smspec_type * ecl_smspec, const char * keyword, const char * unit, float default_value) { + int params_index = ecl_smspec->smspec_nodes.size(); + return ecl_smspec_insert_node(ecl_smspec, std::unique_ptr( new ecl::smspec_node(params_index, + keyword, + unit, + default_value))); +} + + +const ecl::smspec_node * ecl_smspec_add_node(ecl_smspec_type * ecl_smspec, const char * keyword, const char * wgname, const char * unit, float default_value) { + int params_index = ecl_smspec->smspec_nodes.size(); + return ecl_smspec_insert_node(ecl_smspec, std::unique_ptr( new ecl::smspec_node(params_index, + keyword, + wgname, + unit, + default_value, + ecl_smspec->key_join_string.c_str()))); +} + + +const ecl::smspec_node * ecl_smspec_add_node(ecl_smspec_type * ecl_smspec, + const char * keyword, + const char * wgname, + int num, + const char * unit, + float default_value) +{ + int params_index = ecl_smspec->smspec_nodes.size(); + return ecl_smspec_insert_node(ecl_smspec, std::unique_ptr( new ecl::smspec_node(params_index, + keyword, + wgname, + num, + unit, + ecl_smspec->grid_dims, + default_value, + ecl_smspec->key_join_string.c_str()))); +} + + +const ecl::smspec_node * ecl_smspec_add_node(ecl_smspec_type * ecl_smspec, + int params_index, + const char * keyword, + const char * wgname, + int num, + const char * unit, + float default_value) +{ + return ecl_smspec_insert_node(ecl_smspec, std::unique_ptr( new ecl::smspec_node(params_index, + keyword, + wgname, + num, + unit, + ecl_smspec->grid_dims, + default_value, + ecl_smspec->key_join_string.c_str()))); +} + +const ecl::smspec_node * ecl_smspec_add_node(ecl_smspec_type * ecl_smspec, + int params_index, + const char * keyword, + const char * wgname, + int num, + const char * unit, + const char * lgr, + int lgr_i, int lgr_j, int lgr_k, + float default_value) +{ + return ecl_smspec_insert_node(ecl_smspec, std::unique_ptr( new ecl::smspec_node(params_index, + keyword, + wgname, + unit, + lgr, + lgr_i, lgr_j, lgr_k, + default_value, + ecl_smspec->key_join_string.c_str()))); } -void ecl_smspec_insert_node(ecl_smspec_type * ecl_smspec, smspec_node_type * smspec_node){ - int internal_index = vector_get_size( ecl_smspec->smspec_nodes ); - /* This IF test should only apply in write_mode. */ - if (smspec_node_get_params_index( smspec_node ) < 0) { - if (!ecl_smspec->write_mode) - util_abort("%s: internal error \n",__func__); - smspec_node_set_params_index( smspec_node , internal_index); - - if (internal_index >= ecl_smspec->params_size) - ecl_smspec_set_params_size( ecl_smspec , internal_index + 1); - } - vector_append_owned_ref( ecl_smspec->smspec_nodes , smspec_node , smspec_node_free__ ); - - { - int params_index = smspec_node_get_params_index( smspec_node ); - - /* This indexing must be used when writing. */ - int_vector_iset( ecl_smspec->index_map , internal_index , params_index); - - float_vector_iset( ecl_smspec->params_default , params_index , smspec_node_get_default(smspec_node) ); - } -} - - -void ecl_smspec_add_node( ecl_smspec_type * ecl_smspec , smspec_node_type * smspec_node ) { - ecl_smspec_insert_node( ecl_smspec , smspec_node ); - ecl_smspec_index_node( ecl_smspec , smspec_node ); -} - - - -void ecl_smspec_init_var( ecl_smspec_type * ecl_smspec , smspec_node_type * smspec_node , const char * keyword , const char * wgname , int num, const char * unit ) { - smspec_node_init( smspec_node , ecl_smspec_identify_var_type( keyword ) , wgname , keyword , unit , ecl_smspec->key_join_string , ecl_smspec->grid_dims , num ); - ecl_smspec_index_node( ecl_smspec , smspec_node ); -} - - -const int_vector_type * ecl_smspec_get_index_map( const ecl_smspec_type * smspec ) { - return smspec->index_map; +const int * ecl_smspec_get_index_map( const ecl_smspec_type * smspec ) { + return smspec->index_map.data(); } /** @@ -1178,6 +1090,7 @@ static bool ecl_smspec_fread_header(ecl_smspec_type * ecl_smspec, const char * h int params_index; ecl_smspec->num_regions = 0; + ecl_smspec->params_size = ecl_kw_get_size(keywords); if (startdat == NULL) util_abort("%s: could not locate STARTDAT keyword in header - aborting \n",__func__); @@ -1214,7 +1127,6 @@ static bool ecl_smspec_fread_header(ecl_smspec_type * ecl_smspec, const char * h ecl_smspec->grid_dims[1] = ecl_kw_iget_int(dimens , DIMENS_SMSPEC_NY_INDEX ); ecl_smspec->grid_dims[2] = ecl_kw_iget_int(dimens , DIMENS_SMSPEC_NZ_INDEX ); ecl_smspec->restart_step = ecl_kw_iget_int(dimens , DIMENS_SMSPEC_RESTART_STEP_INDEX); - ecl_smspec_set_params_size( ecl_smspec , ecl_kw_get_size(keywords)); ecl_util_get_file_type( header_file , &ecl_smspec->formatted , NULL ); @@ -1225,31 +1137,51 @@ static bool ecl_smspec_fread_header(ecl_smspec_type * ecl_smspec, const char * h char * well = (char*)util_alloc_strip_copy((const char*)ecl_kw_iget_ptr(wells , params_index)); char * kw = (char*)util_alloc_strip_copy((const char*)ecl_kw_iget_ptr(keywords , params_index)); char * unit = (char*)util_alloc_strip_copy((const char*)ecl_kw_iget_ptr(units , params_index)); - char * lgr_name = NULL; - smspec_node_type * smspec_node; - ecl_smspec_var_type var_type = ecl_smspec_identify_var_type( kw ); + ecl_smspec_var_type var_type; if (nums != NULL) num = ecl_kw_iget_int(nums , params_index); + var_type = ecl::smspec_node::valid_type(kw, well, num); + if (var_type == ECL_SMSPEC_INVALID_VAR) { + free( kw ); + free( well ); + free( unit ); + continue; + } + if (ecl_smspec_lgr_var_type( var_type )) { int lgr_i = ecl_kw_iget_int( numlx , params_index ); int lgr_j = ecl_kw_iget_int( numly , params_index ); int lgr_k = ecl_kw_iget_int( numlz , params_index ); - lgr_name = (char*)util_alloc_strip_copy( (const char*)ecl_kw_iget_ptr( lgrs , params_index )); - smspec_node = smspec_node_alloc_lgr( var_type , well , kw , unit , lgr_name , ecl_smspec->key_join_string , lgr_i , lgr_j , lgr_k , params_index, default_value); - } else - smspec_node = smspec_node_alloc( var_type , well , kw , unit , ecl_smspec->key_join_string , ecl_smspec->grid_dims , num , params_index , default_value); + char * lgr_name = (char*)util_alloc_strip_copy( (const char*)ecl_kw_iget_ptr( lgrs , params_index )); - if (smspec_node) - ecl_smspec_add_node( ecl_smspec , smspec_node ); + ecl_smspec_insert_node(ecl_smspec, std::unique_ptr( new ecl::smspec_node(params_index, + kw, + well, + unit, + lgr_name, + lgr_i, lgr_j, lgr_k, + default_value, + ecl_smspec->key_join_string.c_str()))); + free(lgr_name); + } else + ecl_smspec_insert_node(ecl_smspec, std::unique_ptr( new ecl::smspec_node(params_index, + kw, + well, + num, + unit, + ecl_smspec->grid_dims, + default_value, + ecl_smspec->key_join_string.c_str()))); free( kw ); free( well ); free( unit ); - free( lgr_name ); } } - ecl_smspec->header_file = util_alloc_realpath( header_file ); + char * header_str = util_alloc_realpath( header_file ); + ecl_smspec->header_file = header_str; + free(header_str); if (include_restart) ecl_smspec_load_restart( ecl_smspec , header ); @@ -1274,10 +1206,10 @@ ecl_smspec_type * ecl_smspec_fread_alloc(const char *header_file, const char * k if (ecl_smspec_fread_header(ecl_smspec , header_file , include_restart)) { - if (hash_has_key( ecl_smspec->misc_var_index , "TIME")) { - const smspec_node_type * time_node = (const smspec_node_type*)hash_get(ecl_smspec->misc_var_index , "TIME"); - const char * time_unit = smspec_node_get_unit( time_node ); - ecl_smspec->time_index = smspec_node_get_params_index( time_node ); + const ecl::smspec_node * time_node = ecl_smspec_get_var_node(ecl_smspec->misc_var_index, "TIME"); + if (time_node) { + const char * time_unit = time_node->get_unit(); + ecl_smspec->time_index = time_node->get_params_index(); if (util_string_equal( time_unit , "DAYS")) ecl_smspec->time_seconds = 3600 * 24; @@ -1285,12 +1217,14 @@ ecl_smspec_type * ecl_smspec_fread_alloc(const char *header_file, const char * k ecl_smspec->time_seconds = 3600; else util_abort("%s: time_unit:%s not recognized \n",__func__ , time_unit); + } - if (hash_has_key(ecl_smspec->misc_var_index , "DAY")) { - ecl_smspec->day_index = smspec_node_get_params_index( (const smspec_node_type*)hash_get(ecl_smspec->misc_var_index , "DAY") ); - ecl_smspec->month_index = smspec_node_get_params_index( (const smspec_node_type*)hash_get(ecl_smspec->misc_var_index , "MONTH") ); - ecl_smspec->year_index = smspec_node_get_params_index( (const smspec_node_type*)hash_get(ecl_smspec->misc_var_index , "YEAR") ); + const ecl::smspec_node * day_node = ecl_smspec_get_var_node(ecl_smspec->misc_var_index, "DAY"); + if (day_node != NULL) { + ecl_smspec->day_index = smspec_node_get_params_index( day_node ); + ecl_smspec->month_index = smspec_node_get_params_index( &ecl_smspec->misc_var_index["MONTH"] ); + ecl_smspec->year_index = smspec_node_get_params_index( &ecl_smspec->misc_var_index["YEAR"] ); } if ((ecl_smspec->time_index == -1) && ( ecl_smspec->day_index == -1)) { @@ -1313,13 +1247,13 @@ ecl_smspec_type * ecl_smspec_fread_alloc(const char *header_file, const char * k int ecl_smspec_get_num_groups(const ecl_smspec_type * ecl_smspec) { - return hash_get_size(ecl_smspec->group_var_index); + return ecl_smspec->group_var_index.size(); } -char ** ecl_smspec_alloc_group_names(const ecl_smspec_type * ecl_smspec) { +/*char ** ecl_smspec_alloc_group_names(const ecl_smspec_type * ecl_smspec) { return hash_alloc_keylist(ecl_smspec->group_var_index); -} +}*/ int ecl_smspec_get_num_regions(const ecl_smspec_type * ecl_smspec) { return ecl_smspec->num_regions; @@ -1353,15 +1287,15 @@ int ecl_smspec_get_num_regions(const ecl_smspec_type * ecl_smspec) { /*****************************************************************/ -#define NODE_RETURN_INDEX(node) \ - if (node == NULL) \ +#define NODE_RETURN_INDEX(node_ptr) \ + if (!node_ptr) \ return -1; \ - else \ - return smspec_node_get_params_index( node ); + else \ + return smspec_node_get_params_index( node_ptr ); -#define NODE_RETURN_EXISTS(node) \ - if (node == NULL) \ +#define NODE_RETURN_EXISTS(node_ptr) \ + if (!node_ptr) \ return false; \ else \ return true; @@ -1371,26 +1305,24 @@ int ecl_smspec_get_num_regions(const ecl_smspec_type * ecl_smspec) { /******************************************************************/ /* Well variables */ -const smspec_node_type * ecl_smspec_get_well_var_node( const ecl_smspec_type * smspec , const char * well , const char * var) { - const smspec_node_type * node = NULL; - if (hash_has_key( smspec->well_var_index , well)) { - hash_type * var_hash = (hash_type*)hash_get(smspec->well_var_index , well); - if (hash_has_key(var_hash , var)) - node = (const smspec_node_type*)hash_get(var_hash , var); - } - return node; +const ecl::smspec_node& ecl_smspec_get_well_var_node( const ecl_smspec_type * smspec , const char * well , const char * var) { + const auto node_ptr = ecl_smspec_get_str_key_var_node(smspec->well_var_index, well, var); + if (!node_ptr) + throw std::out_of_range("The well: " + std::string(well) + " variable: " + std::string(var) + " combination does not exist."); + + return *node_ptr; } int ecl_smspec_get_well_var_params_index(const ecl_smspec_type * ecl_smspec , const char * well , const char *var) { - const smspec_node_type * node = ecl_smspec_get_well_var_node( ecl_smspec , well , var ); - NODE_RETURN_INDEX(node); + const auto node_ptr = ecl_smspec_get_str_key_var_node(ecl_smspec->well_var_index, well, var); + NODE_RETURN_INDEX(node_ptr); } bool ecl_smspec_has_well_var(const ecl_smspec_type * ecl_smspec , const char * well , const char *var) { - const smspec_node_type * node = ecl_smspec_get_well_var_node(ecl_smspec , well ,var); - NODE_RETURN_EXISTS(node); + const auto node_ptr = ecl_smspec_get_str_key_var_node(ecl_smspec->well_var_index, well, var); + NODE_RETURN_EXISTS(node_ptr); } @@ -1398,52 +1330,50 @@ bool ecl_smspec_has_well_var(const ecl_smspec_type * ecl_smspec , const char * w /*****************************************************************/ /* Group variables */ -const smspec_node_type * ecl_smspec_get_group_var_node( const ecl_smspec_type * smspec , const char * group , const char * var) { - const smspec_node_type * node = NULL; - if (hash_has_key(smspec->group_var_index , group)) { - hash_type * var_hash = (hash_type*)hash_get(smspec->group_var_index , group); - if (hash_has_key(var_hash , var)) - node = (const smspec_node_type*)hash_get(var_hash , var); - } - return node; +const ecl::smspec_node& ecl_smspec_get_group_var_node( const ecl_smspec_type * smspec , const char * group , const char * var) { + const auto node_ptr = ecl_smspec_get_str_key_var_node(smspec->group_var_index, group, var); + if (!node_ptr) + throw std::out_of_range("The group: " + std::string(group) + " variable: " + std::string(var) + " combination does not exist."); + + return *node_ptr; } int ecl_smspec_get_group_var_params_index(const ecl_smspec_type * ecl_smspec , const char * group , const char *var) { - const smspec_node_type * node = ecl_smspec_get_group_var_node( ecl_smspec , group , var ); - NODE_RETURN_INDEX(node); + const auto node_ptr = ecl_smspec_get_str_key_var_node(ecl_smspec->group_var_index, group, var); + NODE_RETURN_INDEX(node_ptr); } bool ecl_smspec_has_group_var(const ecl_smspec_type * ecl_smspec , const char * group , const char *var) { - const smspec_node_type * node = ecl_smspec_get_group_var_node(ecl_smspec , group ,var); - NODE_RETURN_EXISTS(node); + const auto node_ptr = ecl_smspec_get_str_key_var_node(ecl_smspec->group_var_index, group, var); + NODE_RETURN_EXISTS(node_ptr); } /*****************************************************************/ /* Field variables */ -const smspec_node_type * ecl_smspec_get_field_var_node(const ecl_smspec_type * ecl_smspec , const char *var) { - const smspec_node_type * node = NULL; - if (hash_has_key(ecl_smspec->field_var_index , var)) - node = (const smspec_node_type*)hash_get(ecl_smspec->field_var_index , var); +const ecl::smspec_node& ecl_smspec_get_field_var_node(const ecl_smspec_type * ecl_smspec , const char *var) { + const auto node_ptr = ecl_smspec_get_var_node( ecl_smspec->field_var_index, var); + if (!node_ptr) + throw std::out_of_range("The field variable: " + std::string(var) + " does not exist."); - return node; + return *node_ptr; } int ecl_smspec_get_field_var_params_index(const ecl_smspec_type * ecl_smspec , const char *var) { - const smspec_node_type * node = ecl_smspec_get_field_var_node( ecl_smspec , var ); - NODE_RETURN_INDEX(node); + const auto node_ptr = ecl_smspec_get_var_node(ecl_smspec->field_var_index, var); + NODE_RETURN_INDEX(node_ptr); } bool ecl_smspec_has_field_var(const ecl_smspec_type * ecl_smspec , const char *var) { - const smspec_node_type * node = ecl_smspec_get_field_var_node( ecl_smspec , var ); - NODE_RETURN_EXISTS(node); + const auto node_ptr = ecl_smspec_get_var_node(ecl_smspec->field_var_index, var); + NODE_RETURN_EXISTS(node_ptr); } /*****************************************************************/ @@ -1457,54 +1387,40 @@ bool ecl_smspec_has_field_var(const ecl_smspec_type * ecl_smspec , const char *v hash tables. */ -static const smspec_node_type * ecl_smspec_get_block_var_node_string(const ecl_smspec_type * ecl_smspec , const char * block_var , const char * block_str) { - const smspec_node_type * node = NULL; - if (hash_has_key(ecl_smspec->block_var_index , block_var)) { - hash_type * block_hash = (hash_type*)hash_get(ecl_smspec->block_var_index , block_var); - if (hash_has_key(block_hash , block_str)) - node = (const smspec_node_type*)hash_get(block_hash , block_str); - } +const ecl::smspec_node& ecl_smspec_get_block_var_node(const ecl_smspec_type * ecl_smspec , const char * block_var , int block_nr) { + const auto node_ptr = ecl_smspec_get_int_key_var_node(ecl_smspec->block_var_index, block_nr, block_var); + if (!node_ptr) + throw std::out_of_range("No such block variable"); - return node; + return *node_ptr; } -const smspec_node_type * ecl_smspec_get_block_var_node(const ecl_smspec_type * ecl_smspec , const char * block_var , int block_nr) { - const smspec_node_type * node; - char * block_str = util_alloc_sprintf("%d" , block_nr); - node = ecl_smspec_get_block_var_node_string(ecl_smspec , block_var , block_str); - free( block_str ); - return node; -} - - -const smspec_node_type * ecl_smspec_get_block_var_node_ijk(const ecl_smspec_type * ecl_smspec , const char * block_var , int i , int j , int k) { +const ecl::smspec_node& ecl_smspec_get_block_var_node_ijk(const ecl_smspec_type * ecl_smspec , const char * block_var , int i , int j , int k) { return ecl_smspec_get_block_var_node( ecl_smspec , block_var , ecl_smspec_get_global_grid_index( ecl_smspec , i,j,k) ); } bool ecl_smspec_has_block_var(const ecl_smspec_type * ecl_smspec , const char * block_var , int block_nr) { - const smspec_node_type * node = ecl_smspec_get_block_var_node( ecl_smspec , block_var , block_nr ); - NODE_RETURN_EXISTS(node); + const auto node_ptr = ecl_smspec_get_int_key_var_node(ecl_smspec->block_var_index, block_nr, block_var); + NODE_RETURN_EXISTS(node_ptr); } bool ecl_smspec_has_block_var_ijk(const ecl_smspec_type * ecl_smspec , const char * block_var , int i , int j , int k) { - const smspec_node_type * node = ecl_smspec_get_block_var_node_ijk( ecl_smspec , block_var , i,j,k ); - NODE_RETURN_EXISTS(node); + return ecl_smspec_has_block_var(ecl_smspec, block_var, ecl_smspec_get_global_grid_index(ecl_smspec, i, j, k)); } int ecl_smspec_get_block_var_params_index(const ecl_smspec_type * ecl_smspec , const char * block_var , int block_nr) { - const smspec_node_type * node = ecl_smspec_get_block_var_node( ecl_smspec , block_var , block_nr ); - NODE_RETURN_INDEX(node); + const auto node_ptr = ecl_smspec_get_int_key_var_node(ecl_smspec->block_var_index, block_nr, block_var); + NODE_RETURN_INDEX(node_ptr); } int ecl_smspec_get_block_var_params_index_ijk(const ecl_smspec_type * ecl_smspec , const char * block_var , int i , int j , int k) { - const smspec_node_type * node = ecl_smspec_get_block_var_node_ijk( ecl_smspec , block_var , i,j,k ); - NODE_RETURN_INDEX(node); + return ecl_smspec_get_block_var_params_index(ecl_smspec, block_var, ecl_smspec_get_global_grid_index(ecl_smspec, i, j, k)); } @@ -1516,53 +1432,46 @@ int ecl_smspec_get_block_var_params_index_ijk(const ecl_smspec_type * ecl_smspec -const smspec_node_type * ecl_smspec_get_region_var_node(const ecl_smspec_type * ecl_smspec , const char *region_var , int region_nr) { - const smspec_node_type * node = NULL; +const ecl::smspec_node& ecl_smspec_get_region_var_node(const ecl_smspec_type * ecl_smspec , const char *region_var , int region_nr) { + const auto node_ptr = ecl_smspec_get_int_key_var_node(ecl_smspec->region_var_index, region_nr, region_var); + if (!node_ptr) + throw std::out_of_range("No such block variable"); - if (hash_has_key(ecl_smspec->region_var_index , region_var)) { - char * nr_str = util_alloc_sprintf( "%d" , region_nr ); - hash_type * nr_hash = (hash_type*)hash_get(ecl_smspec->region_var_index , region_var); - if (hash_has_key( nr_hash , nr_str)) - node = (const smspec_node_type*)hash_get( nr_hash , nr_str ); - free( nr_str ); - } - - return node; + return *node_ptr; } bool ecl_smspec_has_region_var(const ecl_smspec_type * ecl_smspec , const char *region_var, int region_nr) { - const smspec_node_type * node = ecl_smspec_get_region_var_node( ecl_smspec , region_var , region_nr ); - NODE_RETURN_EXISTS(node); + const auto node_ptr = ecl_smspec_get_int_key_var_node(ecl_smspec->region_var_index, region_nr, region_var); + NODE_RETURN_EXISTS(node_ptr); } int ecl_smspec_get_region_var_params_index(const ecl_smspec_type * ecl_smspec , const char *region_var, int region_nr) { - const smspec_node_type * node = ecl_smspec_get_region_var_node( ecl_smspec , region_var , region_nr ); - NODE_RETURN_INDEX(node); + const auto node_ptr = ecl_smspec_get_int_key_var_node(ecl_smspec->region_var_index, region_nr, region_var); + NODE_RETURN_INDEX(node_ptr); } /*****************************************************************/ /* Misc variables */ -const smspec_node_type * ecl_smspec_get_misc_var_node(const ecl_smspec_type * ecl_smspec , const char *var) { - const smspec_node_type * node = NULL; +const ecl::smspec_node& ecl_smspec_get_misc_var_node(const ecl_smspec_type * ecl_smspec , const char *var) { + const auto node_ptr = ecl_smspec_get_var_node(ecl_smspec->misc_var_index, var); + if (!node_ptr) + throw std::out_of_range("No such misc variable"); - if (hash_has_key(ecl_smspec->misc_var_index , var)) - node = (const smspec_node_type*)hash_get(ecl_smspec->misc_var_index , var); - - return node; + return *node_ptr; } bool ecl_smspec_has_misc_var(const ecl_smspec_type * ecl_smspec , const char *var) { - const smspec_node_type * node = ecl_smspec_get_misc_var_node( ecl_smspec , var ); - NODE_RETURN_EXISTS(node); + const auto node_ptr = ecl_smspec_get_var_node(ecl_smspec->misc_var_index , var ); + NODE_RETURN_EXISTS(node_ptr); } int ecl_smspec_get_misc_var_params_index(const ecl_smspec_type * ecl_smspec , const char *var) { - const smspec_node_type * node = ecl_smspec_get_misc_var_node( ecl_smspec , var ); - NODE_RETURN_INDEX(node); + const auto node_ptr = ecl_smspec_get_var_node(ecl_smspec->misc_var_index , var ); + NODE_RETURN_INDEX(node_ptr); } @@ -1570,33 +1479,33 @@ int ecl_smspec_get_misc_var_params_index(const ecl_smspec_type * ecl_smspec , co /* Well completion - not fully implemented ?? */ -const smspec_node_type * ecl_smspec_get_well_completion_var_node(const ecl_smspec_type * ecl_smspec , const char * well , const char *var, int cell_nr) { - const smspec_node_type * node = NULL; +const ecl::smspec_node * ecl_smspec_get_well_completion_var_node__(const ecl_smspec_type * ecl_smspec , const char * well , const char *var, int cell_nr) { + const auto well_iter = ecl_smspec->well_completion_var_index.find(well); + if (well_iter == ecl_smspec->well_completion_var_index.end()) + return nullptr; - char * cell_str = util_alloc_sprintf("%d" , cell_nr); - if (hash_has_key(ecl_smspec->well_completion_var_index , well)) { - hash_type * cell_hash = (hash_type*)hash_get(ecl_smspec->well_completion_var_index , well); + const auto& num_map = well_iter->second; + return ecl_smspec_get_int_key_var_node( num_map, cell_nr, var ); +} - if (hash_has_key(cell_hash , cell_str)) { - hash_type * var_hash = (hash_type*)hash_get(cell_hash , cell_str); - if (hash_has_key(var_hash , var)) - node = (const smspec_node_type*)hash_get( var_hash , var); - } - } - free(cell_str); - return node; +const ecl::smspec_node& ecl_smspec_get_well_completion_var_node(const ecl_smspec_type * ecl_smspec , const char * well , const char *var, int cell_nr) { + const auto node_ptr = ecl_smspec_get_well_completion_var_node__(ecl_smspec, well, var, cell_nr); + if (!node_ptr) + throw std::out_of_range("No such well/var/completion"); + + return *node_ptr; } bool ecl_smspec_has_well_completion_var(const ecl_smspec_type * ecl_smspec , const char * well , const char *var, int cell_nr) { - const smspec_node_type * node = ecl_smspec_get_well_completion_var_node( ecl_smspec , well , var , cell_nr ); - NODE_RETURN_EXISTS( node ); + const auto node_ptr = ecl_smspec_get_well_completion_var_node__( ecl_smspec , well , var , cell_nr ); + NODE_RETURN_EXISTS( node_ptr ); } int ecl_smspec_get_well_completion_var_params_index(const ecl_smspec_type * ecl_smspec , const char * well , const char *var, int cell_nr) { - const smspec_node_type * node = ecl_smspec_get_well_completion_var_node( ecl_smspec , well , var , cell_nr ); - NODE_RETURN_INDEX( node ); + const auto node_ptr = ecl_smspec_get_well_completion_var_node__( ecl_smspec , well , var , cell_nr ); + NODE_RETURN_INDEX( node_ptr ); } @@ -1610,31 +1519,31 @@ int ecl_smspec_get_well_completion_var_params_index(const ecl_smspec_type * ecl -const smspec_node_type * ecl_smspec_get_general_var_node( const ecl_smspec_type * smspec , const char * lookup_kw ) { - if (hash_has_key( smspec->gen_var_index , lookup_kw )) { - const smspec_node_type * smspec_node = (const smspec_node_type*)hash_get( smspec->gen_var_index , lookup_kw ); - return smspec_node; - } else - return NULL; +const ecl::smspec_node& ecl_smspec_get_general_var_node( const ecl_smspec_type * smspec , const char * lookup_kw ) { + const auto node_ptr = ecl_smspec_get_var_node(smspec->gen_var_index, lookup_kw); + if (!node_ptr) + throw std::out_of_range("No such variable: " + std::string(lookup_kw)); + + return *node_ptr; } int ecl_smspec_get_general_var_params_index(const ecl_smspec_type * ecl_smspec , const char * lookup_kw) { - const smspec_node_type * node = ecl_smspec_get_general_var_node( ecl_smspec , lookup_kw ); - NODE_RETURN_INDEX( node ); + const auto node_ptr = ecl_smspec_get_var_node(ecl_smspec->gen_var_index , lookup_kw ); + NODE_RETURN_INDEX( node_ptr ); } bool ecl_smspec_has_general_var(const ecl_smspec_type * ecl_smspec , const char * lookup_kw) { - const smspec_node_type * node = ecl_smspec_get_general_var_node( ecl_smspec , lookup_kw ); - NODE_RETURN_EXISTS( node ); + const auto node_ptr = ecl_smspec_get_var_node(ecl_smspec->gen_var_index , lookup_kw ); + NODE_RETURN_EXISTS( node_ptr ); } /** DIES if the lookup_kw is not present. */ const char * ecl_smspec_get_general_var_unit( const ecl_smspec_type * ecl_smspec , const char * lookup_kw) { - const smspec_node_type * smspec_node = (const smspec_node_type*)hash_get( ecl_smspec->gen_var_index , lookup_kw ); - return smspec_node_get_unit( smspec_node ); + const auto smspec_node = ecl_smspec_get_general_var_node(ecl_smspec, lookup_kw); + return smspec_node_get_unit( &smspec_node ); } @@ -1645,22 +1554,22 @@ const char * ecl_smspec_get_general_var_unit( const ecl_smspec_type * ecl_smspec */ //const char * ecl_smspec_iget_unit( const ecl_smspec_type * smspec , int node_index ) { -// const smspec_node_type * smspec_node = ecl_smspec_iget_node( smspec , node_index ); +// const ecl::smspec_node * smspec_node = ecl_smspec_iget_node( smspec , node_index ); // return smspec_node_get_unit( smspec_node ); //} // //int ecl_smspec_iget_num( const ecl_smspec_type * smspec , int node_index ) { -// const smspec_node_type * smspec_node = ecl_smspec_iget_node( smspec , node_index ); +// const ecl::smspec_node * smspec_node = ecl_smspec_iget_node( smspec , node_index ); // return smspec_node_get_num( smspec_node ); //} // //const char * ecl_smspec_iget_wgname( const ecl_smspec_type * smspec , int node_index ) { -// const smspec_node_type * smspec_node = ecl_smspec_iget_node( smspec , node_index ); +// const ecl::smspec_node * smspec_node = ecl_smspec_iget_node( smspec , node_index ); // return smspec_node_get_wgname( smspec_node ); //} // //const char * ecl_smspec_iget_keyword( const ecl_smspec_type * smspec , int index ) { -// const smspec_node_type * smspec_node = ecl_smspec_iget_node( smspec , index ); +// const ecl::smspec_node * smspec_node = ecl_smspec_iget_node( smspec , index ); // return smspec_node_get_keyword( smspec_node ); //} @@ -1684,7 +1593,7 @@ bool ecl_smspec_get_formatted( const ecl_smspec_type * ecl_smspec) { } const char * ecl_smspec_get_header_file( const ecl_smspec_type * ecl_smspec ) { - return ecl_smspec->header_file; + return ecl_smspec->header_file.c_str(); } @@ -1701,31 +1610,18 @@ int ecl_smspec_get_first_step(const ecl_smspec_type * ecl_smspec) { const char * ecl_smspec_get_restart_case( const ecl_smspec_type * ecl_smspec) { - return ecl_smspec->restart_case; + if (ecl_smspec->restart_case.size() > 0) + return ecl_smspec->restart_case.c_str(); + else + return NULL; } - -const float_vector_type * ecl_smspec_get_params_default( const ecl_smspec_type * ecl_smspec ) { +const std::vector& ecl_smspec_get_params_default( const ecl_smspec_type * ecl_smspec ) { return ecl_smspec->params_default; } - - void ecl_smspec_free(ecl_smspec_type *ecl_smspec) { - hash_free(ecl_smspec->well_var_index); - hash_free(ecl_smspec->well_completion_var_index); - hash_free(ecl_smspec->group_var_index); - hash_free(ecl_smspec->field_var_index); - hash_free(ecl_smspec->region_var_index); - hash_free(ecl_smspec->misc_var_index); - hash_free(ecl_smspec->block_var_index); - hash_free(ecl_smspec->gen_var_index); - free( ecl_smspec->header_file ); - int_vector_free( ecl_smspec->index_map ); - float_vector_free( ecl_smspec->params_default ); - vector_free( ecl_smspec->smspec_nodes ); - free( ecl_smspec->restart_case ); - free( ecl_smspec ); + delete ecl_smspec; } @@ -1757,8 +1653,8 @@ int ecl_smspec_get_date_year_index( const ecl_smspec_type * smspec ) { bool ecl_smspec_general_is_total( const ecl_smspec_type * smspec , const char * gen_key) { - const smspec_node_type * smspec_node = (const smspec_node_type*)hash_get( smspec->gen_var_index , gen_key ); - return smspec_node_is_total( smspec_node ); + const ecl::smspec_node& smspec_node = ecl_smspec_get_general_var_node(smspec, gen_key); + return smspec_node_is_total( &smspec_node ); } @@ -1786,15 +1682,13 @@ bool ecl_smspec_general_is_total( const ecl_smspec_type * smspec , const char * void ecl_smspec_select_matching_general_var_list( const ecl_smspec_type * smspec , const char * pattern , stringlist_type * keys) { - hash_type * ex_keys = hash_alloc( ); - int i; - for (i=0; i < stringlist_get_size( keys ); i++) - hash_insert_int( ex_keys , stringlist_iget( keys , i ) , 1); + std::set ex_keys; + for (int i=0; i < stringlist_get_size( keys ); i++) + ex_keys.insert( stringlist_iget(keys, i)); { - hash_iter_type * iter = hash_iter_alloc( smspec->gen_var_index ); - while (!hash_iter_is_complete( iter )) { - const char * key = hash_iter_get_next_key( iter ); + for (const auto& pair : smspec->gen_var_index) { + const char * key = pair.first.c_str(); /* The TIME is typically special cased by output and will not @@ -1807,14 +1701,12 @@ void ecl_smspec_select_matching_general_var_list( const ecl_smspec_type * smspec if ((pattern == NULL) || (util_fnmatch( pattern , key ) == 0)) { - if (!hash_has_key( ex_keys , key)) + if (ex_keys.find(key) == ex_keys.end()) stringlist_append_copy( keys , key ); } } - hash_iter_free( iter ); } - hash_free( ex_keys ); stringlist_sort( keys , (string_cmp_ftype *) util_strcmp_int ); } @@ -1833,7 +1725,7 @@ stringlist_type * ecl_smspec_alloc_matching_general_var_list(const ecl_smspec_ty const char * ecl_smspec_get_join_string( const ecl_smspec_type * smspec) { - return smspec->key_join_string; + return smspec->key_join_string.c_str(); } @@ -1850,24 +1742,25 @@ const char * ecl_smspec_get_join_string( const ecl_smspec_type * smspec) { i.e. standard shell wildcards. */ -stringlist_type * ecl_smspec_alloc_well_list( const ecl_smspec_type * smspec , const char * pattern) { - stringlist_type * well_list = stringlist_alloc_new( ); - { - hash_iter_type * iter = hash_iter_alloc( smspec->well_var_index ); +static stringlist_type * ecl_smspec_alloc_map_list( const std::map& mp , const char * pattern) { + stringlist_type * map_list = stringlist_alloc_new( ); + + for (const auto& pair : mp) { + const char * map_name = pair.first.c_str(); + + if (pattern == NULL) + stringlist_append_copy( map_list , map_name ); + else if (util_fnmatch( pattern , map_name) == 0) + stringlist_append_copy( map_list , map_name ); - while (!hash_iter_is_complete( iter )) { - const char * well_name = hash_iter_get_next_key( iter ); - if (pattern == NULL) - stringlist_append_copy( well_list , well_name ); - else if (util_fnmatch( pattern , well_name) == 0) - stringlist_append_copy( well_list , well_name ); - } - hash_iter_free(iter); } - stringlist_sort( well_list , (string_cmp_ftype *) util_strcmp_int ); - return well_list; + stringlist_sort( map_list , (string_cmp_ftype *) util_strcmp_int ); + return map_list; } +stringlist_type * ecl_smspec_alloc_well_list( const ecl_smspec_type * smspec , const char * pattern) { + return ecl_smspec_alloc_map_list( smspec->well_var_index, pattern ); +} /** Returns a stringlist instance with all the (valid) group names. It @@ -1876,21 +1769,7 @@ stringlist_type * ecl_smspec_alloc_well_list( const ecl_smspec_type * smspec , c */ stringlist_type * ecl_smspec_alloc_group_list( const ecl_smspec_type * smspec , const char * pattern) { - stringlist_type * group_list = stringlist_alloc_new( ); - { - hash_iter_type * iter = hash_iter_alloc( smspec->group_var_index ); - - while (!hash_iter_is_complete( iter )) { - const char * group_name = hash_iter_get_next_key( iter ); - if (pattern == NULL) - stringlist_append_copy( group_list , group_name ); - else if (util_fnmatch( pattern , group_name) == 0) - stringlist_append_copy( group_list , group_name ); - } - hash_iter_free(iter); - } - stringlist_sort( group_list , (string_cmp_ftype *) util_strcmp_int ); - return group_list; + return ecl_smspec_alloc_map_list( smspec->group_var_index, pattern ); } @@ -1902,18 +1781,15 @@ stringlist_type * ecl_smspec_alloc_group_list( const ecl_smspec_type * smspec , */ stringlist_type * ecl_smspec_alloc_well_var_list( const ecl_smspec_type * smspec ) { - hash_iter_type * well_iter = hash_iter_alloc( smspec->well_var_index ); - hash_type * var_hash = (hash_type*)hash_iter_get_next_value( well_iter ); - hash_iter_free( well_iter ); - return hash_alloc_stringlist( var_hash ); + stringlist_type * stringlist = stringlist_alloc_new(); + for (const auto& pair : smspec->well_var_index) + stringlist_append_copy(stringlist, pair.first.c_str()); + + return stringlist; } -int ecl_smspec_get_params_size( const ecl_smspec_type * smspec ) { - return smspec->params_size; -} - const int * ecl_smspec_get_grid_dims( const ecl_smspec_type * smspec ) { @@ -1926,19 +1802,19 @@ const int * ecl_smspec_get_grid_dims( const ecl_smspec_type * smspec ) { /*****************************************************************/ char * ecl_smspec_alloc_well_key( const ecl_smspec_type * smspec , const char * keyword , const char * wgname) { - return smspec_alloc_well_key( smspec->key_join_string , keyword , wgname ); + return smspec_alloc_well_key( smspec->key_join_string.c_str() , keyword , wgname ); } -void ecl_smspec_sort( ecl_smspec_type * smspec ) { - vector_sort( smspec->smspec_nodes , smspec_node_cmp__); +/*void ecl_smspec_sort( ecl_smspec_type * smspec ) { + std::sort(smspec->smspec_nodes.begin(), smspec->smspec_nodes.end(), smspec_node_lt); - for (int i=0; i < vector_get_size( smspec->smspec_nodes ); i++) { - smspec_node_type * node = (smspec_node_type*)vector_iget( smspec->smspec_nodes , i ); - smspec_node_set_params_index( node , i ); + for (int i=0; i < static_cast(smspec->smspec_nodes.size()); i++) { + ecl::smspec_node& node = *smspec->smspec_nodes[i].get(); + smspec_node_set_params_index( &node , i ); } - } +*/ ert_ecl_unit_enum ecl_smspec_get_unit_system(const ecl_smspec_type * smspec) { return smspec->unit_system; diff --git a/ThirdParty/Ert/lib/ecl/ecl_subsidence.cpp b/ThirdParty/Ert/lib/ecl/ecl_subsidence.cpp index 1e06968afd..faec3f3fc3 100644 --- a/ThirdParty/Ert/lib/ecl/ecl_subsidence.cpp +++ b/ThirdParty/Ert/lib/ecl/ecl_subsidence.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'ecl_subsidence.c' is part of ERT - Ensemble based Reservoir Tool. @@ -75,6 +75,7 @@ struct ecl_subsidence_survey_struct { char * name; /* Name of the survey - arbitrary string. */ double * porv; /* Reference pore volume */ double * pressure; /* Pressure in each grid cell at survey time */ + double * dynamic_porevolume; /* Porevolume in each grid cell at survey time */ }; @@ -92,6 +93,7 @@ static ecl_subsidence_survey_type * ecl_subsidence_survey_alloc_empty(const ecl_ survey->porv = (double*) util_calloc( sub->grid_cache->size() , sizeof * survey->porv ); survey->pressure = (double*) util_calloc( sub->grid_cache->size() , sizeof * survey->pressure ); + survey->dynamic_porevolume = NULL; return survey; } @@ -111,9 +113,18 @@ static ecl_subsidence_survey_type * ecl_subsidence_survey_alloc_PRESSURE(ecl_sub ecl_kw_type * init_porv_kw = ecl_file_iget_named_kw( ecl_subsidence->init_file , PORV_KW , 0); /*Global indexing*/ ecl_kw_type * pressure_kw = ecl_file_view_iget_named_kw( restart_view , PRESSURE_KW , 0); /*Active indexing*/ + ecl_kw_type * rporv_kw = NULL; + if(ecl_file_view_has_kw(restart_view, RPORV_KW)) { + survey->dynamic_porevolume = (double*) util_calloc( ecl_subsidence->grid_cache->size() , sizeof * survey->dynamic_porevolume); + rporv_kw = ecl_file_view_iget_named_kw(restart_view, RPORV_KW, 0); + } + for (active_index = 0; active_index < size; active_index++){ survey->porv[ active_index ] = ecl_kw_iget_float( init_porv_kw , global_index[active_index] ); survey->pressure[ active_index ] = ecl_kw_iget_float( pressure_kw , active_index ); + + if(rporv_kw) + survey->dynamic_porevolume[ active_index ] = ecl_kw_iget_float(rporv_kw, active_index); } return survey; } @@ -126,6 +137,7 @@ static void ecl_subsidence_survey_free( ecl_subsidence_survey_type * subsidence_ free( subsidence_survey->name ); free( subsidence_survey->porv ); free( subsidence_survey->pressure ); + free( subsidence_survey->dynamic_porevolume ); free( subsidence_survey ); } @@ -193,6 +205,47 @@ static double ecl_subsidence_survey_eval_geertsma( const ecl_subsidence_survey_t } +static double ecl_subsidence_survey_eval_geertsma_rporv( const ecl_subsidence_survey_type * base_survey , + const ecl_subsidence_survey_type * monitor_survey, + ecl_region_type * region , + double utm_x , double utm_y , double depth, + double youngs_modulus, double poisson_ratio, double seabed) { + + const ecl::ecl_grid_cache& grid_cache = *(base_survey->grid_cache); + std::vector weight(grid_cache.size()); + + if(!base_survey->dynamic_porevolume) { + util_abort( + "%s: Keyword RPORV not defined in .UNRST file for %s. Please add RPORV keyword to output in RPTRST clause in .DATA file.\n", + __func__, base_survey->name); + } + + if(monitor_survey && !monitor_survey->dynamic_porevolume) { + util_abort( + "%s: Keyword RPORV not defined in .UNRST file for %s. Please add RPORV keyword to output in RPTRST clause in .DATA file.\n", + __func__, monitor_survey->name); + } + + for (size_t index = 0; index < weight.size(); ++index) { + if (monitor_survey) + weight[index] = (base_survey->dynamic_porevolume[index] - monitor_survey->dynamic_porevolume[index]) / (4*M_PI); + else + weight[index] = base_survey->dynamic_porevolume[index] / (4*M_PI); + } + + return ecl_grav_common_eval_geertsma( + grid_cache, + region, + base_survey->aquifer_cell, + weight.data(), + utm_x, + utm_y, + depth, + poisson_ratio, + seabed + ); +} + /*****************************************************************/ /** @@ -254,6 +307,14 @@ double ecl_subsidence_eval_geertsma( const ecl_subsidence_type * subsidence , co return ecl_subsidence_survey_eval_geertsma( base_survey , monitor_survey , region , utm_x , utm_y , depth , youngs_modulus, poisson_ratio, seabed); } +double ecl_subsidence_eval_geertsma_rporv( const ecl_subsidence_type * subsidence , const char * base, const char * monitor , ecl_region_type * region , + double utm_x, double utm_y , double depth, + double youngs_modulus, double poisson_ratio, double seabed) { + ecl_subsidence_survey_type * base_survey = ecl_subsidence_get_survey( subsidence , base ); + ecl_subsidence_survey_type * monitor_survey = ecl_subsidence_get_survey( subsidence , monitor ); + return ecl_subsidence_survey_eval_geertsma_rporv( base_survey , monitor_survey , region , utm_x , utm_y , depth , youngs_modulus, poisson_ratio, seabed); +} + void ecl_subsidence_free( ecl_subsidence_type * ecl_subsidence ) { delete ecl_subsidence->grid_cache; diff --git a/ThirdParty/Ert/lib/ecl/ecl_sum.cpp b/ThirdParty/Ert/lib/ecl/ecl_sum.cpp index c5c27b58ee..a64e2e4bd8 100644 --- a/ThirdParty/Ert/lib/ecl/ecl_sum.cpp +++ b/ThirdParty/Ert/lib/ecl/ecl_sum.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'ecl_sum.c' is part of ERT - Ensemble based Reservoir Tool. @@ -290,32 +290,16 @@ void ecl_sum_set_fmt_case( ecl_sum_type * ecl_sum , bool fmt_case ) { -smspec_node_type * ecl_sum_add_var( ecl_sum_type * ecl_sum , const char * keyword , const char * wgname , int num , const char * unit , float default_value) { +const ecl::smspec_node * ecl_sum_add_var( ecl_sum_type * ecl_sum , const char * keyword , const char * wgname , int num , const char * unit , float default_value) { if (ecl_sum_data_get_length(ecl_sum->data) > 0) throw std::invalid_argument("Can not interchange variable adding and timesteps.\n"); - - smspec_node_type * smspec_node = smspec_node_alloc( ecl_smspec_identify_var_type(keyword), - wgname, - keyword, - unit, - ecl_sum->key_join_string, - ecl_smspec_get_grid_dims(ecl_sum->smspec), - num, - -1, - default_value); - ecl_smspec_add_node(ecl_sum->smspec, smspec_node); - ecl_sum_data_reset_self_map( ecl_sum->data ); - return smspec_node; + return ecl_smspec_add_node( ecl_sum->smspec, keyword, wgname, num, unit, default_value); } -smspec_node_type * ecl_sum_add_smspec_node(ecl_sum_type * ecl_sum, const smspec_node_type * node) { - return ecl_sum_add_var(ecl_sum, - smspec_node_get_keyword(node), - smspec_node_get_wgname(node), - smspec_node_get_num(node), - smspec_node_get_unit(node), - smspec_node_get_default(node)); + +const ecl::smspec_node * ecl_sum_add_smspec_node(ecl_sum_type * ecl_sum, const ecl::smspec_node * node) { + return ecl_smspec_add_node(ecl_sum->smspec, *node); } @@ -335,7 +319,8 @@ smspec_node_type * ecl_sum_add_smspec_node(ecl_sum_type * ecl_sum, const smspec_ */ ecl_sum_tstep_type * ecl_sum_add_tstep( ecl_sum_type * ecl_sum , int report_step , double sim_seconds) { - return ecl_sum_data_add_new_tstep( ecl_sum->data , report_step , sim_seconds ); + ecl_sum_tstep_type * new_tstep = ecl_sum_data_add_new_tstep( ecl_sum->data , report_step , sim_seconds ); + return new_tstep; } static ecl_sum_type * ecl_sum_alloc_writer__( const char * ecl_case , const char * restart_case , int restart_step, bool fmt_output , bool unified , const char * key_join_string , time_t sim_start , bool time_in_days , int nx , int ny , int nz) { @@ -516,12 +501,12 @@ bool ecl_sum_case_exists( const char * input_file ) { /*****************************************************************/ -double ecl_sum_get_from_sim_time( const ecl_sum_type * ecl_sum , time_t sim_time , const smspec_node_type * node) { - return ecl_sum_data_get_from_sim_time( ecl_sum->data , sim_time , node ); +double ecl_sum_get_from_sim_time( const ecl_sum_type * ecl_sum , time_t sim_time , const ecl::smspec_node * node) { + return ecl_sum_data_get_from_sim_time( ecl_sum->data , sim_time , *node ); } -double ecl_sum_get_from_sim_days( const ecl_sum_type * ecl_sum , double sim_days , const smspec_node_type * node) { - return ecl_sum_data_get_from_sim_days( ecl_sum->data , sim_days , node ); +double ecl_sum_get_from_sim_days( const ecl_sum_type * ecl_sum , double sim_days , const ecl::smspec_node * node) { + return ecl_sum_data_get_from_sim_days( ecl_sum->data , sim_days , *node ); } double ecl_sum_time2days( const ecl_sum_type * ecl_sum , time_t sim_time) { @@ -559,13 +544,13 @@ double ecl_sum_get_well_var(const ecl_sum_type * ecl_sum , int time_index , con } double ecl_sum_get_well_var_from_sim_time( const ecl_sum_type * ecl_sum , time_t sim_time , const char * well , const char * var) { - const smspec_node_type * node = ecl_smspec_get_well_var_node( ecl_sum->smspec , well , var ); - return ecl_sum_get_from_sim_time( ecl_sum , sim_time , node ); + const ecl::smspec_node& node = ecl_smspec_get_well_var_node( ecl_sum->smspec , well , var ); + return ecl_sum_get_from_sim_time( ecl_sum , sim_time , &node ); } double ecl_sum_get_well_var_from_sim_days( const ecl_sum_type * ecl_sum , double sim_days , const char * well , const char * var) { - const smspec_node_type * node = ecl_smspec_get_well_var_node( ecl_sum->smspec , well , var ); - return ecl_sum_get_from_sim_days( ecl_sum , sim_days , node ); + const ecl::smspec_node& node = ecl_smspec_get_well_var_node( ecl_sum->smspec , well , var ); + return ecl_sum_get_from_sim_days( ecl_sum , sim_days , &node ); } @@ -583,13 +568,13 @@ double ecl_sum_get_group_var(const ecl_sum_type * ecl_sum , int time_index , co double ecl_sum_get_group_var_from_sim_time( const ecl_sum_type * ecl_sum , time_t sim_time , const char * group , const char * var) { - const smspec_node_type * node = ecl_smspec_get_group_var_node( ecl_sum->smspec , group , var ); - return ecl_sum_get_from_sim_time( ecl_sum , sim_time , node ); + const ecl::smspec_node& node = ecl_smspec_get_group_var_node( ecl_sum->smspec , group , var ); + return ecl_sum_get_from_sim_time( ecl_sum , sim_time , &node ); } double ecl_sum_get_group_var_from_sim_days( const ecl_sum_type * ecl_sum , double sim_days , const char * group , const char * var) { - const smspec_node_type * node = ecl_smspec_get_group_var_node( ecl_sum->smspec , group , var ); - return ecl_sum_get_from_sim_days( ecl_sum , sim_days , node ); + const ecl::smspec_node& node = ecl_smspec_get_group_var_node( ecl_sum->smspec , group , var ); + return ecl_sum_get_from_sim_days( ecl_sum , sim_days , &node ); } @@ -605,13 +590,13 @@ double ecl_sum_get_field_var(const ecl_sum_type * ecl_sum , int time_index , con } double ecl_sum_get_field_var_from_sim_time( const ecl_sum_type * ecl_sum , time_t sim_time , const char * var) { - const smspec_node_type * node = ecl_smspec_get_field_var_node( ecl_sum->smspec , var ); - return ecl_sum_get_from_sim_time( ecl_sum , sim_time , node ); + const ecl::smspec_node& node = ecl_smspec_get_field_var_node( ecl_sum->smspec , var ); + return ecl_sum_get_from_sim_time( ecl_sum , sim_time , &node ); } double ecl_sum_get_field_var_from_sim_days( const ecl_sum_type * ecl_sum , double sim_days , const char * var) { - const smspec_node_type * node = ecl_smspec_get_field_var_node( ecl_sum->smspec , var ); - return ecl_sum_get_from_sim_days( ecl_sum , sim_days , node ); + const ecl::smspec_node& node = ecl_smspec_get_field_var_node( ecl_sum->smspec , var ); + return ecl_sum_get_from_sim_days( ecl_sum , sim_days , &node ); } @@ -641,13 +626,13 @@ double ecl_sum_get_block_var_ijk(const ecl_sum_type * ecl_sum , int time_index , } double ecl_sum_get_block_var_ijk_from_sim_time( const ecl_sum_type * ecl_sum , time_t sim_time , const char * block_var, int i , int j , int k) { - const smspec_node_type * node = ecl_smspec_get_block_var_node_ijk( ecl_sum->smspec , block_var , i ,j , k); - return ecl_sum_get_from_sim_time( ecl_sum , sim_time , node ); + const ecl::smspec_node& node = ecl_smspec_get_block_var_node_ijk( ecl_sum->smspec , block_var , i ,j , k); + return ecl_sum_get_from_sim_time( ecl_sum , sim_time , &node ); } double ecl_sum_get_block_var_ijk_from_sim_days( const ecl_sum_type * ecl_sum , double sim_days , const char * block_var, int i , int j , int k) { - const smspec_node_type * node = ecl_smspec_get_block_var_node_ijk( ecl_sum->smspec , block_var , i ,j , k); - return ecl_sum_get_from_sim_days( ecl_sum , sim_days , node ); + const ecl::smspec_node& node = ecl_smspec_get_block_var_node_ijk( ecl_sum->smspec , block_var , i ,j , k); + return ecl_sum_get_from_sim_days( ecl_sum , sim_days , &node ); } @@ -668,13 +653,13 @@ double ecl_sum_get_region_var(const ecl_sum_type * ecl_sum , int time_index , co } double ecl_sum_get_region_var_from_sim_time( const ecl_sum_type * ecl_sum , time_t sim_time , const char * var , int region_nr) { - const smspec_node_type * node = ecl_smspec_get_region_var_node( ecl_sum->smspec , var , region_nr); - return ecl_sum_get_from_sim_time( ecl_sum , sim_time , node ); + const ecl::smspec_node& node = ecl_smspec_get_region_var_node( ecl_sum->smspec , var , region_nr); + return ecl_sum_get_from_sim_time( ecl_sum , sim_time , &node ); } double ecl_sum_get_region_var_from_sim_days( const ecl_sum_type * ecl_sum , double sim_days , const char * var , int region_nr) { - const smspec_node_type * node = ecl_smspec_get_region_var_node( ecl_sum->smspec , var , region_nr); - return ecl_sum_get_from_sim_days( ecl_sum , sim_days , node ); + const ecl::smspec_node& node = ecl_smspec_get_region_var_node( ecl_sum->smspec , var , region_nr); + return ecl_sum_get_from_sim_days( ecl_sum , sim_days , &node ); } @@ -715,14 +700,9 @@ double ecl_sum_get_well_completion_var(const ecl_sum_type * ecl_sum , int time_i /*****************************************************************/ /* General variables - this means WWCT:OP_1 - i.e. composite variables*/ -const smspec_node_type * ecl_sum_get_general_var_node(const ecl_sum_type * ecl_sum , const char * lookup_kw) { - const smspec_node_type * node = ecl_smspec_get_general_var_node( ecl_sum->smspec , lookup_kw ); - if (node != NULL) - return node; - else { - util_abort("%s: summary case:%s does not contain key:%s\n",__func__ , ecl_sum_get_case( ecl_sum ) , lookup_kw ); - return NULL; - } +const ecl::smspec_node * ecl_sum_get_general_var_node(const ecl_sum_type * ecl_sum , const char * lookup_kw) { + const ecl::smspec_node& node = ecl_smspec_get_general_var_node( ecl_sum->smspec , lookup_kw ); + return &node; } int ecl_sum_get_general_var_params_index(const ecl_sum_type * ecl_sum , const char * lookup_kw) { @@ -761,30 +741,38 @@ void ecl_sum_fwrite_interp_csv_line(const ecl_sum_type * ecl_sum, time_t sim_tim double ecl_sum_get_general_var_from_sim_time( const ecl_sum_type * ecl_sum , time_t sim_time , const char * var) { - const smspec_node_type * node = ecl_sum_get_general_var_node( ecl_sum , var ); + const ecl::smspec_node * node = ecl_sum_get_general_var_node( ecl_sum , var ); return ecl_sum_get_from_sim_time( ecl_sum , sim_time , node ); } double ecl_sum_get_general_var_from_sim_days( const ecl_sum_type * ecl_sum , double sim_days , const char * var) { - const smspec_node_type * node = ecl_sum_get_general_var_node( ecl_sum , var ); - return ecl_sum_data_get_from_sim_days( ecl_sum->data , sim_days , node ); + const ecl::smspec_node * node = ecl_sum_get_general_var_node( ecl_sum , var ); + return ecl_sum_data_get_from_sim_days( ecl_sum->data , sim_days , *node ); } const char * ecl_sum_get_general_var_unit( const ecl_sum_type * ecl_sum , const char * var) { - const smspec_node_type * node = ecl_sum_get_general_var_node( ecl_sum , var ); + const ecl::smspec_node * node = ecl_sum_get_general_var_node( ecl_sum , var ); return smspec_node_get_unit( node ); } /*****************************************************************/ -ecl_sum_type * ecl_sum_alloc_resample(const ecl_sum_type * ecl_sum, const char * ecl_case, const time_t_vector_type * times) { - time_t start_time = ecl_sum_get_data_start(ecl_sum); +ecl_sum_type * ecl_sum_alloc_resample(const ecl_sum_type * ecl_sum, const char * ecl_case, const time_t_vector_type * times, bool lower_extrapolation, bool upper_extrapolation) { + /* + If lower and / or upper extrapolation is set to true it makes sure that resampling returns the first / last value of the simulation + or in the case of derivate / rate then it gets zero. if these are set to false, we jus throw exception + */ - if ( time_t_vector_get_first(times) < start_time ) + time_t start_time = ecl_sum_get_data_start(ecl_sum); + time_t end_time = ecl_sum_get_end_time(ecl_sum); + time_t input_start = time_t_vector_get_first( times ); + time_t input_end = time_t_vector_get_last( times ); + + if ( !lower_extrapolation && input_start < start_time ) return NULL; - if ( time_t_vector_get_last(times) > ecl_sum_get_end_time(ecl_sum) ) + if ( !upper_extrapolation && input_end > end_time) return NULL; if ( !time_t_vector_is_sorted(times, false) ) return NULL; @@ -792,38 +780,57 @@ ecl_sum_type * ecl_sum_alloc_resample(const ecl_sum_type * ecl_sum, const char * const int * grid_dims = ecl_smspec_get_grid_dims(ecl_sum->smspec); bool time_in_days = false; - const smspec_node_type * node = ecl_smspec_iget_node(ecl_sum->smspec, 0); - if ( util_string_equal(smspec_node_get_unit(node), "DAYS" ) ) + const ecl::smspec_node& node = ecl_smspec_iget_node_w_node_index(ecl_sum->smspec, 0); + if ( util_string_equal(smspec_node_get_unit(&node), "DAYS" ) ) time_in_days = true; - ecl_sum_type * ecl_sum_resampled = ecl_sum_alloc_writer( ecl_case , ecl_sum->fmt_case , ecl_sum->unified , ecl_sum->key_join_string , start_time , time_in_days , grid_dims[0] , grid_dims[1] , grid_dims[2] ); - - + //create elc_sum_resampled with TIME node only + ecl_sum_type * ecl_sum_resampled = ecl_sum_alloc_writer( ecl_case , ecl_sum->fmt_case , ecl_sum->unified , ecl_sum->key_join_string , input_start , time_in_days , grid_dims[0] , grid_dims[1] , grid_dims[2] ); + //add remaining nodes for (int i = 0; i < ecl_smspec_num_nodes(ecl_sum->smspec); i++) { - const smspec_node_type * node = ecl_smspec_iget_node(ecl_sum->smspec, i); - if (util_string_equal(smspec_node_get_gen_key1(node), "TIME")) + const ecl::smspec_node& node = ecl_smspec_iget_node_w_node_index(ecl_sum->smspec, i); + if (util_string_equal(smspec_node_get_gen_key1(&node), "TIME")) continue; - ecl_sum_add_smspec_node( ecl_sum_resampled, node ); + ecl_sum_add_smspec_node( ecl_sum_resampled, &node ); } /* The SMSPEC header structure has been completely initialized, it is time to start filling it up with data. + */ ecl_sum_vector_type * ecl_sum_vector = ecl_sum_vector_alloc(ecl_sum, true); double_vector_type * data = double_vector_alloc( ecl_sum_vector_get_size(ecl_sum_vector) , 0); - for (int report_step = 0; report_step < time_t_vector_size(times); report_step++) { - time_t t = time_t_vector_iget(times, report_step); - - /* Look up interpolated data in the original case. */ - ecl_sum_get_interp_vector( ecl_sum, t, ecl_sum_vector, data); + time_t input_t = time_t_vector_iget(times, report_step); + if (input_t < start_time) { + //clamping to the first value for t < start_time or if it is a rate than derivative is 0 + for (int i=1; i < ecl_smspec_num_nodes(ecl_sum->smspec); i++) { + double value = 0; + const ecl::smspec_node& node = ecl_smspec_iget_node_w_node_index(ecl_sum->smspec, i); + if (!node.is_rate()) + value = ecl_sum_iget_first_value(ecl_sum, node.get_params_index()); + double_vector_iset(data, i-1, value); + } + } else if (input_t > end_time) { + //clamping to the last value for t > end_time or if it is a rate than derivative is 0 + for (int i=1; i < ecl_smspec_num_nodes(ecl_sum->smspec); i++) { + double value = 0; + const ecl::smspec_node& node = ecl_smspec_iget_node_w_node_index(ecl_sum->smspec, i); + if (!node.is_rate()) + value = ecl_sum_iget_last_value(ecl_sum, node.get_params_index()); + double_vector_iset(data, i-1, value); + } + } else { + /* Look up interpolated data in the original case. */ + ecl_sum_get_interp_vector( ecl_sum, input_t, ecl_sum_vector, data); + } /* Add timestep corresponding to the interpolated data in the resampled case. */ - ecl_sum_tstep_type * tstep = ecl_sum_add_tstep( ecl_sum_resampled , report_step , t - start_time); + ecl_sum_tstep_type * tstep = ecl_sum_add_tstep( ecl_sum_resampled , report_step , input_t - input_start); for (int data_index = 0; data_index < ecl_sum_vector_get_size(ecl_sum_vector); data_index++) { double value = double_vector_iget(data,data_index); int params_index = data_index + 1; // The +1 shift is because the first element in the tstep is time value. @@ -844,12 +851,12 @@ double ecl_sum_iget( const ecl_sum_type * ecl_sum , int time_index , int param_i /* Simple get functions which take a general var key as input */ bool ecl_sum_var_is_rate( const ecl_sum_type * ecl_sum , const char * gen_key) { - const smspec_node_type * node = ecl_sum_get_general_var_node( ecl_sum , gen_key ); + const ecl::smspec_node * node = ecl_sum_get_general_var_node( ecl_sum , gen_key ); return smspec_node_is_rate( node ); } bool ecl_sum_var_is_total( const ecl_sum_type * ecl_sum , const char * gen_key) { - const smspec_node_type * node = ecl_sum_get_general_var_node( ecl_sum , gen_key ); + const ecl::smspec_node * node = ecl_sum_get_general_var_node( ecl_sum , gen_key ); return smspec_node_is_total( node ); } @@ -859,27 +866,27 @@ ecl_smspec_var_type ecl_sum_identify_var_type( const char * var ) { } ecl_smspec_var_type ecl_sum_get_var_type( const ecl_sum_type * ecl_sum , const char * gen_key) { - const smspec_node_type * node = ecl_sum_get_general_var_node( ecl_sum , gen_key ); + const ecl::smspec_node * node = ecl_sum_get_general_var_node( ecl_sum , gen_key ); return smspec_node_get_var_type( node ); } const char * ecl_sum_get_unit( const ecl_sum_type * ecl_sum , const char * gen_key) { - const smspec_node_type * node = ecl_sum_get_general_var_node( ecl_sum , gen_key ); + const ecl::smspec_node * node = ecl_sum_get_general_var_node( ecl_sum , gen_key ); return smspec_node_get_unit( node ); } int ecl_sum_get_num( const ecl_sum_type * ecl_sum , const char * gen_key ) { - const smspec_node_type * node = ecl_sum_get_general_var_node( ecl_sum , gen_key ); + const ecl::smspec_node * node = ecl_sum_get_general_var_node( ecl_sum , gen_key ); return smspec_node_get_num( node ); } const char * ecl_sum_get_wgname( const ecl_sum_type * ecl_sum , const char * gen_key ) { - const smspec_node_type * node = ecl_sum_get_general_var_node( ecl_sum , gen_key ); + const ecl::smspec_node * node = ecl_sum_get_general_var_node( ecl_sum , gen_key ); return smspec_node_get_wgname( node ); } const char * ecl_sum_get_keyword( const ecl_sum_type * ecl_sum , const char * gen_key ) { - const smspec_node_type * node = ecl_sum_get_general_var_node( ecl_sum , gen_key ); + const ecl::smspec_node * node = ecl_sum_get_general_var_node( ecl_sum , gen_key ); return smspec_node_get_keyword( node ); } @@ -932,7 +939,7 @@ void ecl_sum_init_double_vector(const ecl_sum_type * ecl_sum, const char * gen_k } void ecl_sum_init_double_vector_interp(const ecl_sum_type * ecl_sum, const char * gen_key, const time_t_vector_type * time_points, double * data) { - const smspec_node_type * node = ecl_smspec_get_general_var_node( ecl_sum->smspec , gen_key); + const ecl::smspec_node& node = ecl_smspec_get_general_var_node( ecl_sum->smspec , gen_key); ecl_sum_data_init_double_vector_interp(ecl_sum->data, node, time_points, data); } @@ -1305,7 +1312,7 @@ stringlist_type * ecl_sum_alloc_well_var_list( const ecl_sum_type * ecl_sum ) { void ecl_sum_resample_from_sim_time( const ecl_sum_type * ecl_sum , const time_t_vector_type * sim_time , double_vector_type * value , const char * gen_key) { - const smspec_node_type * node = ecl_smspec_get_general_var_node( ecl_sum->smspec , gen_key); + const ecl::smspec_node& node = ecl_smspec_get_general_var_node( ecl_sum->smspec , gen_key); double_vector_reset( value ); { int i; @@ -1316,7 +1323,7 @@ void ecl_sum_resample_from_sim_time( const ecl_sum_type * ecl_sum , const time_t void ecl_sum_resample_from_sim_days( const ecl_sum_type * ecl_sum , const double_vector_type * sim_days , double_vector_type * value , const char * gen_key) { - const smspec_node_type * node = ecl_smspec_get_general_var_node( ecl_sum->smspec , gen_key); + const ecl::smspec_node& node = ecl_smspec_get_general_var_node( ecl_sum->smspec , gen_key); double_vector_reset( value ); { int i; @@ -1377,7 +1384,7 @@ int ecl_sum_get_report_step_from_days( const ecl_sum_type * sum , double sim_day /*****************************************************************/ -const ecl_smspec_type * ecl_sum_get_smspec( const ecl_sum_type * ecl_sum ) { +ecl_smspec_type * ecl_sum_get_smspec( const ecl_sum_type * ecl_sum ) { return ecl_sum->smspec; } @@ -1430,8 +1437,8 @@ bool ecl_sum_report_step_compatible( const ecl_sum_type * ecl_sum1 , const ecl_s double_vector_type * ecl_sum_alloc_seconds_solution( const ecl_sum_type * ecl_sum , const char * gen_key , double cmp_value , bool rates_clamp_lower) { - const smspec_node_type * node = ecl_sum_get_general_var_node( ecl_sum , gen_key); - return ecl_sum_data_alloc_seconds_solution( ecl_sum->data , node , cmp_value , rates_clamp_lower); + const ecl::smspec_node * node = ecl_sum_get_general_var_node( ecl_sum , gen_key); + return ecl_sum_data_alloc_seconds_solution( ecl_sum->data , *node , cmp_value , rates_clamp_lower); } @@ -1467,11 +1474,11 @@ double ecl_sum_iget_last_value(const ecl_sum_type * ecl_sum, int param_index) { } double ecl_sum_get_last_value_gen_key(const ecl_sum_type * ecl_sum, const char * gen_key) { - const smspec_node_type * node = ecl_sum_get_general_var_node( ecl_sum , gen_key ); + const ecl::smspec_node * node = ecl_sum_get_general_var_node( ecl_sum , gen_key ); return ecl_sum_iget_last_value(ecl_sum, smspec_node_get_params_index(node)); } -double ecl_sum_get_last_value_node(const ecl_sum_type * ecl_sum, const smspec_node_type *node) { +double ecl_sum_get_last_value_node(const ecl_sum_type * ecl_sum, const ecl::smspec_node *node) { return ecl_sum_iget_last_value(ecl_sum, smspec_node_get_params_index(node)); } @@ -1480,10 +1487,10 @@ double ecl_sum_iget_first_value(const ecl_sum_type * ecl_sum, int param_index) { } double ecl_sum_get_first_value_gen_key(const ecl_sum_type * ecl_sum, const char * gen_key) { - const smspec_node_type * node = ecl_sum_get_general_var_node( ecl_sum , gen_key ); + const ecl::smspec_node * node = ecl_sum_get_general_var_node( ecl_sum , gen_key ); return ecl_sum_iget_first_value(ecl_sum, smspec_node_get_params_index(node)); } -double ecl_sum_get_first_value_node(const ecl_sum_type * ecl_sum, const smspec_node_type *node) { +double ecl_sum_get_first_value_node(const ecl_sum_type * ecl_sum, const ecl::smspec_node *node) { return ecl_sum_iget_first_value(ecl_sum, smspec_node_get_params_index(node)); } diff --git a/ThirdParty/Ert/lib/ecl/ecl_sum_data.cpp b/ThirdParty/Ert/lib/ecl/ecl_sum_data.cpp index b1bc8dba62..e525a6f680 100644 --- a/ThirdParty/Ert/lib/ecl/ecl_sum_data.cpp +++ b/ThirdParty/Ert/lib/ecl/ecl_sum_data.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'ecl_sum_data.c' is part of ERT - Ensemble based Reservoir Tool. @@ -458,16 +458,24 @@ bool ecl_sum_data_check_sim_days( const ecl_sum_data_type * data , double sim_da sequence has no holes. */ +static void fprintf_date_utc(time_t t , FILE * stream) { + int mday,year,month; + + util_set_datetime_values_utc(t , NULL , NULL , NULL , &mday , &month , &year); + fprintf(stream , "%02d/%02d/%4d", mday,month,year); +} + + static int ecl_sum_data_get_index_from_sim_time( const ecl_sum_data_type * data , time_t sim_time) { if (!ecl_sum_data_check_sim_time(data, sim_time)) { time_t start_time = ecl_sum_data_get_data_start(data); time_t end_time = ecl_sum_data_get_sim_end(data); - fprintf(stderr , "Simulation start: "); util_fprintf_date_utc( ecl_smspec_get_start_time( data->smspec ) , stderr ); - fprintf(stderr , "Data start......: "); util_fprintf_date_utc( start_time , stderr ); - fprintf(stderr , "Simulation end .: "); util_fprintf_date_utc( end_time , stderr ); - fprintf(stderr , "Requested date .: "); util_fprintf_date_utc( sim_time , stderr ); + fprintf(stderr , "Simulation start: "); fprintf_date_utc( ecl_smspec_get_start_time( data->smspec ) , stderr ); + fprintf(stderr , "Data start......: "); fprintf_date_utc( start_time , stderr ); + fprintf(stderr , "Simulation end .: "); fprintf_date_utc( end_time , stderr ); + fprintf(stderr , "Requested date .: "); fprintf_date_utc( sim_time , stderr ); util_abort("%s: invalid time_t instance:%d interval: [%d,%d]\n",__func__, sim_time , start_time, end_time); } @@ -569,9 +577,9 @@ void ecl_sum_data_init_interp_from_sim_days( const ecl_sum_data_type * data , do } -double_vector_type * ecl_sum_data_alloc_seconds_solution(const ecl_sum_data_type * data, const smspec_node_type * node, double cmp_value, bool rates_clamp_lower) { +double_vector_type * ecl_sum_data_alloc_seconds_solution(const ecl_sum_data_type * data, const ecl::smspec_node& node, double cmp_value, bool rates_clamp_lower) { double_vector_type * solution = double_vector_alloc(0, 0); - const int param_index = smspec_node_get_params_index(node); + const int param_index = smspec_node_get_params_index(&node); const int size = ecl_sum_data_get_length(data); if (size <= 1) @@ -593,7 +601,7 @@ double_vector_type * ecl_sum_data_alloc_seconds_solution(const ecl_sum_data_type double prev_time = ecl_sum_data_iget_sim_seconds(data, prev_index); double time = ecl_sum_data_iget_sim_seconds(data, index); - if (smspec_node_is_rate(node)) { + if (smspec_node_is_rate(&node)) { double_vector_append(solution, rates_clamp_lower ? prev_time + 1 : time); } else { double slope = (value - prev_value) / (time - prev_time); @@ -811,8 +819,8 @@ double ecl_sum_data_iget( const ecl_sum_data_type * data , int time_index , int if (params_map[params_index] >= 0) return file_data->iget( time_index - index_node.offset, params_map[params_index] ); else { - const smspec_node_type * smspec_node = ecl_smspec_iget_node(data->smspec, params_index); - return smspec_node_get_default(smspec_node); + const ecl::smspec_node& smspec_node = ecl_smspec_iget_node_w_params_index(data->smspec, params_index); + return smspec_node.get_default(); } } @@ -905,9 +913,9 @@ void ecl_sum_data_get_interp_vector( const ecl_sum_data_type * data , time_t sim } } -double ecl_sum_data_get_from_sim_time( const ecl_sum_data_type * data , time_t sim_time , const smspec_node_type * smspec_node) { - int params_index = smspec_node_get_params_index( smspec_node ); - if (smspec_node_is_rate( smspec_node )) { +double ecl_sum_data_get_from_sim_time( const ecl_sum_data_type * data , time_t sim_time , const ecl::smspec_node& smspec_node) { + int params_index = smspec_node_get_params_index( &smspec_node ); + if (smspec_node_is_rate( &smspec_node )) { /* In general the mapping from sim_time to index is based on half open intervals, which are closed in the upper end: @@ -986,7 +994,7 @@ double ecl_sum_data_time2days( const ecl_sum_data_type * data , time_t sim_time) return util_difftime_days( start_time , sim_time ); } -double ecl_sum_data_get_from_sim_days( const ecl_sum_data_type * data , double sim_days , const smspec_node_type * smspec_node) { +double ecl_sum_data_get_from_sim_days( const ecl_sum_data_type * data , double sim_days , const ecl::smspec_node& smspec_node) { time_t sim_time = ecl_smspec_get_start_time( data->smspec ); util_inplace_forward_days_utc( &sim_time , sim_days ); return ecl_sum_data_get_from_sim_time( data , sim_time , smspec_node ); @@ -1076,22 +1084,18 @@ static void ecl_sum_data_init_double_vector__(const ecl_sum_data_type * data, in const auto& params_map = index_node.params_map; int params_index = params_map[main_params_index]; - if (report_only) { - const smspec_node_type * smspec_node = ecl_smspec_iget_node(data->smspec, main_params_index); - double default_value = smspec_node_get_default(smspec_node); + const ecl::smspec_node& smspec_node = ecl_smspec_iget_node_w_params_index(data->smspec, main_params_index); + double default_value = smspec_node.get_default(); offset += data_file->get_data_report(params_index, index_node.length, &output_data[offset], default_value); } else { if (params_index >= 0) data_file->get_data(params_index, index_node.length, &output_data[offset]); else { - const smspec_node_type * smspec_node = ecl_smspec_iget_node(data->smspec, main_params_index); - if (smspec_node) - { - for (int i=0; i < index_node.length; i++) - output_data[offset + i] = smspec_node_get_default(smspec_node); - } + const ecl::smspec_node& smspec_node = ecl_smspec_iget_node_w_params_index(data->smspec, main_params_index); + for (int i=0; i < index_node.length; i++) + output_data[offset + i] = smspec_node.get_default(); } offset += index_node.length; } @@ -1118,6 +1122,9 @@ double_vector_type * ecl_sum_data_alloc_data_vector( const ecl_sum_data_type * d else output_data.resize( ecl_sum_data_get_length(data) ); + if (params_index >= ecl_smspec_get_params_size(data->smspec)) + throw std::out_of_range("Out of range"); + ecl_sum_data_init_double_vector__(data, params_index, output_data.data(), report_only); double_vector_type * data_vector = double_vector_alloc(output_data.size(), 0); { @@ -1129,11 +1136,11 @@ double_vector_type * ecl_sum_data_alloc_data_vector( const ecl_sum_data_type * d void ecl_sum_data_init_double_vector_interp(const ecl_sum_data_type * data, - const smspec_node_type * smspec_node, + const ecl::smspec_node& smspec_node, const time_t_vector_type * time_points, double * output_data) { - bool is_rate = smspec_node_is_rate(smspec_node); - int params_index = smspec_node_get_params_index(smspec_node); + bool is_rate = smspec_node_is_rate(&smspec_node); + int params_index = smspec_node_get_params_index(&smspec_node); time_t start_time = ecl_sum_data_get_data_start(data); time_t end_time = ecl_sum_data_get_sim_end(data); double start_value = 0; diff --git a/ThirdParty/Ert/lib/ecl/ecl_sum_file_data.cpp b/ThirdParty/Ert/lib/ecl/ecl_sum_file_data.cpp index b0367e2ec5..19c6fa28cd 100644 --- a/ThirdParty/Ert/lib/ecl/ecl_sum_file_data.cpp +++ b/ThirdParty/Ert/lib/ecl/ecl_sum_file_data.cpp @@ -471,7 +471,8 @@ void ecl_sum_file_data::fwrite_report( int report_step , fortio_type * fortio) c auto range = this->report_range( report_step ); for (int index = range.first; index <= range.second; index++) { const ecl_sum_tstep_type * tstep = iget_ministep( index ); - ecl_sum_tstep_fwrite( tstep , ecl_smspec_get_index_map( ecl_smspec ) , fortio ); + //ecl_sum_tstep_fwrite( tstep , ecl_smspec_get_index_map( ecl_smspec ) , fortio ); + ecl_sum_tstep_fwrite( tstep , ecl_smspec_get_index_map(ecl_smspec) , ecl_smspec_num_nodes(ecl_smspec), fortio ); } } } @@ -553,7 +554,7 @@ bool ecl_sum_file_data::check_file( ecl_file_type * ecl_file ) { calling routine will read the unified summary file partly. */ -void ecl_sum_file_data::add_ecl_file(int report_step, const ecl_file_view_type * summary_view, const ecl_smspec_type * smspec) { +void ecl_sum_file_data::add_ecl_file(int report_step, const ecl_file_view_type * summary_view) { int num_ministep = ecl_file_view_get_num_named_kw( summary_view , PARAMS_KW); if (num_ministep > 0) { @@ -569,7 +570,7 @@ void ecl_sum_file_data::add_ecl_file(int report_step, const ecl_file_view_type * ministep_nr , params_kw , ecl_file_view_get_src_file( summary_view ), - smspec ); + this->ecl_smspec ); if (tstep) append_tstep( tstep ); @@ -600,7 +601,7 @@ bool ecl_sum_file_data::fread(const stringlist_type * filelist, bool lazy_load, { ecl_file_type * ecl_file = ecl_file_open( data_file , 0); if (ecl_file && check_file( ecl_file )) { - add_ecl_file( report_step , ecl_file_get_global_view( ecl_file ) , ecl_smspec); + this->add_ecl_file( report_step , ecl_file_get_global_view( ecl_file )); ecl_file_close( ecl_file ); } } @@ -632,7 +633,7 @@ bool ecl_sum_file_data::fread(const stringlist_type * filelist, bool lazy_load, */ ecl_file_view_type * summary_view = ecl_file_get_summary_view(ecl_file , block_index); if (summary_view) { - add_ecl_file(block_index + first_report_step , summary_view , ecl_smspec); + this->add_ecl_file(block_index + first_report_step , summary_view); block_index++; } else break; } diff --git a/ThirdParty/Ert/lib/ecl/ecl_sum_index.cpp b/ThirdParty/Ert/lib/ecl/ecl_sum_index.cpp index 3211baac34..ff3694f32f 100644 --- a/ThirdParty/Ert/lib/ecl/ecl_sum_index.cpp +++ b/ThirdParty/Ert/lib/ecl/ecl_sum_index.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'ecl_sum_index.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/ecl_sum_tstep.cpp b/ThirdParty/Ert/lib/ecl/ecl_sum_tstep.cpp index 380b7e5732..6e565e7e16 100644 --- a/ThirdParty/Ert/lib/ecl/ecl_sum_tstep.cpp +++ b/ThirdParty/Ert/lib/ecl/ecl_sum_tstep.cpp @@ -1,5 +1,5 @@ - /* - Copyright (C) 2012 Statoil ASA, Norway. +/* + Copyright (C) 2012 Equinor ASA, Norway. The file 'ecl_sum_tstep.c' is part of ERT - Ensemble based Reservoir Tool. @@ -19,6 +19,8 @@ #include #include +#include + #include #include @@ -59,12 +61,11 @@ Header direction: ecl_smspec DAYS WWCT:OP_3 FOPT BPR:15,10,25 struct ecl_sum_tstep_struct { UTIL_TYPE_ID_DECLARATION; - float * data; /* A memcpy copy of the PARAMS vector in ecl_kw instance - the raw data. */ + std::vector data; /* A memcpy copy of the PARAMS vector in ecl_kw instance - the raw data. */ time_t sim_time; /* The true time (i.e. 20.th of october 2010) of corresponding to this timestep. */ int ministep; /* The ECLIPSE internal time-step number; one ministep per numerical timestep. */ int report_step; /* The report step this time-step is part of - in general there can be many timestep for each report step. */ double sim_seconds; /* Accumulated simulation time up to this ministep. */ - int data_size; /* Number of elements in data - only used for checking indices. */ int internal_index; /* Used for lookups of the next / previous ministep based on an existing ministep. */ const ecl_smspec_type * smspec; /* The smespec header information for this tstep - must be compatible. */ }; @@ -72,11 +73,13 @@ struct ecl_sum_tstep_struct { ecl_sum_tstep_type * ecl_sum_tstep_alloc_remap_copy( const ecl_sum_tstep_type * src , const ecl_smspec_type * new_smspec, float default_value , const int * params_map) { int params_size = ecl_smspec_get_params_size( new_smspec ); - ecl_sum_tstep_type * target = (ecl_sum_tstep_type*)util_alloc_copy(src , sizeof * src ); + ecl_sum_tstep_type * target = new ecl_sum_tstep_type(); + UTIL_TYPE_ID_INIT( target , ECL_SUM_TSTEP_ID); + target->report_step = src->report_step; + target->ministep = src->ministep; target->smspec = new_smspec; - target->data = (float*)util_malloc( params_size * sizeof * target->data ); - target->data_size = params_size; + target->data.resize(params_size); for (int i=0; i < params_size; i++) { if (params_map[i] >= 0) @@ -89,20 +92,23 @@ ecl_sum_tstep_type * ecl_sum_tstep_alloc_remap_copy( const ecl_sum_tstep_type * } ecl_sum_tstep_type * ecl_sum_tstep_alloc_copy( const ecl_sum_tstep_type * src ) { - ecl_sum_tstep_type * target = (ecl_sum_tstep_type*)util_alloc_copy(src , sizeof * src ); - target->data = (float*)util_alloc_copy( src->data , src->data_size * sizeof * src->data ); + ecl_sum_tstep_type * target = new ecl_sum_tstep_type(); + UTIL_TYPE_ID_INIT( target , ECL_SUM_TSTEP_ID); + target->smspec = src->smspec; + target->report_step = src->report_step; + target->ministep = src->ministep; + target->data = src->data; return target; } static ecl_sum_tstep_type * ecl_sum_tstep_alloc( int report_step , int ministep_nr , const ecl_smspec_type * smspec) { - ecl_sum_tstep_type * tstep = (ecl_sum_tstep_type*)util_malloc( sizeof * tstep ); + ecl_sum_tstep_type * tstep = new ecl_sum_tstep_type(); UTIL_TYPE_ID_INIT( tstep , ECL_SUM_TSTEP_ID); tstep->smspec = smspec; tstep->report_step = report_step; tstep->ministep = ministep_nr; - tstep->data_size = ecl_smspec_get_params_size( smspec ); - tstep->data = (float*)util_calloc( tstep->data_size , sizeof * tstep->data ); + tstep->data.resize( ecl_smspec_get_params_size( smspec ) ); return tstep; } @@ -112,8 +118,7 @@ UTIL_SAFE_CAST_FUNCTION_CONST( ecl_sum_tstep , ECL_SUM_TSTEP_ID) void ecl_sum_tstep_free( ecl_sum_tstep_type * ministep ) { - free( ministep->data ); - free( ministep ); + delete ministep; } @@ -201,7 +206,7 @@ ecl_sum_tstep_type * ecl_sum_tstep_alloc_from_file( int report_step , if (data_size == ecl_smspec_get_params_size( smspec )) { ecl_sum_tstep_type * ministep = ecl_sum_tstep_alloc( report_step , ministep_nr , smspec); - ecl_kw_get_memcpy_data( params_kw , ministep->data ); + ecl_kw_get_memcpy_data( params_kw , ministep->data.data() ); ecl_sum_tstep_set_time_info( ministep , smspec ); return ministep; } else { @@ -211,7 +216,11 @@ ecl_sum_tstep_type * ecl_sum_tstep_alloc_from_file( int report_step , ecl_smspec_load_restart() function and the restart case discarded. */ - fprintf(stderr , "** Warning size mismatch between timestep loaded from:%s and header:%s - timestep discarded.\n" , src_file , ecl_smspec_get_header_file( smspec )); + fprintf(stderr , "** Warning size mismatch between timestep loaded from:%s(%d) and header:%s(%d) - timestep discarded.\n" , + src_file , + data_size, + ecl_smspec_get_header_file( smspec ), + ecl_smspec_get_params_size( smspec )); return NULL; } } @@ -223,8 +232,7 @@ ecl_sum_tstep_type * ecl_sum_tstep_alloc_from_file( int report_step , ecl_sum_tstep_type * ecl_sum_tstep_alloc_new( int report_step , int ministep , float sim_seconds , const ecl_smspec_type * smspec ) { ecl_sum_tstep_type * tstep = ecl_sum_tstep_alloc( report_step , ministep , smspec ); - const float_vector_type * default_data = ecl_smspec_get_params_default( smspec ); - float_vector_memcpy_data( tstep->data , default_data ); + tstep->data = ecl_smspec_get_params_default( smspec ); ecl_sum_tstep_set_time_info_from_seconds( tstep , ecl_smspec_get_start_time( smspec ) , sim_seconds ); ecl_sum_tstep_iset( tstep , ecl_smspec_get_time_index( smspec ) , sim_seconds / ecl_smspec_get_time_seconds( smspec ) ); @@ -235,10 +243,10 @@ ecl_sum_tstep_type * ecl_sum_tstep_alloc_new( int report_step , int ministep , f double ecl_sum_tstep_iget(const ecl_sum_tstep_type * ministep , int index) { - if ((index >= 0) && (index < ministep->data_size)) + if ((index >= 0) && (index < (int)ministep->data.size())) return ministep->data[index]; else { - util_abort("%s: param index:%d invalid: Valid range: [0,%d) \n",__func__ , index , ministep->data_size); + util_abort("%s: param index:%d invalid: Valid range: [0,%d) \n",__func__ , index , ministep->data.size()); return -1; } } @@ -269,7 +277,7 @@ int ecl_sum_tstep_get_ministep(const ecl_sum_tstep_type * ministep) { /*****************************************************************/ -void ecl_sum_tstep_fwrite( const ecl_sum_tstep_type * ministep , const int_vector_type * index_map , fortio_type * fortio) { +void ecl_sum_tstep_fwrite( const ecl_sum_tstep_type * ministep , const int * index_map , int index_map_size, fortio_type * fortio) { { ecl_kw_type * ministep_kw = ecl_kw_alloc( MINISTEP_KW , 1 , ECL_INT ); ecl_kw_iset_int( ministep_kw , 0 , ministep->ministep ); @@ -278,16 +286,15 @@ void ecl_sum_tstep_fwrite( const ecl_sum_tstep_type * ministep , const int_vecto } { - int compact_size = int_vector_size( index_map ); + int compact_size = index_map_size; ecl_kw_type * params_kw = ecl_kw_alloc( PARAMS_KW , compact_size , ECL_FLOAT ); - const int * index = int_vector_get_ptr( index_map ); float * data = (float*)ecl_kw_get_ptr( params_kw ); { int i; for (i=0; i < compact_size; i++) - data[i] = ministep->data[ index[i] ]; + data[i] = ministep->data[ index_map[i] ]; } ecl_kw_fwrite( params_kw , fortio ); ecl_kw_free( params_kw ); @@ -298,10 +305,10 @@ void ecl_sum_tstep_fwrite( const ecl_sum_tstep_type * ministep , const int_vecto /*****************************************************************/ void ecl_sum_tstep_iset( ecl_sum_tstep_type * tstep , int index , float value) { - if ((index < tstep->data_size) && (index >= 0)) + if ((index < static_cast(tstep->data.size())) && (index >= 0) ) tstep->data[index] = value; else - util_abort("%s: index:%d invalid. Valid range: [0,%d) \n",__func__ ,index , tstep->data_size); + util_abort("%s: index:%d invalid. Valid range: [0,%d) \n",__func__ ,index , tstep->data.size()); } void ecl_sum_tstep_iscale(ecl_sum_tstep_type * tstep, int index, float scalar) { @@ -312,24 +319,24 @@ void ecl_sum_tstep_ishift(ecl_sum_tstep_type * tstep, int index, float addend) { ecl_sum_tstep_iset(tstep, index, ecl_sum_tstep_iget(tstep, index) + addend); } -void ecl_sum_tstep_set_from_node( ecl_sum_tstep_type * tstep , const smspec_node_type * smspec_node , float value) { - int data_index = smspec_node_get_params_index( smspec_node ); +void ecl_sum_tstep_set_from_node( ecl_sum_tstep_type * tstep , const ecl::smspec_node& smspec_node , float value) { + int data_index = smspec_node_get_params_index( &smspec_node ); ecl_sum_tstep_iset( tstep , data_index , value); } -double ecl_sum_tstep_get_from_node( const ecl_sum_tstep_type * tstep , const smspec_node_type * smspec_node) { - int data_index = smspec_node_get_params_index( smspec_node ); +double ecl_sum_tstep_get_from_node( const ecl_sum_tstep_type * tstep , const ecl::smspec_node& smspec_node) { + int data_index = smspec_node_get_params_index( &smspec_node ); return ecl_sum_tstep_iget( tstep , data_index); } void ecl_sum_tstep_set_from_key( ecl_sum_tstep_type * tstep , const char * gen_key , float value) { - const smspec_node_type * smspec_node = ecl_smspec_get_general_var_node( tstep->smspec , gen_key ); + const ecl::smspec_node& smspec_node = ecl_smspec_get_general_var_node( tstep->smspec , gen_key ); ecl_sum_tstep_set_from_node( tstep , smspec_node , value); } double ecl_sum_tstep_get_from_key(const ecl_sum_tstep_type * tstep , const char * gen_key) { - const smspec_node_type * smspec_node = ecl_smspec_get_general_var_node( tstep->smspec , gen_key ); + const ecl::smspec_node& smspec_node = ecl_smspec_get_general_var_node( tstep->smspec , gen_key ); return ecl_sum_tstep_get_from_node(tstep , smspec_node ); } diff --git a/ThirdParty/Ert/lib/ecl/ecl_sum_vector.cpp b/ThirdParty/Ert/lib/ecl/ecl_sum_vector.cpp index 8bcfebfe4a..ee7d9e1d64 100644 --- a/ThirdParty/Ert/lib/ecl/ecl_sum_vector.cpp +++ b/ThirdParty/Ert/lib/ecl/ecl_sum_vector.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2014 Statoil ASA, Norway. + Copyright (C) 2014 Equinor ASA, Norway. The file 'ecl_sum_vector.c' is part of ERT - Ensemble based Reservoir Tool. @@ -16,6 +16,10 @@ for more details. */ #include + +#include +#include + #include #include #include @@ -23,68 +27,60 @@ #include #include #include -#include -#include #define ECL_SUM_VECTOR_TYPE_ID 8768778 struct ecl_sum_vector_struct { UTIL_TYPE_ID_DECLARATION; - int_vector_type * node_index_list; - bool_vector_type * is_rate_list; - stringlist_type * key_list; + std::vector node_index_list; + std::vector is_rate_list; + std::vector key_list; const ecl_sum_type * ecl_sum; }; void ecl_sum_vector_free( ecl_sum_vector_type * ecl_sum_vector ){ - int_vector_free(ecl_sum_vector->node_index_list); - bool_vector_free(ecl_sum_vector->is_rate_list); - stringlist_free(ecl_sum_vector->key_list); - free(ecl_sum_vector); + delete ecl_sum_vector; } UTIL_IS_INSTANCE_FUNCTION( ecl_sum_vector , ECL_SUM_VECTOR_TYPE_ID ) -static void ecl_sum_vector_add_node(ecl_sum_vector_type * vector, const smspec_node_type * node, const char * key ) { +static void ecl_sum_vector_add_node(ecl_sum_vector_type * vector, const ecl::smspec_node * node, const char * key ) { int params_index = smspec_node_get_params_index( node ); bool is_rate_key = smspec_node_is_rate( node); - int_vector_append(vector->node_index_list, params_index); - bool_vector_append(vector->is_rate_list, is_rate_key); - stringlist_append_copy( vector->key_list, key ); + vector->node_index_list.push_back(params_index); + vector->is_rate_list.push_back(is_rate_key); + vector->key_list.push_back(key); } ecl_sum_vector_type * ecl_sum_vector_alloc(const ecl_sum_type * ecl_sum, bool add_keywords) { - ecl_sum_vector_type * ecl_sum_vector = (ecl_sum_vector_type*)util_malloc( sizeof * ecl_sum_vector ); + ecl_sum_vector_type * ecl_sum_vector = new ecl_sum_vector_type(); UTIL_TYPE_ID_INIT( ecl_sum_vector , ECL_SUM_VECTOR_TYPE_ID); ecl_sum_vector->ecl_sum = ecl_sum; - ecl_sum_vector->node_index_list = int_vector_alloc(0,0); - ecl_sum_vector->is_rate_list = bool_vector_alloc(0,false); - ecl_sum_vector->key_list = stringlist_alloc_new( ); if (add_keywords) { const ecl_smspec_type * smspec = ecl_sum_get_smspec(ecl_sum); for (int i=0; i < ecl_smspec_num_nodes(smspec); i++) { - const smspec_node_type * node = ecl_smspec_iget_node( smspec , i ); - const char * key = smspec_node_get_gen_key1(node); + const ecl::smspec_node& node = ecl_smspec_iget_node_w_node_index( smspec , i ); + const char * key = smspec_node_get_gen_key1(&node); /* The TIME keyword is special case handled to not be included; that is to match the same special casing in the key matching function. */ if (!util_string_equal(key, "TIME")) - ecl_sum_vector_add_node( ecl_sum_vector, node, key); + ecl_sum_vector_add_node( ecl_sum_vector, &node, key); } } return ecl_sum_vector; } static void ecl_sum_vector_add_invalid_key(ecl_sum_vector_type * vector, const char * key) { - int_vector_append(vector->node_index_list, -1); - bool_vector_append(vector->is_rate_list, false); - stringlist_append_copy(vector->key_list, key); + vector->node_index_list.push_back(-1); + vector->is_rate_list.push_back(false); + vector->key_list.push_back(key); } @@ -103,8 +99,8 @@ static void ecl_sum_vector_add_invalid_key(ecl_sum_vector_type * vector, const c ecl_sum_vector_type * ecl_sum_vector_alloc_layout_copy(const ecl_sum_vector_type * src_vector, const ecl_sum_type * ecl_sum) { ecl_sum_vector_type * new_vector = ecl_sum_vector_alloc(ecl_sum, false); - for (int i=0; i < stringlist_get_size(src_vector->key_list); i++) { - const char * key = stringlist_iget(src_vector->key_list, i); + for (size_t i=0; i < src_vector->key_list.size(); i++) { + const char * key = src_vector->key_list[i].c_str(); if (ecl_sum_has_general_var(ecl_sum, key)) ecl_sum_vector_add_key(new_vector, key); else @@ -117,7 +113,7 @@ ecl_sum_vector_type * ecl_sum_vector_alloc_layout_copy(const ecl_sum_vector_type bool ecl_sum_vector_add_key( ecl_sum_vector_type * ecl_sum_vector, const char * key){ if (ecl_sum_has_general_var( ecl_sum_vector->ecl_sum , key)) { - const smspec_node_type * node = ecl_sum_get_general_var_node( ecl_sum_vector->ecl_sum , key ); + const ecl::smspec_node * node = ecl_sum_get_general_var_node( ecl_sum_vector->ecl_sum , key ); ecl_sum_vector_add_node(ecl_sum_vector, node, key); return true; } else @@ -131,29 +127,29 @@ void ecl_sum_vector_add_keys( ecl_sum_vector_type * ecl_sum_vector, const char * int i; for(i = 0; i < num_keywords ;i++){ const char * key = stringlist_iget(keylist, i); - const smspec_node_type * node = ecl_sum_get_general_var_node( ecl_sum_vector->ecl_sum , key ); + const ecl::smspec_node * node = ecl_sum_get_general_var_node( ecl_sum_vector->ecl_sum , key ); ecl_sum_vector_add_node(ecl_sum_vector, node, key); } stringlist_free(keylist); } int ecl_sum_vector_get_size(const ecl_sum_vector_type * ecl_sum_vector){ - return int_vector_size(ecl_sum_vector->node_index_list); + return ecl_sum_vector->node_index_list.size(); } bool ecl_sum_vector_iget_is_rate(const ecl_sum_vector_type * ecl_sum_vector, int index){ - return bool_vector_iget(ecl_sum_vector->is_rate_list, index); + return ecl_sum_vector->is_rate_list[index]; } bool ecl_sum_vector_iget_valid(const ecl_sum_vector_type * ecl_sum_vector, int index) { - return (int_vector_iget(ecl_sum_vector->node_index_list, index) >= 0); + return (ecl_sum_vector->node_index_list[index] >= 0); } int ecl_sum_vector_iget_param_index(const ecl_sum_vector_type * ecl_sum_vector, int index){ - return int_vector_iget(ecl_sum_vector->node_index_list, index); + return ecl_sum_vector->node_index_list[index]; } const char* ecl_sum_vector_iget_key(const ecl_sum_vector_type * ecl_sum_vector, int index){ - return stringlist_iget( ecl_sum_vector->key_list , index); + return ecl_sum_vector->key_list[index].c_str(); } diff --git a/ThirdParty/Ert/lib/ecl/ecl_type.cpp b/ThirdParty/Ert/lib/ecl/ecl_type.cpp index da180467d9..6e0f6dca7c 100644 --- a/ThirdParty/Ert/lib/ecl/ecl_type.cpp +++ b/ThirdParty/Ert/lib/ecl/ecl_type.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2017 Statoil ASA, Norway. + Copyright (C) 2017 Equinor ASA, Norway. The file 'ecl_type.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/ecl_unsmry_loader.cpp b/ThirdParty/Ert/lib/ecl/ecl_unsmry_loader.cpp index bd9eb1edde..e30b038d89 100644 --- a/ThirdParty/Ert/lib/ecl/ecl_unsmry_loader.cpp +++ b/ThirdParty/Ert/lib/ecl/ecl_unsmry_loader.cpp @@ -53,7 +53,7 @@ int unsmry_loader::length() const { std::vector unsmry_loader::get_vector(int pos) const { if (pos >= size) - throw std::invalid_argument("unsmry_loader::get_vector: argument 'pos' mst be less than size of PARAMS."); + throw std::out_of_range("unsmry_loader::get_vector pos: " + std::to_string(pos) + " PARAMS_SIZE: " + std::to_string(size)); std::vector data(this->length()); int_vector_type * index_map = int_vector_alloc( 1 , pos); diff --git a/ThirdParty/Ert/lib/ecl/ecl_util.cpp b/ThirdParty/Ert/lib/ecl/ecl_util.cpp index fd479ca131..f0ddca45dd 100644 --- a/ThirdParty/Ert/lib/ecl/ecl_util.cpp +++ b/ThirdParty/Ert/lib/ecl/ecl_util.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'ecl_util.c' is part of ERT - Ensemble based Reservoir Tool. @@ -1290,6 +1290,8 @@ static int ecl_util_get_num_slave_cpu__(basic_parser_type* parser, FILE* stream, const char * first_item = stringlist_iget(tokens, 0); if (first_item[0] == '/') { + stringlist_free(tokens); + free(buffer); break; } else{ diff --git a/ThirdParty/Ert/lib/ecl/fault_block.cpp b/ThirdParty/Ert/lib/ecl/fault_block.cpp index 8ea051204b..11a3452500 100644 --- a/ThirdParty/Ert/lib/ecl/fault_block.cpp +++ b/ThirdParty/Ert/lib/ecl/fault_block.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2014 Statoil ASA, Norway. + Copyright (C) 2014 Equinor ASA, Norway. The file 'fault_block.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/fault_block_layer.cpp b/ThirdParty/Ert/lib/ecl/fault_block_layer.cpp index c802705d36..3565a02210 100644 --- a/ThirdParty/Ert/lib/ecl/fault_block_layer.cpp +++ b/ThirdParty/Ert/lib/ecl/fault_block_layer.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2014 Statoil ASA, Norway. + Copyright (C) 2014 Equinor ASA, Norway. The file 'fault_block_layer.c' is part of ERT - Ensemble based Reservoir Tool. @@ -67,6 +67,8 @@ fault_block_type * fault_block_layer_add_block( fault_block_layer_type * layer , fault_block_type * block = fault_block_alloc( layer , block_id ); int storage_index = vector_get_size( layer->blocks ); + if (block_id >= int_vector_size(layer->block_map)) + int_vector_resize(layer->block_map, block_id+1, -1); int_vector_iset( layer->block_map , block_id , storage_index ); vector_append_owned_ref( layer->blocks , block , fault_block_free__ ); diff --git a/ThirdParty/Ert/lib/ecl/fortio.c b/ThirdParty/Ert/lib/ecl/fortio.c index ec096364d0..e67c4072cc 100644 --- a/ThirdParty/Ert/lib/ecl/fortio.c +++ b/ThirdParty/Ert/lib/ecl/fortio.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'fortio.c' is part of ERT - Ensemble based Reservoir Tool. @@ -30,8 +30,6 @@ #define FORTIO_ID 345116 -extern int errno; - /** The fortio struct is implemented to handle fortran io. The problem is that when a Fortran program writes unformatted data to file in a diff --git a/ThirdParty/Ert/lib/ecl/grid_dims.cpp b/ThirdParty/Ert/lib/ecl/grid_dims.cpp index 7a243f2878..ab5d327403 100644 --- a/ThirdParty/Ert/lib/ecl/grid_dims.cpp +++ b/ThirdParty/Ert/lib/ecl/grid_dims.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'grid_dims.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/layer.cpp b/ThirdParty/Ert/lib/ecl/layer.cpp index 07fe65f50e..3cbcbf5073 100644 --- a/ThirdParty/Ert/lib/ecl/layer.cpp +++ b/ThirdParty/Ert/lib/ecl/layer.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2014 Statoil ASA, Norway. + Copyright (C) 2014 Equinor ASA, Norway. The file 'layer.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/nnc_info.cpp b/ThirdParty/Ert/lib/ecl/nnc_info.cpp index d520a985ae..2667303b70 100644 --- a/ThirdParty/Ert/lib/ecl/nnc_info.cpp +++ b/ThirdParty/Ert/lib/ecl/nnc_info.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'nnc_info.c' is part of ERT - Ensemble based Reservoir Tool. @@ -18,9 +18,14 @@ #include +#include +#include +#include + #include #include #include +#include #include #include @@ -127,6 +132,8 @@ nnc_vector_type * nnc_info_get_self_vector( const nnc_info_type * nnc_info ) { static void nnc_info_add_vector( nnc_info_type * nnc_info , nnc_vector_type * nnc_vector) { vector_append_owned_ref( nnc_info->lgr_list , nnc_vector , nnc_vector_free__ ); + if (nnc_vector_get_lgr_nr( nnc_vector ) >= int_vector_size( nnc_info->lgr_index_map ) ) + int_vector_resize( nnc_info->lgr_index_map , nnc_vector_get_lgr_nr( nnc_vector)+1, -1); int_vector_iset( nnc_info->lgr_index_map , nnc_vector_get_lgr_nr( nnc_vector ) , vector_get_size( nnc_info->lgr_list ) - 1 ); } @@ -149,27 +156,28 @@ void nnc_info_add_nnc(nnc_info_type * nnc_info, int lgr_nr, int global_cell_numb } } +bool nnc_info_has_grid_index_list( const nnc_info_type * nnc_info, int lgr_nr ) { + return (nnc_info_get_vector( nnc_info , lgr_nr ) != NULL); +} -const int_vector_type * nnc_info_get_grid_index_list(const nnc_info_type * nnc_info, int lgr_nr) { +const std::vector& nnc_info_get_grid_index_list(const nnc_info_type * nnc_info, int lgr_nr) { nnc_vector_type * nnc_vector = nnc_info_get_vector( nnc_info , lgr_nr ); - if (nnc_vector) - return nnc_vector_get_grid_index_list( nnc_vector ); - else - return NULL; + if (!nnc_vector) + throw std::invalid_argument(std::string(__func__)); + return nnc_vector_get_grid_index_list( nnc_vector ); } -const int_vector_type * nnc_info_iget_grid_index_list(const nnc_info_type * nnc_info, int lgr_index) { +const std::vector& nnc_info_iget_grid_index_list(const nnc_info_type * nnc_info, int lgr_index) { nnc_vector_type * nnc_vector = nnc_info_iget_vector( nnc_info , lgr_index ); - if (nnc_vector) - return nnc_vector_get_grid_index_list( nnc_vector ); - else - return NULL; + if (!nnc_vector) + throw std::invalid_argument(std::string(__func__)); + return nnc_vector_get_grid_index_list( nnc_vector ); } -const int_vector_type * nnc_info_get_self_grid_index_list(const nnc_info_type * nnc_info) { +const std::vector& nnc_info_get_self_grid_index_list(const nnc_info_type * nnc_info) { return nnc_info_get_grid_index_list( nnc_info , nnc_info->lgr_nr ); } @@ -205,8 +213,8 @@ void nnc_info_fprintf(const nnc_info_type * nnc_info , FILE * stream) { if (lgr_index >= 0) { printf(" %02d -> %02d => ",lgr_nr , lgr_index); { - const int_vector_type * index_list = nnc_info_iget_grid_index_list( nnc_info , lgr_index ); - int_vector_fprintf( index_list , stream , " " , "%d"); + const std::vector& index_list = nnc_info_iget_grid_index_list( nnc_info , lgr_index ); + vector_util_fprintf( index_list , stream , " " , "%d"); printf("\n"); } } diff --git a/ThirdParty/Ert/lib/ecl/nnc_vector.cpp b/ThirdParty/Ert/lib/ecl/nnc_vector.cpp index b808faa6e4..be24ffba67 100644 --- a/ThirdParty/Ert/lib/ecl/nnc_vector.cpp +++ b/ThirdParty/Ert/lib/ecl/nnc_vector.cpp @@ -1,6 +1,6 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'nnc_vector.c' is part of ERT - Ensemble based Reservoir Tool. @@ -19,10 +19,11 @@ #include +#include + #include #include #include -#include #include @@ -33,9 +34,9 @@ struct nnc_vector_struct { UTIL_TYPE_ID_DECLARATION; - int lgr_nr; - int_vector_type * grid_index_list; - int_vector_type * nnc_index_list; + int lgr_nr; + std::vector grid_index_list; + std::vector nnc_index_list; }; @@ -45,21 +46,19 @@ static UTIL_SAFE_CAST_FUNCTION(nnc_vector , NNC_VECTOR_TYPE_ID) nnc_vector_type * nnc_vector_alloc(int lgr_nr) { - nnc_vector_type * nnc_vector = (nnc_vector_type*)util_malloc( sizeof * nnc_vector ); + nnc_vector_type * nnc_vector = new nnc_vector_type(); UTIL_TYPE_ID_INIT(nnc_vector , NNC_VECTOR_TYPE_ID); - nnc_vector->grid_index_list = int_vector_alloc(0,0); - nnc_vector->nnc_index_list = int_vector_alloc(0,0); nnc_vector->lgr_nr = lgr_nr; return nnc_vector; } nnc_vector_type * nnc_vector_alloc_copy(const nnc_vector_type * src_vector) { - nnc_vector_type * copy_vector = (nnc_vector_type*)util_malloc( sizeof * src_vector ); + nnc_vector_type * copy_vector = new nnc_vector_type(); UTIL_TYPE_ID_INIT(copy_vector , NNC_VECTOR_TYPE_ID); copy_vector->lgr_nr = src_vector->lgr_nr; - copy_vector->grid_index_list = int_vector_alloc_copy( src_vector->grid_index_list ); - copy_vector->nnc_index_list = int_vector_alloc_copy( src_vector->nnc_index_list ); + copy_vector->grid_index_list = src_vector->grid_index_list; + copy_vector->nnc_index_list = src_vector->nnc_index_list; return copy_vector; } @@ -75,10 +74,10 @@ bool nnc_vector_equal( const nnc_vector_type * nnc_vector1 , const nnc_vector_ty if (nnc_vector1->lgr_nr != nnc_vector2->lgr_nr) return false; - if (!int_vector_equal( nnc_vector1->grid_index_list , nnc_vector2->grid_index_list)) + if (nnc_vector1->grid_index_list != nnc_vector2->grid_index_list) return false; - if (!int_vector_equal( nnc_vector1->nnc_index_list , nnc_vector2->nnc_index_list)) + if (nnc_vector1->nnc_index_list != nnc_vector2->nnc_index_list) return false; return true; @@ -87,9 +86,7 @@ bool nnc_vector_equal( const nnc_vector_type * nnc_vector1 , const nnc_vector_ty void nnc_vector_free( nnc_vector_type * nnc_vector ) { - int_vector_free( nnc_vector->grid_index_list ); - int_vector_free( nnc_vector->nnc_index_list ); - free( nnc_vector ); + delete nnc_vector; } @@ -100,21 +97,21 @@ void nnc_vector_free__(void * arg) { void nnc_vector_add_nnc(nnc_vector_type * nnc_vector, int global_cell_number , int nnc_index) { - int_vector_append( nnc_vector->grid_index_list , global_cell_number ); - int_vector_append( nnc_vector->nnc_index_list , nnc_index); + nnc_vector->grid_index_list.push_back( global_cell_number ); + nnc_vector->nnc_index_list.push_back(nnc_index); } -const int_vector_type * nnc_vector_get_grid_index_list(const nnc_vector_type * nnc_vector) { +const std::vector& nnc_vector_get_grid_index_list(const nnc_vector_type * nnc_vector) { return nnc_vector->grid_index_list; } -const int_vector_type * nnc_vector_get_nnc_index_list(const nnc_vector_type * nnc_vector) { +const std::vector& nnc_vector_get_nnc_index_list(const nnc_vector_type * nnc_vector) { return nnc_vector->nnc_index_list; } int nnc_vector_get_size( const nnc_vector_type * nnc_vector ) { - return int_vector_size( nnc_vector->grid_index_list ); + return nnc_vector->grid_index_list.size(); } int nnc_vector_get_lgr_nr( const nnc_vector_type * nnc_vector ) { @@ -122,9 +119,9 @@ int nnc_vector_get_lgr_nr( const nnc_vector_type * nnc_vector ) { } int nnc_vector_iget_nnc_index( const nnc_vector_type * nnc_vector , int index ) { - return int_vector_iget( nnc_vector->nnc_index_list , index ); + return nnc_vector->nnc_index_list[index]; } int nnc_vector_iget_grid_index( const nnc_vector_type * nnc_vector , int index ) { - return int_vector_iget( nnc_vector->grid_index_list , index ); + return nnc_vector->grid_index_list[index]; } diff --git a/ThirdParty/Ert/lib/ecl/smspec_node.cpp b/ThirdParty/Ert/lib/ecl/smspec_node.cpp index 98bf35b597..ba4e9bfdae 100644 --- a/ThirdParty/Ert/lib/ecl/smspec_node.cpp +++ b/ThirdParty/Ert/lib/ecl/smspec_node.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Statoil ASA, Norway. + Copyright (C) 2012 Equinor ASA, Norway. The file 'smspec_node.c' is part of ERT - Ensemble based Reservoir Tool. @@ -18,12 +18,14 @@ #include #include +#include #include #include #include #include #include +#include #include #include @@ -41,6 +43,35 @@ #include "detail/util/string_util.hpp" +/** + The special_vars list is used to associate keywords with special + types, when the kewyord name is in conflict with the default vector + naming convention; all the variables mentioned in the list below + are given the type ECL_SMSPEC_MISC_VAR. + + For instance the keyword 'NEWTON' starts with 'N' and is + classified as a NETWORK type variable. However it should rather + be classified as a MISC type variable. (What a fucking mess). + + The special_vars list is used in the functions + ecl_smspec_identify_special_var() and ecl_smspec_identify_var_type(). +*/ + +static const char* special_vars[] = {"NEWTON", + "NAIMFRAC", + "NLINEARS", + "NLINSMIN", + "NLINSMAX", + "ELAPSED", + "MAXDPR", + "MAXDSO", + "MAXDSG", + "MAXDSW", + "STEPTYPE", + "WNEWTON"}; + + +static const int nums_unused = 0; /** This struct contains meta-information about one element in the smspec @@ -50,53 +81,166 @@ probably the most important field. */ -#define SMSPEC_TYPE_ID 61550451 +/** + Goes through the special_vars static table to check if @var is one + the special variables which does not follow normal naming + convention. If the test eavulates to true the function will return + ECL_SMSPEC_MISC_VAR, otherwise the function will return + ECL_SMSPEC_INVALID_VAR and the variable type will be determined + from the var name according to standard naming conventions. + It is important that this function is called before the standard + method. +*/ -struct smspec_node_struct { - UTIL_TYPE_ID_DECLARATION; - std::string wgname; - std::string keyword; /* The value of the KEYWORDS vector for this elements. */ - std::string unit; /* The value of the UNITS vector for this elements. */ - int num; /* The value of the NUMS vector for this elements - NB this will have the value SMSPEC_NUMS_INVALID if the smspec file does not have a NUMS vector. */ - std::string lgr_name; /* The lgr name of the current variable - will be NULL for non-lgr variables. */ - std::array lgr_ijk; +ecl_smspec_var_type ecl::smspec_node::identify_special_var( const char * var ) { + ecl_smspec_var_type var_type = ECL_SMSPEC_INVALID_VAR; - /*------------------------------------------- All members below this line are *derived* quantities. */ + int num_special = sizeof( special_vars ) / sizeof( special_vars[0] ); + int i; + for (i=0; i < num_special; i++) { + if (strcmp( var , special_vars[i]) == 0) { + var_type = ECL_SMSPEC_MISC_VAR; + break; + } + } - std::string gen_key1; /* The main composite key, i.e. WWCT:OP3 for this element. */ - std::string gen_key2; /* Some of the ijk based elements will have both a xxx:i,j,k and a xxx:num key. Some of the region_2_region elements will have both a xxx:num and a xxx:r2-r2 key. Mostly NULL. */ - ecl_smspec_var_type var_type; /* The variable type */ - std::array ijk; /* The ijk coordinates (NB: OFFSET 1) corresponding to the nums value - will be NULL if not relevant. */ - bool rate_variable; /* Is this a rate variable (i.e. WOPR) or a state variable (i.e. BPR). Relevant when doing time interpolation. */ - bool total_variable; /* Is this a total variable like WOPT? */ - bool historical; /* Does the name end with 'H'? */ - int params_index; /* The index of this variable (applies to all the vectors - in particular the PARAMS vectors of the summary files *.Snnnn / *.UNSMRY ). */ - float default_value; /* Default value for this variable. */ -}; - - - -bool smspec_node_equal( const smspec_node_type * node1, const smspec_node_type * node2) { - return smspec_node_cmp( node1 , node2 ) == 0; + return var_type; } -static bool smspec_node_need_wgname(ecl_smspec_var_type var_type) { - if (var_type == ECL_SMSPEC_COMPLETION_VAR || - var_type == ECL_SMSPEC_GROUP_VAR || - var_type == ECL_SMSPEC_WELL_VAR || - var_type == ECL_SMSPEC_SEGMENT_VAR) - return true; - else - return false; +/* + See table 3.4 in the ECLIPSE file format reference manual. + + Observe that the combined ecl_sum style keys like e.g. WWCT:OP1 + should be formatted with the keyword first, so that this function + will identify both 'WWCT' and 'WWCT:OP_1' as a ECL_SMSPEC_WELL_VAR + instance. +*/ + +ecl_smspec_var_type ecl::smspec_node::identify_var_type(const char * var) { + ecl_smspec_var_type var_type = ecl::smspec_node::identify_special_var(var); + if (var_type == ECL_SMSPEC_INVALID_VAR) { + switch(var[0]) { + case('A'): + var_type = ECL_SMSPEC_AQUIFER_VAR; + break; + case('B'): + var_type = ECL_SMSPEC_BLOCK_VAR; + break; + case('C'): + var_type = ECL_SMSPEC_COMPLETION_VAR; + break; + case('F'): + var_type = ECL_SMSPEC_FIELD_VAR; + break; + case('G'): + var_type = ECL_SMSPEC_GROUP_VAR; + break; + case('L'): + switch(var[1]) { + case('B'): + var_type = ECL_SMSPEC_LOCAL_BLOCK_VAR; + break; + case('C'): + var_type = ECL_SMSPEC_LOCAL_COMPLETION_VAR; + break; + case('W'): + var_type = ECL_SMSPEC_LOCAL_WELL_VAR; + break; + default: + /* + The documentation explicitly mentions keywords starting with + LB, LC and LW as special types, but keywords starting with + L[^BCW] are also valid. These come in the misceallaneous + category; at least the LLINEAR keyword is an example of such + a keyword. + */ + var_type = ECL_SMSPEC_MISC_VAR; + } + break; + case('N'): + var_type = ECL_SMSPEC_NETWORK_VAR; + break; + case('R'): + { + /* + The distinction between regular region variables and region-to-region + variables is less than clear. The manual prescribes a rule based on + the characters at position 3 and 4 or 4 and 5. + + R*FT* => Region to region + R**FT* => Region to region + R*FR* => Region to region + R**FR* => Region to region + + RORFR => exception - normal region var. + + + In addition older test cases seem to imply the following extra + rules/exceptions: + + RNLF: region to region variable + RxF : region to region variable + + The manual does not seem to offer any backup for these extra rules. + */ + + if (strlen(var) == 3 && var[2] == 'F') { + var_type = ECL_SMSPEC_REGION_2_REGION_VAR; + break; + } + + if (util_string_equal( var , "RNLF")) { + var_type = ECL_SMSPEC_REGION_2_REGION_VAR; + break; + } + + if (util_string_equal(var, "RORFR")) { + var_type = ECL_SMSPEC_REGION_VAR; + break; + } + + if (strlen(var) >= 4) { + if (var[2] == 'F') { + if (var[3] == 'T' || var[3] == 'R') { + var_type = ECL_SMSPEC_REGION_2_REGION_VAR; + break; + } + } + } + + if (strlen(var) >= 5) { + if (var[3] == 'F') { + if (var[4] == 'T' || var[4] == 'R') { + var_type = ECL_SMSPEC_REGION_2_REGION_VAR; + break; + } + } + } + + var_type = ECL_SMSPEC_REGION_VAR; + } + break; + case('S'): + var_type = ECL_SMSPEC_SEGMENT_VAR; + break; + case('W'): + var_type = ECL_SMSPEC_WELL_VAR; + break; + default: + /* + It is unfortunately impossible to recognize an error situation - + the rest just goes in "other" variables. + */ + var_type = ECL_SMSPEC_MISC_VAR; + } + } + + return var_type; } -static bool smspec_node_type_supported(ecl_smspec_var_type var_type) { - if (var_type == ECL_SMSPEC_NETWORK_VAR) - return false; - return true; -} + /*****************************************************************/ @@ -123,9 +267,6 @@ static bool smspec_node_type_supported(ecl_smspec_var_type var_type) { #define ECL_SUM_KEYFMT_SEGMENT "%s%s%s%s%d" #define ECL_SUM_KEYFMT_LOCAL_WELL "%s%s%s%s%s" -UTIL_SAFE_CAST_FUNCTION( smspec_node , SMSPEC_TYPE_ID ) -static UTIL_SAFE_CAST_FUNCTION_CONST( smspec_node , SMSPEC_TYPE_ID ) - std::string smspec_alloc_block_num_key( const char * join_string , const std::string& keyword , int num) { return ecl::util::string_format(ECL_SUM_KEYFMT_BLOCK_NUM, @@ -188,7 +329,7 @@ std::string smspec_alloc_completion_ijk_key( const char * join_string , const st join_string , i , j , k ); else - return std::string(); + return NULL; } @@ -202,7 +343,7 @@ std::string smspec_alloc_completion_num_key( const char * join_string , const st join_string , num ); else - return std::string(); + return NULL; } /* @@ -265,7 +406,7 @@ std::string smspec_alloc_segment_key( const char * join_string , const std::stri join_string , num ); else - return std::string(); + return NULL; } @@ -278,7 +419,7 @@ std::string smspec_alloc_local_well_key( const char * join_string , const std::s join_string , wgname.c_str()); else - return std::string(); + return NULL; } std::string smspec_alloc_local_completion_key( const char * join_string, const std::string& keyword , const std::string& lgr_name , const std::string& wgname , int i , int j , int k) { @@ -292,32 +433,15 @@ std::string smspec_alloc_local_completion_key( const char * join_string, const s join_string , i,j,k); else - return std::string(); + return NULL; } /*****************************************************************/ -static void smspec_node_set_keyword( smspec_node_type * smspec_node , const std::string& keyword ) { - // ECLIPSE Standard: Max eight characters - everything beyond is silently dropped - // This function can __ONLY__ be called on time; run-time chaning of keyword is not - // allowed. - if (smspec_node->keyword.size() == 0) - smspec_node->keyword = keyword; - else - util_abort("%s: fatal error - attempt to change keyword runtime detected - aborting\n",__func__); -} - - -static void smspec_node_set_invalid_flags( smspec_node_type * smspec_node) { - smspec_node->rate_variable = false; - smspec_node->total_variable = false; - smspec_node->historical = false; -} - - bool smspec_node_identify_rate(const char * keyword) { - const char *rate_vars[] = {"OPR" , "GPR" , "WPR" , "LPR", "OIR", "GIR", "WIR", "LIR", "GOR" , "WCT"}; + const char *rate_vars[] = {"OPR" , "GPR" , "WPR" , "LPR", "OIR", "GIR", "WIR", "LIR", "GOR" , "WCT", + "OFR" , "GFR" , "WFR"}; int num_rate_vars = sizeof( rate_vars ) / sizeof( rate_vars[0] ); bool is_rate = false; int ivar; @@ -369,104 +493,76 @@ bool smspec_node_identify_total(const char * keyword, ecl_smspec_var_type var_ty } } } + else if (var_type == ECL_SMSPEC_SEGMENT_VAR) { + const char *total_vars[] = {"OFT", "GFT", "WFT"}; + const char *var_substring = &keyword[1]; + const size_t num_total_vars = sizeof(total_vars) / sizeof(total_vars[0]); + for (size_t ivar = 0; ivar < num_total_vars; ivar++) + if (strncmp(total_vars[ivar], var_substring, strlen(total_vars[ivar])) == 0) { + is_total = true; + break; + } + } return is_total; } -static void smspec_node_set_flags( smspec_node_type * smspec_node) { - /* - Check if this is a rate variabel - that info is used when - interpolating results to true_time between ministeps. - */ - smspec_node->rate_variable = smspec_node_identify_rate(smspec_node->keyword.c_str()); - if (smspec_node->keyword.back() == 'H') - smspec_node->historical = true; - smspec_node->total_variable = smspec_node_identify_total(smspec_node->keyword.c_str(), smspec_node->var_type); +namespace ecl { + + + +float smspec_node::get_default() const { + return this->default_value; } -/** - It is possible to change the default value of an smspec node - runtime, but observe that the new value will only be applied to the - new timesteps you add after the change. Already created timesteps - will not be updated if the default value is changed. + +void smspec_node::set_lgr_ijk( int lgr_i , int lgr_j , int lgr_k) { + lgr_ijk[0] = lgr_i; + lgr_ijk[1] = lgr_j; + lgr_ijk[2] = lgr_k; +} + + +/* + Observe that field vectors like 'FOPT' and 'FOPR' will have the string 'FIELD' + in the 'WGNAME' vector, that is not internalized here. */ -void smspec_node_set_default( smspec_node_type * smspec_node , float default_value) { - smspec_node->default_value = default_value; + +void smspec_node::set_wgname(const char * wgname) { + if (!wgname) + return; + + if (IS_DUMMY_WELL(wgname)) + return; + + if (this->var_type == ECL_SMSPEC_WELL_VAR || + this->var_type == ECL_SMSPEC_GROUP_VAR || + this->var_type == ECL_SMSPEC_COMPLETION_VAR || + this->var_type == ECL_SMSPEC_SEGMENT_VAR || + this->var_type == ECL_SMSPEC_LOCAL_WELL_VAR) + this->wgname = wgname; } - -float smspec_node_get_default( const smspec_node_type * smspec_node ) { - return smspec_node->default_value; -} - - -smspec_node_type * smspec_node_alloc_new(int params_index, float default_value) { - smspec_node_type * node = new smspec_node_type(); - - UTIL_TYPE_ID_INIT( node , SMSPEC_TYPE_ID); - node->params_index = params_index; - smspec_node_set_default( node , default_value ); - - node->var_type = ECL_SMSPEC_INVALID_VAR; - smspec_node_set_invalid_flags( node ); - return node; // This is NOT usable -} - - -static void smspec_node_set_wgname( smspec_node_type * index , const char * wgname ) { - index->wgname = wgname; -} - - - -static void smspec_node_set_lgr_name( smspec_node_type * index , const std::string& lgr_name ) { - index->lgr_name = lgr_name; -} - - -static void smspec_node_set_lgr_ijk( smspec_node_type * index , int lgr_i , int lgr_j , int lgr_k) { - index->lgr_ijk[0] = lgr_i; - index->lgr_ijk[1] = lgr_j; - index->lgr_ijk[2] = lgr_k; -} - - -static void smspec_node_init_num( smspec_node_type * node , ecl_smspec_var_type var_type) { - switch( node->var_type ) { - case(ECL_SMSPEC_WELL_VAR): - node->num = SMSPEC_NUMS_WELL; - break; - case(ECL_SMSPEC_GROUP_VAR): - node->num = SMSPEC_NUMS_GROUP; - break; - case(ECL_SMSPEC_FIELD_VAR): - node->num = SMSPEC_NUMS_FIELD; - break; - default: - node->num = SMSPEC_NUMS_INVALID; - } -} -static void smspec_node_set_num( smspec_node_type * index , const int grid_dims[3] , int num) { - if (num == SMSPEC_NUMS_INVALID) +void smspec_node::set_num( const int * grid_dims , int num_) { + if (num_ == SMSPEC_NUMS_INVALID) util_abort("%s: explicitly trying to set nums == SMSPEC_NUMS_INVALID - seems like a bug?!\n",__func__); + this->num = num_; + if ((var_type == ECL_SMSPEC_COMPLETION_VAR) || (var_type == ECL_SMSPEC_BLOCK_VAR)) { + int global_index = this->num - 1; + this->ijk[2] = global_index / ( grid_dims[0] * grid_dims[1] ); global_index -= this->ijk[2] * (grid_dims[0] * grid_dims[1]); + this->ijk[1] = global_index / grid_dims[0] ; global_index -= this->ijk[1] * grid_dims[0]; + this->ijk[0] = global_index; - index->num = num; - if ((index->var_type == ECL_SMSPEC_COMPLETION_VAR) || (index->var_type == ECL_SMSPEC_BLOCK_VAR)) { - int global_index = num - 1; - index->ijk[2] = global_index / ( grid_dims[0] * grid_dims[1] ); global_index -= index->ijk[2] * (grid_dims[0] * grid_dims[1]); - index->ijk[1] = global_index / grid_dims[0] ; global_index -= index->ijk[1] * grid_dims[0]; - index->ijk[0] = global_index; - - index->ijk[0] += 1; - index->ijk[1] += 1; - index->ijk[2] += 1; + this->ijk[0] += 1; + this->ijk[1] += 1; + this->ijk[2] += 1; } } -static void smspec_node_decode_R1R2( const smspec_node_type * smspec_node , int * r1 , int * r2) { - if (smspec_node->var_type == ECL_SMSPEC_REGION_2_REGION_VAR) { - *r1 = smspec_node->num % 32768; - *r2 = ((smspec_node->num - (*r1)) / 32768)-10; +void smspec_node::decode_R1R2(int * r1 , int * r2) const { + if (var_type == ECL_SMSPEC_REGION_2_REGION_VAR) { + *r1 = this->num % 32768; + *r2 = ((this->num - (*r1)) / 32768)-10; } else { *r1 = -1; *r2 = -1; @@ -485,78 +581,67 @@ static void smspec_node_decode_R1R2( const smspec_node_type * smspec_node , int */ -static void smspec_node_set_gen_keys( smspec_node_type * smspec_node , const char * key_join_string) { - switch( smspec_node->var_type) { +void smspec_node::set_gen_keys( const char* key_join_string_) { + switch( var_type) { case(ECL_SMSPEC_COMPLETION_VAR): // KEYWORD:WGNAME:NUM - smspec_node->gen_key1 = smspec_alloc_completion_ijk_key( key_join_string , smspec_node->keyword , smspec_node->wgname , smspec_node->ijk[0], smspec_node->ijk[1], smspec_node->ijk[2]); - smspec_node->gen_key2 = smspec_alloc_completion_num_key( key_join_string , smspec_node->keyword , smspec_node->wgname , smspec_node->num); + gen_key1 = smspec_alloc_completion_ijk_key( key_join_string_ , keyword , wgname , ijk[0], ijk[1], ijk[2]); + gen_key2 = smspec_alloc_completion_num_key( key_join_string_ , keyword , wgname , num); break; case(ECL_SMSPEC_FIELD_VAR): // KEYWORD - smspec_node->gen_key1 = util_alloc_string_copy( smspec_node->keyword.c_str() ); + gen_key1 = keyword; break; case(ECL_SMSPEC_GROUP_VAR): // KEYWORD:WGNAME - smspec_node->gen_key1 = smspec_alloc_group_key( key_join_string , smspec_node->keyword , smspec_node->wgname); + gen_key1 = smspec_alloc_group_key( key_join_string_ , keyword , wgname); break; case(ECL_SMSPEC_WELL_VAR): // KEYWORD:WGNAME - smspec_node->gen_key1 = smspec_alloc_well_key( key_join_string , smspec_node->keyword , smspec_node->wgname); + gen_key1 = smspec_alloc_well_key( key_join_string_ , keyword , wgname); break; case(ECL_SMSPEC_REGION_VAR): // KEYWORD:NUM - smspec_node->gen_key1 = smspec_alloc_region_key( key_join_string , smspec_node->keyword , smspec_node->num); + gen_key1 = smspec_alloc_region_key( key_join_string_ , keyword , num); break; case (ECL_SMSPEC_SEGMENT_VAR): // KEYWORD:WGNAME:NUM - smspec_node->gen_key1 = smspec_alloc_segment_key( key_join_string , smspec_node->keyword , smspec_node->wgname , smspec_node->num); + gen_key1 = smspec_alloc_segment_key( key_join_string_ , keyword , wgname , num); break; case(ECL_SMSPEC_REGION_2_REGION_VAR): // KEYWORDS:RXF:NUM and RXF:R1-R2 { int r1,r2; - smspec_node_decode_R1R2( smspec_node , &r1 , &r2); - smspec_node->gen_key1 = smspec_alloc_region_2_region_r1r2_key( key_join_string , smspec_node->keyword , r1, r2); + decode_R1R2( &r1 , &r2); + gen_key1 = smspec_alloc_region_2_region_r1r2_key( key_join_string_ , keyword , r1, r2); } - smspec_node->gen_key2 = smspec_alloc_region_2_region_num_key( key_join_string , smspec_node->keyword , smspec_node->num); + gen_key2 = smspec_alloc_region_2_region_num_key( key_join_string_ , keyword , num); break; case(ECL_SMSPEC_MISC_VAR): // KEYWORD /* Misc variable - i.e. date or CPU time ... */ - smspec_node->gen_key1 = smspec_node->keyword; + gen_key1 = keyword; break; case(ECL_SMSPEC_BLOCK_VAR): // KEYWORD:NUM - smspec_node->gen_key1 = smspec_alloc_block_ijk_key( key_join_string , smspec_node->keyword , smspec_node->ijk[0], smspec_node->ijk[1], smspec_node->ijk[2]); - smspec_node->gen_key2 = smspec_alloc_block_num_key( key_join_string , smspec_node->keyword , smspec_node->num); + gen_key1 = smspec_alloc_block_ijk_key( key_join_string_ , keyword , ijk[0], ijk[1], ijk[2]); + gen_key2 = smspec_alloc_block_num_key( key_join_string_ , keyword , num); break; case(ECL_SMSPEC_LOCAL_WELL_VAR): /** KEYWORD:LGR:WGNAME */ - smspec_node->gen_key1 = smspec_alloc_local_well_key( key_join_string , smspec_node->keyword , smspec_node->lgr_name , smspec_node->wgname); + gen_key1 = smspec_alloc_local_well_key( key_join_string_ , keyword , lgr_name , wgname); break; case(ECL_SMSPEC_LOCAL_BLOCK_VAR): /* KEYWORD:LGR:i,j,k */ - smspec_node->gen_key1 = smspec_alloc_local_block_key( key_join_string , - smspec_node->keyword , - smspec_node->lgr_name , - smspec_node->lgr_ijk[0] , - smspec_node->lgr_ijk[1] , - smspec_node->lgr_ijk[2] ); + gen_key1 = smspec_alloc_local_block_key( key_join_string_ , keyword , lgr_name , lgr_ijk[0] , lgr_ijk[1] , lgr_ijk[2] ); break; case(ECL_SMSPEC_LOCAL_COMPLETION_VAR): /* KEYWORD:LGR:WELL:i,j,k */ - smspec_node->gen_key1 = smspec_alloc_local_completion_key( key_join_string , - smspec_node->keyword , - smspec_node->lgr_name , - smspec_node->wgname , - smspec_node->lgr_ijk[0], - smspec_node->lgr_ijk[1], - smspec_node->lgr_ijk[2]); + gen_key1 = smspec_alloc_local_completion_key( key_join_string_ , keyword , lgr_name , wgname , lgr_ijk[0], lgr_ijk[1], lgr_ijk[2]); break; case(ECL_SMSPEC_AQUIFER_VAR): - smspec_node->gen_key1 = smspec_alloc_aquifer_key( key_join_string , smspec_node->keyword , smspec_node->num); + gen_key1 = smspec_alloc_aquifer_key( key_join_string_ , keyword , num); break; default: util_abort("%s: internal error - should not be here? \n" , __func__); @@ -564,123 +649,79 @@ static void smspec_node_set_gen_keys( smspec_node_type * smspec_node , const cha } +/* + Observe the following: -static void smspec_node_common_init( smspec_node_type * node , ecl_smspec_var_type var_type , const char * keyword , const std::string& unit ) { - if (node->var_type == ECL_SMSPEC_INVALID_VAR) { - smspec_node_set_unit( node , unit.c_str() ); - smspec_node_set_keyword( node , keyword); - node->var_type = var_type; - smspec_node_set_flags( node ); - smspec_node_init_num( node , var_type ); - } else - util_abort("%s: trying to re-init smspec node with keyword:%s - invalid \n",__func__ , keyword ); -} + 1. There are many legitimate value types here which we do not handle, then we + just return false. + 2. Observe that the LGR variables are not thoroughly checked; the only check + is that the well is not the dummy well. Experience has shown that there has + not been problems with SMSPEC files with invalid LGR and LGRIJK values; + that is therefor just assumed to be right. -static bool smspec_node_init__( smspec_node_type * smspec_node, - ecl_smspec_var_type var_type , - const char * wgname , - const char * keyword , - const char * unit , - const char * key_join_string , - const int grid_dims[3] , - int num) { +*/ - bool initOK = true; +ecl_smspec_var_type smspec_node::valid_type(const char * keyword, const char * wgname, int num) { + auto var_type = smspec_node::identify_var_type(keyword); - smspec_node_common_init( smspec_node , var_type , keyword , unit ); - switch (var_type) { - case(ECL_SMSPEC_COMPLETION_VAR): - /* Completion variable : WGNAME & NUM */ - smspec_node_set_num( smspec_node , grid_dims , num ); - smspec_node_set_wgname( smspec_node , wgname ); - if (num < 0) - initOK = false; - break; - case(ECL_SMSPEC_GROUP_VAR): - /* Group variable : WGNAME */ - smspec_node_set_wgname( smspec_node , wgname ); - break; - case(ECL_SMSPEC_WELL_VAR): - /* Well variable : WGNAME */ - smspec_node_set_wgname( smspec_node , wgname ); - break; - case(ECL_SMSPEC_SEGMENT_VAR): - smspec_node_set_wgname( smspec_node , wgname ); - smspec_node_set_num( smspec_node , grid_dims , num ); - if (num < 0) - initOK = false; - break; - case(ECL_SMSPEC_FIELD_VAR): - /* Field variable : */ - /* Fully initialized with the smspec_common_init() function */ - break; - case(ECL_SMSPEC_REGION_VAR): - /* Region variable : NUM */ - smspec_node_set_num( smspec_node , grid_dims , num ); - break; - case(ECL_SMSPEC_REGION_2_REGION_VAR): - /* Region 2 region variable : NUM */ - smspec_node_set_num( smspec_node , grid_dims , num ); - break; - case(ECL_SMSPEC_BLOCK_VAR): - /* A block variable : NUM*/ - smspec_node_set_num( smspec_node , grid_dims , num ); - break; - case(ECL_SMSPEC_MISC_VAR): - /* Misc variable : */ + if (var_type == ECL_SMSPEC_MISC_VAR) + return var_type; + + if (var_type == ECL_SMSPEC_FIELD_VAR) + return var_type; + + if (var_type == ECL_SMSPEC_LOCAL_BLOCK_VAR) + return var_type; + + if (var_type == ECL_SMSPEC_WELL_VAR || + var_type == ECL_SMSPEC_GROUP_VAR || + var_type == ECL_SMSPEC_LOCAL_WELL_VAR || + var_type == ECL_SMSPEC_LOCAL_COMPLETION_VAR) { + if (IS_DUMMY_WELL(wgname)) + return ECL_SMSPEC_INVALID_VAR; /* - For some keywords the SMSPEC files generated by Eclipse have a - non zero NUMS value although; it seems that value is required - for the generatd summaryfiles to display nicely in - e.g. S3GRAF. + In most cases the dummy well ':+:+:+:+' is used in situations where a + well/group name does not make sense; however we have also encountered the + blank string as an invalid well name; when this is trimmed we get NULL (C) + or "" (C++). */ - if (util_string_equal( keyword ,SMSPEC_TIME_KEYWORD)) - smspec_node_set_num( smspec_node , grid_dims , SMSPEC_TIME_NUMS_VALUE ); + if (!wgname) + return ECL_SMSPEC_INVALID_VAR; - if (util_string_equal( keyword ,SMSPEC_YEARS_KEYWORD)) - smspec_node_set_num( smspec_node , grid_dims , SMSPEC_YEARS_NUMS_VALUE ); + if (strlen(wgname) == 0) + return ECL_SMSPEC_INVALID_VAR; - break; - case(ECL_SMSPEC_AQUIFER_VAR): - smspec_node_set_num( smspec_node , grid_dims , num ); - break; - default: - /* Lots of legitimate alternatives which are not internalized. */ - initOK = false; - break; + return var_type; } - if (initOK) - smspec_node_set_gen_keys( smspec_node , key_join_string ); + if (var_type == ECL_SMSPEC_COMPLETION_VAR || var_type == ECL_SMSPEC_SEGMENT_VAR) { + if (IS_DUMMY_WELL(wgname)) + return ECL_SMSPEC_INVALID_VAR; - return initOK; + if (num < 0) + return ECL_SMSPEC_INVALID_VAR; + + return var_type; + } + + if (var_type == ECL_SMSPEC_REGION_VAR || + var_type == ECL_SMSPEC_REGION_2_REGION_VAR || + var_type == ECL_SMSPEC_BLOCK_VAR || + var_type == ECL_SMSPEC_AQUIFER_VAR) { + + if (num < 0) + return ECL_SMSPEC_INVALID_VAR; + + return var_type; + } + + return ECL_SMSPEC_INVALID_VAR; } -/* - This function should be removed from the public API. -*/ -void smspec_node_init( smspec_node_type * smspec_node, - ecl_smspec_var_type var_type , - const char * wgname , - const char * keyword , - const char * unit , - const char * key_join_string , - const int grid_dims[3] , - int num) { - smspec_node_init__(smspec_node, - var_type, - wgname, - keyword, - unit, - key_join_string, - grid_dims, - num); - -} /** This function will allocate a smspec_node instance, and initialize @@ -696,15 +737,83 @@ void smspec_node_init( smspec_node_type * smspec_node, ecl_smspec_fread_header() functions in addition. UGGGLY */ +smspec_node::smspec_node(int param_index, const char * keyword, int num, const char * unit, const int grid_dims[3], float default_value, const char * key_join_string) + : smspec_node(param_index, + keyword, + nullptr, + num, + unit, + grid_dims, + default_value, + key_join_string) +{ +} + +smspec_node::smspec_node(int param_index, const char * keyword, int num, const char * unit, float default_value, const char * key_join_string) + : smspec_node(param_index, + keyword, + nullptr, + num, + unit, + nullptr, + default_value, + key_join_string) +{ +} -smspec_node_type * smspec_node_alloc( ecl_smspec_var_type var_type , - const char * wgname , - const char * keyword , - const char * unit , - const char * key_join_string , - const int grid_dims[3] , - int num , int param_index, float default_value) { + +smspec_node::smspec_node(int param_index, const char * keyword, const char * wgname, const char * unit, float default_value, const char * key_join_string) + : smspec_node(param_index, + keyword, + wgname, + nums_unused, + unit, + nullptr, + default_value, + key_join_string) +{ +} + +smspec_node::smspec_node(int param_index, const char * keyword, const char * wgname, int num, const char * unit, float default_value, const char * key_join_string) + : smspec_node(param_index, + keyword, + wgname, + num, + unit, + nullptr, + default_value, + key_join_string) +{} + + +smspec_node::smspec_node(int param_index, const char * keyword, const char * unit, float default_value) + : smspec_node(param_index, + keyword, + nullptr, + nums_unused, + unit, + nullptr, + default_value, + nullptr) +{ +} + +//copy constructor with a new id +smspec_node::smspec_node(const smspec_node& node, int param_index) +{ + *this = node; + this->params_index = param_index; +} + +smspec_node::smspec_node(int param_index, + const char * keyword, + const char * wgname , + int num, + const char * unit , + const int grid_dims[3] , + float default_value, + const char * key_join_string) { /* Well and group names in the wgname parameter is quite messy. The situation is as follows: @@ -734,132 +843,129 @@ smspec_node_type * smspec_node_alloc( ecl_smspec_var_type var_type , at all, e.g. like "FOPT" - the wgname input value is ignored completely. */ + this->var_type = this->valid_type(keyword, wgname, num); + if (this->var_type == ECL_SMSPEC_INVALID_VAR) + throw std::invalid_argument("Could not construct smspec_node from this input."); - if (smspec_node_need_wgname(var_type) && IS_DUMMY_WELL(wgname)) - return NULL; + this->params_index = param_index; + this->default_value = default_value; + this->keyword = keyword; + this->num = num; + this->unit = unit; + this->rate_variable = smspec_node_identify_rate(this->keyword.c_str()); + this->total_variable = smspec_node_identify_total(this->keyword.c_str(), this->var_type); + this->historical = (this->keyword.back() == 'H'); + this->set_wgname( wgname ); - if (!smspec_node_type_supported(var_type)) - return NULL; - - /* - TODO: The alloc_new and init functions should be joined in one function. - */ - smspec_node_type * smspec_node = smspec_node_alloc_new( param_index , default_value ); - bool initOK = smspec_node_init__( smspec_node , var_type , wgname , keyword , unit , key_join_string , grid_dims, num); - if (!initOK) { - smspec_node_free(smspec_node); - smspec_node = NULL; - } - - return smspec_node; -} - - - -static void smspec_node_init_lgr( smspec_node_type * smspec_node , - ecl_smspec_var_type var_type , - const char * wgname , - const char * keyword , - const char * unit , - const char * lgr , - const char * key_join_string , - int lgr_i, int lgr_j , int lgr_k - ) { - bool initOK = true; - bool wgnameOK = true; - if ((wgname != NULL) && (IS_DUMMY_WELL(wgname))) - wgnameOK = false; - - smspec_node_common_init( smspec_node , var_type , keyword , unit ); - switch (var_type) { - case(ECL_SMSPEC_LOCAL_WELL_VAR): - smspec_node_set_wgname( smspec_node , wgname ); - smspec_node_set_lgr_name( smspec_node , lgr ); - initOK = wgnameOK; + switch (this->var_type) { + case(ECL_SMSPEC_COMPLETION_VAR): + /* Completion variable : WGNAME & NUM */ + set_num( grid_dims , num ); break; - case(ECL_SMSPEC_LOCAL_BLOCK_VAR): - smspec_node_set_lgr_name( smspec_node , lgr ); - smspec_node_set_lgr_ijk( smspec_node , lgr_i, lgr_j , lgr_k ); + case(ECL_SMSPEC_GROUP_VAR): + /* Group variable : WGNAME */ break; - case(ECL_SMSPEC_LOCAL_COMPLETION_VAR): - smspec_node_set_lgr_name( smspec_node , lgr ); - smspec_node_set_wgname( smspec_node , wgname ); - smspec_node_set_lgr_ijk( smspec_node , lgr_i, lgr_j , lgr_k ); - initOK = wgnameOK; + case(ECL_SMSPEC_WELL_VAR): + /* Well variable : WGNAME */ + break; + case(ECL_SMSPEC_SEGMENT_VAR): + set_num( grid_dims , num ); + break; + case(ECL_SMSPEC_FIELD_VAR): + /* Field variable : */ + /* Fully initialized with the smspec_common_init() function */ + break; + case(ECL_SMSPEC_REGION_VAR): + /* Region variable : NUM */ + set_num( grid_dims , num ); + break; + case(ECL_SMSPEC_REGION_2_REGION_VAR): + /* Region 2 region variable : NUM */ + set_num( grid_dims , num ); + break; + case(ECL_SMSPEC_BLOCK_VAR): + /* A block variable : NUM*/ + set_num( grid_dims , num ); + break; + case(ECL_SMSPEC_MISC_VAR): + /* Misc variable : */ + + /* + For some keywords the SMSPEC files generated by Eclipse have a + non zero NUMS value although; it seems that value is required + for the generatd summaryfiles to display nicely in + e.g. S3GRAF. + */ + + if (this->keyword == std::string(SMSPEC_TIME_KEYWORD)) + set_num( grid_dims , SMSPEC_TIME_NUMS_VALUE ); + + if (this->keyword == std::string(SMSPEC_YEARS_KEYWORD)) + set_num( grid_dims , SMSPEC_YEARS_NUMS_VALUE ); + + break; + case(ECL_SMSPEC_AQUIFER_VAR): + set_num( grid_dims , num ); break; default: - util_abort("%s: internal error: in LGR function with non-LGR keyword:%s \n",__func__ , keyword); + throw std::invalid_argument("Should not be here ... "); + break; + } + set_gen_keys( key_join_string ); +} + +smspec_node::smspec_node( int param_index_, + const char * keyword_ , + const char * wgname_ , + const char * unit_ , + const char * lgr_ , + int lgr_i, int lgr_j , int lgr_k, + float default_value_, + const char * key_join_string_) { + + this->var_type = this->valid_type(keyword_, wgname_, -1); + if (this->var_type == ECL_SMSPEC_INVALID_VAR) + throw std::invalid_argument("Could not construct smspec_node from this input."); + + this->params_index = param_index_; + this->default_value = default_value_; + this->keyword = keyword_; + this->wgname = wgname_; + this->unit = unit_; + this->rate_variable = smspec_node_identify_rate(this->keyword.c_str()); + this->total_variable = smspec_node_identify_total(this->keyword.c_str(), this->var_type); + this->historical = (this->keyword.back() == 'H'); + this->lgr_name = lgr_; + this->num = nums_unused; + + switch (this->var_type) { + case(ECL_SMSPEC_LOCAL_WELL_VAR): + break; + case(ECL_SMSPEC_LOCAL_BLOCK_VAR): + set_lgr_ijk( lgr_i, lgr_j , lgr_k ); + break; + case(ECL_SMSPEC_LOCAL_COMPLETION_VAR): + set_lgr_ijk( lgr_i, lgr_j , lgr_k ); + break; + default: + throw std::invalid_argument("Should not be here .... "); } - if (initOK) - smspec_node_set_gen_keys( smspec_node , key_join_string ); + set_gen_keys( key_join_string_ ); } -smspec_node_type * smspec_node_alloc_lgr( ecl_smspec_var_type var_type , - const char * wgname , - const char * keyword , - const char * unit , - const char * lgr , - const char * key_join_string , - int lgr_i, int lgr_j , int lgr_k, - int param_index , float default_value) { - - smspec_node_type * smspec_node = smspec_node_alloc_new( param_index , default_value ); - smspec_node_init_lgr( smspec_node , var_type , wgname , keyword , unit , lgr , key_join_string , lgr_i, lgr_j , lgr_k); - return smspec_node; -} - -smspec_node_type* smspec_node_alloc_copy( const smspec_node_type* node ) { - - if( !node ) return NULL; - - { - smspec_node_type * copy = new smspec_node_type(); - UTIL_TYPE_ID_INIT( copy, SMSPEC_TYPE_ID ); - copy->gen_key1 = node->gen_key1; - copy->gen_key2 = node->gen_key2; - copy->var_type = node->var_type; - copy->wgname = node->wgname; - copy->keyword = node->keyword; - copy->unit = node->unit; - copy->num = node->num; - copy->ijk = node->ijk; - copy->lgr_name = node->lgr_name; - copy->lgr_ijk = node->lgr_ijk; - - copy->rate_variable = node->rate_variable; - copy->total_variable = node->total_variable; - copy->historical = node->historical; - copy->params_index = node->params_index; - copy->default_value = node->default_value; - return copy; - } -} - -void smspec_node_free( smspec_node_type * index ) { - delete index; -} - -void smspec_node_free__( void * arg ) { - smspec_node_type * node = smspec_node_safe_cast( arg ); - smspec_node_free( node ); -} - /*****************************************************************/ - - -int smspec_node_get_params_index( const smspec_node_type * smspec_node ) { - return smspec_node->params_index; +int smspec_node::get_params_index() const { + return this->params_index; } - -void smspec_node_set_params_index( smspec_node_type * smspec_node , int params_index) { - smspec_node->params_index = params_index; -} +// void smspec_node::set_params_index( int params_index_) { + // this->params_index = params_index_; +// } namespace { @@ -873,69 +979,60 @@ namespace { } -const char * smspec_node_get_gen_key1( const smspec_node_type * smspec_node) { - return get_cstring( smspec_node->gen_key1 ); + +const char * smspec_node::get_gen_key1() const { + return get_cstring( this->gen_key1 ); } -const char * smspec_node_get_gen_key2( const smspec_node_type * smspec_node) { - return get_cstring( smspec_node->gen_key2 ); +const char * smspec_node::get_gen_key2() const { + return get_cstring( this->gen_key2 ); } - -const char * smspec_node_get_wgname( const smspec_node_type * smspec_node) { - return get_cstring( smspec_node->wgname ); +const char * smspec_node::get_wgname() const { + return get_cstring( this->wgname ); } -const char * smspec_node_get_keyword( const smspec_node_type * smspec_node) { - return get_cstring( smspec_node->keyword ); +const char * smspec_node::get_keyword() const { + return get_cstring( this->keyword ); } - - -ecl_smspec_var_type smspec_node_get_var_type( const smspec_node_type * smspec_node) { - return smspec_node->var_type; +ecl_smspec_var_type smspec_node::get_var_type() const { + return this->var_type; } -int smspec_node_get_num( const smspec_node_type * smspec_node) { - return smspec_node->num; +int smspec_node::get_num() const { + return this->num; } -bool smspec_node_is_rate( const smspec_node_type * smspec_node ) { - return smspec_node->rate_variable; +bool smspec_node::is_rate() const { + return this->rate_variable; } - -bool smspec_node_is_total( const smspec_node_type * smspec_node ){ - return smspec_node->total_variable; +bool smspec_node::is_total() const { + return this->total_variable; } -bool smspec_node_is_historical( const smspec_node_type * smspec_node ){ - return smspec_node->historical; +bool smspec_node::is_historical() const { + return this->historical; } -const char * smspec_node_get_unit( const smspec_node_type * smspec_node) { - return smspec_node->unit.c_str(); -} - -void smspec_node_set_unit( smspec_node_type * smspec_node , const char * unit) { - // ECLIPSE Standard: Max eight characters - everything beyond is silently dropped - std::string tmp = unit; - smspec_node->unit = tmp.substr(0,8); +const char * smspec_node::get_unit() const { + return this->unit.c_str(); } // Will be garbage for smspec_nodes which do not have i,j,k -const int* smspec_node_get_ijk( const smspec_node_type * smspec_node ) { - return smspec_node->ijk.data(); +const std::array& smspec_node::get_ijk() const { + return this->ijk; } // Will be NULL for smspec_nodes which are not related to an LGR. -const char* smspec_node_get_lgr_name( const smspec_node_type * smspec_node ) { - return smspec_node->lgr_name.c_str(); +const char * smspec_node::get_lgr_name() const { + return get_cstring(this->lgr_name); } // Will be garbage for smspec_nodes which are not related to an LGR. -const int* smspec_node_get_lgr_ijk( const smspec_node_type * smspec_node ) { - return smspec_node->lgr_ijk.data(); +const std::array& smspec_node::get_lgr_ijk() const { + return this->lgr_ijk; } /* @@ -943,41 +1040,41 @@ const int* smspec_node_get_lgr_ijk( const smspec_node_type * smspec_node ) { of type ECL_SMSPEC_REGION_2_REGION_VAR. */ -int smspec_node_get_R1( const smspec_node_type * smspec_node ) { - if (smspec_node->var_type == ECL_SMSPEC_REGION_2_REGION_VAR) { +int smspec_node::get_R1() const { + if (var_type == ECL_SMSPEC_REGION_2_REGION_VAR) { int r1,r2; - smspec_node_decode_R1R2( smspec_node , &r1 , &r2); + decode_R1R2( &r1 , &r2); return r1; } else return -1; } -int smspec_node_get_R2( const smspec_node_type * smspec_node ) { - if (smspec_node->var_type == ECL_SMSPEC_REGION_2_REGION_VAR) { +int smspec_node::get_R2() const { + if (var_type == ECL_SMSPEC_REGION_2_REGION_VAR) { int r1,r2; - smspec_node_decode_R1R2( smspec_node , &r1 , &r2); + decode_R1R2( &r1 , &r2); return r2; } else return -1; } -bool smspec_node_need_nums( const smspec_node_type * smspec_node ) { +bool smspec_node::need_nums() const { /* Check if this node needs the nums field; if at least one of the nodes need the NUMS field must be stored when writing a SMSPEC file. */ { - if (smspec_node->var_type == ECL_SMSPEC_COMPLETION_VAR || - smspec_node->var_type == ECL_SMSPEC_SEGMENT_VAR || - smspec_node->var_type == ECL_SMSPEC_REGION_VAR || - smspec_node->var_type == ECL_SMSPEC_REGION_2_REGION_VAR || - smspec_node->var_type == ECL_SMSPEC_BLOCK_VAR || - smspec_node->var_type == ECL_SMSPEC_AQUIFER_VAR) + if (this->var_type == ECL_SMSPEC_COMPLETION_VAR || + this->var_type == ECL_SMSPEC_SEGMENT_VAR || + this->var_type == ECL_SMSPEC_REGION_VAR || + this->var_type == ECL_SMSPEC_REGION_2_REGION_VAR || + this->var_type == ECL_SMSPEC_BLOCK_VAR || + this->var_type == ECL_SMSPEC_AQUIFER_VAR) return true; else { - if (smspec_node->num == SMSPEC_NUMS_INVALID) + if (this->num == SMSPEC_NUMS_INVALID) return false; else return true; @@ -986,46 +1083,22 @@ bool smspec_node_need_nums( const smspec_node_type * smspec_node ) { } -void smspec_node_fprintf( const smspec_node_type * smspec_node , FILE * stream) { - fprintf(stream, "KEYWORD: %s \n",smspec_node->keyword.c_str()); - fprintf(stream, "WGNAME : %s \n",smspec_node->wgname.c_str()); - fprintf(stream, "UNIT : %s \n",smspec_node->unit.c_str()); - fprintf(stream, "TYPE : %d \n",smspec_node->var_type); - fprintf(stream, "NUM : %d \n\n",smspec_node->num); -} - - -static bool smspec_node_equal_MISC( const smspec_node_type * node1, const smspec_node_type * node2) { - return node1->keyword == node2->keyword; +void smspec_node::fprintf__( FILE * stream) const { + fprintf(stream, "KEYWORD: %s \n", this->keyword.c_str()); + fprintf(stream, "WGNAME : %s \n", this->wgname.c_str()); + fprintf(stream, "UNIT : %s \n", this->unit.c_str()); + fprintf(stream, "TYPE : %d \n", this->var_type); + fprintf(stream, "NUM : %d \n\n", this->num); } +namespace { /* MISC variables are generally sorted to the end of the list, but some special case variables come at the very beginning. */ -static int smspec_node_cmp_MISC( const smspec_node_type * node1, const smspec_node_type * node2) { - static const std::set early_vars = {"TIME", "DAYS", "DAY", "MONTH", "YEAR", "YEARS"}; - - if (smspec_node_equal_MISC( node1, node2) ) - return 0; - - bool node1_early = !( early_vars.find(node1->keyword) == early_vars.end() ); - bool node2_early = !( early_vars.find(node2->keyword) == early_vars.end() ); - - - if (node1_early && !node2_early) - return -1; - - if (!node1_early && node2_early) - return 1; - - return node1->keyword.compare(node2->keyword); -} - - -static int int_cmp(int v1, int v2) { +int int_cmp(int v1, int v2) { if (v1 < v2) return -1; @@ -1035,174 +1108,354 @@ static int int_cmp(int v1, int v2) { return 0; } -static int smspec_node_cmp_LGRIJK( const smspec_node_type * node1, const smspec_node_type * node2) { - int i_cmp = int_cmp( node1->lgr_ijk[0] , node2->lgr_ijk[0]); + +int cmp_MISC( const smspec_node& node1, const smspec_node& node2) { + static const std::set early_vars = {"TIME", "DAYS", "DAY", "MONTH", "YEAR", "YEARS"}; + + if (&node1 == &node2) + return 0; + + bool node1_early = !( early_vars.find(node1.get_keyword()) == early_vars.end() ); + bool node2_early = !( early_vars.find(node2.get_keyword()) == early_vars.end() ); + + + if (node1_early && !node2_early) + return -1; + + if (!node1_early && node2_early) + return 1; + + return strcmp(node1.get_keyword(), node2.get_keyword()); +} + + +int cmp_LGRIJK( const smspec_node& node1, const smspec_node& node2) { + const auto& ijk1 = node1.get_lgr_ijk(); + const auto& ijk2 = node2.get_lgr_ijk(); + + int i_cmp = int_cmp( ijk1[0] , ijk2[0]); if (i_cmp != 0) return i_cmp; - int j_cmp = int_cmp( node1->lgr_ijk[1] , node2->lgr_ijk[1]); + int j_cmp = int_cmp(ijk1[1] , ijk2[1]); if (j_cmp != 0) return j_cmp; - return int_cmp( node1->lgr_ijk[2] , node2->lgr_ijk[2]); + return int_cmp( ijk1[2] , ijk2[2]); } - -static int smspec_node_cmp_KEYWORD_LGR_LGRIJK( const smspec_node_type * node1, const smspec_node_type * node2) { - int keyword_cmp = node1->keyword.compare(node2->keyword); +int cmp_KEYWORD_LGR_LGRIJK( const smspec_node& node1, const smspec_node& node2) { + int keyword_cmp = strcmp(node1.get_keyword(), node2.get_keyword()); if (keyword_cmp != 0) return keyword_cmp; - int lgr_cmp = node1->lgr_name.compare( node2->lgr_name ); + int lgr_cmp = strcmp(node1.get_lgr_name(), node2.get_lgr_name()); if (lgr_cmp != 0) return lgr_cmp; - return smspec_node_cmp_LGRIJK( node1, node2); + return cmp_LGRIJK( node1, node2); } - -static int smspec_node_cmp_KEYWORD_WGNAME_NUM( const smspec_node_type * node1, const smspec_node_type * node2) { - int keyword_cmp = node1->keyword.compare(node2->keyword); +int cmp_KEYWORD_WGNAME_NUM(const smspec_node& node1, const smspec_node& node2) { + int keyword_cmp = strcmp(node1.get_keyword(), node2.get_keyword()); if (keyword_cmp != 0) return keyword_cmp; - int wgname_cmp = node1->wgname.compare(node2->wgname); + int wgname_cmp = strcmp(node1.get_wgname(), node2.get_wgname()); if (wgname_cmp != 0) return wgname_cmp; - return int_cmp( node1->num , node2->num); + return int_cmp( node1.get_num() , node2.get_num()); } -static int smspec_node_cmp_KEYWORD_WGNAME_LGR( const smspec_node_type * node1, const smspec_node_type * node2) { - int keyword_cmp = node1->keyword.compare(node2->keyword); +int cmp_KEYWORD_WGNAME_LGR( const smspec_node& node1, const smspec_node& node2) { + int keyword_cmp = strcmp(node1.get_keyword(), node2.get_keyword()); if (keyword_cmp != 0) return keyword_cmp; - int wgname_cmp = node1->wgname.compare(node2->wgname); + int wgname_cmp = strcmp(node1.get_wgname(), node2.get_wgname()); if (wgname_cmp != 0) return wgname_cmp; - return node1->lgr_name.compare(node2->lgr_name); + return strcmp(node1.get_lgr_name(), node2.get_lgr_name()); } - -static int smspec_node_cmp_KEYWORD_WGNAME_LGR_LGRIJK( const smspec_node_type * node1, const smspec_node_type * node2) { - int keyword_cmp = node1->keyword.compare(node2->keyword); +int cmp_KEYWORD_WGNAME_LGR_LGRIJK( const smspec_node& node1, const smspec_node& node2) { + int keyword_cmp = strcmp(node1.get_keyword(), node2.get_keyword()); if (keyword_cmp != 0) return keyword_cmp; - int wgname_cmp = node1->wgname.compare(node2->wgname); + int wgname_cmp = strcmp(node1.get_wgname(), node2.get_wgname()); if (wgname_cmp != 0) return wgname_cmp; - int lgr_cmp = node1->lgr_name.compare(node2->lgr_name); + int lgr_cmp = strcmp(node1.get_lgr_name(), node2.get_lgr_name()); if (lgr_cmp != 0) return lgr_cmp; - return smspec_node_cmp_LGRIJK( node1, node2); + return cmp_LGRIJK( node1, node2); } - - - -static int smspec_node_cmp_KEYWORD_WGNAME( const smspec_node_type * node1, const smspec_node_type * node2) { - int keyword_cmp = node1->keyword.compare(node2->keyword); +int cmp_KEYWORD_WGNAME( const smspec_node& node1, const smspec_node& node2) { + int keyword_cmp = strcmp(node1.get_keyword(), node2.get_keyword()); if (keyword_cmp != 0) return keyword_cmp; - if (IS_DUMMY_WELL( node1->wgname.c_str() )) { - if (IS_DUMMY_WELL( node2->wgname.c_str() )) + if (IS_DUMMY_WELL( node1.get_wgname() )) { + if (IS_DUMMY_WELL( node2.get_wgname() )) return 0; else return 1; } - if (IS_DUMMY_WELL( node2->wgname.c_str() )) + if (IS_DUMMY_WELL( node2.get_wgname() )) return -1; - return node1->wgname.compare(node2->wgname); + return strcmp(node1.get_wgname(), node2.get_wgname()); +} + +int cmp_KEYWORD( const smspec_node& node1, const smspec_node& node2) { + return strcmp(node1.get_keyword(), node2.get_keyword()); } -static int smspec_node_cmp_KEYWORD_NUM( const smspec_node_type * node1, const smspec_node_type * node2) { - int keyword_cmp = node1->keyword.compare(node2->keyword); + +int cmp_KEYWORD_NUM( const smspec_node& node1, const smspec_node& node2) { + int keyword_cmp = strcmp(node1.get_keyword(), node2.get_keyword()); if (keyword_cmp != 0) return keyword_cmp; - return int_cmp( node1->num , node2->num); + return int_cmp( node1.get_num() , node2.get_num()); } -static int smspec_node_cmp_KEYWORD( const smspec_node_type * node1, const smspec_node_type * node2) { - return node1->keyword.compare(node2->keyword); -} - -static int smspec_node_cmp_key1( const smspec_node_type * node1, const smspec_node_type * node2) { - if (node1->gen_key1.empty()) { - if (node2->gen_key1.empty()) +int cmp_key1( const smspec_node& node1, const smspec_node& node2) { + if (node1.get_gen_key1() == NULL) { + if (node2.get_gen_key1() == NULL) return 0; else return -1; - } else if (node2->gen_key1.empty()) { + } else if (node2.get_gen_key1() == NULL) return 1; - } - return util_strcmp_int( node1->gen_key1.c_str() , node2->gen_key1.c_str() ); + + return util_strcmp_int( node1.get_gen_key1() , node2.get_gen_key1() ); +} } - -int smspec_node_cmp( const smspec_node_type * node1, const smspec_node_type * node2) { +int smspec_node::cmp(const smspec_node& node1, const smspec_node& node2) { /* 1: Start with special casing for the MISC variables. */ - if ((node1->var_type == ECL_SMSPEC_MISC_VAR) || (node2->var_type == ECL_SMSPEC_MISC_VAR)) - return smspec_node_cmp_MISC( node1 , node2 ); + if ((node1.var_type == ECL_SMSPEC_MISC_VAR) || (node2.var_type == ECL_SMSPEC_MISC_VAR)) + return cmp_MISC( node1 , node2 ); /* 2: Sort according to variable type */ - if (node1->var_type < node2->var_type) + if (node1.var_type < node2.var_type) return -1; - if (node1->var_type > node2->var_type) + if (node1.var_type > node2.var_type) return 1; /* 3: Internal sort of variables of the same type. */ - switch (node1->var_type) { + switch (node1.var_type) { case( ECL_SMSPEC_FIELD_VAR): - return smspec_node_cmp_KEYWORD( node1, node2); + return cmp_KEYWORD( node1, node2); case( ECL_SMSPEC_WELL_VAR): case( ECL_SMSPEC_GROUP_VAR): - return smspec_node_cmp_KEYWORD_WGNAME( node1, node2); + return cmp_KEYWORD_WGNAME( node1, node2); case( ECL_SMSPEC_BLOCK_VAR): case( ECL_SMSPEC_REGION_VAR): case( ECL_SMSPEC_REGION_2_REGION_VAR): case( ECL_SMSPEC_AQUIFER_VAR): - return smspec_node_cmp_KEYWORD_NUM( node1, node2); + return cmp_KEYWORD_NUM( node1, node2); case( ECL_SMSPEC_COMPLETION_VAR): case( ECL_SMSPEC_SEGMENT_VAR): - return smspec_node_cmp_KEYWORD_WGNAME_NUM( node1, node2); + return cmp_KEYWORD_WGNAME_NUM( node1, node2); case (ECL_SMSPEC_NETWORK_VAR): - return smspec_node_cmp_key1( node1, node2); + return cmp_key1( node1, node2); case( ECL_SMSPEC_LOCAL_BLOCK_VAR): - return smspec_node_cmp_KEYWORD_LGR_LGRIJK( node1, node2); + return cmp_KEYWORD_LGR_LGRIJK( node1, node2); case( ECL_SMSPEC_LOCAL_WELL_VAR): - return smspec_node_cmp_KEYWORD_WGNAME_LGR( node1, node2); + return cmp_KEYWORD_WGNAME_LGR( node1, node2); case( ECL_SMSPEC_LOCAL_COMPLETION_VAR): - return smspec_node_cmp_KEYWORD_WGNAME_LGR_LGRIJK( node1, node2); + return cmp_KEYWORD_WGNAME_LGR_LGRIJK( node1, node2); default: /* Should not really end up here. */ - return smspec_node_cmp_key1( node1, node2); + return cmp_key1( node1, node2); } } -int smspec_node_cmp__( const void * node1, const void * node2) { - return smspec_node_cmp( smspec_node_safe_cast_const( node1 ), - smspec_node_safe_cast_const( node2 )); +int smspec_node::cmp(const smspec_node& node2) const { + return smspec_node::cmp(*this, node2); +} + + +} // end namespace ecl + +/************************************** OLD API functions ***********************''''' */ + + +void smspec_node_free( void * index ) { + delete static_cast(index); +} + +void smspec_node_free__( void * arg ) { + smspec_node_free( arg ); +} + +float smspec_node_get_default( const void * smspec_node ) { + return static_cast(smspec_node)->get_default(); +} + +int smspec_node_get_params_index( const void * smspec_node ) { + return static_cast(smspec_node)->get_params_index(); +} + +// void smspec_node_set_params_index( void * smspec_node , int params_index) { + // static_cast(smspec_node)->set_params_index( params_index ); +// } + +const char * smspec_node_get_gen_key1( const void * smspec_node) { + return static_cast(smspec_node)->get_gen_key1(); +} + +const char * smspec_node_get_gen_key2( const void * smspec_node) { + return static_cast(smspec_node)->get_gen_key2(); +} + +const char * smspec_node_get_wgname( const void * smspec_node) { + return static_cast(smspec_node)->get_wgname(); +} + +const char * smspec_node_get_keyword( const void * smspec_node) { + return static_cast(smspec_node)->get_keyword( ); +} + +ecl_smspec_var_type smspec_node_get_var_type( const void * smspec_node) { + return static_cast(smspec_node)->get_var_type(); +} + +int smspec_node_get_num( const void * smspec_node) { + return static_cast(smspec_node)->get_num(); +} + +bool smspec_node_is_rate( const void * smspec_node ) { + return static_cast(smspec_node)->is_rate(); +} + +bool smspec_node_is_total( const void * smspec_node ){ + return static_cast(smspec_node)->is_total(); +} + +bool smspec_node_is_historical( const void * smspec_node ){ + return static_cast(smspec_node)->is_historical(); +} + +const char * smspec_node_get_unit( const void * smspec_node) { + return static_cast(smspec_node)->get_unit(); +} + +// Will be garbage for smspec_nodes which do not have i,j,k +const int* smspec_node_get_ijk( const void * smspec_node ) { + return static_cast(smspec_node)->get_ijk().data(); +} + +// Will be NULL for smspec_nodes which are not related to an LGR. +const char* smspec_node_get_lgr_name( const void * smspec_node ) { + return static_cast(smspec_node)->get_lgr_name(); +} + + +// Will be garbage for smspec_nodes which are not related to an LGR. +const int* smspec_node_get_lgr_ijk( const void * smspec_node ) { + return static_cast(smspec_node)->get_lgr_ijk().data(); +} + +int smspec_node_get_R1( const void * smspec_node ) { + return static_cast(smspec_node)->get_R1(); +} + + +int smspec_node_get_R2( const void * smspec_node ) { + return static_cast(smspec_node)->get_R2(); +} + +bool smspec_node_need_nums( const void * smspec_node ) { + return static_cast(smspec_node)->need_nums(); +} + +void smspec_node_fprintf( const void * smspec_node , FILE * stream) { + static_cast(smspec_node)->fprintf__(stream); +} + +int smspec_node_cmp( const void * node1, const void * node2) { + return ecl::smspec_node::cmp(static_cast(node1), static_cast(node2)); +} + +int smspec_node_cmp__( const void * node1, const void * node2) { + return smspec_node_cmp(node1, node2); +} + + +void * smspec_node_alloc( int param_index, + const char * keyword , + const char * wgname, + int num, + const char * unit , + const int grid_dims[3] , + float default_value, + const char * key_join_string) { + + ecl::smspec_node * node = NULL; + try { + node = new ecl::smspec_node(param_index, + keyword, + wgname, + num, + unit, + grid_dims, + default_value, + key_join_string); + } + catch (const std::invalid_argument& e) { + node = NULL; + } + return node; +} + + +void * smspec_node_alloc_lgr( ecl_smspec_var_type var_type , + const char * wgname , + const char * keyword , + const char * unit , + const char * lgr , + const char * key_join_string , + int lgr_i, int lgr_j , int lgr_k, + int param_index , float default_value) { + + return new ecl::smspec_node( param_index, keyword, wgname, unit, lgr, lgr_i, lgr_j, lgr_k, default_value, key_join_string); +} + + + +bool smspec_node_equal( const void * node1, const void * node2) { + return ecl::smspec_node::cmp( static_cast(node1) , static_cast(node2) ) == 0; +} + + +bool smspec_node_gt( const void * node1, const void * node2) { + return ecl::smspec_node::cmp( static_cast(node1) , static_cast(node2) ) > 0; +} + +bool smspec_node_lt( const void * node1, const void * node2) { + return ecl::smspec_node::cmp( static_cast(node1) , static_cast(node2) ) < 0; } diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_alloc_cpgrid.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_alloc_cpgrid.cpp index f3c1ac4e44..2a06c3cc88 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_alloc_cpgrid.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_alloc_cpgrid.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2017 Statoil ASA, Norway. + Copyright (C) 2017 Equinor ASA, Norway. The file 'ecl_alloc_cpgrid.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_alloc_grid_dxv_dyv_dzv.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_alloc_grid_dxv_dyv_dzv.cpp index 9992680f74..7f7ff44104 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_alloc_grid_dxv_dyv_dzv.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_alloc_grid_dxv_dyv_dzv.cpp @@ -1,6 +1,6 @@ /* Copyright (C) 2013 Andreas Lauser - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'ecl_alloc_grid_dxv_dyv_dzv.c' is part of ERT - Ensemble based Reservoir Tool. @@ -55,6 +55,7 @@ void test_grid() { } } } + ecl_grid_free( ecl_grid ); } int main(int argc , char ** argv) { diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_coarse_test.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_coarse_test.cpp index d1882092cd..b2c36fbb22 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_coarse_test.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_coarse_test.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Statoil ASA, Norway. + Copyright (C) 2012 Equinor ASA, Norway. The file 'ecl_coarse_test.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_dualp.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_dualp.cpp index a26d38b863..35b1860c1e 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_dualp.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_dualp.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'ecl_dualp.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_fault_block_collection_statoil.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_fault_block_collection_equinor.cpp similarity index 95% rename from ThirdParty/Ert/lib/ecl/tests/ecl_fault_block_collection_statoil.cpp rename to ThirdParty/Ert/lib/ecl/tests/ecl_fault_block_collection_equinor.cpp index 73bd471390..a40dbaac1f 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_fault_block_collection_statoil.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_fault_block_collection_equinor.cpp @@ -1,7 +1,7 @@ /* - Copyright (C) 2014 Statoil ASA, Norway. + Copyright (C) 2014 Equinor ASA, Norway. - The file 'ecl_fault_block_collection_statoil.c' is part of ERT - Ensemble based Reservoir Tool. + The file 'ecl_fault_block_collection_equinor.c' is part of ERT - Ensemble based Reservoir Tool. ERT is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_fault_block_layer.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_fault_block_layer.cpp index d8de3438af..e1be64668e 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_fault_block_layer.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_fault_block_layer.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2014 Statoil ASA, Norway. + Copyright (C) 2014 Equinor ASA, Norway. The file 'ecl_fault_block_layer.c' is part of ERT - Ensemble based Reservoir Tool. @@ -98,6 +98,7 @@ void test_trace_edge( const ecl_grid_type * grid) { test_assert_int_equal( 1 , int_vector_size( cell_list )); test_assert_int_equal( 0 , int_vector_iget( cell_list , 0)); + fault_block_layer_free(layer); int_vector_free( cell_list ); double_vector_free( x_list ); double_vector_free( y_list ); diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_fault_block_layer_statoil.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_fault_block_layer_equinor.cpp similarity index 95% rename from ThirdParty/Ert/lib/ecl/tests/ecl_fault_block_layer_statoil.cpp rename to ThirdParty/Ert/lib/ecl/tests/ecl_fault_block_layer_equinor.cpp index 6e2590397a..a7e0f1e18f 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_fault_block_layer_statoil.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_fault_block_layer_equinor.cpp @@ -1,7 +1,7 @@ /* - Copyright (C) 2014 Statoil ASA, Norway. + Copyright (C) 2014 Equinor ASA, Norway. - The file 'ecl_fault_block_layer_statoil.c' is part of ERT - Ensemble based Reservoir Tool. + The file 'ecl_fault_block_layer_equinor.c' is part of ERT - Ensemble based Reservoir Tool. ERT is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_file.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_file.cpp index c680e3d10e..951fe544f6 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_file.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_file.cpp @@ -1,6 +1,6 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'ecl_file.c' is part of ERT - Ensemble based Reservoir Tool. @@ -31,7 +31,7 @@ #include void test_writable(size_t data_size) { - test_work_area_type * work_area = test_work_area_alloc("ecl_file_writable"); + ecl::util::TestArea ta("file_writable"); const char * data_file_name = "test_file"; ecl_kw_type * kw = ecl_kw_alloc("TEST_KW", data_size, ECL_INT); @@ -54,11 +54,10 @@ void test_writable(size_t data_size) { } ecl_kw_free(kw); - test_work_area_free( work_area ); } void test_truncated() { - test_work_area_type * work_area = test_work_area_alloc("ecl_file_truncated" ); + ecl::util::TestArea ta("truncate_file"); int num_kw; { ecl_grid_type * grid = ecl_grid_alloc_rectangular(20,20,20,1,1,1,NULL); @@ -69,6 +68,7 @@ void test_truncated() { ecl_file_type * ecl_file = ecl_file_open("TEST.EGRID" , 0 ); test_assert_true( ecl_file_is_instance( ecl_file ) ); num_kw = ecl_file_get_size( ecl_file ); + test_assert_int_equal( ecl_file_get_num_distinct_kw( ecl_file ), 11); ecl_file_close( ecl_file ); } @@ -83,7 +83,6 @@ void test_truncated() { test_assert_true( ecl_file_get_size( ecl_file) < num_kw ); ecl_file_close( ecl_file ); } - test_work_area_free( work_area ); } diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_file_statoil.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_file_equinor.cpp similarity index 90% rename from ThirdParty/Ert/lib/ecl/tests/ecl_file_statoil.cpp rename to ThirdParty/Ert/lib/ecl/tests/ecl_file_equinor.cpp index 13de6fcf40..3d496444de 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_file_statoil.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_file_equinor.cpp @@ -1,8 +1,8 @@ /* - Copyright (C) 2017 Statoil ASA, Norway. + Copyright (C) 2017 Equinor ASA, Norway. - The file 'ecl_file_statoil.c' is part of ERT - Ensemble based Reservoir Tool. + The file 'ecl_file_equinor.c' is part of ERT - Ensemble based Reservoir Tool. ERT is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -108,10 +108,10 @@ void test_close_stream1(const char * src_file , const char * target_file ) { void test_writable(const char * src_file ) { - test_work_area_type * work_area = test_work_area_alloc("ecl_file_writable" ); + ecl::util::TestArea ta("file_writable"); char * fname = util_split_alloc_filename( src_file ); - test_work_area_copy_file( work_area , src_file ); + ta.copy_file(src_file); { test_flags( fname ); ecl_file_type * ecl_file = ecl_file_open( fname , ECL_FILE_WRITABLE); @@ -127,7 +127,6 @@ void test_writable(const char * src_file ) { swat = ecl_file_iget_named_kw( ecl_file , "SWAT" , 0 ); test_assert_true( util_double_approx_equal( ecl_kw_iget_float( swat , 0 ) , 1000 )); } - test_work_area_free( work_area ); } @@ -138,16 +137,15 @@ int main( int argc , char ** argv) { const char * target_file = argv[2]; { - test_work_area_type * work_area = test_work_area_alloc("ecl_file"); + ecl::util::TestArea ta("file_equinor"); - test_work_area_copy_file( work_area , src_file ); + ta.copy_file( src_file ); test_loadall(src_file , target_file ); test_close_stream1( src_file , target_file); test_close_stream2( src_file , target_file); test_writable( src_file ); - test_work_area_free( work_area ); } exit(0); } diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_file_view.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_file_view.cpp index 9dc7875d7c..7f329c310a 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_file_view.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_file_view.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2017 Statoil ASA, Norway. + Copyright (C) 2017 Equinor ASA, Norway. The file 'ecl_file_view.c' is part of ERT - Ensemble based Reservoir Tool. @@ -59,7 +59,7 @@ void test_create_file_kw() { test_assert_int_equal( ecl_file_kw_get_size( file_kw0 ) , 1000 ); test_assert_true( ecl_type_is_equal( ecl_file_kw_get_data_type( file_kw0 ) , ECL_FLOAT )); { - test_work_area_type * work_area = test_work_area_alloc("file_kw"); + ecl::util::TestArea ta("file_kw"); { FILE * ostream = util_fopen("file_kw" , "w"); ecl_file_kw_fwrite( file_kw0 , ostream ); @@ -101,7 +101,6 @@ void test_create_file_kw() { test_assert_NULL( ecl_file_kw_fread_alloc_multiple( istream , 10)); fclose( istream ); } - test_work_area_free( work_area ); } ecl_file_kw_free( file_kw0 ); ecl_file_kw_free( file_kw1 ); diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_fmt.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_fmt.cpp index 5b04922dce..ea07feae8f 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_fmt.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_fmt.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Statoil ASA, Norway. + Copyright (C) 2012 Equinor ASA, Norway. The file 'ecl_fmt.c' is part of ERT - Ensemble based Reservoir Tool. @@ -25,14 +25,12 @@ #include -void test_content( test_work_area_type * work_area , const char * src_file , bool fmt_file ) { - test_work_area_install_file( work_area , src_file ); +void test_content( const ecl::util::TestArea& ta , const char * src_file , bool fmt_file ) { + ta.copy_file(src_file); { char * base_name; bool fmt; util_alloc_file_components( src_file , NULL , &base_name , NULL); - util_copy_file( src_file , base_name ); - test_assert_true( ecl_util_fmt_file( base_name , &fmt )); test_assert_bool_equal( fmt , fmt_file ); } @@ -41,6 +39,7 @@ void test_content( test_work_area_type * work_area , const char * src_file , boo + void test_small( ) { bool fmt; @@ -56,7 +55,7 @@ void test_small( ) { int main(int argc , char ** argv) { - test_work_area_type * work_area = test_work_area_alloc( "ecl_fmt"); + ecl::util::TestArea ta("ecl_fmt"); { const char * binary_file = argv[1]; const char * text_file = argv[2]; @@ -78,10 +77,9 @@ int main(int argc , char ** argv) { test_assert_false(ecl_util_fmt_file( "TEST_DOES_NOT_EXIST" , &fmt_file )); - test_content( work_area , binary_file , false ); - test_content( work_area , text_file , true ); + test_content( ta , binary_file , false ); + test_content( ta , text_file , true ); test_small( ); } - test_work_area_free( work_area ); exit(0); } diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_fortio.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_fortio.cpp index e18fcd20ae..da7de8e695 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_fortio.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_fortio.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'ecl_fortio.c' is part of ERT - Ensemble based Reservoir Tool. @@ -111,7 +111,7 @@ void test_open_close_read( const char * filename ) { void test_fread_truncated_data() { - test_work_area_type * work_area = test_work_area_alloc("fortio_truncated" ); + ecl::util::TestArea work_area("fortio_truncated"); { const size_t buffer_size = 1000; char * buffer = (char *) util_malloc( buffer_size ); @@ -136,11 +136,10 @@ void test_fread_truncated_data() { } free( buffer ); } - test_work_area_free( work_area ); } void test_fread_truncated_head() { - test_work_area_type * work_area = test_work_area_alloc("fortio_truncated" ); + ecl::util::TestArea work_area("fortio_truncated"); { { FILE * stream = util_fopen("PRESSURE" , "w"); @@ -156,12 +155,11 @@ void test_fread_truncated_head() { fortio_fclose( fortio ); } } - test_work_area_free( work_area ); } void test_fread_truncated_tail() { - test_work_area_type * work_area = test_work_area_alloc("fortio_truncated2" ); + ecl::util::TestArea work_area("fortio_truncated3"); { const size_t buffer_size = 1000; char * buffer = (char *) util_malloc( buffer_size ); @@ -183,12 +181,11 @@ void test_fread_truncated_tail() { } free( buffer ); } - test_work_area_free( work_area ); } void test_fread_invalid_tail() { - test_work_area_type * work_area = test_work_area_alloc("fortio_invalid" ); + ecl::util::TestArea work_area("fortio_invalid"); int record_size = 10; char * buffer = (char *) util_malloc( record_size ); { @@ -215,13 +212,12 @@ void test_fread_invalid_tail() { } free( buffer ); - test_work_area_free( work_area ); } void test_at_eof() { - test_work_area_type * work_area = test_work_area_alloc("fortio_truncated2" ); + ecl::util::TestArea work_area("fortio_truncated3"); { fortio_type * fortio = fortio_open_writer("PRESSURE" , false , true); char * buffer = (char *) util_malloc( 100 ); @@ -242,13 +238,11 @@ void test_at_eof() { fortio_fclose( fortio ); } - - test_work_area_free( work_area ); } void test_fseek() { - test_work_area_type * work_area = test_work_area_alloc("fortio_fseek" ); + ecl::util::TestArea work_area("fortio_fseek"); { fortio_type * fortio = fortio_open_writer("PRESSURE" , false , true); char * buffer = (char *) util_malloc( 100 ); @@ -261,8 +255,6 @@ void test_fseek() { { fortio_type * fortio = fortio_open_reader("PRESSURE" , false , true); - - printf("Starting fssek test \n"); test_assert_true( fortio_fseek( fortio , 0 , SEEK_SET )); test_assert_true( fortio_fseek( fortio , 0 , SEEK_END )); test_assert_false( fortio_fseek( fortio , 100000 , SEEK_END)); @@ -270,14 +262,12 @@ void test_fseek() { fortio_fclose( fortio ); } - - test_work_area_free( work_area ); } void test_write_failure() { - test_work_area_type * work_area = test_work_area_alloc("fortio_fseek" ); + ecl::util::TestArea work_area("fortio_truncated"); { fortio_type * fortio = fortio_open_writer("PRESSURE" , false , true); char * buffer = (char *) util_malloc( 100 ); @@ -292,7 +282,6 @@ void test_write_failure() { test_assert_false( util_file_exists( "PRESSURE")); } - test_work_area_free( work_area ); } @@ -317,10 +306,9 @@ int main( int argc , char ** argv) { test_write( "/tmp/path/does/not/exist" , false ); { - test_work_area_type * work_area = test_work_area_alloc("ecl_fortio.write" ); + ecl::util::TestArea work_area("ecl_fortio_write"); util_make_path("path"); test_write( "path/file.x" , true ); - test_work_area_free( work_area ); } test_write_failure(); diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_get_num_cpu_test.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_get_num_cpu_test.cpp index 3f715b2cd8..c608634367 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_get_num_cpu_test.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_get_num_cpu_test.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Statoil ASA, Norway. + Copyright (C) 2012 Equinor ASA, Norway. The file 'ecl_get_num_cpu_test.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_grid_DEPTHZ.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_grid_DEPTHZ.cpp index 29b14612cb..056eebb750 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_grid_DEPTHZ.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_grid_DEPTHZ.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2014 Statoil ASA, Norway. + Copyright (C) 2014 Equinor ASA, Norway. The file 'ecl_grid_DEPTHZ.c' is part of ERT - Ensemble based Reservoir Tool. @@ -44,15 +44,15 @@ void test_create() { int ny = 100; int nz = 10; - double * DXV = (double *) util_malloc( nx * sizeof * DXV ); - double * DYV = (double *) util_malloc( ny * sizeof * DYV ); + double * DXV = (double *) util_malloc( (nx + 1) * sizeof * DXV ); + double * DYV = (double *) util_malloc( (ny + 1) * sizeof * DYV ); double * DZV = (double *) util_malloc( nz * sizeof * DZV ); double * DEPTHZ = (double *) util_malloc( (nx + 1) * (ny + 1) * sizeof * DEPTHZ); - for (int i=0; i < nx; i++) + for (int i=0; i <= nx; i++) DXV[i] = 1.0 / nx; - for (int j=0; j < ny; j++) + for (int j=0; j <= ny; j++) DYV[j] = 1.0 / ny; for (int k=0; k < nz; k++) diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_grid_add_nnc.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_grid_add_nnc.cpp index d7d9221361..144d8dcc1e 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_grid_add_nnc.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_grid_add_nnc.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2016 Statoil ASA, Norway. + Copyright (C) 2016 Equinor ASA, Norway. The file 'ecl_grid_add_nnc.c' is part of ERT - Ensemble based Reservoir Tool. @@ -60,14 +60,13 @@ void simple_test() { verify_simple_nnc( grid0 ); { - test_work_area_type * test_area = test_work_area_alloc("ecl_grid_nnc"); + ecl::util::TestArea ta("simple_nnc"); ecl_grid_type * grid1; ecl_grid_fwrite_EGRID2( grid0 , "TEST.EGRID" , ECL_METRIC_UNITS); grid1 = ecl_grid_alloc( "TEST.EGRID" ); verify_simple_nnc( grid1 ); ecl_grid_free( grid1 ); - test_work_area_free( test_area ); } ecl_grid_free( grid0 ); } @@ -90,14 +89,13 @@ void overwrite_test() { verify_simple_nnc( grid0 ); { - test_work_area_type * test_area = test_work_area_alloc("ecl_grid_nnc"); + ecl::util::TestArea ta("overwrite"); ecl_grid_type * grid1; ecl_grid_fwrite_EGRID2( grid0 , "TEST.EGRID" , ECL_METRIC_UNITS); grid1 = ecl_grid_alloc( "TEST.EGRID" ); verify_simple_nnc( grid1 ); ecl_grid_free( grid1 ); - test_work_area_free( test_area ); } ecl_grid_free( grid0 ); } @@ -118,15 +116,16 @@ void list_test() { verify_simple_nnc( grid0 ); { - test_work_area_type * test_area = test_work_area_alloc("ecl_grid_nnc"); + ecl::util::TestArea ta("list_test"); ecl_grid_type * grid1; ecl_grid_fwrite_EGRID2( grid0 , "TEST.EGRID" , ECL_METRIC_UNITS); grid1 = ecl_grid_alloc( "TEST.EGRID" ); verify_simple_nnc( grid1 ); ecl_grid_free( grid1 ); - test_work_area_free( test_area ); } + int_vector_free(g1); + int_vector_free(g2); ecl_grid_free( grid0 ); } diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_grid_case.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_grid_case.cpp index 6dcb7f05c2..ca2da22e3f 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_grid_case.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_grid_case.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'ecl_grid_case.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_grid_cell_contains.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_grid_cell_contains.cpp index c44ccbfc2f..bab105c304 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_grid_cell_contains.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_grid_cell_contains.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2014 Statoil ASA, Norway. + Copyright (C) 2014 Equinor ASA, Norway. The file 'ecl_grid_cell_contains.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_grid_cell_contains_wellpath.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_grid_cell_contains_wellpath.cpp index c2eb6d8179..fc11a91c15 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_grid_cell_contains_wellpath.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_grid_cell_contains_wellpath.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2017 Statoil ASA, Norway. + Copyright (C) 2017 Equinor ASA, Norway. The file 'ecl_grid_cell_contains_wellpath.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_grid_copy.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_grid_copy.cpp index b5e69a4eae..37da21546a 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_grid_copy.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_grid_copy.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2014 Statoil ASA, Norway. + Copyright (C) 2014 Equinor ASA, Norway. The file 'ecl_grid_copy.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_grid_copy_statoil.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_grid_copy_equinor.cpp similarity index 91% rename from ThirdParty/Ert/lib/ecl/tests/ecl_grid_copy_statoil.cpp rename to ThirdParty/Ert/lib/ecl/tests/ecl_grid_copy_equinor.cpp index 23182906c3..eafff99257 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_grid_copy_statoil.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_grid_copy_equinor.cpp @@ -1,7 +1,7 @@ /* - Copyright (C) 2014 Statoil ASA, Norway. + Copyright (C) 2014 Equinor ASA, Norway. - The file 'ecl_grid_copy_statoil.c' is part of ERT - Ensemble based Reservoir Tool. + The file 'ecl_grid_copy_equinor.c' is part of ERT - Ensemble based Reservoir Tool. ERT is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_grid_corner.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_grid_corner.cpp index 5b3c2fe044..d651d456e2 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_grid_corner.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_grid_corner.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2014 Statoil ASA, Norway. + Copyright (C) 2014 Equinor ASA, Norway. The file 'ecl_grid_corner.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_grid_create.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_grid_create.cpp index d7d45f32e9..d67b09ebbc 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_grid_create.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_grid_create.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2014 Statoil ASA, Norway. + Copyright (C) 2014 Equinor ASA, Norway. The file 'ecl_grid_create.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_grid_dims.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_grid_dims.cpp index 8658da7089..bff2114681 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_grid_dims.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_grid_dims.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'ecl_grid_dims.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_grid_dx_dy_dz.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_grid_dx_dy_dz.cpp index 542b70b824..35e13dbd8a 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_grid_dx_dy_dz.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_grid_dx_dy_dz.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'ecl_grid_dims.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_grid_export.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_grid_export.cpp index 913269ae36..80dce52d4c 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_grid_export.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_grid_export.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2014 Statoil ASA, Norway. + Copyright (C) 2014 Equinor ASA, Norway. The file 'ecl_grid_export.c' is part of ERT - Ensemble based Reservoir Tool. @@ -154,7 +154,7 @@ void export_mapaxes( const ecl_grid_type * grid , ecl_file_type * ecl_file ) { int main(int argc , char ** argv) { - test_work_area_type * work_area = test_work_area_alloc("grid_export"); + ecl::util::TestArea ta("grid_export"); { const char * test_grid = "TEST.EGRID"; const char * grid_file; @@ -181,5 +181,4 @@ int main(int argc , char ** argv) { ecl_grid_free( ecl_grid ); } } - test_work_area_free( work_area ); } diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_grid_ext_actnum.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_grid_ext_actnum.cpp index 75c497189a..3378bda981 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_grid_ext_actnum.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_grid_ext_actnum.cpp @@ -12,7 +12,7 @@ void test_1() { - test_work_area_type * work_area = test_work_area_alloc("ext_actnum_main_grid"); + ecl::util::TestArea ta("test1"); { const char * filename = "FILE.EGRID"; @@ -41,21 +41,18 @@ void test_1() { std::vector ext_actnum = {0, 1, 0, 1, 1, 1}; ecl_grid_type * grid = ecl_grid_alloc_ext_actnum(filename1, ext_actnum.data()); - test_assert_int_equal( 2, ecl_grid_get_nactive(grid) ); - test_assert_int_equal( 1, ecl_grid_get_nactive_fracture(grid) ); + test_assert_int_equal( 4, ecl_grid_get_nactive(grid) ); + test_assert_int_equal( 0, ecl_grid_get_nactive_fracture(grid) ); test_assert_true( !ecl_grid_cell_active1(grid, 0) ); test_assert_true( !ecl_grid_cell_active1(grid, 2) ); - test_assert_true( !ecl_grid_cell_active1(grid, 3) ); + test_assert_true( ecl_grid_cell_active1(grid, 3) ); test_assert_true( ecl_grid_cell_active1(grid, 4) ); test_assert_true( ecl_grid_cell_active1(grid, 5) ); ecl_grid_free( grid ); } - test_work_area_free( work_area ); - - } diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_grid_fwrite.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_grid_fwrite.cpp index 861edc0c42..d359a41f71 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_grid_fwrite.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_grid_fwrite.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2014 Statoil ASA, Norway. + Copyright (C) 2014 Equinor ASA, Norway. The file 'ecl_kw_fwrite.c' is part of ERT - Ensemble based Reservoir Tool. @@ -37,12 +37,72 @@ void test_fwrite_EGRID(ecl_grid_type * grid ) { test_work_area_free( work_area ); } +namespace { + void test_fwrite_fmt_vs_unfmt( ) { + ecl::util::TestArea ta( "fmt_file" ); + ecl_grid_type * ecl_grid = ecl_grid_alloc_rectangular( 5 , 5 , 5 , 1 , 1 , 1 , nullptr); + + /* .FEGRID -> formatted */ + { + ecl_grid_fwrite_EGRID2( ecl_grid , "CASE.FEGRID" , ECL_METRIC_UNITS ); + test_assert_true( util_fmt_bit8( "CASE.FEGRID" ) ); + } + + /* .EGRID -> unformatted */ + { + ecl_grid_fwrite_EGRID2( ecl_grid , "CASE.EGRID" , ECL_METRIC_UNITS ); + test_assert_false( util_fmt_bit8( "CASE.EGRID" ) ); + } + + /* Unknown -> unformatted */ + { + ecl_grid_fwrite_EGRID2( ecl_grid , "CASE.UNKNOWN" , ECL_METRIC_UNITS ); + test_assert_false( util_fmt_bit8( "CASE.UNKNOWN" ) ); + } + + /* Abuse: .FUNRST -> formatted */ + { + ecl_grid_fwrite_EGRID2( ecl_grid , "CASE.FUNRST" , ECL_METRIC_UNITS ); + test_assert_true( util_fmt_bit8( "CASE.FUNRST" ) ); + } + + /* Abuse: .FSMSPEC -> formatted */ + { + ecl_grid_fwrite_EGRID2( ecl_grid , "CASE.FSMSPEC" , ECL_METRIC_UNITS ); + test_assert_true( util_fmt_bit8( "CASE.FSMSPEC" ) ); + } + + /* Abuse: .F0001 -> formatted */ + { + ecl_grid_fwrite_EGRID2( ecl_grid , "CASE.F0001" , ECL_METRIC_UNITS ); + test_assert_true( util_fmt_bit8( "CASE.F0001" ) ); + } + + /* Abuse: .X1234 -> unformatted */ + { + ecl_grid_fwrite_EGRID2( ecl_grid , "CASE.X1234" , ECL_METRIC_UNITS ); + test_assert_false( util_fmt_bit8( "CASE.X1234" ) ); + } + + /* Abuse: .UNSMRY -> unformatted */ + { + ecl_grid_fwrite_EGRID2( ecl_grid , "CASE.UNSMRY" , ECL_METRIC_UNITS ); + test_assert_false( util_fmt_bit8( "CASE.UNSMRY" ) ); + } + + ecl_grid_free( ecl_grid ); + } +} int main( int argc , char **argv) { - const char * src_file = argv[1]; - ecl_grid_type * grid = ecl_grid_alloc( src_file ); + if (argc > 1) { + const char * src_file = argv[1]; + ecl_grid_type * grid = ecl_grid_alloc( src_file ); - test_fwrite_EGRID( grid ); + test_fwrite_EGRID( grid ); - ecl_grid_free( grid ); + ecl_grid_free( grid ); + } + + test_fwrite_fmt_vs_unfmt( ); } diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_grid_init_fwrite.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_grid_init_fwrite.cpp index dc480232e0..8d6111f125 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_grid_init_fwrite.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_grid_init_fwrite.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2016 Statoil ASA, Norway. + Copyright (C) 2016 Equinor ASA, Norway. This file is part of ERT - Ensemble based Reservoir Tool. @@ -31,7 +31,7 @@ void test_write_depth(const ecl_grid_type * grid) { - test_work_area_type * test_area = test_work_area_alloc("write_depth"); + ecl::util::TestArea ta("write_depth"); { fortio_type * init_file = fortio_open_writer( "INIT" , false , ECL_ENDIAN_FLIP ); ecl_grid_fwrite_depth( grid , init_file , ECL_METRIC_UNITS); @@ -47,12 +47,11 @@ void test_write_depth(const ecl_grid_type * grid) { ecl_file_close(init_file); } - test_work_area_free( test_area ); } void test_write_dims(const ecl_grid_type * grid) { - test_work_area_type * test_area = test_work_area_alloc("write_dims"); + ecl::util::TestArea ta("write_dims"); { fortio_type * init_file = fortio_open_writer( "INIT" , false , ECL_ENDIAN_FLIP ); ecl_grid_fwrite_dims( grid , init_file , ECL_METRIC_UNITS ); @@ -74,7 +73,6 @@ void test_write_dims(const ecl_grid_type * grid) { } ecl_file_close(init_file); } - test_work_area_free( test_area ); } diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_grid_layer_contains.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_grid_layer_contains.cpp index 6af4f412be..5cb968d336 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_grid_layer_contains.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_grid_layer_contains.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2014 Statoil ASA, Norway. + Copyright (C) 2014 Equinor ASA, Norway. The file 'ecl_grid_layer_contains' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_grid_lgr_name.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_grid_lgr_name.cpp index 59d314316f..0055b0a0a3 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_grid_lgr_name.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_grid_lgr_name.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'ecl_grid_lgr_name.c' is part of ERT - Ensemble based Reservoir Tool. @@ -41,8 +41,6 @@ Name ..................: LG003014 Grid nr ...............: 110 - - Name ..................: /private/joaho/ERT/git/ert/test-data/Statoil/ECLIPSE/Troll/MSW_LGR/2BRANCHES-CCEWELLPATH-NEW-SCH-TUNED-AR3.EGRID */ diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_grid_reset_actnum.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_grid_reset_actnum.cpp index c0c39aab37..99d99d26ba 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_grid_reset_actnum.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_grid_reset_actnum.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2014 Statoil ASA, Norway. + Copyright (C) 2014 Equinor ASA, Norway. The file 'ecl_grid_reset_actnum.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_grid_simple.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_grid_simple.cpp index 8d9f9ed5a8..052766aaff 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_grid_simple.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_grid_simple.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'ecl_grid_simple.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_grid_unit_system.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_grid_unit_system.cpp index 2e75a1c59b..b191503ca9 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_grid_unit_system.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_grid_unit_system.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2018 Statoil ASA, Norway. + Copyright (C) 2018 Equinor ASA, Norway. The file 'ecl_grid_unit_system.c' is part of ERT - Ensemble based Reservoir Tool. @@ -52,12 +52,10 @@ void test_GRID(const char * filename, ert_ecl_unit_enum unit_system) { int main(int argc, char **argv) { - test_work_area_type * work_area = test_work_area_alloc("grid_export"); + ecl::util::TestArea ta("grid_unit_system"); test_EGRID("METRIC.EGRID", ECL_METRIC_UNITS); test_EGRID("FIELD.EGRID", ECL_FIELD_UNITS); test_GRID("METRIC.GRID", ECL_METRIC_UNITS); test_GRID("FIELD.GRID", ECL_FIELD_UNITS); - - test_work_area_free(work_area); } diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_grid_volume.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_grid_volume.cpp index eb6feb62d1..393bc3d14a 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_grid_volume.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_grid_volume.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'ecl_grid_volume.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_init_file.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_init_file.cpp index d4dbb4a293..4246bc32eb 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_init_file.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_init_file.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2016 Statoil ASA, Norway. + Copyright (C) 2016 Equinor ASA, Norway. The file 'ecl_init_file.c' is part of ERT - Ensemble based Reservoir Tool. @@ -36,8 +36,8 @@ void test_write_header() { int ny = 10; int nz = 5; + ecl::util::TestArea ta("WRITE_header"); int_vector_type * actnum = int_vector_alloc( nx*ny*nz , 1 ); - test_work_area_type * test_area = test_work_area_alloc( "ecl_init_file" ); time_t start_time = util_make_date_utc(15 , 12 , 2010 ); ecl_grid_type * ecl_grid; @@ -84,7 +84,8 @@ void test_write_header() { ecl_init_file_fwrite_header( f , ecl_grid , NULL , ECL_METRIC_UNITS, 7 , start_time ); fortio_fclose( f ); } - test_work_area_free( test_area ); + ecl_grid_free( ecl_grid ); + int_vector_free( actnum ); } diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_kw_cmp_string.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_kw_cmp_string.cpp index d7d925bc49..ecc411680e 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_kw_cmp_string.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_kw_cmp_string.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'ecl_kw_cmp_string.c' is part of ERT - Ensemble based Reservoir Tool. @@ -39,6 +39,7 @@ void test_cmp_string() { test_assert_false( ecl_kw_icmp_string( ecl_kw , 0 , "")); test_assert_false( ecl_kw_icmp_string( ecl_kw , 0 , "")); + ecl_kw_free(ecl_kw); } diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_kw_equal.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_kw_equal.cpp index 912816025f..231e882468 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_kw_equal.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_kw_equal.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'ecl_kw_equal.c' is part of ERT - Ensemble based Reservoir Tool. @@ -55,12 +55,13 @@ int main(int argc , char ** argv) { test_assert_true( ecl_kw_content_equal( ecl_kw1 , ecl_ikw )); test_assert_false( ecl_kw_content_equal( ecl_kw1 , ecl_fkw )); + + ecl_kw_free(ecl_ikw); + ecl_kw_free(ecl_fkw); } test_assert_true( ecl_kw_data_equal( ecl_kw1 , data )); data[0] = 99; test_assert_false( ecl_kw_data_equal( ecl_kw1 , data )); - - - + ecl_kw_free(ecl_kw1); } diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_kw_fread.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_kw_fread.cpp index 2cf4a24be8..a4badb438b 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_kw_fread.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_kw_fread.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2015 Statoil ASA, Norway. + Copyright (C) 2015 Equinor ASA, Norway. The file 'ecl_kw_init.c' is part of ERT - Ensemble based Reservoir Tool. @@ -45,7 +45,7 @@ void test_truncated(const char * filename , offset_type truncate_size) { void test_fread_alloc() { - test_work_area_type * work_area = test_work_area_alloc("ecl_kw_fread" ); + ecl::util::TestArea ta("fread_alloc"); { ecl_kw_type * kw1 = ecl_kw_alloc( "INT" , 100 , ECL_INT ); int i; @@ -74,11 +74,10 @@ void test_fread_alloc() { } ecl_kw_free( kw1 ); } - test_work_area_free( work_area ); } void test_kw_io_charlength() { - test_work_area_type * work_area = test_work_area_alloc("ecl_kw_io_charlength"); + ecl::util::TestArea ta("io_charlength"); { const char * KW0 = "QWERTYUI"; const char * KW1 = "ABCDEFGHIJTTTTTTTTTTTTTTTTTTTTTTABCDEFGHIJKLMNOP"; @@ -115,13 +114,13 @@ void test_kw_io_charlength() { test_assert_double_equal(ecl_kw_iget_as_double(ecl_kw_in, 0), 0.0); test_assert_double_equal(ecl_kw_iget_as_double(ecl_kw_in, 4), 6.0); + ecl_kw_free(ecl_kw_in); fclose(file); } ecl_kw_free( ecl_kw_out0 ); ecl_kw_free( ecl_kw_out1 ); } - test_work_area_free( work_area ); } diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_kw_grdecl.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_kw_grdecl.cpp index a1b49eb55b..97dd9c7947 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_kw_grdecl.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_kw_grdecl.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'ecl_kw_grdecl.c' is part of ERT - Ensemble based Reservoir Tool. @@ -32,7 +32,7 @@ int main(int argc , char ** argv) { ecl_kw_iset_int(ecl_kw , i , i ); { - test_work_area_type * work_area = test_work_area_alloc("ecl_kw_grdecl"); + ecl::util::TestArea ta("kw_grdecl"); FILE * stream = util_fopen( "FILE.grdecl" , "w"); ecl_kw_fprintf_grdecl(ecl_kw , stream ); @@ -65,7 +65,6 @@ int main(int argc , char ** argv) { ecl_kw_free( ecl_kw2 ); } fclose( stream ); - test_work_area_free( work_area ); } ecl_kw_free( ecl_kw ); diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_kw_init.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_kw_init.cpp index 0f4a883526..16b382a188 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_kw_init.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_kw_init.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'ecl_kw_init.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_layer.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_layer.cpp index ab5d85c6d5..7a0d0ad0d0 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_layer.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_layer.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2014 Statoil ASA, Norway. + Copyright (C) 2014 Equinor ASA, Norway. The file 'ecl_layer.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_layer_statoil.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_layer_equinor.cpp similarity index 96% rename from ThirdParty/Ert/lib/ecl/tests/ecl_layer_statoil.cpp rename to ThirdParty/Ert/lib/ecl/tests/ecl_layer_equinor.cpp index 912248dfd4..a984cb84f8 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_layer_statoil.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_layer_equinor.cpp @@ -1,7 +1,7 @@ /* - Copyright (C) 2014 Statoil ASA, Norway. + Copyright (C) 2014 Equinor ASA, Norway. - The file 'ecl_layer_statoil.c' is part of ERT - Ensemble based Reservoir Tool. + The file 'ecl_layer_equinor.c' is part of ERT - Ensemble based Reservoir Tool. ERT is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_lfs.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_lfs.cpp index 6d2048cfdb..0a6163349a 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_lfs.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_lfs.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'ecl_win64.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_lgr_name.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_lgr_name.cpp index ca798963d8..f45c5d6aec 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_lgr_name.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_lgr_name.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'ecl_lgr_name.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_lgr_test.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_lgr_test.cpp index a585de4fb2..c0807e951e 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_lgr_test.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_lgr_test.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'ecl_lgr_test.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_nnc_data_statoil_root.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_nnc_data_equinor_root.cpp similarity index 97% rename from ThirdParty/Ert/lib/ecl/tests/ecl_nnc_data_statoil_root.cpp rename to ThirdParty/Ert/lib/ecl/tests/ecl_nnc_data_equinor_root.cpp index 784864bf97..f804376366 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_nnc_data_statoil_root.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_nnc_data_equinor_root.cpp @@ -1,7 +1,7 @@ /* - Copyright (C) 2017 Statoil ASA, Norway. + Copyright (C) 2017 Equinor ASA, Norway. - The file 'test_ecl_nnc_data_statoil.c' is part of ERT - Ensemble based Reservoir Tool. + The file 'test_ecl_nnc_data_equinor.c' is part of ERT - Ensemble based Reservoir Tool. ERT is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_nnc_export.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_nnc_export.cpp index 556e2df7a0..ed97f621f9 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_nnc_export.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_nnc_export.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'ecl_nnc_export.c' is part of ERT - Ensemble based Reservoir Tool. @@ -74,8 +74,10 @@ int count_kw_data( const ecl_file_type * file , ecl_grid_type * grid , const cha void test_count(const char * name) { char * grid_file_name = ecl_util_alloc_filename(NULL , name , ECL_EGRID_FILE , false , -1); + char * init_file_name = ecl_util_alloc_filename(NULL , name , ECL_INIT_FILE , false , -1); ecl_grid_type * grid = ecl_grid_alloc( grid_file_name ); ecl_file_type * grid_file = ecl_file_open( grid_file_name , 0 ); + ecl_file_type * init_file = ecl_file_open( init_file_name , 0); int num_nnc = 0; @@ -83,7 +85,7 @@ void test_count(const char * name) { num_nnc += count_kw_data( grid_file , grid , "NNCG" , NULL); num_nnc += count_kw_data( grid_file , grid , "NNA1" , NULL); - test_assert_int_equal( num_nnc , ecl_nnc_export_get_size( grid )); + test_assert_int_equal(num_nnc, ecl_nnc_export_get_size(grid, init_file)); free(grid_file_name); ecl_grid_free( grid ); @@ -97,7 +99,7 @@ void test_nnc_export_missing_TRANX(const char * name ) { if (util_entry_exists(init_file_name)) { ecl_grid_type * grid = ecl_grid_alloc( grid_file_name ); ecl_file_type * init_file = ecl_file_open( init_file_name , 0); - ecl_nnc_type * nnc_data1 = (ecl_nnc_type *) util_calloc( ecl_nnc_export_get_size( grid ) , sizeof * nnc_data1 ); + ecl_nnc_type * nnc_data1 = (ecl_nnc_type *) util_calloc(ecl_nnc_export_get_size(grid, init_file), sizeof *nnc_data1); int count = ecl_nnc_export(grid, init_file, nnc_data1); int i; test_assert_int_equal( count , 0 ); @@ -113,8 +115,8 @@ void test_export(const char * name, bool have_tran_data) { ecl_grid_type * grid = ecl_grid_alloc( grid_file_name ); ecl_file_type * grid_file = ecl_file_open( grid_file_name , 0 ); ecl_file_type * init_file = ecl_file_open( init_file_name , 0); - ecl_nnc_type * nnc_data1 = (ecl_nnc_type *) util_calloc( ecl_nnc_export_get_size( grid ) , sizeof * nnc_data1 ); - ecl_nnc_type * nnc_data2 = (ecl_nnc_type *) util_calloc( ecl_nnc_export_get_size( grid ) , sizeof * nnc_data2 ); + ecl_nnc_type * nnc_data1 = (ecl_nnc_type *) util_calloc(ecl_nnc_export_get_size(grid, init_file), sizeof *nnc_data1); + ecl_nnc_type * nnc_data2 = (ecl_nnc_type *) util_calloc(ecl_nnc_export_get_size(grid, init_file), sizeof *nnc_data2); { @@ -214,23 +216,23 @@ void test_export(const char * name, bool have_tran_data) { } } - test_assert_int_equal( nnc_offset , ecl_nnc_export_get_size( grid )); + test_assert_int_equal(nnc_offset, ecl_nnc_export_get_size(grid, init_file )); ecl_nnc_sort( nnc_data1 , nnc_offset ); } { int export_size = ecl_nnc_export( grid , init_file , nnc_data2 ); - test_assert_int_equal( export_size , ecl_nnc_export_get_size( grid )); + test_assert_int_equal(export_size , ecl_nnc_export_get_size(grid, init_file)); } { int i; - int size = ecl_nnc_export_get_size( grid ); + int size = ecl_nnc_export_get_size(grid, init_file); for (i=0; i < size; i++) test_assert_int_equal( 0 , ecl_nnc_sort_cmp( &nnc_data1[i] , &nnc_data2[i])); } - for (int i =0; i < ecl_nnc_export_get_size( grid ); i++) + for (int i = 0; i < ecl_nnc_export_get_size(grid, init_file); i++) test_assert_true( ecl_nnc_equal( &nnc_data1[i] , &nnc_data2[i] )); { @@ -238,7 +240,7 @@ void test_export(const char * name, bool have_tran_data) { ecl_file_view_type * view_file = ecl_file_get_global_view( init_file ); ecl_nnc_data_type * nnc_geo_data = ecl_nnc_data_alloc_tran(grid, nnc_geo, view_file); - test_assert_int_equal( ecl_nnc_export_get_size( grid ), ecl_nnc_geometry_size( nnc_geo )); + test_assert_int_equal(ecl_nnc_export_get_size(grid, init_file), ecl_nnc_geometry_size(nnc_geo)); for (int i=0; i < ecl_nnc_geometry_size( nnc_geo ); i++) { const ecl_nnc_pair_type *nnc_pair = ecl_nnc_geometry_iget( nnc_geo , i ); ecl_nnc_type * nnc1 = &nnc_data1[i]; diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_nnc_export_get_tran.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_nnc_export_get_tran.cpp index fb40436af0..61addc079a 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_nnc_export_get_tran.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_nnc_export_get_tran.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'ecl_nnc_export.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_nnc_export_intersect.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_nnc_export_intersect.cpp new file mode 100644 index 0000000000..7a8113823d --- /dev/null +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_nnc_export_intersect.cpp @@ -0,0 +1,117 @@ +/* + Copyright (C) 2018 Equinor ASA, Norway. + + The file 'ecl_nnc_export_intersect.c' is part of ERT - Ensemble based + Reservoir Tool. + + ERT 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. + + ERT 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 detals. +*/ +// #include +// #include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + + + +namespace { + +const auto GRIDX = 10, GRIDY = 10, GRIDZ = 10; +const auto GRID_NNC_NUM = 342; +const auto INIT_NNC_NUM = 298; + + +ERT::ert_unique_ptr +make_intersect_grid() { + auto out = ERT::ert_unique_ptr( + ecl_grid_alloc_rectangular(GRIDX, GRIDY, GRIDZ, 1., 1., 1., nullptr) + ); + for(auto i = 0; i < GRID_NNC_NUM; ++i) + ecl_grid_add_self_nnc(out.get(), 2 * i + 1, 2 * i, i); + return out; +} + + +ERT::ert_unique_ptr +make_intersect_init_file() { + // Create keywords with useless data + auto nnc1_kw = ecl_kw_alloc(NNC1_KW, INIT_NNC_NUM, ECL_INT); + auto nnc2_kw = ecl_kw_alloc(NNC2_KW, INIT_NNC_NUM, ECL_INT); + auto tran_kw = ecl_kw_alloc(TRANNNC_KW, INIT_NNC_NUM, ECL_DOUBLE); + for(auto i = 0; i < INIT_NNC_NUM; ++i) { + ecl_kw_iset_int(nnc1_kw, i, 2 * i); + ecl_kw_iset_int(nnc2_kw, i, 2 * i + 1 ); + ecl_kw_iset_double(tran_kw, i, 2.5 * i); + } + + // write to file directly using fortio + auto init_filename = util_alloc_tmp_file("/tmp", "ecl_nnc_export_intersect_init_file", false); + auto fortio = fortio_open_writer(init_filename, false, ECL_ENDIAN_FLIP); + ecl_kw_fwrite(nnc1_kw, fortio); + ecl_kw_fwrite(nnc2_kw, fortio); + ecl_kw_fwrite(tran_kw, fortio); + fortio_fclose(fortio); + + // reopen the file as an ecl file + auto out = ERT::ert_unique_ptr( + ecl_file_open(init_filename, 0) + ); + + ecl_kw_free(nnc1_kw); + ecl_kw_free(nnc2_kw); + ecl_kw_free(tran_kw); + free(init_filename); + return out; +} +} /* unnamed namespace */ + + + +int main(int argc, char ** argv) { + util_install_signals(); + + const auto grid = make_intersect_grid(); + const auto init_file = make_intersect_init_file(); + + test_assert_true(ecl_nnc_intersect_format(grid.get(), init_file.get())); + test_assert_int_equal(ecl_nnc_export_get_size(grid.get(), init_file.get()), INIT_NNC_NUM); + + auto nnc_data = std::vector( + ecl_nnc_export_get_size(grid.get(), init_file.get()) + ); + auto const total_valid_trans = ecl_nnc_export(grid.get(), init_file.get(), nnc_data.data()); + test_assert_int_equal(total_valid_trans, INIT_NNC_NUM); + test_assert_int_equal(int(nnc_data.size()), INIT_NNC_NUM); + + for(auto i = 0; i < int(nnc_data.size()); ++i) { + auto const& nnc = nnc_data[i]; + test_assert_int_equal(nnc.grid_nr1, 0); + test_assert_int_equal(nnc.grid_nr2, 0); + test_assert_int_equal(nnc.global_index1, 2 * i); // as set in make_intersect_init_file() + test_assert_int_equal(nnc.global_index2, 2 * i + 1); // as set in make_intersect_init_file() + test_assert_double_equal(nnc.trans, 2.5 * i); // as set in make_intersect_init_file() + test_assert_int_equal(nnc.input_index, i); + } + + return 0; +} diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_nnc_geometry.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_nnc_geometry.cpp index d457ee7b6b..25fb4e6633 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_nnc_geometry.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_nnc_geometry.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2017 Statoil ASA, Norway. + Copyright (C) 2017 Equinor ASA, Norway. The file 'ecl_nnc_geometry.c' is part of ERT - Ensemble based Reservoir Tool. @@ -36,7 +36,7 @@ void test_create_empty() { } void test_create_simple() { - test_work_area_type * work_area = test_work_area_alloc("nnc-INIT"); + ecl::util::TestArea ta("nnc_geometry"); { int nx = 10; int ny = 10; @@ -64,10 +64,10 @@ void test_create_simple() { fortio_fclose( f ); ecl_kw_free( trann_nnc ); } + ecl_nnc_geometry_free(nnc_geo); } ecl_grid_free( grid0 ); } - test_work_area_free( work_area ); } diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_nnc_index_list.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_nnc_index_list.cpp index dd4f2e616a..c464e6ee07 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_nnc_index_list.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_nnc_index_list.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'ecl_nnc_index_list.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_nnc_index_list_grid.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_nnc_index_list_grid.cpp index cfec278eaa..35181b9549 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_nnc_index_list_grid.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_nnc_index_list_grid.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'ecl_nnc_index_list_grid.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_nnc_info_test.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_nnc_info_test.cpp index dba5876244..8ddd77ddfd 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_nnc_info_test.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_nnc_info_test.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'ecl_nnc_info_test.c' is part of ERT - Ensemble based Reservoir Tool. @@ -18,6 +18,8 @@ #include #include +#include + #include #include #include @@ -53,6 +55,8 @@ void test_equal( ) { nnc_info_add_nnc( nnc_info1 , lgr_nr + 2 , 11 , 11 ); nnc_info_add_nnc( nnc_info2 , lgr_nr + 1 , 10 , 10 ); test_assert_true( nnc_info_equal( nnc_info1 , nnc_info2 )); + nnc_info_free( nnc_info1 ); + nnc_info_free( nnc_info2 ); } @@ -91,23 +95,22 @@ void basic_test() { nnc_vector_type * nnc_vector = nnc_info_get_vector( nnc_info , 1); - const int_vector_type * nnc_cells = nnc_info_get_grid_index_list(nnc_info, 1); - test_assert_int_equal(int_vector_size(nnc_cells), 2); - test_assert_ptr_equal( nnc_cells , nnc_vector_get_grid_index_list( nnc_vector )); + const std::vector& nnc_cells = nnc_info_get_grid_index_list(nnc_info, 1); + test_assert_int_equal(nnc_cells.size(), 2); + test_assert_ptr_equal( nnc_cells.data() , nnc_vector_get_grid_index_list( nnc_vector ).data()); nnc_vector_type * nnc_vector_null = nnc_info_get_vector( nnc_info , 2); - const int_vector_type * nnc_cells_null = nnc_info_get_grid_index_list(nnc_info, 2); - test_assert_NULL(nnc_cells_null); + test_assert_true( !nnc_info_has_grid_index_list(nnc_info, 2) ); test_assert_NULL(nnc_vector_null); nnc_vector_type * nnc_vector_self = nnc_info_get_self_vector( nnc_info ); const nnc_vector_type * nnc_vector_77 = nnc_info_get_vector( nnc_info , lgr_nr ); test_assert_ptr_equal( nnc_vector_77 , nnc_vector_self ); - const int_vector_type * nnc_cells_77 = nnc_info_get_grid_index_list(nnc_info, lgr_nr); - const int_vector_type * nnc_cells_self = nnc_info_get_self_grid_index_list(nnc_info); - test_assert_ptr_equal( nnc_cells_77 , nnc_cells_self ); + const std::vector& nnc_cells_77 = nnc_info_get_grid_index_list(nnc_info, lgr_nr); + const std::vector& nnc_cells_self = nnc_info_get_self_grid_index_list(nnc_info); + test_assert_ptr_equal( nnc_cells_77.data() , nnc_cells_self.data() ); test_assert_int_equal( 2 , nnc_info_get_size( nnc_info )); diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_nnc_pair.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_nnc_pair.cpp index 2827077c4e..4f807b6e50 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_nnc_pair.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_nnc_pair.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2017 Statoil ASA, Norway. + Copyright (C) 2017 Equinor ASA, Norway. The file 'ecl_nnc_pair.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_nnc_test.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_nnc_test.cpp index 5a7d72d958..e84d672cbe 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_nnc_test.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_nnc_test.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'ecl_nnc_test.c' is part of ERT - Ensemble based Reservoir Tool. @@ -18,9 +18,12 @@ #include #include +#include + #include #include #include +#include #include #include @@ -55,9 +58,9 @@ void test_scan( const char * grid_filename) { if (g2 < ecl_grid_get_global_size( lgr )) { // Skipping matrix <-> fracture link in dual poro. const nnc_info_type * nnc_info = ecl_grid_get_cell_nnc_info1( lgr , g1 ); - const int_vector_type * index_list = nnc_info_get_grid_index_list( nnc_info , lgr_nr); + const std::vector& index_list = nnc_info_get_grid_index_list( nnc_info , lgr_nr); test_assert_not_NULL( nnc_info ); - test_assert_int_not_equal( -1 , int_vector_index( index_list , g2 )); + test_assert_int_not_equal( -1 , vector_util_index( index_list , g2 )); } } } @@ -79,9 +82,9 @@ void test_scan( const char * grid_filename) { const nnc_info_type * nnc_info = ecl_grid_get_cell_nnc_info1( ecl_grid , g ); test_assert_not_NULL( nnc_info ); { - const int_vector_type * index_list = nnc_info_get_grid_index_list( nnc_info , lgr_nr ); - test_assert_not_NULL( index_list ); - test_assert_int_not_equal( -1 , int_vector_index( index_list , l )); + const std::vector& index_list = nnc_info_get_grid_index_list( nnc_info , lgr_nr ); + test_assert_true(nnc_info_has_grid_index_list( nnc_info , lgr_nr ) ); + test_assert_int_not_equal( -1 , vector_util_index( index_list , l )); } } } @@ -102,9 +105,9 @@ void test_scan( const char * grid_filename) { const int g2 = ecl_kw_iget_int( nnc2_kw , i ) - 1; const nnc_info_type * nnc_info = ecl_grid_get_cell_nnc_info1( lgr1 , g1 ); - const int_vector_type * index_list = nnc_info_get_grid_index_list( nnc_info , lgr_nr2); + const std::vector& index_list = nnc_info_get_grid_index_list( nnc_info , lgr_nr2); test_assert_not_NULL( nnc_info ); - test_assert_int_not_equal( -1 , int_vector_index( index_list , g2 )); + test_assert_int_not_equal( -1 , vector_util_index( index_list , g2 )); } } } diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_nnc_vector.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_nnc_vector.cpp index e568531756..7c12598534 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_nnc_vector.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_nnc_vector.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'ecl_nnc_vector.c' is part of ERT - Ensemble based Reservoir Tool. @@ -18,6 +18,8 @@ #include #include +#include + #include #include @@ -41,17 +43,17 @@ void test_basic() { test_assert_int_equal( 6 , nnc_vector_get_size( vector )); { - const int_vector_type * grid_index_list = nnc_vector_get_grid_index_list( vector ); - const int_vector_type * nnc_index_list = nnc_vector_get_nnc_index_list( vector ); + const std::vector& grid_index_list = nnc_vector_get_grid_index_list( vector ); + const std::vector& nnc_index_list = nnc_vector_get_nnc_index_list( vector ); - test_assert_int_equal( 6 , int_vector_size( nnc_index_list )); - test_assert_int_equal( 1 , int_vector_iget( nnc_index_list , 0 )); - test_assert_int_equal( 6 , int_vector_iget( nnc_index_list , 5 )); + test_assert_int_equal( 6 , nnc_index_list.size() ); + test_assert_int_equal( 1 , nnc_index_list[0] ); + test_assert_int_equal( 6 , nnc_index_list[5] ); - test_assert_int_equal( 6 , int_vector_size( grid_index_list )); - test_assert_int_equal( 100 , int_vector_iget( grid_index_list , 0 )); - test_assert_int_equal( 200 , int_vector_iget( grid_index_list , 1 )); - test_assert_int_equal( 300 , int_vector_iget( grid_index_list , 2 )); + test_assert_int_equal( 6 , grid_index_list.size() ); + test_assert_int_equal( 100 , grid_index_list[0] ); + test_assert_int_equal( 200 , grid_index_list[1] ); + test_assert_int_equal( 300 , grid_index_list[2] ); } nnc_vector_free( vector ); diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_region.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_region.cpp index 2ddf344fa3..98d0961b8a 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_region.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_region.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Statoil ASA, Norway. + Copyright (C) 2012 Equinor ASA, Norway. The file 'ecl_region.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_region2region.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_region2region.cpp index 3402bf92fa..a5dcc685f0 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_region2region.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_region2region.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Statoil ASA, Norway. + Copyright (C) 2012 Equinor ASA, Norway. The file 'ecl_region2region.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_restart_test.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_restart_test.cpp index f36d0297ea..3fbe747b50 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_restart_test.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_restart_test.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Statoil ASA, Norway. + Copyright (C) 2012 Equinor ASA, Norway. The file 'ecl_restart_test.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_rft.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_rft.cpp index fd7c698ae9..f7a9a18811 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_rft.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_rft.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'ecl_rft.c' is part of ERT - Ensemble based Reservoir Tool. @@ -40,10 +40,9 @@ void test_rft_read_write(const char * rft_file){ ecl_rft_node_type * old_node = ecl_rft_file_iget_node(rft, 0); ecl_rft_node_type * new_node = ecl_rft_node_alloc_new("DUMMY", "R", ecl_rft_node_get_date(old_node), ecl_rft_node_get_days(old_node)); nodes[2]=new_node; - test_work_area_type * work_area = test_work_area_alloc("RFT_RW"); + ecl::util::TestArea ta("rft"); ecl_rft_file_update("eclipse.rft", nodes,3, ECL_METRIC_UNITS); - test_work_area_free(work_area); free(nodes); } @@ -81,8 +80,6 @@ void test_rft( const char * rft_file ) { test_assert_ptr_equal( cell1 , cell2 ); } } - ecl_rft_node_inplace_sort_cells( rft_node ); - ecl_rft_file_free( rft ); } @@ -94,7 +91,6 @@ void test_plt_msw( const char * plt_file ) { test_assert_true( ecl_rft_node_is_PLT( plt_node )); test_assert_true( ecl_rft_node_is_MSW( plt_node )); test_assert_int_equal( 22 , ecl_rft_node_get_size( plt_node )); - ecl_rft_node_inplace_sort_cells( plt_node ); { int i; for (i=1; i < ecl_rft_node_get_size( plt_node ); i++) { @@ -143,7 +139,6 @@ void test_plt( const char * plt_file ) { test_assert_ptr_equal( cell1 , cell2 ); } - ecl_rft_node_inplace_sort_cells( plt_node ); } ecl_rft_file_free( plt ); @@ -159,7 +154,7 @@ void test_simple_load_rft(const char * filename) { int main( int argc , char ** argv) { const char * rft_file = argv[1]; const char * mode_string = argv[2]; - + util_install_signals(); if (strcmp( mode_string , "RFT") == 0) test_rft( rft_file ); diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_rft_cell.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_rft_cell.cpp index 03e0be4bcc..cd9e82cbc0 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_rft_cell.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_rft_cell.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'ecl_rft_cell.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_rst_file.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_rst_file.cpp index 50d1bb6703..b708490790 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_rst_file.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_rst_file.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2016 Statoil ASA, Norway. + Copyright (C) 2016 Equinor ASA, Norway. The file 'ecl_rst_file.c' is part of ERT - Ensemble based Reservoir Tool. @@ -65,7 +65,7 @@ void test_file( const char * src_file , const char * target_file , int report_st void test_Xfile() { - test_work_area_type * work_area = test_work_area_alloc("rst-file"); + ecl::util::TestArea ta("xfile"); { fortio_type * f = fortio_open_writer( "TEST.X0010" , false , ECL_ENDIAN_FLIP); @@ -80,13 +80,12 @@ void test_Xfile() { fortio_fclose( f ); } test_file( "TEST.X0010" , "FILE.X0010" , 10 , 0 ); - test_work_area_free( work_area ); } void test_UNRST0() { - test_work_area_type * work_area = test_work_area_alloc("rst-file"); + ecl::util::TestArea ta("rst-file"); offset_type pos10; offset_type pos20; offset_type pos_end; @@ -118,12 +117,11 @@ void test_UNRST0() { test_file( "TEST.UNRST" , "FILE.UNRST" , 15 , pos20 ); test_file( "TEST.UNRST" , "FILE.UNRST" , 20 , pos20 ); test_file( "TEST.UNRST" , "FILE.UNRST" , 25 , pos_end ); - test_work_area_free( work_area ); } void test_UNRST1() { - test_work_area_type * work_area = test_work_area_alloc("rst-file"); + ecl::util::TestArea ta("rst-file"); offset_type pos5; offset_type pos10; offset_type pos20; @@ -158,7 +156,6 @@ void test_UNRST1() { test_file( "TEST.UNRST" , "FILE.UNRST" , 15 , pos20 ); test_file( "TEST.UNRST" , "FILE.UNRST" , 20 , pos20 ); test_file( "TEST.UNRST" , "FILE.UNRST" , 25 , pos_end ); - test_work_area_free( work_area ); } diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_rsthead.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_rsthead.cpp index c690d71535..ab551c685c 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_rsthead.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_rsthead.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'ecl_rst_header.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_smspec.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_smspec.cpp index 6ee378897e..963ce03f41 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_smspec.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_smspec.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2016 Statoil ASA, Norway. + Copyright (C) 2016 Equinor ASA, Norway. This file is part of ERT - Ensemble based Reservoir Tool. @@ -23,28 +23,13 @@ #include #include -void test_sort( ecl_smspec_type * smspec ) -{ - int num_nodes = ecl_smspec_num_nodes( smspec ); - ecl_smspec_sort( smspec ); - test_assert_int_equal( num_nodes, ecl_smspec_num_nodes( smspec )); - - for (int i=1; i < ecl_smspec_num_nodes( smspec ); i++) { - const smspec_node_type * node1 = ecl_smspec_iget_node( smspec, i - 1 ); - const smspec_node_type * node2 = ecl_smspec_iget_node( smspec, i ); - test_assert_true( smspec_node_cmp( node1 , node2 ) <= 0 ); - - test_assert_int_equal( smspec_node_get_params_index( node1 ) , i - 1 ); - } -} - void test_copy(const ecl_smspec_type * smspec1) { ecl_sum_type * ecl_sum2 = ecl_sum_alloc_writer("CASE", false, true, ":", 0, true, 100, 100, 100); const ecl_smspec_type * smspec2 = ecl_sum_get_smspec(ecl_sum2); for (int i=0; i < ecl_smspec_num_nodes(smspec1); i++) { - const smspec_node_type * node = ecl_smspec_iget_node(smspec1, i); - ecl_sum_add_smspec_node(ecl_sum2, node); + const ecl::smspec_node& node = ecl_smspec_iget_node_w_node_index(smspec1, i); + ecl_sum_add_smspec_node(ecl_sum2, &node); } test_assert_true( ecl_smspec_equal(smspec1, smspec2)); ecl_sum_free(ecl_sum2); @@ -63,8 +48,6 @@ int main(int argc, char ** argv) { test_assert_false( ecl_smspec_equal( smspec1 , smspec2 )); test_assert_false( ecl_smspec_equal( smspec2 , smspec1 )); - test_sort( smspec1 ); - test_sort( smspec2 ); ecl_smspec_free( smspec1 ); ecl_smspec_free( smspec2 ); } diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_smspec_node.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_smspec_node.cpp index 7806fc8dec..bc0efbe740 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_smspec_node.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_smspec_node.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2017 Statoil ASA, Norway. + Copyright (C) 2017 Equinor ASA, Norway. This file is part of ERT - Ensemble based Reservoir Tool. @@ -25,94 +25,158 @@ #include +static void test_identify_rate_variable() { + const char* rate_vars[] = { + "WOPR" , "GGPR" , "FWPR" , "WLPR" , "WOIR" , "FGIR" , "GWIR" , + "WLIR" , "GGOR" , "FWCT" , "SOFR" , "SGFR" , "SWFR" , + }; + + const auto n_var = sizeof(rate_vars) / sizeof(rate_vars[0]); + + for (auto var = rate_vars, end = rate_vars + n_var; var != end; ++var) + test_assert_true(smspec_node_identify_rate(*var)); + + test_assert_false(smspec_node_identify_rate("SPR")); + test_assert_false(smspec_node_identify_rate("SOFT")); + test_assert_false(smspec_node_identify_rate("SGFT")); + test_assert_false(smspec_node_identify_rate("SWFT")); +} + +static void test_identify_total_variable() { + test_assert_true(smspec_node_identify_total("WOPT", ECL_SMSPEC_WELL_VAR)); + test_assert_true(smspec_node_identify_total("GGPT", ECL_SMSPEC_GROUP_VAR)); + test_assert_true(smspec_node_identify_total("FWPT", ECL_SMSPEC_FIELD_VAR)); + test_assert_true(smspec_node_identify_total("RGIT", ECL_SMSPEC_REGION_VAR)); + test_assert_true(smspec_node_identify_total("CWIT", ECL_SMSPEC_COMPLETION_VAR)); + + test_assert_true(smspec_node_identify_total("WOPTF", ECL_SMSPEC_WELL_VAR)); + test_assert_true(smspec_node_identify_total("GOPTS", ECL_SMSPEC_GROUP_VAR)); + test_assert_true(smspec_node_identify_total("FOIT", ECL_SMSPEC_FIELD_VAR)); + test_assert_true(smspec_node_identify_total("ROVPT", ECL_SMSPEC_REGION_VAR)); + test_assert_true(smspec_node_identify_total("COVIT", ECL_SMSPEC_COMPLETION_VAR)); + + test_assert_true(smspec_node_identify_total("WMWT", ECL_SMSPEC_WELL_VAR)); + test_assert_true(smspec_node_identify_total("GWVPT", ECL_SMSPEC_GROUP_VAR)); + test_assert_true(smspec_node_identify_total("FWVIT", ECL_SMSPEC_FIELD_VAR)); + test_assert_true(smspec_node_identify_total("RGMT", ECL_SMSPEC_REGION_VAR)); + test_assert_true(smspec_node_identify_total("CGPTF", ECL_SMSPEC_COMPLETION_VAR)); + + test_assert_true(smspec_node_identify_total("WSGT", ECL_SMSPEC_WELL_VAR)); + test_assert_true(smspec_node_identify_total("GGST", ECL_SMSPEC_GROUP_VAR)); + test_assert_true(smspec_node_identify_total("FFGT", ECL_SMSPEC_FIELD_VAR)); + test_assert_true(smspec_node_identify_total("RGCT", ECL_SMSPEC_REGION_VAR)); + test_assert_true(smspec_node_identify_total("CGIMT", ECL_SMSPEC_COMPLETION_VAR)); + + test_assert_true(smspec_node_identify_total("WWGPT", ECL_SMSPEC_WELL_VAR)); + test_assert_true(smspec_node_identify_total("GWGIT", ECL_SMSPEC_GROUP_VAR)); + test_assert_true(smspec_node_identify_total("FEGT", ECL_SMSPEC_FIELD_VAR)); + test_assert_true(smspec_node_identify_total("REXGT", ECL_SMSPEC_REGION_VAR)); + test_assert_true(smspec_node_identify_total("CGVPT", ECL_SMSPEC_COMPLETION_VAR)); + + test_assert_true(smspec_node_identify_total("WGVIT", ECL_SMSPEC_WELL_VAR)); + test_assert_true(smspec_node_identify_total("GLPT", ECL_SMSPEC_GROUP_VAR)); + test_assert_true(smspec_node_identify_total("FVPT", ECL_SMSPEC_FIELD_VAR)); + test_assert_true(smspec_node_identify_total("RVIT", ECL_SMSPEC_REGION_VAR)); + test_assert_true(smspec_node_identify_total("CNPT", ECL_SMSPEC_COMPLETION_VAR)); + + test_assert_true(smspec_node_identify_total("WNIT", ECL_SMSPEC_WELL_VAR)); + test_assert_true(smspec_node_identify_total("GCPT", ECL_SMSPEC_GROUP_VAR)); + test_assert_true(smspec_node_identify_total("FCIT", ECL_SMSPEC_FIELD_VAR)); + + test_assert_true(smspec_node_identify_total("SOFT", ECL_SMSPEC_SEGMENT_VAR)); + test_assert_true(smspec_node_identify_total("SGFT", ECL_SMSPEC_SEGMENT_VAR)); + test_assert_true(smspec_node_identify_total("SWFT", ECL_SMSPEC_SEGMENT_VAR)); + + test_assert_false(smspec_node_identify_total("SOPT", ECL_SMSPEC_SEGMENT_VAR)); + test_assert_false(smspec_node_identify_total("HEI!", ECL_SMSPEC_SEGMENT_VAR)); + test_assert_false(smspec_node_identify_total("xXx", ECL_SMSPEC_SEGMENT_VAR)); + test_assert_false(smspec_node_identify_total("SPR", ECL_SMSPEC_SEGMENT_VAR)); +} + + +void test_nums_default() { + ecl::smspec_node field_node( 0, "FOPT" , "UNIT" , 0); + ecl::smspec_node group_node( 0, "GOPR" , "G1", "UNIT" , 0, ":"); + ecl::smspec_node well_node( 0, "WOPR" , "W1", "UNIT" , 0, ":"); + + int default_nums = 0; + /* + The integer constant default nums corresponds to the symbol nums_unused + in smspec_node.cpp. It is duplicated here to avoid exporting it - it should + not really be a publically available symbol. + */ + + test_assert_int_equal( field_node.get_num(), default_nums); + test_assert_int_equal( group_node.get_num(), default_nums); + test_assert_int_equal( well_node.get_num(), default_nums); +} + + void test_cmp_types() { const int dims[3] = {10,10,10}; - smspec_node_type * field_node = smspec_node_alloc( ECL_SMSPEC_FIELD_VAR , NULL , "FOPT" , "UNIT" , ":" , dims , 0 , 0 , 0 ); - smspec_node_type * region_node = smspec_node_alloc( ECL_SMSPEC_REGION_VAR , NULL , "RPR" , "UNIT" , ":" , dims , 10 , 0 , 0 ); - smspec_node_type * group_node = smspec_node_alloc( ECL_SMSPEC_GROUP_VAR , "G1" , "GOPR" , "UNIT" , ":" , dims , 10 , 0 , 0 ); - smspec_node_type * well_node = smspec_node_alloc( ECL_SMSPEC_WELL_VAR , "W1" , "WOPR" , "UNIT" , ":" , dims , 10 , 0 , 0 ); - smspec_node_type * block_node = smspec_node_alloc( ECL_SMSPEC_BLOCK_VAR , NULL , "BPR" , "UNIT" , ":" , dims , 10 , 0 , 0 ); - smspec_node_type * aquifer_node = smspec_node_alloc( ECL_SMSPEC_AQUIFER_VAR , NULL , "AAQP" , "UNIT" , ":" , dims , 10 , 0 , 0 ); - smspec_node_type * segment_node = smspec_node_alloc( ECL_SMSPEC_SEGMENT_VAR , "W1" , "SGOR" , "UNIT" , ":" , dims , 10 , 0 , 0 ); - smspec_node_type * misc_node1 = smspec_node_alloc( ECL_SMSPEC_MISC_VAR , NULL , "TIME" , "UNIT" , ":", dims, 10 , 0, 0); - smspec_node_type * misc_node2 = smspec_node_alloc( ECL_SMSPEC_MISC_VAR , NULL , "TCPU" , "UNIT" , ":", dims, 10 , 0, 0); + ecl::smspec_node field_node( 0, "FOPT" , "UNIT" , 0); + ecl::smspec_node region_node( 0, "RPR" , 10, "UNIT" , dims , 0 , ":"); + ecl::smspec_node group_node( 0, "GOPR" , "G1", "UNIT" , 0, ":"); + ecl::smspec_node well_node( 0, "WOPR" , "W1", "UNIT" , 0, ":"); + ecl::smspec_node block_node( 0, "BPR", 10, "UNIT", dims, 0, ":"); + ecl::smspec_node aquifer_node( 0, "AAQP" , 10, "UNIT" , dims, 0 , ":"); + ecl::smspec_node segment_node( 0, "SGOR" , "W1" , 10, "UNIT" , dims , 0 , ":"); + ecl::smspec_node misc_node1( 0, "TIME" , "UNIT", 0 ); + ecl::smspec_node misc_node2( 0, "TCPU", "UNIT", 0); - test_assert_int_equal( smspec_node_cmp( field_node , field_node ), 0); - test_assert_int_equal( smspec_node_cmp( region_node , region_node ), 0); - test_assert_int_equal( smspec_node_cmp( well_node , well_node ), 0); - test_assert_int_equal( smspec_node_cmp( group_node , group_node ), 0); - test_assert_int_equal( smspec_node_cmp( block_node , block_node ), 0); + test_assert_int_equal( field_node.cmp(field_node), 0); + test_assert_int_equal( region_node.cmp(region_node), 0); + test_assert_int_equal( well_node.cmp(well_node), 0); + test_assert_int_equal( group_node.cmp(group_node), 0); + test_assert_int_equal( block_node.cmp(block_node), 0); - test_assert_true( smspec_node_cmp( misc_node1 , field_node ) < 0 ); - test_assert_true( smspec_node_cmp( field_node , region_node ) < 0 ); - test_assert_true( smspec_node_cmp( region_node , group_node ) < 0 ); - test_assert_true( smspec_node_cmp( group_node , well_node ) < 0 ); - test_assert_true( smspec_node_cmp( well_node , segment_node ) < 0 ); - test_assert_true( smspec_node_cmp( segment_node , block_node ) < 0 ); - test_assert_true( smspec_node_cmp( block_node , aquifer_node) < 0 ); - test_assert_true( smspec_node_cmp( aquifer_node , misc_node2 ) < 0 ); + test_assert_true( misc_node1.cmp(field_node) < 0 ); + test_assert_true( field_node.cmp(region_node) < 0 ); + test_assert_true( region_node.cmp(group_node) < 0 ); + test_assert_true( group_node.cmp(well_node) < 0 ); + test_assert_true( well_node.cmp(segment_node) < 0 ); + test_assert_true( segment_node.cmp(block_node) < 0 ); + test_assert_true( block_node.cmp(aquifer_node)< 0 ); + test_assert_true( aquifer_node.cmp(misc_node2) < 0 ); - test_assert_true( smspec_node_cmp( field_node, misc_node1) > 0 ); - test_assert_true( smspec_node_cmp( misc_node2, aquifer_node) > 0 ); - test_assert_true( smspec_node_cmp( misc_node1, misc_node2) < 0 ); - test_assert_true( smspec_node_cmp( misc_node2, misc_node1) > 0 ); - - smspec_node_free( segment_node ); - smspec_node_free( aquifer_node ); - smspec_node_free( block_node ); - smspec_node_free( group_node ); - smspec_node_free( well_node ); - smspec_node_free( region_node ); - smspec_node_free( field_node ); - smspec_node_free( misc_node1 ); - smspec_node_free( misc_node2 ); + test_assert_true( field_node.cmp(misc_node1) > 0 ); + test_assert_true( misc_node2.cmp(aquifer_node) > 0 ); + test_assert_true( misc_node1.cmp(misc_node2) < 0 ); + test_assert_true( misc_node2.cmp(misc_node1) > 0 ); } void test_cmp_well() { - const int dims[3] = {10,10,10}; - smspec_node_type * well_node1_1 = smspec_node_alloc( ECL_SMSPEC_WELL_VAR , "W1" , "WOPR" , "UNIT" , ":" , dims , 10 , 0 , 0 ); - smspec_node_type * well_node1_2 = smspec_node_alloc( ECL_SMSPEC_WELL_VAR , "W2" , "WOPR" , "UNIT" , ":" , dims , 10 , 0 , 0 ); - smspec_node_type * well_node2_1 = smspec_node_alloc( ECL_SMSPEC_WELL_VAR , "W1" , "WWCT" , "UNIT" , ":" , dims , 10 , 0 , 0 ); - smspec_node_type * well_node2_2 = smspec_node_alloc( ECL_SMSPEC_WELL_VAR , "W2" , "WWWT" , "UNIT" , ":" , dims , 10 , 0 , 0 ); - smspec_node_type * well_node_dummy = smspec_node_alloc( ECL_SMSPEC_WELL_VAR , DUMMY_WELL , "WOPR" , "UNIT" , ":" , dims , 10 , 0 , 0 ); + ecl::smspec_node well_node1_1( 0 , "WOPR" ,"W1" , "UNIT" , 10 ,":"); + ecl::smspec_node well_node1_2( 0 , "WOPR" ,"W2" , "UNIT" , 10 ,":"); + ecl::smspec_node well_node2_1( 0 , "WWCT" ,"W1" , "UNIT" , 10 ,":"); + ecl::smspec_node well_node2_2( 0 , "WWWT" ,"W2" , "UNIT" , 10 ,":"); - test_assert_NULL( well_node_dummy); - test_assert_int_equal( smspec_node_cmp( well_node1_1 , well_node1_1 ), 0); - test_assert_int_equal( smspec_node_cmp( well_node2_2 , well_node2_2 ), 0); + test_assert_int_equal( well_node1_1.cmp(well_node1_1), 0); + test_assert_int_equal( well_node2_2.cmp(well_node2_2), 0); - test_assert_true( smspec_node_cmp( well_node1_1, well_node1_2) < 0 ); - test_assert_true( smspec_node_cmp( well_node1_1, well_node2_1) < 0 ); - test_assert_true( smspec_node_cmp( well_node1_1, well_node2_2) < 0 ); + test_assert_true( well_node1_1.cmp(well_node1_2)< 0 ); + test_assert_true( well_node1_1.cmp(well_node2_1)< 0 ); + test_assert_true( well_node1_1.cmp(well_node2_2)< 0 ); - test_assert_true( smspec_node_cmp( well_node1_2, well_node1_1) > 0 ); - test_assert_true( smspec_node_cmp( well_node1_2, well_node2_1) < 0 ); - - smspec_node_free( well_node1_1 ); - smspec_node_free( well_node2_1 ); - smspec_node_free( well_node1_2 ); - smspec_node_free( well_node2_2 ); + test_assert_true( well_node1_2.cmp(well_node1_1)> 0 ); + test_assert_true( well_node1_2.cmp(well_node2_1)< 0 ); } void test_cmp_region() { const int dims[3] = {10,10,10}; - smspec_node_type * region_node1_1 = smspec_node_alloc( ECL_SMSPEC_REGION_VAR , NULL , "ROIP" , "UNIT" , ":" , dims , 10 , 0 , 0 ); - smspec_node_type * region_node1_2 = smspec_node_alloc( ECL_SMSPEC_REGION_VAR , NULL , "ROIP" , "UNIT" , ":" , dims , 11 , 0 , 0 ); - smspec_node_type * region_node2_1 = smspec_node_alloc( ECL_SMSPEC_REGION_VAR , NULL , "RPR" , "UNIT" , ":" , dims , 10 , 0 , 0 ); - smspec_node_type * region_node2_2 = smspec_node_alloc( ECL_SMSPEC_REGION_VAR , NULL , "RPR" , "UNIT" , ":" , dims , 12 , 0 , 0 ); + ecl::smspec_node region_node1_1( 0, "ROIP" , 10 ,"UNIT" , dims , 0 , ":" ); + ecl::smspec_node region_node1_2( 0, "ROIP" , 11 ,"UNIT" , dims , 0 , ":" ); + ecl::smspec_node region_node2_1( 0, "RPR" , 10 ,"UNIT" , dims , 0 , ":" ); + ecl::smspec_node region_node2_2( 0, "RPR" , 12 ,"UNIT" , dims , 0 , ":" ); - test_assert_true( smspec_node_cmp( region_node1_1, region_node1_2) < 0 ); - test_assert_true( smspec_node_cmp( region_node1_1, region_node2_1) < 0 ); - test_assert_true( smspec_node_cmp( region_node1_1, region_node2_2) < 0 ); + test_assert_true( region_node1_1.cmp(region_node1_2)< 0 ); + test_assert_true( region_node1_1.cmp(region_node2_1)< 0 ); + test_assert_true( region_node1_1.cmp(region_node2_2)< 0 ); - test_assert_true( smspec_node_cmp( region_node1_2, region_node1_1) > 0 ); - test_assert_true( smspec_node_cmp( region_node1_2, region_node2_1) < 0 ); - - smspec_node_free( region_node1_1 ); - smspec_node_free( region_node2_1 ); - smspec_node_free( region_node1_2 ); - smspec_node_free( region_node2_2 ); + test_assert_true( region_node1_2.cmp(region_node1_1)> 0 ); + test_assert_true( region_node1_2.cmp(region_node2_1)< 0 ); } @@ -121,4 +185,7 @@ int main(int argc, char ** argv) { test_cmp_types(); test_cmp_well(); test_cmp_region( ); + test_identify_rate_variable(); + test_identify_total_variable(); + test_nums_default(); } diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_sum_alloc_resampled_test.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_sum_alloc_resampled_test.cpp index 3eb32c2f5a..ae98f6acb4 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_sum_alloc_resampled_test.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_sum_alloc_resampled_test.cpp @@ -3,6 +3,7 @@ #include #include +#include ecl_sum_type * test_alloc_ecl_sum() { time_t start_time = util_make_date_utc( 1,1,2010 ); @@ -12,16 +13,16 @@ ecl_sum_type * test_alloc_ecl_sum() { int num_dates = 4; double ministep_length = 86400; // seconds in a day - smspec_node_type * node1 = ecl_sum_add_var( ecl_sum , "FOPT" , NULL , 0 , "Barrels" , 99.0 ); - smspec_node_type * node2 = ecl_sum_add_var( ecl_sum , "BPR" , NULL , 567 , "BARS" , 0.0 ); - smspec_node_type * node3 = ecl_sum_add_var( ecl_sum , "WWCT" , "OP-1" , 0 , "(1)" , 0.0 ); + const ecl::smspec_node * node1 = ecl_sum_add_var( ecl_sum , "FOPT" , NULL , 0 , "Barrels" , 99.0 ); + const ecl::smspec_node * node2 = ecl_sum_add_var( ecl_sum , "BPR" , NULL , 567 , "BARS" , 0.0 ); + const ecl::smspec_node * node3 = ecl_sum_add_var( ecl_sum , "WWCT" , "OP-1" , 0 , "(1)" , 0.0 ); for (int report_step = 0; report_step < num_dates; report_step++) { { ecl_sum_tstep_type * tstep = ecl_sum_add_tstep( ecl_sum , report_step + 1 , sim_seconds ); - ecl_sum_tstep_set_from_node( tstep , node1 , report_step*2.0 ); - ecl_sum_tstep_set_from_node( tstep , node2 , report_step*4.0 + 2.0 ); - ecl_sum_tstep_set_from_node( tstep , node3 , report_step*6.0 + 4.0 ); + ecl_sum_tstep_set_from_node( tstep , *node1 , report_step*2.0 ); + ecl_sum_tstep_set_from_node( tstep , *node2 , report_step*4.0 + 2.0 ); + ecl_sum_tstep_set_from_node( tstep , *node3 , report_step*6.0 + 4.0 ); } sim_seconds += ministep_length * 3; @@ -37,19 +38,19 @@ void test_correct_time_vector() { time_t_vector_append(t, util_make_date_utc( 4,1,2010 )); time_t_vector_append(t, util_make_date_utc( 6,1,2010 )); time_t_vector_append(t, util_make_date_utc( 8,1,2010 )); - ecl_sum_type * ecl_sum_resampled = ecl_sum_alloc_resample(ecl_sum, "kk", t); + ecl_sum_type * ecl_sum_resampled = ecl_sum_alloc_resample(ecl_sum, "kk", t, false, false); test_assert_int_equal( ecl_sum_get_report_time(ecl_sum_resampled, 2) , util_make_date_utc( 6,1,2010 )); const ecl_smspec_type * smspec_resampled = ecl_sum_get_smspec(ecl_sum_resampled); - const smspec_node_type * node1 = ecl_smspec_iget_node(smspec_resampled, 1); - const smspec_node_type * node2 = ecl_smspec_iget_node(smspec_resampled, 2); - const smspec_node_type * node3 = ecl_smspec_iget_node(smspec_resampled, 3); - test_assert_string_equal( "BPR" , smspec_node_get_keyword(node2) ); - test_assert_string_equal( "BARS" , smspec_node_get_unit(node2) ); + const ecl::smspec_node& node1 = ecl_smspec_iget_node_w_params_index(smspec_resampled, 1); + const ecl::smspec_node& node2 = ecl_smspec_iget_node_w_params_index(smspec_resampled, 2); + const ecl::smspec_node& node3 = ecl_smspec_iget_node_w_params_index(smspec_resampled, 3); + test_assert_string_equal( "BPR" , smspec_node_get_keyword(&node2) ); + test_assert_string_equal( "BARS" , smspec_node_get_unit(&node2) ); - test_assert_double_equal(3.33333, ecl_sum_get_from_sim_time( ecl_sum_resampled, util_make_date_utc( 6,1,2010 ), node1) ); - test_assert_double_equal(3.33333, ecl_sum_get_from_sim_time( ecl_sum_resampled, util_make_date_utc( 2,1,2010 ), node2) ); - test_assert_double_equal(10.0000, ecl_sum_get_from_sim_time( ecl_sum_resampled, util_make_date_utc( 4,1,2010 ), node3) ); + test_assert_double_equal(3.33333, ecl_sum_get_from_sim_time( ecl_sum_resampled, util_make_date_utc( 6,1,2010 ), &node1) ); + test_assert_double_equal(3.33333, ecl_sum_get_from_sim_time( ecl_sum_resampled, util_make_date_utc( 2,1,2010 ), &node2) ); + test_assert_double_equal(10.0000, ecl_sum_get_from_sim_time( ecl_sum_resampled, util_make_date_utc( 4,1,2010 ), &node3) ); ecl_sum_free(ecl_sum_resampled); @@ -57,23 +58,38 @@ void test_correct_time_vector() { ecl_sum_free(ecl_sum); } -void test_time_before() { - ecl_sum_type * ecl_sum = test_alloc_ecl_sum(); - time_t_vector_type * t = time_t_vector_alloc( 0 , 0 ); - time_t_vector_append(t, util_make_date_utc( 1,1,2009 )); - test_assert_NULL( ecl_sum_alloc_resample(ecl_sum, "kk", t) ); - time_t_vector_free(t); - ecl_sum_free(ecl_sum); -} -void test_time_after() { - ecl_sum_type * ecl_sum = test_alloc_ecl_sum(); - time_t_vector_type * t = time_t_vector_alloc( 0 , 0 ); - time_t_vector_append(t, util_make_date_utc( 1,1,2010 )); - time_t_vector_append(t, util_make_date_utc( 11,1,2010 )); - test_assert_NULL( ecl_sum_alloc_resample(ecl_sum, "kk", t) ); - time_t_vector_free(t); - ecl_sum_free(ecl_sum); +void test_resample_extrapolate_rate() { + + ecl_sum_type * ecl_sum = test_alloc_ecl_sum(); + + time_t_vector_type * t = time_t_vector_alloc( 0 , 0 ); + time_t_vector_append(t, util_make_date_utc( 1,1,2009 )); + time_t_vector_append(t, util_make_date_utc( 4,1,2010 )); + time_t_vector_append(t, util_make_date_utc( 12,1,2010 )); + + ecl_sum_type * ecl_sum_resampled = ecl_sum_alloc_resample(ecl_sum, "kk", t, true, true); + + + const ecl_smspec_type * smspec_resampled = ecl_sum_get_smspec(ecl_sum_resampled); + const ecl::smspec_node& node1 = ecl_smspec_iget_node_w_params_index(smspec_resampled, 1); + const ecl::smspec_node& node3 = ecl_smspec_iget_node_w_params_index(smspec_resampled, 3); + + + //testing extrapolation for rate wrt. 3 dates: lower, inside and upper + test_assert_double_equal(0, ecl_sum_get_from_sim_time( ecl_sum_resampled, util_make_date_utc( 1, 1, 2009), &node3)); + test_assert_double_equal(10.000, ecl_sum_get_from_sim_time( ecl_sum_resampled, util_make_date_utc( 4, 1, 2010), &node3)); + test_assert_double_equal(0, ecl_sum_get_from_sim_time( ecl_sum_resampled, util_make_date_utc( 12, 1, 2010), &node3)); + + //testing extrapolation for variable wrt. 3 dates: lower, inside and upper + test_assert_double_equal(0, ecl_sum_get_from_sim_time( ecl_sum_resampled, util_make_date_utc( 1, 1, 2009 ), &node1) ); + test_assert_double_equal(2.000, ecl_sum_get_from_sim_time( ecl_sum_resampled, util_make_date_utc( 4, 1,2010 ), &node1) ); + test_assert_double_equal(6.000, ecl_sum_get_from_sim_time( ecl_sum_resampled, util_make_date_utc( 12, 1,2010 ), &node1) ); + + + ecl_sum_free(ecl_sum_resampled); + time_t_vector_free(t); + ecl_sum_free(ecl_sum); } void test_not_sorted() { @@ -82,7 +98,7 @@ void test_not_sorted() { time_t_vector_append(t, util_make_date_utc( 1,1,2010 )); time_t_vector_append(t, util_make_date_utc( 3,1,2010 )); time_t_vector_append(t, util_make_date_utc( 2,1,2010 )); - test_assert_NULL( ecl_sum_alloc_resample( ecl_sum, "kk", t) ); + test_assert_NULL( ecl_sum_alloc_resample( ecl_sum, "kk", t, false, false) ); time_t_vector_free(t); ecl_sum_free(ecl_sum); } @@ -90,8 +106,7 @@ void test_not_sorted() { int main() { test_correct_time_vector(); - test_time_before(); - test_time_after(); + test_resample_extrapolate_rate(); test_not_sorted(); return 0; } diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_sum_case_exists.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_sum_case_exists.cpp index ed43da456d..a9f852388d 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_sum_case_exists.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_sum_case_exists.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'ecl_sum_case_exists.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_sum_data_intermediate_test.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_sum_data_intermediate_test.cpp index 9a4e569894..3de2dd13a7 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_sum_data_intermediate_test.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_sum_data_intermediate_test.cpp @@ -5,16 +5,21 @@ #include #include +#include +#include +#include +#include #include +#include /* CASE1 --------- -1 : BPR:1 100 200 300 400 -2 : BPR:2 110 210 310 410 -3 : BRP:3 120 220 320 430 +1 : BPR:1 100 200 300 400 500 600 700 800 900 .... +2 : BPR:2 110 210 310 410 510 610 710 810 910 .... +3 : BRP:3 120 220 320 420 520 620 720 820 920 .... @@ -51,13 +56,14 @@ Total CASE3: #define ieq(d,i,v) test_assert_double_equal(double_vector_iget(d,(i)), v) -void verify_CASE1() { +void verify_CASE1(int length) { ecl_sum_type * sum = ecl_sum_fread_alloc_case("CASE1", ":"); + int params_size = 4; // TIME, BPR:1, BPR:2, BPR:3 - for (int i=1; i < 4; i++) { + for (int i=1; i < params_size; i++) { double_vector_type * d = ecl_sum_alloc_data_vector(sum, i, false); - //test_assert_int_equal(4, double_vector_size(d)); - for (int j=0; j < 4; j++) { + test_assert_int_equal(length, double_vector_size(d)); + for (int j=0; j < length; j++) { test_assert_double_equal( double_vector_iget(d, j), (i - 1)*10 + (j + 1)*100); } double_vector_free(d); @@ -72,37 +78,38 @@ void write_CASE1(bool unified) { ecl_sum_type * ecl_sum = ecl_sum_alloc_writer( "CASE1" , false , unified, ":" , start_time , true , 10 , 10 , 10 ); double sim_seconds = 0; - int num_dates = 4; + int num_dates = 100; double ministep_length = 86400; // seconds in a day - smspec_node_type * node1 = ecl_sum_add_var( ecl_sum , "BPR" , NULL , 1 , "BARS" , 0.0 ); - smspec_node_type * node2 = ecl_sum_add_var( ecl_sum , "BPR" , NULL , 2 , "BARS" , 0.0 ); - smspec_node_type * node3 = ecl_sum_add_var( ecl_sum , "BPR" , NULL , 3 , "BARS" , 0.0 ); + const ecl::smspec_node * node1 = ecl_sum_add_var( ecl_sum , "BPR" , NULL , 1 , "BARS" , 0.0 ); + const ecl::smspec_node * node2 = ecl_sum_add_var( ecl_sum , "BPR" , NULL , 2 , "BARS" , 0.0 ); + const ecl::smspec_node * node3 = ecl_sum_add_var( ecl_sum , "BPR" , NULL , 3 , "BARS" , 0.0 ); for (int report_step = 0; report_step < num_dates; report_step++) { { ecl_sum_tstep_type * tstep = ecl_sum_add_tstep( ecl_sum , report_step + 1 , sim_seconds ); - ecl_sum_tstep_set_from_node( tstep , node1 , (1 + report_step) * 100 ); - ecl_sum_tstep_set_from_node( tstep , node2 , (1 + report_step) * 100 + 10.0 ); - ecl_sum_tstep_set_from_node( tstep , node3 , (1 + report_step) * 100 + 20.0 ); + ecl_sum_tstep_set_from_node( tstep , *node1 , (1 + report_step) * 100 ); + ecl_sum_tstep_set_from_node( tstep , *node2 , (1 + report_step) * 100 + 10.0 ); + ecl_sum_tstep_set_from_node( tstep , *node3 , (1 + report_step) * 100 + 20.0 ); } sim_seconds += ministep_length * 3; } ecl_sum_fwrite( ecl_sum ); ecl_sum_free(ecl_sum); - verify_CASE1(); + verify_CASE1(num_dates); } -void verify_CASE2() { +void verify_CASE2(int length) { ecl_sum_type * sum = ecl_sum_fread_alloc_case2__("CASE2", ":", false, true, 0); + const int params_size = 2; // TIME, BPR:2, BPR:1 - for (int i=0; i < 2; i++) { + for (int i=0; i < params_size; i++) { double_vector_type * d = ecl_sum_alloc_data_vector(sum, i+1, false); - //test_assert_int_equal(4, double_vector_size(d)); - for (int j=1; j < 4; j++) + test_assert_int_equal(length, double_vector_size(d)); + for (int j=1; j < length; j++) test_assert_double_equal( double_vector_iget(d, j-1), (1 - i)*100 + j*1000); double_vector_free(d); } @@ -111,9 +118,9 @@ void verify_CASE2() { sum = ecl_sum_fread_alloc_case("CASE2", ":"); - for (int i=0; i < 2; i++) { + for (int i=0; i < params_size; i++) { double_vector_type * d = ecl_sum_alloc_data_vector(sum, i+1, false); - //test_assert_int_equal(double_vector_size(d), 7); + test_assert_int_equal(double_vector_size(d), 7); ieq(d,0,(1 - i)*10 + 100); ieq(d,1,(1 - i)*10 + 200); ieq(d,2,(1 - i)*10 + 300); @@ -137,30 +144,31 @@ void write_CASE2(bool unified) { double sim_seconds = ministep_length * 2.5 * 3; ecl_sum_type * ecl_sum = ecl_sum_alloc_restart_writer( "CASE2" , "CASE1", false , true , ":" , start_time , true , 10 , 10 , 10 ); - smspec_node_type * node2 = ecl_sum_add_var( ecl_sum , "BPR" , NULL , 2 , "BARS" , 0.0 ); - smspec_node_type * node1 = ecl_sum_add_var( ecl_sum , "BPR" , NULL , 1 , "BARS" , 0.0 ); + const ecl::smspec_node * node2 = ecl_sum_add_var( ecl_sum , "BPR" , NULL , 2 , "BARS" , 0.0 ); + const ecl::smspec_node * node1 = ecl_sum_add_var( ecl_sum , "BPR" , NULL , 1 , "BARS" , 0.0 ); for (int report_step = 1; report_step <= num_dates; report_step++) { { ecl_sum_tstep_type * tstep = ecl_sum_add_tstep( ecl_sum , report_step + 3 , sim_seconds ); - ecl_sum_tstep_set_from_node( tstep , node1 , report_step*1000); - ecl_sum_tstep_set_from_node( tstep , node2 , report_step*1000 + 100); + ecl_sum_tstep_set_from_node( tstep , *node1 , report_step*1000); + ecl_sum_tstep_set_from_node( tstep , *node2 , report_step*1000 + 100); } sim_seconds += ministep_length * 3; } ecl_sum_fwrite( ecl_sum ); ecl_sum_free(ecl_sum); - verify_CASE2(); + verify_CASE2(num_dates); } } -void verify_CASE3() { +void verify_CASE3(int length) { + const int params_size = 3; ecl_sum_type * sum = ecl_sum_fread_alloc_case2__("CASE3", ":", false, true, 0); - for (int i=0; i < 3; i++) { + for (int i=0; i < params_size; i++) { double_vector_type * d = ecl_sum_alloc_data_vector(sum, i+1, false); - //test_assert_int_equal(4, double_vector_size(d)); - for (int j=0; j < 4; j++) { + test_assert_int_equal(length, double_vector_size(d)); + for (int j=0; j < length; j++) { test_assert_double_equal( double_vector_iget(d, j), (2 - i)*1000 + (j + 1)*10000); } double_vector_free(d); @@ -168,15 +176,15 @@ void verify_CASE3() { ecl_sum_free(sum); sum = ecl_sum_fread_alloc_case("CASE3", ":"); - for (int i=0; i < 3; i++) { + for (int i=0; i < params_size; i++) { double_vector_type * d = ecl_sum_alloc_data_vector(sum, i+1, false); ieq(d,0,(2 - i)*10 + 100); ieq(d,1,(2 - i)*10 + 200); ieq(d,2,(2 - i)*10 + 300); if (i == 0) { - const smspec_node_type * node = ecl_smspec_iget_node(ecl_sum_get_smspec(sum), i); - double default_value = smspec_node_get_default(node); + const ecl::smspec_node& node = ecl_smspec_iget_node_w_params_index(ecl_sum_get_smspec(sum), i); + double default_value = node.get_default(); ieq(d,3,default_value); ieq(d,4,default_value); } else { @@ -190,12 +198,16 @@ void verify_CASE3() { double_vector_free(d); } + ecl_sum_vector_type * vector = ecl_sum_vector_alloc(sum, true); + double frame[27]; //3 vectors X 9 data points pr. vector + ecl_sum_init_double_frame(sum, vector, frame); + ecl_sum_vector_free(vector); + ecl_sum_free(sum); } void write_CASE3(bool unified) { - test_work_area_type * work_area = test_work_area_alloc("SMSPEC"); write_CASE2(unified); { time_t start_time = util_make_date_utc( 1,1,2010 ); @@ -204,29 +216,103 @@ void write_CASE3(bool unified) { double sim_seconds = ministep_length * 4.0 * 3; ecl_sum_type * ecl_sum = ecl_sum_alloc_restart_writer( "CASE3" , "CASE2", false , true , ":" , start_time , true , 10 , 10 , 10 ); - smspec_node_type * node3 = ecl_sum_add_var( ecl_sum , "BPR" , NULL , 3 , "BARS" , 0.0 ); - smspec_node_type * node2 = ecl_sum_add_var( ecl_sum , "BPR" , NULL , 2 , "BARS" , 0.0 ); - smspec_node_type * node1 = ecl_sum_add_var( ecl_sum , "BPR" , NULL , 1 , "BARS" , 0.0 ); + const ecl::smspec_node * node3 = ecl_sum_add_var( ecl_sum , "BPR" , NULL , 3 , "BARS" , 0.0 ); + const ecl::smspec_node * node2 = ecl_sum_add_var( ecl_sum , "BPR" , NULL , 2 , "BARS" , 0.0 ); + const ecl::smspec_node * node1 = ecl_sum_add_var( ecl_sum , "BPR" , NULL , 1 , "BARS" , 0.0 ); for (int report_step = 1; report_step <= num_dates; report_step++) { { ecl_sum_tstep_type * tstep = ecl_sum_add_tstep( ecl_sum , report_step + 5 , sim_seconds ); - ecl_sum_tstep_set_from_node( tstep , node1 , report_step*10000); - ecl_sum_tstep_set_from_node( tstep , node2 , report_step*10000 + 1000); - ecl_sum_tstep_set_from_node( tstep , node3 , report_step*10000 + 2000); + ecl_sum_tstep_set_from_node( tstep , *node1 , report_step*10000); + ecl_sum_tstep_set_from_node( tstep , *node2 , report_step*10000 + 1000); + ecl_sum_tstep_set_from_node( tstep , *node3 , report_step*10000 + 2000); } sim_seconds += ministep_length * 3; } ecl_sum_fwrite( ecl_sum ); ecl_sum_free(ecl_sum); - verify_CASE3(); + verify_CASE3(num_dates); } - test_work_area_free(work_area); } +void verify_CASE4() { + ecl_sum_type * sum = ecl_sum_fread_alloc_case("CASE4", ":"); + + double_vector_type * d; + d = ecl_sum_alloc_data_vector(sum, 0, false); double_vector_free(d); + d = ecl_sum_alloc_data_vector(sum, 1, false); double_vector_free(d); + d = ecl_sum_alloc_data_vector(sum, 2, false); double_vector_free(d); + d = ecl_sum_alloc_data_vector(sum, 4, false); + ieq(d, 0, -99); + ieq(d, 4, -99); + ieq(d, 5, 10000); + ieq(d, 8, 40000); + double_vector_free(d); + + ecl_sum_vector_type * vector = ecl_sum_vector_alloc(sum, true); + double frame[27]; //3 vectors X 9 data points pr. vector + ecl_sum_init_double_frame(sum, vector, frame); + test_assert_double_equal(frame[26], 40000); + ecl_sum_vector_free(vector); + + ecl_sum_free(sum); +} + + +void write_CASE4(bool unified) { + ecl::util::TestArea ta("case4"); + write_CASE3(unified); + { + ecl_file_type * sum_file = ecl_file_open("CASE3.UNSMRY", 0); + ecl_file_type * smspec_file = ecl_file_open("CASE3.SMSPEC", 0); + + ecl_kw_type * keywords = ecl_file_iget_named_kw(smspec_file, "KEYWORDS", 0); + ecl_kw_resize(keywords, 5); + ecl_kw_iset_char_ptr(keywords, 3, "WTPRWI1"); + ecl_kw_iset_char_ptr(keywords, 4, "BPR"); + + ecl_kw_type * nums = ecl_file_iget_named_kw(smspec_file, "NUMS", 0); + ecl_kw_resize(nums, 5); + unsigned int * nums_ptr = (unsigned int *)ecl_kw_get_int_ptr(nums); + nums_ptr[3] = 5; + nums_ptr[4] = 8; //a different + + ecl_kw_type * wgnames = ecl_file_iget_named_kw(smspec_file, "WGNAMES", 0); + ecl_kw_resize(wgnames, 5); + ecl_kw_iset_char_ptr(wgnames, 4, ":+:+:+:+"); + + ecl_kw_type * units = ecl_file_iget_named_kw(smspec_file, "UNITS", 0); + ecl_kw_resize(units, 5); + ecl_kw_iset_char_ptr(units, 4, "BARS"); + + int num_params = ecl_file_get_num_named_kw(sum_file, "PARAMS"); + for (int i = 0; i < num_params; i++) { + ecl_kw_type * params_kw = ecl_file_iget_named_kw(sum_file, "PARAMS", i); + ecl_kw_resize(params_kw, 5); + float * ptr = (float*)ecl_kw_get_void_ptr(params_kw); + ptr[4] = ptr[3]; + ptr[3] = -1; + } + + fortio_type * f; + const char * filename_sum = "CASE4.UNSMRY"; + f = fortio_open_writer( filename_sum, false, ECL_ENDIAN_FLIP ); + ecl_file_fwrite_fortio(sum_file, f, 0); + fortio_fclose( f ); + + const char * filename_smspec = "CASE4.SMSPEC"; + f = fortio_open_writer( filename_smspec, false, ECL_ENDIAN_FLIP ); + ecl_file_fwrite_fortio(smspec_file, f, 0); + fortio_fclose( f ); + + ecl_file_close(smspec_file); + ecl_file_close(sum_file); + verify_CASE4(); + } +} int main() { - write_CASE3(true); - write_CASE3(false); + write_CASE4(true); + write_CASE4(false); return 0; } diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_sum_report_step_compatible.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_sum_report_step_compatible.cpp index 4cd4b1ece4..673755d55b 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_sum_report_step_compatible.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_sum_report_step_compatible.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'ecl_sum_test.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_sum_report_step_equal.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_sum_report_step_equal.cpp index d9b30efa0e..93f8b3f572 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_sum_report_step_equal.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_sum_report_step_equal.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'ecl_sum_test.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_sum_restart.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_sum_restart.cpp new file mode 100644 index 0000000000..aa247fcd29 --- /dev/null +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_sum_restart.cpp @@ -0,0 +1,167 @@ +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +/* + +CASE1 +--------- +1 : BPR:1 100 200 300 400 500 600 700 800 900 .... +2 : BPR:2 110 210 310 410 510 610 710 810 910 .... +3 : BRP:3 120 220 320 420 520 620 720 820 920 .... + + + +CASE2 +--------- +1 : BRP:2 1100 2100 3100 4100 +2 : BPR:1 1000 2000 3000 4000 + + + +Total CASE2: +------------ +1 : BPR:2 110 210 310 1100 2100 3100 4100 +2 : BRP:1 100 200 300 1000 2000 3000 4000 + + + +CASE3 +----- +1 : BPR:3 12000 22000 32000 42000 +2 : BRP:2 11000 21000 31000 41000 +3 : BPR:1 10000 20000 30000 40000 + + +Total CASE3: +------------ +1 : BPR:3 120 220 320 0 0 12000 22000 32000 42000 +2 : BPR:2 110 210 310 1100 2100 11000 21000 31000 41000 +3 : BPR:1 100 200 300 1000 2000 10000 20000 30000 40000 + +*/ + + +#define ieq(d,i,v) test_assert_double_equal(double_vector_iget(d,(i)), v) + + +void verify_CASE1(int length) { + ecl_sum_type * sum = ecl_sum_fread_alloc_case("CASE1", ":"); + int params_size = 4; // TIME, BPR:1, BPR:2, BPR:3 + + for (int i=1; i < params_size; i++) { + double_vector_type * d = ecl_sum_alloc_data_vector(sum, i, false); + test_assert_int_equal(length, double_vector_size(d)); + for (int j=0; j < length; j++) { + test_assert_double_equal( double_vector_iget(d, j), (i - 1)*10 + (j + 1)*100); + } + double_vector_free(d); + } + ecl_sum_free(sum); +} + + +void verify_CASE2(int length) { + ecl_sum_type * sum = ecl_sum_fread_alloc_case2__("CASE2", ":", false, true, 0); + const int params_size = 2; // TIME, BPR:2, BPR:1 + + for (int i=0; i < params_size; i++) { + double_vector_type * d = ecl_sum_alloc_data_vector(sum, i+1, false); + test_assert_int_equal(length, double_vector_size(d)); + for (int j=1; j < length; j++) + test_assert_double_equal( double_vector_iget(d, j-1), (1 - i)*100 + j*1000); + double_vector_free(d); + } + + ecl_sum_free(sum); + + sum = ecl_sum_fread_alloc_case("CASE2", ":"); + for (int i=0; i < params_size; i++) { + double_vector_type * d = ecl_sum_alloc_data_vector(sum, i+1, false); + test_assert_int_equal(double_vector_size(d), 4); + ieq(d,0,(1 - i)*100 + 1000); + ieq(d,1,(1 - i)*100 + 2000); + ieq(d,2,(1 - i)*100 + 3000); + ieq(d,3,(1 - i)*100 + 4000); + double_vector_free(d); + } + + ecl_sum_free(sum); +} + + +void write_CASE1(bool unified) { + time_t start_time = util_make_date_utc( 1,1,2010 ); + ecl_sum_type * ecl_sum = ecl_sum_alloc_writer( "CASE1" , false , unified, ":" , start_time , true , 10 , 10 , 10 ); + double sim_seconds = 0; + + int num_dates = 100; + double ministep_length = 86400; // seconds in a day + + const ecl::smspec_node * node1 = ecl_sum_add_var( ecl_sum , "BPR" , NULL , 1 , "BARS" , 0.0 ); + const ecl::smspec_node * node2 = ecl_sum_add_var( ecl_sum , "BPR" , NULL , 2 , "BARS" , 0.0 ); + const ecl::smspec_node * node3 = ecl_sum_add_var( ecl_sum , "BPR" , NULL , 3 , "BARS" , 0.0 ); + + for (int report_step = 0; report_step < num_dates; report_step++) { + { + ecl_sum_tstep_type * tstep = ecl_sum_add_tstep( ecl_sum , report_step + 1 , sim_seconds ); + ecl_sum_tstep_set_from_node( tstep , *node1 , (1 + report_step) * 100 ); + ecl_sum_tstep_set_from_node( tstep , *node2 , (1 + report_step) * 100 + 10.0 ); + ecl_sum_tstep_set_from_node( tstep , *node3 , (1 + report_step) * 100 + 20.0 ); + } + sim_seconds += ministep_length * 3; + } + ecl_sum_fwrite( ecl_sum ); + ecl_sum_free(ecl_sum); + + verify_CASE1(num_dates); +} + + + + +void write_CASE2() { + bool unified = false; + write_CASE1(unified); + { + time_t start_time = util_make_date_utc( 1,1,2010 ); + int num_dates = 4; + double ministep_length = 86400; // seconds in a day + double sim_seconds = ministep_length * 2.5 * 3; + ecl_sum_type * ecl_sum = ecl_sum_alloc_restart_writer( "CASE2" , "CASE1", false , true , ":" , start_time , true , 10 , 10 , 10 ); + + const ecl::smspec_node * node2 = ecl_sum_add_var( ecl_sum , "BPR" , NULL , 2 , "BARS" , 0.0 ); + const ecl::smspec_node * node1 = ecl_sum_add_var( ecl_sum , "BPR" , NULL , 1 , "BARS" , 0.0 ); + + for (int report_step = 1; report_step <= num_dates; report_step++) { + { + ecl_sum_tstep_type * tstep = ecl_sum_add_tstep( ecl_sum , report_step + 3 , sim_seconds ); + ecl_sum_tstep_set_from_node( tstep , *node1 , report_step*1000); + ecl_sum_tstep_set_from_node( tstep , *node2 , report_step*1000 + 100); + } + sim_seconds += ministep_length * 3; + } + ecl_sum_fwrite( ecl_sum ); + ecl_sum_free(ecl_sum); + + util_unlink("CASE1.SMSPEC"); + + verify_CASE2(num_dates); + } +} + +int main() { + write_CASE2(); + return 0; +} diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_sum_test.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_sum_test.cpp index 9b049bdb79..58d6f693be 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_sum_test.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_sum_test.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'ecl_sum_test.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_sum_writer.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_sum_writer.cpp index 2fb3abb4c9..9db9f9f4d6 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_sum_writer.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_sum_writer.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2016 Statoil ASA, Norway. + Copyright (C) 2016 Equinor ASA, Norway. The file 'ecl_sum_writer.c' is part of ERT - Ensemble based Reservoir Tool. @@ -32,10 +32,13 @@ double write_summary( const char * name , time_t start_time , int nx , int ny , int nz , int num_dates, int num_ministep, double ministep_length) { ecl_sum_type * ecl_sum = ecl_sum_alloc_writer( name , false , true , ":" , start_time , true , nx , ny , nz ); double sim_seconds = 0; + ecl_smspec_type * smspec = ecl_sum_get_smspec( ecl_sum ); - smspec_node_type * node1 = ecl_sum_add_var( ecl_sum , "FOPT" , NULL , 0 , "Barrels" , 99.0 ); - smspec_node_type * node2 = ecl_sum_add_var( ecl_sum , "BPR" , NULL , 567 , "BARS" , 0.0 ); - smspec_node_type * node3 = ecl_sum_add_var( ecl_sum , "WWCT" , "OP-1" , 0 , "(1)" , 0.0 ); + test_assert_int_equal( ecl_smspec_get_params_size( smspec ), 1); + const ecl::smspec_node * node1 = ecl_smspec_add_node( smspec , "FOPT" , "Barrels", 99.0); + const ecl::smspec_node * node2 = ecl_smspec_add_node( smspec , "BPR" , 567 , "BARS", 0.0 ); + const ecl::smspec_node * node3 = ecl_smspec_add_node( smspec , "WWCT" , "OP-1" , "(1)" , 0.0 ); + test_assert_int_equal( ecl_smspec_get_params_size( smspec ), 4); for (int report_step = 0; report_step < num_dates; report_step++) { for (int step = 0; step < num_ministep; step++) { @@ -43,13 +46,13 @@ double write_summary( const char * name , time_t start_time , int nx , int ny , { ecl_sum_tstep_type * tstep = ecl_sum_add_tstep( ecl_sum , report_step + 1 , sim_seconds ); - ecl_sum_tstep_set_from_node( tstep , node1 , sim_seconds ); - ecl_sum_tstep_set_from_node( tstep , node2 , 10*sim_seconds ); - ecl_sum_tstep_set_from_node( tstep , node3 , 100*sim_seconds ); + ecl_sum_tstep_set_from_node( tstep , *node1 , sim_seconds ); + ecl_sum_tstep_set_from_node( tstep , *node2 , 10*sim_seconds ); + ecl_sum_tstep_set_from_node( tstep , *node3 , 100*sim_seconds ); - test_assert_double_equal( ecl_sum_tstep_get_from_node( tstep , node1 ), sim_seconds ); - test_assert_double_equal( ecl_sum_tstep_get_from_node( tstep , node2 ), sim_seconds*10 ); - test_assert_double_equal( ecl_sum_tstep_get_from_node( tstep , node3 ), sim_seconds*100 ); + test_assert_double_equal( ecl_sum_tstep_get_from_node( tstep , *node1 ), sim_seconds ); + test_assert_double_equal( ecl_sum_tstep_get_from_node( tstep , *node2 ), sim_seconds*10 ); + test_assert_double_equal( ecl_sum_tstep_get_from_node( tstep , *node3 ), sim_seconds*100 ); } sim_seconds += ministep_length; } @@ -61,20 +64,20 @@ double write_summary( const char * name , time_t start_time , int nx , int ny , int write_restart_summary(const char * name, const char * restart_name , int start_report_step, double sim_seconds, time_t start_time , int nx , int ny , int nz , int num_dates, int num_ministep, double ministep_length) { ecl_sum_type * ecl_sum = ecl_sum_alloc_restart_writer( name , restart_name, false , true , ":" , start_time , true , nx , ny , nz ); + ecl_smspec_type * smspec = ecl_sum_get_smspec( ecl_sum ); - - smspec_node_type * node1 = ecl_sum_add_var( ecl_sum , "FOPT" , NULL , 0 , "Barrels" , 99.0 ); - smspec_node_type * node2 = ecl_sum_add_var( ecl_sum , "BPR" , NULL , 567 , "BARS" , 0.0 ); - smspec_node_type * node3 = ecl_sum_add_var( ecl_sum , "WWCT" , "OP-1" , 0 , "(1)" , 0.0 ); + const ecl::smspec_node * node1 = ecl_smspec_add_node( smspec , "FOPT", "Barrels" , 99.0 ); + const ecl::smspec_node * node2 = ecl_smspec_add_node( smspec , "BPR" , 567 , "BARS" , 0.0 ); + const ecl::smspec_node * node3 = ecl_smspec_add_node( smspec , "WWCT" , "OP-1" , "(1)", 0.0 ); int num_report_steps = start_report_step + num_dates; for (int report_step = start_report_step; report_step < num_report_steps; report_step++) { for (int step = 0; step < num_ministep; step++) { { ecl_sum_tstep_type * tstep = ecl_sum_add_tstep( ecl_sum , report_step + 1 , sim_seconds ); - ecl_sum_tstep_set_from_node( tstep , node1 , sim_seconds); - ecl_sum_tstep_set_from_node( tstep , node2 , 10*sim_seconds ); - ecl_sum_tstep_set_from_node( tstep , node3 , 100*sim_seconds ); + ecl_sum_tstep_set_from_node( tstep , *node1 , sim_seconds); + ecl_sum_tstep_set_from_node( tstep , *node2 , 10*sim_seconds ); + ecl_sum_tstep_set_from_node( tstep , *node3 , 100*sim_seconds ); } sim_seconds += ministep_length; @@ -97,17 +100,24 @@ void test_write_read( ) { int num_ministep = 10; double ministep_length = 86400; // Seconds - numerical value chosen to avoid rounding problems when converting between seconds and days. { - test_work_area_type * work_area = test_work_area_alloc("sum/write"); ecl_sum_type * ecl_sum; - write_summary( name , start_time , nx , ny , nz , num_dates , num_ministep , ministep_length); + auto seconds = write_summary( name , start_time , nx , ny , nz , num_dates , num_ministep , ministep_length); ecl_sum = ecl_sum_fread_alloc_case( name , ":" ); test_assert_true( ecl_sum_is_instance( ecl_sum )); + printf("days: %g \n", seconds / 86400.0 ); + /* Time direction */ test_assert_time_t_equal( start_time , ecl_sum_get_start_time(ecl_sum)); test_assert_time_t_equal( start_time , ecl_sum_get_data_start(ecl_sum)); util_inplace_forward_seconds_utc(&end_time, (num_dates * num_ministep - 1) * ministep_length ); + { + time_t et = ecl_sum_get_end_time(ecl_sum); + printf("days: %g \n", 1.0 * (et - start_time) / 86400); + printf("days: %g \n", 1.0 * (end_time - start_time) / 86400); + printf("%ld %ld diff:%ld fraction:%g \n", end_time, et, end_time - et , 1.0 * et / end_time); + } test_assert_time_t_equal( end_time , ecl_sum_get_end_time(ecl_sum)); /* Keys */ @@ -126,14 +136,13 @@ void test_write_read( ) { } ecl_sum_free( ecl_sum ); - test_work_area_free( work_area ); + //test_work_area_free( work_area ); } } void test_ecl_sum_alloc_restart_writer() { - - test_work_area_type * work_area = test_work_area_alloc("sum_write_restart"); + ecl::util::TestArea ta("sum_write_restart"); { const char * name1 = "CASE1"; const char * name2 = "CASE2"; @@ -170,7 +179,6 @@ void test_ecl_sum_alloc_restart_writer() { ecl_file_close(restart_file); } - test_work_area_free( work_area ); } @@ -182,7 +190,7 @@ void test_long_restart_names() { strcat(restart_case, s); } const char * name = "THE_CASE"; - test_work_area_type * work_area = test_work_area_alloc("sum_write_restart_long_name"); + ecl::util::TestArea ta("suM_write_restart_long_name"); { int restart_step = 77; time_t start_time = util_make_date_utc( 1,1,2010 ); @@ -210,12 +218,10 @@ void test_long_restart_names() { ecl_smspec_free( smspec); } } - - test_work_area_free( work_area ); - } int main( int argc , char ** argv) { + util_install_signals(); test_write_read(); test_ecl_sum_alloc_restart_writer(); test_long_restart_names(); diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_unsmry_loader_test.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_unsmry_loader_test.cpp index 55606a6ffa..e142b78cab 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_unsmry_loader_test.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_unsmry_loader_test.cpp @@ -17,16 +17,16 @@ ecl_sum_type * write_ecl_sum() { int num_dates = 4; double ministep_length = 86400; // seconds in a day - smspec_node_type * node1 = ecl_sum_add_var( ecl_sum , "FOPT" , NULL , 0 , "Barrels" , 99.0 ); - smspec_node_type * node2 = ecl_sum_add_var( ecl_sum , "BPR" , NULL , 567 , "BARS" , 0.0 ); - smspec_node_type * node3 = ecl_sum_add_var( ecl_sum , "WWCT" , "OP-1" , 0 , "(1)" , 0.0 ); + const ecl::smspec_node * node1 = ecl_sum_add_var( ecl_sum , "FOPT" , NULL , 0 , "Barrels" , 99.0 ); + const ecl::smspec_node * node2 = ecl_sum_add_var( ecl_sum , "BPR" , NULL , 567 , "BARS" , 0.0 ); + const ecl::smspec_node * node3 = ecl_sum_add_var( ecl_sum , "WWCT" , "OP-1" , 0 , "(1)" , 0.0 ); for (int report_step = 0; report_step < num_dates; report_step++) { { ecl_sum_tstep_type * tstep = ecl_sum_add_tstep( ecl_sum , report_step + 1 , sim_seconds ); - ecl_sum_tstep_set_from_node( tstep , node1 , report_step*2.0 ); - ecl_sum_tstep_set_from_node( tstep , node2 , report_step*4.0 + 2.0 ); - ecl_sum_tstep_set_from_node( tstep , node3 , report_step*6.0 + 4.0 ); + ecl_sum_tstep_set_from_node( tstep , *node1 , report_step*2.0 ); + ecl_sum_tstep_set_from_node( tstep , *node2 , report_step*4.0 + 2.0 ); + ecl_sum_tstep_set_from_node( tstep , *node3 , report_step*6.0 + 4.0 ); } sim_seconds += ministep_length * 3; @@ -36,7 +36,7 @@ ecl_sum_type * write_ecl_sum() { } void test_load() { - test_work_area_type * work_area = test_work_area_alloc("unsmry_loader"); + ecl::util::TestArea ta("ecl_sum_loader"); ecl_sum_type * ecl_sum = write_ecl_sum(); test_assert_true( util_file_exists("CASE.SMSPEC") ); test_assert_true( util_file_exists("CASE.UNSMRY") ); @@ -52,7 +52,6 @@ void test_load() { delete loader; ecl_sum_free(ecl_sum); - test_work_area_free(work_area); } int main() { diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_util_filenames.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_util_filenames.cpp index 65bc7d58fd..afc25cb970 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_util_filenames.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_util_filenames.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2018 Statoil ASA, Norway. + Copyright (C) 2018 Equinor ASA, Norway. The file 'ecl_util_filenames.c' is part of ERT - Ensemble based Reservoir Tool. @@ -33,14 +33,21 @@ void test_filename_report_nr() { } void test_filename_case() { - test_assert_NULL( ecl_util_alloc_filename(NULL, "mixedBase", ECL_EGRID_FILE, false, -1)); - test_assert_string_equal( ecl_util_alloc_filename(NULL, "UPPER", ECL_EGRID_FILE, false, -1), "UPPER.EGRID"); - test_assert_string_equal( ecl_util_alloc_filename(NULL , "lower", ECL_EGRID_FILE, false, -1), "lower.egrid"); + char * f1 = ecl_util_alloc_filename(NULL, "mixedBase", ECL_EGRID_FILE, false, -1); + char * f2 = ecl_util_alloc_filename(NULL, "UPPER", ECL_EGRID_FILE, false, -1); + char * f3 = ecl_util_alloc_filename(NULL , "lower", ECL_EGRID_FILE, false, -1); + + test_assert_NULL( f1 ); + test_assert_string_equal( f2 , "UPPER.EGRID"); + test_assert_string_equal( f3 , "lower.egrid"); + + free(f2); + free(f3); } void test_file_list() { - test_work_area_type * work_area = test_work_area_alloc("RESTART_FILES"); + ecl::util::TestArea ta("file_list"); stringlist_type * s = stringlist_alloc_new(); for (int i = 0; i < 10; i += 2) { @@ -109,7 +116,6 @@ void test_file_list() { test_assert_int_equal(stringlist_get_size(s), 10); stringlist_free(s); - test_work_area_free(work_area); } diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_util_make_date_no_shift.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_util_make_date_no_shift.cpp index b4d6cc1eaa..6af65736e0 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_util_make_date_no_shift.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_util_make_date_no_shift.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'ecl_util_make_date_no_shift.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_util_make_date_shift.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_util_make_date_shift.cpp index 73fa007994..159a874b0f 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_util_make_date_shift.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_util_make_date_shift.cpp @@ -1,4 +1,4 @@ - /* Copyright (C) 2013 Statoil ASA, Norway. + /* Copyright (C) 2013 Equinor ASA, Norway. The file 'ecl_util_make_date_shift.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_util_month_range.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_util_month_range.cpp index afd3d7af11..f708805d15 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_util_month_range.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_util_month_range.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'ecl_util_month_range.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_util_path_access.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_util_path_access.cpp index 470acebe53..f1821756cb 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_util_path_access.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_util_path_access.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2018 Statoil ASA, Norway. + Copyright (C) 2018 Equinor ASA, Norway. The file 'ecl_util_path_access.c' is part of ERT - Ensemble based Reservoir Tool. @@ -27,7 +27,7 @@ void test_relative_access() { - test_work_area_type * work_area = test_work_area_alloc("access"); + ecl::util::TestArea ta("ecl_access"); test_assert_false( ecl_util_path_access("No/directory/does/not/exist")); util_make_path("path"); @@ -44,7 +44,6 @@ void test_relative_access() { test_assert_false( ecl_util_path_access("path/file")); test_assert_true( ecl_util_path_access("ECLIPSE_CASE")); - test_work_area_free( work_area ); } diff --git a/ThirdParty/Ert/lib/ecl/tests/ecl_valid_basename.cpp b/ThirdParty/Ert/lib/ecl/tests/ecl_valid_basename.cpp index b275c4300f..f69e5d47d7 100644 --- a/ThirdParty/Ert/lib/ecl/tests/ecl_valid_basename.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/ecl_valid_basename.cpp @@ -5,7 +5,7 @@ * Author: joaho */ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'ecl_lgr_test.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/eclxx_filename.cpp b/ThirdParty/Ert/lib/ecl/tests/eclxx_filename.cpp index 1dd75bd20e..cb9b2e05c8 100644 --- a/ThirdParty/Ert/lib/ecl/tests/eclxx_filename.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/eclxx_filename.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2017 Statoil ASA, Norway. + Copyright (C) 2017 Equinor ASA, Norway. This file is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/eclxx_fortio.cpp b/ThirdParty/Ert/lib/ecl/tests/eclxx_fortio.cpp index bbfab425cb..238572e725 100644 --- a/ThirdParty/Ert/lib/ecl/tests/eclxx_fortio.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/eclxx_fortio.cpp @@ -1,5 +1,5 @@ /* - Copyright 2015 Statoil ASA. + Copyright 2015 Equinor ASA. This file is part of the Open Porous Media project (OPM). @@ -28,7 +28,7 @@ void test_open() { - test_work_area_type * work_area = test_work_area_alloc("FORTIO"); + ecl::util::TestArea ta("fortioxx"); ERT::FortIO fortio; fortio.open( "new_file" , std::fstream::out ); @@ -67,12 +67,11 @@ void test_open() { } test_assert_false( fortio.ftruncate( 0 )); fortio.close(); - test_work_area_free(work_area); } void test_fortio() { - test_work_area_type * work_area = test_work_area_alloc("FORTIO"); + ecl::util::TestArea ta("FORTIO"); ERT::FortIO fortio("new_file" , std::fstream::out ); { std::vector data; @@ -97,12 +96,11 @@ void test_fortio() { fortio.close(); test_assert_throw( ERT::FortIO fortio("file/does/not/exists" , std::fstream::in) , std::invalid_argument ); - test_work_area_free(work_area); } void test_fortio_kw() { - test_work_area_type * work_area = test_work_area_alloc("FORTIO"); + ecl::util::TestArea ta("fortio_kw"); std::vector< int > vec( 1000 ); for (size_t i =0 ; i < vec.size(); i++) @@ -123,12 +121,7 @@ void test_fortio_kw() { for (size_t i =0 ; i < kw.size(); i++) test_assert_int_equal( kw.at( i ), kw2.at( i ) ); - - fortio = ERT::FortIO("new_file" , std::fstream::in ); - test_assert_throw( ERT::EclKW::load(fortio) , std::invalid_argument ); - fortio.close(); } - test_work_area_free(work_area); } diff --git a/ThirdParty/Ert/lib/ecl/tests/eclxx_kw.cpp b/ThirdParty/Ert/lib/ecl/tests/eclxx_kw.cpp index f348304c33..a3c561681c 100644 --- a/ThirdParty/Ert/lib/ecl/tests/eclxx_kw.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/eclxx_kw.cpp @@ -1,5 +1,5 @@ /* - Copyright 2015 Statoil ASA. + Copyright 2015 Equinor ASA. This file is part of the Open Porous Media project (OPM). @@ -170,7 +170,7 @@ void test_read_write() { std::vector s_data = {"S1", "S2", "S3"}; { - test_work_area_type * work_area = test_work_area_alloc("READ_WRITE"); + ecl::util::TestArea ta("kw-read-write"); { ERT::FortIO f("test_file", std::ios_base::out); ERT::write_kw(f, "DOUBLE", d_data); @@ -208,7 +208,6 @@ void test_read_write() { } ecl_file_close(f); - test_work_area_free(work_area); } } } diff --git a/ThirdParty/Ert/lib/ecl/tests/eclxx_smspec.cpp b/ThirdParty/Ert/lib/ecl/tests/eclxx_smspec.cpp deleted file mode 100644 index ca134cf6f9..0000000000 --- a/ThirdParty/Ert/lib/ecl/tests/eclxx_smspec.cpp +++ /dev/null @@ -1,130 +0,0 @@ -/* - Copyright 2015 Statoil ASA. - - This file is part of the Open Porous Media project (OPM). - - OPM 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. - - OPM 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 for more details. - - You should have received a copy of the GNU General Public License - along with OPM. If not, see . -*/ - -#include -#include - -#include - -void test_smspec_copy() { - std::string kw( "FOPT" ); - ERT::smspec_node field( kw ); - - ERT::smspec_node copy( field ); -} - -void test_smspec_get() { - std::string kw( "FOPT" ); - ERT::smspec_node field( kw ); - - test_assert_true( field.get() != nullptr ); -} - -void test_smspec_move() { - std::string kw( "FOPT" ); - ERT::smspec_node field( kw ); - ERT::smspec_node move_ctor( std::move( field ) ); - auto move_assignment = std::move( move_ctor ); -} - -void test_smspec_wg() { - std::string wkw( "WWCT" ); - std::string gkw( "GWCT" ); - std::string wg( "OP1" ); - std::string gr( "WG1" ); - - ERT::smspec_node well( ECL_SMSPEC_WELL_VAR, wg, wkw ); - ERT::smspec_node group( ECL_SMSPEC_GROUP_VAR, gr, gkw ); - - test_assert_string_equal(well.key1() , "WWCT:OP1"); - test_assert_string_equal(well.keyword() , "WWCT"); - test_assert_true(well.wgname() == wg); - test_assert_true(well.type() == ECL_SMSPEC_WELL_VAR ); - - test_assert_string_equal(group.key1(), "GWCT:WG1"); - test_assert_string_equal(group.keyword() , "GWCT"); - test_assert_true(group.wgname() == gr); - test_assert_true(group.type() == ECL_SMSPEC_GROUP_VAR ); -} - -void test_smspec_field() { - std::string kw( "FOPT" ); - ERT::smspec_node field( kw ); - - test_assert_string_equal( field.key1() , "FOPT" ); - test_assert_true( field.keyword() == kw ); - test_assert_true( field.type() == ECL_SMSPEC_FIELD_VAR ); -} - -void test_smspec_block() { - std::string kw( "BPR" ); - int dims[ 3 ] = { 10, 10, 10 }; - int ijk[ 3 ] = { 5, 5, 5 }; - - ERT::smspec_node block( kw, dims, ijk ); - - // Observe that ERT::smspec_node( ) constructor is considered part - // of the developer API, with offset zero indices, whereas the - // key1() string is meant for user consumption and has offset 1 - - // what a mess! - test_assert_string_equal( block.key1(), "BPR:6,6,6" ); - test_assert_true( block.keyword() == kw ); - test_assert_true( block.type() == ECL_SMSPEC_BLOCK_VAR ); - test_assert_true( block.num() == 556 ); -} - -void test_smspec_misc() { - ERT::smspec_node tcpu( "TCPU" ); - test_assert_true( tcpu.type() == ECL_SMSPEC_MISC_VAR ); -} - - -void test_smspec_region() { - std::string kw( "ROIP" ); - int dims[ 3 ] = { 10, 10, 10 }; - ERT::smspec_node region( kw, dims, 0 ); - - test_assert_true( region.keyword() == kw ); - test_assert_true( region.type() == ECL_SMSPEC_REGION_VAR ); - test_assert_true( region.num() == 0 ); -} - -void test_smspec_completion() { - std::string kw( "CWIT" ); - std::string wg( "WELL1" ); - int dims[ 3 ] = { 10, 10, 10 }; - int ijk[ 3 ] = { 1, 1, 1 }; - ERT::smspec_node completion( kw, wg, dims, ijk ); - - test_assert_true( completion.keyword() == kw ); - test_assert_true( completion.type() == ECL_SMSPEC_COMPLETION_VAR ); - test_assert_true( completion.num() == 112 ); -} - -int main (int argc, char **argv) { - test_smspec_copy(); - test_smspec_move(); - test_smspec_get(); - test_smspec_wg(); - test_smspec_field(); - test_smspec_block(); - test_smspec_region(); - test_smspec_completion(); - test_smspec_misc(); -} diff --git a/ThirdParty/Ert/lib/ecl/tests/eclxx_types.cpp b/ThirdParty/Ert/lib/ecl/tests/eclxx_types.cpp index 7b04d9414d..c1098b2e0e 100644 --- a/ThirdParty/Ert/lib/ecl/tests/eclxx_types.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/eclxx_types.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2017 Statoil ASA, Norway. + Copyright (C) 2017 Equinor ASA, Norway. This file is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/rft_test.cpp b/ThirdParty/Ert/lib/ecl/tests/rft_test.cpp index 4bd4b85f5f..fae3c59b93 100644 --- a/ThirdParty/Ert/lib/ecl/tests/rft_test.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/rft_test.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'rft_test.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/test_ecl_file_index.cpp b/ThirdParty/Ert/lib/ecl/tests/test_ecl_file_index.cpp index 59f59bb79e..5a4fc201ea 100644 --- a/ThirdParty/Ert/lib/ecl/tests/test_ecl_file_index.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/test_ecl_file_index.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2017 Statoil ASA, Norway. + Copyright (C) 2017 Equinor ASA, Norway. The file 'test_ecl_file_index.c' is part of ERT - Ensemble based Reservoir Tool. @@ -34,7 +34,7 @@ void test_load_nonexisting_file() { void test_create_and_load_index_file() { - test_work_area_type * work_area = test_work_area_alloc("ecl_file_index_testing"); + ecl::util::TestArea ta("Load_index"); { const char * file_name = "initial_data_file"; const char * index_file_name = "index_file"; @@ -98,7 +98,6 @@ void test_create_and_load_index_file() { ecl_kw_free(kw2); ecl_file_close( ecl_file_index ); } - test_work_area_free( work_area ); } diff --git a/ThirdParty/Ert/lib/ecl/tests/test_ecl_nnc_data.cpp b/ThirdParty/Ert/lib/ecl/tests/test_ecl_nnc_data.cpp index a68185e61f..cc5f3cf460 100644 --- a/ThirdParty/Ert/lib/ecl/tests/test_ecl_nnc_data.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/test_ecl_nnc_data.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2017 Statoil ASA, Norway. + Copyright (C) 2017 Equinor ASA, Norway. The file 'test_ecl_nnc_data.c' is part of ERT - Ensemble based Reservoir Tool. @@ -34,7 +34,7 @@ void test_alloc_global_only(bool data_in_file) { - test_work_area_type * work_area = test_work_area_alloc("nnc-INIT"); + ecl::util::TestArea ta("nnc-INIT"); { int nx = 10; int ny = 10; @@ -90,7 +90,6 @@ void test_alloc_global_only(bool data_in_file) { } ecl_grid_free( grid0 ); } - test_work_area_free( work_area ); } diff --git a/ThirdParty/Ert/lib/ecl/tests/test_transactions.cpp b/ThirdParty/Ert/lib/ecl/tests/test_transactions.cpp index 1d6f9933ad..057f3f4fbc 100644 --- a/ThirdParty/Ert/lib/ecl/tests/test_transactions.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/test_transactions.cpp @@ -1,6 +1,6 @@ /* - Copyright (C) 2017 Statoil ASA, Norway. + Copyright (C) 2017 Equinor ASA, Norway. The file 'test_transactions.c' is part of ERT - Ensemble based Reservoir Tool. @@ -38,7 +38,7 @@ void test_transaction() { - test_work_area_type * work_area = test_work_area_alloc("ecl_file_index_testing"); + ecl::util::TestArea ta("index_testing"); { const char * file_name = "data_file"; fortio_type * fortio = fortio_open_writer(file_name, false, ECL_ENDIAN_FLIP); @@ -99,9 +99,10 @@ void test_transaction() { test_assert_false( ecl_file_kw_get_kw_ptr(file_kw2) ); ecl_file_close(file); - + ecl_kw_free(kw1); + ecl_kw_free(kw2); + ecl_kw_free(kw3); } - test_work_area_free( work_area ); } diff --git a/ThirdParty/Ert/lib/ecl/tests/well_branch_collection.cpp b/ThirdParty/Ert/lib/ecl/tests/well_branch_collection.cpp index df88ed73af..55cd4c8563 100644 --- a/ThirdParty/Ert/lib/ecl/tests/well_branch_collection.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/well_branch_collection.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'well_branch_collection.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/well_conn.cpp b/ThirdParty/Ert/lib/ecl/tests/well_conn.cpp index c81907c0bc..95ed85fdcd 100644 --- a/ThirdParty/Ert/lib/ecl/tests/well_conn.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/well_conn.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'well_conn.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/well_conn_CF.cpp b/ThirdParty/Ert/lib/ecl/tests/well_conn_CF.cpp index 27de6631d5..dc89d6a935 100644 --- a/ThirdParty/Ert/lib/ecl/tests/well_conn_CF.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/well_conn_CF.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'well_conn_load.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/well_conn_collection.cpp b/ThirdParty/Ert/lib/ecl/tests/well_conn_collection.cpp index d988c1b1e6..b843a6cb3b 100644 --- a/ThirdParty/Ert/lib/ecl/tests/well_conn_collection.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/well_conn_collection.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'well_conn_collection.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/well_conn_load.cpp b/ThirdParty/Ert/lib/ecl/tests/well_conn_load.cpp index 02fd157415..197d11f37d 100644 --- a/ThirdParty/Ert/lib/ecl/tests/well_conn_load.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/well_conn_load.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'well_conn_load.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/well_dualp.cpp b/ThirdParty/Ert/lib/ecl/tests/well_dualp.cpp index 30315df48e..abcc652a50 100644 --- a/ThirdParty/Ert/lib/ecl/tests/well_dualp.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/well_dualp.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'well_dualp.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/well_info.cpp b/ThirdParty/Ert/lib/ecl/tests/well_info.cpp index 2daf549175..e2f4fe3df0 100644 --- a/ThirdParty/Ert/lib/ecl/tests/well_info.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/well_info.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'well_conn.c' is part of ERT - Ensemble based Reservoir Tool. @@ -30,6 +30,7 @@ int main(int argc , char ** argv) { + util_install_signals(); const char * grid_file = argv[1]; ecl_grid_type * grid = ecl_grid_alloc( grid_file ); @@ -37,6 +38,9 @@ int main(int argc , char ** argv) { { well_info_type * well_info = well_info_alloc( grid ); test_assert_not_NULL( well_info ); + if (argc >= 3) + well_info_load_rstfile(well_info, argv[2], true); + well_info_free( well_info ); } ecl_grid_free( grid ); diff --git a/ThirdParty/Ert/lib/ecl/tests/well_lgr_load.cpp b/ThirdParty/Ert/lib/ecl/tests/well_lgr_load.cpp index 4e060c1772..86bfd96336 100644 --- a/ThirdParty/Ert/lib/ecl/tests/well_lgr_load.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/well_lgr_load.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'well_lgr_load.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/well_segment.cpp b/ThirdParty/Ert/lib/ecl/tests/well_segment.cpp index fd3062716a..512bf4be10 100644 --- a/ThirdParty/Ert/lib/ecl/tests/well_segment.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/well_segment.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'well_segment.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/well_segment_branch_conn_load.cpp b/ThirdParty/Ert/lib/ecl/tests/well_segment_branch_conn_load.cpp index 55761b2448..68b399ab4b 100644 --- a/ThirdParty/Ert/lib/ecl/tests/well_segment_branch_conn_load.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/well_segment_branch_conn_load.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'well_segment_conn_load.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/well_segment_collection.cpp b/ThirdParty/Ert/lib/ecl/tests/well_segment_collection.cpp index 8c28653adc..aafcded940 100644 --- a/ThirdParty/Ert/lib/ecl/tests/well_segment_collection.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/well_segment_collection.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'well_segment_collection.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/well_segment_conn.cpp b/ThirdParty/Ert/lib/ecl/tests/well_segment_conn.cpp index 9b53f16eaa..bd4d31b915 100644 --- a/ThirdParty/Ert/lib/ecl/tests/well_segment_conn.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/well_segment_conn.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'well_segment_conn.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/well_segment_conn_load.cpp b/ThirdParty/Ert/lib/ecl/tests/well_segment_conn_load.cpp index 92b213fbfd..9de125c64c 100644 --- a/ThirdParty/Ert/lib/ecl/tests/well_segment_conn_load.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/well_segment_conn_load.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'well_segment_conn_load.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/well_segment_load.cpp b/ThirdParty/Ert/lib/ecl/tests/well_segment_load.cpp index 6ca651d811..dc59ea1d4f 100644 --- a/ThirdParty/Ert/lib/ecl/tests/well_segment_load.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/well_segment_load.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'well_segment_load.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/well_state.cpp b/ThirdParty/Ert/lib/ecl/tests/well_state.cpp index 436aad1cd0..7c12b932dc 100644 --- a/ThirdParty/Ert/lib/ecl/tests/well_state.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/well_state.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'well_state.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/well_state_load.cpp b/ThirdParty/Ert/lib/ecl/tests/well_state_load.cpp index e78acdfcd5..52bbf88a46 100644 --- a/ThirdParty/Ert/lib/ecl/tests/well_state_load.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/well_state_load.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'well_state_load.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/well_state_load_missing_RSEG.cpp b/ThirdParty/Ert/lib/ecl/tests/well_state_load_missing_RSEG.cpp index d20955352b..a80f7aeda7 100644 --- a/ThirdParty/Ert/lib/ecl/tests/well_state_load_missing_RSEG.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/well_state_load_missing_RSEG.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'well_state_load_missing_RSEG.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/ecl/tests/well_ts.cpp b/ThirdParty/Ert/lib/ecl/tests/well_ts.cpp index 7a4dba9dc9..9fe458d8cb 100644 --- a/ThirdParty/Ert/lib/ecl/tests/well_ts.cpp +++ b/ThirdParty/Ert/lib/ecl/tests/well_ts.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'well_ts.c' is part of ERT - Ensemble based Reservoir Tool. @@ -70,7 +70,8 @@ int main(int argc , char ** argv) { well_info_load_rstfile( well_info , stringlist_iget(file_list , i), true); well_info_free( well_info ); } - + ecl_grid_free( grid ); + free( grid_file ); exit(0); } diff --git a/ThirdParty/Ert/lib/ecl/well_branch_collection.cpp b/ThirdParty/Ert/lib/ecl/well_branch_collection.cpp index 005419decf..46f5ef3e25 100644 --- a/ThirdParty/Ert/lib/ecl/well_branch_collection.cpp +++ b/ThirdParty/Ert/lib/ecl/well_branch_collection.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'well_branch_collection.c' is part of ERT - Ensemble based Reservoir Tool. @@ -18,10 +18,10 @@ #include +#include + #include #include -#include -#include #include #include @@ -33,8 +33,8 @@ struct well_branch_collection_struct { UTIL_TYPE_ID_DECLARATION; - vector_type * __start_segments; - int_vector_type * index_map; + std::vector __start_segments; + std::vector index_map; }; @@ -43,19 +43,24 @@ static UTIL_SAFE_CAST_FUNCTION( well_branch_collection , WELL_BRANCH_COLLECTION_ well_branch_collection_type * well_branch_collection_alloc() { - well_branch_collection_type * branch_collection = (well_branch_collection_type*)util_malloc( sizeof * branch_collection ); + well_branch_collection_type * branch_collection = new well_branch_collection_type(); UTIL_TYPE_ID_INIT( branch_collection , WELL_BRANCH_COLLECTION_TYPE_ID ); - branch_collection->__start_segments = vector_alloc_new(); - branch_collection->index_map = int_vector_alloc(0 , -1 ); return branch_collection; } +namespace { +int well_branch_collection_safe_iget_index( const well_branch_collection_type * branches, int index ) { + if (index >= (int)branches->index_map.size()) + return -1; + else + return branches->index_map[index]; +} + +} void well_branch_collection_free( well_branch_collection_type * branches ) { - vector_free( branches->__start_segments ); - int_vector_free( branches->index_map ); - free( branches ); + delete branches; } @@ -67,12 +72,12 @@ void well_branch_collection_free__( void * arg ) { int well_branch_collection_get_size( const well_branch_collection_type * branches ) { - return vector_get_size( branches->__start_segments ); + return branches->__start_segments.size(); } bool well_branch_collection_has_branch( const well_branch_collection_type * branches , int branch_id) { - if (int_vector_safe_iget( branches->index_map , branch_id) >= 0) + if (well_branch_collection_safe_iget_index( branches , branch_id) >= 0) return true; else return false; @@ -81,8 +86,8 @@ bool well_branch_collection_has_branch( const well_branch_collection_type * bran const well_segment_type * well_branch_collection_iget_start_segment( const well_branch_collection_type * branches , int index ) { - if (index < vector_get_size( branches->__start_segments)) - return (const well_segment_type*)vector_iget_const( branches->__start_segments , index); + if (index < static_cast(branches->__start_segments.size())) + return branches->__start_segments[index]; else return NULL; } @@ -90,7 +95,7 @@ const well_segment_type * well_branch_collection_iget_start_segment( const well_ const well_segment_type * well_branch_collection_get_start_segment( const well_branch_collection_type * branches , int branch_id) { - int internal_index = int_vector_safe_iget( branches->index_map , branch_id); + int internal_index = well_branch_collection_safe_iget_index( branches , branch_id); if (internal_index >= 0) return well_branch_collection_iget_start_segment( branches , internal_index ); else @@ -98,16 +103,18 @@ const well_segment_type * well_branch_collection_get_start_segment( const well_b } -bool well_branch_collection_add_start_segment( well_branch_collection_type * branches , const well_segment_type * start_segment) { +bool well_branch_collection_add_start_segment( well_branch_collection_type * branches , well_segment_type * start_segment) { if ((well_segment_get_link_count( start_segment ) == 0) && (well_segment_get_outlet(start_segment))) { int branch_id = well_segment_get_branch_id( start_segment ); - int current_index = int_vector_safe_iget( branches->index_map , branch_id); + int current_index = well_branch_collection_safe_iget_index( branches , branch_id); if (current_index >= 0) - vector_iset_ref( branches->__start_segments , current_index , start_segment); + branches->__start_segments[current_index] = start_segment; else { - int new_index = vector_get_size( branches->__start_segments ); - vector_append_ref( branches->__start_segments , start_segment); - int_vector_iset( branches->index_map , branch_id , new_index); + int new_index = branches->__start_segments.size(); + branches->__start_segments.push_back(start_segment); + if (branch_id >= (int)branches->index_map.size()) + branches->index_map.resize(branch_id+1, -1); + branches->index_map[branch_id] = new_index; } return true; diff --git a/ThirdParty/Ert/lib/ecl/well_conn.cpp b/ThirdParty/Ert/lib/ecl/well_conn.cpp index eaa8a90ac4..e3f2f2a890 100644 --- a/ThirdParty/Ert/lib/ecl/well_conn.cpp +++ b/ThirdParty/Ert/lib/ecl/well_conn.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'well_conn.c' is part of ERT - Ensemble based Reservoir Tool. @@ -92,7 +92,7 @@ UTIL_SAFE_CAST_FUNCTION( well_conn , WELL_CONN_TYPE_ID) static well_conn_type * well_conn_alloc__( int i , int j , int k , double connection_factor , well_conn_dir_enum dir , bool open, int segment_id, bool matrix_connection) { if (well_conn_assert_direction( dir , matrix_connection)) { - well_conn_type * conn = (well_conn_type*)util_malloc( sizeof * conn ); + well_conn_type * conn = new well_conn_type(); UTIL_TYPE_ID_INIT( conn , WELL_CONN_TYPE_ID ); conn->i = i; conn->j = j; @@ -245,7 +245,7 @@ well_conn_type * well_conn_alloc_from_kw( const ecl_kw_type * icon_kw , void well_conn_free( well_conn_type * conn) { - free( conn ); + delete conn; } diff --git a/ThirdParty/Ert/lib/ecl/well_conn_collection.cpp b/ThirdParty/Ert/lib/ecl/well_conn_collection.cpp index 788d25440a..1616e796dc 100644 --- a/ThirdParty/Ert/lib/ecl/well_conn_collection.cpp +++ b/ThirdParty/Ert/lib/ecl/well_conn_collection.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'well_conn_collection.c' is part of ERT - Ensemble based Reservoir Tool. @@ -18,9 +18,10 @@ #include +#include + #include #include -#include #include #include @@ -34,7 +35,8 @@ struct well_conn_collection_struct { UTIL_TYPE_ID_DECLARATION; - vector_type * connection_list; + std::vector connection_list; + std::vector connection_list_owned; }; @@ -43,9 +45,8 @@ static UTIL_SAFE_CAST_FUNCTION( well_conn_collection , WELL_CONN_COLLECTION_TYPE well_conn_collection_type * well_conn_collection_alloc() { - well_conn_collection_type * wellcc = (well_conn_collection_type*)util_malloc( sizeof * wellcc ); + well_conn_collection_type * wellcc = new well_conn_collection_type(); UTIL_TYPE_ID_INIT( wellcc , WELL_CONN_COLLECTION_TYPE_ID ); - wellcc->connection_list = vector_alloc_new(); return wellcc; } @@ -55,7 +56,8 @@ well_conn_collection_type * well_conn_collection_alloc() { */ void well_conn_collection_add( well_conn_collection_type * wellcc , well_conn_type * conn) { - vector_append_owned_ref( wellcc->connection_list , conn , well_conn_free__); + wellcc->connection_list.push_back(conn); + wellcc->connection_list_owned.push_back(true); } /* @@ -63,13 +65,16 @@ void well_conn_collection_add( well_conn_collection_type * wellcc , well_conn_ty */ void well_conn_collection_add_ref( well_conn_collection_type * wellcc , well_conn_type * conn) { - vector_append_ref( wellcc->connection_list , conn ); + wellcc->connection_list.push_back(conn); + wellcc->connection_list_owned.push_back(false); } void well_conn_collection_free( well_conn_collection_type * wellcc ) { - vector_free( wellcc->connection_list ); - free( wellcc ); + for (size_t i = 0; i < wellcc->connection_list.size(); i++) + if (wellcc->connection_list_owned[i]) + well_conn_free(wellcc->connection_list[i]); + delete wellcc; } void well_conn_collection_free__( void * arg ) { @@ -79,14 +84,14 @@ void well_conn_collection_free__( void * arg ) { int well_conn_collection_get_size( const well_conn_collection_type * wellcc ) { - return vector_get_size( wellcc->connection_list ); + return wellcc->connection_list.size(); } const well_conn_type * well_conn_collection_iget_const(const well_conn_collection_type * wellcc , int index) { int size = well_conn_collection_get_size( wellcc ); if (index < size) - return (const well_conn_type*)vector_iget_const( wellcc->connection_list , index ); + return wellcc->connection_list[index]; else return NULL; } @@ -95,7 +100,7 @@ const well_conn_type * well_conn_collection_iget_const(const well_conn_collectio well_conn_type * well_conn_collection_iget(const well_conn_collection_type * wellcc , int index) { int size = well_conn_collection_get_size( wellcc ); if (index < size) - return (well_conn_type*)vector_iget( wellcc->connection_list , index ); + return wellcc->connection_list[index]; else return NULL; } diff --git a/ThirdParty/Ert/lib/ecl/well_info.cpp b/ThirdParty/Ert/lib/ecl/well_info.cpp index b838955ff9..94f6692dd7 100644 --- a/ThirdParty/Ert/lib/ecl/well_info.cpp +++ b/ThirdParty/Ert/lib/ecl/well_info.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'well_info.c' is part of ERT - Ensemble based Reservoir Tool. @@ -21,10 +21,10 @@ #include #include +#include +#include #include -#include -#include #include #include @@ -182,7 +182,7 @@ struct well_info_struct { - hash_type * wells; /* Hash table of well_ts_type instances; indexed by well name. */ + std::map wells; /* std::map of well_ts_type instances; indexed by well name. */ std::vector well_names; /* A list of all the well names. */ const ecl_grid_type * grid; }; @@ -195,23 +195,25 @@ struct well_info_struct { well_info_type * well_info_alloc( const ecl_grid_type * grid) { well_info_type * well_info = new well_info_type(); - well_info->wells = hash_alloc(); well_info->grid = grid; return well_info; } bool well_info_has_well( well_info_type * well_info , const char * well_name ) { - return hash_has_key( well_info->wells , well_name ); + const auto it = well_info->wells.find(well_name); + if (it == well_info->wells.end()) + return false; + return true; } well_ts_type * well_info_get_ts( const well_info_type * well_info , const char *well_name) { - return (well_ts_type*)hash_get( well_info->wells , well_name ); + return well_info->wells.at( well_name ); } static void well_info_add_new_ts( well_info_type * well_info , const char * well_name) { well_ts_type * well_ts = well_ts_alloc( well_name ) ; - hash_insert_hash_owned_ref( well_info->wells , well_name , well_ts , well_ts_free__); + well_info->wells[well_name] = well_ts; well_info->well_names.push_back( well_name ); } @@ -353,7 +355,9 @@ void well_info_load_rst_eclfile( well_info_type * well_info , ecl_file_type * ec } void well_info_free( well_info_type * well_info ) { - hash_free( well_info->wells ); + for (const auto& pair : well_info->wells) + well_ts_free(pair.second); + delete well_info; } diff --git a/ThirdParty/Ert/lib/ecl/well_rseg_loader.cpp b/ThirdParty/Ert/lib/ecl/well_rseg_loader.cpp index c0bc317cc2..43c757ec2d 100644 --- a/ThirdParty/Ert/lib/ecl/well_rseg_loader.cpp +++ b/ThirdParty/Ert/lib/ecl/well_rseg_loader.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'well_info.c' is part of ERT - Ensemble based Reservoir Tool. @@ -79,6 +79,7 @@ double * well_rseg_loader_load_values(const well_rseg_loader_type * loader, int int_vector_type * index_map = loader->absolute_index_map; int index = 0; + int_vector_resize( index_map, int_vector_size(loader->relative_index_map), 0 ); for(index = 0; index < int_vector_size(loader->relative_index_map); index++) { int relative_index = int_vector_iget(loader->relative_index_map, index); int_vector_iset(index_map, index, relative_index + rseg_offset); diff --git a/ThirdParty/Ert/lib/ecl/well_segment.cpp b/ThirdParty/Ert/lib/ecl/well_segment.cpp index 8d3717847e..cfb041c7e8 100644 --- a/ThirdParty/Ert/lib/ecl/well_segment.cpp +++ b/ThirdParty/Ert/lib/ecl/well_segment.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'well_segment.c' is part of ERT - Ensemble based Reservoir Tool. @@ -18,8 +18,10 @@ #include +#include +#include + #include -#include #include #include @@ -39,7 +41,8 @@ struct well_segment_struct { int branch_id; int outlet_segment_id; // This is in the global index space given by the ISEG keyword. well_segment_type * outlet_segment; - hash_type * connections; // hash_type; + std::map connections; // hash_type; double depth; // The depth of the segment node; furthest away from the wellhead. double length; @@ -53,7 +56,7 @@ static UTIL_SAFE_CAST_FUNCTION( well_segment , WELL_SEGMENT_TYPE_ID ) well_segment_type * well_segment_alloc(int segment_id , int outlet_segment_id , int branch_id , const double * rseg_data) { - well_segment_type * segment = (well_segment_type*)util_malloc( sizeof * segment ); + well_segment_type * segment = new well_segment_type(); UTIL_TYPE_ID_INIT( segment , WELL_SEGMENT_TYPE_ID ); segment->link_count = 0; @@ -61,7 +64,6 @@ well_segment_type * well_segment_alloc(int segment_id , int outlet_segment_id , segment->outlet_segment_id = outlet_segment_id; segment->branch_id = branch_id; segment->outlet_segment = NULL; - segment->connections = hash_alloc(); segment->depth = 0.0; segment->length = 0.0; @@ -116,8 +118,10 @@ well_segment_type * well_segment_alloc_from_kw( const ecl_kw_type * iseg_kw , co void well_segment_free(well_segment_type * segment ) { - hash_free( segment->connections ); - free( segment ); + for (auto& pair : segment->connections) + well_conn_collection_free(pair.second); + + delete segment; } void well_segment_free__(void * arg) { @@ -196,7 +200,10 @@ void well_segment_link_strict( well_segment_type * segment , well_segment_type * bool well_segment_has_grid_connections( const well_segment_type * segment , const char * grid_name) { - return hash_has_key( segment->connections , grid_name ); + const auto it = segment->connections.find(grid_name); + if (it == segment->connections.end()) + return false; + return true; } @@ -208,13 +215,11 @@ bool well_segment_has_global_grid_connections( const well_segment_type * segment bool well_segment_add_connection( well_segment_type * segment , const char * grid_name , well_conn_type * conn) { int conn_segment_id = well_conn_get_segment_id( conn ); if (conn_segment_id == segment->segment_id) { - if (!well_segment_has_grid_connections( segment , grid_name )) - hash_insert_hash_owned_ref( segment->connections , grid_name , well_conn_collection_alloc() , well_conn_collection_free__ ); - { - well_conn_collection_type * connections = (well_conn_collection_type*)hash_get( segment->connections , grid_name ); - well_conn_collection_add_ref( connections , conn ); - } + if (!well_segment_has_grid_connections(segment, grid_name)) + segment->connections[grid_name] = well_conn_collection_alloc(); + + well_conn_collection_add_ref( segment->connections[grid_name] , conn ); return true; } else return false; @@ -223,7 +228,7 @@ bool well_segment_add_connection( well_segment_type * segment , const char * gri const well_conn_collection_type * well_segment_get_connections(const well_segment_type * segment , const char * grid_name ) { if (well_segment_has_grid_connections( segment , grid_name)) - return (const well_conn_collection_type*)hash_get( segment->connections , grid_name); + return segment->connections.at(grid_name); else return NULL; } diff --git a/ThirdParty/Ert/lib/ecl/well_segment_collection.cpp b/ThirdParty/Ert/lib/ecl/well_segment_collection.cpp index 841ee7d394..da9d1b3de8 100644 --- a/ThirdParty/Ert/lib/ecl/well_segment_collection.cpp +++ b/ThirdParty/Ert/lib/ecl/well_segment_collection.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'well_segment_collection.c' is part of ERT - Ensemble based Reservoir Tool. @@ -18,6 +18,8 @@ #include +#include + #include #include @@ -33,56 +35,61 @@ struct well_segment_collection_struct { - int_vector_type * segment_index_map; - vector_type * __segment_storage; + std::vector segment_index_map; + std::vector __segment_storage; }; well_segment_collection_type * well_segment_collection_alloc(void) { - well_segment_collection_type * segment_collection = (well_segment_collection_type*)util_malloc( sizeof * segment_collection ); - - segment_collection->__segment_storage = vector_alloc_new(); - segment_collection->segment_index_map = int_vector_alloc( 0 , -1 ); + well_segment_collection_type * segment_collection = new well_segment_collection_type(); return segment_collection; } void well_segment_collection_free(well_segment_collection_type * segment_collection ) { - vector_free( segment_collection->__segment_storage ); - int_vector_free( segment_collection->segment_index_map ); - free( segment_collection ); + for (int i = 0; i < static_cast(segment_collection->__segment_storage.size()); i++) + well_segment_free( segment_collection->__segment_storage[i] ); + delete segment_collection; } int well_segment_collection_get_size( const well_segment_collection_type * segment_collection ) { - return vector_get_size( segment_collection->__segment_storage ); + return segment_collection->__segment_storage.size(); } void well_segment_collection_add( well_segment_collection_type * segment_collection , well_segment_type * segment) { int segment_id = well_segment_get_id( segment ); - int current_index = int_vector_safe_iget( segment_collection->segment_index_map , segment_id ); - if (current_index >= 0) - vector_iset_owned_ref( segment_collection->__segment_storage , current_index , segment , well_segment_free__); + int current_index = -1; + if (segment_id < static_cast(segment_collection->segment_index_map.size())) + current_index = segment_collection->segment_index_map[segment_id]; + if (current_index >= 0) { + well_segment_free( segment_collection->__segment_storage[current_index] ); + segment_collection->__segment_storage[current_index] = segment; + } else { - int new_index = vector_get_size(segment_collection->__segment_storage); - vector_append_owned_ref( segment_collection->__segment_storage , segment , well_segment_free__); - int_vector_iset( segment_collection->segment_index_map , segment_id , new_index); + int new_index = segment_collection->__segment_storage.size(); + segment_collection->__segment_storage.push_back( segment ); + if ( segment_id >= static_cast(segment_collection->segment_index_map.size()) ) + segment_collection->segment_index_map.resize(segment_id+1, -1); + segment_collection->segment_index_map[segment_id] = new_index; } } well_segment_type * well_segment_collection_iget( const well_segment_collection_type * segment_collection , int index) { - return (well_segment_type*)vector_iget( segment_collection->__segment_storage , index ); + return segment_collection->__segment_storage[ index ]; } well_segment_type * well_segment_collection_get( const well_segment_collection_type * segment_collection , int segment_id) { - int internal_index = int_vector_safe_iget( segment_collection->segment_index_map , segment_id ); + int internal_index = -1; + if (segment_id < static_cast(segment_collection->segment_index_map.size())) + internal_index = segment_collection->segment_index_map[segment_id]; if (internal_index >= 0) return well_segment_collection_iget( segment_collection , internal_index ); else @@ -91,7 +98,9 @@ well_segment_type * well_segment_collection_get( const well_segment_collection_t bool well_segment_collection_has_segment( const well_segment_collection_type * segment_collection , int segment_id) { - int internal_index = int_vector_safe_iget( segment_collection->segment_index_map , segment_id ); + int internal_index = -1; + if (segment_id < static_cast(segment_collection->segment_index_map.size())) + internal_index = segment_collection->segment_index_map[segment_id]; if (internal_index >= 0) return true; else @@ -133,8 +142,8 @@ int well_segment_collection_load_from_kw( well_segment_collection_type * segment void well_segment_collection_link(const well_segment_collection_type * segment_collection) { - int index; - for (index = 0; index < vector_get_size( segment_collection->__segment_storage); index++) { + size_t index; + for (index = 0; index < segment_collection->__segment_storage.size(); index++) { well_segment_type * segment = well_segment_collection_iget( segment_collection , index ); int outlet_segment_id = well_segment_get_outlet_id( segment ); if (!well_segment_nearest_wellhead(segment)) { @@ -166,7 +175,7 @@ void well_segment_collection_add_branches( const well_segment_collection_type * well_branch_collection_type * branches ) { int iseg; for (iseg =0; iseg < well_segment_collection_get_size( segment_collection ); iseg++) { - const well_segment_type * segment = well_segment_collection_iget( segment_collection , iseg ); + well_segment_type * segment = well_segment_collection_iget( segment_collection , iseg ); if (well_segment_get_link_count( segment ) == 0) well_branch_collection_add_start_segment( branches , segment ); } diff --git a/ThirdParty/Ert/lib/ecl/well_state.cpp b/ThirdParty/Ert/lib/ecl/well_state.cpp index d0dc6c0273..67fedbe68e 100644 --- a/ThirdParty/Ert/lib/ecl/well_state.cpp +++ b/ThirdParty/Ert/lib/ecl/well_state.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'well_state.c' is part of ERT - Ensemble based Reservoir Tool. @@ -31,6 +31,10 @@ #include #include +#include +#include +#include + #include #include #include @@ -105,7 +109,7 @@ links are as follows: Segment1: C2 Segment2: C3 Segment3: C4, C5 - Segment4: C6 + Segment4: C6state_free( Segment5: C7 Each segment has an outlet segment, which will link the segments @@ -164,7 +168,7 @@ coupledte implementation these objects are modelled as such: struct well_state_struct { UTIL_TYPE_ID_DECLARATION; - char * name; + std::string name; time_t valid_from_time; int valid_from_report; int global_well_nr; @@ -176,15 +180,15 @@ struct well_state_struct { double water_rate; double volume_rate; ert_ecl_unit_enum unit_system; - - hash_type * connections; // hash + + std::map connections; // hash well_segment_collection_type * segments; well_branch_collection_type * branches; /*****************************************************************/ - - vector_type * index_wellhead; // An well_conn_type instance representing the wellhead - indexed by grid_nr. - hash_type * name_wellhead; // An well_conn_type instance representing the wellhead - indexed by lgr_name. + + std::vector index_wellhead; // An well_conn_type instance representing the wellhead - indexed by grid_nr. + std::map name_wellhead; // An well_conn_type instance representing the wellhead - indexed by lgr_name. }; @@ -193,18 +197,15 @@ UTIL_IS_INSTANCE_FUNCTION( well_state , WELL_STATE_TYPE_ID) well_state_type * well_state_alloc(const char * well_name , int global_well_nr , bool open, well_type_enum type , int report_nr, time_t valid_from) { - well_state_type * well_state = (well_state_type*)util_malloc( sizeof * well_state ); + well_state_type * well_state = new well_state_type(); UTIL_TYPE_ID_INIT( well_state , WELL_STATE_TYPE_ID ); - well_state->index_wellhead = vector_alloc_new(); - well_state->name_wellhead = hash_alloc(); - well_state->name = util_alloc_string_copy( well_name ); + well_state->name = well_name; well_state->valid_from_time = valid_from; well_state->valid_from_report = report_nr; well_state->open = open; well_state->type = type; well_state->global_well_nr = global_well_nr; - well_state->connections = hash_alloc(); well_state->segments = well_segment_collection_alloc(); well_state->branches = well_branch_collection_alloc(); well_state->is_MSW_well = false; @@ -291,8 +292,10 @@ void well_state_add_wellhead( well_state_type * well_state , const ecl_rsthead_t well_conn_type * wellhead = well_conn_alloc_wellhead( iwel_kw , header , well_nr ); if (wellhead != NULL) { - vector_safe_iset_owned_ref( well_state->index_wellhead , grid_nr , wellhead , well_conn_free__ ); - hash_insert_ref( well_state->name_wellhead , grid_name , wellhead ); + if (grid_nr >= static_cast(well_state->index_wellhead.size())) + well_state->index_wellhead.resize(grid_nr+1, NULL); + well_state->index_wellhead[grid_nr] = wellhead; + well_state->name_wellhead[grid_name] = wellhead; } } @@ -342,7 +345,7 @@ static int well_state_get_lgr_well_nr( const well_state_type * well_state , cons { char * lgr_well_name = (char*)util_alloc_strip_copy( (const char*)ecl_kw_iget_ptr( zwel_kw , well_nr * header->nzwelz) ); - if ( strcmp( well_state->name , lgr_well_name) == 0) + if ( well_state->name == lgr_well_name) found = true; else well_nr++; @@ -406,27 +409,29 @@ static void well_state_add_connections__( well_state_type * well_state , int well_nr ) { ecl_rsthead_type * header = ecl_rsthead_alloc( rst_view , -1); - const ecl_kw_type * icon_kw = ecl_file_view_iget_named_kw( rst_view , ICON_KW , 0); const ecl_kw_type * iwel_kw = ecl_file_view_iget_named_kw( rst_view , IWEL_KW , 0); well_state_add_wellhead( well_state , header , iwel_kw , well_nr , grid_name , grid_nr ); - if (!well_state_has_grid_connections( well_state , grid_name )) - hash_insert_hash_owned_ref( well_state->connections , grid_name, well_conn_collection_alloc( ) , well_conn_collection_free__ ); + if (ecl_file_view_has_kw(rst_view, ICON_KW)) { + const ecl_kw_type * icon_kw = ecl_file_view_iget_named_kw( rst_view , ICON_KW , 0); + if (!well_state_has_grid_connections( well_state , grid_name )) + well_state->connections[grid_name] = well_conn_collection_alloc(); - { - ecl_kw_type * scon_kw = NULL; - if (ecl_file_view_has_kw( rst_view , SCON_KW)) - scon_kw = ecl_file_view_iget_named_kw( rst_view , SCON_KW , 0); + { + ecl_kw_type * scon_kw = NULL; + if (ecl_file_view_has_kw( rst_view , SCON_KW)) + scon_kw = ecl_file_view_iget_named_kw( rst_view , SCON_KW , 0); - ecl_kw_type * xcon_kw = NULL; - if (ecl_file_view_has_kw( rst_view , XCON_KW)) { - xcon_kw = ecl_file_view_iget_named_kw(rst_view, XCON_KW, 0); + ecl_kw_type * xcon_kw = NULL; + if (ecl_file_view_has_kw( rst_view , XCON_KW)) { + xcon_kw = ecl_file_view_iget_named_kw(rst_view, XCON_KW, 0); + } + + well_conn_collection_type * wellcc = well_state->connections[grid_name]; + well_conn_collection_load_from_kw( wellcc , iwel_kw , icon_kw , scon_kw, xcon_kw , well_nr , header ); } - - well_conn_collection_type * wellcc = (well_conn_collection_type*)hash_get( well_state->connections , grid_name ); - well_conn_collection_load_from_kw( wellcc , iwel_kw , icon_kw , scon_kw, xcon_kw , well_nr , header ); } ecl_rsthead_free( header ); } @@ -447,10 +452,19 @@ static void well_state_add_LGR_connections(well_state_type * well_state, int num_lgr = ecl_grid_get_num_lgr( grid ); for (int lgr_index = 0; lgr_index < num_lgr; lgr_index++) { ecl_file_view_type * lgr_view = ecl_file_view_add_blockview(file_view , LGR_KW , lgr_index); - const char * grid_name = ecl_grid_iget_lgr_name( grid , lgr_index ); - int well_nr = well_state_get_lgr_well_nr( well_state , lgr_view ); - if (well_nr >= 0) - well_state_add_connections__( well_state , lgr_view , grid_name , lgr_index + 1, well_nr ); + /* + Even though the grid has LGR information the restart file is not required + to have corresponding LGR information. This has for a long time been + unchecked, and there might be bugs lurking based on the incorrect + assumption that if the grid has LGR information then the corresponding LGR + information can also be found in the restart file. + */ + if (lgr_view) { + const char * grid_name = ecl_grid_iget_lgr_name( grid , lgr_index ); + int well_nr = well_state_get_lgr_well_nr( well_state , lgr_view ); + if (well_nr >= 0) + well_state_add_connections__( well_state , lgr_view , grid_name , lgr_index + 1, well_nr ); + } } } @@ -515,13 +529,12 @@ bool well_state_add_MSW2( well_state_type * well_state , if (segment_count > 0) { - hash_iter_type * grid_iter = hash_iter_alloc( well_state->connections ); - while (!hash_iter_is_complete( grid_iter )) { - const char * grid_name = hash_iter_get_next_key( grid_iter ); - const well_conn_collection_type * connections = (const well_conn_collection_type*)hash_get( well_state->connections , grid_name ); - well_segment_collection_add_connections( well_state->segments , grid_name , connections ); + + auto it = well_state->connections.begin(); + while (it != well_state->connections.end()) { + well_segment_collection_add_connections( well_state->segments , it->first.c_str() , it->second ); + it++; } - hash_iter_free( grid_iter ); well_segment_collection_link( well_state->segments ); well_segment_collection_add_branches( well_state->segments , well_state->branches ); @@ -607,14 +620,19 @@ well_state_type * well_state_alloc_from_file2( ecl_file_view_type * file_view , void well_state_free( well_state_type * well ) { - hash_free( well->name_wellhead ); - vector_free( well->index_wellhead ); - hash_free( well->connections ); + + for (size_t i = 0; i < well->index_wellhead.size(); i++) { + if (well->index_wellhead[i]) + well_conn_free(well->index_wellhead[i]); + } + + for (auto& pair : well->connections) + well_conn_collection_free(pair.second); + well_segment_collection_free( well->segments ); well_branch_collection_free( well->branches ); - free( well->name ); - free( well ); + delete well; } /*****************************************************************/ @@ -631,22 +649,30 @@ time_t well_state_get_sim_time( const well_state_type * well_state ) { Will return NULL if no wellhead in this grid. */ const well_conn_type * well_state_iget_wellhead( const well_state_type * well_state , int grid_nr) { - return (const well_conn_type*)vector_safe_iget_const( well_state->index_wellhead , grid_nr ); + if (grid_nr < static_cast(well_state->index_wellhead.size())) + return well_state->index_wellhead[grid_nr]; + else + return NULL; +} + + +bool well_state_has_named_well_conn( const well_state_type * well_state , const char * grid_name ) { + const auto it = well_state->name_wellhead.find( grid_name ); + if (it == well_state->name_wellhead.end()) + return false; + return true; } const well_conn_type * well_state_get_wellhead( const well_state_type * well_state , const char * grid_name) { - if (hash_has_key( well_state->name_wellhead , grid_name)) - return (const well_conn_type*)hash_get( well_state->name_wellhead , grid_name ); - else - return NULL; + const auto it = well_state->name_wellhead.find( grid_name ); + if (it != well_state->name_wellhead.end()) + return it->second; + return NULL; } const well_conn_type * well_state_get_global_wellhead( const well_state_type * well_state ) { - if (hash_has_key( well_state->name_wellhead , ECL_GRID_GLOBAL_GRID)) - return (const well_conn_type*)hash_get( well_state->name_wellhead , ECL_GRID_GLOBAL_GRID ); - else - return NULL; + return well_state_get_wellhead( well_state, ECL_GRID_GLOBAL_GRID ); } @@ -664,15 +690,15 @@ int well_state_get_well_nr( const well_state_type * well_state ) { const char * well_state_get_name( const well_state_type * well_state ) { - return well_state->name; + return well_state->name.c_str(); } /*****************************************************************/ const well_conn_collection_type * well_state_get_grid_connections( const well_state_type * well_state , const char * grid_name) { - if (hash_has_key( well_state->connections , grid_name)) - return (const well_conn_collection_type*)hash_get( well_state->connections , grid_name); + if (well_state_has_grid_connections(well_state, grid_name) ) + return well_state->connections.at(grid_name); else return NULL; } @@ -684,10 +710,11 @@ const well_conn_collection_type * well_state_get_global_connections( const well_ bool well_state_has_grid_connections( const well_state_type * well_state , const char * grid_name) { - if (hash_has_key( well_state->connections , grid_name)) - return true; - else + + const auto it = well_state->connections.find(grid_name); + if (it == well_state->connections.end()) return false; + return true; } diff --git a/ThirdParty/Ert/lib/ecl/well_ts.cpp b/ThirdParty/Ert/lib/ecl/well_ts.cpp index 6aa42d4c16..cfae4974c1 100644 --- a/ThirdParty/Ert/lib/ecl/well_ts.cpp +++ b/ThirdParty/Ert/lib/ecl/well_ts.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'well_ts.c' is part of ERT - Ensemble based Reservoir Tool. @@ -62,6 +62,10 @@ #include #include +#include +#include +#include + #include #include @@ -84,14 +88,14 @@ typedef struct { struct well_ts_struct { UTIL_TYPE_ID_DECLARATION; - char * well_name; - vector_type * ts; + std::string well_name; + std::vector ts; }; /******************************************************************/ static well_node_type * well_node_alloc( well_state_type * well_state) { - well_node_type * node = (well_node_type*)util_malloc( sizeof * node ); + well_node_type * node = new well_node_type(); UTIL_TYPE_ID_INIT( node , WELL_NODE_TYPE_ID ); node->report_nr = well_state_get_report_nr( well_state ); node->sim_time = well_state_get_sim_time( well_state ); @@ -100,41 +104,23 @@ static well_node_type * well_node_alloc( well_state_type * well_state) { } -static UTIL_SAFE_CAST_FUNCTION( well_node , WELL_NODE_TYPE_ID ) -static UTIL_SAFE_CAST_FUNCTION_CONST( well_node , WELL_NODE_TYPE_ID ) - - static void well_node_free( well_node_type * well_node ) { well_state_free( well_node->well_state ); - free( well_node ); + delete well_node; } -static void well_node_free__( void * arg ) { - well_node_type * node = well_node_safe_cast( arg ); - well_node_free( node ); -} - -static int well_node_time_cmp( const void * arg1 , const void * arg2) { - const well_node_type * node1 = well_node_safe_cast_const( arg1 ); - const well_node_type * node2 = well_node_safe_cast_const( arg2 ); - - if (node1->sim_time < node2->sim_time) - return -1; - else if (node1->sim_time == node2->sim_time) - return 0; - else - return 1; +static bool well_node_time_lt( const well_node_type * node1 , const well_node_type * node2) { + return (node1->sim_time < node2->sim_time); } /*****************************************************************/ static well_ts_type * well_ts_alloc_empty( ) { - well_ts_type * well_ts = (well_ts_type*)util_malloc( sizeof * well_ts ); + well_ts_type * well_ts = new well_ts_type(); UTIL_TYPE_ID_INIT( well_ts , WELL_TS_TYPE_ID ); - well_ts->ts = vector_alloc_new(); return well_ts; } @@ -143,22 +129,22 @@ static UTIL_SAFE_CAST_FUNCTION( well_ts , WELL_TS_TYPE_ID ) well_ts_type * well_ts_alloc( const char * well_name ) { well_ts_type * well_ts = well_ts_alloc_empty(); - well_ts->well_name = util_alloc_string_copy( well_name ); + well_ts->well_name = well_name; return well_ts; } -char * well_ts_get_name( const well_ts_type * well_ts) { - return well_ts->well_name; +const char * well_ts_get_name( const well_ts_type * well_ts) { + return well_ts->well_name.c_str(); } static int well_ts_get_index__( const well_ts_type * well_ts , int report_step , time_t sim_time , bool use_report) { - const int size = vector_get_size( well_ts->ts ); + const int size = well_ts->ts.size(); if (size == 0) return 0; else { - const well_node_type * first_node = (const well_node_type*)vector_iget_const( well_ts->ts , 0 ); - const well_node_type * last_node = (const well_node_type*)vector_get_last_const( well_ts->ts ); + const well_node_type * first_node = well_ts->ts[0]; + const well_node_type * last_node = well_ts->ts.back(); if (use_report) { if (report_step < first_node->report_nr) @@ -181,7 +167,7 @@ static int well_ts_get_index__( const well_ts_type * well_ts , int report_step , while (true) { int center_index = (lower_index + upper_index) / 2; - const well_node_type * center_node = (const well_node_type*)vector_iget_const( well_ts->ts , center_index ); + const well_node_type * center_node = well_ts->ts[center_index]; double cmp; if (use_report) cmp = center_node->report_nr - report_step; @@ -221,11 +207,11 @@ static int well_ts_get_index( const well_ts_type * well_ts , int report_step , t // Inline check that the index is correct { bool OK = true; - const well_node_type * node = (const well_node_type*)vector_iget_const( well_ts->ts , index ); + const well_node_type * node = well_ts->ts[index]; well_node_type * next_node = NULL; - if (index < (vector_get_size( well_ts->ts ) - 1)) - next_node = (well_node_type*)vector_iget( well_ts->ts , index + 1); + if (index < (static_cast(well_ts->ts.size()) - 1) ) + next_node = well_ts->ts[index + 1]; if (use_report) { if (index < 0) { @@ -265,24 +251,24 @@ static int well_ts_get_index( const well_ts_type * well_ts , int report_step , t void well_ts_add_well( well_ts_type * well_ts , well_state_type * well_state ) { well_node_type * new_node = well_node_alloc( well_state ); - vector_append_owned_ref( well_ts->ts , new_node , well_node_free__ ); + well_ts->ts.push_back( new_node ); - if (vector_get_size( well_ts->ts ) > 1) { - const well_node_type * last_node = (const well_node_type*)vector_get_last_const(well_ts->ts ); + if (well_ts->ts.size() > 1) { + const well_node_type * last_node = well_ts->ts.back(); if (new_node->sim_time < last_node->sim_time) // The new node is chronologically before the previous node; // i.e. we must sort the nodes in time. This should probably happen - // quite seldom: - vector_sort( well_ts->ts , well_node_time_cmp ); + // quite seldom: + std::sort( well_ts->ts.begin(), well_ts->ts.end(), well_node_time_lt ); } } void well_ts_free( well_ts_type * well_ts ){ - free( well_ts->well_name ); - vector_free( well_ts->ts ); - free( well_ts ); + for (size_t i = 0; i < well_ts->ts.size(); i++) + well_node_free( well_ts->ts[i] ); + delete well_ts; } @@ -294,7 +280,7 @@ void well_ts_free__( void * arg ) { int well_ts_get_size( const well_ts_type * well_ts) { - return vector_get_size( well_ts->ts ); + return well_ts->ts.size(); } @@ -304,12 +290,12 @@ well_state_type * well_ts_get_first_state( const well_ts_type * well_ts) { well_state_type * well_ts_get_last_state( const well_ts_type * well_ts) { - return well_ts_iget_state( well_ts , vector_get_size( well_ts->ts ) - 1); + return well_ts_iget_state( well_ts , well_ts->ts.size() - 1); } well_state_type * well_ts_iget_state( const well_ts_type * well_ts , int index) { - well_node_type * node = (well_node_type*)vector_iget( well_ts->ts , index ); + well_node_type * node = well_ts->ts[index]; return node->well_state; } diff --git a/ThirdParty/Ert/lib/geometry/geo_pointset.cpp b/ThirdParty/Ert/lib/geometry/geo_pointset.cpp index 0aa2777753..513c89cbf0 100644 --- a/ThirdParty/Ert/lib/geometry/geo_pointset.cpp +++ b/ThirdParty/Ert/lib/geometry/geo_pointset.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'geo_pointset.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/geometry/geo_polygon.cpp b/ThirdParty/Ert/lib/geometry/geo_polygon.cpp index e375bb07e5..67571ca5f5 100644 --- a/ThirdParty/Ert/lib/geometry/geo_polygon.cpp +++ b/ThirdParty/Ert/lib/geometry/geo_polygon.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'geo_polygon.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/geometry/geo_polygon_collection.cpp b/ThirdParty/Ert/lib/geometry/geo_polygon_collection.cpp index 043bffcb83..d3bcd4170f 100644 --- a/ThirdParty/Ert/lib/geometry/geo_polygon_collection.cpp +++ b/ThirdParty/Ert/lib/geometry/geo_polygon_collection.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2014 Statoil ASA, Norway. + Copyright (C) 2014 Equinor ASA, Norway. The file 'geo_polygon_collection.c' is part of ERT - Ensemble based Reservoir Tool. @@ -20,10 +20,12 @@ #include #include +#include +#include + #include #include #include -#include #include #include @@ -35,17 +37,16 @@ struct geo_polygon_collection_struct { UTIL_TYPE_ID_DECLARATION; vector_type * polygon_list; - hash_type * polygon_map; + std::map polygon_map; }; UTIL_IS_INSTANCE_FUNCTION( geo_polygon_collection , GEO_POLYGON_COLLECTION_TYPE_ID) geo_polygon_collection_type * geo_polygon_collection_alloc( ) { - geo_polygon_collection_type * polygons = (geo_polygon_collection_type*)util_malloc( sizeof * polygons ); + geo_polygon_collection_type * polygons = new geo_polygon_collection_type(); UTIL_TYPE_ID_INIT( polygons , GEO_POLYGON_COLLECTION_TYPE_ID ); polygons->polygon_list = vector_alloc_new(); - polygons->polygon_map = hash_alloc(); return polygons; } @@ -82,7 +83,7 @@ bool geo_polygon_collection_add_polygon( geo_polygon_collection_type * polygons vector_append_ref( polygons->polygon_list , polygon ); if (name) - hash_insert_ref( polygons->polygon_map , name , polygon ); + polygons->polygon_map[name] = polygon; return true; } @@ -91,7 +92,7 @@ bool geo_polygon_collection_add_polygon( geo_polygon_collection_type * polygons bool geo_polygon_collection_has_polygon( const geo_polygon_collection_type * polygons , const char * name) { if (name) - return hash_has_key( polygons->polygon_map , name ); + return (polygons->polygon_map.count(name) > 0); else return false; } @@ -99,8 +100,7 @@ bool geo_polygon_collection_has_polygon( const geo_polygon_collection_type * pol void geo_polygon_collection_free( geo_polygon_collection_type * polygons ) { vector_free( polygons->polygon_list ); - hash_free( polygons->polygon_map ); - free( polygons ); + delete polygons; } @@ -111,5 +111,5 @@ geo_polygon_type * geo_polygon_collection_iget_polygon(const geo_polygon_collect geo_polygon_type * geo_polygon_collection_get_polygon(const geo_polygon_collection_type * polygons , const char * polygon_name) { - return (geo_polygon_type*)hash_get( polygons->polygon_map , polygon_name ); + return polygons->polygon_map.at( polygon_name ); } diff --git a/ThirdParty/Ert/lib/geometry/geo_region.cpp b/ThirdParty/Ert/lib/geometry/geo_region.cpp index 5ce2a6f382..c8e4985abb 100644 --- a/ThirdParty/Ert/lib/geometry/geo_region.cpp +++ b/ThirdParty/Ert/lib/geometry/geo_region.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'geo_region.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/geometry/geo_surface.cpp b/ThirdParty/Ert/lib/geometry/geo_surface.cpp index 773da26113..00e76938e1 100644 --- a/ThirdParty/Ert/lib/geometry/geo_surface.cpp +++ b/ThirdParty/Ert/lib/geometry/geo_surface.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'geo_surface.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/geometry/geo_util.cpp b/ThirdParty/Ert/lib/geometry/geo_util.cpp index e8d0b1cbb1..5f80362a66 100644 --- a/ThirdParty/Ert/lib/geometry/geo_util.cpp +++ b/ThirdParty/Ert/lib/geometry/geo_util.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'geo_util.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/geometry/tests/geo_polygon.cpp b/ThirdParty/Ert/lib/geometry/tests/geo_polygon.cpp index f3f46e6f60..fe97113cd2 100644 --- a/ThirdParty/Ert/lib/geometry/tests/geo_polygon.cpp +++ b/ThirdParty/Ert/lib/geometry/tests/geo_polygon.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'geo_surface.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/geometry/tests/geo_polygon_collection.cpp b/ThirdParty/Ert/lib/geometry/tests/geo_polygon_collection.cpp index 7023a82446..8627ccde6a 100644 --- a/ThirdParty/Ert/lib/geometry/tests/geo_polygon_collection.cpp +++ b/ThirdParty/Ert/lib/geometry/tests/geo_polygon_collection.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2014 Statoil ASA, Norway. + Copyright (C) 2014 Equinor ASA, Norway. The file 'geo_polygon_collection.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/geometry/tests/geo_surface.cpp b/ThirdParty/Ert/lib/geometry/tests/geo_surface.cpp index c9fd440b54..b506064d79 100644 --- a/ThirdParty/Ert/lib/geometry/tests/geo_surface.cpp +++ b/ThirdParty/Ert/lib/geometry/tests/geo_surface.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'geo_surface.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/geometry/tests/geo_util_xlines.cpp b/ThirdParty/Ert/lib/geometry/tests/geo_util_xlines.cpp index 6c926632c0..06f7ee72d1 100644 --- a/ThirdParty/Ert/lib/geometry/tests/geo_util_xlines.cpp +++ b/ThirdParty/Ert/lib/geometry/tests/geo_util_xlines.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2014 Statoil ASA, Norway. + Copyright (C) 2014 Equinor ASA, Norway. The file 'geo_util_xlines.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/ecl/EclFilename.hpp b/ThirdParty/Ert/lib/include/ert/ecl/EclFilename.hpp index 858fccfb59..b5e9900582 100644 --- a/ThirdParty/Ert/lib/include/ert/ecl/EclFilename.hpp +++ b/ThirdParty/Ert/lib/include/ert/ecl/EclFilename.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2017 Statoil ASA, Norway. + Copyright (C) 2017 Equinor ASA, Norway. This file is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/ecl/EclKW.hpp b/ThirdParty/Ert/lib/include/ert/ecl/EclKW.hpp index 9a07836bf8..71a7c70264 100644 --- a/ThirdParty/Ert/lib/include/ert/ecl/EclKW.hpp +++ b/ThirdParty/Ert/lib/include/ert/ecl/EclKW.hpp @@ -1,5 +1,5 @@ /* - Copyright 2015 Statoil ASA. + Copyright 2015 Equinor ASA. This file is part of the Open Porous Media project (OPM). diff --git a/ThirdParty/Ert/lib/include/ert/ecl/FortIO.hpp b/ThirdParty/Ert/lib/include/ert/ecl/FortIO.hpp index 2f7d69fa09..e4312eb61b 100644 --- a/ThirdParty/Ert/lib/include/ert/ecl/FortIO.hpp +++ b/ThirdParty/Ert/lib/include/ert/ecl/FortIO.hpp @@ -1,5 +1,5 @@ /* - Copyright 2015 Statoil ASA. + Copyright 2015 Equinor ASA. This file is part of the Open Porous Media project (OPM). diff --git a/ThirdParty/Ert/lib/include/ert/ecl/Smspec.hpp b/ThirdParty/Ert/lib/include/ert/ecl/Smspec.hpp deleted file mode 100644 index b16c4ced38..0000000000 --- a/ThirdParty/Ert/lib/include/ert/ecl/Smspec.hpp +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef OPM_ERT_SMSPEC_HPP -#define OPM_ERT_SMSPEC_HPP - -#include -#include - -#include -#include - -namespace ERT { - - class smspec_node { - public: - smspec_node( const smspec_node& ); - smspec_node( smspec_node&& ); - - smspec_node& operator=( const smspec_node& ); - smspec_node& operator=( smspec_node&& ); - - static int cmp( const smspec_node& node1, const smspec_node& node2); - smspec_node( - ecl_smspec_var_type, - const std::string& wgname, - const std::string& keyword - ); - - smspec_node( const std::string& keyword ); - - smspec_node( const std::string& keyword, - const int dims[ 3 ], - const int ijk[ 3 ] ); - - smspec_node( const std::string& keyword, - const std::string& wellname, - const int dims[ 3 ], - const int ijk[ 3 ] ); - - smspec_node( const std::string& keyword, - const int dims[ 3 ], - int region ); - - int type() const; - const char* keyword() const; - const char* wgname() const; - const char* key1() const; - int num() const; - smspec_node_type* get(); - const smspec_node_type* get() const; - - private: - smspec_node( - ecl_smspec_var_type, - const char*, const char*, const char*, const char*, - const int[3], int, int = 0, float = 0 ); - - ert_unique_ptr< smspec_node_type, smspec_node_free > node; - }; - -} - -#endif //OPM_ERT_SMSPEC_HPP diff --git a/ThirdParty/Ert/lib/include/ert/ecl/ecl_box.hpp b/ThirdParty/Ert/lib/include/ert/ecl/ecl_box.hpp index e88098554a..a08d496b28 100644 --- a/ThirdParty/Ert/lib/include/ert/ecl/ecl_box.hpp +++ b/ThirdParty/Ert/lib/include/ert/ecl/ecl_box.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'ecl_box.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/ecl/ecl_coarse_cell.hpp b/ThirdParty/Ert/lib/include/ert/ecl/ecl_coarse_cell.hpp index 6b04ac1523..2bcea05cf2 100644 --- a/ThirdParty/Ert/lib/include/ert/ecl/ecl_coarse_cell.hpp +++ b/ThirdParty/Ert/lib/include/ert/ecl/ecl_coarse_cell.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Statoil ASA, Norway. + Copyright (C) 2012 Equinor ASA, Norway. This file is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/ecl/ecl_endian_flip.hpp b/ThirdParty/Ert/lib/include/ert/ecl/ecl_endian_flip.hpp index 9876aaf0ef..409a023512 100644 --- a/ThirdParty/Ert/lib/include/ert/ecl/ecl_endian_flip.hpp +++ b/ThirdParty/Ert/lib/include/ert/ecl/ecl_endian_flip.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'ecl_endian_flip.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/ecl/ecl_file.hpp b/ThirdParty/Ert/lib/include/ert/ecl/ecl_file.hpp index 8ddae75c74..eaafb00654 100644 --- a/ThirdParty/Ert/lib/include/ert/ecl/ecl_file.hpp +++ b/ThirdParty/Ert/lib/include/ert/ecl/ecl_file.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'ecl_file.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/ecl/ecl_file_kw.hpp b/ThirdParty/Ert/lib/include/ert/ecl/ecl_file_kw.hpp index f066fd1b5d..18abcaea6c 100644 --- a/ThirdParty/Ert/lib/include/ert/ecl/ecl_file_kw.hpp +++ b/ThirdParty/Ert/lib/include/ert/ecl/ecl_file_kw.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'ecl_file_kw.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/ecl/ecl_file_view.hpp b/ThirdParty/Ert/lib/include/ert/ecl/ecl_file_view.hpp index 20ab40af07..7cceec3319 100644 --- a/ThirdParty/Ert/lib/include/ert/ecl/ecl_file_view.hpp +++ b/ThirdParty/Ert/lib/include/ert/ecl/ecl_file_view.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2016 Statoil ASA, Norway. + Copyright (C) 2016 Equinor ASA, Norway. This file is part of ERT - Ensemble based Reservoir Tool. @@ -81,8 +81,8 @@ typedef struct ecl_file_transaction_struct ecl_file_transaction_type; void ecl_file_view_fwrite( const ecl_file_view_type * ecl_file_view , fortio_type * target , int offset); int ecl_file_view_iget_occurence( const ecl_file_view_type * ecl_file_view , int global_index); void ecl_file_view_fprintf_kw_list(const ecl_file_view_type * ecl_file_view , FILE * stream); - ecl_file_view_type * ecl_file_view_add_blockview(const ecl_file_view_type * ecl_file_view , const char * header, int occurence); - ecl_file_view_type * ecl_file_view_add_blockview2(const ecl_file_view_type * ecl_file_view , const char * start_kw, const char * end_kw, int occurence); + ecl_file_view_type * ecl_file_view_add_blockview(ecl_file_view_type * ecl_file_view , const char * header, int occurence); + ecl_file_view_type * ecl_file_view_add_blockview2(ecl_file_view_type * ecl_file_view , const char * start_kw, const char * end_kw, int occurence); ecl_file_view_type * ecl_file_view_add_restart_view(ecl_file_view_type * file_view , int seqnum_index, int report_step , time_t sim_time, double sim_days); ecl_file_view_type * ecl_file_view_alloc_blockview(const ecl_file_view_type * ecl_file_view , const char * header, int occurence); ecl_file_view_type * ecl_file_view_alloc_blockview2(const ecl_file_view_type * ecl_file_view , const char * start_kw, const char * end_kw, int occurence); diff --git a/ThirdParty/Ert/lib/include/ert/ecl/ecl_grav.hpp b/ThirdParty/Ert/lib/include/ert/ecl/ecl_grav.hpp index 41e09f34cd..b39de29fb2 100644 --- a/ThirdParty/Ert/lib/include/ert/ecl/ecl_grav.hpp +++ b/ThirdParty/Ert/lib/include/ert/ecl/ecl_grav.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. This file is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/ecl/ecl_grav_calc.hpp b/ThirdParty/Ert/lib/include/ert/ecl/ecl_grav_calc.hpp index 62a1b84ed1..3b42b0ed94 100644 --- a/ThirdParty/Ert/lib/include/ert/ecl/ecl_grav_calc.hpp +++ b/ThirdParty/Ert/lib/include/ert/ecl/ecl_grav_calc.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'ecl_grav.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/ecl/ecl_grav_common.hpp b/ThirdParty/Ert/lib/include/ert/ecl/ecl_grav_common.hpp index 925508cf17..3097395f4e 100644 --- a/ThirdParty/Ert/lib/include/ert/ecl/ecl_grav_common.hpp +++ b/ThirdParty/Ert/lib/include/ert/ecl/ecl_grav_common.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'ecl_grav_common.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/ecl/ecl_grid.hpp b/ThirdParty/Ert/lib/include/ert/ecl/ecl_grid.hpp index 4efac56885..9fdd7fc75c 100644 --- a/ThirdParty/Ert/lib/include/ert/ecl/ecl_grid.hpp +++ b/ThirdParty/Ert/lib/include/ert/ecl/ecl_grid.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'ecl_grid.h' is part of ERT - Ensemble based Reservoir Tool. @@ -18,9 +18,7 @@ #ifndef ERT_ECL_GRID_H #define ERT_ECL_GRID_H -#ifdef __cplusplus -extern "C" { -#endif + #include #include @@ -32,6 +30,10 @@ extern "C" { #include #include +#ifdef __cplusplus +extern "C" { +#endif + #define ECL_GRID_COORD_SIZE(nx,ny) (((nx) + 1) * ((ny) + 1) * 6) #define ECL_GRID_ZCORN_SIZE(nx,ny,nz) (((nx) * (ny) * (nz) * 8)) diff --git a/ThirdParty/Ert/lib/include/ert/ecl/ecl_grid_dims.hpp b/ThirdParty/Ert/lib/include/ert/ecl/ecl_grid_dims.hpp index f67179badd..358c06d9cb 100644 --- a/ThirdParty/Ert/lib/include/ert/ecl/ecl_grid_dims.hpp +++ b/ThirdParty/Ert/lib/include/ert/ecl/ecl_grid_dims.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'ecl_grid_dims.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/ecl/ecl_init_file.hpp b/ThirdParty/Ert/lib/include/ert/ecl/ecl_init_file.hpp index 8870ffe54a..a515a15eeb 100644 --- a/ThirdParty/Ert/lib/include/ert/ecl/ecl_init_file.hpp +++ b/ThirdParty/Ert/lib/include/ert/ecl/ecl_init_file.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Statoil ASA, Norway. + Copyright (C) 2012 Equinor ASA, Norway. The file 'ecl_init_file.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/ecl/ecl_io_config.hpp b/ThirdParty/Ert/lib/include/ert/ecl/ecl_io_config.hpp index d198d47ca6..104d5c74a6 100644 --- a/ThirdParty/Ert/lib/include/ert/ecl/ecl_io_config.hpp +++ b/ThirdParty/Ert/lib/include/ert/ecl/ecl_io_config.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'ecl_io_config.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/ecl/ecl_kw.hpp b/ThirdParty/Ert/lib/include/ert/ecl/ecl_kw.hpp index 607c638af3..6e13c1be4c 100644 --- a/ThirdParty/Ert/lib/include/ert/ecl/ecl_kw.hpp +++ b/ThirdParty/Ert/lib/include/ert/ecl/ecl_kw.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'ecl_kw.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/ecl/ecl_kw_grdecl.hpp b/ThirdParty/Ert/lib/include/ert/ecl/ecl_kw_grdecl.hpp index 2113c18cd9..1e777d3d86 100644 --- a/ThirdParty/Ert/lib/include/ert/ecl/ecl_kw_grdecl.hpp +++ b/ThirdParty/Ert/lib/include/ert/ecl/ecl_kw_grdecl.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'ecl_kw_grdecl.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/ecl/ecl_nnc_data.hpp b/ThirdParty/Ert/lib/include/ert/ecl/ecl_nnc_data.hpp index 8ed4c594e7..b3697d54d6 100644 --- a/ThirdParty/Ert/lib/include/ert/ecl/ecl_nnc_data.hpp +++ b/ThirdParty/Ert/lib/include/ert/ecl/ecl_nnc_data.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2017 Statoil ASA, Norway. + Copyright (C) 2017 Equinor ASA, Norway. The file 'ecl_nnc_geometry.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/ecl/ecl_nnc_export.hpp b/ThirdParty/Ert/lib/include/ert/ecl/ecl_nnc_export.hpp index 68ca00d61a..1e2b2d9106 100644 --- a/ThirdParty/Ert/lib/include/ert/ecl/ecl_nnc_export.hpp +++ b/ThirdParty/Ert/lib/include/ert/ecl/ecl_nnc_export.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'ecl_nnc_export.h' is part of ERT - Ensemble based Reservoir Tool. @@ -45,7 +45,8 @@ typedef struct { } ecl_nnc_type; - int ecl_nnc_export_get_size( const ecl_grid_type * grid ); +bool ecl_nnc_intersect_format(const ecl_grid_type * grid, const ecl_file_type * init_file); + int ecl_nnc_export_get_size( const ecl_grid_type * grid , const ecl_file_type * init_file ); int ecl_nnc_export( const ecl_grid_type * grid , const ecl_file_type * init_file , ecl_nnc_type * nnc_data); ecl_kw_type * ecl_nnc_export_get_tranx_kw( const ecl_grid_type * grid , const ecl_file_type * init_file , int lgr_nr1, int lgr_nr2 ); diff --git a/ThirdParty/Ert/lib/include/ert/ecl/ecl_nnc_geometry.hpp b/ThirdParty/Ert/lib/include/ert/ecl/ecl_nnc_geometry.hpp index 66c5742ede..dbca5d9d5e 100644 --- a/ThirdParty/Ert/lib/include/ert/ecl/ecl_nnc_geometry.hpp +++ b/ThirdParty/Ert/lib/include/ert/ecl/ecl_nnc_geometry.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2017 Statoil ASA, Norway. + Copyright (C) 2017 Equinor ASA, Norway. The file 'ecl_nnc_geometry.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/ecl/ecl_region.hpp b/ThirdParty/Ert/lib/include/ert/ecl/ecl_region.hpp index 321b1f68d5..bf9acfa99f 100644 --- a/ThirdParty/Ert/lib/include/ert/ecl/ecl_region.hpp +++ b/ThirdParty/Ert/lib/include/ert/ecl/ecl_region.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'ecl_region.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/ecl/ecl_rft_cell.hpp b/ThirdParty/Ert/lib/include/ert/ecl/ecl_rft_cell.hpp index 96ba37abd6..07460401e2 100644 --- a/ThirdParty/Ert/lib/include/ert/ecl/ecl_rft_cell.hpp +++ b/ThirdParty/Ert/lib/include/ert/ecl/ecl_rft_cell.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'ecl_rft_cell.h' is part of ERT - Ensemble based Reservoir Tool. @@ -76,7 +76,7 @@ UTIL_IS_INSTANCE_HEADER( ecl_rft_cell ); int ecl_rft_cell_cmp__( const void * arg1 , const void * arg2); int ecl_rft_cell_cmp( const ecl_rft_cell_type * cell1 , const ecl_rft_cell_type * cell2); - + bool ecl_rft_cell_lt( const ecl_rft_cell_type * cell1 , const ecl_rft_cell_type * cell2); #ifdef __cplusplus } #endif diff --git a/ThirdParty/Ert/lib/include/ert/ecl/ecl_rft_file.hpp b/ThirdParty/Ert/lib/include/ert/ecl/ecl_rft_file.hpp index 02f23cb048..eb58c5e4d2 100644 --- a/ThirdParty/Ert/lib/include/ert/ecl/ecl_rft_file.hpp +++ b/ThirdParty/Ert/lib/include/ert/ecl/ecl_rft_file.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'ecl_rft_file.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/ecl/ecl_rft_node.hpp b/ThirdParty/Ert/lib/include/ert/ecl/ecl_rft_node.hpp index ab6dcd46c6..6ad7896f97 100644 --- a/ThirdParty/Ert/lib/include/ert/ecl/ecl_rft_node.hpp +++ b/ThirdParty/Ert/lib/include/ert/ecl/ecl_rft_node.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'ecl_rft_node.h' is part of ERT - Ensemble based Reservoir Tool. @@ -62,7 +62,8 @@ double ecl_rft_node_iget_sgas( const ecl_rft_node_type * rft_node , int index); double ecl_rft_node_iget_soil( const ecl_rft_node_type * rft_node , int index); void ecl_rft_node_fwrite(const ecl_rft_node_type * rft_node, fortio_type * fortio, ert_ecl_unit_enum unit_set); double ecl_rft_node_get_days(const ecl_rft_node_type * rft_node ); -int ecl_rft_node_cmp( const ecl_rft_node_type * n1 , const ecl_rft_node_type * n2); +int ecl_rft_node_cmp( const ecl_rft_node_type * n1 , const ecl_rft_node_type * n2); +bool ecl_rft_node_lt(const ecl_rft_node_type * n1, const ecl_rft_node_type * n2); void ecl_rft_node_append_cell( ecl_rft_node_type * rft_node , ecl_rft_cell_type * cell); ecl_rft_node_type * ecl_rft_node_alloc_new(const char * well_name, const char * data_type_string, const time_t recording_date, const double days); diff --git a/ThirdParty/Ert/lib/include/ert/ecl/ecl_rst_file.hpp b/ThirdParty/Ert/lib/include/ert/ecl/ecl_rst_file.hpp index f4d6e5d4a8..7a36ef0ad1 100644 --- a/ThirdParty/Ert/lib/include/ert/ecl/ecl_rst_file.hpp +++ b/ThirdParty/Ert/lib/include/ert/ecl/ecl_rst_file.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Statoil ASA, Norway. + Copyright (C) 2012 Equinor ASA, Norway. The file 'ecl_rst_file.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/ecl/ecl_rsthead.hpp b/ThirdParty/Ert/lib/include/ert/ecl/ecl_rsthead.hpp index 8c91a65e16..566f60517c 100644 --- a/ThirdParty/Ert/lib/include/ert/ecl/ecl_rsthead.hpp +++ b/ThirdParty/Ert/lib/include/ert/ecl/ecl_rsthead.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'ecl_RSTHEAD.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/ecl/ecl_smspec.hpp b/ThirdParty/Ert/lib/include/ert/ecl/ecl_smspec.hpp index 5bfef485f8..5a5bea9578 100644 --- a/ThirdParty/Ert/lib/include/ert/ecl/ecl_smspec.hpp +++ b/ThirdParty/Ert/lib/include/ert/ecl/ecl_smspec.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'ecl_smspec.h' is part of ERT - Ensemble based Reservoir Tool. @@ -29,12 +29,29 @@ #include #include +typedef struct ecl_smspec_struct ecl_smspec_type; + +#ifdef __cplusplus +#include +const std::vector& ecl_smspec_get_params_default( const ecl_smspec_type * ecl_smspec ); +const ecl::smspec_node& ecl_smspec_get_well_var_node( const ecl_smspec_type * smspec , const char * well , const char * var); +const ecl::smspec_node& ecl_smspec_get_group_var_node( const ecl_smspec_type * smspec , const char * group , const char * var); +const ecl::smspec_node& ecl_smspec_get_field_var_node( const ecl_smspec_type * smspec , const char * var); +const ecl::smspec_node& ecl_smspec_get_region_var_node(const ecl_smspec_type * ecl_smspec , const char *region_var , int region_nr); +const ecl::smspec_node& ecl_smspec_get_misc_var_node(const ecl_smspec_type * ecl_smspec , const char *var); +const ecl::smspec_node& ecl_smspec_get_block_var_node(const ecl_smspec_type * ecl_smspec , const char * block_var , int block_nr); +const ecl::smspec_node& ecl_smspec_get_block_var_node_ijk(const ecl_smspec_type * ecl_smspec , const char * block_var , int i , int j , int k); +const ecl::smspec_node& ecl_smspec_get_well_completion_var_node(const ecl_smspec_type * ecl_smspec , const char * well , const char *var, int cell_nr); +const ecl::smspec_node& ecl_smspec_get_general_var_node( const ecl_smspec_type * smspec , const char * lookup_kw ); +const ecl::smspec_node& ecl_smspec_iget_node_w_node_index( const ecl_smspec_type * smspec , int node_index ); +const ecl::smspec_node& ecl_smspec_iget_node_w_params_index( const ecl_smspec_type * smspec , int params_index ); +const ecl::smspec_node& ecl_smspec_iget_node(const ecl_smspec_type * smspec, int index); +#endif + #ifdef __cplusplus extern "C" { #endif -typedef struct ecl_smspec_struct ecl_smspec_type; - /** These are the different variable types, see table 3.4 in the @@ -47,10 +64,7 @@ typedef struct ecl_smspec_struct ecl_smspec_type; */ int * ecl_smspec_alloc_mapping( const ecl_smspec_type * self, const ecl_smspec_type * other); - const int_vector_type * ecl_smspec_get_index_map( const ecl_smspec_type * smspec ); - void ecl_smspec_index_node( ecl_smspec_type * ecl_smspec , smspec_node_type * smspec_node); - void ecl_smspec_insert_node(ecl_smspec_type * ecl_smspec, smspec_node_type * smspec_node); - void ecl_smspec_add_node( ecl_smspec_type * ecl_smspec , smspec_node_type * smspec_node ); + const int * ecl_smspec_get_index_map( const ecl_smspec_type * smspec ); ecl_smspec_var_type ecl_smspec_iget_var_type( const ecl_smspec_type * smspec , int index ); bool ecl_smspec_needs_num( ecl_smspec_var_type var_type ); bool ecl_smspec_needs_wgname( ecl_smspec_var_type var_type ); @@ -71,39 +85,30 @@ typedef struct ecl_smspec_struct ecl_smspec_type; int ecl_smspec_get_date_year_index( const ecl_smspec_type * smspec ); - const smspec_node_type * ecl_smspec_get_well_var_node( const ecl_smspec_type * smspec , const char * well , const char * var); int ecl_smspec_get_well_var_params_index(const ecl_smspec_type * ecl_smspec , const char * well , const char *var); bool ecl_smspec_has_well_var(const ecl_smspec_type * ecl_smspec , const char * well , const char *var); - const smspec_node_type * ecl_smspec_get_group_var_node( const ecl_smspec_type * smspec , const char * group , const char * var); int ecl_smspec_get_group_var_params_index(const ecl_smspec_type * ecl_smspec , const char * group , const char *var); bool ecl_smspec_has_group_var(const ecl_smspec_type * ecl_smspec , const char * group , const char *var); - const smspec_node_type * ecl_smspec_get_field_var_node( const ecl_smspec_type * smspec , const char * var); int ecl_smspec_get_field_var_params_index(const ecl_smspec_type * ecl_smspec , const char *var); bool ecl_smspec_has_field_var(const ecl_smspec_type * ecl_smspec , const char *var); - const smspec_node_type * ecl_smspec_get_region_var_node(const ecl_smspec_type * ecl_smspec , const char *region_var , int region_nr); int ecl_smspec_get_region_var_params_index(const ecl_smspec_type * ecl_smspec , const char * region_var , int region_nr); bool ecl_smspec_has_region_var(const ecl_smspec_type * ecl_smspec , const char * region_var , int region_nr); - const smspec_node_type * ecl_smspec_get_misc_var_node(const ecl_smspec_type * ecl_smspec , const char *var); int ecl_smspec_get_misc_var_params_index(const ecl_smspec_type * ecl_smspec , const char *var); bool ecl_smspec_has_misc_var(const ecl_smspec_type * ecl_smspec , const char *var); - const smspec_node_type * ecl_smspec_get_block_var_node(const ecl_smspec_type * ecl_smspec , const char * block_var , int block_nr); int ecl_smspec_get_block_var_params_index(const ecl_smspec_type * ecl_smspec , const char * block_var , int block_nr); bool ecl_smspec_has_block_var(const ecl_smspec_type * ecl_smspec , const char * block_var , int block_nr); - const smspec_node_type * ecl_smspec_get_block_var_node_ijk(const ecl_smspec_type * ecl_smspec , const char * block_var , int i , int j , int k); int ecl_smspec_get_block_var_params_index_ijk(const ecl_smspec_type * ecl_smspec , const char * block_var , int i , int j , int k); bool ecl_smspec_has_block_var_ijk(const ecl_smspec_type * ecl_smspec , const char * block_var , int i , int j , int k); - const smspec_node_type * ecl_smspec_get_well_completion_var_node(const ecl_smspec_type * ecl_smspec , const char * well , const char *var, int cell_nr); int ecl_smspec_get_well_completion_var_params_index(const ecl_smspec_type * ecl_smspec , const char * well , const char *var, int cell_nr); bool ecl_smspec_has_well_completion_var(const ecl_smspec_type * ecl_smspec , const char * well , const char *var, int cell_nr); - const smspec_node_type * ecl_smspec_get_general_var_node( const ecl_smspec_type * smspec , const char * lookup_kw ); int ecl_smspec_get_general_var_params_index(const ecl_smspec_type * ecl_smspec , const char * lookup_kw); bool ecl_smspec_has_general_var(const ecl_smspec_type * ecl_smspec , const char * lookup_kw); const char * ecl_smspec_get_general_var_unit( const ecl_smspec_type * ecl_smspec , const char * lookup_kw); @@ -120,7 +125,6 @@ typedef struct ecl_smspec_struct ecl_smspec_type; - void ecl_smspec_init_var( ecl_smspec_type * ecl_smspec , smspec_node_type * smspec_node , const char * keyword , const char * wgname , int num, const char * unit ); void ecl_smspec_select_matching_general_var_list( const ecl_smspec_type * smspec , const char * pattern , stringlist_type * keys); stringlist_type * ecl_smspec_alloc_matching_general_var_list(const ecl_smspec_type * smspec , const char * pattern); @@ -138,21 +142,48 @@ typedef struct ecl_smspec_struct ecl_smspec_type; int ecl_smspec_get_restart_step(const ecl_smspec_type * ecl_smspec); const char * ecl_smspec_get_restart_case( const ecl_smspec_type * ecl_smspec); const char * ecl_smspec_get_join_string( const ecl_smspec_type * smspec); - const float_vector_type * ecl_smspec_get_params_default( const ecl_smspec_type * ecl_smspec ); const int * ecl_smspec_get_grid_dims( const ecl_smspec_type * smspec ); int ecl_smspec_get_params_size( const ecl_smspec_type * smspec ); int ecl_smspec_num_nodes( const ecl_smspec_type * smspec); - const smspec_node_type * ecl_smspec_iget_node( const ecl_smspec_type * smspec , int index ); - char * ecl_smspec_alloc_well_key( const ecl_smspec_type * smspec , const char * keyword , const char * wgname); bool ecl_smspec_equal( const ecl_smspec_type * self , const ecl_smspec_type * other); - void ecl_smspec_sort( ecl_smspec_type * smspec ); + // void ecl_smspec_sort( ecl_smspec_type * smspec ); ert_ecl_unit_enum ecl_smspec_get_unit_system(const ecl_smspec_type * smspec); + #ifdef __cplusplus } #endif + +const ecl::smspec_node * ecl_smspec_add_node(ecl_smspec_type * ecl_smspec, const ecl::smspec_node& node); +const ecl::smspec_node * ecl_smspec_add_node(ecl_smspec_type * ecl_smspec, const char * keyword, int num, const char * unit, float default_value); +const ecl::smspec_node * ecl_smspec_add_node(ecl_smspec_type * ecl_smspec, const char * keyword, const char * unit, float default_value); +const ecl::smspec_node * ecl_smspec_add_node(ecl_smspec_type * ecl_smspec, const char * keyword, const char * wgname, const char * unit, float default_value); +const ecl::smspec_node * ecl_smspec_add_node(ecl_smspec_type * ecl_smspec, const char * keyword, const char * wgname, int num, const char * unit, float default_value); +const ecl::smspec_node * ecl_smspec_add_node(ecl_smspec_type * ecl_smspec, const char * keyword, int num, const char * unit, float default_value); + +const ecl::smspec_node * ecl_smspec_add_node(ecl_smspec_type * ecl_smspec, + int params_index, + const char * keyword, + const char * wgname, + int num, + const char * unit, + float default_value); + +const ecl::smspec_node * ecl_smspec_add_node(ecl_smspec_type * ecl_smspec, + int params_index, + const char * keyword, + const char * wgname, + int num, + const char * unit, + const char * lgr, + int lgr_i, int lgr_j, int lgr_k, + float default_value); + + + + #endif diff --git a/ThirdParty/Ert/lib/include/ert/ecl/ecl_subsidence.hpp b/ThirdParty/Ert/lib/include/ert/ecl/ecl_subsidence.hpp index 84f8977fbb..c41d9091d4 100644 --- a/ThirdParty/Ert/lib/include/ert/ecl/ecl_subsidence.hpp +++ b/ThirdParty/Ert/lib/include/ert/ecl/ecl_subsidence.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'ecl_subsidence.h' is part of ERT - Ensemble based Reservoir Tool. @@ -47,6 +47,12 @@ extern "C" { double utm_x, double utm_y , double depth, double youngs_modulus, double poisson_ratio, double seabed); + double ecl_subsidence_eval_geertsma_rporv( const ecl_subsidence_type * subsidence , const char * base, const char * monitor , ecl_region_type * region , + double utm_x, double utm_y , double depth, + double youngs_modulus, double poisson_ratio, double seabed); + + + #ifdef __cplusplus } diff --git a/ThirdParty/Ert/lib/include/ert/ecl/ecl_sum.hpp b/ThirdParty/Ert/lib/include/ert/ecl/ecl_sum.hpp index a66529fb45..201384b878 100644 --- a/ThirdParty/Ert/lib/include/ert/ecl/ecl_sum.hpp +++ b/ThirdParty/Ert/lib/include/ert/ecl/ecl_sum.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'ecl_sum.h' is part of ERT - Ensemble based Reservoir Tool. @@ -58,8 +58,8 @@ typedef struct ecl_sum_vector_struct ecl_sum_vector_type; typedef struct ecl_sum_struct ecl_sum_type; void ecl_sum_fmt_init_summary_x( const ecl_sum_type * ecl_sum , ecl_sum_fmt_type * fmt ); - double ecl_sum_get_from_sim_time( const ecl_sum_type * ecl_sum , time_t sim_time , const smspec_node_type * node); - double ecl_sum_get_from_sim_days( const ecl_sum_type * ecl_sum , double sim_days , const smspec_node_type * node); + double ecl_sum_get_from_sim_time( const ecl_sum_type * ecl_sum , time_t sim_time , const ecl::smspec_node * node); + double ecl_sum_get_from_sim_days( const ecl_sum_type * ecl_sum , double sim_days , const ecl::smspec_node * node); double ecl_sum_time2days( const ecl_sum_type * ecl_sum , time_t sim_time); void ecl_sum_set_unified( ecl_sum_type * ecl_sum , bool unified ); @@ -93,7 +93,7 @@ typedef struct ecl_sum_struct ecl_sum_type; ecl_sum_type * ecl_sum_fread_alloc_case(const char * , const char * key_join_string); ecl_sum_type * ecl_sum_fread_alloc_case__(const char * input_file , const char * key_join_string , bool include_restart); ecl_sum_type * ecl_sum_fread_alloc_case2__(const char * , const char * key_join_string , bool include_restart, bool lazy_load, int file_options); - ecl_sum_type * ecl_sum_alloc_resample(const ecl_sum_type * ecl_sum, const char * ecl_case, const time_t_vector_type * times); + ecl_sum_type * ecl_sum_alloc_resample(const ecl_sum_type * ecl_sum, const char * ecl_case, const time_t_vector_type * times, bool lower_extrapolation, bool upper_extrapolation); bool ecl_sum_case_exists( const char * input_file ); /* Accessor functions : */ @@ -130,7 +130,7 @@ typedef struct ecl_sum_struct ecl_sum_type; double ecl_sum_get_general_var(const ecl_sum_type * ecl_sum , int time_index , const char * lookup_kw); int ecl_sum_get_general_var_params_index(const ecl_sum_type * ecl_sum , const char * lookup_kw); - const smspec_node_type * ecl_sum_get_general_var_node(const ecl_sum_type * ecl_sum , const char * lookup_kw); + const ecl::smspec_node * ecl_sum_get_general_var_node(const ecl_sum_type * ecl_sum , const char * lookup_kw); bool ecl_sum_has_general_var(const ecl_sum_type * ecl_sum , const char * lookup_kw); bool ecl_sum_has_key(const ecl_sum_type * ecl_sum , const char * lookup_kw); double ecl_sum_get_general_var_from_sim_days( const ecl_sum_type * ecl_sum , double sim_days , const char * var); @@ -190,7 +190,7 @@ typedef struct ecl_sum_struct ecl_sum_type; stringlist_type * ecl_sum_alloc_well_var_list( const ecl_sum_type * ecl_sum ); stringlist_type * ecl_sum_alloc_matching_general_var_list(const ecl_sum_type * ecl_sum , const char * pattern); void ecl_sum_select_matching_general_var_list( const ecl_sum_type * ecl_sum , const char * pattern , stringlist_type * keys); - const ecl_smspec_type * ecl_sum_get_smspec( const ecl_sum_type * ecl_sum ); + ecl_smspec_type * ecl_sum_get_smspec( const ecl_sum_type * ecl_sum ); ecl_smspec_var_type ecl_sum_identify_var_type(const char * var); ecl_smspec_var_type ecl_sum_get_var_type( const ecl_sum_type * ecl_sum , const char * gen_key); bool ecl_sum_var_is_rate( const ecl_sum_type * ecl_sum , const char * gen_key); @@ -230,8 +230,8 @@ typedef struct ecl_sum_struct ecl_sum_type; void ecl_sum_fwrite( const ecl_sum_type * ecl_sum ); bool ecl_sum_can_write( const ecl_sum_type * ecl_sum ); void ecl_sum_fwrite_smspec( const ecl_sum_type * ecl_sum ); - smspec_node_type * ecl_sum_add_smspec_node(ecl_sum_type * ecl_sum, const smspec_node_type * node); - smspec_node_type * ecl_sum_add_var(ecl_sum_type * ecl_sum , + const ecl::smspec_node * ecl_sum_add_smspec_node(ecl_sum_type * ecl_sum, const ecl::smspec_node * node); + const ecl::smspec_node * ecl_sum_add_var(ecl_sum_type * ecl_sum , const char * keyword , const char * wgname , int num , @@ -256,10 +256,10 @@ typedef struct ecl_sum_struct ecl_sum_type; double ecl_sum_iget_last_value(const ecl_sum_type * ecl_sum, int param_index); double ecl_sum_get_last_value_gen_key(const ecl_sum_type * ecl_sum, const char * gen_key); - double ecl_sum_get_last_value_node(const ecl_sum_type * ecl_sum, const smspec_node_type *node); + double ecl_sum_get_last_value_node(const ecl_sum_type * ecl_sum, const ecl::smspec_node *node); double ecl_sum_iget_first_value(const ecl_sum_type * ecl_sum, int param_index); double ecl_sum_get_first_value_gen_key(const ecl_sum_type * ecl_sum, const char * gen_key); - double ecl_sum_get_first_value_node(const ecl_sum_type * ecl_sum, const smspec_node_type *node); + double ecl_sum_get_first_value_node(const ecl_sum_type * ecl_sum, const ecl::smspec_node *node); void ecl_sum_init_datetime64_vector(const ecl_sum_type * ecl_sum, int64_t * data, int multiplier); void ecl_sum_init_double_vector_interp(const ecl_sum_type * ecl_sum, const char * gen_key, const time_t_vector_type * time_points, double * data); diff --git a/ThirdParty/Ert/lib/include/ert/ecl/ecl_sum_data.hpp b/ThirdParty/Ert/lib/include/ert/ecl/ecl_sum_data.hpp index 0c6fdbc0b1..22ab10a768 100644 --- a/ThirdParty/Ert/lib/include/ert/ecl/ecl_sum_data.hpp +++ b/ThirdParty/Ert/lib/include/ert/ecl/ecl_sum_data.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'ecl_sum_data.h' is part of ERT - Ensemble based Reservoir Tool. @@ -75,8 +75,8 @@ typedef struct ecl_sum_data_struct ecl_sum_data_type ; int ecl_sum_data_get_last_report_step( const ecl_sum_data_type * data ); int ecl_sum_data_get_first_report_step( const ecl_sum_data_type * data ); - double ecl_sum_data_get_from_sim_time( const ecl_sum_data_type * data , time_t sim_time , const smspec_node_type * smspec_node); - double ecl_sum_data_get_from_sim_days( const ecl_sum_data_type * data , double sim_days , const smspec_node_type * smspec_node); + double ecl_sum_data_get_from_sim_time( const ecl_sum_data_type * data , time_t sim_time , const ecl::smspec_node& smspec_node); + double ecl_sum_data_get_from_sim_days( const ecl_sum_data_type * data , double sim_days , const ecl::smspec_node& smspec_node); int ecl_sum_data_get_length( const ecl_sum_data_type * data ); int ecl_sum_data_iget_report_step(const ecl_sum_data_type * data , int internal_index); @@ -92,14 +92,14 @@ typedef struct ecl_sum_data_struct ecl_sum_data_type ; void ecl_sum_data_init_datetime64_vector(const ecl_sum_data_type * data, int64_t * output_data, int multiplier); void ecl_sum_data_init_double_frame(const ecl_sum_data_type * data, const ecl_sum_vector_type * keywords, double *output_data); - double_vector_type * ecl_sum_data_alloc_seconds_solution( const ecl_sum_data_type * data , const smspec_node_type * node , double value, bool rates_clamp_lower); + double_vector_type * ecl_sum_data_alloc_seconds_solution( const ecl_sum_data_type * data , const ecl::smspec_node& node , double value, bool rates_clamp_lower); void ecl_sum_data_init_double_frame_interp(const ecl_sum_data_type * data, const ecl_sum_vector_type * keywords, const time_t_vector_type * time_points, double * output_data); void ecl_sum_data_init_double_vector_interp(const ecl_sum_data_type * data, - const smspec_node_type * smspec_node, + const ecl::smspec_node& smspec_node, const time_t_vector_type * time_points, double * output_data); diff --git a/ThirdParty/Ert/lib/include/ert/ecl/ecl_sum_index.hpp b/ThirdParty/Ert/lib/include/ert/ecl/ecl_sum_index.hpp index d68088f976..bb4a216441 100644 --- a/ThirdParty/Ert/lib/include/ert/ecl/ecl_sum_index.hpp +++ b/ThirdParty/Ert/lib/include/ert/ecl/ecl_sum_index.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'ecl_sum_index.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/ecl/ecl_sum_tstep.hpp b/ThirdParty/Ert/lib/include/ert/ecl/ecl_sum_tstep.hpp index 4fc332ea00..ac113a5559 100644 --- a/ThirdParty/Ert/lib/include/ert/ecl/ecl_sum_tstep.hpp +++ b/ThirdParty/Ert/lib/include/ert/ecl/ecl_sum_tstep.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Statoil ASA, Norway. + Copyright (C) 2012 Equinor ASA, Norway. The file 'ecl_sum_tstep.h' is part of ERT - Ensemble based Reservoir Tool. @@ -19,15 +19,15 @@ #ifndef ERT_ECL_SUM_TSTEP_H #define ERT_ECL_SUM_TSTEP_H -#ifdef __cplusplus -extern "C" { -#endif - #include #include #include +#ifdef __cplusplus +extern "C" { +#endif + typedef struct ecl_sum_tstep_struct ecl_sum_tstep_type; ecl_sum_tstep_type * ecl_sum_tstep_alloc_remap_copy( const ecl_sum_tstep_type * src , const ecl_smspec_type * new_smspec, float default_value , const int * params_map); @@ -42,6 +42,9 @@ typedef struct ecl_sum_tstep_struct ecl_sum_tstep_type; ecl_sum_tstep_type * ecl_sum_tstep_alloc_new( int report_step , int ministep , float sim_seconds , const ecl_smspec_type * smspec ); + void ecl_sum_tstep_set_from_node( ecl_sum_tstep_type * tstep , const ecl::smspec_node& smspec_node , float value); + double ecl_sum_tstep_get_from_node( const ecl_sum_tstep_type * tstep , const ecl::smspec_node& smspec_node); + double ecl_sum_tstep_iget(const ecl_sum_tstep_type * ministep , int index); time_t ecl_sum_tstep_get_sim_time(const ecl_sum_tstep_type * ministep); double ecl_sum_tstep_get_sim_days(const ecl_sum_tstep_type * ministep); @@ -50,7 +53,7 @@ typedef struct ecl_sum_tstep_struct ecl_sum_tstep_type; int ecl_sum_tstep_get_report(const ecl_sum_tstep_type * ministep); int ecl_sum_tstep_get_ministep(const ecl_sum_tstep_type * ministep); - void ecl_sum_tstep_fwrite( const ecl_sum_tstep_type * ministep , const int_vector_type * index_map , fortio_type * fortio); + void ecl_sum_tstep_fwrite( const ecl_sum_tstep_type * ministep , const int * index_map , int index_map_size, fortio_type * fortio); void ecl_sum_tstep_iset( ecl_sum_tstep_type * tstep , int index , float value); /// scales with value; equivalent to iset( iget() * scalar) @@ -59,8 +62,6 @@ typedef struct ecl_sum_tstep_struct ecl_sum_tstep_type; /// adds addend to tstep[index]; equivalent to iset( iget() + addend) void ecl_sum_tstep_ishift(ecl_sum_tstep_type * tstep, int index, float addend); - void ecl_sum_tstep_set_from_node( ecl_sum_tstep_type * tstep , const smspec_node_type * smspec_node , float value); - double ecl_sum_tstep_get_from_node( const ecl_sum_tstep_type * tstep , const smspec_node_type * smspec_node); void ecl_sum_tstep_set_from_key( ecl_sum_tstep_type * tstep , const char * gen_key , float value); double ecl_sum_tstep_get_from_key( const ecl_sum_tstep_type * tstep , const char * gen_key); @@ -75,5 +76,7 @@ typedef struct ecl_sum_tstep_struct ecl_sum_tstep_type; #ifdef __cplusplus } + + #endif #endif diff --git a/ThirdParty/Ert/lib/include/ert/ecl/ecl_sum_vector.hpp b/ThirdParty/Ert/lib/include/ert/ecl/ecl_sum_vector.hpp index c9e4ed9c42..b04dee0c8e 100644 --- a/ThirdParty/Ert/lib/include/ert/ecl/ecl_sum_vector.hpp +++ b/ThirdParty/Ert/lib/include/ert/ecl/ecl_sum_vector.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2014 Statoil ASA, Norway. + Copyright (C) 2014 Equinor ASA, Norway. The file 'ecl_sum_vector.h' is part of ERT - Ensemble based Reservoir Tool. @@ -19,14 +19,14 @@ #ifndef ERT_ECL_SUM_VECTOR_H #define ERT_ECL_SUM_VECTOR_H -#ifdef __cplusplus -extern "C" { -#endif - #include #include +#ifdef __cplusplus +extern "C" { +#endif + typedef struct ecl_sum_vector_struct ecl_sum_vector_type; void ecl_sum_vector_free( ecl_sum_vector_type * keylist ); diff --git a/ThirdParty/Ert/lib/include/ert/ecl/ecl_type.hpp b/ThirdParty/Ert/lib/include/ert/ecl/ecl_type.hpp index a218330974..305498057e 100644 --- a/ThirdParty/Ert/lib/include/ert/ecl/ecl_type.hpp +++ b/ThirdParty/Ert/lib/include/ert/ecl/ecl_type.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2017 Statoil ASA, Norway. + Copyright (C) 2017 Equinor ASA, Norway. The file 'ecl_type.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/ecl/ecl_units.hpp b/ThirdParty/Ert/lib/include/ert/ecl/ecl_units.hpp index ecee98a662..c752ff4438 100644 --- a/ThirdParty/Ert/lib/include/ert/ecl/ecl_units.hpp +++ b/ThirdParty/Ert/lib/include/ert/ecl/ecl_units.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2017 Statoil ASA, Norway. + Copyright (C) 2017 Equinor ASA, Norway. The file 'ecl_units.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/ecl/ecl_util.hpp b/ThirdParty/Ert/lib/include/ert/ecl/ecl_util.hpp index 0cf1ada4b7..590068d135 100644 --- a/ThirdParty/Ert/lib/include/ert/ecl/ecl_util.hpp +++ b/ThirdParty/Ert/lib/include/ert/ecl/ecl_util.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'ecl_util.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/ecl/fault_block.hpp b/ThirdParty/Ert/lib/include/ert/ecl/fault_block.hpp index 5d9ebbc27a..ec0b8ad41a 100644 --- a/ThirdParty/Ert/lib/include/ert/ecl/fault_block.hpp +++ b/ThirdParty/Ert/lib/include/ert/ecl/fault_block.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2014 Statoil ASA, Norway. + Copyright (C) 2014 Equinor ASA, Norway. The file 'fault_block.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/ecl/fault_block_layer.hpp b/ThirdParty/Ert/lib/include/ert/ecl/fault_block_layer.hpp index 745fa509d9..2d84d396dd 100644 --- a/ThirdParty/Ert/lib/include/ert/ecl/fault_block_layer.hpp +++ b/ThirdParty/Ert/lib/include/ert/ecl/fault_block_layer.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2014 Statoil ASA, Norway. + Copyright (C) 2014 Equinor ASA, Norway. The file 'fault_block_layer.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/ecl/fortio.h b/ThirdParty/Ert/lib/include/ert/ecl/fortio.h index 93a56eb827..c2228d784c 100644 --- a/ThirdParty/Ert/lib/include/ert/ecl/fortio.h +++ b/ThirdParty/Ert/lib/include/ert/ecl/fortio.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'fortio.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/ecl/grid_dims.hpp b/ThirdParty/Ert/lib/include/ert/ecl/grid_dims.hpp index b7955cf404..510f86d89d 100644 --- a/ThirdParty/Ert/lib/include/ert/ecl/grid_dims.hpp +++ b/ThirdParty/Ert/lib/include/ert/ecl/grid_dims.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'grid_dims.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/ecl/layer.hpp b/ThirdParty/Ert/lib/include/ert/ecl/layer.hpp index 450ee240d3..27c0f268f4 100644 --- a/ThirdParty/Ert/lib/include/ert/ecl/layer.hpp +++ b/ThirdParty/Ert/lib/include/ert/ecl/layer.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2014 Statoil ASA, Norway. + Copyright (C) 2014 Equinor ASA, Norway. The file 'layer.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/ecl/nnc_info.hpp b/ThirdParty/Ert/lib/include/ert/ecl/nnc_info.hpp index 91858cefbf..a6b6efc0a5 100644 --- a/ThirdParty/Ert/lib/include/ert/ecl/nnc_info.hpp +++ b/ThirdParty/Ert/lib/include/ert/ecl/nnc_info.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'nnc_info.h' is part of ERT - Ensemble based Reservoir Tool. @@ -19,16 +19,24 @@ #ifndef ERT_NNC_INFO_H #define ERT_NNC_INFO_H -#ifdef __cplusplus -extern "C" { -#endif #include #include #include - typedef struct nnc_info_struct nnc_info_type; +typedef struct nnc_info_struct nnc_info_type; + +#ifdef __cplusplus +#include + const std::vector& nnc_info_get_grid_index_list(const nnc_info_type * nnc_info, int lgr_nr); + const std::vector& nnc_info_iget_grid_index_list(const nnc_info_type * nnc_info, int lgr_index); + const std::vector& nnc_info_get_self_grid_index_list(const nnc_info_type * nnc_info); +#endif + +#ifdef __cplusplus +extern "C" { +#endif UTIL_IS_INSTANCE_HEADER(nnc_info); @@ -36,13 +44,10 @@ extern "C" { void nnc_info_free( nnc_info_type * nnc_info ); void nnc_info_add_nnc(nnc_info_type * nnc_info, int lgr_nr, int global_cell_number, int nnc_index); - const int_vector_type * nnc_info_iget_grid_index_list(const nnc_info_type * nnc_info, int lgr_index); nnc_vector_type * nnc_info_iget_vector( const nnc_info_type * nnc_info , int lgr_index); - const int_vector_type * nnc_info_get_grid_index_list(const nnc_info_type * nnc_info, int lgr_nr); nnc_vector_type * nnc_info_get_vector( const nnc_info_type * nnc_info , int lgr_nr); - const int_vector_type * nnc_info_get_self_grid_index_list(const nnc_info_type * nnc_info); nnc_vector_type * nnc_info_get_self_vector( const nnc_info_type * nnc_info ); int nnc_info_get_lgr_nr(const nnc_info_type * nnc_info ); @@ -52,6 +57,7 @@ extern "C" { bool nnc_info_equal( const nnc_info_type * nnc_info1 , const nnc_info_type * nnc_info2 ); nnc_info_type * nnc_info_alloc_copy( const nnc_info_type * src_info ); + bool nnc_info_has_grid_index_list( const nnc_info_type * nnc_info, int lgr_nr ); #ifdef __cplusplus } diff --git a/ThirdParty/Ert/lib/include/ert/ecl/nnc_vector.hpp b/ThirdParty/Ert/lib/include/ert/ecl/nnc_vector.hpp index 3c5f6c304c..741bbaa5aa 100644 --- a/ThirdParty/Ert/lib/include/ert/ecl/nnc_vector.hpp +++ b/ThirdParty/Ert/lib/include/ert/ecl/nnc_vector.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'nnc_vector.h' is part of ERT - Ensemble based Reservoir Tool. @@ -19,14 +19,21 @@ #ifndef ERT_NNC_VECTOR_H #define ERT_NNC_VECTOR_H -#ifdef __cplusplus -extern "C" { -#endif #include #include - typedef struct nnc_vector_struct nnc_vector_type; +typedef struct nnc_vector_struct nnc_vector_type; + +#ifdef __cplusplus +#include + const std::vector& nnc_vector_get_grid_index_list(const nnc_vector_type * nnc_vector); + const std::vector& nnc_vector_get_nnc_index_list(const nnc_vector_type * nnc_vector); +#endif + +#ifdef __cplusplus +extern "C" { +#endif UTIL_IS_INSTANCE_HEADER(nnc_vector); @@ -36,8 +43,6 @@ extern "C" { nnc_vector_type * nnc_vector_alloc_copy(const nnc_vector_type * src_vector); void nnc_vector_free( nnc_vector_type * nnc_vector ); void nnc_vector_add_nnc(nnc_vector_type * nnc_vector, int global_cell_number, int nnc_index); - const int_vector_type * nnc_vector_get_grid_index_list(const nnc_vector_type * nnc_vector); - const int_vector_type * nnc_vector_get_nnc_index_list(const nnc_vector_type * nnc_vector); int nnc_vector_get_lgr_nr(const nnc_vector_type * nnc_vector ); void nnc_vector_free__(void * arg); int nnc_vector_get_size( const nnc_vector_type * nnc_vector ); diff --git a/ThirdParty/Ert/lib/include/ert/ecl/smspec_node.h b/ThirdParty/Ert/lib/include/ert/ecl/smspec_node.h index e0e4b77ccd..b058fc8898 100644 --- a/ThirdParty/Ert/lib/include/ert/ecl/smspec_node.h +++ b/ThirdParty/Ert/lib/include/ert/ecl/smspec_node.h @@ -4,6 +4,133 @@ to switch to include the new hpp header directly in your code. */ -#include +#include +#include + +#ifndef ERT_SMSPEC_NODE_H +#define ERT_SMSPEC_NODE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define DUMMY_WELL ":+:+:+:+" +#define IS_DUMMY_WELL(well) (strcmp((well) , DUMMY_WELL) == 0) +#define SMSPEC_PARAMS_INDEX_INVALID -77 + + +#define SMSPEC_TIME_KEYWORD "TIME" +#define SMSPEC_TIME_NUMS_VALUE -32676 + +#define SMSPEC_YEARS_KEYWORD "YEARS" +#define SMSPEC_YEARS_NUMS_VALUE -32676 + +typedef enum {ECL_SMSPEC_INVALID_VAR = 0 , + ECL_SMSPEC_FIELD_VAR = 1 , /* X */ + ECL_SMSPEC_REGION_VAR = 2 , /* X */ + ECL_SMSPEC_GROUP_VAR = 3 , /* X */ + ECL_SMSPEC_WELL_VAR = 4 , /* X */ + ECL_SMSPEC_SEGMENT_VAR = 5 , /* X */ + ECL_SMSPEC_BLOCK_VAR = 6 , /* X */ + ECL_SMSPEC_AQUIFER_VAR = 7 , + ECL_SMSPEC_COMPLETION_VAR = 8 , /* X */ + ECL_SMSPEC_NETWORK_VAR = 9 , + ECL_SMSPEC_REGION_2_REGION_VAR = 10 , + ECL_SMSPEC_LOCAL_BLOCK_VAR = 11 , /* X */ + ECL_SMSPEC_LOCAL_COMPLETION_VAR = 12 , /* X */ + ECL_SMSPEC_LOCAL_WELL_VAR = 13 , /* X */ + ECL_SMSPEC_MISC_VAR = 14 /* X */} ecl_smspec_var_type; + +#define SMSPEC_NUMS_INVALID -991199 +#define SMSPEC_NUMS_WELL 1 +#define SMSPEC_NUMS_GROUP 2 +#define SMSPEC_NUMS_FIELD 0 + +#define SMSPEC_TYPE_ID 61550451 + + char * smspec_alloc_block_ijk_key( const char * join_string , const char * keyword , int i , int j , int k); + char * smspec_alloc_completion_ijk_key( const char * join_string , const char * keyword, const char * wgname , int i , int j , int k); + char * smspec_alloc_completion_num_key( const char * join_string , const char * keyword, const char * wgname , int num); + char * smspec_alloc_group_key( const char * join_string , const char * keyword , const char * wgname); + char * smspec_alloc_well_key( const char * join_string , const char * keyword , const char * wgname); + char * smspec_alloc_region_key( const char * join_string , const char * keyword , int num); + char * smspec_alloc_region_2_region_r1r2_key( const char * join_string , const char * keyword , int r1, int r2); + char * smspec_alloc_region_2_region_num_key( const char * join_string , const char * keyword , int num); + char * smspec_alloc_segment_key( const char * join_string , const char * keyword , const char * wgname , int num); + char * smspec_alloc_block_num_key( const char * join_string , const char * keyword , int num); + char * smspec_alloc_local_well_key( const char * join_string , const char * keyword , const char * lgr_name , const char * wgname); + char * smspec_alloc_local_block_key( const char * join_string , const char * keyword , const char * lgr_name , int i , int j , int k); + char * smspec_alloc_local_completion_key( const char * join_string, const char * keyword , const char * lgr_name , const char * wgname , int i , int j , int k); + + bool smspec_node_identify_total(const char * keyword, ecl_smspec_var_type var_type); + bool smspec_node_identify_rate(const char * keyword); + + bool smspec_node_equal( const void * node1, const void * node2); + + void smspec_node_init( void * smspec_node, + ecl_smspec_var_type var_type , + const char * wgname , + const char * keyword , + const char * unit , + const char * key_join_string , + const int grid_dims[3] , + int num); + + void * smspec_node_alloc( int param_index, + const char * keyword , + const char * wgname, + int num, + const char * unit , + const int grid_dims[3] , + float default_value, + const char * key_join_string); + + void * smspec_node_alloc_lgr( ecl_smspec_var_type var_type , + const char * wgname , + const char * keyword , + const char * unit , + const char * lgr , + const char * key_join_string , + int lgr_i, int lgr_j , int lgr_k, + int param_index, + float default_value); + + void * smspec_node_alloc_copy( const void* ); + + void smspec_node_free( void * index ); + void smspec_node_free__(void * arg); + void smspec_node_set_params_index( void * smspec_node , int params_index); + int smspec_node_get_params_index( const void * smspec_node ); + const char * smspec_node_get_gen_key1( const void * smspec_node); + const char * smspec_node_get_gen_key2( const void * smspec_node); + ecl_smspec_var_type smspec_node_get_var_type( const void * smspec_node); + int smspec_node_get_num( const void * smspec_node); + const char * smspec_node_get_wgname( const void * smspec_node); + const char * smspec_node_get_keyword( const void * smspec_node); + const char * smspec_node_get_unit( const void * smspec_node); + bool smspec_node_is_rate( const void * smspec_node ); + bool smspec_node_is_total( const void * smspec_node ); + bool smspec_node_is_historical( const void * smspec_node ); + bool smspec_node_need_nums( const void * smspec_node ); + void smspec_node_fprintf( const void * smspec_node , FILE * stream); + + float smspec_node_get_default( const void * smspec_node); + + const int* smspec_node_get_ijk( const void * smpsec_node ); + const char* smspec_node_get_lgr_name( const void * smpsec_node ); + const int* smspec_node_get_lgr_ijk( const void * smpsec_node ); + + int smspec_node_get_R1( const void * smpsec_node ); + int smspec_node_get_R2( const void * smpsec_node ); + + bool smspec_node_lt( const void * node1, const void * node2); + bool smspec_node_gt( const void * node1, const void * node2); + int smspec_node_cmp( const void * node1, const void * node2); + int smspec_node_cmp__( const void * node1, const void * node2); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/ThirdParty/Ert/lib/include/ert/ecl/smspec_node.hpp b/ThirdParty/Ert/lib/include/ert/ecl/smspec_node.hpp index a8dfc0dba2..50dd00e451 100644 --- a/ThirdParty/Ert/lib/include/ert/ecl/smspec_node.hpp +++ b/ThirdParty/Ert/lib/include/ert/ecl/smspec_node.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Statoil ASA, Norway. + Copyright (C) 2012 Equinor ASA, Norway. The file 'smspec_node.h' is part of ERT - Ensemble based Reservoir Tool. @@ -17,132 +17,110 @@ */ -#ifndef ERT_SMSPEC_NODE_H -#define ERT_SMSPEC_NODE_H +#ifndef ERT_SMSPEC_NODE_HPP +#define ERT_SMSPEC_NODE_HPP #include #include -#ifdef __cplusplus -extern "C" { -#endif +#include +#include -#define DUMMY_WELL ":+:+:+:+" -#define IS_DUMMY_WELL(well) (strcmp((well) , DUMMY_WELL) == 0) -#define SMSPEC_PARAMS_INDEX_INVALID -77 +#include + +#include -#define SMSPEC_TIME_KEYWORD "TIME" -#define SMSPEC_TIME_NUMS_VALUE -32676 +namespace ecl { -#define SMSPEC_YEARS_KEYWORD "YEARS" -#define SMSPEC_YEARS_NUMS_VALUE -32676 + class smspec_node { + private: + std::string wgname; + std::string keyword; /* The value of the KEYWORDS vector for this elements. */ + std::string unit; /* The value of the UNITS vector for this elements. */ + int num; /* The value of the NUMS vector for this elements - NB this will have the value SMSPEC_NUMS_INVALID if the smspec file does not have a NUMS vector. */ + std::string lgr_name; /* The lgr name of the current variable - will be NULL for non-lgr variables. */ + std::array lgr_ijk; -typedef enum {ECL_SMSPEC_INVALID_VAR = 0 , - ECL_SMSPEC_FIELD_VAR = 1 , /* X */ - ECL_SMSPEC_REGION_VAR = 2 , /* X */ - ECL_SMSPEC_GROUP_VAR = 3 , /* X */ - ECL_SMSPEC_WELL_VAR = 4 , /* X */ - ECL_SMSPEC_SEGMENT_VAR = 5 , /* X */ - ECL_SMSPEC_BLOCK_VAR = 6 , /* X */ - ECL_SMSPEC_AQUIFER_VAR = 7 , - ECL_SMSPEC_COMPLETION_VAR = 8 , /* X */ - ECL_SMSPEC_NETWORK_VAR = 9 , - ECL_SMSPEC_REGION_2_REGION_VAR = 10 , - ECL_SMSPEC_LOCAL_BLOCK_VAR = 11 , /* X */ - ECL_SMSPEC_LOCAL_COMPLETION_VAR = 12 , /* X */ - ECL_SMSPEC_LOCAL_WELL_VAR = 13 , /* X */ - ECL_SMSPEC_MISC_VAR = 14 /* X */} ecl_smspec_var_type; + /*------------------------------------------- All members below this line are *derived* quantities. */ + std::string gen_key1; /* The main composite key, i.e. WWCT:OP3 for this element. */ + std::string gen_key2; /* Some of the ijk based elements will have both a xxx:i,j,k and a xxx:num key. Some of the region_2_region elements will have both a xxx:num and a xxx:r2-r2 key. Mostly NULL. */ + ecl_smspec_var_type var_type; /* The variable type */ + std::array ijk; /* The ijk coordinates (NB: OFFSET 1) corresponding to the nums value - will be NULL if not relevant. */ + bool rate_variable; /* Is this a rate variable (i.e. WOPR) or a state variable (i.e. BPR). Relevant when doing time interpolation. */ + bool total_variable; /* Is this a total variable like WOPT? */ + bool historical; /* Does the name end with 'H'? */ + int params_index; /* The index of this variable (applies to all the vectors - in particular the PARAMS vectors of the summary files *.Snnnn / *.UNSMRY ). */ + float default_value; /* Default value for this variable. */ -#define SMSPEC_NUMS_INVALID -991199 -#define SMSPEC_NUMS_WELL 1 -#define SMSPEC_NUMS_GROUP 2 -#define SMSPEC_NUMS_FIELD 0 + static ecl_smspec_var_type identify_special_var( const char * var ); + void set_wgname(const char * wgname); + void set_num( const int grid_dims[3] , int num_); + void set_gen_keys( const char * key_join_string_); + void decode_R1R2( int * r1 , int * r2) const; + void set_lgr_ijk( int lgr_i , int lgr_j , int lgr_k); - typedef struct smspec_node_struct smspec_node_type; + public: - char * smspec_alloc_block_ijk_key( const char * join_string , const char * keyword , int i , int j , int k); - char * smspec_alloc_completion_ijk_key( const char * join_string , const char * keyword, const char * wgname , int i , int j , int k); - char * smspec_alloc_completion_num_key( const char * join_string , const char * keyword, const char * wgname , int num); - char * smspec_alloc_group_key( const char * join_string , const char * keyword , const char * wgname); - char * smspec_alloc_well_key( const char * join_string , const char * keyword , const char * wgname); - char * smspec_alloc_region_key( const char * join_string , const char * keyword , int num); - char * smspec_alloc_region_2_region_r1r2_key( const char * join_string , const char * keyword , int r1, int r2); - char * smspec_alloc_region_2_region_num_key( const char * join_string , const char * keyword , int num); - char * smspec_alloc_segment_key( const char * join_string , const char * keyword , const char * wgname , int num); - char * smspec_alloc_block_num_key( const char * join_string , const char * keyword , int num); - char * smspec_alloc_local_well_key( const char * join_string , const char * keyword , const char * lgr_name , const char * wgname); - char * smspec_alloc_local_block_key( const char * join_string , const char * keyword , const char * lgr_name , int i , int j , int k); - char * smspec_alloc_local_completion_key( const char * join_string, const char * keyword , const char * lgr_name , const char * wgname , int i , int j , int k); + static ecl_smspec_var_type valid_type(const char * keyword, const char * wgname, int num); + int cmp(const smspec_node& node2) const; + static int cmp(const smspec_node& node1, const smspec_node& node2); - bool smspec_node_equal( const smspec_node_type * node1, const smspec_node_type * node2); + smspec_node(int param_index, + const char * keyword , + const char * wgname, + int num, + const char * unit , + const int grid_dims[3] , + float default_value, + const char * key_join_string); - void smspec_node_init( smspec_node_type * smspec_node, - ecl_smspec_var_type var_type , - const char * wgname , - const char * keyword , - const char * unit , - const char * key_join_string , - const int grid_dims[3] , - int num); + smspec_node(int param_index, + const char * keyword , + const char * wgname , + const char * unit , + const char * lgr , + int lgr_i, int lgr_j , int lgr_k, + float default_value, + const char * key_join_string); - smspec_node_type * smspec_node_alloc( ecl_smspec_var_type var_type , - const char * wgname , - const char * keyword , - const char * unit , - const char * key_join_string , - const int grid_dims[3] , - int num , int param_index, float default_value); + smspec_node(int param_index, const char * keyword, const char * unit, float default_value); + smspec_node(int param_index, const char * keyword, int num, const char * unit, const int grid_dims[3], float default_value, const char * key_join_string); + smspec_node(int param_index, const char * keyword, int num, const char * unit, float default_value, const char * key_join_string); + smspec_node(int param_index, const char * keyword, const char * wgname, const char * unit, float default_value, const char * key_join_string); + smspec_node(int param_index, const char * keyword, const char * wgname, int num, const char * unit, float default_value, const char * key_join_string); + smspec_node(const smspec_node& node, int param_index); - smspec_node_type * smspec_node_alloc_lgr( ecl_smspec_var_type var_type , - const char * wgname , - const char * keyword , - const char * unit , - const char * lgr , - const char * key_join_string , - int lgr_i, int lgr_j , int lgr_k, - int param_index, - float default_value); + static ecl_smspec_var_type identify_var_type(const char * var); - smspec_node_type * smspec_node_alloc_new(int params_index, float default_value); - smspec_node_type * smspec_node_alloc_copy( const smspec_node_type* ); + static int cmp( const smspec_node * node1, const smspec_node * node2) { + return node1->cmp(*node2); + } - void smspec_node_free( smspec_node_type * index ); - void smspec_node_free__(void * arg); - void smspec_node_set_params_index( smspec_node_type * smspec_node , int params_index); - int smspec_node_get_params_index( const smspec_node_type * smspec_node ); - const char * smspec_node_get_gen_key1( const smspec_node_type * smspec_node); - const char * smspec_node_get_gen_key2( const smspec_node_type * smspec_node); - ecl_smspec_var_type smspec_node_get_var_type( const smspec_node_type * smspec_node); - int smspec_node_get_num( const smspec_node_type * smspec_node); - const char * smspec_node_get_wgname( const smspec_node_type * smspec_node); - const char * smspec_node_get_keyword( const smspec_node_type * smspec_node); - const char * smspec_node_get_unit( const smspec_node_type * smspec_node); - void smspec_node_set_unit( smspec_node_type * smspec_node , const char * unit ); - bool smspec_node_is_rate( const smspec_node_type * smspec_node ); - bool smspec_node_is_total( const smspec_node_type * smspec_node ); - bool smspec_node_is_historical( const smspec_node_type * smspec_node ); - bool smspec_node_need_nums( const smspec_node_type * smspec_node ); - void smspec_node_fprintf( const smspec_node_type * smspec_node , FILE * stream); + int get_R1() const; + int get_R2() const; + const char * get_gen_key1() const; + const char * get_gen_key2() const; + ecl_smspec_var_type get_var_type() const; + int get_num() const; + const char * get_wgname() const; + const char * get_keyword() const; + const char * get_unit() const; + bool is_rate() const; + bool is_total() const; + bool is_historical() const; + bool need_nums() const; + void fprintf__( FILE * stream) const; + int get_params_index() const; + float get_default() const; + const std::array& get_ijk() const; + const char * get_lgr_name() const; + const std::array& get_lgr_ijk() const; - void smspec_node_set_default( smspec_node_type * smspec_node , float default_value); - float smspec_node_get_default( const smspec_node_type * smspec_node); + }; - const int* smspec_node_get_ijk( const smspec_node_type * smpsec_node ); - const char* smspec_node_get_lgr_name( const smspec_node_type * smpsec_node ); - const int* smspec_node_get_lgr_ijk( const smspec_node_type * smpsec_node ); - - int smspec_node_get_R1( const smspec_node_type * smpsec_node ); - int smspec_node_get_R2( const smspec_node_type * smpsec_node ); - - int smspec_node_cmp( const smspec_node_type * node1, const smspec_node_type * node2); - int smspec_node_cmp__( const void * node1, const void * node2); - bool smspec_node_identify_total(const char * keyword, ecl_smspec_var_type var_type); - bool smspec_node_identify_rate(const char * keyword); - -#ifdef __cplusplus } -#endif + #endif diff --git a/ThirdParty/Ert/lib/include/ert/ecl_well/well_branch_collection.hpp b/ThirdParty/Ert/lib/include/ert/ecl_well/well_branch_collection.hpp index d7aca7a963..c8c942ce96 100644 --- a/ThirdParty/Ert/lib/include/ert/ecl_well/well_branch_collection.hpp +++ b/ThirdParty/Ert/lib/include/ert/ecl_well/well_branch_collection.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'well_branch_collection.h' is part of ERT - Ensemble based Reservoir Tool. @@ -40,7 +40,7 @@ extern "C" { int well_branch_collection_get_size( const well_branch_collection_type * branches ); const well_segment_type * well_branch_collection_iget_start_segment( const well_branch_collection_type * branches , int index ); const well_segment_type * well_branch_collection_get_start_segment( const well_branch_collection_type * branches , int branch_id); - bool well_branch_collection_add_start_segment( well_branch_collection_type * branches , const well_segment_type * start_segment); + bool well_branch_collection_add_start_segment( well_branch_collection_type * branches , well_segment_type * start_segment); UTIL_IS_INSTANCE_HEADER( well_branch_collection ); diff --git a/ThirdParty/Ert/lib/include/ert/ecl_well/well_conn.hpp b/ThirdParty/Ert/lib/include/ert/ecl_well/well_conn.hpp index 610779ab5d..eabcbc421b 100644 --- a/ThirdParty/Ert/lib/include/ert/ecl_well/well_conn.hpp +++ b/ThirdParty/Ert/lib/include/ert/ecl_well/well_conn.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'well_conn.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/ecl_well/well_conn_collection.hpp b/ThirdParty/Ert/lib/include/ert/ecl_well/well_conn_collection.hpp index 3cc9a178c8..e08fe23674 100644 --- a/ThirdParty/Ert/lib/include/ert/ecl_well/well_conn_collection.hpp +++ b/ThirdParty/Ert/lib/include/ert/ecl_well/well_conn_collection.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'well_conn_collection.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/ecl_well/well_const.hpp b/ThirdParty/Ert/lib/include/ert/ecl_well/well_const.hpp index 41a2ade9f2..833e5c9b00 100644 --- a/ThirdParty/Ert/lib/include/ert/ecl_well/well_const.hpp +++ b/ThirdParty/Ert/lib/include/ert/ecl_well/well_const.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'well_const.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/ecl_well/well_info.hpp b/ThirdParty/Ert/lib/include/ert/ecl_well/well_info.hpp index b7bad41564..b3474c0db5 100644 --- a/ThirdParty/Ert/lib/include/ert/ecl_well/well_info.hpp +++ b/ThirdParty/Ert/lib/include/ert/ecl_well/well_info.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'well_info.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/ecl_well/well_rseg_loader.hpp b/ThirdParty/Ert/lib/include/ert/ecl_well/well_rseg_loader.hpp index 1270fba0d8..2060487ded 100644 --- a/ThirdParty/Ert/lib/include/ert/ecl_well/well_rseg_loader.hpp +++ b/ThirdParty/Ert/lib/include/ert/ecl_well/well_rseg_loader.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'well_info.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/ecl_well/well_segment.hpp b/ThirdParty/Ert/lib/include/ert/ecl_well/well_segment.hpp index 084cfea8da..cee97fe73d 100644 --- a/ThirdParty/Ert/lib/include/ert/ecl_well/well_segment.hpp +++ b/ThirdParty/Ert/lib/include/ert/ecl_well/well_segment.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'well_segment.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/ecl_well/well_segment_collection.hpp b/ThirdParty/Ert/lib/include/ert/ecl_well/well_segment_collection.hpp index fc4dd95d45..270d1171bb 100644 --- a/ThirdParty/Ert/lib/include/ert/ecl_well/well_segment_collection.hpp +++ b/ThirdParty/Ert/lib/include/ert/ecl_well/well_segment_collection.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'well_segment_collection.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/ecl_well/well_state.hpp b/ThirdParty/Ert/lib/include/ert/ecl_well/well_state.hpp index c41e215685..b6151b9aae 100644 --- a/ThirdParty/Ert/lib/include/ert/ecl_well/well_state.hpp +++ b/ThirdParty/Ert/lib/include/ert/ecl_well/well_state.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'well_state.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/ecl_well/well_ts.hpp b/ThirdParty/Ert/lib/include/ert/ecl_well/well_ts.hpp index 5044b685b0..572462790b 100644 --- a/ThirdParty/Ert/lib/include/ert/ecl_well/well_ts.hpp +++ b/ThirdParty/Ert/lib/include/ert/ecl_well/well_ts.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'well_ts.h' is part of ERT - Ensemble based Reservoir Tool. @@ -37,7 +37,7 @@ extern "C" { well_state_type * well_ts_get_state_from_report( const well_ts_type * well_ts , int report_nr); well_state_type * well_ts_iget_state( const well_ts_type * well_ts , int index); int well_ts_get_size( const well_ts_type * well_ts); - char * well_ts_get_name( const well_ts_type * well_ts); + const char * well_ts_get_name( const well_ts_type * well_ts); well_state_type * well_ts_get_first_state( const well_ts_type * well_ts); well_state_type * well_ts_get_last_state( const well_ts_type * well_ts); diff --git a/ThirdParty/Ert/lib/include/ert/geometry/geo_pointset.hpp b/ThirdParty/Ert/lib/include/ert/geometry/geo_pointset.hpp index 7e549e6852..d591c513f0 100644 --- a/ThirdParty/Ert/lib/include/ert/geometry/geo_pointset.hpp +++ b/ThirdParty/Ert/lib/include/ert/geometry/geo_pointset.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'geo_pointset.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/geometry/geo_polygon.hpp b/ThirdParty/Ert/lib/include/ert/geometry/geo_polygon.hpp index b7287644b8..675942701a 100644 --- a/ThirdParty/Ert/lib/include/ert/geometry/geo_polygon.hpp +++ b/ThirdParty/Ert/lib/include/ert/geometry/geo_polygon.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'geo_polygon.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/geometry/geo_polygon_collection.hpp b/ThirdParty/Ert/lib/include/ert/geometry/geo_polygon_collection.hpp index 1ee312ee10..36777e1a8a 100644 --- a/ThirdParty/Ert/lib/include/ert/geometry/geo_polygon_collection.hpp +++ b/ThirdParty/Ert/lib/include/ert/geometry/geo_polygon_collection.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2014 Statoil ASA, Norway. + Copyright (C) 2014 Equinor ASA, Norway. The file 'geo_polygon_collection.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/geometry/geo_region.hpp b/ThirdParty/Ert/lib/include/ert/geometry/geo_region.hpp index e719112d2c..882c1553e4 100644 --- a/ThirdParty/Ert/lib/include/ert/geometry/geo_region.hpp +++ b/ThirdParty/Ert/lib/include/ert/geometry/geo_region.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'geo_region.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/geometry/geo_surface.hpp b/ThirdParty/Ert/lib/include/ert/geometry/geo_surface.hpp index 8a827b5b88..b5c77dc136 100644 --- a/ThirdParty/Ert/lib/include/ert/geometry/geo_surface.hpp +++ b/ThirdParty/Ert/lib/include/ert/geometry/geo_surface.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'geo_surface.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/geometry/geo_util.hpp b/ThirdParty/Ert/lib/include/ert/geometry/geo_util.hpp index a988963dbc..b02d56df83 100644 --- a/ThirdParty/Ert/lib/include/ert/geometry/geo_util.hpp +++ b/ThirdParty/Ert/lib/include/ert/geometry/geo_util.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'geo_util.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/util/atomic.h b/ThirdParty/Ert/lib/include/ert/util/atomic.h index 08aae0110e..16cf9a1f2d 100644 --- a/ThirdParty/Ert/lib/include/ert/util/atomic.h +++ b/ThirdParty/Ert/lib/include/ert/util/atomic.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'atomic.h' is part of ERT - Ensemble based Reservoir Tool. @@ -30,124 +30,124 @@ /** - * Atomic type. - */ +�* Atomic type. +�*/ typedef struct { volatile int counter; } atomic_t; -#define ATOMIC_INIT(i)  { (i) } +#define ATOMIC_INIT(i) �{ (i) } /** - * Read atomic variable - * @param v pointer of type atomic_t - * - * Atomically reads the value of @v. - */ +�* Read atomic variable +�* @param v pointer of type atomic_t +�* +�* Atomically reads the value of @v. +�*/ #define atomic_read(v) ((v)->counter) /** - * Set atomic variable - * @param v pointer of type atomic_t - * @param i required value - */ +�* Set atomic variable +�* @param v pointer of type atomic_t +�* @param i required value +�*/ #define atomic_set(v,i) (((v)->counter) = (i)) /** - * Add to the atomic variable - * @param i integer value to add - * @param v pointer of type atomic_t - */ +�* Add to the atomic variable +�* @param i integer value to add +�* @param v pointer of type atomic_t +�*/ static inline void atomic_add( int i, atomic_t *v ) { (void)__sync_add_and_fetch(&v->counter, i); } /** - * Subtract the atomic variable - * @param i integer value to subtract - * @param v pointer of type atomic_t - * - * Atomically subtracts @i from @v. - */ +�* Subtract the atomic variable +�* @param i integer value to subtract +�* @param v pointer of type atomic_t +�* +�* Atomically subtracts @i from @v. +�*/ static inline void atomic_sub( int i, atomic_t *v ) { (void)__sync_sub_and_fetch(&v->counter, i); } /** - * Subtract value from variable and test result - * @param i integer value to subtract - * @param v pointer of type atomic_t - * - * Atomically subtracts @i from @v and returns - * true if the result is zero, or false for all - * other cases. - */ +�* Subtract value from variable and test result +�* @param i integer value to subtract +�* @param v pointer of type atomic_t +�* +�* Atomically subtracts @i from @v and returns +�* true if the result is zero, or false for all +�* other cases. +�*/ static inline int atomic_sub_and_test( int i, atomic_t *v ) { return !(__sync_sub_and_fetch(&v->counter, i)); } /** - * Increment atomic variable - * @param v pointer of type atomic_t - * - * Atomically increments @v by 1. - */ +�* Increment atomic variable +�* @param v pointer of type atomic_t +�* +�* Atomically increments @v by 1. +�*/ static inline void atomic_inc( atomic_t *v ) { (void)__sync_fetch_and_add(&v->counter, 1); } /** - * @brief decrement atomic variable - * @param v: pointer of type atomic_t - * - * Atomically decrements @v by 1.  Note that the guaranteed - * useful range of an atomic_t is only 24 bits. - */ +�* @brief decrement atomic variable +�* @param v: pointer of type atomic_t +�* +�* Atomically decrements @v by 1. �Note that the guaranteed +�* useful range of an atomic_t is only 24 bits. +�*/ static inline void atomic_dec( atomic_t *v ) { (void)__sync_fetch_and_sub(&v->counter, 1); } /** - * @brief Decrement and test - * @param v pointer of type atomic_t - * - * Atomically decrements @v by 1 and - * returns true if the result is 0, or false for all other - * cases. - */ +�* @brief Decrement and test +�* @param v pointer of type atomic_t +�* +�* Atomically decrements @v by 1 and +�* returns true if the result is 0, or false for all other +�* cases. +�*/ static inline int atomic_dec_and_test( atomic_t *v ) { return !(__sync_sub_and_fetch(&v->counter, 1)); } /** - * @brief Increment and test - * @param v pointer of type atomic_t - * - * Atomically increments @v by 1 - * and returns true if the result is zero, or false for all - * other cases. - */ +�* @brief Increment and test +�* @param v pointer of type atomic_t +�* +�* Atomically increments @v by 1 +�* and returns true if the result is zero, or false for all +�* other cases. +�*/ static inline int atomic_inc_and_test( atomic_t *v ) { return !(__sync_add_and_fetch(&v->counter, 1)); } /** - * @brief add and test if negative - * @param v pointer of type atomic_t - * @param i integer value to add - * - * Atomically adds @i to @v and returns true - * if the result is negative, or false when - * result is greater than or equal to zero. - */ +�* @brief add and test if negative +�* @param v pointer of type atomic_t +�* @param i integer value to add +�* +�* Atomically adds @i to @v and returns true +�* if the result is negative, or false when +�* result is greater than or equal to zero. +�*/ static inline int atomic_add_negative( int i, atomic_t *v ) { return (__sync_add_and_fetch(&v->counter, i) < 0); @@ -168,14 +168,14 @@ static inline int atomic_add_negative( int i, atomic_t *v ) // ////As a second example, consider a compare and swap operation, frequently used in lock-free algorithms. Once again, it's trivially: ///** -// * @brief compare and swap -// * @param v pointer of type atomic_t -// * -// * If the current value of @b v is @b oldval, -// * then write @b newval into @b v. Returns #TRUE if -// * the comparison is successful and @b newval was -// * written. -// */ +//�* @brief compare and swap +//�* @param v pointer of type atomic_t +//�* +//�* If the current value of @b v is @b oldval, +//�* then write @b newval into @b v. Returns #TRUE if +//�* the comparison is successful and @b newval was +//�* written. +//�*/ //static inline int atomic_cas( atomic_t *v, int oldval, int newval ) //{ // return __sync_bool_compare_and_swap(&v->counter, oldval, newval); diff --git a/ThirdParty/Ert/lib/include/ert/util/buffer.hpp b/ThirdParty/Ert/lib/include/ert/util/buffer.hpp index 167028a46b..0784c33c4b 100644 --- a/ThirdParty/Ert/lib/include/ert/util/buffer.hpp +++ b/ThirdParty/Ert/lib/include/ert/util/buffer.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'buffer.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/util/ecl_version.hpp b/ThirdParty/Ert/lib/include/ert/util/ecl_version.hpp index 83c39ae8b2..c431152a91 100644 --- a/ThirdParty/Ert/lib/include/ert/util/ecl_version.hpp +++ b/ThirdParty/Ert/lib/include/ert/util/ecl_version.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2016 Statoil ASA, Norway. + Copyright (C) 2016 Equinor ASA, Norway. The file 'ecl_version.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/util/hash.hpp b/ThirdParty/Ert/lib/include/ert/util/hash.hpp index deae544285..4fdc1426ab 100644 --- a/ThirdParty/Ert/lib/include/ert/util/hash.hpp +++ b/ThirdParty/Ert/lib/include/ert/util/hash.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'hash.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/util/hash_node.hpp b/ThirdParty/Ert/lib/include/ert/util/hash_node.hpp index 8579068ebb..bc0a7194b8 100644 --- a/ThirdParty/Ert/lib/include/ert/util/hash_node.hpp +++ b/ThirdParty/Ert/lib/include/ert/util/hash_node.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'hash_node.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/util/hash_sll.hpp b/ThirdParty/Ert/lib/include/ert/util/hash_sll.hpp index 2af6319e41..4a830e1374 100644 --- a/ThirdParty/Ert/lib/include/ert/util/hash_sll.hpp +++ b/ThirdParty/Ert/lib/include/ert/util/hash_sll.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'hash_sll.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/util/lookup_table.hpp b/ThirdParty/Ert/lib/include/ert/util/lookup_table.hpp index 9658cd411b..781842d127 100644 --- a/ThirdParty/Ert/lib/include/ert/util/lookup_table.hpp +++ b/ThirdParty/Ert/lib/include/ert/util/lookup_table.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'lookup_table.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/util/mzran.hpp b/ThirdParty/Ert/lib/include/ert/util/mzran.hpp index 06315a06ce..fbabf0d3c1 100644 --- a/ThirdParty/Ert/lib/include/ert/util/mzran.hpp +++ b/ThirdParty/Ert/lib/include/ert/util/mzran.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'mzran.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/util/node_ctype.hpp b/ThirdParty/Ert/lib/include/ert/util/node_ctype.hpp index 344a3aa0f3..57c91d6698 100644 --- a/ThirdParty/Ert/lib/include/ert/util/node_ctype.hpp +++ b/ThirdParty/Ert/lib/include/ert/util/node_ctype.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'node_ctype.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/util/node_data.hpp b/ThirdParty/Ert/lib/include/ert/util/node_data.hpp index 4e572f1836..a4aa3d0ad4 100644 --- a/ThirdParty/Ert/lib/include/ert/util/node_data.hpp +++ b/ThirdParty/Ert/lib/include/ert/util/node_data.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'node_data.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/util/parser.hpp b/ThirdParty/Ert/lib/include/ert/util/parser.hpp index d00e311f0f..250cea4fc9 100644 --- a/ThirdParty/Ert/lib/include/ert/util/parser.hpp +++ b/ThirdParty/Ert/lib/include/ert/util/parser.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'parser.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/util/path_stack.hpp b/ThirdParty/Ert/lib/include/ert/util/path_stack.hpp index 7da9f9fc27..237852e3ac 100644 --- a/ThirdParty/Ert/lib/include/ert/util/path_stack.hpp +++ b/ThirdParty/Ert/lib/include/ert/util/path_stack.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Statoil ASA, Norway. + Copyright (C) 2012 Equinor ASA, Norway. The file 'path_stack.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/util/perm_vector.hpp b/ThirdParty/Ert/lib/include/ert/util/perm_vector.hpp index 60662c2e9b..539c2d4e50 100644 --- a/ThirdParty/Ert/lib/include/ert/util/perm_vector.hpp +++ b/ThirdParty/Ert/lib/include/ert/util/perm_vector.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2016 Statoil ASA, Norway. + Copyright (C) 2016 Equinor ASA, Norway. The file 'perm_vector.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/util/rng.hpp b/ThirdParty/Ert/lib/include/ert/util/rng.hpp index 2964296877..2576ae7143 100644 --- a/ThirdParty/Ert/lib/include/ert/util/rng.hpp +++ b/ThirdParty/Ert/lib/include/ert/util/rng.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'rng.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/util/ssize_t.hpp b/ThirdParty/Ert/lib/include/ert/util/ssize_t.hpp index 10507fa5d9..9a6c894e76 100644 --- a/ThirdParty/Ert/lib/include/ert/util/ssize_t.hpp +++ b/ThirdParty/Ert/lib/include/ert/util/ssize_t.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'ssize_t.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/util/statistics.hpp b/ThirdParty/Ert/lib/include/ert/util/statistics.hpp index 5a14bb390a..27da8dda20 100644 --- a/ThirdParty/Ert/lib/include/ert/util/statistics.hpp +++ b/ThirdParty/Ert/lib/include/ert/util/statistics.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'statistics.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/util/string_util.hpp b/ThirdParty/Ert/lib/include/ert/util/string_util.hpp index dc43464a76..e6f5d212a2 100644 --- a/ThirdParty/Ert/lib/include/ert/util/string_util.hpp +++ b/ThirdParty/Ert/lib/include/ert/util/string_util.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'string_util.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/util/stringlist.hpp b/ThirdParty/Ert/lib/include/ert/util/stringlist.hpp index 8e8176739d..0596c178ef 100644 --- a/ThirdParty/Ert/lib/include/ert/util/stringlist.hpp +++ b/ThirdParty/Ert/lib/include/ert/util/stringlist.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'stringlist.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/util/test_util.hpp b/ThirdParty/Ert/lib/include/ert/util/test_util.hpp index 0e3087681d..939fc516fd 100644 --- a/ThirdParty/Ert/lib/include/ert/util/test_util.hpp +++ b/ThirdParty/Ert/lib/include/ert/util/test_util.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Statoil ASA, Norway. + Copyright (C) 2012 Equinor ASA, Norway. The file 'test_util.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/util/test_work_area.hpp b/ThirdParty/Ert/lib/include/ert/util/test_work_area.hpp index e988012536..8faff93d22 100644 --- a/ThirdParty/Ert/lib/include/ert/util/test_work_area.hpp +++ b/ThirdParty/Ert/lib/include/ert/util/test_work_area.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'test_work_area.h' is part of ERT - Ensemble based Reservoir Tool. @@ -20,36 +20,58 @@ #ifndef ERT_TEST_WORK_AREA_H #define ERT_TEST_WORK_AREA_H +#include + +namespace ecl { +namespace util { + +class TestArea { +public: + TestArea(const std::string& test_name, bool store_area = false); + ~TestArea(); + const std::string& test_cwd() const; + const std::string& original_cwd() const; + + void copy_directory(const std::string input_directory) const; + void copy_directory_content(const std::string input_directory) const; + bool copy_parent(const std::string input_path) const; + bool copy_parent_content(const std::string original_path) const; + + void copy_file(const std::string& input_src_file) const; + std::string original_path(const std::string& input_path) const; + +private: + bool store; + std::string cwd; + std::string org_cwd; +}; + + +} +} + +typedef ecl::util::TestArea test_work_area_type; + #ifdef __cplusplus extern "C" { #endif #include -#include - - typedef struct test_work_area_struct test_work_area_type; - char * test_work_area_alloc_input_path( const test_work_area_type * work_area , const char * input_path ); test_work_area_type * test_work_area_alloc(const char * test_name ); + test_work_area_type * test_work_area_alloc__(const char * test_name, bool store_area ); test_work_area_type * test_work_area_alloc_relative(const char * prefix , const char * test_path); - void test_work_area_set_store( test_work_area_type * work_area , bool store); void test_work_area_free(test_work_area_type * work_area); const char * test_work_area_get_cwd( const test_work_area_type * work_area ); const char * test_work_area_get_original_cwd( const test_work_area_type * work_area ); - void test_work_area_install_file( test_work_area_type * work_area , const char * input_src_file ); - void test_work_area_copy_directory( test_work_area_type * work_area , const char * input_directory); - void test_work_area_copy_directory_content( test_work_area_type * work_area , const char * input_directory); - void test_work_area_copy_file( test_work_area_type * work_area , const char * input_file); - bool test_work_area_copy_parent_directory( test_work_area_type * work_area , const char * input_path); - bool test_work_area_copy_parent_content( test_work_area_type * work_area , const char * input_path); - void test_work_area_sync( test_work_area_type * work_area); - - test_work_area_type * temp_area_alloc_relative(const char * prefix , const char * test_path); - test_work_area_type * temp_area_alloc(const char * test_path); - - UTIL_IS_INSTANCE_HEADER( test_work_area ); + void test_work_area_install_file( const test_work_area_type * work_area , const char * input_src_file ); + void test_work_area_copy_directory( const test_work_area_type * work_area , const char * input_directory); + void test_work_area_copy_directory_content( const test_work_area_type * work_area , const char * input_directory); + void test_work_area_copy_file( const test_work_area_type * work_area , const char * input_file); + bool test_work_area_copy_parent_directory( const test_work_area_type * work_area , const char * input_path); + bool test_work_area_copy_parent_content( const test_work_area_type * work_area , const char * input_path); #ifdef __cplusplus } diff --git a/ThirdParty/Ert/lib/include/ert/util/thread_pool1.h b/ThirdParty/Ert/lib/include/ert/util/thread_pool1.h index be605c0ba3..b5b6111692 100644 --- a/ThirdParty/Ert/lib/include/ert/util/thread_pool1.h +++ b/ThirdParty/Ert/lib/include/ert/util/thread_pool1.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'thread_pool1.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/util/time_interval.hpp b/ThirdParty/Ert/lib/include/ert/util/time_interval.hpp index 939a2748e4..c35438a68a 100644 --- a/ThirdParty/Ert/lib/include/ert/util/time_interval.hpp +++ b/ThirdParty/Ert/lib/include/ert/util/time_interval.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2018 Statoil ASA, Norway. + Copyright (C) 2018 Equinor ASA, Norway. This is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/util/timer.hpp b/ThirdParty/Ert/lib/include/ert/util/timer.hpp index 8830222065..619c5b6164 100644 --- a/ThirdParty/Ert/lib/include/ert/util/timer.hpp +++ b/ThirdParty/Ert/lib/include/ert/util/timer.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'timer.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/util/type_vector_functions.hpp b/ThirdParty/Ert/lib/include/ert/util/type_vector_functions.hpp index f607faf163..69b7bf638b 100644 --- a/ThirdParty/Ert/lib/include/ert/util/type_vector_functions.hpp +++ b/ThirdParty/Ert/lib/include/ert/util/type_vector_functions.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'type_vector_functions.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/util/util.h b/ThirdParty/Ert/lib/include/ert/util/util.h index 5d44346560..fff69fc5ac 100644 --- a/ThirdParty/Ert/lib/include/ert/util/util.h +++ b/ThirdParty/Ert/lib/include/ert/util/util.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'util.h' is part of ERT - Ensemble based Reservoir Tool. @@ -96,16 +96,9 @@ typedef bool (walk_dir_callback_ftype) (const char * , /* The current director void *); /* Arbitrary argument */ - -typedef enum {left_pad = 0, - right_pad = 1, - center_pad = 2} string_alignement_type; - - //#define UTIL_CXX_MALLOC(var , num_elm) (typeof (var)) util_malloc( (num_elm) * sizeof var) char * util_get_timezone(void); time_t util_make_datetime_utc(int , int , int , int , int , int ); bool util_make_datetime_utc_validated(int sec, int min, int hour , int mday , int month , int year, time_t * t); - void util_fprintf_date_utc(time_t , FILE * ); time_t util_make_date_utc(int , int , int); time_t util_make_pure_date_utc(time_t t); void util_inplace_forward_seconds_utc(time_t * t , double seconds); @@ -128,9 +121,6 @@ typedef enum {left_pad = 0, char * util_alloc_sprintf_va(const char * fmt , va_list ap); char * util_alloc_sprintf(const char * , ...); char * util_realloc_sprintf(char * , const char * , ...); - void util_fprintf_int(int , int , FILE * ); - void util_fprintf_string(const char * , int , string_alignement_type , FILE * ); - void util_fprintf_double(double , int , int , char , FILE *); bool util_fscanf_date_utc(FILE * , time_t *); bool util_sscanf_date_utc(const char * , time_t *); bool util_sscanf_isodate(const char * , time_t *); @@ -237,7 +227,6 @@ typedef enum {left_pad = 0, char * util_alloc_filename(const char * , const char * , const char * ); char * util_realloc_filename(char * , const char * , const char * , const char * ); char * util_alloc_strip_copy(const char *); - void util_set_strip_copy(char * , const char *); char * util_alloc_string_sum(const char ** , int); char * util_strcat_realloc(char *, const char * ); char * util_alloc_string_copy(const char *); diff --git a/ThirdParty/Ert/lib/include/ert/util/util.hpp b/ThirdParty/Ert/lib/include/ert/util/util.hpp index 8d293d4382..e7ca212096 100644 --- a/ThirdParty/Ert/lib/include/ert/util/util.hpp +++ b/ThirdParty/Ert/lib/include/ert/util/util.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2018 Statoil ASA, Norway. + Copyright (C) 2018 Equinor ASA, Norway. This is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/util/util_endian.h b/ThirdParty/Ert/lib/include/ert/util/util_endian.h index 96f2399f4a..4a4e145fa9 100644 --- a/ThirdParty/Ert/lib/include/ert/util/util_endian.h +++ b/ThirdParty/Ert/lib/include/ert/util/util_endian.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Statoil ASA, Norway. + Copyright (C) 2012 Equinor ASA, Norway. The file 'util_endian.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/util/util_unlink.h b/ThirdParty/Ert/lib/include/ert/util/util_unlink.h index 3fc1e232c5..4d0766de6e 100644 --- a/ThirdParty/Ert/lib/include/ert/util/util_unlink.h +++ b/ThirdParty/Ert/lib/include/ert/util/util_unlink.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2017 Statoil ASA, Norway. + Copyright (C) 2017 Equinor ASA, Norway. The file 'util_unlink.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/util/vector.hpp b/ThirdParty/Ert/lib/include/ert/util/vector.hpp index ff4f526bc2..ffcf764572 100644 --- a/ThirdParty/Ert/lib/include/ert/util/vector.hpp +++ b/ThirdParty/Ert/lib/include/ert/util/vector.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'vector.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/include/ert/util/vector_util.hpp b/ThirdParty/Ert/lib/include/ert/util/vector_util.hpp new file mode 100644 index 0000000000..6ddc913466 --- /dev/null +++ b/ThirdParty/Ert/lib/include/ert/util/vector_util.hpp @@ -0,0 +1,52 @@ +/* + Copyright (C) 2018 Equinor ASA, Norway. + + The file 'vector_util.h' is part of ERT - Ensemble based Reservoir Tool. + + ERT 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. + + ERT 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 + +#include +#include + +template +int vector_util_index(const std::vector& vec, T value) { + + int index; + auto iter = find(vec.begin(), vec.end(), value); + if (iter == vec.end()) + index = -1; + else + index = iter - vec.begin(); + return index; +} + + +template +void vector_util_fprintf(const std::vector& vec , FILE * stream , const char * name , const char * fmt) { + size_t i; + if (name != NULL) + fprintf(stream , "%s = [" , name); + else + fprintf(stream , "["); + + for (i = 0; i < vec.size(); i++) { + fprintf(stream , fmt , vec[i]); + if (i < (vec.size() - 1)) + fprintf(stream , ", "); + } + + fprintf(stream , "]\n"); +} diff --git a/ThirdParty/Ert/lib/private-include/detail/ecl/ecl_grid_cache.hpp b/ThirdParty/Ert/lib/private-include/detail/ecl/ecl_grid_cache.hpp index cb96cee2e7..60543c500e 100644 --- a/ThirdParty/Ert/lib/private-include/detail/ecl/ecl_grid_cache.hpp +++ b/ThirdParty/Ert/lib/private-include/detail/ecl/ecl_grid_cache.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'ecl_grid_cache.h' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/private-include/detail/ecl/ecl_sum_file_data.hpp b/ThirdParty/Ert/lib/private-include/detail/ecl/ecl_sum_file_data.hpp index 3435cc6017..e323a307f6 100644 --- a/ThirdParty/Ert/lib/private-include/detail/ecl/ecl_sum_file_data.hpp +++ b/ThirdParty/Ert/lib/private-include/detail/ecl/ecl_sum_file_data.hpp @@ -141,7 +141,7 @@ private: void build_index(); void fwrite_report( int report_step , fortio_type * fortio) const; bool check_file( ecl_file_type * ecl_file ); - void add_ecl_file(int report_step, const ecl_file_view_type * summary_view, const ecl_smspec_type * smspec); + void add_ecl_file(int report_step, const ecl_file_view_type * summary_view); }; diff --git a/ThirdParty/Ert/lib/util/buffer.cpp b/ThirdParty/Ert/lib/util/buffer.cpp index 909b220f91..64eaf25dec 100644 --- a/ThirdParty/Ert/lib/util/buffer.cpp +++ b/ThirdParty/Ert/lib/util/buffer.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'buffer.c' is part of ERT - Ensemble based Reservoir Tool. @@ -563,12 +563,36 @@ void buffer_replace_string( buffer_type * buffer , size_t offset , size_t old_si touching internal state. */ +namespace { + + /* + This homemade strstr() implementation is used here because we can not + guarantee that the buffer->data is '\0' terminated and then normal strstr() + gives undefined behaviour - problem found with address sanitizer. + */ + + const char * memcmp_strstr(const char * buffer, size_t buffer_size, const char * expr) { + size_t N = strlen(expr); + const char * pos = buffer; + while (true) { + if (buffer_size < N) + return NULL; + + if (memcmp(pos, expr, N) == 0) + return pos; + + pos++; + buffer_size--; + } + } +} + bool buffer_strstr( buffer_type * buffer , const char * expr ) { bool match = false; if (strlen(expr) > 0) { - char * match_ptr = strstr( &buffer->data[buffer->pos] , expr ); + const char * match_ptr = memcmp_strstr( &buffer->data[buffer->pos], buffer->content_size - buffer->pos, expr ); if (match_ptr) { buffer->pos += match_ptr - &buffer->data[buffer->pos]; match = true; diff --git a/ThirdParty/Ert/lib/util/cxx_string_util.cpp b/ThirdParty/Ert/lib/util/cxx_string_util.cpp index 5927039620..b49197b540 100644 --- a/ThirdParty/Ert/lib/util/cxx_string_util.cpp +++ b/ThirdParty/Ert/lib/util/cxx_string_util.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2018 Equinor Statoil ASA, Norway. + Copyright (C) 2018 Equinor Equinor ASA, Norway. The file 'cxx_string_util.cpp' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/util/hash.cpp b/ThirdParty/Ert/lib/util/hash.cpp index a085abe6b9..214664a444 100644 --- a/ThirdParty/Ert/lib/util/hash.cpp +++ b/ThirdParty/Ert/lib/util/hash.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'hash.c' is part of ERT - Ensemble based Reservoir Tool. @@ -82,11 +82,6 @@ static void * __hash_get_node(const hash_type *__hash , const char *key, bool ab hash_type * hash = (hash_type *) __hash; /* The net effect is no change - but .... ?? */ hash_node_type * node = NULL; { - if (key == NULL) - { - return NULL; - } - const uint32_t global_index = hash->hashf(key , strlen(key)); const uint32_t table_index = (global_index % hash->size); diff --git a/ThirdParty/Ert/lib/util/hash_node.cpp b/ThirdParty/Ert/lib/util/hash_node.cpp index 1a983e0ba7..66e099879e 100644 --- a/ThirdParty/Ert/lib/util/hash_node.cpp +++ b/ThirdParty/Ert/lib/util/hash_node.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'hash_node.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/util/hash_sll.cpp b/ThirdParty/Ert/lib/util/hash_sll.cpp index 6f3ec0f623..080462cfaf 100644 --- a/ThirdParty/Ert/lib/util/hash_sll.cpp +++ b/ThirdParty/Ert/lib/util/hash_sll.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'hash_sll.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/util/lookup_table.cpp b/ThirdParty/Ert/lib/util/lookup_table.cpp index 616a54eac6..2f453a8d19 100644 --- a/ThirdParty/Ert/lib/util/lookup_table.cpp +++ b/ThirdParty/Ert/lib/util/lookup_table.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'lookup_table.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/util/mzran.cpp b/ThirdParty/Ert/lib/util/mzran.cpp index fd1bc353b5..a042988ff9 100644 --- a/ThirdParty/Ert/lib/util/mzran.cpp +++ b/ThirdParty/Ert/lib/util/mzran.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'mzran.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/util/node_ctype.cpp b/ThirdParty/Ert/lib/util/node_ctype.cpp index b50ce095fd..8db8504f1f 100644 --- a/ThirdParty/Ert/lib/util/node_ctype.cpp +++ b/ThirdParty/Ert/lib/util/node_ctype.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'node_ctype.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/util/node_data.cpp b/ThirdParty/Ert/lib/util/node_data.cpp index ae7d2a3653..728cbf8566 100644 --- a/ThirdParty/Ert/lib/util/node_data.cpp +++ b/ThirdParty/Ert/lib/util/node_data.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'node_data.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/util/parser.cpp b/ThirdParty/Ert/lib/util/parser.cpp index 48b963575e..8b187214d1 100644 --- a/ThirdParty/Ert/lib/util/parser.cpp +++ b/ThirdParty/Ert/lib/util/parser.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'parser.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/util/path.cpp b/ThirdParty/Ert/lib/util/path.cpp index 30d206e9e3..d0cb5418a8 100644 --- a/ThirdParty/Ert/lib/util/path.cpp +++ b/ThirdParty/Ert/lib/util/path.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Statoil ASA, Norway. + Copyright (C) 2012 Equinor ASA, Norway. The file 'path_stack.c' is part of ERT - Ensemble based Reservoir Tool. @@ -15,6 +15,7 @@ See the GNU General Public License at for more details. */ +#include #include @@ -55,10 +56,16 @@ namespace ecl { { const char * c_str = fname.c_str(); + const char * return_raw; if (end_pos == std::string::npos || end_pos < offset) - return util_alloc_string_copy( &c_str[offset] ); + return_raw = util_alloc_string_copy( &c_str[offset] ); + else + return_raw = util_alloc_substring_copy(c_str, offset, end_pos - offset); + std::string return_value = return_raw; + free( (void*)return_raw ); + return return_value; + - return util_alloc_substring_copy(c_str, offset, end_pos - offset); } } @@ -71,7 +78,11 @@ namespace ecl { if (last_slash == std::string::npos || end_pos > last_slash) { const char * c_str = fname.c_str(); - return util_alloc_substring_copy( c_str, end_pos + 1, fname.size() - end_pos - 1); + + const char * return_raw = util_alloc_substring_copy( c_str, end_pos + 1, fname.size() - end_pos - 1); + std::string return_value = return_raw; + free( (void*)return_raw ); + return return_value; } return ""; diff --git a/ThirdParty/Ert/lib/util/path_stack.cpp b/ThirdParty/Ert/lib/util/path_stack.cpp index 9ae4ff9433..fd6f03565f 100644 --- a/ThirdParty/Ert/lib/util/path_stack.cpp +++ b/ThirdParty/Ert/lib/util/path_stack.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Statoil ASA, Norway. + Copyright (C) 2012 Equinor ASA, Norway. The file 'path_stack.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/util/perm_vector.cpp b/ThirdParty/Ert/lib/util/perm_vector.cpp index 459eced207..03e52ed6fc 100644 --- a/ThirdParty/Ert/lib/util/perm_vector.cpp +++ b/ThirdParty/Ert/lib/util/perm_vector.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2016 Statoil ASA, Norway. + Copyright (C) 2016 Equinor ASA, Norway. The file 'perm_vector.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/util/rng.cpp b/ThirdParty/Ert/lib/util/rng.cpp index f0daadcb2f..b5822d76ab 100644 --- a/ThirdParty/Ert/lib/util/rng.cpp +++ b/ThirdParty/Ert/lib/util/rng.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'rng.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/util/statistics.cpp b/ThirdParty/Ert/lib/util/statistics.cpp index 9aa170b849..7dfec8be3b 100644 --- a/ThirdParty/Ert/lib/util/statistics.cpp +++ b/ThirdParty/Ert/lib/util/statistics.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'statistics.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/util/string_util.cpp b/ThirdParty/Ert/lib/util/string_util.cpp index 37f258fea7..41f2b3f353 100644 --- a/ThirdParty/Ert/lib/util/string_util.cpp +++ b/ThirdParty/Ert/lib/util/string_util.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'string_util.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/util/stringlist.cpp b/ThirdParty/Ert/lib/util/stringlist.cpp index 237deabc03..879d1fa5d9 100644 --- a/ThirdParty/Ert/lib/util/stringlist.cpp +++ b/ThirdParty/Ert/lib/util/stringlist.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'stringlist.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/util/test_util.cpp b/ThirdParty/Ert/lib/util/test_util.cpp index 0e4349f7e0..e52612b558 100644 --- a/ThirdParty/Ert/lib/util/test_util.cpp +++ b/ThirdParty/Ert/lib/util/test_util.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Statoil ASA, Norway. + Copyright (C) 2012 Equinor ASA, Norway. The file 'test_util.c' is part of ERT - Ensemble based Reservoir Tool. @@ -37,6 +37,7 @@ void test_error_exit( const char * fmt , ...) { s = util_alloc_sprintf_va(fmt , ap); va_end(ap); fprintf(stderr, "%s", s); + free(s); exit(1); } diff --git a/ThirdParty/Ert/lib/util/test_work_area.cpp b/ThirdParty/Ert/lib/util/test_work_area.cpp index 32a6267b4c..df7643ef2f 100644 --- a/ThirdParty/Ert/lib/util/test_work_area.cpp +++ b/ThirdParty/Ert/lib/util/test_work_area.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'test_work_area.c' is part of ERT - Ensemble based Reservoir Tool. @@ -25,19 +25,16 @@ #include #endif +#include + #include #include #include #include #include -#include -#include -#ifdef ERT_HAVE_OPENDIR -#include -#include -#endif +#include "detail/util/path.hpp" /* This file implements a small work area implementation to be used for @@ -96,82 +93,65 @@ #define TEST_WORK_AREA_TYPE_ID 1107355 -struct test_work_area_struct { - UTIL_TYPE_ID_DECLARATION; - bool store; - char * cwd; - char * original_cwd; - bool change_dir; +static char * test_work_area_alloc_prefix( ) { +#ifdef HAVE_WINDOWS_GET_TEMP_PATH - /* - There have been issues where a test like this: + char tmp_path[MAX_PATH]; + GetTempPath( MAX_PATH , tmp_path ); + return util_alloc_string_copy( tmp_path ); - 1. Create new file in test area. - 2. Open file for reading. - - Fail randomly at step 2 with "File not found", although the file - is clearly there when checking afterwards. Inspired by this - article: https:/lwn.net/Articles/457667/ we try to call fsync() on - the directory file descriptor. - */ -#ifdef ERT_HAVE_OPENDIR - DIR * dir_stream; -#endif - int dir_fd; -}; - - - - -static test_work_area_type * test_work_area_alloc__(const char * prefix , const char * test_path, bool change_dir) { - test_work_area_type * work_area = NULL; - - if (util_is_directory( prefix )) { - char * test_cwd = util_alloc_sprintf(FULL_PATH_FMT , prefix , test_path ); - util_make_path( test_cwd ); - if (true) { - work_area = (test_work_area_type*)util_malloc( sizeof * work_area ); - - UTIL_TYPE_ID_INIT( work_area , TEST_WORK_AREA_TYPE_ID ); - work_area->original_cwd = util_alloc_cwd(); - work_area->cwd = test_cwd; - work_area->change_dir = change_dir; - if (change_dir ) - if(util_chdir( work_area->cwd ) != 0) - util_abort("%s: Failed to move into temporary directory: %s", __func__, test_cwd); - - test_work_area_set_store( work_area , DEFAULT_STORE); - -#ifdef ERT_HAVE_OPENDIR - work_area->dir_stream = opendir( work_area->cwd ); - if (work_area->dir_stream) - work_area->dir_fd = dirfd( work_area->dir_stream ); - else - work_area->dir_fd = -1; #else - work_area->dir_fd = -1 + + const char * prefix_path = getenv("TMPDIR"); + +#ifdef P_tmpdir + if (!prefix_path) + prefix_path = P_tmpdir; #endif - } else - free( test_cwd ); + + if (!prefix_path) + prefix_path = _PATH_TMP; + + return util_alloc_realpath(prefix_path); + +#endif +} + + + +namespace ecl { +namespace util { + +static bool test_work_area_copy_parent__( const TestArea * work_area , const std::string& input_path, bool copy_content) { + char * full_path; + + if (util_is_abs_path( input_path.c_str() )) + full_path = util_alloc_string_copy( input_path.c_str() ); + else + full_path = util_alloc_filename( work_area->original_cwd().c_str( ) , input_path.c_str() , NULL); + + if (util_entry_exists( full_path)) { + char * parent_path = util_alloc_parent_path( full_path ); + + if (copy_content) + work_area->copy_directory_content(std::string(parent_path)); + else + work_area->copy_directory(std::string(parent_path)); + + free( full_path ); + free( parent_path ); + return true; + } else { + free( full_path ); + return false; } - return work_area; } -test_work_area_type * test_work_area_alloc_relative(const char * prefix , const char * test_path) { - return test_work_area_alloc__(prefix , test_path , true ); -} - - -test_work_area_type * temp_area_alloc_relative(const char * prefix , const char * test_path) { - return test_work_area_alloc__(prefix , test_path , false ); -} - - -UTIL_IS_INSTANCE_FUNCTION( test_work_area , TEST_WORK_AREA_TYPE_ID) - -static test_work_area_type * test_work_area_alloc_with_prefix(const char * prefix , const char * test_name, bool change_dir) { - if (test_name) { +TestArea::TestArea(const std::string& test_name, bool store_area) : + store(store_area) +{ + char * prefix = test_work_area_alloc_prefix(); unsigned int random_int; util_fread_dev_urandom( sizeof random_int, (char *) &random_int); random_int = random_int % 100000000; @@ -183,216 +163,177 @@ static test_work_area_type * test_work_area_alloc_with_prefix(const char * prefi #else char * user_name = util_alloc_sprintf("ert-test-%08u" , random_int); #endif - char * test_path = util_alloc_sprintf( TEST_PATH_FMT , user_name , test_name , random_int); - test_work_area_type * work_area = test_work_area_alloc__( prefix , test_path, change_dir); + + char * test_path = util_alloc_sprintf( TEST_PATH_FMT , user_name , test_name.c_str() , random_int); + char * test_cwd = util_alloc_sprintf(FULL_PATH_FMT , prefix , test_path ); + util_make_path( test_cwd ); + + { + char * cwd_tmp = util_alloc_cwd(); + this->org_cwd = cwd_tmp; + free(cwd_tmp); + } + this->cwd = test_cwd; + if (util_chdir( this->cwd.c_str() ) != 0) + util_abort("%s: Failed to move into temporary directory: %s", __func__, this->cwd.c_str()); + free( test_path ); free( user_name ); - return work_area; - } else + free( test_cwd ); + free( prefix ); +} + +TestArea::~TestArea() { + if (!this->store) + util_clear_directory( this->cwd.c_str() , true , true ); + + util_chdir( this->org_cwd.c_str() ); +} + +const std::string& TestArea::test_cwd() const { + return this->cwd; +} + +const std::string& TestArea::original_cwd() const { + return this->org_cwd; +} + +std::string TestArea::original_path(const std::string& input_path) const { + if (util_is_abs_path( input_path.c_str() )) + return std::string(input_path); + else { + char * fname = util_alloc_filename( this->original_cwd().c_str(), input_path.c_str() , NULL); + + std::string return_string = std::string(fname); + free(fname); + + return return_string; + } +} + + +void TestArea::copy_file(const std::string& input_src_file) const { + std::string src_file = this->original_path(input_src_file); + + if (util_file_exists( src_file.c_str() )) { + char * target_name = util_split_alloc_filename( input_src_file.c_str() ); + char * target_file = util_alloc_filename( this->test_cwd().c_str() , target_name , NULL ); + util_copy_file( src_file.c_str(), target_file ); + free( target_file ); + free( target_name ); + } +} + +void TestArea::copy_directory(const std::string input_directory) const { + std::string src_directory = this->original_path(input_directory); + util_copy_directory(src_directory.c_str() , this->test_cwd().c_str() ); +} + +void TestArea::copy_directory_content(const std::string input_directory) const { + std::string src_directory = this->original_path(input_directory); + util_copy_directory_content(src_directory.c_str() , this->test_cwd().c_str() ); +} + +bool TestArea::copy_parent(const std::string input_path) const { + return test_work_area_copy_parent__(this, input_path, false); +} + +bool TestArea::copy_parent_content(const std::string input_path) const { + return test_work_area_copy_parent__(this, input_path, true); +} + +} +} + +/*****************************************************************/ +/* C API */ + +test_work_area_type * test_work_area_alloc__(const char * test_name, bool store_area) { + if (test_name) + return new ecl::util::TestArea(test_name, store_area); + else return NULL; } -static char * test_work_area_alloc_prefix( ) { -#ifdef HAVE_WINDOWS_GET_TEMP_PATH - - char tmp_path[MAX_PATH]; - GetTempPath( MAX_PATH , tmp_path ); - return util_alloc_string_copy( tmp_path ); - -#else - - const char * prefix_path = getenv("TMPDIR"); - - #ifdef P_tmpdir - if (!prefix_path) - prefix_path = P_tmpdir; - #endif - - if (!prefix_path) - prefix_path = _PATH_TMP; - - return util_alloc_realpath(prefix_path); - -#endif -} - - test_work_area_type * test_work_area_alloc(const char * test_name) { - test_work_area_type * work_area; - { - char * tmp_prefix = test_work_area_alloc_prefix( ); - work_area = test_work_area_alloc_with_prefix( tmp_prefix , test_name , true); - free( tmp_prefix ); - } - return work_area; + return test_work_area_alloc__(test_name, false); } -test_work_area_type * temp_area_alloc(const char * path) { - test_work_area_type * work_area; - { - char * tmp_prefix = test_work_area_alloc_prefix( ); - work_area = test_work_area_alloc_with_prefix( tmp_prefix , path , false ); - free( tmp_prefix ); - } - return work_area; -} - - - -void test_work_area_set_store( test_work_area_type * work_area , bool store) { - work_area->store = store; -} - - -void test_work_area_sync( test_work_area_type * work_area) { -#ifdef ERT_HAVE_OPENDIR - if (work_area->dir_fd >= 0) - fsync( work_area->dir_fd ); -#endif -} void test_work_area_free(test_work_area_type * work_area) { - if (!work_area->store) - util_clear_directory( work_area->cwd , true , true ); - - if (work_area->change_dir) - util_chdir( work_area->original_cwd ); - -#ifdef ERT_HAVE_OPENDIR - if (work_area->dir_stream) - closedir( work_area->dir_stream ); -#endif - - free( work_area->original_cwd ); - free( work_area->cwd ); - free( work_area ); + delete work_area; } const char * test_work_area_get_cwd( const test_work_area_type * work_area ) { - return work_area->cwd; + return work_area->test_cwd().c_str(); } const char * test_work_area_get_original_cwd( const test_work_area_type * work_area ) { - return work_area->original_cwd; + return work_area->original_cwd().c_str(); } + char * test_work_area_alloc_input_path( const test_work_area_type * work_area , const char * input_path ) { - if (util_is_abs_path( input_path )) - return util_alloc_string_copy( input_path ); - else { - if (work_area->change_dir) - return util_alloc_filename( work_area->original_cwd , input_path , NULL); - else - return util_alloc_string_copy( input_path ); - } + std::string relocated_input_path = work_area->original_path(std::string(input_path)); + return util_alloc_string_copy(relocated_input_path.c_str()); } + + /** The point of this function is that the test code should be able to access the file @input_file independent of the fact that it has changed path. If @input_file is an absolute path the function will - do nothing, if @input_file is a realtive path the function will + do nothing, if @input_file is a relative path the function will copy @input_file from the location relative to the original cwd to the corresponding location relative to the test cwd. */ - -void test_work_area_install_file( test_work_area_type * work_area , const char * input_src_file ) { - if (util_is_abs_path( input_src_file )) +void test_work_area_install_file( const test_work_area_type * work_area , const char * input_src_file ) { + if (util_is_abs_path( input_src_file)) return; else { - char * src_file = test_work_area_alloc_input_path( work_area , input_src_file ); - char * src_path = NULL; + std::string src_file = work_area->original_path(input_src_file); + std::string src_path = ecl::util::path::dirname(input_src_file); - util_alloc_file_components( input_src_file , &src_path , NULL , NULL); - if (!util_entry_exists( src_path )) - util_make_path( src_path ); + if (!util_entry_exists( src_path.c_str() )) + util_make_path( src_path.c_str() ); - if (util_file_exists( src_file )) { - char * target_file = util_alloc_filename( work_area->cwd , input_src_file , NULL ); - util_copy_file( src_file , target_file ); + if (util_file_exists( src_file.c_str() )) { + char * target_file = util_alloc_filename( work_area->test_cwd().c_str(), input_src_file, NULL ); + util_copy_file( src_file.c_str() , target_file ); free( target_file ); } - free( src_file ); - free( src_path ); } } -void test_work_area_copy_directory( test_work_area_type * work_area , const char * input_directory) { - char * src_directory = test_work_area_alloc_input_path( work_area , input_directory ); - util_copy_directory(src_directory , work_area->cwd ); - free( src_directory ); - test_work_area_sync( work_area ); +void test_work_area_copy_file( const test_work_area_type * work_area , const char * input_file) { + if (input_file) + work_area->copy_file(std::string(input_file)); } -void test_work_area_copy_directory_content( test_work_area_type * work_area , const char * input_directory) { - char * src_directory = test_work_area_alloc_input_path( work_area , input_directory ); - util_copy_directory_content(src_directory , work_area->cwd ); - free( src_directory ); - test_work_area_sync( work_area ); +void test_work_area_copy_directory( const test_work_area_type * work_area , const char * input_directory) { + work_area->copy_directory(std::string(input_directory)); } - -void test_work_area_copy_file( test_work_area_type * work_area , const char * input_file) { - if (input_file) { - char * src_file = test_work_area_alloc_input_path( work_area , input_file ); - - if (util_file_exists( src_file )) { - char * target_name = util_split_alloc_filename( input_file ); - char * target_file = util_alloc_filename( work_area->cwd , target_name , NULL ); - util_copy_file( src_file , target_file ); - free( target_file ); - free( target_name ); - } - free( src_file ); - test_work_area_sync( work_area ); - } +void test_work_area_copy_directory_content( const test_work_area_type * work_area , const char * input_directory) { + work_area->copy_directory_content(std::string(input_directory)); } - -static bool test_work_area_copy_parent__( test_work_area_type * work_area , const char * input_path, bool copy_content) { - char * full_path; - - if (util_is_abs_path( input_path )) - full_path = util_alloc_string_copy( input_path ); - else - full_path = util_alloc_filename( work_area->original_cwd , input_path , NULL); - - if (util_entry_exists( full_path)) { - char * parent_path = NULL; - - parent_path = util_alloc_parent_path( full_path ); - - if (copy_content) - test_work_area_copy_directory_content( work_area , parent_path ); - else - test_work_area_copy_directory( work_area , parent_path ); - - free( full_path ); - free( parent_path ); - test_work_area_sync( work_area ); - return true; - } else { - free( full_path ); - return false; - } +bool test_work_area_copy_parent_directory( const test_work_area_type * work_area , const char * input_path) { + return work_area->copy_parent(std::string(input_path)); } -bool test_work_area_copy_parent_directory( test_work_area_type * work_area , const char * input_path) { - return test_work_area_copy_parent__( work_area , input_path , false ); -} - - -bool test_work_area_copy_parent_content( test_work_area_type * work_area , const char * input_path) { - return test_work_area_copy_parent__( work_area , input_path , true ); +bool test_work_area_copy_parent_content( const test_work_area_type * work_area , const char * input_path) { + return work_area->copy_parent_content(std::string(input_path)); } diff --git a/ThirdParty/Ert/lib/util/tests/ert_util_addr2line.cpp b/ThirdParty/Ert/lib/util/tests/ert_util_addr2line.cpp index 06d76bfc28..07cb596216 100644 --- a/ThirdParty/Ert/lib/util/tests/ert_util_addr2line.cpp +++ b/ThirdParty/Ert/lib/util/tests/ert_util_addr2line.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Statoil ASA, Norway. + Copyright (C) 2012 Equinor ASA, Norway. The file 'ert_util_addr2line.c' is part of ERT - Ensemble based Reservoir Tool. @@ -28,7 +28,6 @@ void test_lookup(bool valid_address, bool change_cwd) { const char * file = __FILE__; - const char * func = __func__; int line; const int max_bt = 50; void *bt_addr[max_bt]; @@ -45,7 +44,6 @@ void test_lookup(bool valid_address, bool change_cwd) { util_chdir("/tmp"); if (valid_address) { test_assert_false( util_addr2line_lookup( bt_addr[0] , &func_name , &file_name , &line_nr)); - test_assert_string_equal( func_name , func ); test_assert_string_equal( file_name , NULL ); test_assert_int_equal( 0 , line_nr); } else { @@ -59,7 +57,6 @@ void test_lookup(bool valid_address, bool change_cwd) { } else { if (valid_address) { test_assert_true( util_addr2line_lookup( bt_addr[0] , &func_name , &file_name , &line_nr)); - test_assert_string_equal( func_name , func ); test_assert_string_equal( file_name , file ); test_assert_int_equal( line , line_nr ); } else { @@ -90,6 +87,7 @@ int main( int argc , char ** argv) { util_chdir(path); dot_name = util_alloc_sprintf("./%s" , name); util_spawn_blocking(dot_name, 0, NULL, NULL, NULL); + free(dot_name); exit(0); } else { printf("Testing internal lookup ....\n"); diff --git a/ThirdParty/Ert/lib/util/tests/ert_util_alloc_file_components.cpp b/ThirdParty/Ert/lib/util/tests/ert_util_alloc_file_components.cpp index cfdf63fda2..c8a80b4d30 100644 --- a/ThirdParty/Ert/lib/util/tests/ert_util_alloc_file_components.cpp +++ b/ThirdParty/Ert/lib/util/tests/ert_util_alloc_file_components.cpp @@ -8,36 +8,33 @@ #include -bool checkPath(const char * path, const char * directory, const char * base_name, const char * extension) { +void checkPath(const char * path, const char * directory, const char * base_name, const char * extension) { char * dir; char * base; char * ext; util_alloc_file_components(path, &dir, &base, &ext); - bool success = true; - - success = success && (util_string_equal(dir, directory) || dir == directory); - success = success && (util_string_equal(base, base_name) || base == base_name); - success = success && (util_string_equal(ext, extension) || ext == extension); + test_assert_string_equal(dir, directory); + test_assert_string_equal(base, base_name); + test_assert_string_equal(ext, extension); free(dir); free(base); free(ext); - return success; } int main(int argc , char ** argv) { - test_assert_true(checkPath("/dir/filename.ext", "/dir", "filename", "ext")); - test_assert_true(checkPath("/dir/subdir/filename.ext", "/dir/subdir", "filename", "ext")); - test_assert_true(checkPath("/dir/subdir/filename.name.ext", "/dir/subdir", "filename.name", "ext")); - test_assert_true(checkPath("/dir/subdir/filename", "/dir/subdir", "filename", NULL)); - test_assert_true(checkPath("filename.ext", NULL, "filename", "ext")); - test_assert_true(checkPath("filename", NULL, "filename", NULL)); - test_assert_true(checkPath(".filename", NULL, ".filename", NULL)); - test_assert_true(checkPath(".filename.ext", NULL, ".filename", "ext")); - - exit(0); + checkPath("/dir/filename.ext", "/dir", "filename", "ext"); + checkPath("/dir/subdir/filename.ext", "/dir/subdir", "filename", "ext"); + checkPath("/dir/subdir/filename.name.ext", "/dir/subdir", "filename.name", "ext"); + checkPath("/dir/subdir/filename", "/dir/subdir", "filename", NULL); + checkPath("filename.ext", NULL, "filename", "ext"); + checkPath("filename", NULL, "filename", NULL); + checkPath(".filename", NULL, ".filename", NULL); + checkPath(".filename.ext", NULL, ".filename", "ext"); + checkPath("./SPECASE1", ".", "SPECASE1", NULL); + checkPath("/absolute/path/to/CASE", "/absolute/path/to", "CASE", NULL); } diff --git a/ThirdParty/Ert/lib/util/tests/ert_util_approx_equal.cpp b/ThirdParty/Ert/lib/util/tests/ert_util_approx_equal.cpp index d9b9f45acf..19f2212795 100644 --- a/ThirdParty/Ert/lib/util/tests/ert_util_approx_equal.cpp +++ b/ThirdParty/Ert/lib/util/tests/ert_util_approx_equal.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Statoil ASA, Norway. + Copyright (C) 2012 Equinor ASA, Norway. The file 'ert_util_approx_equal.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/util/tests/ert_util_before_after.cpp b/ThirdParty/Ert/lib/util/tests/ert_util_before_after.cpp index d5982d27bd..a3e9753f53 100644 --- a/ThirdParty/Ert/lib/util/tests/ert_util_before_after.cpp +++ b/ThirdParty/Ert/lib/util/tests/ert_util_before_after.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Statoil ASA, Norway. + Copyright (C) 2012 Equinor ASA, Norway. The file 'ert_util_before_after.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/util/tests/ert_util_binary_split.cpp b/ThirdParty/Ert/lib/util/tests/ert_util_binary_split.cpp index 4c3ee41585..4a1e49ad2c 100644 --- a/ThirdParty/Ert/lib/util/tests/ert_util_binary_split.cpp +++ b/ThirdParty/Ert/lib/util/tests/ert_util_binary_split.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'ert_util_binary_split.c' is part of ERT - Ensemble based Reservoir Tool. @@ -25,18 +25,22 @@ void test_split(const char * test_string , bool split_on_first , const char * tr char * part1; char * part2; - util_binary_split_string( test_string , ":" , split_on_first , &part1 , &part2 ); test_assert_string_equal( true1 , part1 ); test_assert_string_equal( true2 , part2 ); + free(part1); + free(part2); util_binary_split_string( test_string , ":;" , split_on_first , &part1 , &part2 ); test_assert_string_equal( true1 , part1 ); test_assert_string_equal( true2 , part2 ); + free(part1); + free(part2); util_binary_split_string( test_string , ";" , split_on_first , &part1 , &part2 ); test_assert_string_equal( test_string , part1 ); test_assert_string_equal( NULL , part2 ); + free(part1); } int main(int argc , char ** argv) { diff --git a/ThirdParty/Ert/lib/util/tests/ert_util_buffer.cpp b/ThirdParty/Ert/lib/util/tests/ert_util_buffer.cpp index a42768df2f..b510933274 100644 --- a/ThirdParty/Ert/lib/util/tests/ert_util_buffer.cpp +++ b/ThirdParty/Ert/lib/util/tests/ert_util_buffer.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2015 Statoil ASA, Norway. + Copyright (C) 2015 Equinor ASA, Norway. The file 'ert_util_buffer.c' is part of ERT - Ensemble based Reservoir Tool. @@ -68,6 +68,7 @@ void test_buffer_strstr() { test_assert_true( buffer_strstr( buffer , "ABC" )); test_assert_true( buffer_strstr( buffer , "BC" )); test_assert_false( buffer_strstr( buffer , "ABC" )); + buffer_free(buffer); } diff --git a/ThirdParty/Ert/lib/util/tests/ert_util_chdir.cpp b/ThirdParty/Ert/lib/util/tests/ert_util_chdir.cpp index bd84459deb..f465ac7031 100644 --- a/ThirdParty/Ert/lib/util/tests/ert_util_chdir.cpp +++ b/ThirdParty/Ert/lib/util/tests/ert_util_chdir.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2017 Statoil ASA, Norway. + Copyright (C) 2017 Equinor ASA, Norway. The file 'ert_util_chdir.c' is part of ERT - Ensemble based Reservoir Tool. @@ -24,8 +24,8 @@ void test_chdir() { - test_work_area_type * work_area = test_work_area_alloc("test-area"); - const char * cwd = test_work_area_get_cwd( work_area ); + ecl::util::TestArea ta("chdir"); + const char * cwd = ta.test_cwd().c_str(); test_assert_false( util_chdir_file( "/file/does/not/exist")); test_assert_false( util_chdir_file( cwd )); @@ -34,8 +34,13 @@ void test_chdir() { fclose( stream ); } test_assert_true( util_chdir_file( "path/FILE" )); - test_assert_string_equal( util_alloc_cwd() , util_alloc_filename( cwd, "path", NULL)); - test_work_area_free( work_area ); + { + char * new_cwd = util_alloc_cwd(); + char * fname = util_alloc_filename(cwd, "path", NULL); + test_assert_string_equal( new_cwd, fname ); + free(new_cwd); + free(fname); + } } diff --git a/ThirdParty/Ert/lib/util/tests/ert_util_clamp.cpp b/ThirdParty/Ert/lib/util/tests/ert_util_clamp.cpp index e56640ada0..65932ab25c 100644 --- a/ThirdParty/Ert/lib/util/tests/ert_util_clamp.cpp +++ b/ThirdParty/Ert/lib/util/tests/ert_util_clamp.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Statoil ASA, Norway. + Copyright (C) 2012 Equinor ASA, Norway. The file 'ert_util_clamp.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/util/tests/ert_util_copy_file.cpp b/ThirdParty/Ert/lib/util/tests/ert_util_copy_file.cpp index 6ccb4f99ed..1fd0012cff 100644 --- a/ThirdParty/Ert/lib/util/tests/ert_util_copy_file.cpp +++ b/ThirdParty/Ert/lib/util/tests/ert_util_copy_file.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2014 Statoil ASA, Norway. + Copyright (C) 2014 Equinor ASA, Norway. The file 'enkf_util_copy_file.c' is part of ERT - Ensemble based Reservoir Tool. @@ -36,7 +36,7 @@ void test_copy_file( const char * executable ) { mode0 = stat_buf.st_mode; { - test_work_area_type * test_area = test_work_area_alloc( "executable-copy" ); + ecl::util::TestArea ta("copy_file"); util_copy_file( executable , "test.x"); test_assert_true( util_file_exists( "test.x" )); @@ -44,7 +44,6 @@ void test_copy_file( const char * executable ) { mode1 = stat_buf.st_mode; test_assert_true( mode0 == mode1 ); - test_work_area_free( test_area ); } } diff --git a/ThirdParty/Ert/lib/util/tests/ert_util_cwd_test.cpp b/ThirdParty/Ert/lib/util/tests/ert_util_cwd_test.cpp index 0b59b4fa69..e04523deb8 100644 --- a/ThirdParty/Ert/lib/util/tests/ert_util_cwd_test.cpp +++ b/ThirdParty/Ert/lib/util/tests/ert_util_cwd_test.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Statoil ASA, Norway. + Copyright (C) 2012 Equinor ASA, Norway. The file 'ert_util_cwd_test.c' is part of ERT - Ensemble based Reservoir Tool. @@ -24,10 +24,11 @@ int main(int argc , char ** argv) { char * cwd = argv[1]; - printf("cwd :%s\n",util_alloc_cwd()); + char * cwd_alloc = util_alloc_cwd(); + printf("cwd :%s\n",cwd_alloc); printf("argv[1]:%s\n",argv[1]); - if (!util_is_cwd(cwd)) + if (!util_is_cwd(cwd_alloc)) test_error_exit("Hmmm did not recognize:%s as cwd\n",cwd); if (util_is_cwd("/some/path")) diff --git a/ThirdParty/Ert/lib/util/tests/ert_util_datetime.cpp b/ThirdParty/Ert/lib/util/tests/ert_util_datetime.cpp index 2564784ee0..3673653497 100644 --- a/ThirdParty/Ert/lib/util/tests/ert_util_datetime.cpp +++ b/ThirdParty/Ert/lib/util/tests/ert_util_datetime.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2017 Statoil ASA, Norway. + Copyright (C) 2017 Equinor ASA, Norway. This file is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/util/tests/ert_util_file_readable.cpp b/ThirdParty/Ert/lib/util/tests/ert_util_file_readable.cpp index 25e29b5a42..13bf0f5c1f 100644 --- a/ThirdParty/Ert/lib/util/tests/ert_util_file_readable.cpp +++ b/ThirdParty/Ert/lib/util/tests/ert_util_file_readable.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'ert_util_file_readable.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/util/tests/ert_util_filename.cpp b/ThirdParty/Ert/lib/util/tests/ert_util_filename.cpp index d42150605e..a88c8f5027 100644 --- a/ThirdParty/Ert/lib/util/tests/ert_util_filename.cpp +++ b/ThirdParty/Ert/lib/util/tests/ert_util_filename.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Statoil ASA, Norway. + Copyright (C) 2012 Equinor ASA, Norway. The file 'ert_util_PATH_test.c' is part of ERT - Ensemble based Reservoir Tool. @@ -21,6 +21,7 @@ #include #include +#include #include #include diff --git a/ThirdParty/Ert/lib/util/tests/ert_util_hash_test.cpp b/ThirdParty/Ert/lib/util/tests/ert_util_hash_test.cpp index d157750e23..c75b8ee219 100644 --- a/ThirdParty/Ert/lib/util/tests/ert_util_hash_test.cpp +++ b/ThirdParty/Ert/lib/util/tests/ert_util_hash_test.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Statoil ASA, Norway. + Copyright (C) 2012 Equinor ASA, Norway. The file 'ert_util_hash_test.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/util/tests/ert_util_mkdir_p.cpp b/ThirdParty/Ert/lib/util/tests/ert_util_mkdir_p.cpp index 30a2ea8d39..a87a6b86f1 100644 --- a/ThirdParty/Ert/lib/util/tests/ert_util_mkdir_p.cpp +++ b/ThirdParty/Ert/lib/util/tests/ert_util_mkdir_p.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2018 Statoil ASA, Norway. + Copyright (C) 2018 Equinor ASA, Norway. The file 'ert_util_mkdir_p.c' is part of ERT - Ensemble based Reservoir Tool. @@ -24,7 +24,7 @@ int main(int argc , char ** argv) { - test_work_area_type * work_area = test_work_area_alloc("Test_area"); + ecl::util::TestArea ta("mkdir"); // Regular use test_assert_true( util_mkdir_p("some/path/with/many/levels")); @@ -45,6 +45,5 @@ int main(int argc , char ** argv) { chmod("read_only", 0555); test_assert_false(util_mkdir_p("read_only/no/not/this")); - test_work_area_free(work_area); exit(0); } diff --git a/ThirdParty/Ert/lib/util/tests/ert_util_normal_path.cpp b/ThirdParty/Ert/lib/util/tests/ert_util_normal_path.cpp index ff1f117020..8b46860ba6 100644 --- a/ThirdParty/Ert/lib/util/tests/ert_util_normal_path.cpp +++ b/ThirdParty/Ert/lib/util/tests/ert_util_normal_path.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2017 Statoil ASA, Norway. + Copyright (C) 2017 Equinor ASA, Norway. The file 'ert_util_normal_path.c' is part of ERT - Ensemble based Reservoir Tool. @@ -32,7 +32,7 @@ void test_path(const char * input_path, const char * expected_path) { void test_relative() { - test_work_area_type * work_area = test_work_area_alloc("Work"); + ecl::util::TestArea ta("relative_path"); util_make_path("level0/level1/level2"); test_path( "level0/level1/../", "level0"); @@ -48,11 +48,10 @@ void test_relative() { util_chdir("level0/level1"); test_path("../../level0/level1/level2/../file.txt" , "file.txt"); test_path("../../level0/level1/level2/../" , ""); - test_work_area_free( work_area ); } void test_beyond_root() { - test_work_area_type * work_area = test_work_area_alloc("Work"); + ecl::util::TestArea("beyond_root"); char * cwd = util_alloc_cwd( ); char * backref_cwd1 = util_alloc_sprintf("../../../../../../../../../../../%s" , cwd ); char * backref_cwd2 = util_alloc_sprintf("/../../../../../../../../../../../%s" , cwd ); @@ -61,7 +60,6 @@ void test_beyond_root() { free( backref_cwd1 ); free( backref_cwd2 ); free( cwd ); - test_work_area_free( work_area ); } diff --git a/ThirdParty/Ert/lib/util/tests/ert_util_parent_path.cpp b/ThirdParty/Ert/lib/util/tests/ert_util_parent_path.cpp index b5af351b93..7e3d5bdeef 100644 --- a/ThirdParty/Ert/lib/util/tests/ert_util_parent_path.cpp +++ b/ThirdParty/Ert/lib/util/tests/ert_util_parent_path.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Statoil ASA, Norway. + Copyright (C) 2012 Equinor ASA, Norway. The file 'ert_util_parent_path.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/util/tests/ert_util_path_stack_test.cpp b/ThirdParty/Ert/lib/util/tests/ert_util_path_stack_test.cpp index ddc26dbaf0..89e0cd018a 100644 --- a/ThirdParty/Ert/lib/util/tests/ert_util_path_stack_test.cpp +++ b/ThirdParty/Ert/lib/util/tests/ert_util_path_stack_test.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Statoil ASA, Norway. + Copyright (C) 2012 Equinor ASA, Norway. The file 'ert_util_path_stack_test.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/util/tests/ert_util_ping.cpp b/ThirdParty/Ert/lib/util/tests/ert_util_ping.cpp index 58f8e69ba3..a9291d3630 100644 --- a/ThirdParty/Ert/lib/util/tests/ert_util_ping.cpp +++ b/ThirdParty/Ert/lib/util/tests/ert_util_ping.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Statoil ASA, Norway. + Copyright (C) 2012 Equinor ASA, Norway. The file 'ert_util_ping.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/util/tests/ert_util_realpath.cpp b/ThirdParty/Ert/lib/util/tests/ert_util_realpath.cpp index 7f8c6e814e..2862e07060 100644 --- a/ThirdParty/Ert/lib/util/tests/ert_util_realpath.cpp +++ b/ThirdParty/Ert/lib/util/tests/ert_util_realpath.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'ert_util_realpath.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/util/tests/ert_util_relpath_test.cpp b/ThirdParty/Ert/lib/util/tests/ert_util_relpath_test.cpp index e19b336e99..2de2b0ea13 100644 --- a/ThirdParty/Ert/lib/util/tests/ert_util_relpath_test.cpp +++ b/ThirdParty/Ert/lib/util/tests/ert_util_relpath_test.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Statoil ASA, Norway. + Copyright (C) 2012 Equinor ASA, Norway. The file 'ert_util_relpath_test.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/util/tests/ert_util_rng.cpp b/ThirdParty/Ert/lib/util/tests/ert_util_rng.cpp index ed12cffa83..c309769072 100644 --- a/ThirdParty/Ert/lib/util/tests/ert_util_rng.cpp +++ b/ThirdParty/Ert/lib/util/tests/ert_util_rng.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'ert_util_rng.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/util/tests/ert_util_spawn.cpp b/ThirdParty/Ert/lib/util/tests/ert_util_spawn.cpp index 19d402f031..127c7847dd 100644 --- a/ThirdParty/Ert/lib/util/tests/ert_util_spawn.cpp +++ b/ThirdParty/Ert/lib/util/tests/ert_util_spawn.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2016 Statoil ASA, Norway. + Copyright (C) 2016 Equinor ASA, Norway. The file 'ert_util_spawn.c' is part of ERT - Ensemble based Reservoir Tool. @@ -59,7 +59,7 @@ bool check_script(const char* script) { } void test_spawn_no_redirect() { - test_work_area_type * test_area = test_work_area_alloc("spawn1"); + ecl::util::TestArea ta("spawn1"); { int status; make_script("script" , stdout_msg , stderr_msg); @@ -77,7 +77,6 @@ void test_spawn_no_redirect() { test_assert_int_equal( status , 0 ); } } - test_work_area_free( test_area ); } @@ -136,7 +135,7 @@ void * test_spawn_redirect__( const char * path ) { void test_spawn_redirect() { - test_work_area_type * test_area = test_work_area_alloc("spawn1"); + ecl::util::TestArea ta("test_redirect"); { make_script("script" , stdout_msg , stderr_msg); util_addmode_if_owner( "script" , S_IRUSR + S_IWUSR + S_IXUSR + S_IRGRP + S_IWGRP + S_IXGRP + S_IROTH + S_IXOTH); /* u:rwx g:rwx o:rx */ @@ -144,14 +143,13 @@ void test_spawn_redirect() { test_spawn_redirect__( NULL ); } - test_work_area_free( test_area ); } void test_spawn_redirect_threaded() { const int num = 128; // Generate the scripts on disk first - test_work_area_type * test_area = test_work_area_alloc("spawn1_threaded"); + ecl::util::TestArea("spawn1_threaded"); int * path_codes = (int *)util_calloc(num, sizeof *path_codes); stringlist_type * script_fullpaths = stringlist_alloc_new(); for (int i=0; i < num; i++) { @@ -180,7 +178,6 @@ void test_spawn_redirect_threaded() { stringlist_free(script_fullpaths); free(path_codes); - test_work_area_free( test_area ); } diff --git a/ThirdParty/Ert/lib/util/tests/ert_util_split_path.cpp b/ThirdParty/Ert/lib/util/tests/ert_util_split_path.cpp index 4fce2b4e81..c759c624f7 100644 --- a/ThirdParty/Ert/lib/util/tests/ert_util_split_path.cpp +++ b/ThirdParty/Ert/lib/util/tests/ert_util_split_path.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2018 Statoil ASA, Norway. + Copyright (C) 2018 Equinor ASA, Norway. The file 'ert_util_split_path.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/util/tests/ert_util_sscan_test.cpp b/ThirdParty/Ert/lib/util/tests/ert_util_sscan_test.cpp index 60f4d180e1..f2d885b816 100644 --- a/ThirdParty/Ert/lib/util/tests/ert_util_sscan_test.cpp +++ b/ThirdParty/Ert/lib/util/tests/ert_util_sscan_test.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2014 Statoil ASA, Norway. + Copyright (C) 2014 Equinor ASA, Norway. The file 'ert_util_sscan_test.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/util/tests/ert_util_statistics.cpp b/ThirdParty/Ert/lib/util/tests/ert_util_statistics.cpp index ea859328f1..2ecfe9aef9 100644 --- a/ThirdParty/Ert/lib/util/tests/ert_util_statistics.cpp +++ b/ThirdParty/Ert/lib/util/tests/ert_util_statistics.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'ert_util_statistics.c' is part of ERT - Ensemble based Reservoir Tool. @@ -32,6 +32,8 @@ void test_mean_std() { test_assert_double_equal( statistics_mean( d ) , 0.50 ); test_assert_double_equal( statistics_std( d ) , 0.50 ); + + double_vector_free( d ); } diff --git a/ThirdParty/Ert/lib/util/tests/ert_util_strcat_test.cpp b/ThirdParty/Ert/lib/util/tests/ert_util_strcat_test.cpp index a7042a38eb..27742cc4ff 100644 --- a/ThirdParty/Ert/lib/util/tests/ert_util_strcat_test.cpp +++ b/ThirdParty/Ert/lib/util/tests/ert_util_strcat_test.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Statoil ASA, Norway. + Copyright (C) 2012 Equinor ASA, Norway. The file 'ert_util_strcat_test.c' is part of ERT - Ensemble based Reservoir Tool. @@ -28,8 +28,11 @@ void test_strcat(char * s1 , const char *s2 , const char * expected) { char * cat = util_strcat_realloc(s1 , s2 ); if (test_check_string_equal( cat , expected )) free( cat ); - else - test_error_exit("util_strcat_realloc(%s,%s) Got:%s expected:%s \n",s1,s2,cat , expected); + else { + fprintf(stderr, "util_strcat_realloc(%s,%s) Got:%s expected:%s \n",s1,s2,cat , expected); + free(cat); + exit(1); + } } diff --git a/ThirdParty/Ert/lib/util/tests/ert_util_string_util.cpp b/ThirdParty/Ert/lib/util/tests/ert_util_string_util.cpp index 65389d7176..872578336c 100644 --- a/ThirdParty/Ert/lib/util/tests/ert_util_string_util.cpp +++ b/ThirdParty/Ert/lib/util/tests/ert_util_string_util.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Statoil ASA, Norway. + Copyright (C) 2012 Equinor ASA, Norway. The file 'ert_util_string_util.c' is part of ERT - Ensemble based Reservoir Tool. @@ -60,6 +60,7 @@ void test_active_list() { test_assert_true( string_util_update_active_list("4-6" , active_list) ); test_int_vector( active_list , 13 , 0,1,3,4,5,6,7,8,9,10,14,15,16); + int_vector_free(active_list); } diff --git a/ThirdParty/Ert/lib/util/tests/ert_util_stringlist_test.cpp b/ThirdParty/Ert/lib/util/tests/ert_util_stringlist_test.cpp index 1ad4c890a7..f01c422819 100644 --- a/ThirdParty/Ert/lib/util/tests/ert_util_stringlist_test.cpp +++ b/ThirdParty/Ert/lib/util/tests/ert_util_stringlist_test.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Statoil ASA, Norway. + Copyright (C) 2012 Equinor ASA, Norway. The file 'ert_util_stringlist_test.c' is part of ERT - Ensemble based Reservoir Tool. @@ -36,15 +36,25 @@ void test_char() { { char ** copy = stringlist_alloc_char_copy( s ); int i; + bool equal = true; for (i=0; i < stringlist_get_size( s ); i++) { if (strcmp( stringlist_iget( s , i ) , copy[i]) != 0) - exit(1); - + equal = false; + free(copy[i]); } + free(copy); + if (!equal) + test_assert_false("Bug in test_char() function\n"); } + stringlist_free(s); } +void test_alloc_join(const stringlist_type * s, const char * sep, const char * expected) { + char * j = stringlist_alloc_joined_string(s, sep); + test_assert_string_equal(j, expected); + free(j); +} void test_join() { const char * elt0 = "AAA"; @@ -55,13 +65,8 @@ void test_join() { const char * elt5 = "FFF"; stringlist_type * s = stringlist_alloc_new(); + test_alloc_join(s, "!!!", ""); - { - // empty join - const char* empty_join = stringlist_alloc_joined_string(s, "!!!"); - test_assert_not_NULL(empty_join); - test_assert_string_equal("", empty_join); - } stringlist_append_copy( s , elt0 ); stringlist_append_copy( s , elt1 ); @@ -71,28 +76,37 @@ void test_join() { const char * sep1 = "!!!"; const char * sep2 = " abc "; - const char * j0 = stringlist_alloc_joined_string( s, sep0); - const char * j1 = stringlist_alloc_joined_string( s, sep1); - const char * j2 = stringlist_alloc_joined_string( s, sep2); + test_alloc_join(s, sep0, "AAABBBCCC"); + test_alloc_join(s, sep1, "AAA!!!BBB!!!CCC"); + test_alloc_join(s, sep2, "AAA abc BBB abc CCC"); - test_assert_string_equal( j0, "AAABBBCCC"); - test_assert_string_equal( j1, "AAA!!!BBB!!!CCC"); - test_assert_string_equal( j2, "AAA abc BBB abc CCC"); + { + stringlist_type * s1 = stringlist_alloc_new(); - stringlist_type * s1 = stringlist_alloc_new(); - stringlist_append_copy( s1 , elt0 ); - test_assert_string_equal( "AAA", stringlist_alloc_joined_string( s1, sep0)); - test_assert_string_equal( "AAA", stringlist_alloc_joined_string( s1, sep1)); - test_assert_string_equal( "AAA", stringlist_alloc_joined_string( s1, sep2)); + stringlist_append_copy( s1 , elt0 ); + test_alloc_join(s1, sep0, "AAA"); + test_alloc_join(s1, sep1, "AAA"); + test_alloc_join(s1, sep2, "AAA"); - stringlist_type * sub = stringlist_alloc_new(); - stringlist_append_copy( sub , elt0 ); - stringlist_append_copy( sub , elt1 ); - stringlist_append_copy( sub , elt2 ); - stringlist_append_copy( sub , elt3 ); - stringlist_append_copy( sub , elt4 ); - stringlist_append_copy( sub , elt5 ); - test_assert_string_equal( "CCC:DDD:EEE", stringlist_alloc_joined_substring( sub, 2, 5, ":")); + stringlist_free(s1); + } + { + stringlist_type * sub = stringlist_alloc_new(); + stringlist_append_copy( sub , elt0 ); + stringlist_append_copy( sub , elt1 ); + stringlist_append_copy( sub , elt2 ); + stringlist_append_copy( sub , elt3 ); + stringlist_append_copy( sub , elt4 ); + stringlist_append_copy( sub , elt5 ); + { + char * j = stringlist_alloc_joined_substring( sub, 2, 5, ":"); + test_assert_string_equal( "CCC:DDD:EEE", j); + free(j); + } + + stringlist_free(sub); + } + stringlist_free(s); } @@ -112,6 +126,8 @@ void test_reverse() { test_assert_string_equal( s2 , stringlist_iget(s , 0 )); test_assert_string_equal( s1 , stringlist_iget(s , 1 )); test_assert_string_equal( s0 , stringlist_iget(s , 2 )); + + stringlist_free(s); } @@ -136,6 +152,7 @@ void test_iget_as_int() { value = stringlist_iget_as_int( s , 2 , NULL); test_assert_int_equal( value , -1); } + stringlist_free(s); } @@ -161,6 +178,7 @@ void test_iget_as_double() { test_assert_double_equal( value , -1); test_assert_false( valid ); } + stringlist_free(s); } @@ -235,12 +253,14 @@ void test_iget_as_bool() { test_assert_false( value ); test_assert_false( valid ); } + stringlist_free(s); } void test_empty() { stringlist_type * s = stringlist_alloc_new(); stringlist_fprintf( s , "\n" , stdout ); + stringlist_free(s); } void test_front_back() { @@ -347,7 +367,7 @@ bool not_FILE_predicate(const char * name, const void * arg) { void test_predicate_matching() { - test_work_area_type * work_area = test_work_area_alloc("predicate_test"); + ecl::util::TestArea ta("stringlist"); stringlist_type * s = stringlist_alloc_new(); stringlist_append_copy(s, "s"); stringlist_select_files(s, "does/not/exist", NULL, NULL); @@ -358,7 +378,7 @@ void test_predicate_matching() { FILE * f = util_fopen("FILE.txt", "w"); fclose(f); } - stringlist_select_files(s , test_work_area_get_cwd(work_area), NULL, NULL); + stringlist_select_files(s , ta.test_cwd().c_str(), NULL, NULL); test_assert_int_equal(1, stringlist_get_size(s)); { char * exp = util_alloc_abs_path("FILE.txt"); @@ -370,7 +390,7 @@ void test_predicate_matching() { test_assert_int_equal(1, stringlist_get_size(s)); test_assert_string_equal( "FILE.txt", stringlist_iget(s, 0)); - stringlist_select_files(s , test_work_area_get_cwd(work_area), FILE_predicate, NULL); + stringlist_select_files(s , ta.test_cwd().c_str(), FILE_predicate, NULL); test_assert_int_equal(1, stringlist_get_size(s)); { char * exp = util_alloc_abs_path("FILE.txt"); @@ -378,11 +398,10 @@ void test_predicate_matching() { free(exp); } - stringlist_select_files(s , test_work_area_get_cwd(work_area), not_FILE_predicate, NULL); + stringlist_select_files(s , ta.test_cwd().c_str(), not_FILE_predicate, NULL); test_assert_int_equal(0, stringlist_get_size(s)); stringlist_free(s); - test_work_area_free(work_area); } @@ -399,6 +418,7 @@ void test_unique() { stringlist_append_copy( s, "S2"); test_assert_false( stringlist_unique( s )); + stringlist_free(s); } int main( int argc , char ** argv) { diff --git a/ThirdParty/Ert/lib/util/tests/ert_util_strstr_int_format.cpp b/ThirdParty/Ert/lib/util/tests/ert_util_strstr_int_format.cpp index 567323c8eb..04b6e84ad0 100644 --- a/ThirdParty/Ert/lib/util/tests/ert_util_strstr_int_format.cpp +++ b/ThirdParty/Ert/lib/util/tests/ert_util_strstr_int_format.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Statoil ASA, Norway. + Copyright (C) 2012 Equinor ASA, Norway. The file 'ert_util_str_str_int_format.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/util/tests/ert_util_type_vector_functions.cpp b/ThirdParty/Ert/lib/util/tests/ert_util_type_vector_functions.cpp index 802e8e69cf..7376df2d50 100644 --- a/ThirdParty/Ert/lib/util/tests/ert_util_type_vector_functions.cpp +++ b/ThirdParty/Ert/lib/util/tests/ert_util_type_vector_functions.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'ert_util_type_vector_functions.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/util/tests/ert_util_type_vector_test.cpp b/ThirdParty/Ert/lib/util/tests/ert_util_type_vector_test.cpp index 1a447db084..5ef217d461 100644 --- a/ThirdParty/Ert/lib/util/tests/ert_util_type_vector_test.cpp +++ b/ThirdParty/Ert/lib/util/tests/ert_util_type_vector_test.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Statoil ASA, Norway. + Copyright (C) 2012 Equinor ASA, Norway. The file 'ert_util_type_vector_test.c' is part of ERT - Ensemble based Reservoir Tool. @@ -94,10 +94,12 @@ void test_contains() { int_vector_type * int_vector = int_vector_alloc( 0 , 100); test_assert_false( int_vector_contains( int_vector , 100 )); + int_vector_resize( int_vector, 1, 100 ); int_vector_iset( int_vector , 0 , 77 ); test_assert_false( int_vector_contains( int_vector , 100 )); test_assert_true( int_vector_contains( int_vector , 77 )); + int_vector_resize( int_vector, 11, 100 ); int_vector_iset( int_vector , 10 , 33 ); test_assert_true( int_vector_contains( int_vector , 100 )); test_assert_true( int_vector_contains( int_vector , 77 )); @@ -120,12 +122,15 @@ void test_contains_sorted() { test_assert_false( int_vector_contains( int_vector , 100 )); test_assert_true( int_vector_contains( int_vector , 89 )); test_assert_true( int_vector_contains( int_vector , 109 )); + + int_vector_free(int_vector); } void test_div() { int_vector_type * int_vector = int_vector_alloc( 0 , 100); + int_vector_resize( int_vector, 11, 100 ); int_vector_iset( int_vector , 10 , 100 ); int_vector_div( int_vector , 10 ); { @@ -133,6 +138,7 @@ void test_div() { for (i=0; i < int_vector_size( int_vector ); i++) test_assert_int_equal( 10 , int_vector_iget( int_vector , i )); } + int_vector_free(int_vector); } void test_memcpy_from_data() { @@ -239,6 +245,8 @@ void test_idel_insert() { void test_iset_block() { int_vector_type * vec = int_vector_alloc(0,0); + int_vector_resize( vec, 10, 0 ); + int_vector_resize( vec, 20, 77 ); int_vector_iset_block( vec , 10 , 10 , 77 ); test_assert_int_equal( int_vector_size( vec ) , 20 ); { @@ -263,8 +271,8 @@ void test_resize() { int i; int def = 77; int_vector_type * vec = int_vector_alloc(0,def); - int_vector_resize( vec , 10 ); - test_assert_int_equal( int_vector_size( vec ) , 10 ); + int_vector_resize( vec , 10 , def); + test_assert_int_equal( int_vector_size( vec ) , 10 ); for (i=0; i < 10; i++) test_assert_int_equal( int_vector_iget( vec , i ) , def ); @@ -272,12 +280,12 @@ void test_resize() { for (i=5; i < 10; i++) test_assert_int_equal( int_vector_iget( vec , i ) , 5 ); - int_vector_resize( vec , 5 ); + int_vector_resize( vec , 5 , def); test_assert_int_equal( int_vector_size( vec ) , 5 ); for (i=0; i < 5; i++) test_assert_int_equal( int_vector_iget( vec , i ) , def ); - int_vector_resize( vec , 10 ); + int_vector_resize( vec , 10, def ); test_assert_int_equal( int_vector_size( vec ) , 10 ); for (i=0; i < 10; i++) test_assert_int_equal( int_vector_iget( vec , i ) , def ); @@ -345,9 +353,9 @@ void test_empty() { void test_equal_index() { - int_vector_type * v1 = int_vector_alloc(0,0); - int_vector_type * v2 = int_vector_alloc(0,0); - int_vector_type * v3 = int_vector_alloc(0,0); + int_vector_type * v1 = int_vector_alloc(5,0); + int_vector_type * v2 = int_vector_alloc(5,0); + int_vector_type * v3 = int_vector_alloc(5,0); for (int i=0; i < 5; i++) { int_vector_iset(v1,i,i); @@ -373,10 +381,18 @@ void test_equal_index() { int_vector_free(v3); } +void test_misc() { + int_vector_type * v = int_vector_alloc(5, 123); + test_assert_int_equal( int_vector_iget(v, 2), 123 ); + int_vector_resize(v, 20, 0); + test_assert_int_equal( int_vector_iget(v, 4), 123); + test_assert_int_equal( int_vector_iget(v, 9), 0 ); + test_assert_int_equal( int_vector_iget(v, 19), 0); + int_vector_free(v); +} -int main(int argc , char ** argv) { - +void misc_int_vector_test() { int_vector_type * int_vector = int_vector_alloc( 0 , 99); test_abort(); @@ -385,8 +401,10 @@ int main(int argc , char ** argv) { test_assert_true( int_vector_is_instance( int_vector )); test_assert_false( double_vector_is_instance( int_vector )); + int_vector_resize( int_vector, 3, 99 ); int_vector_iset( int_vector , 2 , 0); int_vector_insert( int_vector , 2 , 77 ); + int_vector_resize( int_vector, 6, 99 ); int_vector_iset( int_vector , 5 , -10); assert_equal( int_vector_iget(int_vector , 0 ) == 99 ); @@ -428,6 +446,12 @@ int main(int argc , char ** argv) { test_assert_int_equal( int_vector_iget( int_vector , 3 ) , -245); test_assert_int_equal( int_vector_get_last( int_vector ) , -935); + int_vector_free(int_vector); +} + +int main(int argc , char ** argv) { + test_misc(); + misc_int_vector_test(); { int_vector_type * v1 = int_vector_alloc(0,0); int_vector_type * v2 = int_vector_alloc(0,0); diff --git a/ThirdParty/Ert/lib/util/tests/ert_util_unique_ptr.cpp b/ThirdParty/Ert/lib/util/tests/ert_util_unique_ptr.cpp index a2873abd6c..4d755633e7 100644 --- a/ThirdParty/Ert/lib/util/tests/ert_util_unique_ptr.cpp +++ b/ThirdParty/Ert/lib/util/tests/ert_util_unique_ptr.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2016 Statoil ASA, Norway. + Copyright (C) 2016 Equinor ASA, Norway. This is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/util/tests/ert_util_vector_test.cpp b/ThirdParty/Ert/lib/util/tests/ert_util_vector_test.cpp index ade1cb5f99..8a44cd2168 100644 --- a/ThirdParty/Ert/lib/util/tests/ert_util_vector_test.cpp +++ b/ThirdParty/Ert/lib/util/tests/ert_util_vector_test.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Statoil ASA, Norway. + Copyright (C) 2012 Equinor ASA, Norway. The file 'ert_util_vector_test.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/util/tests/ert_util_work_area.cpp b/ThirdParty/Ert/lib/util/tests/ert_util_work_area.cpp index 29e344729a..2c462290a6 100644 --- a/ThirdParty/Ert/lib/util/tests/ert_util_work_area.cpp +++ b/ThirdParty/Ert/lib/util/tests/ert_util_work_area.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Statoil ASA, Norway. + Copyright (C) 2012 Equinor ASA, Norway. The file 'ert_util_PATH_test.c' is part of ERT - Ensemble based Reservoir Tool. @@ -22,6 +22,7 @@ #include #include +#include #include #include @@ -48,10 +49,9 @@ void test_get_original_cwd() { void create_test_area(const char * test_name , bool store) { char * pre_cwd = util_alloc_cwd(); - test_work_area_type * work_area = test_work_area_alloc( test_name ); + test_work_area_type * work_area = test_work_area_alloc__( test_name, store ); char * work_path = util_alloc_string_copy( test_work_area_get_cwd( work_area )); - test_work_area_set_store( work_area , store ); test_assert_true( util_is_directory( work_path )); test_work_area_free( work_area ); test_assert_bool_equal( store , util_entry_exists( work_path )); @@ -158,31 +158,14 @@ void test_copy_parent_content( const char * path ) { } -void test_with_prefix() { - test_work_area_type * work_area = test_work_area_alloc( "with-prefix" ); - - util_make_path( "PREFIX" ); - { - test_work_area_type * sub_area = test_work_area_alloc_relative("PREFIX" , "sub-work" ); - test_assert_true( test_work_area_is_instance( sub_area )); - test_work_area_free( sub_area ); - test_assert_true( util_entry_exists("PREFIX/sub-work")); - } - { - test_work_area_type * sub_area = test_work_area_alloc_relative("DoesNotExist" , "sub-work" ); - test_assert_NULL( sub_area ); - } - test_work_area_free( work_area ); -} - void test_update_store() { { - test_work_area_type * work_area = test_work_area_alloc( "update-store1" ); + test_work_area_type * work_area = test_work_area_alloc__( "update-store1" , true); char * work_cwd = util_alloc_string_copy( test_work_area_get_cwd( work_area )); - test_work_area_set_store( work_area , true ); test_work_area_free( work_area ); test_assert_true( util_entry_exists( work_cwd )); + free(work_cwd); } { @@ -190,22 +173,23 @@ void test_update_store() { char * work_cwd = util_alloc_string_copy( test_work_area_get_cwd( work_area )); test_work_area_free( work_area ); test_assert_false( util_entry_exists( work_cwd )); + free(work_cwd); } { - test_work_area_type * work_area = test_work_area_alloc( "update-store3" ); + test_work_area_type * work_area = test_work_area_alloc__( "update-store3" , false); char * work_cwd = util_alloc_string_copy( test_work_area_get_cwd( work_area )); - test_work_area_set_store( work_area , false ); test_work_area_free( work_area ); test_assert_false( util_entry_exists( work_cwd )); + free(work_cwd); } { - test_work_area_type * work_area = test_work_area_alloc( "update-store4" ); + test_work_area_type * work_area = test_work_area_alloc__( "update-store4" , true); char * work_cwd = util_alloc_string_copy( test_work_area_get_cwd( work_area )); - test_work_area_set_store( work_area , true); test_work_area_free( work_area ); test_assert_true( util_entry_exists( work_cwd )); + free(work_cwd); } } @@ -215,10 +199,12 @@ int main(int argc , char ** argv) { const char * abs_path_file = argv[2]; const char * rel_directory = argv[3]; - create_test_area("STORE-TEST" , true ); - create_test_area("DEL-TEST" , false); + create_test_area("STORE-TEST", true ); + create_test_area("DEL-TEST", false); + test_install_file_exists( rel_path_file ); test_install_file_exists( abs_path_file ); + test_copy_directory( rel_directory ); test_input(); test_get_cwd(); @@ -233,8 +219,6 @@ int main(int argc , char ** argv) { test_copy_parent_content( rel_path_file ); test_copy_parent_content( abs_path_file ); - test_with_prefix(); test_update_store(); - exit(0); } diff --git a/ThirdParty/Ert/lib/util/tests/test_area.cpp b/ThirdParty/Ert/lib/util/tests/test_area.cpp new file mode 100644 index 0000000000..9f580ae18f --- /dev/null +++ b/ThirdParty/Ert/lib/util/tests/test_area.cpp @@ -0,0 +1,34 @@ +/* + Copyright (C) 2019 Equinor ASA, Norway. + + The file 'test_area.cpp' is part of ERT - Ensemble based Reservoir Tool. + + ERT 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. + + ERT 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 + +#include +#include + +void test_create() { + ecl::util::TestArea ta("Name"); + + test_assert_true( ta.test_cwd() != ta.original_cwd() ); + +} + + + +int main(int argc, char **argv) { + test_create(); +} diff --git a/ThirdParty/Ert/lib/util/tests/test_thread_pool.cpp b/ThirdParty/Ert/lib/util/tests/test_thread_pool.cpp index 1700de5a3b..f2679ae6d8 100644 --- a/ThirdParty/Ert/lib/util/tests/test_thread_pool.cpp +++ b/ThirdParty/Ert/lib/util/tests/test_thread_pool.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2015 Statoil ASA, Norway. + Copyright (C) 2015 Equinor ASA, Norway. The file 'test_thread_pool.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/util/timer.cpp b/ThirdParty/Ert/lib/util/timer.cpp index c333a20663..7c87a9c8c3 100644 --- a/ThirdParty/Ert/lib/util/timer.cpp +++ b/ThirdParty/Ert/lib/util/timer.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'timer.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/util/type_vector_functions.cpp b/ThirdParty/Ert/lib/util/type_vector_functions.cpp index 2dec9f3f1e..9daf66111e 100644 --- a/ThirdParty/Ert/lib/util/type_vector_functions.cpp +++ b/ThirdParty/Ert/lib/util/type_vector_functions.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'ert_util_vector_function.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/util/util.c b/ThirdParty/Ert/lib/util/util.c index 9ae01521b7..84048565e2 100644 --- a/ThirdParty/Ert/lib/util/util.c +++ b/ThirdParty/Ert/lib/util/util.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'util.c' is part of ERT - Ensemble based Reservoir Tool. @@ -996,7 +996,9 @@ char * util_alloc_normal_path( const char * input_path ) { return util_alloc_realpath__( input_path ); char * realpath = util_alloc_realpath__(input_path); - return util_alloc_rel_path( NULL , realpath ); + char * rel_path = util_alloc_rel_path( NULL , realpath ); + free( realpath ); + return rel_path; } @@ -2153,8 +2155,6 @@ int util_fmove( FILE * stream , long offset , long shift) { #ifdef HAVE_WINDOWS__ACCESS bool util_access(const char * entry, int mode) { - if (!entry) return false; - return (_access(entry, mode) == 0); } @@ -2162,8 +2162,6 @@ bool util_access(const char * entry, int mode) { #ifdef HAVE_POSIX_ACCESS bool util_access(const char * entry, mode_t mode) { - if (!entry) return false; - return (access(entry, mode) == 0); } #endif @@ -2890,13 +2888,6 @@ bool util_fscanf_date_utc(FILE *stream , time_t *t) { */ -void util_fprintf_date_utc(time_t t , FILE * stream) { - int mday,year,month; - - util_set_datetime_values_utc(t , NULL , NULL , NULL , &mday , &month , &year); - fprintf(stream , "%02d/%02d/%4d", mday,month,year); -} - char * util_alloc_date_string_utc( time_t t ) { int mday,year,month; @@ -3070,22 +3061,6 @@ time_t util_make_pure_date_utc(time_t t) { /*****************************************************************/ -void util_set_strip_copy(char * copy , const char *src) { - const char null_char = '\0'; - const char space_char = ' '; - int src_index = 0; - int target_index = 0; - while (src[src_index] == space_char) - src_index++; - - while (src[src_index] != null_char && src[src_index] != space_char) { - copy[target_index] = src[src_index]; - src_index++; - target_index++; - } - copy[target_index] = null_char; -} - /** The function will allocate a new copy of src where leading and @@ -4334,53 +4309,6 @@ void * util_realloc_copy(void * org_ptr , const void * src , size_t byte_size ) /*****************************************************************/ -/** - These small functions write formatted values onto a stream. The - main point about these functions is to avoid creating small one-off - format strings. The character base_fmt should be 'f' or 'g' -*/ - -void util_fprintf_double(double value , int width , int decimals , char base_fmt , FILE * stream) { - char * fmt = util_alloc_sprintf("%c%d.%d%c" , '%' , width , decimals , base_fmt); - fprintf(stream , fmt , value); - free(fmt); -} - - -void util_fprintf_int(int value , int width , FILE * stream) { - char fmt[32]; - sprintf(fmt , "%%%dd" , width); - fprintf(stream , fmt , value); -} - - - -void util_fprintf_string(const char * s , int width_ , string_alignement_type alignement , FILE * stream) { - char fmt[32]; - size_t i; - size_t width = width_; - if (alignement == left_pad) { - i = 0; - if (width > strlen(s)) { - for (i=0; i < (width - strlen(s)); i++) - fputc(' ' , stream); - } - fprintf(stream , "%s", s); - } else if (alignement == right_pad) { - sprintf(fmt , "%%-%lus" , width); - fprintf(stream , fmt , s); - } else { - int total_pad = width - strlen(s); - int front_pad = total_pad / 2; - int back_pad = total_pad - front_pad; - int i; - util_fprintf_string(s , front_pad + strlen(s) , left_pad , stream); - for (i=0; i < back_pad; i++) - fputc(' ' , stream); - } -} - - diff --git a/ThirdParty/Ert/lib/util/util_endian.cpp b/ThirdParty/Ert/lib/util/util_endian.cpp index 0613f0e639..a8a03f7af8 100644 --- a/ThirdParty/Ert/lib/util/util_endian.cpp +++ b/ThirdParty/Ert/lib/util/util_endian.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Statoil ASA, Norway. + Copyright (C) 2012 Equinor ASA, Norway. The file 'util_endian.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/util/util_lfs.c b/ThirdParty/Ert/lib/util/util_lfs.c index d6d9c1f735..422e87fd63 100644 --- a/ThirdParty/Ert/lib/util/util_lfs.c +++ b/ThirdParty/Ert/lib/util/util_lfs.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. + Copyright (C) 2013 Equinor ASA, Norway. The file 'util_lfs.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/util/util_unlink.cpp b/ThirdParty/Ert/lib/util/util_unlink.cpp index be7d633665..74200f572d 100644 --- a/ThirdParty/Ert/lib/util/util_unlink.cpp +++ b/ThirdParty/Ert/lib/util/util_unlink.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2017 Statoil ASA, Norway. + Copyright (C) 2017 Equinor ASA, Norway. The file 'util_unlink.c' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/lib/util/vector.cpp b/ThirdParty/Ert/lib/util/vector.cpp index 27da7ff790..9c8fdd6d76 100644 --- a/ThirdParty/Ert/lib/util/vector.cpp +++ b/ThirdParty/Ert/lib/util/vector.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'vector.c' is part of ERT - Ensemble based Reservoir Tool. @@ -589,6 +589,7 @@ int_vector_type * vector_alloc_sort_perm(const vector_type * vector , vector_cmp vector_sort_node_type * sort_data = vector_alloc_sort_data( vector , cmp ); int_vector_type * sort_perm = int_vector_alloc(0,0); int i; + int_vector_resize( sort_perm, vector->size, 0 ); for (i = 0; i < vector->size; i++) int_vector_iset( sort_perm , i , sort_data[i].index); diff --git a/ThirdParty/Ert/lib/util/vector_template.cpp b/ThirdParty/Ert/lib/util/vector_template.cpp index de5ee77a28..d9811f01ce 100644 --- a/ThirdParty/Ert/lib/util/vector_template.cpp +++ b/ThirdParty/Ert/lib/util/vector_template.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'vector_template.c' is part of ERT - Ensemble based Reservoir Tool. @@ -47,29 +47,29 @@ ------------------------------------ - ·-----·-----· + �-----�-----� 1. | 77 | 77 | size = 0, alloc_size = 2 - ·-----·-----· + �-----�-----� - ·-----·-----· + �-----�-----� 2. | 1 | 77 | size = 1, alloc_size = 2 - ·-----·-----· + �-----�-----� - ·-----·-----· + �-----�-----� 3. | 1 | 0 | size = 2, alloc_size = 2 - ·-----·-----· + �-----�-----� - ·-----·-----·-----·-----· + �-----�-----�-----�-----� 4. | 1 | 0 | 12 | 77 | size = 3, alloc_size = 4 - ·-----·-----·-----·-----· + �-----�-----�-----�-----� - ·-----·-----·-----·-----·-----·-----·-----·-----·-----·-----·-----·-----·-----·-----·-----·-----· + �-----�-----�-----�-----�-----�-----�-----�-----�-----�-----�-----�-----�-----�-----�-----�-----� 5. | 1 | 0 | 12 | 77 | 77 | 77 | 78 | 77 | 77 | 77 | 77 | 77 | 77 | 77 | 77 | 77 | size = 7, alloc_size = 12, default = 77 - ·-----·-----·-----·-----·-----·-----·-----·-----·-----·-----·-----·-----·-----·-----·-----·-----· + �-----�-----�-----�-----�-----�-----�-----�-----�-----�-----�-----�-----�-----�-----�-----�-----� - ·-----·-----·-----·-----·-----·-----·-----·-----·-----·-----·-----·-----·-----·-----·-----·-----· + �-----�-----�-----�-----�-----�-----�-----�-----�-----�-----�-----�-----�-----�-----�-----�-----� 6. | 1 | 0 | 12 | 77 | 77 | 77 | 78 | 99 | 99 | 99 | 99 | 99 | 99 | 99 | 99 | 99 | size = 7, alloc_size = 12, default = 99 - ·-----·-----·-----·-----·-----·-----·-----·-----·-----·-----·-----·-----·-----·-----·-----·-----· + �-----�-----�-----�-----�-----�-----�-----�-----�-----�-----�-----�-----�-----�-----�-----�-----� 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @@ -137,14 +137,14 @@ UTIL_SAFE_CAST_FUNCTION(@TYPE@_vector , TYPE_VECTOR_ID); UTIL_IS_INSTANCE_FUNCTION(@TYPE@_vector , TYPE_VECTOR_ID); -static void @TYPE@_vector_realloc_data__(@TYPE@_vector_type * vector , int new_alloc_size) { +static void @TYPE@_vector_realloc_data__(@TYPE@_vector_type * vector , int new_alloc_size, @TYPE@ default_value) { if (new_alloc_size != vector->alloc_size) { if (vector->data_owner) { if (new_alloc_size > 0) { int i; vector->data = (@TYPE@*)util_realloc(vector->data , new_alloc_size * sizeof * vector->data ); for (i=vector->alloc_size; i < new_alloc_size; i++) - vector->data[i] = vector->default_value; + vector->data[i] = default_value; } else { if (vector->alloc_size > 0) { free(vector->data); @@ -163,7 +163,7 @@ static void @TYPE@_vector_memmove(@TYPE@_vector_type * vector , int offset , int util_abort("%s: offset:%d left_shift:%d - invalid \n",__func__ , offset , -shift); if ((shift + vector->size > vector->alloc_size)) - @TYPE@_vector_realloc_data__( vector , util_int_min( 2*vector->alloc_size , shift + vector->size )); + @TYPE@_vector_realloc_data__( vector , util_int_min( 2*vector->alloc_size , shift + vector->size ), vector->default_value); { size_t move_size = (vector->size - offset) * sizeof(@TYPE@); @@ -230,7 +230,7 @@ static @TYPE@_vector_type * @TYPE@_vector_alloc__(int init_size , @TYPE@ default @TYPE@_vector_set_read_only( vector , false ); if (init_size > 0) - @TYPE@_vector_iset( vector , init_size - 1 , default_value ); /* Filling up the init size elements with the default value */ + @TYPE@_vector_resize( vector , init_size , default_value ); /* Filling up the init size elements with the default value */ return vector; } @@ -253,11 +253,18 @@ static @TYPE@_vector_type * @TYPE@_vector_alloc__(int init_size , @TYPE@ default new_size > current_size: The vector will grow by adding default elements at the end. */ -void @TYPE@_vector_resize( @TYPE@_vector_type * vector , int new_size ) { - if (new_size <= vector->size) - vector->size = new_size; - else - @TYPE@_vector_iset( vector , new_size - 1 , vector->default_value); +void @TYPE@_vector_resize( @TYPE@_vector_type * vector , int new_size, @TYPE@ default_value ) { + if (new_size > vector->size) { + if (new_size > vector->alloc_size) { + for (int i = vector->size; i < vector->alloc_size; i++) + vector->data[i] = default_value; + @TYPE@_vector_realloc_data__( vector, 2 * new_size, default_value); + } + else + for (int i = vector->size; i < new_size; i++) + vector->data[i] = default_value; + } + vector->size = new_size; } @@ -341,7 +348,8 @@ void @TYPE@_vector_memcpy_data_block( @TYPE@_vector_type * target , const @TYPE@ void @TYPE@_vector_memcpy_from_data( @TYPE@_vector_type * target , const @TYPE@ * src , int src_size ) { @TYPE@_vector_reset( target ); - @TYPE@_vector_iset( target , src_size - 1 , 0 ); + //@TYPE@_vector_iset( target , src_size - 1 , 0 ); + @TYPE@_vector_resize( target, src_size, 0); memcpy( target->data , src , src_size * sizeof * target->data ); } @@ -397,7 +405,7 @@ void @TYPE@_vector_memcpy( @TYPE@_vector_type * target, const @TYPE@_vector_type @TYPE@_vector_type * @TYPE@_vector_alloc_copy( const @TYPE@_vector_type * src) { @TYPE@_vector_type * copy = @TYPE@_vector_alloc( src->size , src->default_value ); - @TYPE@_vector_realloc_data__( copy , src->alloc_size ); + @TYPE@_vector_realloc_data__( copy , src->alloc_size, src->default_value ); copy->size = src->size; memcpy(copy->data , src->data , src->alloc_size * sizeof * src->data ); return copy; @@ -616,7 +624,7 @@ void @TYPE@_vector_iset(@TYPE@_vector_type * vector , int index , @TYPE@ value) util_abort("%s: Sorry - can NOT set negative indices. called with index:%d \n",__func__ , index); { if (vector->alloc_size <= index) - @TYPE@_vector_realloc_data__(vector , 2 * (index + 1)); /* Must have ( + 1) here to ensure we are not doing 2*0 */ + @TYPE@_vector_realloc_data__(vector , 2 * (index + 1), vector->default_value); /* Must have ( + 1) here to ensure we are not doing 2*0 */ vector->data[index] = value; if (index >= vector->size) { int i; @@ -729,7 +737,10 @@ void @TYPE@_vector_insert( @TYPE@_vector_type * vector , int index , @TYPE@ valu void @TYPE@_vector_append(@TYPE@_vector_type * vector , @TYPE@ value) { - @TYPE@_vector_iset(vector , vector->size , value); + //@TYPE@_vector_iset(vector , vector->size , value); + int size = vector->size; + @TYPE@_vector_resize(vector, size+1, 0); + vector->data[size] = value; } @@ -746,7 +757,7 @@ void @TYPE@_vector_free_container(@TYPE@_vector_type * vector) { void @TYPE@_vector_free_data(@TYPE@_vector_type * vector) { @TYPE@_vector_reset(vector); - @TYPE@_vector_realloc_data__(vector , 0); + @TYPE@_vector_realloc_data__(vector , 0, vector->default_value); } @@ -848,7 +859,7 @@ void @TYPE@_vector_set_many(@TYPE@_vector_type * vector , int index , const @TYP { int min_size = index + length; if (min_size > vector->alloc_size) - @TYPE@_vector_realloc_data__(vector , 2 * min_size); + @TYPE@_vector_realloc_data__(vector , 2 * min_size, vector->default_value); memcpy( &vector->data[index] , data , length * sizeof * data); if (min_size > vector->size) vector->size = min_size; @@ -931,7 +942,7 @@ void @TYPE@_vector_append_vector(@TYPE@_vector_type * vector , const @TYPE@_vect */ void @TYPE@_vector_shrink(@TYPE@_vector_type * vector) { - @TYPE@_vector_realloc_data__(vector , vector->size); + @TYPE@_vector_realloc_data__(vector , vector->size, vector->default_value); } @@ -1420,7 +1431,7 @@ void @TYPE@_vector_fprintf(const @TYPE@_vector_type * vector , FILE * stream , c vector_resize based on the input size. */ void @TYPE@_vector_fread_data( @TYPE@_vector_type * vector , int size, FILE * stream) { - @TYPE@_vector_realloc_data__( vector , size ); + @TYPE@_vector_realloc_data__( vector , size, vector->default_value ); util_fread( vector->data , sizeof * vector->data , size , stream , __func__); vector->size = size; } diff --git a/ThirdParty/Ert/lib/vector_template.h.in b/ThirdParty/Ert/lib/vector_template.h.in index c11dc38d34..8850800e2e 100644 --- a/ThirdParty/Ert/lib/vector_template.h.in +++ b/ThirdParty/Ert/lib/vector_template.h.in @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'vector_template.h' is part of ERT - Ensemble based Reservoir Tool. @@ -61,7 +61,7 @@ typedef @TYPE@ (@TYPE@_ftype) (@TYPE@); int @TYPE@_vector_get_min_index(const @TYPE@_vector_type * vector, bool reverse); int @TYPE@_vector_get_max_index(const @TYPE@_vector_type * vector, bool reverse); @TYPE@ @TYPE@_vector_iadd( @TYPE@_vector_type * vector , int index , @TYPE@ delta); - void @TYPE@_vector_resize( @TYPE@_vector_type * vector , int new_size ); + void @TYPE@_vector_resize( @TYPE@_vector_type * vector , int new_size , @TYPE@ default_value ); void @TYPE@_vector_iset(@TYPE@_vector_type * , int , @TYPE@); void @TYPE@_vector_iset_block(@TYPE@_vector_type * vector , int index , int block_size , @TYPE@ value); void @TYPE@_vector_idel_block( @TYPE@_vector_type * vector , int index , int block_size); diff --git a/ThirdParty/Ert/lib/vector_template.hpp.in b/ThirdParty/Ert/lib/vector_template.hpp.in index f4574fdda5..cc98127f36 100644 --- a/ThirdParty/Ert/lib/vector_template.hpp.in +++ b/ThirdParty/Ert/lib/vector_template.hpp.in @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. + Copyright (C) 2011 Equinor ASA, Norway. The file 'vector_template.hpp' is part of ERT - Ensemble based Reservoir Tool. diff --git a/ThirdParty/Ert/python/CMakeLists.txt b/ThirdParty/Ert/python/CMakeLists.txt index 6463a7704c..8f9cf51d9f 100644 --- a/ThirdParty/Ert/python/CMakeLists.txt +++ b/ThirdParty/Ert/python/CMakeLists.txt @@ -35,3 +35,6 @@ if (BUILD_TESTS) add_subdirectory( tests ) endif() +if(RST_DOC) + add_subdirectory( docs ) +endif() diff --git a/ThirdParty/Ert/python/docs/CMakeLists.txt b/ThirdParty/Ert/python/docs/CMakeLists.txt new file mode 100644 index 0000000000..58516cf894 --- /dev/null +++ b/ThirdParty/Ert/python/docs/CMakeLists.txt @@ -0,0 +1,60 @@ +find_package(Sphinx REQUIRED) + +set(DOC_INSTALL_PREFIX "share/libecl/docs") +set(doc_build "${PROJECT_BINARY_DIR}/doc_build") +file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/code" DESTINATION ${doc_build}) + +configure_file(index.rst.in "${doc_build}/index.rst") +configure_file(conf.py.in "${doc_build}/conf.py") + +add_custom_target(api-doc ALL + COMMAND sphinx-apidoc -e -o "${doc_build}/api" ${PROJECT_BINARY_DIR}/${PYTHON_INSTALL_PREFIX} tests + WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/${PYTHON_INSTALL_PREFIX} + DEPENDS ecl) + +add_custom_target(html-doc ALL + COMMAND sphinx-build -b html -d ${doc_build}/doctrees ${doc_build} ${doc_build}/html + WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/${PYTHON_INSTALL_PREFIX} + DEPENDS api-doc) + +INSTALL( DIRECTORY ${doc_build}/html DESTINATION ${CMAKE_INSTALL_PREFIX}/${DOC_INSTALL_PREFIX}) + + +# This command will configure sphinx to create a LaTeX version of the manual in +# ${doc_build}/latex - this can then subsequently be compiled with pdflatex to +# generate a pdf document. +# +# The LaTeX code generated by sphinx uses some packages which are not +# installed on RHEL 6/7, those sty files are therefor bundled with this +# project and copied manually to the LaTeX directory. +# +# Observe that at least on stock ubuntu 16.04 cmake will complain with a message: +# +# -- Could NOT find LATEX (missing: pdflatex) +# +# even in situatons where pdflatex is found and works ok; in this case the +# PDFLATEX_COMPILER variable is set and the pdf generation seems to work as +# expected. +find_package(LATEX COMPONENTS pdflatex) +if (PDFLATEX_COMPILER) + set(latex_workdir "${doc_build}/latex") + + add_custom_target(latex-doc ALL + COMMAND sphinx-build -b latex -d ${doc_build}/doctrees ${doc_build} ${latex_workdir} + WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/${PYTHON_INSTALL_PREFIX} + DEPENDS api-doc) + + file(GLOB sty_files "latex/*.sty") + file(COPY ${sty_files} DESTINATION ${latex_workdir}) + + # The pdflatex command is issued twice to let latex resolve references + # correctly. + add_custom_target(pdf-doc ALL + COMMAND ${PDFLATEX_COMPILER} "libecl.tex" + COMMAND ${PDFLATEX_COMPILER} "libecl.tex" + DEPENDS latex-doc + WORKING_DIRECTORY ${latex_workdir}) + + install(FILES ${latex_workdir}/libecl.pdf DESTINATION ${CMAKE_INSTALL_PREFIX}/${DOC_INSTALL_PREFIX}/pdf) +endif() + diff --git a/ThirdParty/Ert/docs/code/index.rst b/ThirdParty/Ert/python/docs/code/index.rst similarity index 90% rename from ThirdParty/Ert/docs/code/index.rst rename to ThirdParty/Ert/python/docs/code/index.rst index 8ebb5c1196..35405bde17 100644 --- a/ThirdParty/Ert/docs/code/index.rst +++ b/ThirdParty/Ert/python/docs/code/index.rst @@ -7,5 +7,4 @@ Contents: :maxdepth: 1 python/index - C/index diff --git a/ThirdParty/Ert/docs/code/python/eclipse/index.rst b/ThirdParty/Ert/python/docs/code/python/eclipse/index.rst similarity index 100% rename from ThirdParty/Ert/docs/code/python/eclipse/index.rst rename to ThirdParty/Ert/python/docs/code/python/eclipse/index.rst diff --git a/ThirdParty/Ert/docs/code/python/examples/eclipse/index.rst b/ThirdParty/Ert/python/docs/code/python/examples/eclipse/index.rst similarity index 100% rename from ThirdParty/Ert/docs/code/python/examples/eclipse/index.rst rename to ThirdParty/Ert/python/docs/code/python/examples/eclipse/index.rst diff --git a/ThirdParty/Ert/docs/code/python/examples/geo/index.rst b/ThirdParty/Ert/python/docs/code/python/examples/geo/index.rst similarity index 100% rename from ThirdParty/Ert/docs/code/python/examples/geo/index.rst rename to ThirdParty/Ert/python/docs/code/python/examples/geo/index.rst diff --git a/ThirdParty/Ert/docs/code/python/examples/index.rst b/ThirdParty/Ert/python/docs/code/python/examples/index.rst similarity index 81% rename from ThirdParty/Ert/docs/code/python/examples/index.rst rename to ThirdParty/Ert/python/docs/code/python/examples/index.rst index d5f7978c2f..90b577182b 100644 --- a/ThirdParty/Ert/docs/code/python/examples/index.rst +++ b/ThirdParty/Ert/python/docs/code/python/examples/index.rst @@ -7,4 +7,3 @@ Examples Eclipse results Geometric objects - Full ert cases diff --git a/ThirdParty/Ert/docs/code/python/index.rst b/ThirdParty/Ert/python/docs/code/python/index.rst similarity index 54% rename from ThirdParty/Ert/docs/code/python/index.rst rename to ThirdParty/Ert/python/docs/code/python/index.rst index 80e9b8d0f0..ec5233c5e3 100644 --- a/ThirdParty/Ert/docs/code/python/index.rst +++ b/ThirdParty/Ert/python/docs/code/python/index.rst @@ -9,5 +9,3 @@ Python documentation introduction/index Overview of ert Python examples/index - ert package - autogenerated API documentation <../../API/python/ert> - ert_gui package - autogenerated API documentation <../../API/python/ert_gui> diff --git a/ThirdParty/Ert/docs/code/python/introduction/index.rst b/ThirdParty/Ert/python/docs/code/python/introduction/index.rst similarity index 100% rename from ThirdParty/Ert/docs/code/python/introduction/index.rst rename to ThirdParty/Ert/python/docs/code/python/introduction/index.rst diff --git a/ThirdParty/Ert/docs/code/python/packages/eclipse/index.rst b/ThirdParty/Ert/python/docs/code/python/packages/eclipse/index.rst similarity index 100% rename from ThirdParty/Ert/docs/code/python/packages/eclipse/index.rst rename to ThirdParty/Ert/python/docs/code/python/packages/eclipse/index.rst diff --git a/ThirdParty/Ert/docs/code/python/packages/index.rst b/ThirdParty/Ert/python/docs/code/python/packages/index.rst similarity index 86% rename from ThirdParty/Ert/docs/code/python/packages/index.rst rename to ThirdParty/Ert/python/docs/code/python/packages/index.rst index f7522ecb6c..04ebdc6959 100644 --- a/ThirdParty/Ert/docs/code/python/packages/index.rst +++ b/ThirdParty/Ert/python/docs/code/python/packages/index.rst @@ -4,10 +4,7 @@ The ert packages .. toctree:: :maxdepth: 1 - util/index.rst eclipse/index.rst - well/index.rst - geometry/index.rst Currently only the package targeted at working with Eclipse files, diff --git a/ThirdParty/Ert/docs/conf.py.in b/ThirdParty/Ert/python/docs/conf.py.in similarity index 93% rename from ThirdParty/Ert/docs/conf.py.in rename to ThirdParty/Ert/python/docs/conf.py.in index 2bde72df1c..7d57a51d49 100644 --- a/ThirdParty/Ert/docs/conf.py.in +++ b/ThirdParty/Ert/python/docs/conf.py.in @@ -19,7 +19,7 @@ import os # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. #sys.path.insert(0, os.path.abspath('.')) -sys.path.insert(0, os.path.abspath('${PYTHON_INSTALL_PREFIX}')) +sys.path.insert(0, os.path.join('${PROJECT_BINARY_DIR}','${PYTHON_INSTALL_PREFIX}')) # -- General configuration ------------------------------------------------ @@ -47,17 +47,17 @@ source_suffix = '.rst' master_doc = 'index' # General information about the project. -project = u'ert' -copyright = u'2014, Statoil ASA' +project = u'libecl' +copyright = u'2014, Equinor ASA' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. -version = '${ERT_VERSION_MAJOR}.${ERT_VERSION_MINOR}' +version = '${LIBECL_VERSION_MAJOR}.${LIBECL_VERSION_MINOR}' # The full version, including alpha/beta/rc tags. -release = '${ERT_VERSION_MAJOR}.${ERT_VERSION_MINOR}.${ERT_VERSION_MICRO}' +release = '${LIBECL_VERSION_MAJOR}.${LIBECL_VERSION_MINOR}.${LIBECL_VERSION_MICRO}' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. @@ -180,7 +180,7 @@ html_static_path = ['_static'] #html_file_suffix = None # Output file base name for HTML help builder. -htmlhelp_basename = 'ertdoc' +htmlhelp_basename = 'libecldoc' # -- Options for LaTeX output --------------------------------------------- @@ -200,8 +200,8 @@ latex_elements = { # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ - ('index', 'ert.tex', u'ert Documentation', - u'Statoil ASA', 'manual'), + ('index', 'libecl.tex', u'libecl documentation', + u'Equinor ASA', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of @@ -230,8 +230,8 @@ latex_documents = [ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ - ('index', 'ert', u'ert Documentation', - [u'Statoil ASA'], 1) + ('index', 'libecl', u'libecl documentation', + [u'Equinor ASA'], 1) ] # If true, show URL addresses after external links. @@ -244,8 +244,8 @@ man_pages = [ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - ('index', 'ert', u'ert Documentation', - u'Statoil ASA', 'ert', 'One line description of project.', + ('index', 'libecl', u'libecl ocumentation', + u'Equinor ASA', 'ert', 'One line description of project.', 'Miscellaneous'), ] @@ -266,9 +266,9 @@ texinfo_documents = [ # Bibliographic Dublin Core info. epub_title = u'ert' -epub_author = u'Statoil ASA' -epub_publisher = u'Statoil ASA' -epub_copyright = u'2014, Statoil ASA' +epub_author = u'Equinor ASA' +epub_publisher = u'Equinor ASA' +epub_copyright = u'2014, Equinor ASA' # The basename for the epub file. It defaults to the project name. #epub_basename = u'ert' diff --git a/ThirdParty/Ert/docs/examples/avg_pressure.py b/ThirdParty/Ert/python/docs/examples/avg_pressure.py similarity index 96% rename from ThirdParty/Ert/docs/examples/avg_pressure.py rename to ThirdParty/Ert/python/docs/examples/avg_pressure.py index 45dd786802..aa502b8c77 100644 --- a/ThirdParty/Ert/docs/examples/avg_pressure.py +++ b/ThirdParty/Ert/python/docs/examples/avg_pressure.py @@ -3,7 +3,8 @@ import sys import matplotlib.pyplot as plt # Import the required symbols from the ecl.ecl package. -from ecl.ecl import EclFile, EclGrid, EclRegion, EclRestartFile +from ecl.eclfile import EclFile, EclRestartFile +from ecl.grid import EclGrid, EclRegion # Calculate the average pressure for all the cells in the region using diff --git a/ThirdParty/Ert/docs/examples/cmp_nnc.py b/ThirdParty/Ert/python/docs/examples/cmp_nnc.py similarity index 69% rename from ThirdParty/Ert/docs/examples/cmp_nnc.py rename to ThirdParty/Ert/python/docs/examples/cmp_nnc.py index 1e1ff2f52c..248d3000f2 100644 --- a/ThirdParty/Ert/docs/examples/cmp_nnc.py +++ b/ThirdParty/Ert/python/docs/examples/cmp_nnc.py @@ -1,7 +1,8 @@ #!/usr/bin/env python import sys from operator import itemgetter -from ecl.ecl import EclFile, EclGrid +from ecl.eclfile import EclFile +from ecl.grid import EclGrid @@ -22,10 +23,15 @@ if __name__ == "__main__": nnc_list = sorted(nnc_list, key = itemgetter(0)) for (g1,g2,T) in nnc_list: + # grid_ijk assumes 0-based indexing, g1/g2 are 1-based (FORTRAN) + # Convert them to zero based ones. + g1 = g1 - 1 + g2 = g2 - 1 i1,j1,k1 = grid.get_ijk( global_index = g1 ) i2,j2,k2 = grid.get_ijk( global_index = g2 ) - print "(%02d,%02d,%02d) -> (%02d,%02d,%02d) T:%g" % (i1,j1,k2,i2,j2,k2,T) + # print 1-based indices just like in eclipse PRT files + print "(%02d,%02d,%02d) -> (%02d,%02d,%02d) T:%g" % (i1+1,j1+1,k1+1,i2+1,j2+1,k2+1,T) diff --git a/ThirdParty/Ert/docs/examples/grid_info.py b/ThirdParty/Ert/python/docs/examples/grid_info.py similarity index 94% rename from ThirdParty/Ert/docs/examples/grid_info.py rename to ThirdParty/Ert/python/docs/examples/grid_info.py index 3a226a929f..20ffdb0cab 100644 --- a/ThirdParty/Ert/docs/examples/grid_info.py +++ b/ThirdParty/Ert/python/docs/examples/grid_info.py @@ -1,6 +1,6 @@ #!/usr/bin/env python import sys -from ecl.ecl import EclGrid, EclRegion +from ecl.grid import EclGrid, EclRegion def volume_min_max(grid): diff --git a/ThirdParty/Ert/docs/index.rst.in b/ThirdParty/Ert/python/docs/index.rst.in similarity index 87% rename from ThirdParty/Ert/docs/index.rst.in rename to ThirdParty/Ert/python/docs/index.rst.in index f75b6f9116..9d688b5183 100644 --- a/ThirdParty/Ert/docs/index.rst.in +++ b/ThirdParty/Ert/python/docs/index.rst.in @@ -7,10 +7,8 @@ Contents: :maxdepth: 1 :numbered: - user/index code/index - ${ERT_DOC_LINK} - + api/ecl Indices and tables ================== diff --git a/ThirdParty/Ert/python/docs/latex/capt-of.sty b/ThirdParty/Ert/python/docs/latex/capt-of.sty new file mode 100644 index 0000000000..b40978ad2c --- /dev/null +++ b/ThirdParty/Ert/python/docs/latex/capt-of.sty @@ -0,0 +1,33 @@ +%% +%% This is file `capt-of.sty', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% capt-of.dtx (with options: `package') +%% ---------------------------------------------------------------------- +%% The capt-off package -- float-style captions outside of floats +%% Copyright (c) 2010 Robin Fairbairns +%% +%% This work may be distributed and/or modified under the conditions of the +%% LaTeX Project Public License, either version 1.3c of this license or (at +%% your option) any later version. The latest version of this license is in: +%% http://www.latex-project.org/lppl.txt, and version 1.3c or later is part +%% of all distributions of LaTeX version 2005/12/01 or later. +%% +%% This work has the LPPL maintenance status `author-maintained'. +%% +%% This work consists of the files capt-of.dtx, capt-of.ins, and README +%% and the derived files footmisc.sty (not distributed from the archive) +%% and footmisc.pdf. +%% ----------------------------------------------------------------------- +%% +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{capt-of}% + [2009/12/29 v0.2 + standard captions outside of floats% + ]% $Id: footmisc.dtx,v 4.20 2005/03/17 13:41:58 rf Exp rf10 $ +\newcommand\captionof[1]{\def\@captype{#1}\caption} +\endinput +%% +%% End of file `capt-of.sty'. diff --git a/ThirdParty/Ert/python/docs/latex/fncychap.sty b/ThirdParty/Ert/python/docs/latex/fncychap.sty new file mode 100644 index 0000000000..f0a9c97e22 --- /dev/null +++ b/ThirdParty/Ert/python/docs/latex/fncychap.sty @@ -0,0 +1,701 @@ +%% Copyright 2007 Ulf Lindgren +% +% This work may be distributed and/or modified under the conditions of the LaTeX +% Project Public License, either version 1.3 of this license or (at your option) +% any later version. The latest version of this license is in +% http://www.latex-project.org/lppl.txt +% and version 1.3 or later is part of all distributions of LaTeX version +% 2005/12/01 or later. +% +% This work has the LPPL maintenance status `maintained'. +% +% The Current Maintainer of this work is Ulf Lindgren. +% +% This work consists of all files listed in manifest.txt. +% +%% This statement added 2010/12/10 by Clea F. Rees following correspondence +%% between Ulf Lindgren and Karl Berry concerning licensing. + +%%% Copyright Ulf A. Lindgren +%%% +%%% Note Premission is granted to modify this file under +%%% the condition that it is saved using another +%%% file and package name. +%%% +%%% Revision 1.1 (1997) +%%% +%%% Jan. 8th Modified package name base date option +%%% Jan. 22th Modified FmN and FmTi for error in book.cls +%%% \MakeUppercase{#}->{\MakeUppercase#} +%%% Apr. 6th Modified Lenny option to prevent undesired +%%% skip of line. +%%% Nov. 8th Fixed \@chapapp for AMS +%%% +%%% Revision 1.2 (1998) +%%% +%%% Feb. 11th Fixed appendix problem related to Bjarne +%%% Aug. 11th Fixed problem related to 11pt and 12pt +%%% suggested by Tomas Lundberg. THANKS! +%%% +%%% Revision 1.3 (2004) +%%% Sep. 20th problem with frontmatter, mainmatter and +%%% backmatter, pointed out by Lapo Mori +%%% +%%% Revision 1.31 (2004) +%%% Sep. 21th problem with the Rejne definition streched text +%%% caused ugly gaps in the vrule aligned with the title +%%% text. Kindly pointed out to me by Hendri Adriaens +%%% +%%% Revision 1.32 (2005) +%%% Jun. 23th compatibility problem with the KOMA class 'scrbook.cls' +%%% a remedy is a redefinition of '\@schapter' in +%%% line with that used in KOMA. The problem was pointed +%%% out to me by Mikkel Holm Olsen +%%% +%%% Revision 1.33 (2005) +%%% Aug. 9th misspelled ``TWELV'' corrected, the error was pointed +%%% out to me by George Pearson +%%% +%%% Revision 1.34 (2007) +%%% Added an alternative to Lenny provided by Peter +%%% Osborne (2005-11-28) +%%% Corrected front, main and back matter, based on input +%%% from Bas van Gils (2006-04-24) +%%% Jul. 30th Added Bjornstrup option provided by Jean-Marc +%%% Francois (2007-01-05). +%%% Reverted to \MakeUppercase{#} see rev 1.1, solved +%%% problem with MakeUppercase and MakeLowercase pointed +%%% out by Marco Feuerstein (2007-06-06) + + +%%% Last modified Jul. 2007 + +\NeedsTeXFormat{LaTeX2e}[1995/12/01] +\ProvidesPackage{fncychap} + [2007/07/30 v1.34 + LaTeX package (Revised chapters)] + +%%%% For conditional inclusion of color +\newif\ifusecolor +\usecolorfalse + + + +%%%% DEFINITION OF Chapapp variables +\newcommand{\CNV}{\huge\bfseries} +\newcommand{\ChNameVar}[1]{\renewcommand{\CNV}{#1}} + + +%%%% DEFINITION OF TheChapter variables +\newcommand{\CNoV}{\huge\bfseries} +\newcommand{\ChNumVar}[1]{\renewcommand{\CNoV}{#1}} + +\newif\ifUCN +\UCNfalse +\newif\ifLCN +\LCNfalse +\def\ChNameLowerCase{\LCNtrue\UCNfalse} +\def\ChNameUpperCase{\UCNtrue\LCNfalse} +\def\ChNameAsIs{\UCNfalse\LCNfalse} + +%%%%% Fix for AMSBook 971008 + +\@ifundefined{@chapapp}{\let\@chapapp\chaptername}{} + + +%%%%% Fix for Bjarne and appendix 980211 + +\newif\ifinapp +\inappfalse +\renewcommand\appendix{\par + \setcounter{chapter}{0}% + \setcounter{section}{0}% + \inapptrue% + \renewcommand\@chapapp{\appendixname}% + \renewcommand\thechapter{\@Alph\c@chapter}} + +%%%%% Fix for frontmatter, mainmatter, and backmatter 040920 + +\@ifundefined{@mainmatter}{\newif\if@mainmatter \@mainmattertrue}{} + +%%%%% + + + +\newcommand{\FmN}[1]{% +\ifUCN + {\MakeUppercase{#1}}\LCNfalse +\else + \ifLCN + {\MakeLowercase{#1}}\UCNfalse + \else #1 + \fi +\fi} + + +%%%% DEFINITION OF Title variables +\newcommand{\CTV}{\Huge\bfseries} +\newcommand{\ChTitleVar}[1]{\renewcommand{\CTV}{#1}} + +%%%% DEFINITION OF the basic rule width +\newlength{\RW} +\setlength{\RW}{1pt} +\newcommand{\ChRuleWidth}[1]{\setlength{\RW}{#1}} + +\newif\ifUCT +\UCTfalse +\newif\ifLCT +\LCTfalse +\def\ChTitleLowerCase{\LCTtrue\UCTfalse} +\def\ChTitleUpperCase{\UCTtrue\LCTfalse} +\def\ChTitleAsIs{\UCTfalse\LCTfalse} +\newcommand{\FmTi}[1]{% +\ifUCT + {\MakeUppercase{#1}}\LCTfalse +\else + \ifLCT + {\MakeLowercase{#1}}\UCTfalse + \else {#1} + \fi +\fi} + + + +\newlength{\mylen} +\newlength{\myhi} +\newlength{\px} +\newlength{\py} +\newlength{\pyy} +\newlength{\pxx} + + +\def\mghrulefill#1{\leavevmode\leaders\hrule\@height #1\hfill\kern\z@} + +\newcommand{\DOCH}{% + \CNV\FmN{\@chapapp}\space \CNoV\thechapter + \par\nobreak + \vskip 20\p@ + } +\newcommand{\DOTI}[1]{% + \CTV\FmTi{#1}\par\nobreak + \vskip 40\p@ + } +\newcommand{\DOTIS}[1]{% + \CTV\FmTi{#1}\par\nobreak + \vskip 40\p@ + } + +%%%%%% SONNY DEF + +\DeclareOption{Sonny}{% + \ChNameVar{\Large\sf} + \ChNumVar{\Huge} + \ChTitleVar{\Large\sf} + \ChRuleWidth{0.5pt} + \ChNameUpperCase + \renewcommand{\DOCH}{% + \raggedleft + \CNV\FmN{\@chapapp}\space \CNoV\thechapter + \par\nobreak + \vskip 40\p@} + \renewcommand{\DOTI}[1]{% + \CTV\raggedleft\mghrulefill{\RW}\par\nobreak + \vskip 5\p@ + \CTV\FmTi{#1}\par\nobreak + \mghrulefill{\RW}\par\nobreak + \vskip 40\p@} + \renewcommand{\DOTIS}[1]{% + \CTV\raggedleft\mghrulefill{\RW}\par\nobreak + \vskip 5\p@ + \CTV\FmTi{#1}\par\nobreak + \mghrulefill{\RW}\par\nobreak + \vskip 40\p@} +} + +%%%%%% LENNY DEF + +\DeclareOption{Lenny}{% + + \ChNameVar{\fontsize{14}{16}\usefont{OT1}{phv}{m}{n}\selectfont} + \ChNumVar{\fontsize{60}{62}\usefont{OT1}{ptm}{m}{n}\selectfont} + \ChTitleVar{\Huge\bfseries\rm} + \ChRuleWidth{1pt} + \renewcommand{\DOCH}{% + \settowidth{\px}{\CNV\FmN{\@chapapp}} + \addtolength{\px}{2pt} + \settoheight{\py}{\CNV\FmN{\@chapapp}} + \addtolength{\py}{1pt} + + \settowidth{\mylen}{\CNV\FmN{\@chapapp}\space\CNoV\thechapter} + \addtolength{\mylen}{1pt} + \settowidth{\pxx}{\CNoV\thechapter} + \addtolength{\pxx}{-1pt} + + \settoheight{\pyy}{\CNoV\thechapter} + \addtolength{\pyy}{-2pt} + \setlength{\myhi}{\pyy} + \addtolength{\myhi}{-1\py} + \par + \parbox[b]{\textwidth}{% + \rule[\py]{\RW}{\myhi}% + \hskip -\RW% + \rule[\pyy]{\px}{\RW}% + \hskip -\px% + \raggedright% + \CNV\FmN{\@chapapp}\space\CNoV\thechapter% + \hskip1pt% + \mghrulefill{\RW}% + \rule{\RW}{\pyy}\par\nobreak% + \vskip -\baselineskip% + \vskip -\pyy% + \hskip \mylen% + \mghrulefill{\RW}\par\nobreak% + \vskip \pyy}% + \vskip 20\p@} + + + \renewcommand{\DOTI}[1]{% + \raggedright + \CTV\FmTi{#1}\par\nobreak + \vskip 40\p@} + + \renewcommand{\DOTIS}[1]{% + \raggedright + \CTV\FmTi{#1}\par\nobreak + \vskip 40\p@} + } + +%%%%%% Peter Osbornes' version of LENNY DEF + +\DeclareOption{PetersLenny}{% + +% five new lengths +\newlength{\bl} % bottom left : orig \space +\setlength{\bl}{6pt} +\newcommand{\BL}[1]{\setlength{\bl}{#1}} +\newlength{\br} % bottom right : orig 1pt +\setlength{\br}{1pt} +\newcommand{\BR}[1]{\setlength{\br}{#1}} +\newlength{\tl} % top left : orig 2pt +\setlength{\tl}{2pt} +\newcommand{\TL}[1]{\setlength{\tl}{#1}} +\newlength{\trr} % top right :orig 1pt +\setlength{\trr}{1pt} +\newcommand{\TR}[1]{\setlength{\trr}{#1}} +\newlength{\blrule} % top right :orig 1pt +\setlength{\trr}{0pt} +\newcommand{\BLrule}[1]{\setlength{\blrule}{#1}} + + + \ChNameVar{\fontsize{14}{16}\usefont{OT1}{phv}{m}{n}\selectfont} + \ChNumVar{\fontsize{60}{62}\usefont{OT1}{ptm}{m}{n}\selectfont} + \ChTitleVar{\Huge\bfseries\rm} + \ChRuleWidth{1pt} +\renewcommand{\DOCH}{% + + +%%%%%%% tweaks for 1--9 and A--Z +\ifcase\c@chapter\relax% +\or\BL{-3pt}\TL{-4pt}\BR{0pt}\TR{-6pt}%1 +\or\BL{0pt}\TL{-4pt}\BR{2pt}\TR{-4pt}%2 +\or\BL{0pt}\TL{-4pt}\BR{2pt}\TR{-4pt}%3 +\or\BL{0pt}\TL{5pt}\BR{2pt}\TR{-4pt}%4 +\or\BL{0pt}\TL{3pt}\BR{2pt}\TR{-4pt}%5 +\or\BL{-1pt}\TL{0pt}\BR{2pt}\TR{-2pt}%6 +\or\BL{0pt}\TL{-3pt}\BR{2pt}\TR{-2pt}%7 +\or\BL{0pt}\TL{-3pt}\BR{2pt}\TR{-2pt}%8 +\or\BL{0pt}\TL{-3pt}\BR{-4pt}\TR{-2pt}%9 +\or\BL{-3pt}\TL{-3pt}\BR{2pt}\TR{-7pt}%10 +\or\BL{-6pt}\TL{-6pt}\BR{0pt}\TR{-9pt}%11 +\or\BL{-6pt}\TL{-6pt}\BR{2pt}\TR{-7pt}%12 +\or\BL{-5pt}\TL{-5pt}\BR{0pt}\TR{-9pt}%13 +\or\BL{-6pt}\TL{-6pt}\BR{0pt}\TR{-9pt}%14 +\or\BL{-3pt}\TL{-3pt}\BR{3pt}\TR{-6pt}%15 +\or\BL{-3pt}\TL{-3pt}\BR{3pt}\TR{-6pt}%16 +\or\BL{-5pt}\TL{-3pt}\BR{-8pt}\TR{-6pt}%17 +\or\BL{-5pt}\TL{-5pt}\BR{0pt}\TR{-9pt}%18 +\or\BL{-3pt}\TL{-3pt}\BR{-6pt}\TR{-9pt}%19 +\or\BL{0pt}\TL{0pt}\BR{0pt}\TR{-5pt}%20 +\fi + +\ifinapp\ifcase\c@chapter\relax% +\or\BL{0pt}\TL{14pt}\BR{5pt}\TR{-19pt}%A +\or\BL{0pt}\TL{-5pt}\BR{-3pt}\TR{-8pt}%B +\or\BL{-3pt}\TL{-2pt}\BR{1pt}\TR{-6pt}\BLrule{0pt}%C +\or\BL{0pt}\TL{-5pt}\BR{-3pt}\TR{-8pt}\BLrule{0pt}%D +\or\BL{0pt}\TL{-5pt}\BR{2pt}\TR{-3pt}%E +\or\BL{0pt}\TL{-5pt}\BR{-10pt}\TR{-1pt}%F +\or\BL{-3pt}\TL{0pt}\BR{0pt}\TR{-7pt}%G +\or\BL{0pt}\TL{-5pt}\BR{3pt}\TR{-1pt}%H +\or\BL{0pt}\TL{-5pt}\BR{3pt}\TR{-1pt}%I +\or\BL{2pt}\TL{0pt}\BR{-3pt}\TR{1pt}%J +\or\BL{0pt}\TL{-5pt}\BR{3pt}\TR{-1pt}%K +\or\BL{0pt}\TL{-5pt}\BR{2pt}\TR{-19pt}%L +\or\BL{0pt}\TL{-5pt}\BR{3pt}\TR{-1pt}%M +\or\BL{0pt}\TL{-5pt}\BR{-2pt}\TR{-1pt}%N +\or\BL{-3pt}\TL{-2pt}\BR{-3pt}\TR{-11pt}%O +\or\BL{0pt}\TL{-5pt}\BR{-9pt}\TR{-3pt}%P +\or\BL{-3pt}\TL{-2pt}\BR{-3pt}\TR{-11pt}%Q +\or\BL{0pt}\TL{-5pt}\BR{4pt}\TR{-8pt}%R +\or\BL{-2pt}\TL{-2pt}\BR{-2pt}\TR{-7pt}%S +\or\BL{-3pt}\TL{0pt}\BR{-5pt}\TR{4pt}\BLrule{8pt}%T +\or\BL{-7pt}\TL{-11pt}\BR{-5pt}\TR{-7pt}\BLrule{0pt}%U +\or\BL{-14pt}\TL{-5pt}\BR{-14pt}\TR{-1pt}\BLrule{14pt}%V +\or\BL{-10pt}\TL{-9pt}\BR{-13pt}\TR{-3pt}\BLrule{7pt}%W +\or\BL{0pt}\TL{-5pt}\BR{3pt}\TR{-1pt}\BLrule{0pt}%X +\or\BL{-6pt}\TL{-4pt}\BR{-7pt}\TR{1pt}\BLrule{7pt}%Y +\or\BL{0pt}\TL{-5pt}\BR{3pt}\TR{-1pt}\BLrule{0pt}%Z +\fi\fi +%%%%%%% + \settowidth{\px}{\CNV\FmN{\@chapapp}} + \addtolength{\px}{\tl} %MOD change 2pt to \tl + \settoheight{\py}{\CNV\FmN{\@chapapp}} + \addtolength{\py}{1pt} + + \settowidth{\mylen}{\CNV\FmN{\@chapapp}\space\CNoV\thechapter} + \addtolength{\mylen}{\trr}% MOD change 1pt to \tr + \settowidth{\pxx}{\CNoV\thechapter} + \addtolength{\pxx}{-1pt} + + \settoheight{\pyy}{\CNoV\thechapter} + \addtolength{\pyy}{-2pt} + \setlength{\myhi}{\pyy} + \addtolength{\myhi}{-1\py} + \par + \parbox[b]{\textwidth}{% + \rule[\py]{\RW}{\myhi}% + \hskip -\RW% + \rule[\pyy]{\px}{\RW}% + \hskip -\px% + \raggedright% + \CNV\FmN{\@chapapp}\rule{\blrule}{\RW}\hskip\bl\CNoV\thechapter%MOD +% \CNV\FmN{\@chapapp}\space\CNoV\thechapter %ORIGINAL + \hskip\br% %MOD 1pt to \br + \mghrulefill{\RW}% + \rule{\RW}{\pyy}\par\nobreak% + \vskip -\baselineskip% + \vskip -\pyy% + \hskip \mylen% + \mghrulefill{\RW}\par\nobreak% + \vskip \pyy}% + \vskip 20\p@} + + + \renewcommand{\DOTI}[1]{% + \raggedright + \CTV\FmTi{#1}\par\nobreak + \vskip 40\p@} + + \renewcommand{\DOTIS}[1]{% + \raggedright + \CTV\FmTi{#1}\par\nobreak + \vskip 40\p@} + } + + +% + + +%%%%%% BJORNSTRUP DEF + +\DeclareOption{Bjornstrup}{% + \usecolortrue + % pzc (Zapf Chancelery) is nice. ppl (Palatino) is cool too. + \ChNumVar{\fontsize{76}{80}\usefont{OT1}{pzc}{m}{n}\selectfont} + \ChTitleVar{\raggedleft\Large\sffamily\bfseries} + + \setlength{\myhi}{10pt} % Space between grey box border and text + \setlength{\mylen}{\textwidth} + \addtolength{\mylen}{-2\myhi} + \renewcommand{\DOCH}{% + \settowidth{\py}{\CNoV\thechapter} + \addtolength{\py}{-10pt} % Amount of space by which the +% % number is shifted right + \fboxsep=0pt% + \colorbox[gray]{.85}{\rule{0pt}{40pt}\parbox[b]{\textwidth}{\hfill}}% + \kern-\py\raise20pt% + \hbox{\color[gray]{.5}\CNoV\thechapter}\\% + } + + \renewcommand{\DOTI}[1]{% + \nointerlineskip\raggedright% + \fboxsep=\myhi% + \vskip-1ex% + \colorbox[gray]{.85}{\parbox[t]{\mylen}{\CTV\FmTi{#1}}}\par\nobreak% + \vskip 40\p@% + } + + \renewcommand{\DOTIS}[1]{% + \fboxsep=0pt + \colorbox[gray]{.85}{\rule{0pt}{40pt}\parbox[b]{\textwidth}{\hfill}}\\% + \nointerlineskip\raggedright% + \fboxsep=\myhi% + \colorbox[gray]{.85}{\parbox[t]{\mylen}{\CTV\FmTi{#1}}}\par\nobreak% + \vskip 40\p@% + } +} + + +%%%%%%% GLENN DEF + + +\DeclareOption{Glenn}{% + \ChNameVar{\bfseries\Large\sf} + \ChNumVar{\Huge} + \ChTitleVar{\bfseries\Large\rm} + \ChRuleWidth{1pt} + \ChNameUpperCase + \ChTitleUpperCase + \renewcommand{\DOCH}{% + \settoheight{\myhi}{\CTV\FmTi{Test}} + \setlength{\py}{\baselineskip} + \addtolength{\py}{\RW} + \addtolength{\py}{\myhi} + \setlength{\pyy}{\py} + \addtolength{\pyy}{-1\RW} + + \raggedright + \CNV\FmN{\@chapapp}\space\CNoV\thechapter + \hskip 3pt\mghrulefill{\RW}\rule[-1\pyy]{2\RW}{\py}\par\nobreak} + + \renewcommand{\DOTI}[1]{% + \addtolength{\pyy}{-4pt} + \settoheight{\myhi}{\CTV\FmTi{#1}} + \addtolength{\myhi}{\py} + \addtolength{\myhi}{-1\RW} + \vskip -1\pyy + \rule{2\RW}{\myhi}\mghrulefill{\RW}\hskip 2pt + \raggedleft\CTV\FmTi{#1}\par\nobreak + \vskip 80\p@} + +\newlength{\backskip} + \renewcommand{\DOTIS}[1]{% +% \setlength{\py}{10pt} +% \setlength{\pyy}{\py} +% \addtolength{\pyy}{\RW} +% \setlength{\myhi}{\baselineskip} +% \addtolength{\myhi}{\pyy} +% \mghrulefill{\RW}\rule[-1\py]{2\RW}{\pyy}\par\nobreak +% \addtolength{}{} +%\vskip -1\baselineskip +% \rule{2\RW}{\myhi}\mghrulefill{\RW}\hskip 2pt +% \raggedleft\CTV\FmTi{#1}\par\nobreak +% \vskip 60\p@} +%% Fix suggested by Tomas Lundberg + \setlength{\py}{25pt} % eller vad man vill + \setlength{\pyy}{\py} + \setlength{\backskip}{\py} + \addtolength{\backskip}{2pt} + \addtolength{\pyy}{\RW} + \setlength{\myhi}{\baselineskip} + \addtolength{\myhi}{\pyy} + \mghrulefill{\RW}\rule[-1\py]{2\RW}{\pyy}\par\nobreak + \vskip -1\backskip + \rule{2\RW}{\myhi}\mghrulefill{\RW}\hskip 3pt % + \raggedleft\CTV\FmTi{#1}\par\nobreak + \vskip 40\p@} + } + +%%%%%%% CONNY DEF + +\DeclareOption{Conny}{% + \ChNameUpperCase + \ChTitleUpperCase + \ChNameVar{\centering\Huge\rm\bfseries} + \ChNumVar{\Huge} + \ChTitleVar{\centering\Huge\rm} + \ChRuleWidth{2pt} + + \renewcommand{\DOCH}{% + \mghrulefill{3\RW}\par\nobreak + \vskip -0.5\baselineskip + \mghrulefill{\RW}\par\nobreak + \CNV\FmN{\@chapapp}\space \CNoV\thechapter + \par\nobreak + \vskip -0.5\baselineskip + } + \renewcommand{\DOTI}[1]{% + \mghrulefill{\RW}\par\nobreak + \CTV\FmTi{#1}\par\nobreak + \vskip 60\p@ + } + \renewcommand{\DOTIS}[1]{% + \mghrulefill{\RW}\par\nobreak + \CTV\FmTi{#1}\par\nobreak + \vskip 60\p@ + } + } + +%%%%%%% REJNE DEF + +\DeclareOption{Rejne}{% + + \ChNameUpperCase + \ChTitleUpperCase + \ChNameVar{\centering\Large\rm} + \ChNumVar{\Huge} + \ChTitleVar{\centering\Huge\rm} + \ChRuleWidth{1pt} + \renewcommand{\DOCH}{% + \settoheight{\py}{\CNoV\thechapter} + \parskip=0pt plus 1pt % Set parskip to default, just in case v1.31 + \addtolength{\py}{-1pt} + \CNV\FmN{\@chapapp}\par\nobreak + \vskip 20\p@ + \setlength{\myhi}{2\baselineskip} + \setlength{\px}{\myhi} + \addtolength{\px}{-1\RW} + \rule[-1\px]{\RW}{\myhi}\mghrulefill{\RW}\hskip + 10pt\raisebox{-0.5\py}{\CNoV\thechapter}\hskip 10pt\mghrulefill{\RW}\rule[-1\px]{\RW}{\myhi}\par\nobreak + \vskip -3\p@% Added -2pt vskip to correct for streched text v1.31 + } + \renewcommand{\DOTI}[1]{% + \setlength{\mylen}{\textwidth} + \parskip=0pt plus 1pt % Set parskip to default, just in case v1.31 + \addtolength{\mylen}{-2\RW} + {\vrule width\RW}\parbox{\mylen}{\CTV\FmTi{#1}}{\vrule width\RW}\par\nobreak% + \vskip -3pt\rule{\RW}{2\baselineskip}\mghrulefill{\RW}\rule{\RW}{2\baselineskip}% + \vskip 60\p@% Added -2pt in vskip to correct for streched text v1.31 + } + \renewcommand{\DOTIS}[1]{% + \setlength{\py}{\fboxrule} + \setlength{\fboxrule}{\RW} + \setlength{\mylen}{\textwidth} + \addtolength{\mylen}{-2\RW} + \fbox{\parbox{\mylen}{\vskip 2\baselineskip\CTV\FmTi{#1}\par\nobreak\vskip \baselineskip}} + \setlength{\fboxrule}{\py} + \vskip 60\p@ + } + } + + +%%%%%%% BJARNE DEF + +\DeclareOption{Bjarne}{% + \ChNameUpperCase + \ChTitleUpperCase + \ChNameVar{\raggedleft\normalsize\rm} + \ChNumVar{\raggedleft \bfseries\Large} + \ChTitleVar{\raggedleft \Large\rm} + \ChRuleWidth{1pt} + + +%% Note thechapter -> c@chapter fix appendix bug +%% Fixed misspelled 12 + + \newcounter{AlphaCnt} + \newcounter{AlphaDecCnt} + \newcommand{\AlphaNo}{% + \ifcase\number\theAlphaCnt + \ifnum\c@chapter=0 + ZERO\else{}\fi + \or ONE\or TWO\or THREE\or FOUR\or FIVE + \or SIX\or SEVEN\or EIGHT\or NINE\or TEN + \or ELEVEN\or TWELVE\or THIRTEEN\or FOURTEEN\or FIFTEEN + \or SIXTEEN\or SEVENTEEN\or EIGHTEEN\or NINETEEN\fi +} + + \newcommand{\AlphaDecNo}{% + \setcounter{AlphaDecCnt}{0} + \@whilenum\number\theAlphaCnt>0\do + {\addtocounter{AlphaCnt}{-10} + \addtocounter{AlphaDecCnt}{1}} + \ifnum\number\theAlphaCnt=0 + \else + \addtocounter{AlphaDecCnt}{-1} + \addtocounter{AlphaCnt}{10} + \fi + + + \ifcase\number\theAlphaDecCnt\or TEN\or TWENTY\or THIRTY\or + FORTY\or FIFTY\or SIXTY\or SEVENTY\or EIGHTY\or NINETY\fi + } + \newcommand{\TheAlphaChapter}{% + + \ifinapp + \thechapter + \else + \setcounter{AlphaCnt}{\c@chapter} + \ifnum\c@chapter<20 + \AlphaNo + \else + \AlphaDecNo\AlphaNo + \fi + \fi + } + \renewcommand{\DOCH}{% + \mghrulefill{\RW}\par\nobreak + \CNV\FmN{\@chapapp}\par\nobreak + \CNoV\TheAlphaChapter\par\nobreak + \vskip -1\baselineskip\vskip 5pt\mghrulefill{\RW}\par\nobreak + \vskip 20\p@ + } + \renewcommand{\DOTI}[1]{% + \CTV\FmTi{#1}\par\nobreak + \vskip 40\p@ + } + \renewcommand{\DOTIS}[1]{% + \CTV\FmTi{#1}\par\nobreak + \vskip 40\p@ + } +} + +\DeclareOption*{% + \PackageWarning{fancychapter}{unknown style option} + } + +\ProcessOptions* \relax + +\ifusecolor + \RequirePackage{color} +\fi +\def\@makechapterhead#1{% + \vspace*{50\p@}% + {\parindent \z@ \raggedright \normalfont + \ifnum \c@secnumdepth >\m@ne + \if@mainmatter%%%%% Fix for frontmatter, mainmatter, and backmatter 040920 + \DOCH + \fi + \fi + \interlinepenalty\@M + \if@mainmatter%%%%% Fix for frontmatter, mainmatter, and backmatter 060424 + \DOTI{#1}% + \else% + \DOTIS{#1}% + \fi + }} + + +%%% Begin: To avoid problem with scrbook.cls (fncychap version 1.32) + +%%OUT: +%\def\@schapter#1{\if@twocolumn +% \@topnewpage[\@makeschapterhead{#1}]% +% \else +% \@makeschapterhead{#1}% +% \@afterheading +% \fi} + +%%IN: +\def\@schapter#1{% +\if@twocolumn% + \@makeschapterhead{#1}% +\else% + \@makeschapterhead{#1}% + \@afterheading% +\fi} + +%%% End: To avoid problem with scrbook.cls (fncychap version 1.32) + +\def\@makeschapterhead#1{% + \vspace*{50\p@}% + {\parindent \z@ \raggedright + \normalfont + \interlinepenalty\@M + \DOTIS{#1} + \vskip 40\p@ + }} + +\endinput + + diff --git a/ThirdParty/Ert/python/docs/latex/framed.sty b/ThirdParty/Ert/python/docs/latex/framed.sty new file mode 100644 index 0000000000..b044e96593 --- /dev/null +++ b/ThirdParty/Ert/python/docs/latex/framed.sty @@ -0,0 +1,548 @@ +% framed.sty v 0.96 2011/10/22 +% Copyright (C) 1992-2011 by Donald Arseneau (asnd@triumf.ca) +% These macros may be freely transmitted, reproduced, or modified +% for any purpose provided that this notice is left intact. +% +%====================== Begin Instructions ======================= +% +% framed.sty +% ~~~~~~~~~~ +% Create framed, shaded, or differently highlighted regions that can +% break across pages. The environments defined are +% framed - ordinary frame box (\fbox) with edge at margin +% oframed - framed with open top/bottom at page breaks +% shaded - shaded background (\colorbox) bleeding into margin +% shaded* - shaded background (\colorbox) with edge at margin +% snugshade - shaded with tight fit around text (esp. in lists) +% snugshade* - like snugshade with shading edge at margin +% leftbar - thick vertical line in left margin +% +% to be used like +% \begin{framed} +% copious text +% \end{framed} +% +% But the more general purpose of this package is to facilitate the +% definition of new environments that take multi-line material, +% wrap it with some non-breakable formatting (some kind of box or +% decoration) and allow page breaks in the material. Such environments +% are defined to declare (or use) \FrameCommand for applying the boxy +% decoration, and \MakeFramed{settings} ... \endMakeFramed wrapped +% around the main text argument (environment body). +% +% The "framed" environment uses "\fbox", by default, as its "\FrameCommand" +% with the additional settings "\fboxrule=\FrameRule" and "\fboxsep=\FrameSep". +% You can change these lengths (using "\setlength") and you can change +% the definition of "\FrameCommand" to use much fancier boxes. +% +% In fact, the "shaded" environment just redefines \FrameCommand to be +% "\colorbox{shadecolor}" (and you have to define the color `"shadecolor"': +% "\definecolor{shadecolor}..."). +% +% Although the intention is for other packages to define the varieties +% of decoration, a command "\OpenFbox" is defined for frames with open +% tops or bottoms, and used for the "oframed" environment. This facility +% is based on a more complex and capable command "\CustomFBox" which can +% be used for a wider range of frame styles. One such style of a title-bar +% frame with continuation marks is provided as an example. It is used by +% the "titled-frame" environment. To make use of "titled-frame" in your +% document, or the "\TitleBarFrame" command in your own environment +% definitions, you must define the colors TFFrameColor (for the frame) +% and a contrasting TFTitleColor (for the title text). +% +% A page break is allowed, and even encouraged, before the framed +% environment. If you want to attach some text (a box title) to the +% frame, then the text should be inserted by \FrameCommand so it cannot +% be separated from the body. +% +% The contents of the framed regions are restricted: +% Floats, footnotes, marginpars and head-line entries will be lost. +% (Some of these may be handled in a later version.) +% This package will not work with the page breaking of multicol.sty, +% or other systems that perform column-balancing. +% +% The MakeFramed environment does the work. Its `settings' argument +% should contain any adjustments to the text width (via a setting of +% "\hsize"). Here, the parameter "\width" gives the measured extra width +% added by the frame, so a common setting is "\advance\hsize-\width" +% which reduces the width of the text just enough that the outer edge +% of the frame aligns with the margins. The `settings' should also +% include a `restore' command -- "\@parboxrestore" or "\FrameRestore" +% or something similar; for instance, the snugshade environment uses +% settings to eliminate list indents and vertical space, but uses +% "\hspace" in "\FrameCommand" to reproduce the list margin ouside the +% shading. +% +% There are actually four variants of "\FrameCommand" to allow different +% formatting for each part of an environment broken over pages. Unbroken +% text is adorned by "\FrameCommand", whereas split text first uses +% "\FirstFrameCommand", possibly followed by "\MidFrameCommand", and +% finishing with "\LastFrameCommand". The default definitions for +% these three just invokes "\FrameCommand", so that all portions are +% framed the same way. See the oframe environment for use of distinct +% First/Mid/Last frames. +% +% Expert commands: +% \MakeFramed, \endMakeFramed: the "MakeFramed" environment +% \FrameCommand: command to draw the frame around its argument +% \FirstFrameCommand: the frame for the first part of a split environment +% \LastFrameCommand: for the last portion +% \MidFrameCommand: for any intermediate segments +% \FrameRestore: restore some text settings, but fewer than \@parboxrestore +% \FrameRule: length register; \fboxrule for default "framed". +% \FrameSep: length register; \fboxsep for default "framed". +% \FrameHeightAdjust: macro; height of frame above baseline at top of page +% \OuterFrameSep: vertical space before and after the framed env. Defaults to "\topsep" +% +% This is still a `pre-production' version because I can think of many +% features/improvements that should be made. Also, a detailed manual needs +% to be written. Nevertheless, starting with version 0.5 it should be bug-free. +% +% ToDo: +% Test more varieties of list +% Improve and correct documentation +% Propagation of \marks +% Handle footnotes (how??) floats (?) and marginpars. +% Stretchability modification. +% Make inner contents height/depth influence placement. +%======================== End Instructions ======================== + +\ProvidesPackage{framed}[2011/10/22 v 0.96: + framed or shaded text with page breaks] + +\newenvironment{framed}% using default \FrameCommand + {\MakeFramed {\advance\hsize-\width \FrameRestore}}% + {\endMakeFramed} + +\newenvironment{shaded}{% + \def\FrameCommand{\fboxsep=\FrameSep \colorbox{shadecolor}}% + \MakeFramed {\FrameRestore}}% + {\endMakeFramed} + +\newenvironment{shaded*}{% + \def\FrameCommand{\fboxsep=\FrameSep \colorbox{shadecolor}}% + \MakeFramed {\advance\hsize-\width \FrameRestore}}% + {\endMakeFramed} + +\newenvironment{leftbar}{% + \def\FrameCommand{\vrule width 3pt \hspace{10pt}}% + \MakeFramed {\advance\hsize-\width \FrameRestore}}% + {\endMakeFramed} + +% snugshde: Shaded environment that +% -- uses the default \fboxsep instead of \FrameSep +% -- leaves the text indent unchanged (shading bleeds out) +% -- eliminates possible internal \topsep glue (\@setminipage) +% -- shrinks inside the margins for lists +% An \item label will tend to hang outside the shading, thanks to +% the small \fboxsep. + +\newenvironment{snugshade}{% + \def\FrameCommand##1{\hskip\@totalleftmargin \hskip-\fboxsep + \colorbox{shadecolor}{##1}\hskip-\fboxsep + % There is no \@totalrightmargin, so: + \hskip-\linewidth \hskip-\@totalleftmargin \hskip\columnwidth}% + \MakeFramed {\advance\hsize-\width + \@totalleftmargin\z@ \linewidth\hsize + \@setminipage}% + }{\par\unskip\@minipagefalse\endMakeFramed} + +\newenvironment{snugshade*}{% + \def\FrameCommand##1{\hskip\@totalleftmargin + \colorbox{shadecolor}{##1}% + % There is no \@totalrightmargin, so: + \hskip-\linewidth \hskip-\@totalleftmargin \hskip\columnwidth}% + \MakeFramed {\advance\hsize-\width + \@totalleftmargin\z@ \linewidth\hsize + \advance\labelsep\fboxsep + \@setminipage}% + }{\par\unskip\@minipagefalse\endMakeFramed} + +\newenvironment{oframed}{% open (top or bottom) framed + \def\FrameCommand{\OpenFBox\FrameRule\FrameRule}% + \def\FirstFrameCommand{\OpenFBox\FrameRule\z@}% + \def\MidFrameCommand{\OpenFBox\z@\z@}% + \def\LastFrameCommand{\OpenFBox\z@\FrameRule}% + \MakeFramed {\advance\hsize-\width \FrameRestore}% + }{\endMakeFramed} + +% A simplified entry to \CustomFBox with two customized parameters: +% the thicknesses of the top and bottom rules. Perhaps we want to +% use less \fboxsep on the open edges? + +\def\OpenFBox#1#2{\fboxsep\FrameSep + \CustomFBox{}{}{#1}{#2}\FrameRule\FrameRule} + +% \CustomFBox is like an amalgamation of \fbox and \@frameb@x, +% so it can be used by an alternate to \fbox or \fcolorbox, but +% it has more parameters for various customizations. +% Parameter #1 is inserted (in vmode) right after the top rule +% (useful for a title or assignments), and #2 is similar, but +% inserted right above the bottom rule. +% The thicknesses of the top, bottom, left, and right rules are +% given as parameters #3,#4,#5,#6 respectively. They should be +% \fboxrule or \z@ (or some other thickness). +% The text argument is #7. +% An instance of this can be used for the frame of \fcolorbox by +% locally defining \fbox before \fcolorbox; e.g., +% \def\fbox{\CustomFBox{}{}\z@\z@\fboxrule\fboxrule}\fcolorbox +% +% Do we need to use different \fboxsep on different sides too? +% +\long\def\CustomFBox#1#2#3#4#5#6#7{% + \leavevmode\begingroup + \setbox\@tempboxa\hbox{% + \color@begingroup + \kern\fboxsep{#7}\kern\fboxsep + \color@endgroup}% + \hbox{% + % Here we calculate and shift for the depth. Done in + % a group because one of the arguments might be \@tempdima + % (we could use \dimexpr instead without grouping). + \begingroup + \@tempdima#4\relax + \advance\@tempdima\fboxsep + \advance\@tempdima\dp\@tempboxa + \expandafter\endgroup\expandafter + \lower\the\@tempdima\hbox{% + \vbox{% + \hrule\@height#3\relax + #1% + \hbox{% + \vrule\@width#5\relax + \vbox{% + \vskip\fboxsep % maybe these should be parameters too + \copy\@tempboxa + \vskip\fboxsep}% + \vrule\@width#6\relax}% + #2% + \hrule\@height#4\relax}% + }% + }% + \endgroup +} + + +% A particular type of titled frame with continuation marks. +% Parameter #1 is the title, repeated on each page. +\newenvironment{titled-frame}[1]{% + \def\FrameCommand{\fboxsep8pt\fboxrule2pt + \TitleBarFrame{\textbf{#1}}}% + \def\FirstFrameCommand{\fboxsep8pt\fboxrule2pt + \TitleBarFrame[$\blacktriangleright$]{\textbf{#1}}}% + \def\MidFrameCommand{\fboxsep8pt\fboxrule2pt + \TitleBarFrame[$\blacktriangleright$]{\textbf{#1\ (cont)}}}% + \def\LastFrameCommand{\fboxsep8pt\fboxrule2pt + \TitleBarFrame{\textbf{#1\ (cont)}}}% + \MakeFramed{\advance\hsize-20pt \FrameRestore}}% +% note: 8 + 2 + 8 + 2 = 20. Don't use \width because the frame title +% could interfere with the width measurement. + {\endMakeFramed} + +% \TitleBarFrame[marker]{title}{contents} +% Frame with a label at top, optional continuation marker at bottom right. +% Frame color is TFFrameColor and title color is a contrasting TFTitleColor; +% both need to be defined before use. The frame itself use \fboxrule and +% \fboxsep. If the title is omitted entirely, the title bar is omitted +% (use a blank space to force a blank title bar). +% +\newcommand\TitleBarFrame[3][]{\begingroup + \ifx\delimiter#1\delimiter + \let\TF@conlab\@empty + \else + \def\TF@conlab{% continuation label + \nointerlineskip + \smash{\rlap{\kern\wd\@tempboxa\kern\fboxrule\kern\fboxsep #1}}}% + \fi + \let\TF@savecolor\current@color + \textcolor{TFFrameColor}{% + \CustomFBox + {\TF@Title{#2}}{\TF@conlab}% + \fboxrule\fboxrule\fboxrule\fboxrule + {\let\current@color\TF@savecolor\set@color #3}% + }\endgroup +} + +% The title bar for \TitleBarFrame +\newcommand\TF@Title[1]{% + \ifx\delimiter#1\delimiter\else + \kern-0.04pt\relax + \begingroup + \setbox\@tempboxa\vbox{% + \kern0.8ex + \hbox{\kern\fboxsep\textcolor{TFTitleColor}{#1}\vphantom{Tj)}}% + \kern0.8ex}% + \hrule\@height\ht\@tempboxa + \kern-\ht\@tempboxa + \box\@tempboxa + \endgroup + \nointerlineskip + \kern-0.04pt\relax + \fi +} + +\chardef\FrameRestore=\catcode`\| % for debug +\catcode`\|=\catcode`\% % (debug: insert space after backslash) + +\newlength\OuterFrameSep \OuterFrameSep=\maxdimen \relax + +\def\MakeFramed#1{\par + % apply default \OuterFrameSep = \topsep + \ifdim\OuterFrameSep=\maxdimen \OuterFrameSep\topsep \fi + % measure added width and height; call result \width and \height + \fb@sizeofframe\FrameCommand + \let\width\fb@frw \let\height\fb@frh + % insert pre-penalties and skips + \begingroup + \skip@\lastskip + \if@nobreak\else + \penalty9999 % updates \page parameters + \ifdim\pagefilstretch=\z@ \ifdim\pagefillstretch=\z@ + % not infinitely stretchable, so encourage a page break here + \edef\@tempa{\the\skip@}% + \ifx\@tempa\zero@glue \penalty-30 + \else \vskip-\skip@ \penalty-30 \vskip\skip@ + \fi\fi\fi + \penalty\z@ + % Give a stretchy breakpoint that will always be taken in preference + % to the \penalty 9999 used to update page parameters. The cube root + % of 10000/100 indicates a multiplier of 0.21545, but the maximum + % calculated badness is really 8192, not 10000, so the multiplier + % is 0.2301. + \advance\skip@ \z@ plus-.5\baselineskip + \advance\skip@ \z@ plus-.231\height + \advance\skip@ \z@ plus-.231\skip@ + \advance\skip@ \z@ plus-.231\OuterFrameSep + \vskip-\skip@ \penalty 1800 \vskip\skip@ + \fi + \addvspace{\OuterFrameSep}% + \endgroup + % clear out pending page break + \penalty\@M \vskip 2\baselineskip \vskip\height + \penalty9999 \vskip -2\baselineskip \vskip-\height + \penalty9999 % updates \pagetotal +|\message{After clearout, \pagetotal=\the\pagetotal, \pagegoal=\the\pagegoal. }% + \fb@adjheight + \setbox\@tempboxa\vbox\bgroup + #1% Modifications to \hsize (can use \width and \height) + \textwidth\hsize \columnwidth\hsize +} + +\def\endMakeFramed{\par + \kern\z@ + \hrule\@width\hsize\@height\z@ % possibly bad + \penalty-100 % (\hrule moves depth into height) + \egroup +%%% {\showoutput\showbox\@tempboxa}% + \begingroup + \fb@put@frame\FrameCommand\FirstFrameCommand + \endgroup + \@minipagefalse % In case it was set and not cleared +} + +% \fb@put@frame takes the contents of \@tempboxa and puts all, or a piece, +% of it on the page with a frame (\FrameCommand, \FirstFrameCommand, +% \MidFrameCommand, or \LastFrameCommand). It recurses until all of +% \@tempboxa has been used up. (\@tempboxa must have zero depth.) +% #1 = attempted framing command, if no split +% #2 = framing command if split +% First iteration: Try to fit with \FrameCommand. If it does not fit, +% split for \FirstFrameCommand. +% Later iteration: Try to fit with \LastFrameCommand. If it does not +% fit, split for \MidFrameCommand. +\def\fb@put@frame#1#2{\relax + \ifdim\pagegoal=\maxdimen \pagegoal\vsize \fi +| \message{=============== Entering putframe ====================^^J +| \pagegoal=\the\pagegoal, \pagetotal=\the\pagetotal. }% + \ifinner + \fb@putboxa#1% + \fb@afterframe + \else + \dimen@\pagegoal \advance\dimen@-\pagetotal % natural space left on page + \ifdim\dimen@<2\baselineskip % Too little room on page +| \message{Page has only \the\dimen@\space room left; eject. }% + \eject \fb@adjheight \fb@put@frame#1#2% + \else % there's appreciable room left on the page + \fb@sizeofframe#1% +| \message{\string\pagetotal=\the\pagetotal, +| \string\pagegoal=\the\pagegoal, +| \string\pagestretch=\the\pagestretch, +| \string\pageshrink=\the\pageshrink, +| \string\fb@frh=\the\fb@frh. \space} +| \message{^^JBox of size \the\ht\@tempboxa\space}% + \begingroup % temporarily set \dimen@ to be... + \advance\dimen@.8\pageshrink % maximum space available on page + \advance\dimen@-\fb@frh\relax % max space available for frame's contents +%%% LOOKS SUBTRACTED AND ADDED, SO DOUBLE ACCOUNTING! + \expandafter\endgroup + % expand \ifdim, then restore \dimen@ to real room left on page + \ifdim\dimen@>\ht\@tempboxa % whole box does fit +| \message{fits in \the\dimen@. }% + % ToDo: Change this to use vsplit anyway to capture the marks + % MERGE THIS WITH THE else CLAUSE!!! + \fb@putboxa#1% + \fb@afterframe + \else % box must be split +| \message{must be split to fit in \the\dimen@. }% + % update frame measurement to use \FirstFrameCommand or \MidFrameCommand + \fb@sizeofframe#2% + \setbox\@tempboxa\vbox{% simulate frame and flexiblity of the page: + \vskip \fb@frh \@plus\pagestretch \@minus.8\pageshrink + \kern137sp\kern-137sp\penalty-30 + \unvbox\@tempboxa}% + \edef\fb@resto@set{\boxmaxdepth\the\boxmaxdepth + \splittopskip\the\splittopskip}% + \boxmaxdepth\z@ \splittopskip\z@ +| \message{^^JPadded box of size \the\ht\@tempboxa\space split to \the\dimen@}% + % Split box here + \setbox\tw@\vsplit\@tempboxa to\dimen@ +| \toks99\expandafter{\splitfirstmark}% +| \toks98\expandafter{\splitbotmark}% +| \message{Marks are: \the\toks99, \the\toks98. }% + \setbox\tw@\vbox{\unvbox\tw@}% natural-sized +| \message{Natural height of split box is \the\ht\tw@, leaving +| \the\ht\@tempboxa\space remainder. }% + % If the split-to size > (\vsize-\topskip), then set box to full size. + \begingroup + \advance\dimen@\topskip + \expandafter\endgroup + \ifdim\dimen@>\pagegoal +| \message{Frame is big -- Use up the full column. }% + \dimen@ii\pagegoal + \advance\dimen@ii -\topskip + \advance\dimen@ii \FrameHeightAdjust\relax + \else % suspect this is implemented incorrectly: + % If the split-to size > feasible room_on_page, rebox it smaller. + \advance\dimen@.8\pageshrink + \ifdim\ht\tw@>\dimen@ +| \message{Box too tall; rebox it to \the\dimen@. }% + \dimen@ii\dimen@ + \else % use natural size + \dimen@ii\ht\tw@ + \fi + \fi + % Re-box contents to desired size \dimen@ii + \advance\dimen@ii -\fb@frh + \setbox\tw@\vbox to\dimen@ii \bgroup + % remove simulated frame and page flexibility: + \vskip -\fb@frh \@plus-\pagestretch \@minus-.8\pageshrink + \unvbox\tw@ \unpenalty\unpenalty + \ifdim\lastkern=-137sp % whole box went to next page +| \message{box split at beginning! }% + % need work here??? + \egroup \fb@resto@set \eject % (\vskip for frame size was discarded) + \fb@adjheight + \fb@put@frame#1#2% INSERTED ??? + \else % Got material split off at the head + \egroup \fb@resto@set + \ifvoid\@tempboxa % it all fit after all +| \message{box split at end! }% + \setbox\@tempboxa\box\tw@ + \fb@putboxa#1% + \fb@afterframe + \else % it really did split +| \message{box split as expected. Its reboxed height is \the\ht\tw@. }% + \ifdim\wd\tw@>\z@ + \wd\tw@\wd\@tempboxa + \centerline{#2{\box\tw@}}% ??? \centerline bad idea + \else +| \message{Zero width means likely blank. Don't frame it (guess)}% + \box\tw@ + \fi + \hrule \@height\z@ \@width\hsize + \eject + \fb@adjheight + \fb@put@frame\LastFrameCommand\MidFrameCommand + \fi\fi\fi\fi\fi +} + +\def\fb@putboxa#1{% + \ifvoid\@tempboxa + \PackageWarning{framed}{Boxa is void -- discard it. }% + \else +| \message{Frame and place boxa. }% +| %{\showoutput\showbox\@tempboxa}% + \centerline{#1{\box\@tempboxa}}% + \fi +} + +\def\fb@afterframe{% + \nointerlineskip \null %{\showoutput \showlists} + \penalty-30 \vskip\OuterFrameSep \relax +} + +% measure width and height added by frame (#1 = frame command) +% call results \fb@frw and \fb@frh +% todo: a mechanism to handle wide frame titles +\newdimen\fb@frw +\newdimen\fb@frh +\def\fb@sizeofframe#1{\begingroup + \setbox\z@\vbox{\vskip-5in \hbox{\hskip-5in + #1{\hbox{\vrule \@height 4.7in \@depth.3in \@width 5in}}}% + \vskip\z@skip}% +| \message{Measuring frame addition for \string#1 in \@currenvir\space +| gives ht \the\ht\z@\space and wd \the\wd\z@. }% +| %{\showoutput\showbox\z@}% + \global\fb@frw\wd\z@ \global\fb@frh\ht\z@ + \endgroup +} + +\def\fb@adjheight{% + \vbox to\FrameHeightAdjust{}% get proper baseline skip from above. + \penalty\@M \nointerlineskip + \vskip-\FrameHeightAdjust + \penalty\@M} % useful for tops of pages + +\edef\zero@glue{\the\z@skip} + +\catcode`\|=\FrameRestore + +% Provide configuration commands: +\providecommand\FrameCommand{% + \setlength\fboxrule{\FrameRule}\setlength\fboxsep{\FrameSep}% + \fbox} +\@ifundefined{FrameRule}{\newdimen\FrameRule \FrameRule=\fboxrule}{} +\@ifundefined{FrameSep} {\newdimen\FrameSep \FrameSep =3\fboxsep}{} +\providecommand\FirstFrameCommand{\FrameCommand} +\providecommand\MidFrameCommand{\FrameCommand} +\providecommand\LastFrameCommand{\FrameCommand} + +% Height of frame above first baseline when frame starts a page: +\providecommand\FrameHeightAdjust{6pt} + +% \FrameRestore has parts of \@parboxrestore, performing a similar but +% less complete restoration of the default layout. See how it is used in +% the "settings" argument of \MakeFrame. Though not a parameter, \hsize +% should be set to the desired total line width available inside the +% frame before invoking \FrameRestore. +\def\FrameRestore{% + \let\if@nobreak\iffalse + \let\if@noskipsec\iffalse + \let\-\@dischyph + \let\'\@acci\let\`\@accii\let\=\@acciii + % \message{FrameRestore: + % \@totalleftmargin=\the \@totalleftmargin, + % \rightmargin=\the\rightmargin, + % \@listdepth=\the\@listdepth. }% + % Test if we are in a list (or list-like paragraph) + \ifnum \ifdim\@totalleftmargin>\z@ 1\fi + \ifdim\rightmargin>\z@ 1\fi + \ifnum\@listdepth>\z@ 1\fi 0>\z@ + % \message{In a list: \linewidth=\the\linewidth, \@totalleftmargin=\the\@totalleftmargin, + % \parshape=\the\parshape, \columnwidth=\the\columnwidth, \hsize=\the\hsize, + % \labelwidth=\the\labelwidth. }% + \@setminipage % snug fit around the item. I would like this to be non-global. + % Now try to propageate changes of width from \hsize to list parameters. + % This is deficient, but a more advanced way to indicate modification to text + % dimensions is not (yet) provided; in particular, no separate left/right + % adjustment. + \advance\linewidth-\columnwidth \advance\linewidth\hsize + \parshape\@ne \@totalleftmargin \linewidth + \else % Not in list + \linewidth=\hsize + %\message{No list, set \string\linewidth=\the\hsize. }% + \fi + \sloppy +} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/ThirdParty/Ert/python/docs/latex/needspace.sty b/ThirdParty/Ert/python/docs/latex/needspace.sty new file mode 100644 index 0000000000..113d87216f --- /dev/null +++ b/ThirdParty/Ert/python/docs/latex/needspace.sty @@ -0,0 +1,35 @@ + +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{needspace}[2010/09/12 v1.3d reserve vertical space] + +\newcommand{\needspace}[1]{% + \begingroup + \setlength{\dimen@}{#1}% + \vskip\z@\@plus\dimen@ + \penalty -100\vskip\z@\@plus -\dimen@ + \vskip\dimen@ + \penalty 9999% + \vskip -\dimen@ + \vskip\z@skip % hide the previous |\vskip| from |\addvspace| + \endgroup +} + +\newcommand{\Needspace}{\@ifstar{\@sneedsp@}{\@needsp@}} + +\newcommand{\@sneedsp@}[1]{\par \penalty-100\begingroup + \setlength{\dimen@}{#1}% + \dimen@ii\pagegoal \advance\dimen@ii-\pagetotal + \ifdim \dimen@>\dimen@ii + \break + \fi\endgroup} + +\newcommand{\@needsp@}[1]{\par \penalty-100\begingroup + \setlength{\dimen@}{#1}% + \dimen@ii\pagegoal \advance\dimen@ii-\pagetotal + \ifdim \dimen@>\dimen@ii + \ifdim \dimen@ii>\z@ + \vfil + \fi + \break + \fi\endgroup} + diff --git a/ThirdParty/Ert/python/docs/latex/tabulary.sty b/ThirdParty/Ert/python/docs/latex/tabulary.sty new file mode 100644 index 0000000000..5660cdfbbe --- /dev/null +++ b/ThirdParty/Ert/python/docs/latex/tabulary.sty @@ -0,0 +1,451 @@ +%% +%% This is file `tabulary.sty', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% tabulary.dtx (with options: `package') +%% DRAFT VERSION +%% +%% File `tabulary.dtx'. +%% Copyright (C) 1995 1996 2003 2008 David Carlisle +%% This file may be distributed under the terms of the LPPL. +%% See 00readme.txt for details. +%% +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{tabulary} + [2014/06/11 v0.10 tabulary package (DPC)] +\RequirePackage{array} +\catcode`\Z=14 +\DeclareOption{debugshow}{\catcode`\Z=9\relax} +\ProcessOptions +\def\arraybackslash{\let\\=\@arraycr} +\def\@finalstrut#1{% + \unskip\ifhmode\nobreak\fi\vrule\@width\z@\@height\z@\@depth\dp#1} +\newcount\TY@count +\def\tabulary{% + \let\TY@final\tabular + \let\endTY@final\endtabular + \TY@tabular} +\def\TY@tabular#1{% + \edef\TY@{\@currenvir}% + {\ifnum0=`}\fi + \@ovxx\TY@linewidth + \@ovyy\TY@tablewidth + \count@\z@ + \@tempswatrue + \@whilesw\if@tempswa\fi{% + \advance\count@\@ne + \expandafter\ifx\csname TY@F\the\count@\endcsname\relax + \@tempswafalse + \else + \expandafter\let\csname TY@SF\the\count@\expandafter\endcsname + \csname TY@F\the\count@\endcsname + \global\expandafter\let\csname TY@F\the\count@\endcsname\relax + \expandafter\let\csname TY@S\the\count@\expandafter\endcsname + \csname TY@\the\count@\endcsname + \fi}% + \global\TY@count\@ne + \TY@width\xdef{0pt}% + \global\TY@tablewidth\z@ + \global\TY@linewidth#1\relax +Z\message{^^J^^JTable^^J% +Z Target Width: \the\TY@linewidth^^J% +Z \string\tabcolsep: \the\tabcolsep\space +Z \string\arrayrulewidth: \the\arrayrulewidth\space +Z \string\doublerulesep: \the\doublerulesep^^J% +Z \string\tymin: \the\tymin\space +Z \string\tymax: \the\tymax^^J}% + \let\@classz\TY@classz + \let\verb\TX@verb + \toks@{}\TY@get@body} +\let\TY@@mkpream\@mkpream +\def\TY@mkpream{% + \def\@addamp{% + \if@firstamp \@firstampfalse \else + \global\advance\TY@count\@ne + \edef\@preamble{\@preamble &}\fi + \TY@width\xdef{0pt}}% + \def\@acol{% + \TY@subwidth\col@sep + \@addtopreamble{\hskip\col@sep}}% + \let\@arrayrule\TY@arrayrule + \let\@classvi\TY@classvi + \def\@classv{\save@decl + \expandafter\NC@ecs\@nextchar\extracolsep{}\extracolsep\@@@ + \sbox\z@{\d@llarbegin\@nextchar\d@llarend}% + \TY@subwidth{\wd\z@}% + \@addtopreamble{\d@llarbegin\the@toks\the\count@\relax\d@llarend}% + \prepnext@tok}% + \global\let\@mkpream\TY@@mkpream + \TY@@mkpream} +\def\TY@arrayrule{% + \TY@subwidth\arrayrulewidth + \@addtopreamble \vline} +\def\TY@classvi{\ifcase \@lastchclass + \@acol \or + \TY@subwidth\doublerulesep + \@addtopreamble{\hskip \doublerulesep}\or + \@acol \or + \@classvii + \fi} +\def\TY@tab{% + \setbox\z@\hbox\bgroup + \let\[$\let\]$% + \let\equation$\let\endequation$% + \col@sep\tabcolsep + \let\d@llarbegin\begingroup\let\d@llarend\endgroup + \let\@mkpream\TY@mkpream + \def\multicolumn##1##2##3{\multispan##1\relax}% + \CT@start\TY@tabarray} +\def\TY@tabarray{\@ifnextchar[{\TY@array}{\@array[t]}} +\def\TY@array[#1]{\@array[t]} +\def\TY@width#1{% + \expandafter#1\csname TY@\the\TY@count\endcsname} +\def\TY@subwidth#1{% + \TY@width\dimen@ + \advance\dimen@-#1\relax + \TY@width\xdef{\the\dimen@}% + \global\advance\TY@linewidth-#1\relax} +\def\endtabulary{% + \gdef\@halignto{}% + \expandafter\TY@tab\the\toks@ + \crcr\omit + {\xdef\TY@save@row{}% + \loop + \advance\TY@count\m@ne + \ifnum\TY@count>\z@ + \xdef\TY@save@row{\TY@save@row&\omit}% + \repeat}\TY@save@row + \endarray\global\setbox1=\lastbox\setbox0=\vbox{\unvbox1 + \unskip\global\setbox1=\lastbox}\egroup + \dimen@\TY@linewidth + \divide\dimen@\TY@count + \ifdim\dimen@<\tymin + \TY@warn{tymin too large (\the\tymin), resetting to \the\dimen@}% + \tymin\dimen@ + \fi + \setbox\tw@=\hbox{\unhbox\@ne + \loop +\@tempdima=\lastskip +\ifdim\@tempdima>\z@ +Z \message{ecs=\the\@tempdima^^J}% + \global\advance\TY@linewidth-\@tempdima +\fi + \unskip + \setbox\tw@=\lastbox + \ifhbox\tw@ +Z \message{Col \the\TY@count: Initial=\the\wd\tw@\space}% + \ifdim\wd\tw@>\tymax + \wd\tw@\tymax +Z \message{> max\space}% +Z \else +Z \message{ \@spaces\space}% + \fi + \TY@width\dimen@ +Z \message{\the\dimen@\space}% + \advance\dimen@\wd\tw@ +Z \message{Final=\the\dimen@\space}% + \TY@width\xdef{\the\dimen@}% + \ifdim\dimen@<\tymin +Z \message{< tymin}% + \global\advance\TY@linewidth-\dimen@ + \expandafter\xdef\csname TY@F\the\TY@count\endcsname + {\the\dimen@}% + \else + \expandafter\ifx\csname TY@F\the\TY@count\endcsname\z@ +Z \message{***}% + \global\advance\TY@linewidth-\dimen@ + \expandafter\xdef\csname TY@F\the\TY@count\endcsname + {\the\dimen@}% + \else +Z \message{> tymin}% + \global\advance\TY@tablewidth\dimen@ + \global\expandafter\let\csname TY@F\the\TY@count\endcsname + \maxdimen + \fi\fi + \advance\TY@count\m@ne + \repeat}% + \TY@checkmin + \TY@checkmin + \TY@checkmin + \TY@checkmin + \TY@count\z@ + \let\TY@box\TY@box@v + {\expandafter\TY@final\the\toks@\endTY@final}% + \count@\z@ + \@tempswatrue + \@whilesw\if@tempswa\fi{% + \advance\count@\@ne + \expandafter\ifx\csname TY@SF\the\count@\endcsname\relax + \@tempswafalse + \else + \global\expandafter\let\csname TY@F\the\count@\expandafter\endcsname + \csname TY@SF\the\count@\endcsname + \global\expandafter\let\csname TY@\the\count@\expandafter\endcsname + \csname TY@S\the\count@\endcsname + \fi}% + \TY@linewidth\@ovxx + \TY@tablewidth\@ovyy + \ifnum0=`{\fi}} +\def\TY@checkmin{% + \let\TY@checkmin\relax +\ifdim\TY@tablewidth>\z@ + \Gscale@div\TY@ratio\TY@linewidth\TY@tablewidth + \ifdim\TY@tablewidth <\TY@linewidth + \def\TY@ratio{1}% + \fi +\else + \TY@warn{No suitable columns!}% + \def\TY@ratio{1}% +\fi +\count@\z@ +Z \message{^^JLine Width: \the\TY@linewidth, +Z Natural Width: \the\TY@tablewidth, +Z Ratio: \TY@ratio^^J}% +\@tempdima\z@ +\loop +\ifnum\count@<\TY@count +\advance\count@\@ne + \ifdim\csname TY@F\the\count@\endcsname>\tymin + \dimen@\csname TY@\the\count@\endcsname + \dimen@\TY@ratio\dimen@ + \ifdim\dimen@<\tymin +Z \message{Column \the\count@\space ->}% + \global\expandafter\let\csname TY@F\the\count@\endcsname\tymin + \global\advance\TY@linewidth-\tymin + \global\advance\TY@tablewidth-\csname TY@\the\count@\endcsname + \let\TY@checkmin\TY@@checkmin + \else + \expandafter\xdef\csname TY@F\the\count@\endcsname{\the\dimen@}% + \advance\@tempdima\csname TY@F\the\count@\endcsname + \fi + \fi +Z \dimen@\csname TY@F\the\count@\endcsname\message{\the\dimen@, }% +\repeat +Z \message{^^JTotal:\the\@tempdima^^J}% +} +\let\TY@@checkmin\TY@checkmin +\newdimen\TY@linewidth +\def\tyformat{\everypar{{\nobreak\hskip\z@skip}}} +\newdimen\tymin +\tymin=10pt +\newdimen\tymax +\tymax=2\textwidth +\def\@testpach{\@chclass + \ifnum \@lastchclass=6 \@ne \@chnum \@ne \else + \ifnum \@lastchclass=7 5 \else + \ifnum \@lastchclass=8 \tw@ \else + \ifnum \@lastchclass=9 \thr@@ + \else \z@ + \ifnum \@lastchclass = 10 \else + \edef\@nextchar{\expandafter\string\@nextchar}% + \@chnum + \if \@nextchar c\z@ \else + \if \@nextchar l\@ne \else + \if \@nextchar r\tw@ \else + \if \@nextchar C7 \else + \if \@nextchar L8 \else + \if \@nextchar R9 \else + \if \@nextchar J10 \else + \z@ \@chclass + \if\@nextchar |\@ne \else + \if \@nextchar !6 \else + \if \@nextchar @7 \else + \if \@nextchar <8 \else + \if \@nextchar >9 \else + 10 + \@chnum + \if \@nextchar m\thr@@\else + \if \@nextchar p4 \else + \if \@nextchar b5 \else + \z@ \@chclass \z@ \@preamerr \z@ \fi \fi \fi \fi\fi \fi \fi\fi \fi + \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi} +\def\TY@classz{% + \@classx + \@tempcnta\count@ + \ifx\TY@box\TY@box@v + \global\advance\TY@count\@ne + \fi + \let\centering c% + \let\raggedright\noindent + \let\raggedleft\indent + \let\arraybackslash\relax + \prepnext@tok + \ifnum\@chnum<4 + \global\expandafter\let\csname TY@F\the\TY@count\endcsname\z@ + \fi + \ifnum\@chnum=6 + \global\expandafter\let\csname TY@F\the\TY@count\endcsname\z@ + \fi + \@addtopreamble{% + \ifcase\@chnum + \hfil \d@llarbegin\insert@column\d@llarend \hfil \or + \kern\z@ + \d@llarbegin \insert@column \d@llarend \hfil \or + \hfil\kern\z@ \d@llarbegin \insert@column \d@llarend \or + $\vcenter\@startpbox{\@nextchar}\insert@column \@endpbox $\or + \vtop \@startpbox{\@nextchar}\insert@column \@endpbox \or + \vbox \@startpbox{\@nextchar}\insert@column \@endpbox \or + \d@llarbegin \insert@column \d@llarend \or% dubious "s" case + \TY@box\centering\or + \TY@box\raggedright\or + \TY@box\raggedleft\or + \TY@box\relax + \fi}\prepnext@tok} +\def\TY@box#1{% + \ifx\centering#1% + \hfil \d@llarbegin\insert@column\d@llarend \hfil \else + \ifx\raggedright#1% + \kern\z@%<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< + \d@llarbegin \insert@column \d@llarend \hfil \else + \ifx\raggedleft#1% + \hfil\kern\z@ \d@llarbegin \insert@column \d@llarend \else + \ifx\relax#1% + \d@llarbegin \insert@column \d@llarend + \fi \fi \fi \fi} +\def\TY@box@v#1{% + \vtop \@startpbox{\csname TY@F\the\TY@count\endcsname}% + #1\arraybackslash\tyformat + \insert@column\@endpbox} +\newdimen\TY@tablewidth +\def\Gscale@div#1#2#3{% + \setlength\dimen@{#3}% + \ifdim\dimen@=\z@ + \PackageError{graphics}{Division by 0}\@eha + \dimen@#2% + \fi + \edef\@tempd{\the\dimen@}% + \setlength\dimen@{#2}% + \count@65536\relax + \ifdim\dimen@<\z@ + \dimen@-\dimen@ + \count@-\count@ + \fi + \loop + \ifdim\dimen@<8192\p@ + \dimen@\tw@\dimen@ + \divide\count@\tw@ + \repeat + \dimen@ii=\@tempd\relax + \divide\dimen@ii\count@ + \divide\dimen@\dimen@ii + \edef#1{\strip@pt\dimen@}} +\long\def\TY@get@body#1\end + {\toks@\expandafter{\the\toks@#1}\TY@find@end} +\def\TY@find@end#1{% + \def\@tempa{#1}% + \ifx\@tempa\TY@\def\@tempa{\end{#1}}\expandafter\@tempa + \else\toks@\expandafter + {\the\toks@\end{#1}}\expandafter\TY@get@body\fi} +\def\TY@warn{% + \PackageWarning{tabulary}} +\catcode`\Z=11 +\AtBeginDocument{ +\@ifpackageloaded{colortbl}{% +\expandafter\def\expandafter\@mkpream\expandafter#\expandafter1% + \expandafter{% + \expandafter\let\expandafter\CT@setup\expandafter\relax + \expandafter\let\expandafter\CT@color\expandafter\relax + \expandafter\let\expandafter\CT@do@color\expandafter\relax + \expandafter\let\expandafter\color\expandafter\relax + \expandafter\let\expandafter\CT@column@color\expandafter\relax + \expandafter\let\expandafter\CT@row@color\expandafter\relax + \expandafter\let\expandafter\CT@cell@color\expandafter\relax + \@mkpream{#1}} +\let\TY@@mkpream\@mkpream +\def\TY@classz{% + \@classx + \@tempcnta\count@ + \ifx\TY@box\TY@box@v + \global\advance\TY@count\@ne + \fi + \let\centering c% + \let\raggedright\noindent + \let\raggedleft\indent + \let\arraybackslash\relax + \prepnext@tok +\expandafter\CT@extract\the\toks\@tempcnta\columncolor!\@nil + \ifnum\@chnum<4 + \global\expandafter\let\csname TY@F\the\TY@count\endcsname\z@ + \fi + \ifnum\@chnum=6 + \global\expandafter\let\csname TY@F\the\TY@count\endcsname\z@ + \fi + \@addtopreamble{% + \setbox\z@\hbox\bgroup\bgroup + \ifcase\@chnum + \hskip\stretch{.5}\kern\z@ + \d@llarbegin\insert@column\d@llarend\hskip\stretch{.5}\or + \kern\z@%<<<<<<<<<<<<<<<<<<<<<<<<<<< + \d@llarbegin \insert@column \d@llarend \hfill \or + \hfill\kern\z@ \d@llarbegin \insert@column \d@llarend \or + $\vcenter\@startpbox{\@nextchar}\insert@column \@endpbox $\or + \vtop \@startpbox{\@nextchar}\insert@column \@endpbox \or + \vbox \@startpbox{\@nextchar}\insert@column \@endpbox \or + \d@llarbegin \insert@column \d@llarend \or% dubious s case + \TY@box\centering\or + \TY@box\raggedright\or + \TY@box\raggedleft\or + \TY@box\relax + \fi + \egroup\egroup +\begingroup + \CT@setup + \CT@column@color + \CT@row@color + \CT@cell@color + \CT@do@color +\endgroup + \@tempdima\ht\z@ + \advance\@tempdima\minrowclearance + \vrule\@height\@tempdima\@width\z@ +\unhbox\z@ +}\prepnext@tok}% + \def\TY@arrayrule{% + \TY@subwidth\arrayrulewidth + \@addtopreamble{{\CT@arc@\vline}}}% + \def\TY@classvi{\ifcase \@lastchclass + \@acol \or + \TY@subwidth\doublerulesep + \ifx\CT@drsc@\relax + \@addtopreamble{\hskip\doublerulesep}% + \else + \@addtopreamble{{\CT@drsc@\vrule\@width\doublerulesep}}% + \fi\or + \@acol \or + \@classvii + \fi}% +}{% +\let\CT@start\relax +} +} +{\uccode`\*=`\ % +\uppercase{\gdef\TX@verb{% + \leavevmode\null\TX@vwarn + {\ifnum0=`}\fi\ttfamily\let\\\ignorespaces + \@ifstar{\let~*\TX@vb}{\TX@vb}}}} +\def\TX@vb#1{\def\@tempa##1#1{\toks@{##1}\edef\@tempa{\the\toks@}% + \expandafter\TX@v\meaning\@tempa\\ \\\ifnum0=`{\fi}}\@tempa!} +\def\TX@v#1!{\afterassignment\TX@vfirst\let\@tempa= } +\begingroup +\catcode`\*=\catcode`\# +\catcode`\#=12 +\gdef\TX@vfirst{% + \if\@tempa#% + \def\@tempb{\TX@v@#}% + \else + \let\@tempb\TX@v@ + \if\@tempa\space~\else\@tempa\fi + \fi + \@tempb} +\gdef\TX@v@*1 *2{% + \TX@v@hash*1##\relax\if*2\\\else~\expandafter\TX@v@\fi*2} +\gdef\TX@v@hash*1##*2{*1\ifx*2\relax\else#\expandafter\TX@v@hash\fi*2} +\endgroup +\def\TX@vwarn{% + \@warning{\noexpand\verb may be unreliable inside tabularx/y}% + \global\let\TX@vwarn\@empty} +\endinput +%% +%% End of file `tabulary.sty'. diff --git a/ThirdParty/Ert/python/docs/latex/titlesec.sty b/ThirdParty/Ert/python/docs/latex/titlesec.sty new file mode 100644 index 0000000000..ab4d0177cc --- /dev/null +++ b/ThirdParty/Ert/python/docs/latex/titlesec.sty @@ -0,0 +1,1349 @@ +% +--------------------------------------------------+ +% | Typeset titlesec.tex to get the documentation. | +% +--------------------------------------------------+ +% +% Copyright (c) 1998-2016 by Javier Bezos. +% All Rights Reserved. +% +% This file is part of the titlesec distribution release 2.10.1 +% ----------------------------------------------------------- +% +% It may be distributed and/or modified under the +% conditions of the LaTeX Project Public License, either version 1.3 +% of this license or (at your option) any later version. +% The latest version of this license is in +% http://www.latex-project.org/lppl.txt +% and version 1.3 or later is part of all distributions of LaTeX +% version 2003/12/01 or later. +% +% This work has the LPPL maintenance status "maintained". +% +% The Current Maintainer of this work is Javier Bezos. +% +% Notes +% ~~~~~ +% +% The following tags are used: +% ttl@ : the generic tag used through the style +% ttlh@ : a shape definition +% ttlf@ : a macro containing the title format +% ttls@ : id. the title space +% ttlp@ : page key related macros +% ttll@ : level number +% +% The ttlf@ and ttls@ contains data in the form {..}{..}. +% Perhaps in future releases they should be converted +% to a prop-like list, similar to that proposed by the +% latex team. +% +% Admittedly, the current implementation seems too +% complicated, but that's necessary in order to provide +% certain compatibility with the sections as defined by the +% used class. Other packages opt for providing the sections +% as defined by standard classes ignoring the class; for +% instance sectsty which does a simple task in a simple and +% nice way. However, that was not my goal. +% +% Release +% ~~~~~~~ + +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{titlesec}[2016/03/15 v2.10.1 Sectioning titles] + +% Initialization +% ~~~~~~~~~~~~~~ + +\newif\ifttl@ps +\ttl@psfalse + +% The \ttl@label switch is used when printing the label in titles. +% A numberless variant makes it to true. +% There is a \ttl@toclabel as well, which is true iff the +% title is numbered; used in toc entries (except default part +% and chapter) and marks (only in titlesec pagestyles). + +\newif\ifttl@label +\newif\ifttl@toclabel + +\newbox\ttl@box + +% A provision for the report style: + +\@ifundefined{if@mainmatter} + {\let\if@mainmatter\iftrue}{} + +\@ifundefined{if@openright} + {\let\if@openright\iftrue}{} + +% and the ams styles as well + +\@ifundefined{@chapapp} + {\let\@chapapp\chaptername}{} + +\def\ttl@trylist{\ttl@try{}} + +\def\ttl@getkeys#1#2{% + \if\expandafter @\@gobble#1@\@empty + \edef\ttl@b{\expandafter\@gobble\string#1}% + \let\ttl@a\ttl@b + \else + \makeatletter + \edef\ttl@d{% + \noexpand\input{ttlkeys.def}% + \catcode`\noexpand\@=\the\catcode`\@}% + \ttl@d + \ttl@getkeys{#1}{#2}% + \fi} + +% A more meaningful error for \@notdefinable + +\expandafter\AtEndOfPackage\expandafter{\expandafter + \gdef\expandafter\@notdefinable\expandafter{\@notdefinable}} + +\def\@notdefinable{% + \PackageError{titlesec}% + {Incompatible package}% + {Titlesec cannot continue defining its own macros + because\MessageBreak + \@backslashchar\reserved@a\space is already used by other package, + the class\MessageBreak + or the document.}} + +% +-----------------+ +% | C L A S S E S | +% +-----------------+ + +\def\ttl@useclass#1#2{% + \@ifstar + {\ttl@labelfalse#1{#2}[]}% + {\ttl@labeltrue\@dblarg{#1{#2}}}} + +\def\ttl@straightclass{\ttl@useclass\ttl@straight@i} +\def\ttl@partclass{\ttl@useclass\ttl@part@i} +\def\ttl@topclass{\ttl@useclass\ttl@top@i} +\def\ttl@pageclass{\ttl@useclass\ttl@page@i} + +% Here \scantokens is used to make sure the unescaped name +% has `letters' and no `others'. Mainly for hyperref, so there +% should be no problems. + +\newcommand\titleclass[1]{% + \edef\ttl@a{\expandafter\@gobble\string#1}% + \ifx\scantokens\@undefined\else + \scantokens\expandafter{\expandafter + \def\expandafter\ttl@a\expandafter{\ttl@a}}% + \fi + \@ifnextchar[{\@tempswatrue\ttl@class@i{#1}}% + {\@tempswafalse\ttl@class@ii{#1}}} + +\def\ttl@class@i#1[#2]{% + \@namedef{ttll@\ttl@a}{#2}% + \expandafter\providecommand\csname\ttl@a title\endcsname{}%%%% + \@ifundefined{ttl@toplevel}{}% + {\expandafter\let\csname ttlss@\ttl@a\expandafter\endcsname + \csname ttlss@\ttl@toplevel\endcsname}% + \edef\ttl@toplevel{\ttl@a}% + \ttl@class@ii{#1}} + +\def\ttl@class@ii#1#2{% + \@ifundefined{ttl@#2class}% + {\PackageError{titlesec}{Unknown sectioning class}% + {Valid names are top, page and straight}}% + {\expandafter\let\csname ttl@compat\ttl@a\endcsname\relax + \@ifundefined{\ttl@a mark}% + {\@namedef{\ttl@a mark}{\@gobble}}% + {}% + \edef#1{% + \expandafter\noexpand\csname ttl@#2class\endcsname{\ttl@a}}}% + \if@tempswa + \expandafter\@gobble + \else + \expandafter\@firstofone + \fi + {\@ifnextchar[% + {\ttl@class@iii}% + {\@ifundefined{ttll@\ttl@a}% + {\PackageError{titlesec}{Unknown sectioning level}% + {\string\titleclass\space with no optional arguments\MessageBreak + only changes the class of an *existing* level}}}}} + +\def\ttl@class@iii[#1]{% + \edef\ttl@b{\expandafter\@gobble\string#1}% + \expandafter\let\csname ttlss@\ttl@a\expandafter\endcsname + \csname ttlss@\ttl@b\endcsname + \expandafter\edef\csname ttlss@\ttl@b\endcsname{\ttl@a}% + \let\ttl@a\ttl@toplevel + \count@\csname ttll@\ttl@toplevel\endcsname + \ttl@class@iv} + +\def\ttl@class@iv{% + \@ifundefined{ttlss@\ttl@a}{}% + {\advance\count@\@ne + \edef\ttl@a{\csname ttlss@\ttl@a\endcsname}% + \expandafter\edef\csname ttll@\ttl@a\endcsname{\the\count@}% + \ttl@class@iv}} + +% Typesetting Classes: General tools +% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +% The following command handles the *n spacing +% Some tricks are necessary to multiply a +% skip by a non integer number + +\newskip\beforetitleunit +\beforetitleunit=1ex\@plus.3ex\@minus.06ex +\newskip\aftertitleunit +\aftertitleunit=1ex\@plus.1ex + +\newdimen\ttl@plus +\newdimen\ttl@minus + +\def\ttl@assign#1{% + \@ifstar + {\ttl@assign@i{#1}}% + {\ttl@assign@d{#1}}} + +\def\ttl@assign@i#1#2\relax#3{% + \ttl@plus\z@ + \ttl@minus\z@ + \afterassignment\ttl@assign@ii + \dimen@\the#3, % <- space + #1 = #2\dimen@ + plus #2\ttl@plus + minus #2\ttl@minus} + +\def\ttl@assign@ii#1 {% <- space + \if#1,\else\afterassignment\ttl@assign@ii\fi + \csname ttl@\string#1\endcsname} + +\def\ttl@assign@d#1#2\relax#3{\setlength#1{#2}} + +% To be used with \v/vspace to make them calc-savvy + +\def\ttl@calc#1#2{% + {\setlength\@tempskipa{#2}% + #1\@tempskipa}} + +\def\ttl@calcneg#1#2{% + {\setlength\@tempskipa{#2}% + #1{-\@tempskipa}}} + +% Gets from ttls@ and passes the spacing parameters: + +\def\ttl@startargs#1#2{% Get the first arguments, with the spacing + \@ifundefined{ttlp@#2}% + {\let\ttl@key@page\@empty}% + {\ttlp@fetch{#2}}% + \begingroup + \def\ttl@b{ttls@#2}% + \edef\ttl@key@numberless{\ifttl@label//\else/*\fi}% + \def\ttl@a##1{\csname ttl@key@##1\endcsname}% Used as elt in try + \ttl@trylist + \xdef\ttl@b{\ttl@c}% + \endgroup + \ifx\ttl@b\@empty + \PackageError{titlesec}{Format/spacing not found}% + {I was unable to find the format corresponding to #2.\MessageBreak + Maybe you haven't set it with \string\titleformat\space and + \string\titlespacing} + \fi + \expandafter#1\ttl@b{#2}} + +% Used in ttl@select + +\def\ttl@savefn#1[#2]#3{% + \ifcase#1% + \footnotemark[#2]% + \gdef\ttl@fn{\footnotetext[#2]{#3}}% + \else + \footnotemark + \gdef\ttl@fn{\footnotetext{#3}}% + \fi} + +\def\ttl@nest@error{% + \PackageError{titlesec}{Nested titles}{Titles must not be nested}} + +\def\ttl@hmode@error{% + \PackageError{titlesec}{Entered in horizontal mode} + {The argument cannot contain horizontal material\MessageBreak + such as text, \string\noindent, \string\makebox, etc.}} + +% \ttl@select not only selects the right version to be +% used. It also take steps to ensure that a mark +% is not lost inside a box by saving it into \ttl@mk, +% which in turn is used by the sect and chap commands. + +\newif\ifttl@explicit + +\def\ttl@gmk#1{\gdef\ttl@mk{#1}} + +\def\ttl@select#1#2#3#4{% + \ttl@Hy@saveanchor + \global\let\ttl@mk\@empty % global because of rigidchapters + \global\let\ttl@fn\@empty + \begingroup + \if@inlabel\else % Keep item's \everypar + \everypar{\setbox\z@\lastbox\strut}% + \fi + \let\ttl@straight@i\ttl@nest@error + \let\ttl@top@i \ttl@nest@error + \let\ttl@part@i \ttl@nest@error + \let\ttl@page@i \ttl@nest@error + \let\ttl@newpage\newpage + \def\newpage{\ttl@savewrite\ttl@newpage}% + \def\markboth##1##2{\protect\ttl@gmk{\protect\markboth{##1}{##2}}}% + \def\markright##1{\protect\ttl@gmk{\protect\markright{##1}}}% + \def\@mkboth##1##2{\protect\ttl@gmk{\protect\@mkboth{##1}{##2}}}% + \def\footnote{\@ifnextchar[% + {\ttl@savefn\z@}{\ttl@savefn\@ne[]}}% + \edef\ttl@key@numberless{\ifttl@label//\else/*\fi}% + \def\ttl@b{ttlf@#1}% + \def\ttl@a##1{\csname ttl@key@##1\endcsname}% Used as elt in try + \ttl@trylist + \ifttl@explicit + \def\ttl@passexplicit{\ttl@case{#4}}% + \ttl@c{#4}{#2}{#3}{}% ttl@c is returned by ttl@try with ttlf@... + \else + \let\ttl@passexplicit\ttl@case + \ttl@c{#2}{#3}{#4}% ttl@c is returned by ttl@try with ttlf@... + \fi + \endgroup} + +\let\ttl@savewrite\@empty + +\def\ttl@finmarks{% + \ttl@savewrite + \ttl@mk % Contains a possible mark, returned by \ttl@select + \ttl@fn} % And a footnote + +\def\ttl@try#1{% + \edef\ttl@c{#1}% #1 is a list in the form \ttl@a{key}\ttl@a{key} + \@ifundefined{\ttl@b\ttl@c}{}{% + \edef\ttl@c{\expandafter\noexpand\csname\ttl@b\ttl@c\endcsname}% + \def\ttl@a##1{\csname ttl@extra@##1\endcsname}% + #1% + \let\ttl@try\@gobble}} % locally modified to `break' testings + +% \ttl@write writes marks and toc. tocdepth is taken care of when +% the toc is typesetted and not here. Used always through +% ttl@savewrite, which is reset to \@empty to avoid duplicated +% calls. + +\def\ttl@write#1#2{% + \ttl@blinemarks + \csname#1mark\endcsname{#2}% + \def\ttl@a{\protect\numberline{\@nameuse{the#1}}}% + \@nameuse{ttl@toc#1}% eg, \ttl@tocpart modifies \ttl@a + \ttl@addcontentsline{#1}{#2}% Depends on toctitles, uses \ttl@a + \ttl@elinemarks + \global\ttl@toclabelfalse + \global\let\ttl@savewrite\@empty} + +\newif\ifttl@premark % to be used in ttlps.def +\ttl@premarkfalse + +\def\ttl@premark#1#2{% + \protected@xdef\ttl@prevmarks{\ttl@marks}% + \ttl@blinemarks + \csname#1mark\endcsname{#2}% + \ttl@elinemarks + \gdef\ttl@prevmarks{\ttl@marks}} + +% Must be preceded by a default \ttl@savewrite, which is used +% in starred variants--\@empty in top and straight classes. +% In straight class, it is preceded by the setting of +% prev marks to provide a "fixed" top mark. Otherwise, +% the default prev mark (= curr mark) is used (restored +% after ttl@labelling in straight). This is the command +% to be hacked if you want to change the behaviour of +% starred variants. + +\def\ttl@labelling#1#2{% + \let\ttl@Hy@saveanchor\@empty + \ifttl@label % 1st - if star + \def\ttl@savewrite{\ttl@write{#1}{#2}}% + \@nameuse{ttl@#1label}% eg, sets if mainmatter in chapter. + \ifttl@label % 2nd - eg, if not main matter + \ifnum\@nameuse{ttll@#1}>\c@secnumdepth\relax + \ttl@labelfalse % 3rd - if too deep + \else + \ttl@Hy@refstepcounter{#1}% + \@nameuse{ttl@#1out}% + \fi + \fi + \fi + \let\ifttl@toclabel\ifttl@label + \ifx\ttl@savewrite\@empty\else % If marks + \ifttl@ps + \ifttl@premark + \global\ttl@premarkfalse + \else % if no \pretitlemark + \ttl@premark{#1}{#2}% + \fi + \fi + \ifttl@label\else\ttl@Hy@steplink{#1}\fi + \fi} + +% Executed by ttl@labelling if the name of section is chapter: + +\def\ttl@chapterlabel{\if@mainmatter\else\ttl@labelfalse\fi} + +% Executed by ttl@labelling if chapter has a number. Note +% you can define messages for other sectioning levels (eg, +% \ttl@sectionout). + +\def\ttl@chapterout{\typeout{\chaptertitlename\space\thechapter.}} + +% Straight class +% ~~~~~~~~~~~~~ +% Default for nobottomtitles. Changed by nobottomtitles* + +\def\ttl@addstretch{\advance\@tempskipa-\pagestretch} + +% 1:name 2:level 3:indent 4:before 5:after 6:afind [7]:cap 8:title +% The second argument of ttl@sect is the level, which +% is empty if the star version is used. In this case +% neither the toc nor the marks are written. + +\def\ttl@straight@i#1[#2]#3{% + \def\@currentlabelname{#2}% for nameref + \gdef\ttl@savemark{\csname#1mark\endcsname{#3}}% + \let\ttl@savewrite\@empty + \def\ttl@savetitle{#3}% + \gdef\thetitle{\csname the#1\endcsname}% + \if@noskipsec \leavevmode \fi + \par + \ttl@labelling{#1}{#2}% + \ttl@startargs\ttl@straight@ii{#1}{#3}} + +% 1:left 2:right 3:before 4:after 5:afterindent 6:name 7:title + +\def\ttl@straight@ii#1#2#3#4#5#6#7{% + \ttl@assign\@tempskipa#3\relax\beforetitleunit + \@ifundefined{ttl@ps@#6}{}% + {\PackageWarning{titlesec}{Page style in straight class ignored}}% + \if@nobreak + \ttl@titlespace{\@tempskipa}% + \else + \@ifundefined{#6break}% + {\addpenalty{\@secpenalty}}% + {\csname#6break\endcsname}% + \addvspace{\@tempskipa}% + \ifdim\bottomtitlespace<\z@ + \else + \begingroup + \@tempskipb\pagegoal + \@tempskipa\pagegoal + \ttl@addstretch % \relax if nobottomtitle* + \advance\@tempskipa-\bottomtitlespace\relax % not a register + \pagegoal\@tempskipa + \def\@textbottom{\vskip\z@\@plus.0001fil}% + \penalty9999 + \pagegoal\@tempskipb + \endgroup + \fi + \fi + \@afterindenttrue + \ifcase#5 \@afterindentfalse\fi + \ttl@assign\@tempskipb#4\relax\aftertitleunit + \ttl@select{#6}{#1}{#2}{#7}% + \ttl@finmarks + \@ifundefined{ttlp@#6}{}{\ttlp@write{#6}}% + \if@noskipsec + \global\@nobreakfalse + \everypar{% + \if@noskipsec + \global\@noskipsecfalse + \clubpenalty\@M + \hskip-\parindent + \begingroup + \@svsechd\unskip{\hspace{\@tempskipb}}% + \endgroup + \else + \clubpenalty\@clubpenalty\everypar{}% + \fi}% + \else + \par\nobreak + \vspace{\@tempskipb}% + \@afterheading + \fi + \ignorespaces} + +% Part class +% ~~~~~~~~~~ + +\providecommand\partmark[1]{\markboth{}{}} + +\def\ttl@part@i#1[#2]#3{% + \gdef\ttl@savemark{\csname#1mark\endcsname{#3}}% + \ifx\ttl@notocparts\@undefined + \def\ttl@savewrite{\ttl@write{#1}{#3}}% Not #2! + \else + \let\ttl@savewrite\@empty + \fi + \def\ttl@savetitle{#3}% + \ttl@labelling{#1}{#2}% + \ttl@startargs\ttl@part@ii{#1}{#3}} + +\def\ttl@part@ii#1#2#3#4#5#6#7{% + \ttl@assign\@tempskipa#3\relax\beforetitleunit + \vspace*{\@tempskipa}% + \@ifundefined{ttl@ps@#6}{}% + {\PackageWarning{titlesec}{Page style in part class ignored}}% + \global\@afterindenttrue + \ifcase#5 \global\@afterindentfalse \fi + \ttl@assign\@tempskipb#4\relax\aftertitleunit + \ttl@select{#6}{#1}{#2}{#7}% + \ttl@finmarks + \@ifundefined{ttlp@#6}{}{\ttlp@write{#6}}% + \par\nobreak + \vspace{\@tempskipb}% + \@afterheading} + +% Page class +% ~~~~~~~~~~ + +\def\ttl@page@i#1[#2]#3{% + \gdef\ttl@savemark{\csname#1mark\endcsname{#3}}% + \ifx\ttl@notocparts\@undefined + \def\ttl@savewrite{\ttl@write{#1}{#3}}% Not #2! + \else + \let\ttl@savewrite\@empty + \fi + \def\ttl@savetitle{#3}% + \ttl@labelling{#1}{#2}% + \ttl@startargs\ttl@page@ii{#1}{#3}} + +\def\ttl@page@ii#1#2#3#4#5#6#7{% + \ttl@assign\@tempskipa#3\relax\beforetitleunit + \if@openright + \cleardoublepage + \else + \clearpage + \fi + \@ifundefined{ttl@ps@#6}% + {\thispagestyle{plain}}% + {\thispagestyle{\@nameuse{ttl@ps@#6}}}% + \if@twocolumn + \onecolumn + \@tempswatrue + \else + \@tempswafalse + \fi + \vspace*{\@tempskipa}% + \@afterindenttrue + \ifcase#5 \@afterindentfalse\fi + \ttl@assign\@tempskipb#4\relax\aftertitleunit + \ttl@select{#6}{#1}{#2}{#7}% + \ttl@finmarks + \@ifundefined{ttlp@#6}{}{\ttlp@write{#6}}% + \vspace{\@tempskipb}% + \newpage + \if@twoside + \if@openright + \null + \@ifundefined{ttl@ps@#6}% + {\thispagestyle{empty}}% + {\thispagestyle{\@nameuse{ttl@ps@#6}}}% + \newpage + \fi + \fi + \if@tempswa + \twocolumn + \fi + \ignorespaces} + +% Top class and some makechapterhead stuff +% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +% +% \ttl@mkchap is the new make(s)chapterhead. + +\def\ttl@mkchap#1#2#3#4#5#6#7{% + \gdef\ttl@savemark{\csname#6mark\endcsname{#7}}% + \let\ttl@savewrite\@empty + \let\ttl@Hy@saveanchor\@empty + \@ifundefined{ttl@ps@#6}{}% + {\thispagestyle{\@nameuse{ttl@ps@#6}}}% + \let\ifttl@toclabel\ifttl@label + \ttl@mkchap@i{#1}{#2}{#3}{#4}{#5}{#6}{#7}} + +% But \ttl@mkchap@i is used by both makechapterhead and +% the top class. + +\def\ttl@mkchap@i#1#2#3#4#5#6#7{% + \ttl@assign\@tempskipa#3\relax\beforetitleunit + \vspace*{\@tempskipa}% + \global\@afterindenttrue + \ifcase#5 \global\@afterindentfalse\fi + \ttl@assign\@tempskipb#4\relax\aftertitleunit + \ttl@topmode{\@tempskipb}{% + \ttl@select{#6}{#1}{#2}{#7}}% + \ttl@finmarks % Outside the box! + \@ifundefined{ttlp@#6}{}{\ttlp@write{#6}}} + +\def\ttl@top@i#1[#2]#3{% + \gdef\ttl@savemark{\csname#1mark\endcsname{#3}}% + \let\ttl@savewrite\@empty + \def\ttl@savetitle{#3}% + \ttl@labelling{#1}{#2}% + \ttl@startargs\ttl@top@ii{#1}{#3}} + +\def\ttl@top@ii#1#2#3#4#5#6#7{% + \@ifundefined{#6break}% + {\if@openright + \cleardoublepage + \else + \clearpage + \fi}% + {\csname#6break\endcsname}% + \@ifundefined{ttl@ps@#6}% + {\thispagestyle{plain}}% + {\thispagestyle{\@nameuse{ttl@ps@#6}}}% + \global\@topnum\z@ + \@ifundefined{#6tolists}% + {\addtocontents{lof}{\protect\ttl@tocsep}% + \addtocontents{lot}{\protect\ttl@tocsep}} + {\@nameuse{#6tolists}}% + \if@twocolumn + \@topnewpage[\ttl@mkchap@i{#1}{#2}{#3}{#4}{#5}{#6}{#7}]% + \else + \ttl@mkchap@i{#1}{#2}{#3}{#4}{#5}{#6}{#7}% + \@afterheading + \fi + \ignorespaces} + + +% \def\ttl@noskipsectrue{% +% \if@noskipsec +% \PackageError{titlesec}{Invalid shape for top class}% +% {The selected shape only makes sense when merged into\MessageBreak +% a paragraph. That is impossible in the top class}% +% \else + +\newcommand\chaptertitlename{\@chapapp} +\def\ttl@tocsep{\addvspace{10\p@}} + +% +-----------------+ +% | S H A P E S | +% +-----------------+ +% +% % Reformatting Titles: Interface +% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +% The surrounding space is stored in a macro +% named \ttls@

whose content is +% {left}{right}{before}{after}{afterindent}. +% But if there is the page key, the name is +% \ttls@
/ + +\newcommand\titlespacing{% + \@ifstar{\ttl@spacing@i{\z@}}{\ttl@spacing@i{\@ne}}} + +\def\ttl@spacing@i#1#2#3#4#5{% + \ttl@getkeys{#2}{titlesec}% + \@ifnextchar[{% + \ttl@spacing@ii{#1}{#3}{#4}{#5}% + }{% + \ttl@spacing@ii{#1}{#3}{#4}{#5}[\z@]}} + +\def\ttl@spacing@ii#1#2#3#4[#5]{% + \expandafter\def\csname ttls@\ttl@a\endcsname + {{#2}{#5}{#3}{#4}{#1}}} + +% The section name is built in \ttl@a. +% The format is stored in a macro named \ttlf@
, +% or \ttlf@
/ if there is the page spec, +% or \ttlf@.../* if numberless is true +% whose content is +% \ttl@{format}{label}{sep}{before}{after} + +\newtoks\ttl@toksa + +\newcommand\titleformat{% + \@ifstar{\ttl@format@s}% + {\ttl@format@i}} + +\def\ttl@format@s#1#2{% + \edef\ttl@a{\expandafter\@gobble\string#1}% + \@ifundefined{ttlf@\ttl@a}% + {\PackageError{titlesec}{Not allowed in `easy' settings} + {The sectiong command you are trying to redefine\MessageBreak + is not handled by the starred variant (eg, \string\part)}}{} + \expandafter\expandafter\expandafter + \ttl@format@si\csname ttlf@\ttl@a \endcsname + {#2}} + +\def\ttl@format@si#1#2#3#4#5#6#7{% + \@namedef{ttlf@\ttl@a}{#1{#7}{#3}{#4}{#5}{#6}}} + +\def\ttl@format@i#1{% + \@ifnextchar[{\ttl@format@ii{#1}}{\ttl@format@ii{#1}[hang]}} + +\def\ttl@format@ii#1[#2]#3#4#5#6{% + \ttl@getkeys{#1}{titlesec}% + \ttl@toksa{{#3}{#4}{#5}{#6}}% Save arguments + \@ifnextchar[{% + \ttl@format@iii{#2}% + }{% + \ttl@format@iii{#2}[]}} + +% First, we get the shape -- if not defined it loads +% the corresponding file. + +\def\ttl@format@iii#1[#2]{% + \@ifundefined{ttlh@#1}{% + \begingroup + \makeatletter + \InputIfFileExists{#1.tss}{}{% + \PackageError{titlesec}{Unknown shape}% + {Shapes are defined in files with extension tss\MessageBreak + Either you have misspelled the shape\MessageBreak + or there is no a #1.tss file}}% + \endgroup}{}% + \@temptokena{#2}% + \ifttl@explicit + \edef\ttl@b{% + \def\expandafter\noexpand\csname ttlf@\ttl@a\endcsname####1% + {\expandafter\noexpand\csname ttlh@#1\endcsname + \the\ttl@toksa{\the\@temptokena}}}% + \else + \edef\ttl@b{% + \def\expandafter\noexpand\csname ttlf@\ttl@a\endcsname + {\expandafter\noexpand\csname ttlh@#1\endcsname + \the\ttl@toksa{\the\@temptokena}}}% + \fi + \ttl@b + \csname ttl@compat\ttl@a\endcsname} + +% Styles +% ~~~~~~ + +% 1:global 2:label 3:sep 4:style 5:after 6:left 7:right 8:title +% \ttl@ and \ttlh@ take the following eight +% arguments: +% {format}{label}{sep}{before}{after}{left}{right}{title} +% where before and after refer to the format. +% With the option explicit, #4 contains the title and #8 is +% empty. + +\def\ttlh@display#1#2#3#4#5#6#7#8{% + \gdef\ttl@makeline##1{\ttl@calc\hspace{#6}##1\ttl@calc\hspace{#7}}% + \setlength\leftskip{#6}% + \setlength\rightskip{#7}% + \interlinepenalty\@M + \ttl@changecentercr + \ttl@beginlongest + #1\ifhmode\ttl@hmode@error\fi + \ttl@glcmds + \parindent\z@ + \ifttl@label + {#2\strut\@@par}\nobreak\ttl@calc\vspace{#3}% + \fi + #4{#8}% + \kern\z@\strut\@@par + \nobreak\ttl@midlongest#5\@@par + \ttl@endlongest} + +\def\ttlh@hang#1#2#3#4#5#6#7#8{% + \gdef\ttl@makeline##1{\ttl@calc\hspace{#6}##1\ttl@calc\hspace{#7}}% + \setlength\leftskip{#6}% + \setlength\rightskip{#7}% + \interlinepenalty\@M + \ttl@changecentercr + \ttl@beginlongest + #1{\ifhmode\ttl@hmode@error\fi + \ttl@glcmds + \parindent\z@ + \begingroup + \ifttl@label + \sbox\z@{#2\strut\ttl@calc\hspace{#3}}% + \hangindent\wd\z@ + \noindent\box\z@ + \fi + #4{#8}% + \kern\z@\strut\@@par + \endgroup + \nobreak\ttl@midlongest#5\@@par}% + \ttl@endlongest} + +\def\ttlh@runin#1#2#3#4#5#6#7#8{% + \global\@noskipsectrue + \gdef\ttl@makeline##1{##1}% + \ttl@changecentercr + #1{\ifhmode\ttl@hmode@error\fi + \global\sbox\ttl@box{% + \ttl@calc\hspace{#6}% + \ifttl@label{\strut#2}\ttl@calc\hspace{#3}\fi + #4{#8}#5\unskip}}% + \gdef\@svsechd{\unhbox\ttl@box}} + +% +-----------------+ +% | T O O L S | +% +-----------------+ +% +% calcwidth +% ~~~~~~~~~ +% Implemented after code from soul (but much modified...) + +\newdimen\titlewidth +\newdimen\titlewidthlast +\newdimen\titlewidthfirst + +\let\ttl@glcmds\relax +\let\ttl@beginlongest\@empty +\let\ttl@midlongest\@empty +\let\ttl@endlongest\@empty +\let\iftitlemeasuring\@secondoftwo + +\def\ttl@xbeginlongest#1\ttl@endlongest{% + \titlewidth\z@ + \titlewidthlast\z@ + \let\iftitlemeasuring\@firstoftwo + \setbox\ttl@box\vbox{% + \def\ttl@glcmds{% + \def\\{\@ifstar{\@ifnextchar[{\ttl@bs}{\newline}}% + {\@ifnextchar[{\ttl@bs}{\newline}}}% + \def\ttl@bs[####1]{\newline}% + \let\@centercr\\% + \def\ttl@midlongest####1\@@par{}% Very dirty... + \advance\rightskip 1\leftskip plus 1fil + \leftskip=\z@}% + #1}% + \let\iftitlemeasuring\@secondoftwo + \ttl@boxprocess + #1} + +\def\ttl@boxprocess{% + \setbox\ttl@box=\vbox{% + \unvcopy\ttl@box + \unskip\unpenalty + \global\setbox\@ne=\lastbox}% + \ifvoid\@ne + \else + \setbox\tw@=\hbox{\hskip-\leftskip\unhbox\@ne\hskip-\rightskip}% + \titlewidthfirst\wd\tw@ + \ifdim\titlewidth<\titlewidthfirst + \titlewidth\titlewidthfirst + \fi + \ifdim\titlewidthlast=\z@ + \titlewidthlast\titlewidthfirst + \fi + \expandafter\ttl@boxprocess + \fi} + +% Rules +% ~~~~~ + +\providecommand\titleline{% + \@ifstar{\ttl@line@i{\hb@xt@\titlewidth}}% + {\ttl@line@i{}}} + +\def\ttl@line@i#1{% + \@ifnextchar[{\ttl@line{#1}}{\ttl@line{#1}[s]}} + +\def\ttl@line#1[#2]#3{% + \vskip\topskip + \hrule \@height \z@ + \nobreak + \vskip-\topskip + \begingroup + \parindent\z@ + \everypar{}% + \leftskip\z@ + \rightskip\z@ % #1 is either \hb@xt@\titlewidth or empty: + \@makebox[\hsize][#2]{\ttl@makeline{#1{#3}}}% + \par + \endgroup + \hrule height \z@ + \nobreak} + +\providecommand\titlerule{\@ifstar{\ttl@row}{\ttl@rule}} + +\let\ttl@leaders\xleaders % For titletoc compatibility + +\def\ttl@row{\@ifnextchar[{\ttl@row@i}{\ttl@row@i[\wd\z@]}} +\def\ttl@row@i[#1]#2{% + \ifvmode\expandafter\titleline\fi + {\sbox\z@{#2}% + \ttl@calcneg\hspace{#1}% + \hskip\wd\z@ + \ttl@leaders\hb@xt@#1{\hss\box\z@}% + \hfill\kern\z@}} + +\def\ttl@rule{\@ifnextchar[{\ttl@rule@i}{\ttl@rule@i[.4\p@]}} +\def\ttl@rule@i[#1]{% + \ifvmode\expandafter\titleline\fi + {\leaders\hrule height #1\hfill\kern\z@}} + +% Par shapes and space +% ~~~~~~~~~~~~~~~~~~~~ + +\providecommand\filright{% + \gdef\ttl@filleft##1{\hskip##1}% + \gdef\ttl@filright##1{\hfill}% + \let\\\@centercr + \advance\rightskip\z@ \@plus 1fil\relax} +\providecommand\filleft{% + \gdef\ttl@filleft##1{\hfill}% + \gdef\ttl@filright##1{\hskip##1}% + \let\\\@centercr + \advance\leftskip\z@ \@plus 1fil + \parfillskip\z@} +\providecommand\filcenter{\filleft\filright + \gdef\ttl@filleft##1{\hfill}} +\providecommand\fillast{% + \gdef\ttl@filleft##1{\hfill}% + \gdef\ttl@filright##1{\hfill}% + \let\\\@centercr + \filleft\advance\rightskip\z@ \@plus -1fil + \parfillskip\z@ \@plus 2fil\relax} +\newcommand\filinner{% + \if@twoside + \ifodd\count\z@\filleft\else\filright\fi + \else + \filleft + \fi} +\newcommand\filouter{% + \if@twoside + \ifodd\count\z@\filright\else\filleft\fi + \else + \filright + \fi} + +\newcommand\wordsep{\fontdimen\tw@\font \@plus + \fontdimen\thr@@\font \@minus \fontdimen4\font} + +% +-----------------+ +% | O P T I O N S | +% +-----------------+ + + +\DeclareOption{pagestyles}{\let\sectiontitle\@empty} +\DeclareOption{extramarks}{\let\ttl@fetchmark\@empty} +\DeclareOption{floatps}{% + \ifx\sectiontitle\@empty + \let\ttl@replace\space + \else + \PackageWarning{titlesec}{Ignoring `floatps' without + `pagestyles'. This option is now deprecated.}% + \fi} +\DeclareOption{psfloats}{% + \ifx\sectiontitle\@empty + \let\ttl@replace\@empty + \else + \PackageWarning{titlesec}{Ignoring `psfloats' without + `pagestyles'}% + \fi} + +\DeclareOption{loadonly}{\let\ttl@extract\@empty} + +\DeclareOption{outermarks}{% + \def\ttl@titlemarks{\outertitlemarks}} +\DeclareOption{topmarks}{ + \def\ttl@titlemarks{\toptitlemarks}} +\DeclareOption{botmarks}{% + \def\ttl@titlemarks{\bottitlemarks}} +\DeclareOption{innermarks}{% + \def\ttl@titlemarks{\innertitlemarks}} + +\DeclareOption{footmarks}{} % Backward compat + +\DeclareOption{explicit}{\ttl@explicittrue} + +\DeclareOption{clearempty}{% + \def\cleardoublepage{% + \clearpage{\ps@empty\if@twoside\ifodd\c@page\else + \hbox{}\newpage\if@twocolumn\hbox{}\newpage\fi\fi\fi}}} + +\DeclareOption{rigidchapters}{% + \def\ttl@topmode#1#2{\vbox to #1{#2\vfil}}% + \def\ttl@chapafter{.26\textheight}} +\DeclareOption{rubberchapters}{% + \def\ttl@topmode#1#2{{#2}\ttl@calc\vspace{#1}}% + \def\ttl@chapafter{40\p@}} + +\DeclareOption{bottomtitles}{% + \def\bottomtitlespace{-1\p@}} +\DeclareOption{nobottomtitles}{% + \def\bottomtitlespace{.2\textheight}} +\DeclareOption{nobottomtitles*}{% + \let\ttl@addstretch\relax + \def\bottomtitlespace{.2\textheight}} + +\DeclareOption{calcwidth}{% + \let\ttl@beginlongest\ttl@xbeginlongest} + +\DeclareOption{aftersep}{% + \let\ttl@titlespace\@gobble} +\DeclareOption{largestsep}{% + \let\ttl@titlespace\addvspace} + +\DeclareOption{oldparttoc}{% + \def\ttl@tocpart{\def\ttl@a{\thepart\hspace{1em}}}} +\DeclareOption{newparttoc}{% + \let\ttl@tocpart\relax} +\DeclareOption{notocpart*}{% + \let\ttl@notocparts\@empty} + +\DeclareOption{rm}{% + \protected@xdef\ttl@fonts{\ttl@fonts\protect\rmfamily}} +\DeclareOption{sf}{% + \protected@xdef\ttl@fonts{\ttl@fonts\protect\sffamily}} +\DeclareOption{tt}{% + \protected@xdef\ttl@fonts{\ttl@fonts\protect\ttfamily}} +\DeclareOption{md}{% + \protected@xdef\ttl@fonts{\ttl@fonts\protect\mdseries}} +\DeclareOption{bf}{% + \protected@xdef\ttl@fonts{\ttl@fonts\protect\bfseries}} +\DeclareOption{up}{% + \protected@xdef\ttl@fonts{\ttl@fonts\protect\upshape}} +\DeclareOption{it}{% + \protected@xdef\ttl@fonts{\ttl@fonts\protect\itshape}} +\DeclareOption{sl}{% + \protected@xdef\ttl@fonts{\ttl@fonts\protect\slshape}} +\DeclareOption{sc}{% + \protected@xdef\ttl@fonts{\ttl@fonts\protect\scshape}} + +\DeclareOption{big}{% + \gdef\ttl@sizes#1{\ifcase#1\relax\Huge\or\Large\or\large + \or\normalsize\or\or\or\huge\fi}} +\DeclareOption{medium}{% + \gdef\ttl@sizes#1{\ifcase#1\relax\huge\or\Large\or\large + \or\normalsize\or\or\or\LARGE\fi}} +\DeclareOption{small}{% + \gdef\ttl@sizes#1{\ifcase#1\relax\LARGE\or\large + \or\normalsize\or\normalsize\or\or\or\Large\fi}} +\DeclareOption{tiny}{% + \gdef\ttl@sizes#1{\ifcase#1\relax\large\or\normalsize\or + \normalsize\or\normalsize\or\or\or\normalsize\fi}} + +\DeclareOption{raggedleft}{% + \gdef\ttl@fil{\filleft}} +\DeclareOption{center}{% + \gdef\ttl@fil{\filcenter}} +\DeclareOption{raggedright}{% + \gdef\ttl@fil{\filright}} + +\DeclareOption{uppercase}{% + \gdef\ttl@case{\MakeUppercase}} + +\DeclareOption{compact}{% + \gdef\ttl@space{1}% + \gdef\ttl@chapafter{30\p@}} + +% Deprecated. To be remmoved in a major upgrade (3.0) +\DeclareOption{indentfirst}{% + \gdef\@afterindentfalse{\let\if@afterindent\iftrue}% + \@afterindenttrue + \def\titlespacing{% + \@ifstar{\ttl@spacing@i{\@ne}}{\ttl@spacing@i{\@ne}}}} +\DeclareOption{nonindentfirst}{% + \def\titlespacing{% + \@ifstar{\ttl@spacing@i{\z@}}{\ttl@spacing@i{\z@}}}} + +% New names +\DeclareOption{indentafter}{% + \gdef\@afterindentfalse{\let\if@afterindent\iftrue}% + \@afterindenttrue + \def\titlespacing{% + \@ifstar{\ttl@spacing@i{\@ne}}{\ttl@spacing@i{\@ne}}}} +\DeclareOption{noindentafter}{% + \def\titlespacing{% + \@ifstar{\ttl@spacing@i{\z@}}{\ttl@spacing@i{\z@}}}} + +% newlinetospace +\let\ttl@blinemarks\relax +\let\ttl@elinemarks\relax + +\DeclareRobustCommand\ttl@linetosp{% + \@ifstar{\ttl@linetosp@i}{\ttl@linetosp@i}}% + +\def\ttl@linetosp@i{% + \ifdim\lastskip>\z@\else\space\fi + \ignorespaces} + +\DeclareOption{newlinetospace}{% + \def\ttl@blinemarks{% + \let\ttl@e\\% + \def\\{\ttl@linetosp}}% + \def\ttl@elinemarks{\let\\\ttl@e}}% + +% toctitles +\def\ttl@addcontentsline#1#2{% + \addcontentsline{toc}{#1}{\ifttl@toclabel\ttl@a\fi#2}% + \nobreak} + +\DeclareOption{toctitles}{% + \def\ttl@addcontentsline#1#2{% + \addcontentsline{toc}{#1}{\ifttl@toclabel\ttl@a\fi\ttl@savetitle}% + \nobreak}} + +% pageatnewline + +\def\ttl@changecentercr{% + \let\ttl@centercr\@centercr + \def\@centercr{\@ifstar{\ttl@centercr*}{\ttl@centercr*}}} + +\DeclareOption{pageatnewline}{\let\ttl@changecentercr\relax} + +\def\ttl@fonts{} + +\ExecuteOptions{rubberchapters,bottomtitles,aftersep,oldparttoc,% + innermarks} + +\ProcessOptions + +% +-----------------+ +% | H Y P E R R E F | +% +-----------------+ +% +% These two commands are provided by hyperref. But if they +% are not defined at \begin{document} hyperref has not been +% loaded or it is an old version. + +\AtBeginDocument{% + \ifx\ttl@Hy@steplink\@undefined + \let\ttl@Hy@steplink\@gobble + \let\ttl@Hy@refstepcounter\refstepcounter + \fi} + +% +-----------------+ +% | PAGE STYLES | +% +-----------------+ +% +% This is generic: + +\newcommand\assignpagestyle[2]{% + \@namedef{ttl@ps@\expandafter\@gobble\string#1}{#2}} + +% Old pagestyles +% ~~~~~~~~~~~~~~ + +\providecommand\newpagestyle{% + \let\ttl@compatps\@empty % marks the ``old interface'' + \makeatletter + \edef\ttl@d{% + \noexpand\input{ttlps.def}% + \catcode`\noexpand\@=\the\catcode`\@}% + \ttl@d + \newpagestyle} + +\providecommand\renewpagestyle{% + \let\ttl@compatps\@empty % marks the ``old interface'' + \makeatletter + \edef\ttl@d{% + \noexpand\input{ttlps.def}% + \catcode`\noexpand\@=\the\catcode`\@}% + \ttl@d + \renewpagestyle} + +\providecommand\widenhead{% + \let\ttl@compatps\@empty % marks the ``old interface'' + \makeatletter + \edef\ttl@d{% + \noexpand\input{ttlps.def}% + \catcode`\noexpand\@=\the\catcode`\@}% + \ttl@d + \widenhead} + +% New pagestyles +% ~~~~~~~~~~~~~~ + +\@ifundefined{sectiontitle}{}{\input{ttlps.def}} + +% +-----------------+ +% | C O M P A T | +% +-----------------+ +% Easy setup, i.e., that of package options, is +% taken care of, if necessary. + +\renewcommand\secdef[2]{% + \@ifstar + {\ttl@labelfalse + #2} + {\ttl@labeltrue + \ifx#1\@chapter + \if@mainmatter\else\ttl@labelfalse\fi + \ifnum\ttll@chapter>\c@secnumdepth\ttl@labelfalse\fi + \else\ifx#1\@part + \ifnum\ttll@part>\c@secnumdepth\ttl@labelfalse\fi + \fi\fi + \let\ifttl@toclabel\ifttl@label + \@dblarg{#1}}} + +\@ifundefined{ttl@extract}{}{\endinput} + +\newcommand\titlelabel[1]{% + \def\@seccntformat##1{#1}} + +\expandafter\ifx\csname chapter\endcsname\relax + + \def\ttl@compatpart{\titleclass{\part}{part}\relax} + +\else + + \def\ttl@compatchapter{% + \def\@makechapterhead{% + \ttl@labeltrue + \if@mainmatter\else\ttl@labelfalse\fi + \ifnum\ttll@chapter>\c@secnumdepth\ttl@labelfalse\fi + \ttl@startargs\ttl@mkchap{chapter}}% + \def\@makeschapterhead{% + \ttl@labelfalse + \if@mainmatter\else\ttl@labelfalse\fi + \ifnum\ttll@chapter>\c@secnumdepth\ttl@labelfalse\fi + \ttl@startargs\ttl@mkchap{chapter}}} + + \def\ttl@compatpart{\titleclass{\part}{page}\relax} + +\fi + +\def\ttl@@extract#1\@startsection#2#3#4#5#6#7#8{% + \@tempskipa=#5 + \@tempskipb=#6 + \ifdim\@tempskipa<\z@ + \toks@{\titlespacing*#8{#4}}% + \@tempskipa-\@tempskipa + \else + \toks@{\titlespacing#8{#4}}% + \fi + \@ifundefined{ttl@space}{}{% + \ttl@assign\@tempskipa*\ttl@space\relax\beforetitleunit}% + \ifdim\@tempskipb<\z@ + \if@tempswa + \titleformat#8[runin]% + {\ttl@fonts\ttl@sizes{#3}}{\@seccntformat{#2}}% + {\z@}\ttl@passexplicit + \else + \titleformat#8[runin]% + {#7}{\@seccntformat{#2}}% + {\z@}\ttl@passexplicit + \fi + \@tempskipb-\@tempskipb + \else + \if@tempswa + \titleformat#8% + {\ttl@fil\ttl@fonts\ttl@sizes{#3}}{\@seccntformat{#2}}% + {\z@}\ttl@passexplicit + \else + \titleformat#8% + {#7}{\@seccntformat{#2}}% + {\z@}\ttl@passexplicit + \fi + \@ifundefined{ttl@space}{}{% + \ttl@assign\@tempskipb*\ttl@space\relax\aftertitleunit}% + \fi + \edef\ttl@a{\the\toks@{\the\@tempskipa}{\the\@tempskipb}} + \ttl@a} + +\def\ttl@extract#1{% + \expandafter\in@\expandafter\@startsection\expandafter{#1}% + \ifin@ + \expandafter\ttl@@extract#1#1% + \else + \PackageWarningNoLine{titlesec}% + {Non standard sectioning command detected\MessageBreak + Using default spacing and no format} + \titlespacing*#1{\z@}{*3}{*2}% + \fi} + +\@tempswafalse + +\ifx\ttl@fonts\@empty + \def\ttl@fonts{\bfseries} +\else + \@tempswatrue +\fi + +\expandafter\ifx\csname ttl@sizes\endcsname\relax + \gdef\ttl@sizes#1{\ifcase#1\relax\Huge\or\Large\or\large + \or\normalsize\or\or\or\huge\fi} +\else + \@tempswatrue +\fi + +\expandafter\ifx\csname ttl@fil\endcsname\relax + \let\ttl@fil\@empty +\else + \@tempswatrue +\fi + +\expandafter\ifx\csname ttl@case\endcsname\relax + \let\ttl@case\@firstofone +\else + \@tempswatrue +\fi + +\if@tempswa + + \expandafter\ifx\csname chapter\endcsname\relax\else + \titleformat\chapter[display]% + {\@ifundefined{ttl@fil}{\raggedright}{\ttl@fil}\ttl@fonts\ttl@sizes6} + {\@chapapp\space\thechapter}{.8\baselineskip}{\ttl@sizes\z@\ttl@passexplicit} + \fi + +\fi + +\ttl@extract\section +\ttl@extract\subsection +\ttl@extract\subsubsection +\ttl@extract\paragraph +\ttl@extract\subparagraph + +\let\ttl@extract\@undefined +\let\ttl@@extract\@undefined + +\def\ttl@toplevel{part} + +\expandafter\ifx\csname chapter\endcsname\relax + + \@namedef{ttll@part}{0} + \titleclass{\section}{straight}[\part] + + \titlespacing*{\part} + {\z@} + {4ex} + {3ex} + +\else + + \let\ttl@save@mkchap\@makechapterhead + \let\ttl@save@mkschap\@makeschapterhead + + \def\@makechapterhead#1{% + \gdef\ttl@savemark{\chaptermark{#1}}% + \ttl@save@mkchap{#1}% + \@ifundefined{ttl@ps@chapter}{}% + {\thispagestyle{\@nameuse{ttl@ps@chapter}}}} + + \def\@makeschapterhead#1{% + \gdef\ttl@savemark{\chaptermark{#1}}% + \ttl@save@mkschap{#1}% + \@ifundefined{ttl@ps@chapter}{}% + {\thispagestyle{\@nameuse{ttl@ps@chapter}}}} + + \@namedef{ttll@part}{-1} + \@namedef{ttlss@part}{chapter} + \@namedef{ttll@chapter}{0} + \titleclass{\section}{straight}[\chapter] + +% The following is unoperant, unless when \chapter / \part +% format is redefined + + \titlespacing*{\part} + {\z@} + {\z@\@plus1fil} + {\z@\@plus1fil} + + \titlespacing*\chapter + {\z@}% + {50\p@}% + {\ttl@chapafter}% + +\fi + +\titleclass{\subsection} {straight}[\section] +\titleclass{\subsubsection}{straight}[\subsection] +\titleclass{\paragraph} {straight}[\subsubsection] +\titleclass{\subparagraph} {straight}[\paragraph] + +\endinput diff --git a/ThirdParty/Ert/python/docs/latex/upquote.sty b/ThirdParty/Ert/python/docs/latex/upquote.sty new file mode 100644 index 0000000000..6b9d754f2a --- /dev/null +++ b/ThirdParty/Ert/python/docs/latex/upquote.sty @@ -0,0 +1,40 @@ +%% +%% This is file `upquote.sty', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% upquote.dtx (with options: `package') +%% +%% Copyright (C) 2000 by Michael A. Covington +%% Copyright (C) 2003 by Frank Mittelbach +%% Copyright (C) 2012 by Markus Kuhn (current maintainer) +%% +%% Released under the LaTeX Project Public License v1.3c or later +%% See http://www.latex-project.org/lppl.txt +%% +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{upquote} + [2012/04/19 v1.3 upright-quote and grave-accent glyphs in verbatim] +\newcommand\upquote@cmtt{cmtt} +\newcommand\upquote@OTone{OT1} +\ifx\encodingdefault\upquote@OTone + \ifx\ttdefault\upquote@cmtt\else\RequirePackage{textcomp}\fi +\else + \RequirePackage{textcomp} +\fi +\begingroup +\catcode`'=\active +\catcode``=\active +\g@addto@macro\@noligs + {\let'\textquotesingle + \let`\textasciigrave + \ifx\encodingdefault\upquote@OTone + \ifx\ttdefault\upquote@cmtt + \def'{\char13 }% + \def`{\char18 }% + \fi\fi} +\endgroup +\endinput +%% +%% End of file `upquote.sty'. diff --git a/ThirdParty/Ert/python/docs/latex/wrapfig.sty b/ThirdParty/Ert/python/docs/latex/wrapfig.sty new file mode 100644 index 0000000000..ea85e1b0d4 --- /dev/null +++ b/ThirdParty/Ert/python/docs/latex/wrapfig.sty @@ -0,0 +1,598 @@ +% W R A P F I G . S T Y ver 3.6 (Jan 31, 2003) +% +% Copyright (C) 1991-2003 by Donald Arseneau +% This software is released under the terms of the LaTeX Project +% public license. +% +% Environments "wrapfigure" and "wraptable" place a figure or table +% at the side of the page and wrap text around it. +% +% \begin{wrapfigure}[12]{r}[34pt]{5cm}
\end{wrapfigure} +% -- - ---- --- +% [number of narrow lines] {placement} [overhang] {width of figure} +% +% Placement is one of r, l, i, o, R, L, I, O, for right, left, +% inside, outside, (here / FLOAT). +% The figure sticks into the margin by `overhang', if given, or by the +% length \wrapoverhang, which is normally zero. +% The number of wrapped text lines is normally calculated from the height +% of the figure, but may be specified manually ("12" above). +% +% Environments similar to "wrapfigure" and "wraptable" may be easily added, +% or invoked by "\begin{wrapfloat}{float_name}" +% +% More detailed instructions are given below, following the definitions. +% Please direct any problem reports to asnd@triumf.ca + +%%%%% ----- Begin definitions ----- %%%%% + +\@ifundefined{c@WF@wrappedlines}{}{\endinput} + +\newdimen\wrapoverhang \wrapoverhang\z@ +\newdimen\WF@size +\newcount\c@WF@wrappedlines % used globally +\newbox\WF@box +\newtoks\WF@everypar +\newif\ifWF@float +\let\@@parshape\parshape +\let\WF@@everypar\everypar + +\def\wrapfloat#1{\def\@captype{#1}\@ifnextchar[\WF@wr{\WF@wr[]}} + +\def\wrapfigure{\wrapfloat{figure}} +\def\wraptable{\wrapfloat{table}} + +\def\WF@wr[#1]#2{% first two args: #1=num lines, #2=placement + \xdef\WF@wfname{wrap\@captype\space}% + \ifvoid\WF@box\else \WFclear \WF@collision \fi + \xdef\WF@place{\string`\@car#2r\@nil}% + \ifnum\lccode\WF@place=\WF@place \global\WF@floatfalse + \else \global\WF@floattrue \fi + \ifx\parshape\WF@fudgeparshape \ifWF@float\else\WF@collision\fi \else + \ifx\par\@@par \ifnum\@@parshape>\z@\WF@conflict\fi \else \WF@conflict\fi + \fi \gdef\WF@wli{#1}% + \@ifnextchar[\WF@rapt{\WF@rapt[\wrapoverhang]}} + +\def\WF@rapt[#1]#2{% final two args: #1 = overhang, #2 = width, + \gdef\WF@ovh{#1}% hold overhang for later, when \width is known + \global\setbox\WF@box\vtop\bgroup \setlength\hsize{#2}% + \ifdim\hsize>\z@ \@parboxrestore \else + \setbox\z@\hbox\bgroup \let\wf@@caption\caption \let\caption\wf@caption + \ignorespaces \fi} + +\def\wf@caption{\relax + \ifdim\hsize>\z@ \let\caption\wf@@caption \else + \unskip \egroup \hsize\wd\z@ \@parboxrestore \box\z@ \fi \caption} + +\def\endwrapfloat{% + \ifdim\hsize>\z@ \par\hrule\@width\hsize\@height\z@ % force width + \else \unskip \egroup \box\z@ \fi % or end hbox + \egroup % end the \vtop; width is known so now is "later" + \WF@floatstyhook % support float.sty + \def\width{\wd\WF@box}\setlength\wrapoverhang{\WF@ovh}% + \xdef\WF@ovh{\the\wrapoverhang}% save until wrapping + \ifdim\ht\WF@box>\topskip \ht\WF@box\z@ \fi % too much height, set flag. + \ifdim\ht\WF@box<.5\p@ % too tall (starts with \vbox) or too short + \global\setbox\WF@box\vtop{\vskip-1.4ex\unvbox\WF@box}\fi + \global\WF@size\dp\WF@box % box is guaranteed to have little height. + \global\advance\WF@size1.5\baselineskip \global\advance\WF@size\tw@\intextsep + \aftergroup\WF@startfloating % even when not really floating! + \ifWF@float\else \ifhmode + {\unskip \parfillskip\z@skip \par \vskip-\parskip}\aftergroup\noindent + \fi\fi \global\@ignoretrue} + +\let\endwrapfigure\endwrapfloat +\let\endwraptable\endwrapfloat + +% Subvert \everypar to float fig and do wrapping. Also for non-float. +\def\WF@startfloating{% + \WF@everypar\expandafter{\the\everypar}\let\everypar\WF@everypar + \WF@@everypar{\ifvoid\WF@box\else\WF@floathand\fi \the\everypar + \WF@wraphand +}} + +\def\WF@floathand{% +\ifx\parshape\WF@fudgeparshape \WF@fltmes\else + \ifx\par\@@par\ifnum\@@parshape=\z@\ifdim\hangindent=\z@ + \setbox\z@\lastbox \begingroup + \@@par \WF@@everypar{}\WF@putfigmaybe + \endgroup % start wrapping + \ifvoid\z@\else\box\z@\fi % replace indentation + \else\WF@fltmes\fi\else\WF@fltmes\fi\else\WF@fltmes\fi\fi} + +% Put fig here if it fits or if it can't float +\def\WF@putfigmaybe{% +\ifinner + \vskip-\parskip \global\WF@floatfalse + \let\pagetotal\maxdimen % kludge flag for "not top of page" +\else % outer page + \@tempdima\pagedepth % save page depth + {\advance\parskip\@tempdima\vskip-\parskip}% back up to baseline + \penalty\interlinepenalty % update pg. parameters + \@tempdimb\pagegoal \advance\@tempdimb-\pagetotal % room left on page + \ifdim\@tempdimb<\z@ % \WF@info{Page overfull already;}% + \global\WF@floatfalse + \ifdim-\@tempdimb>\pageshrink \else \pagebreak \fi + \else + \ifdim\WF@size>\@tempdimb +% \WF@info{Size \the\WF@size\space does not fit in \the\@tempdimb}% + \ifWF@float \dimen@.5\baselineskip \else \dimen@ 2\baselineskip\fi + \ifdim\pagestretch>\dimen@ \dimen@\pagestretch \fi + \ifdim\pagefilstretch>\z@ \dimen@\@tempdimb \fi + \ifdim\pagefillstretch>\z@ \dimen@\@tempdimb \fi + \advance\dimen@.5\baselineskip + \ifdim\dimen@>\@tempdimb % \WF@info{Page nearly full; can stretch}% + \global\WF@floatfalse \pagebreak + \fi + \else % \WF@info{Fits in \the\@tempdimb;}% + \global\WF@floatfalse + \fi\fi + \vskip\@tempdima\relax % (return erased page depth) +\fi +\noindent +\ifWF@float + \WF@fltmes +\else % putting here; + \WF@info{Put \WF@wfname here:}% + {\ifodd\if@twoside\c@page\else\@ne\fi % assign l/r to i/o placement + \lccode`i`l\lccode`o`r\else \lccode`i`r\lccode`o`l\fi + \xdef\WF@place{\the\lccode\lccode\WF@place}}% twice to get only l or r + \hbox to\z@{% llap or rlap depending on {l} or {r}; calc effective width + \@tempdima\wd\WF@box \@tempdimb\WF@ovh + \advance\@tempdima-\@tempdimb \advance\@tempdima\columnsep + \@tempdimb\hsize \advance\@tempdimb-\@tempdima + \xdef\WF@adjlw{\the\@tempdima}% + \ifnum `l=\WF@place % fig on left + \hss % figure overlaps space to the left + \def\@tempa{\kern\columnsep}% position to left of the gap + \else % fig on right + \@tempdima\z@ % no left indentation + \kern\@tempdimb \kern\columnsep + \def\@tempa{\hss}% figure overlaps space to the right + \fi + \ifdim\@tempdimb<\hsize + \xdef\WF@wrapil{\the\@tempdima \the\@tempdimb}% indentation and length + \xdef\WF@adjtlm{\the\@tempdima}% + \else + \xdef\WF@wrapil{\z@ \the\hsize}% + \xdef\WF@adjlw{\z@}\xdef\WF@adjtlm{\z@}% + \fi + \ifdim\pagetotal=\z@ % \WF@info{Put \WF@wfname at top of p.\thepage}% + \global\advance\WF@size-\intextsep + \else % \WF@info{Putting \WF@wfname in middle of page}% + \setbox\WF@box\hbox{\lower\intextsep\box\WF@box}% + \fi \dp\WF@box\z@ \box\WF@box \@tempa + }% end \hbox to 0pt + \aftergroup\WF@startwrapping % after the \endgroup which immediately follows +\fi} + +\def\WF@startwrapping{% + \ifx\WF@wli\@empty + {\advance\WF@size1.1\baselineskip + \divide\WF@size\baselineskip \global\c@WF@wrappedlines\WF@size}% + \else + \setcounter{WF@wrappedlines}{\WF@wli}\global\advance\c@WF@wrappedlines\@ne + \fi + \ifnum\c@WF@wrappedlines>\@ne + \let\parshape\WF@fudgeparshape \let\WF@pspars\@empty \let\WF@@par\par + \def\@setpar##1{\def\WF@@par{##1}}\def\par{\@par}\let\@par\WF@mypar + \xdef\WF@restoretol{\tolerance\the\tolerance}\tolerance9999 + \advance\linewidth-\WF@adjlw \advance\@totalleftmargin\WF@adjtlm + \fi} + +\def\WF@wraphand{% +\ifnum\c@WF@wrappedlines<\tw@ \WF@finale +\else \begingroup % Create \parshape command: + \@tempcnta\@ne \let\WF@wrapil\relax \gdef\WF@ps{}% + \@whilenum \@tempcnta<\c@WF@wrappedlines\do{% repeated indentation, length + \xdef\WF@ps{\WF@ps\WF@wrapil}\advance\@tempcnta\@ne + }\endgroup + \ifx\WF@pspars\@empty + \@@parshape\c@WF@wrappedlines \WF@ps \WF@noil + \else % use external `parshape' values to modify my parshape + \WF@modps +\fi\fi} + +\def\WF@mypar{\relax + \WF@@par % what the rest of LaTeX expects \par to be (usually \@@par) + \ifnum\@@parshape=\z@ \let\WF@pspars\@empty \fi % reset `parshape' + \global\advance\c@WF@wrappedlines-\prevgraf \prevgraf\z@ + \ifnum\c@WF@wrappedlines<\tw@ \WF@finale \fi} + +\def\WF@modps{\begingroup + \afterassignment\@tempdimb \@tempdima\WF@pspars % a=ind, b=wid + \advance\@tempdima-\WF@adjtlm \advance\@tempdimb\WF@adjlw +% \afterassignment\dimen@\advance\@tempdima\WF@wrapil +% \advance\@tempdimb\dimen@ \advance\@tempdimb-\hsize + \let\WF@wrapil\WF@pspars%{\the\@tempdima \the\@tempdimb}% + \edef\@tempb{\@@parshape\c@WF@wrappedlines \WF@ps \the\@tempdima \the\@tempdimb}% + \expandafter\endgroup\@tempb} + +\let\@@setpar\@setpar +\def\WF@noil{\z@ \hsize} +\let\WF@pspars\@empty + +\def\WF@fudgeparshape{\relax \ifnum\c@WF@wrappedlines<\tw@ \WF@finale + \else \afterassignment\WF@fudgeparshapee \fam \fi} +\def\WF@fudgeparshapee{\ifnum\fam=\@ne \expandafter \WF@parshapeee \else + \WF@conflict \@@parshape\fam \fi} +\def\WF@parshapeee#1#2{\begingroup\delimitershortfall#1% + \nulldelimiterspace#2%\advance\nulldelimiterspace\WF@adjlw + \edef\@tempa{\def\noexpand\WF@pspars{% + \the\delimitershortfall \the\nulldelimiterspace}}% + \expandafter\endgroup\@tempa \WF@wraphand} + +\def\WF@finale{\ifx\parshape\WF@fudgeparshape + \WF@restoretol \let\@setpar\@@setpar \let\par\WF@@par + \advance\linewidth\WF@adjlw \advance\@totalleftmargin-\WF@adjtlm + \WF@info{Finish wrapping text}% + \ifx\par\@@par \def\@par{\let\par\@@par\par}\else \let\@par\WF@@par \fi + \let\parshape\@@parshape + \parshape\ifx\WF@pspars\@empty \z@ \else \@ne \WF@pspars\fi \fi + \ifvoid\WF@box \ifx\everypar\WF@everypar + \let\everypar\WF@@everypar \everypar\expandafter{\the\WF@everypar}% + \fi\fi} + +\newcommand{\WFclear}{\par + \ifvoid\WF@box\else \vskip\bigskipamount \box\WF@box + \let\everypar\WF@@everypar \everypar\expandafter{\the\WF@everypar}% + \fi \global\c@WF@wrappedlines\z@ \WF@finale} + +\begingroup + \toks0={\let\everypar\WF@@everypar \everypar\expandafter{\the\WF@everypar}% + \let\parshape\@@parshape \let\@setpar\@@setpar } + \toks1=\expandafter{\@arrayparboxrestore} + \toks2=\expandafter{\clearpage} + \edef\@tempa{\def\noexpand\@arrayparboxrestore{\the\toks0 \the\toks1}% + \def\noexpand\clearpage{\noexpand\protect\noexpand\WFclear \the\toks2}} + \expandafter +\endgroup\@tempa + +\@ifundefined{@capwidth}{\let\@capwidth\hsize}{}% Pamper RevTeX's Stupidity + +\def\WF@conflict{\WF@warning + {\WF@wfname used inside a conflicting environment}} +\def\WF@collision{\WF@warning{Collision between wrapping environments}} +\def\WF@fltmes{\ifWF@float \WF@info{\WF@wfname floats}% + \else \WF@warning{Stationary \WF@wfname forced to float}\fi} + +\let\WF@warning\@warning +\let\WF@info\@gobble + +% Support float.sty: float styles and \newfloat. Make \newfloat{foo} +% define the `wrapfoo' environment. Support \newfloat from memoir.cls +% and \newfloatlist from ccaption.sty. +% +\let\WF@floatstyhook\relax + +\@ifundefined{newfloat}{}{% There is a \newfloat command +% + \@ifundefined{restylefloat}{ + % \newfloat comes from somewhere besides float.sty + \@ifclassloaded{memoir}{ + \toks@=\expandafter\expandafter\expandafter + {\csname\string\newfloat\endcsname [{#1}]{#2}{#3}{#4}% + \newenvironment{wrap#2}{\wrapfloat{#2}}{\endwrapfloat}% + } + \edef\@tempa{\def\expandafter\noexpand\csname\string\newfloat\endcsname + [##1]##2##3##4{\the\toks@}} + \@tempa + }% end memoir support + {}% Other origins of \newfloat here?? + }{ + % float.sty handler. Ooops: Two versions for different versions + % Changing \float@restyle (or \restylefloat) changes \newfloat too. + \@ifundefined{float@restyle}{% older float.sty + \toks@=\expandafter{\restylefloat{#1}% (env may or may not be defined) + \@namedef{wrap#1}{\def\@captype{#1}\@nameuse{fst@#1}% + \def\WF@floatstyhook{\let\@currbox\WF@box \columnwidth\wd\WF@box + \global\setbox\WF@box\float@makebox}% + \@ifnextchar[\WF@wr{\WF@wr[]}}% + \expandafter\let\csname endwrap#1\endcsname \endwrapfigure + }\edef\@tempa{\def\noexpand\restylefloat##1{\the\toks@}} + }{% newer float.sty: use \float@restyle, and \float@makebox takes width arg + \toks@=\expandafter{\float@restyle{#1}% (env may or may not be defined) + \@namedef{wrap#1}{\def\@captype{#1}\@nameuse{fst@#1}% + \def\WF@floatstyhook{\let\@currbox\WF@box + \global\setbox\WF@box\float@makebox{\wd\WF@box}}% + \@ifnextchar[\WF@wr{\WF@wr[]}}% + \expandafter\let\csname endwrap#1\endcsname \endwrapfigure + }\edef\@tempa{\def\noexpand\float@restyle##1{\the\toks@}} + } + \@tempa % perform redefinitions + % + }% End float.sty handler +}% End redefinitions of \newfloat + +% Support ccaption.sty +\@ifundefined{\string\newfloatlist}{}{ + \toks@=\expandafter\expandafter\expandafter + {\csname\string\newfloatlist\endcsname [{#1}]{#2}{#3}{#4}{#5}% + \@namedef{wrap#2}{\wrapfloat{#2}}% + \expandafter\let\csname endwrap#2\endcsname \endwrapfloat + } + \edef\@tempa{\def\expandafter\noexpand\csname\string\newfloatlist\endcsname + [##1]##2##3##4##5{\the\toks@}} + \@tempa +} + +% Process package options. + +\@ifundefined{DeclareOption}{\endinput}{} + +\def\WF@warning{\PackageWarning{wrapfig}} +\ProvidesPackage{wrapfig}[2003/01/31 \space v 3.6] +\DeclareOption{verbose}{\def\WF@info{\PackageInfo{wrapfig}}} +\ProcessOptions +\AtEndDocument{\WFclear} + +\endinput + +%%%%% ----- End definitions ----- %%%%% + +%%%%% ----- Begin Instructions ----- %%%%% + + +W R A P F I G . S T Y \ \ ver 3.6 \ \ (Jan 31, 2003) + +Copyright (C) 1991-2003 by Donald Arseneau (asnd@triumf.ca) + +Wrapfig.sty provides the environments "wrapfigure" and "wraptable" for +typesetting a narrow float at the edge of the text, and making the text +wrap around it. The "wrapfigure" and "wraptable" environments interact +properly with the "\caption" command to produce proper numbering, but +they are not regular floats like "figure" and "table", so (beware!) they +may be printed out of sequence with the regular floats. There are four +parameters for "\begin{wrapfigure}", two optional and two required, plus +the text of the figure, with a caption perhaps: + + \begin{wrapfigure}[12]{r}[34pt]{5cm}
\end{wrapfigure} + == = ==== === + [number of narrow lines] {placement} [overhang] {width} + +Some idiosyncrasies: + + - You must not specify a wrapfigure in any type of list environment or + or immediately before or immediately after one. It is OK to follow + a list if there is a blank line ("\par") in between. + + - If you put a wrapfigure in a parbox or a minipage, or any other type + of grouping, the text wrapping should end before the group does. + + - It does work in two-column format, but are your figures that small? + + - It may be out of sequence with regular floats. + + - The hlines that may be printed above and below floats are ignored; + you must insert them manually if desired. + + - "\linewidth" is now adjusted within the wrapped text, but since it + can only be set for whole paragraphs at a time, it will persist with + the wrong value after the wrapping, until the paragraph is finished. + +New wrapping environments may be added when new float types are defined +(using memoir.cls, float.sty, or ccaption.sty). Any wrapping environment, +"wrapfigure", "wraptable", or something else may be invoked using the +"wrapfloat" environment, as in "\begin{wrapfloat}{figure}{O}{5cm}". + +To use float.sty properly, load package "float" before "wrapfig", +and declare any new float types after loading both. Likewise for +ccaption.sty and "\newfloatlist" and memoir.cls and its "\newfloat". + +\section{Placement and Floating} + +Parameter "#2" (required) is the figure placement code, but the valid +codes are different from regular figures. They come in pairs: an +uppercase version which allows the figure to float, and a lowercase +version that puts the figure ``exactly here''. + + r R - the right side of the text + l L - the left side of the text + i I - the inside edge--near the binding (if "[twoside]" document) + o O - the outside edge--far from the binding + +You should specify one code only, not a list. The figure or table must +be on one side or the other; it cannot be in the middle with text on +both sides. The "i" and "o" options refer to the inside and outside of +the whole page, not individual columns. + +The ability to float is somewhat restricted, and you will get best results +by giving exact manual placement, but floating is more convenient while +revising the document. Any changes to the formatting can ruin your manual +positioning so you should adjust the placement just before printing a +final copy. Here are some tips for good placement: + + - The environment should be placed so as to not run over a page break. + + - The environment must not be placed in special places like lists. + + - For esthetic reasons, only plain text should wrap around the figure. + Section titles and big equations look bad; lists are bad if the figure + is on the left. (All these function properly, they just don't look + very good.) Small equations look fine. + + - It is convenient to begin the environment between paragraphs, but if + you want placement in the middle of a paragraph, you must put the + environment between two words where there is a natural line break. + +When floating, \LaTeX\ tries to apply these rules. More specifically, +a floated wrapping environment will only begin... + + - at the beginning of a paragraph, + + - when there is enough room on the page, or it is possible to go on + the next page, + + - if the `paragraph' is not in a section title or a list, + + - if the paragraph is not wrapping around another figure, + + - in the main text (not in a minipage etc.) + +It is possible that a non-floating wrapfigure will be forced to float +when an earlier one is still being processed. A warning will be written +in that case. You can have more information about the floating process +written to the log file by specifying "\usepackage[verbose]{wrapfig}". + +If there is a lot of flexibility on a page, a floating wrapfigure may +be placed badly; you must turn to manual placement. A rare problem is +that floats and footnotes specified within the wrapping text can also +cause poor placement and bad formatting. + + +\section {Sizing and optional overhang} + +Parameter "#4" (the second required parameter) is the width of the figure +or table. Given the way that \LaTeX\ puts just about everything into boxes +with the current line-width, the width parameter will take precedence over +whatever natural width the figure has. In particular, the caption is always +typeset with the specified width. If the figure is wider than the space +allotted, you will get an ``overfull box'' warning. + +However, if you specify a width of *zero* ("0pt"), the actual width of +the figure will determine the wrapping width. A following "\caption" +should have the same width as the figure, but it might fail badly; it +is safer to specify a width when you use a caption. + +\LaTeX\ will wrap surrounding text around the figure, leaving a gap of +"\intextsep" at the top and bottom, and "\columsep" at the side, by +producing a series of shortened text lines beside the figure. The +indentation (shortening) of the text is the figure width plus "\columnsep" +minus overhang (if any; see below). + +\LaTeX\ calculates the number of short lines needed based on the height +of the figure and the length "\intextsep". You can override this guess +by giving the first optional argument (parameter "#1") specifying the +number of shortened lines (counting each displayed equation as 3 lines). +This is particularly useful when the surrounding text contains extra +vertical spacing that is not accounted for automatically. + +The second optional parameter ("#3") tells how much the figure should +hang out into the margin. The default overhang is given by the length +"\wrapoverhang", which is "0pt" normally but can be changed using +"\setlength". For example, to have all wrapfigures use the space +reserved for marginal notes, + + \setlength{\wrapoverhang}{\marginparwidth} + \addtolength{\wrapoverhang}{\marginparsep} + +When you do specify the overhang explicitly for a particular figure, you +can use a special unit called "\width" meaning the width of the figure. +For example, "[0.5\width]" makes the center of the figure sit on the +edge of the text, and "[\width]" puts the figure entirely in the margin +(and the adjacent text is indented by just "\columnsep"). This "\width" +is the actual width of the wrapfigure, which may be greater than the +declared width. + + +\section{Some Random Implementation Notes} + +Unfortunately, \LaTeX's system of setting "\everypar" and "\par" is +unable to coexist peacefully with a wrapping environment, so I was +forced to subvert the "\@setpar" mechanism and "\everypar". ("\everypar" +is already subverted once by NFSS.) + +When checking the room left on the page, remember that if there is less +than "\baselineskip" the new paragraph will begin on the next page, even +if there is no page stretch. If non-floating, I force a bad page break +rather than have the figure hang into the bottom margin. + +Here are notes on various variables and some macros; what info they +store and how they are used. + + \WF@wli - number-of-wrapped-lines parameter, saved for start of wrapping. + Set globally by "\WF@wr" (set empty if no optional parameter given). + The floating mechanism ignores this and uses the real size. + + \WF@ovh - margin overhang set globally by "\WF@rapt", saved until placing + figure (but not reset). Actually, the setting is very tricky so that + the expected values are used when a figure floats. First, the expression + is saved without evaluation by "\WF@rapt" ("\begin{wrapfigure}") because + "\width" is still unknown. Soon after that, "\endwrapfigure" executes + "\WF@ovh" to evaluate the overhang and save the result (so that changes + to "\wrapoverhang" while this figure is floating won't affect this + figure). Finally, it is used by "\WF@putfigmaybe" when printing the fig. + + \WF@place - a macro that is used as a number, giving the placement code. + It might start out as "`I" and later be converted to "114" (r). + + \WF@box - tested for void at "\begin{wrapfigure}", to avoid collisions, + by "\everypar" to do floating, and by "\WF@finale" before resetting + "\everypar". Voided globally when used by "\WF@putfigmaybe" (or by + "\WF@wr" if an old figure must be dumped prematurely). + + \par - test if it is "\@@par" by "\begin{wrapfigure}" and "\WF@floathand" + to float past special environments. It is set to "\@par" ("\WF@mypar") + by "\WF@startwrapping", and restored by an end-group (bad!) or by + "\WF@finale" (good). It is protected from change by redefining + "\@setpar". + + \parshape - let to "\WF@fudgeparshape" by "\WF@startwrapping", so lists + will continue wrapping; "\@@parshape" preserves the real "\parshape" + command, and it is restored by "\WF@finale" or "\@parboxrestore". + "\WF@floathand" and "\WF@wr" test if old wrapping is still in progress + with "\ifx\parshape\WF@fudgeparshape". The value of "\@@parshape" is + also tested to float past lists and other wrapping environments. + + \hangindent - tested to float past section titles etc. + + \c@WF@wrappedlines - the number of shortened lines + 1; set globally by + "\WF@startwrapping" and decremented by "\par" ("\WF@mypar"). It is > 1 + only when wrapping is incomplete. "\WF@wraphand", "\WF@fudgeparshape", + and "\WF@mypar" test the number for calling "\WF@finale". It may get + stuck at some high value if "\par" is restored by an end-group, (and + wrapping is terminated prematurely) so it is unwise to use this as a + test for wrapping-complete. + + \pagetotal - one of many parameters used to compute floating. When + putting a wrapfigure in a parbox, I assign "\let\pagetotal\maxdimen" + (locally!) to signal not-top-of-page and no floating. + + \WF@pspars - the "\parshape" parameters as LaTeX sets them for lists + ("\WF@fudgeparshape"); when wrapping I test it and use it to modify my + own real params for the paragraph. They are also used when "\parshape" + is restored after wrapping. + + \WF@finale - is performed by "\par" when wrapping should end. However, + that might happen inside a group (a list especially), so the subverted + versions of "\par", "\parshape" etc. will be reinstated when the group + ends. Thus, they must themselves test "\c@WF@wrappedlines" < 2 to see + when wrapping is over, and if so, they should just do "\WF@finale" again. + +These are the tests to see if a floating wrapfigure will fit at a particular +spot. These tests are performed at the beginning of every paragraph after +the figure, except in lists etc. ("\pagegoal" - "\pagetotal" is the room +left on the page.) + + > + room_left := \pagegoal - \pagetotal + if room_left < 0 then page overfull already: put figure (on next page) + else + if figure_size > room_left then does not fit + if max(min_stretch, \pagestretch) + extra > room_left + then page can stretch until full: put figure (at top of next page) + fi + else figure fits: put figure + fi fi + < + +Even if a wrapfigure is not floating, it will go through the same logic +to generate a "\pagebreak", and maybe an underfull page, when the current +page can stretch until full. The "min_stretch" depends on whether it is +floating or not: ".5\baselineskip" (floating) "2\baselineskip" (not). The +"extra" is ".5\baselineskip" in either case. These values can be adjusted. + +There are some other `magic numbers' for floating that aren't really so +special, but you must change them together if you change them at all. +To make floating wrapfigures float less and fit on pages more frequently, +but not change the number of wrapped lines, decrease the "1.5" in +"\global\advance\WF@size1.5\baselineskip" and increase the "1.1" in +"\advance\WF@size1.1\baselineskip" by the same amount (and vice versa). +To make more (or fewer) wrapped lines for the same size figure, without +changing the floating, change "1.1" in "\advance\WF@size1.1\baselineskip" +unilaterally. + +%%%%% ----- End Instructions ----- %%%%% + +Test file integrity: ASCII 32-57, 58-126: !"#$%&'()*+,-./0123456789 +:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ diff --git a/ThirdParty/Ert/python/ecl/__init__.py b/ThirdParty/Ert/python/ecl/__init__.py index 50cb5823bd..f60dd2b8c6 100644 --- a/ThirdParty/Ert/python/ecl/__init__.py +++ b/ThirdParty/Ert/python/ecl/__init__.py @@ -1,4 +1,4 @@ -# Copyright (C) 2011 Statoil ASA, Norway. +# Copyright (C) 2011 Equinor ASA, Norway. # # The file '__init__.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/ecl_type.py b/ThirdParty/Ert/python/ecl/ecl_type.py index 330d636a9a..69537a9a6b 100644 --- a/ThirdParty/Ert/python/ecl/ecl_type.py +++ b/ThirdParty/Ert/python/ecl/ecl_type.py @@ -1,4 +1,4 @@ -# Copyright (C) 2017 Statoil ASA, Norway. +# Copyright (C) 2017 Equinor ASA, Norway. # # The file 'ecl_type.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/ecl_util.py b/ThirdParty/Ert/python/ecl/ecl_util.py index 3835d3e5ae..e6edce0351 100644 --- a/ThirdParty/Ert/python/ecl/ecl_util.py +++ b/ThirdParty/Ert/python/ecl/ecl_util.py @@ -1,4 +1,4 @@ -# Copyright (C) 2011 Statoil ASA, Norway. +# Copyright (C) 2011 Equinor ASA, Norway. # # The file 'ecl_util.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/eclfile/__init__.py b/ThirdParty/Ert/python/ecl/eclfile/__init__.py index c98633910f..a183ea32b6 100644 --- a/ThirdParty/Ert/python/ecl/eclfile/__init__.py +++ b/ThirdParty/Ert/python/ecl/eclfile/__init__.py @@ -1,4 +1,4 @@ -# Copyright (C) 2018 Statoil ASA, Norway. +# Copyright (C) 2018 Equinor ASA, Norway. # # This file is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/eclfile/ecl_3d_file.py b/ThirdParty/Ert/python/ecl/eclfile/ecl_3d_file.py index 0d462a7636..90156ac322 100644 --- a/ThirdParty/Ert/python/ecl/eclfile/ecl_3d_file.py +++ b/ThirdParty/Ert/python/ecl/eclfile/ecl_3d_file.py @@ -1,4 +1,4 @@ -# Copyright (C) 2015 Statoil ASA, Norway. +# Copyright (C) 2015 Equinor ASA, Norway. # # This file is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/eclfile/ecl_3dkw.py b/ThirdParty/Ert/python/ecl/eclfile/ecl_3dkw.py index f19d01f171..6db3647849 100644 --- a/ThirdParty/Ert/python/ecl/eclfile/ecl_3dkw.py +++ b/ThirdParty/Ert/python/ecl/eclfile/ecl_3dkw.py @@ -1,4 +1,4 @@ -# Copyright (C) 2015 Statoil ASA, Norway. +# Copyright (C) 2015 Equinor ASA, Norway. # # The file 'ecl_3dkw.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/eclfile/ecl_file.py b/ThirdParty/Ert/python/ecl/eclfile/ecl_file.py index 75ac344456..ca96e6cdc3 100644 --- a/ThirdParty/Ert/python/ecl/eclfile/ecl_file.py +++ b/ThirdParty/Ert/python/ecl/eclfile/ecl_file.py @@ -1,4 +1,4 @@ -# Copyright (C) 2011 Statoil ASA, Norway. +# Copyright (C) 2011 Equinor ASA, Norway. # # The file 'ecl_file.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/eclfile/ecl_file_view.py b/ThirdParty/Ert/python/ecl/eclfile/ecl_file_view.py index ccb29032fa..1c6f02345d 100644 --- a/ThirdParty/Ert/python/ecl/eclfile/ecl_file_view.py +++ b/ThirdParty/Ert/python/ecl/eclfile/ecl_file_view.py @@ -1,4 +1,4 @@ -# Copyright (C) 2017 Statoil ASA, Norway. +# Copyright (C) 2017 Equinor ASA, Norway. # # This file is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/eclfile/ecl_init_file.py b/ThirdParty/Ert/python/ecl/eclfile/ecl_init_file.py index 51ae032143..e15df9dab3 100644 --- a/ThirdParty/Ert/python/ecl/eclfile/ecl_init_file.py +++ b/ThirdParty/Ert/python/ecl/eclfile/ecl_init_file.py @@ -1,4 +1,4 @@ -# Copyright (C) 2015 Statoil ASA, Norway. +# Copyright (C) 2015 Equinor ASA, Norway. # # The file 'ecl_init_file.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/eclfile/ecl_kw.py b/ThirdParty/Ert/python/ecl/eclfile/ecl_kw.py index d5cd61dcad..6a47ddecc5 100644 --- a/ThirdParty/Ert/python/ecl/eclfile/ecl_kw.py +++ b/ThirdParty/Ert/python/ecl/eclfile/ecl_kw.py @@ -1,4 +1,4 @@ -# Copyright (C) 2011 Statoil ASA, Norway. +# Copyright (C) 2011 Equinor ASA, Norway. # # The file 'ecl_kw.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/eclfile/ecl_restart_file.py b/ThirdParty/Ert/python/ecl/eclfile/ecl_restart_file.py index bdd2e33e8f..d09f179d65 100644 --- a/ThirdParty/Ert/python/ecl/eclfile/ecl_restart_file.py +++ b/ThirdParty/Ert/python/ecl/eclfile/ecl_restart_file.py @@ -1,4 +1,4 @@ -# Copyright (C) 2015 Statoil ASA, Norway. +# Copyright (C) 2015 Equinor ASA, Norway. # # The file 'ecl_restart_file.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/eclfile/fortio.py b/ThirdParty/Ert/python/ecl/eclfile/fortio.py index e454a9b8b0..d32e501990 100644 --- a/ThirdParty/Ert/python/ecl/eclfile/fortio.py +++ b/ThirdParty/Ert/python/ecl/eclfile/fortio.py @@ -1,4 +1,4 @@ -# Copyright (C) 2011 Statoil ASA, Norway. +# Copyright (C) 2011 Equinor ASA, Norway. # # The file 'fortio.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/gravimetry/__init__.py b/ThirdParty/Ert/python/ecl/gravimetry/__init__.py index f218261dda..16881ceaba 100644 --- a/ThirdParty/Ert/python/ecl/gravimetry/__init__.py +++ b/ThirdParty/Ert/python/ecl/gravimetry/__init__.py @@ -1,4 +1,4 @@ -# Copyright (C) 2018 Statoil ASA, Norway. +# Copyright (C) 2018 Equinor ASA, Norway. # # This file is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/gravimetry/ecl_grav.py b/ThirdParty/Ert/python/ecl/gravimetry/ecl_grav.py index f8d75a3822..41171d94fe 100644 --- a/ThirdParty/Ert/python/ecl/gravimetry/ecl_grav.py +++ b/ThirdParty/Ert/python/ecl/gravimetry/ecl_grav.py @@ -1,4 +1,4 @@ -# Copyright (C) 2011 Statoil ASA, Norway. +# Copyright (C) 2011 Equinor ASA, Norway. # # The file 'ecl_grav.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/gravimetry/ecl_grav_calc.py b/ThirdParty/Ert/python/ecl/gravimetry/ecl_grav_calc.py index c00a1e714b..58dd878724 100644 --- a/ThirdParty/Ert/python/ecl/gravimetry/ecl_grav_calc.py +++ b/ThirdParty/Ert/python/ecl/gravimetry/ecl_grav_calc.py @@ -1,4 +1,4 @@ -# Copyright (C) 2011 Statoil ASA, Norway. +# Copyright (C) 2011 Equinor ASA, Norway. # # This file is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/gravimetry/ecl_subsidence.py b/ThirdParty/Ert/python/ecl/gravimetry/ecl_subsidence.py index 890e4e5ccc..a9073c4d80 100644 --- a/ThirdParty/Ert/python/ecl/gravimetry/ecl_subsidence.py +++ b/ThirdParty/Ert/python/ecl/gravimetry/ecl_subsidence.py @@ -1,4 +1,4 @@ -# Copyright (C) 2011 Statoil ASA, Norway. +# Copyright (C) 2011 Equinor ASA, Norway. # # The file 'ecl_subsidence.py' is part of ERT - Ensemble based # Reservoir Tool. @@ -49,6 +49,7 @@ class EclSubsidence(BaseCClass): _add_survey_PRESSURE = EclPrototype("void* ecl_subsidence_add_survey_PRESSURE( ecl_subsidence , char* , ecl_file_view )") _eval = EclPrototype("double ecl_subsidence_eval( ecl_subsidence , char* , char* , ecl_region , double , double , double, double, double)") _eval_geertsma = EclPrototype("double ecl_subsidence_eval_geertsma( ecl_subsidence , char* , char* , ecl_region , double , double , double, double, double, double)") + _eval_geertsma_rporv = EclPrototype("double ecl_subsidence_eval_geertsma_rporv( ecl_subsidence , char* , char* , ecl_region , double , double , double, double, double, double)") _has_survey = EclPrototype("bool ecl_subsidence_has_survey( ecl_subsidence , char*)") def __init__( self, grid, init_file ): @@ -103,6 +104,17 @@ class EclSubsidence(BaseCClass): return self._eval_geertsma(base_survey, monitor_survey, region, pos[0], pos[1], pos[2], youngs_modulus, poisson_ratio, seabed) + def eval_geertsma_rporv(self, base_survey, monitor_survey, pos, youngs_modulus, poisson_ratio, seabed, region=None): + if not base_survey in self: + raise KeyError("No such survey: %s" % base_survey) + + if monitor_survey is not None: + if not monitor_survey in self: + raise KeyError("No such survey: %s" % monitor_survey) + + return self._eval_geertsma_rporv(base_survey, monitor_survey, region, pos[0], pos[1], pos[2], youngs_modulus, poisson_ratio, seabed) + + def eval(self, base_survey, monitor_survey, pos, compressibility, poisson_ratio, region=None): """ Calculates the subsidence change between two surveys. diff --git a/ThirdParty/Ert/python/ecl/grid/__init__.py b/ThirdParty/Ert/python/ecl/grid/__init__.py index 69d110e0bf..b262c5b381 100644 --- a/ThirdParty/Ert/python/ecl/grid/__init__.py +++ b/ThirdParty/Ert/python/ecl/grid/__init__.py @@ -1,4 +1,4 @@ -# Copyright (C) 2018 Statoil ASA, Norway. +# Copyright (C) 2018 Equinor ASA, Norway. # # This file is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/grid/cell.py b/ThirdParty/Ert/python/ecl/grid/cell.py index 5824d6fc47..ee6949624e 100644 --- a/ThirdParty/Ert/python/ecl/grid/cell.py +++ b/ThirdParty/Ert/python/ecl/grid/cell.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright (C) 2017 Statoil ASA, Norway. +# Copyright (C) 2017 Equinor ASA, Norway. # # This file is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/grid/ecl_grid.py b/ThirdParty/Ert/python/ecl/grid/ecl_grid.py index 9afc3acd30..e8b662b006 100644 --- a/ThirdParty/Ert/python/ecl/grid/ecl_grid.py +++ b/ThirdParty/Ert/python/ecl/grid/ecl_grid.py @@ -1,4 +1,4 @@ -# Copyright (C) 2011 Statoil ASA, Norway. +# Copyright (C) 2011 Equinor ASA, Norway. # # The file 'ecl_grid.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/grid/ecl_grid_generator.py b/ThirdParty/Ert/python/ecl/grid/ecl_grid_generator.py index 7bdf798bd3..66d4eec2a3 100644 --- a/ThirdParty/Ert/python/ecl/grid/ecl_grid_generator.py +++ b/ThirdParty/Ert/python/ecl/grid/ecl_grid_generator.py @@ -1,4 +1,4 @@ -# Copyright (C) 2017 Statoil ASA, Norway. +# Copyright (C) 2017 Equinor ASA, Norway. # # The file 'ecl_grid_generator.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/grid/ecl_region.py b/ThirdParty/Ert/python/ecl/grid/ecl_region.py index 295f0e59f9..db1a0bc092 100644 --- a/ThirdParty/Ert/python/ecl/grid/ecl_region.py +++ b/ThirdParty/Ert/python/ecl/grid/ecl_region.py @@ -1,4 +1,4 @@ -# Copyright (C) 2011 Statoil ASA, Norway. +# Copyright (C) 2011 Equinor ASA, Norway. # # The file 'ecl_region.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/grid/faults/fault.py b/ThirdParty/Ert/python/ecl/grid/faults/fault.py index ac5ef42acb..986b6288ba 100644 --- a/ThirdParty/Ert/python/ecl/grid/faults/fault.py +++ b/ThirdParty/Ert/python/ecl/grid/faults/fault.py @@ -1,4 +1,4 @@ -# Copyright (C) 2014 Statoil ASA, Norway. +# Copyright (C) 2014 Equinor ASA, Norway. # # The file 'fault.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/grid/faults/fault_block.py b/ThirdParty/Ert/python/ecl/grid/faults/fault_block.py index e5313170a7..0757b9e4eb 100644 --- a/ThirdParty/Ert/python/ecl/grid/faults/fault_block.py +++ b/ThirdParty/Ert/python/ecl/grid/faults/fault_block.py @@ -1,4 +1,4 @@ -# Copyright (C) 2014 Statoil ASA, Norway. +# Copyright (C) 2014 Equinor ASA, Norway. # # The file 'fault_block.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/grid/faults/fault_block_collection.py b/ThirdParty/Ert/python/ecl/grid/faults/fault_block_collection.py index 16166c3ea6..bc4ad438c6 100644 --- a/ThirdParty/Ert/python/ecl/grid/faults/fault_block_collection.py +++ b/ThirdParty/Ert/python/ecl/grid/faults/fault_block_collection.py @@ -1,4 +1,4 @@ -# Copyright (C) 2014 Statoil ASA, Norway. +# Copyright (C) 2014 Equinor ASA, Norway. # # The file 'fault_block_collection.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/grid/faults/fault_block_layer.py b/ThirdParty/Ert/python/ecl/grid/faults/fault_block_layer.py index cc84d65981..e51e889c19 100644 --- a/ThirdParty/Ert/python/ecl/grid/faults/fault_block_layer.py +++ b/ThirdParty/Ert/python/ecl/grid/faults/fault_block_layer.py @@ -1,4 +1,4 @@ -# Copyright (C) 2014 Statoil ASA, Norway. +# Copyright (C) 2014 Equinor ASA, Norway. # # The file 'fault_block_layer.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/grid/faults/fault_collection.py b/ThirdParty/Ert/python/ecl/grid/faults/fault_collection.py index 704c5fad87..755ff90d58 100644 --- a/ThirdParty/Ert/python/ecl/grid/faults/fault_collection.py +++ b/ThirdParty/Ert/python/ecl/grid/faults/fault_collection.py @@ -1,4 +1,4 @@ -# Copyright (C) 2014 Statoil ASA, Norway. +# Copyright (C) 2014 Equinor ASA, Norway. # # The file 'fault_collection.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/grid/faults/fault_line.py b/ThirdParty/Ert/python/ecl/grid/faults/fault_line.py index 10ef3da0e8..cbd9b7a67b 100644 --- a/ThirdParty/Ert/python/ecl/grid/faults/fault_line.py +++ b/ThirdParty/Ert/python/ecl/grid/faults/fault_line.py @@ -1,4 +1,4 @@ -# Copyright (C) 2014 Statoil ASA, Norway. +# Copyright (C) 2014 Equinor ASA, Norway. # # The file 'fault_line.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/grid/faults/fault_segments.py b/ThirdParty/Ert/python/ecl/grid/faults/fault_segments.py index 7949a44d0e..b7af6ea97f 100644 --- a/ThirdParty/Ert/python/ecl/grid/faults/fault_segments.py +++ b/ThirdParty/Ert/python/ecl/grid/faults/fault_segments.py @@ -1,4 +1,4 @@ -# Copyright (C) 2014. Statoil ASA, Norway. +# Copyright (C) 2014. Equinor ASA, Norway. # # This file is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/grid/faults/layer.py b/ThirdParty/Ert/python/ecl/grid/faults/layer.py index 855f8f6be0..dc8df60a29 100644 --- a/ThirdParty/Ert/python/ecl/grid/faults/layer.py +++ b/ThirdParty/Ert/python/ecl/grid/faults/layer.py @@ -1,4 +1,4 @@ -# Copyright (C) 2014 Statoil ASA, Norway. +# Copyright (C) 2014 Equinor ASA, Norway. # # The file 'layer.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/rft/__init__.py b/ThirdParty/Ert/python/ecl/rft/__init__.py index d4efcd32c0..ac830d914b 100644 --- a/ThirdParty/Ert/python/ecl/rft/__init__.py +++ b/ThirdParty/Ert/python/ecl/rft/__init__.py @@ -1,4 +1,4 @@ -# Copyright (C) 2018 Statoil ASA, Norway. +# Copyright (C) 2018 Equinor ASA, Norway. # # This file is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/rft/ecl_rft.py b/ThirdParty/Ert/python/ecl/rft/ecl_rft.py index 38411dfd4b..493fa47727 100644 --- a/ThirdParty/Ert/python/ecl/rft/ecl_rft.py +++ b/ThirdParty/Ert/python/ecl/rft/ecl_rft.py @@ -1,4 +1,4 @@ -# Copyright (C) 2011 Statoil ASA, Norway. +# Copyright (C) 2011 Equinor ASA, Norway. # # The file 'ecl_rft.py' is part of ERT - Ensemble based Reservoir Tool. # @@ -53,8 +53,6 @@ class EclRFT(BaseCClass): _get_date = EclPrototype("time_t ecl_rft_node_get_date( ecl_rft )") _get_size = EclPrototype("int ecl_rft_node_get_size( ecl_rft )") _iget_cell = EclPrototype("void* ecl_rft_node_iget_cell( ecl_rft )") - _iget_cell_sorted = EclPrototype("void* ecl_rft_node_iget_cell_sorted( ecl_rft )") - _sort_cells = EclPrototype("void* ecl_rft_node_inplace_sort_cells( ecl_rft )") _iget_depth = EclPrototype("double ecl_rft_node_iget_depth( ecl_rft )") _iget_pressure = EclPrototype("double ecl_rft_node_iget_pressure(ecl_rft)") _iget_ijk = EclPrototype("void ecl_rft_node_iget_ijk( ecl_rft , int , int*, int*, int*)") @@ -165,6 +163,9 @@ class EclRFT(BaseCClass): The return value from the __getitem__() method is either an EclRFTCell instance or a EclPLTCell instance, depending on the type of this particular RFT object. + + For MSW wells the cells will come in sorted order along the wellpath, + for other well types the cells will come sorted in input order. """ self.assert_cell_index( index ) cell_ptr = self._iget_cell( index ) @@ -175,46 +176,6 @@ class EclRFT(BaseCClass): return self[index] - def iget_sorted( self , index ): - """ - Will return the cell nr @index in the list of sorted cells. - - See method sort() for further documentation. - """ - self.assert_cell_index( index ) - cell_ptr = self._iget_cell_sorted( index ) - return self.__cell_ref( cell_ptr ) - - - def sort(self): - """ - Will sort cells in RFT; currently only applies to MSW wells. - - By default the cells in the RFT come in the order they are - specified in the ECLIPSE input file; that is not necessarily - in a suitable order. In the case of MSW wells it is possible - to sort the connections after distance along the wellpath. To - access the cells in sort order you have two options: - - 1. Sort the cells using the sort() method, and then - subsequently access them sequentially: - - rft.sort() - for cell in rft: - print cell - - 2. Let the rft object stay unsorted, but access the cells - using the iget_sorted() method: - - for i in range(len(rft)): - cell = rft.iget_sorted( i ) - - Currently only MSW/PLTs are sorted, based on the CONLENST - keyword; for other wells the sort() method does nothing. - """ - self._sort_cells( ) - - # ijk are zero offset def ijkget( self , ijk ): """ diff --git a/ThirdParty/Ert/python/ecl/rft/ecl_rft_cell.py b/ThirdParty/Ert/python/ecl/rft/ecl_rft_cell.py index 13a80cc4b6..ae01fb1ff6 100644 --- a/ThirdParty/Ert/python/ecl/rft/ecl_rft_cell.py +++ b/ThirdParty/Ert/python/ecl/rft/ecl_rft_cell.py @@ -1,4 +1,4 @@ -# Copyright (C) 2011 Statoil ASA, Norway. +# Copyright (C) 2011 Equinor ASA, Norway. # # The file 'ecl_rft_cell.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/rft/well_trajectory.py b/ThirdParty/Ert/python/ecl/rft/well_trajectory.py index abe0cadcd5..7df3a76c80 100644 --- a/ThirdParty/Ert/python/ecl/rft/well_trajectory.py +++ b/ThirdParty/Ert/python/ecl/rft/well_trajectory.py @@ -1,4 +1,4 @@ -# Copyright (C) 2015 Statoil ASA, Norway. +# Copyright (C) 2015 Equinor ASA, Norway. # # The file 'well_trajectory.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/summary/__init__.py b/ThirdParty/Ert/python/ecl/summary/__init__.py index 946fcf6e8d..064164accf 100644 --- a/ThirdParty/Ert/python/ecl/summary/__init__.py +++ b/ThirdParty/Ert/python/ecl/summary/__init__.py @@ -1,4 +1,4 @@ -# Copyright (C) 2018 Statoil ASA, Norway. +# Copyright (C) 2018 Equinor ASA, Norway. # # This file is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/summary/ecl_cmp.py b/ThirdParty/Ert/python/ecl/summary/ecl_cmp.py index ce705d20e7..dfbcf626a2 100644 --- a/ThirdParty/Ert/python/ecl/summary/ecl_cmp.py +++ b/ThirdParty/Ert/python/ecl/summary/ecl_cmp.py @@ -1,4 +1,4 @@ -# Copyright (C) 2015 Statoil ASA, Norway. +# Copyright (C) 2015 Equinor ASA, Norway. # # The file 'ecl_cmp.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/summary/ecl_npv.py b/ThirdParty/Ert/python/ecl/summary/ecl_npv.py index 67363f2669..3f1fbe42ad 100644 --- a/ThirdParty/Ert/python/ecl/summary/ecl_npv.py +++ b/ThirdParty/Ert/python/ecl/summary/ecl_npv.py @@ -1,4 +1,4 @@ -# Copyright (C) 2013 Statoil ASA, Norway. +# Copyright (C) 2013 Equinor ASA, Norway. # # The file 'ecl_npv.py' is part of ERT - Ensemble based Reservoir Tool. # @@ -136,7 +136,7 @@ class NPVPriceVector(object): class EclNPV(object): - sumKeyRE = re.compile("[[]([\w:,]+)[]]") + sumKeyRE = re.compile("[\[]([\w:,]+)[\]]") def __init__(self, baseCase): diff --git a/ThirdParty/Ert/python/ecl/summary/ecl_smspec_node.py b/ThirdParty/Ert/python/ecl/summary/ecl_smspec_node.py index 893eb66162..676515bd1d 100644 --- a/ThirdParty/Ert/python/ecl/summary/ecl_smspec_node.py +++ b/ThirdParty/Ert/python/ecl/summary/ecl_smspec_node.py @@ -1,4 +1,4 @@ -# Copyright (C) 2016 Statoil ASA, Norway. +# Copyright (C) 2016 Equinor ASA, Norway. # # This file is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/summary/ecl_sum.py b/ThirdParty/Ert/python/ecl/summary/ecl_sum.py index 029334836a..f721ee9dee 100644 --- a/ThirdParty/Ert/python/ecl/summary/ecl_sum.py +++ b/ThirdParty/Ert/python/ecl/summary/ecl_sum.py @@ -1,4 +1,4 @@ -# Copyright (C) 2011 Statoil ASA, Norway. +# Copyright (C) 2011 Equinor ASA, Norway. # # The file 'ecl_sum.py' is part of ERT - Ensemble based Reservoir Tool. # @@ -26,6 +26,8 @@ import numpy import datetime import os.path import ctypes +import pandas +import re # Observe that there is some convention conflict with the C code # regarding order of arguments: The C code generally takes the time @@ -90,7 +92,7 @@ class EclSum(BaseCClass): _fread_alloc = EclPrototype("void* ecl_sum_fread_alloc(char*, stringlist, char*, bool)", bind=False) _create_restart_writer = EclPrototype("ecl_sum_obj ecl_sum_alloc_restart_writer2(char*, char*, int, bool, bool, char*, time_t, bool, int, int, int)", bind = False) _create_writer = EclPrototype("ecl_sum_obj ecl_sum_alloc_writer(char*, bool, bool, char*, time_t, bool, int, int, int)", bind = False) - _resample = EclPrototype("ecl_sum_obj ecl_sum_alloc_resample( ecl_sum, char*, time_t_vector)") + _resample = EclPrototype("ecl_sum_obj ecl_sum_alloc_resample( ecl_sum, char*, time_t_vector, bool, bool)") _iiget = EclPrototype("double ecl_sum_iget(ecl_sum, int, int)") _free = EclPrototype("void ecl_sum_free(ecl_sum)") _data_length = EclPrototype("int ecl_sum_get_data_length(ecl_sum)") @@ -303,9 +305,8 @@ class EclSum(BaseCClass): raise TypeError('Parameter sim_days should be float, was %r' % sim_days) sim_seconds = sim_days * 24 * 60 * 60 - - return self._add_tstep(report_step, sim_seconds).setParent(parent=self) - + tstep = self._add_tstep(report_step, sim_seconds).setParent(parent=self) + return tstep @@ -500,7 +501,6 @@ class EclSum(BaseCClass): .... """ from ecl.summary import EclSumKeyWordVector - import pandas if column_keys is None: keywords = EclSumKeyWordVector(self, add_keywords = True) else: @@ -524,6 +524,61 @@ class EclSum(BaseCClass): frame = pandas.DataFrame(index = time_index, columns=list(keywords), data=data) return frame + @staticmethod + def _compile_headers_list(headers, dims): + var_list = [] + for key in headers: + lst = re.split(':', key) + kw = lst[0] + wgname = None + num = 0; + unit = "UNIT" + if len(lst) > 1: + nums = [] + if lst[1][0].isdigit(): + nums = re.split(',', lst[1]) + else: + wgname = lst[1] + if len(lst) == 3: + nums = re.split(",", lst[2]) + if len(nums) == 3: + i = int(nums[0])-1 + j = int(nums[1])-1 + k = int(nums[2])-1 + if dims is None: + raise ValueError("For key %s When using indexing i,j,k you must supply a valid value for the dims argument" % key) + num = i + j * dims[0] + k * dims[0]*dims[1] + 1 + elif len(nums) == 1: + num = int(nums[0]) + + var_list.append( [kw, wgname, num, unit] ) + return var_list + + @classmethod + def from_pandas(cls, case, frame, dims = None, headers = None): + start_time = frame.index[0] + var_list = [] + if headers is None: + header_list = EclSum._compile_headers_list( frame.columns.values, dims ) + else: + header_list = EclSum._compile_headers_list( headers, dims ) + if dims is None: + dims = [1,1,1]; + ecl_sum = EclSum.writer(case, + start_time.to_pydatetime(), + dims[0], dims[1], dims[2]) + for kw, wgname, num, unit in header_list: + var_list.append( ecl_sum.addVariable( kw , wgname = wgname , num = num, unit =unit).getKey1() ) + + for i, time in enumerate(frame.index): + days = (time - start_time).days + t_step = ecl_sum.addTStep( i+1 , days ) + + for var in var_list: + t_step[var] = frame.iloc[i][var] + + return ecl_sum + def get_key_index(self, key): """ @@ -1481,8 +1536,12 @@ are advised to fetch vector as a numpy vector and then scale that yourself: - def resample(self, new_case_name, time_points): - return self._resample(new_case_name, time_points) + def resample(self, new_case_name, time_points, lower_extrapolation=False, upper_extrapolation=False): + new_case = self._resample(new_case_name, time_points, lower_extrapolation, upper_extrapolation) + if new_case is None: + raise ValueError("Failed to create new resampled case:{}".format(new_case_name)) + + return new_case import ecl.summary.ecl_sum_keyword_vector diff --git a/ThirdParty/Ert/python/ecl/summary/ecl_sum_keyword_vector.py b/ThirdParty/Ert/python/ecl/summary/ecl_sum_keyword_vector.py index a3fc4c12a6..466106bfcc 100644 --- a/ThirdParty/Ert/python/ecl/summary/ecl_sum_keyword_vector.py +++ b/ThirdParty/Ert/python/ecl/summary/ecl_sum_keyword_vector.py @@ -1,4 +1,4 @@ -# Copyright (C) 2011 Statoil ASA, Norway. +# Copyright (C) 2011 Equinor ASA, Norway. # # The file 'ecl_sum_keyword_vector.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/summary/ecl_sum_tstep.py b/ThirdParty/Ert/python/ecl/summary/ecl_sum_tstep.py index 0b165e6e0a..1fa471619b 100644 --- a/ThirdParty/Ert/python/ecl/summary/ecl_sum_tstep.py +++ b/ThirdParty/Ert/python/ecl/summary/ecl_sum_tstep.py @@ -1,4 +1,4 @@ -# Copyright (C) 2017 Statoil ASA, Norway. +# Copyright (C) 2017 Equinor ASA, Norway. # # This file is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/summary/ecl_sum_var_type.py b/ThirdParty/Ert/python/ecl/summary/ecl_sum_var_type.py index 039105f497..3d19a9eff3 100644 --- a/ThirdParty/Ert/python/ecl/summary/ecl_sum_var_type.py +++ b/ThirdParty/Ert/python/ecl/summary/ecl_sum_var_type.py @@ -1,4 +1,4 @@ -# Copyright (C) 2016 Statoil ASA, Norway. +# Copyright (C) 2016 Equinor ASA, Norway. # # The file 'ecl_sum_var_type.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/summary/ecl_sum_vector.py b/ThirdParty/Ert/python/ecl/summary/ecl_sum_vector.py index 8c7a614eef..3feff8d326 100644 --- a/ThirdParty/Ert/python/ecl/summary/ecl_sum_vector.py +++ b/ThirdParty/Ert/python/ecl/summary/ecl_sum_vector.py @@ -1,4 +1,4 @@ -# Copyright (C) 2017 Statoil ASA, Norway. +# Copyright (C) 2017 Equinor ASA, Norway. # # This file is part of ERT - Ensemble based Reservoir Tool. # @@ -46,7 +46,7 @@ class EclSumVector(object): self.__dates = parent.get_dates(report_only) self.__days = parent.get_days(report_only) - self.__mpl_dates = parent.get_mpl_dates(report_only) + self.__numpy_dates = parent.numpy_dates self.__report_step = parent.get_report_step(report_only) self.__values = None @@ -99,8 +99,21 @@ class EclSumVector(object): def mpl_dates(self): """ All the dates as numpy vector of dates in matplotlib format. + This property will be replaced by numpy_dates, but is kept for + backwards-compatibility for the time-being. Usage will trigger + a depreciation warning. """ - return self.__mpl_dates + warnings.warn("The mpl_dates property has been deprecated - use numpy_dates instead", + DeprecationWarning) + + return self.parent.get_mpl_dates(self.report_only) + + @property + def numpy_dates(self): + """ + All the dates as numpy vector of dates in numpy format. + """ + return self.__numpy_dates @property def report_step(self): @@ -119,7 +132,7 @@ class EclSumVector(object): return EclSumNode(self.__report_step[index], self.__days[index], self.__dates[index], - self.__mpl_dates[index], + self.mpl_dates[index], self.__values[index]) diff --git a/ThirdParty/Ert/python/ecl/util/geometry/__init__.py b/ThirdParty/Ert/python/ecl/util/geometry/__init__.py index e4bc012dc9..d970567ebe 100644 --- a/ThirdParty/Ert/python/ecl/util/geometry/__init__.py +++ b/ThirdParty/Ert/python/ecl/util/geometry/__init__.py @@ -1,4 +1,4 @@ -# Copyright (C) 2011 Statoil ASA, Norway. +# Copyright (C) 2011 Equinor ASA, Norway. # # The file '__init__.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/util/geometry/cpolyline.py b/ThirdParty/Ert/python/ecl/util/geometry/cpolyline.py index 227413182b..550bd68bcb 100644 --- a/ThirdParty/Ert/python/ecl/util/geometry/cpolyline.py +++ b/ThirdParty/Ert/python/ecl/util/geometry/cpolyline.py @@ -1,4 +1,4 @@ -# Copyright (C) 2011 Statoil ASA, Norway. +# Copyright (C) 2011 Equinor ASA, Norway. # # This file is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/util/geometry/cpolyline_collection.py b/ThirdParty/Ert/python/ecl/util/geometry/cpolyline_collection.py index 335f3092b6..814900cca1 100644 --- a/ThirdParty/Ert/python/ecl/util/geometry/cpolyline_collection.py +++ b/ThirdParty/Ert/python/ecl/util/geometry/cpolyline_collection.py @@ -1,4 +1,4 @@ -# Copyright (C) 2014 Statoil ASA, Norway. +# Copyright (C) 2014 Equinor ASA, Norway. # # The file 'cpolyline_collection.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/util/geometry/geo_pointset.py b/ThirdParty/Ert/python/ecl/util/geometry/geo_pointset.py index 6286de3eef..501af9e451 100644 --- a/ThirdParty/Ert/python/ecl/util/geometry/geo_pointset.py +++ b/ThirdParty/Ert/python/ecl/util/geometry/geo_pointset.py @@ -1,4 +1,4 @@ -# Copyright (C) 2017 Statoil ASA, Norway. +# Copyright (C) 2017 Equinor ASA, Norway. # # This file is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/util/geometry/geo_region.py b/ThirdParty/Ert/python/ecl/util/geometry/geo_region.py index 9d4e290147..fab03e64c9 100644 --- a/ThirdParty/Ert/python/ecl/util/geometry/geo_region.py +++ b/ThirdParty/Ert/python/ecl/util/geometry/geo_region.py @@ -1,4 +1,4 @@ -# Copyright (C) 2017 Statoil ASA, Norway. +# Copyright (C) 2017 Equinor ASA, Norway. # # This file is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/util/geometry/surface.py b/ThirdParty/Ert/python/ecl/util/geometry/surface.py index ba610cb9bc..8152b1cc08 100644 --- a/ThirdParty/Ert/python/ecl/util/geometry/surface.py +++ b/ThirdParty/Ert/python/ecl/util/geometry/surface.py @@ -1,4 +1,4 @@ -# Copyright (C) 2016 Statoil ASA, Norway. +# Copyright (C) 2016 Equinor ASA, Norway. # # The file 'surface' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/util/test/CMakeLists.txt b/ThirdParty/Ert/python/ecl/util/test/CMakeLists.txt index 4d87b9efca..50c2a9bd09 100644 --- a/ThirdParty/Ert/python/ecl/util/test/CMakeLists.txt +++ b/ThirdParty/Ert/python/ecl/util/test/CMakeLists.txt @@ -6,7 +6,6 @@ set(PYTHON_SOURCES test_run.py source_enumerator.py test_area.py - temp_area.py path_context.py lint_test_case.py import_test_case.py diff --git a/ThirdParty/Ert/python/ecl/util/test/__init__.py b/ThirdParty/Ert/python/ecl/util/test/__init__.py index 1cc89f8d32..ab79dd25d9 100644 --- a/ThirdParty/Ert/python/ecl/util/test/__init__.py +++ b/ThirdParty/Ert/python/ecl/util/test/__init__.py @@ -3,7 +3,6 @@ from .test_run import path_exists from .extended_testcase import ExtendedTestCase from .source_enumerator import SourceEnumerator from .test_area import TestArea , TestAreaContext -from .temp_area import TempArea , TempAreaContext from .ert_test_runner import ErtTestRunner from .path_context import PathContext from .lint_test_case import LintTestCase diff --git a/ThirdParty/Ert/python/ecl/util/test/ecl_mock/ecl_sum_mock.py b/ThirdParty/Ert/python/ecl/util/test/ecl_mock/ecl_sum_mock.py index 9fc8b7a8b1..3096791654 100644 --- a/ThirdParty/Ert/python/ecl/util/test/ecl_mock/ecl_sum_mock.py +++ b/ThirdParty/Ert/python/ecl/util/test/ecl_mock/ecl_sum_mock.py @@ -39,8 +39,10 @@ def createEclSum( case, days = time_offset + report_step * report_step_length + mini_step * mini_step_length t_step = ecl_sum.addTStep( report_step + 1 , sim_days = days ) + for var in var_list: key = var.getKey1( ) + if key in func_table: func = func_table[key] t_step[key] = func( days ) diff --git a/ThirdParty/Ert/python/ecl/util/test/ert_test_context.py b/ThirdParty/Ert/python/ecl/util/test/ert_test_context.py index dd89c5a720..931578ac79 100644 --- a/ThirdParty/Ert/python/ecl/util/test/ert_test_context.py +++ b/ThirdParty/Ert/python/ecl/util/test/ert_test_context.py @@ -1,4 +1,4 @@ -# Copyright (C) 2013 Statoil ASA, Norway. +# Copyright (C) 2013 Equinor ASA, Norway. # # The file 'test_work_area.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/util/test/import_test_case.py b/ThirdParty/Ert/python/ecl/util/test/import_test_case.py index 13b940d49b..089107f2b7 100644 --- a/ThirdParty/Ert/python/ecl/util/test/import_test_case.py +++ b/ThirdParty/Ert/python/ecl/util/test/import_test_case.py @@ -1,4 +1,4 @@ -# Copyright (C) 2017 Statoil ASA, Norway. +# Copyright (C) 2017 Equinor ASA, Norway. # # This file is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/util/test/lint_test_case.py b/ThirdParty/Ert/python/ecl/util/test/lint_test_case.py index ff3bd729d6..3b27225384 100644 --- a/ThirdParty/Ert/python/ecl/util/test/lint_test_case.py +++ b/ThirdParty/Ert/python/ecl/util/test/lint_test_case.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright (C) 2017 Statoil ASA, Norway. +# Copyright (C) 2017 Equinor ASA, Norway. # # This file is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/util/test/temp_area.py b/ThirdParty/Ert/python/ecl/util/test/temp_area.py deleted file mode 100644 index 4b7d2aa697..0000000000 --- a/ThirdParty/Ert/python/ecl/util/test/temp_area.py +++ /dev/null @@ -1,81 +0,0 @@ -# Copyright (C) 2016 Statoil ASA, Norway. -# -# The file 'temp_area.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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. - -import os -import os.path -from ecl import EclPrototype -from . import TestArea - -class TempArea(TestArea): - """TempArea class is essentially similar to the TestArea class, with - the only difference that the cwd is *not* changed into the newly - created area. - """ - - _temp_area_alloc = EclPrototype("void* temp_area_alloc( char* )" , bind = False) - _temp_area_alloc_relative = EclPrototype("void* temp_area_alloc_relative( char* , char* )" , bind = False) - - def __init__(self, name, prefix = None , store_area=False): - if prefix: - if os.path.exists( prefix ): - c_ptr = self._temp_area_alloc_relative(prefix , name) - else: - raise IOError("The prefix path:%s must exist" % prefix) - else: - c_ptr = self._temp_area_alloc(name) - super(TempArea, self).__init__(name , c_ptr = c_ptr , store_area = store_area) - - - def __str__(self): - return self.getPath() - - - def get_cwd(self): - """ - Since the TempArea class does *not* change the cwd this method - just returns the ordinary os.getcwd(). - """ - return os.getcwd() - - - def getPath(self): - """ - Will return the full path to the temporary working area. - """ - return self._get_cwd( ) - - - -class TempAreaContext(object): - def __init__(self, name, prefix = None , store_area=False): - self.name = name - self.store_area = store_area - self.prefix = prefix - - def __enter__(self): - """ - @rtype: TempArea - """ - self.temp_area = TempArea(self.name, prefix = self.prefix , store_area = self.store_area ) - return self.temp_area - - - def __exit__(self, exc_type, exc_val, exc_tb): - del self.temp_area - return False - - - diff --git a/ThirdParty/Ert/python/ecl/util/test/test_area.py b/ThirdParty/Ert/python/ecl/util/test/test_area.py index 22089bd86c..929bae6ff2 100644 --- a/ThirdParty/Ert/python/ecl/util/test/test_area.py +++ b/ThirdParty/Ert/python/ecl/util/test/test_area.py @@ -1,4 +1,4 @@ -# Copyright (C) 2013 Statoil ASA, Norway. +# Copyright (C) 2013 Equinor ASA, Norway. # # The file 'test_work_area.py' is part of ERT - Ensemble based Reservoir Tool. # @@ -20,8 +20,7 @@ from ecl import EclPrototype class TestArea(BaseCClass): - _test_area_alloc = EclPrototype("void* test_work_area_alloc( char* )" , bind = False) - _test_area_alloc_relative = EclPrototype("void* test_work_area_alloc_relative( char* , char* )" , bind = False) + _test_area_alloc = EclPrototype("void* test_work_area_alloc__( char*, bool )" , bind = False) _free = EclPrototype("void test_work_area_free( test_area )") _install_file = EclPrototype("void test_work_area_install_file( test_area , char* )") _copy_directory = EclPrototype("void test_work_area_copy_directory( test_area , char* )") @@ -31,22 +30,13 @@ class TestArea(BaseCClass): _copy_parent_content = EclPrototype("void test_work_area_copy_parent_content( test_area , char* )") _get_cwd = EclPrototype("char* test_work_area_get_cwd( test_area )") _get_original_cwd = EclPrototype("char* test_work_area_get_original_cwd( test_area )") - _set_store = EclPrototype("void test_work_area_set_store( test_area , bool)") - _sync = EclPrototype("void test_work_area_sync( test_area )") - def __init__(self, test_name, prefix = None , store_area=False , c_ptr = None): + def __init__(self, test_name, store_area=False , c_ptr = None): if c_ptr is None: - if prefix: - if os.path.exists( prefix ): - c_ptr = self._test_area_alloc_relative(prefix , test_name) - else: - raise IOError("The prefix path:%s must exist" % prefix) - else: - c_ptr = self._test_area_alloc(test_name) + c_ptr = self._test_area_alloc(test_name, store_area) super(TestArea, self).__init__(c_ptr) - self.set_store( store_area ) def get_original_cwd(self): @@ -111,10 +101,6 @@ class TestArea(BaseCClass): self._free() - def set_store(self, store): - self._set_store(store) - - def getFullPath(self , path): if not os.path.exists( path ): raise IOError("Path not found:%s" % path) @@ -125,22 +111,17 @@ class TestArea(BaseCClass): return os.path.join( self.get_cwd() , path ) - def sync(self): - return self._sync( ) - - class TestAreaContext(object): - def __init__(self, test_name, prefix = None , store_area=False): + def __init__(self, test_name, store_area=False): self.test_name = test_name self.store_area = store_area - self.prefix = prefix def __enter__(self): """ @rtype: TestArea """ - self.test_area = TestArea(self.test_name, prefix = self.prefix , store_area = self.store_area ) + self.test_area = TestArea(self.test_name, store_area = self.store_area ) return self.test_area diff --git a/ThirdParty/Ert/python/ecl/util/test/test_run.py b/ThirdParty/Ert/python/ecl/util/test/test_run.py index 496353ba4d..b32a8f45c5 100644 --- a/ThirdParty/Ert/python/ecl/util/test/test_run.py +++ b/ThirdParty/Ert/python/ecl/util/test/test_run.py @@ -1,4 +1,4 @@ -# Copyright (C) 2013 Statoil ASA, Norway. +# Copyright (C) 2013 Equinor ASA, Norway. # # The file 'test_run.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/util/util/__init__.py b/ThirdParty/Ert/python/ecl/util/util/__init__.py index aa5edf30b6..3960e7bfd2 100644 --- a/ThirdParty/Ert/python/ecl/util/util/__init__.py +++ b/ThirdParty/Ert/python/ecl/util/util/__init__.py @@ -1,4 +1,4 @@ -# Copyright (C) 2011 Statoil ASA, Norway. +# Copyright (C) 2011 Equinor ASA, Norway. # # The file '__init__.py' is part of ERT - Ensemble based Reservoir Tool. # @@ -71,7 +71,7 @@ from .cwd_context import CWDContext ### the process of changing camelCase function names to snake_case function ### names. ### -### See https://github.com/Statoil/libecl/issues/142 for a discussion and for +### See https://github.com/Equinor/libecl/issues/142 for a discussion and for ### usage. ### diff --git a/ThirdParty/Ert/python/ecl/util/util/arg_pack.py b/ThirdParty/Ert/python/ecl/util/util/arg_pack.py index 4b53e03b18..018cffcb48 100644 --- a/ThirdParty/Ert/python/ecl/util/util/arg_pack.py +++ b/ThirdParty/Ert/python/ecl/util/util/arg_pack.py @@ -1,4 +1,4 @@ -# Copyright (C) 2015 Statoil ASA, Norway. +# Copyright (C) 2015 Equinor ASA, Norway. # # The file 'arg_pack.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/util/util/bool_vector.py b/ThirdParty/Ert/python/ecl/util/util/bool_vector.py index d688562682..cb68a2d013 100644 --- a/ThirdParty/Ert/python/ecl/util/util/bool_vector.py +++ b/ThirdParty/Ert/python/ecl/util/util/bool_vector.py @@ -1,4 +1,4 @@ -# Copyright (C) 2014 Statoil ASA, Norway. +# Copyright (C) 2014 Equinor ASA, Norway. # # The file 'vector_template.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/util/util/cthread_pool.py b/ThirdParty/Ert/python/ecl/util/util/cthread_pool.py index 39d8c3be91..30c923e8f3 100644 --- a/ThirdParty/Ert/python/ecl/util/util/cthread_pool.py +++ b/ThirdParty/Ert/python/ecl/util/util/cthread_pool.py @@ -1,4 +1,4 @@ -# Copyright (C) 2015 Statoil ASA, Norway. +# Copyright (C) 2015 Equinor ASA, Norway. # # The file 'cthread_pool.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/util/util/ctime.py b/ThirdParty/Ert/python/ecl/util/util/ctime.py index 0c92ecd893..173f7c64ad 100644 --- a/ThirdParty/Ert/python/ecl/util/util/ctime.py +++ b/ThirdParty/Ert/python/ecl/util/util/ctime.py @@ -1,4 +1,4 @@ -# Copyright (C) 2011 Statoil ASA, Norway. +# Copyright (C) 2011 Equinor ASA, Norway. # # The file 'ctime.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/util/util/double_vector.py b/ThirdParty/Ert/python/ecl/util/util/double_vector.py index 9ba7100958..c9fa16d66f 100644 --- a/ThirdParty/Ert/python/ecl/util/util/double_vector.py +++ b/ThirdParty/Ert/python/ecl/util/util/double_vector.py @@ -1,4 +1,4 @@ -# Copyright (C) 2014 Statoil ASA, Norway. +# Copyright (C) 2014 Equinor ASA, Norway. # # The file 'double_vector.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/util/util/hash.py b/ThirdParty/Ert/python/ecl/util/util/hash.py index 3edc600763..62def2f3c3 100644 --- a/ThirdParty/Ert/python/ecl/util/util/hash.py +++ b/ThirdParty/Ert/python/ecl/util/util/hash.py @@ -1,4 +1,4 @@ -# Copyright (C) 2011 Statoil ASA, Norway. +# Copyright (C) 2011 Equinor ASA, Norway. # # The file 'hash.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/util/util/int_vector.py b/ThirdParty/Ert/python/ecl/util/util/int_vector.py index f280603df8..34c6cd8415 100644 --- a/ThirdParty/Ert/python/ecl/util/util/int_vector.py +++ b/ThirdParty/Ert/python/ecl/util/util/int_vector.py @@ -1,4 +1,4 @@ -# Copyright (C) 2014 Statoil ASA, Norway. +# Copyright (C) 2014 Equinor ASA, Norway. # # The file 'int_vector.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/util/util/lookup_table.py b/ThirdParty/Ert/python/ecl/util/util/lookup_table.py index 4d01ba8732..3ebf71c5f5 100644 --- a/ThirdParty/Ert/python/ecl/util/util/lookup_table.py +++ b/ThirdParty/Ert/python/ecl/util/util/lookup_table.py @@ -1,4 +1,4 @@ -# Copyright (C) 2011 Statoil ASA, Norway. +# Copyright (C) 2011 Equinor ASA, Norway. # # The file 'lookup_table.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/util/util/matrix.py b/ThirdParty/Ert/python/ecl/util/util/matrix.py deleted file mode 100644 index 160763987c..0000000000 --- a/ThirdParty/Ert/python/ecl/util/util/matrix.py +++ /dev/null @@ -1,230 +0,0 @@ - -# Copyright (C) 2011 Statoil ASA, Norway. -# -# The file 'matrix.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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. - - -# The Matrix class implemented here wraps the C matrix implementation -# in matrix.c from the libutil library. The C matrix implementation -# has the very limited ambition of just barely satisfying the matrix -# needs of the EnKF algorithm, i.e. for general linear algebra -# applications you will probably be better served by a more complete -# matrix library. This applies even more so to this Python -# implementation; it is only here facilitate use of C libraries which -# expect a matrix instance as input (i.e. the LARS estimator). For -# general linear algebra in Python the numpy library is a natural -# choice. - - -from cwrap import BaseCClass,CFILE -from ecl import EclPrototype - - -class Matrix(BaseCClass): - _matrix_alloc = EclPrototype("void* matrix_alloc(int, int )" , bind = False) - _matrix_alloc_identity = EclPrototype("matrix_obj matrix_alloc_identity( int )" , bind = False) - _alloc_transpose = EclPrototype("matrix_obj matrix_alloc_transpose(matrix)") - _inplace_transpose = EclPrototype("void matrix_inplace_transpose(matrix)") - _copy = EclPrototype("matrix_obj matrix_alloc_copy(matrix)" ) - _sub_copy = EclPrototype("matrix_obj matrix_alloc_sub_copy(matrix, int , int , int , int)" ) - _free = EclPrototype("void matrix_free(matrix)") - _iget = EclPrototype("double matrix_iget( matrix , int , int )") - _iset = EclPrototype("void matrix_iset( matrix , int , int , double)") - _set_all = EclPrototype("void matrix_scalar_set( matrix , double)") - _scale_column = EclPrototype("void matrix_scale_column(matrix , int , double)") - _scale_row = EclPrototype("void matrix_scale_row(matrix , int , double)") - _copy_column = EclPrototype("void matrix_copy_column(matrix , matrix , int , int)" , bind = False) - _rows = EclPrototype("int matrix_get_rows(matrix)") - _columns = EclPrototype("int matrix_get_columns(matrix)") - _equal = EclPrototype("bool matrix_equal(matrix, matrix)") - _pretty_print = EclPrototype("void matrix_pretty_print(matrix, char*, char*)") - _fprint = EclPrototype("void matrix_fprintf(matrix, char*, FILE)") - _random_init = EclPrototype("void matrix_random_init(matrix, rng)") - _dump_csv = EclPrototype("void matrix_dump_csv(matrix, char*)") - - # Requires BLAS. If the library does not have the - # matrix_alloc_matmul() function the prototype will have _func = - # None, and NotImplementedError( ) will be raised int the - # __call__() method if we try to use this function. - try: - _alloc_matmul = EclPrototype("matrix_obj matrix_alloc_matmul(matrix, matrix)" , bind = False) - except AttributeError: - _alloc_matmul = None - - # Requires BLAS! - @classmethod - def matmul(cls, m1,m2): - """ - Will return a new matrix which is matrix product of m1 and m2. - """ - if m1.columns( ) == m2.rows( ): - return cls._alloc_matmul( m1, m2) - else: - raise ValueError("Matrix size mismatch") - - - def __init__(self, rows, columns, value=0): - c_ptr = self._matrix_alloc(rows, columns) - super(Matrix, self).__init__(c_ptr) - self.setAll(value) - - def copy(self): - return self._copy( ) - - @classmethod - def identity(cls, dim): - """Returns a dim x dim identity matrix.""" - if dim < 1: - raise ValueError('Identity matrix must have positive size, %d not allowed.' % dim) - return cls._matrix_alloc_identity(dim) - - def subCopy(self, row_offset, column_offset, rows, columns): - if row_offset < 0 or row_offset >= self.rows(): - raise ValueError("Invalid row offset") - - if column_offset < 0 or column_offset >= self.columns(): - raise ValueError("Invalid column offset") - - if row_offset + rows > self.rows(): - raise ValueError("Invalid rows") - - if column_offset + columns > self.columns(): - raise ValueError("Invalid columns") - - return self._sub_copy( row_offset , column_offset , rows , columns) - - - def __str__(self): - s = "" - for i in range(self.rows()): - s += "[" - for j in range(self.columns()): - d = self._iget(i, j) - s += "%6.3g " % d - s += "]\n" - return s - - def __getitem__(self, index_tuple): - if not 0 <= index_tuple[0] < self.rows(): - raise IndexError("Expected 0 <= %d < %d" % (index_tuple[0], self.rows())) - - if not 0 <= index_tuple[1] < self.columns(): - raise IndexError("Expected 0 <= %d < %d" % (index_tuple[1], self.columns())) - - return self._iget(index_tuple[0], index_tuple[1]) - - def __setitem__(self, index_tuple, value): - if not 0 <= index_tuple[0] < self.rows(): - raise IndexError("Expected 0 <= %d < %d" % (index_tuple[0], self.rows())) - - if not 0 <= index_tuple[1] < self.columns(): - raise IndexError("Expected 0 <= %d < %d" % (index_tuple[1], self.columns())) - - return self._iset(index_tuple[0], index_tuple[1], value) - - def dims(self): - return self._rows(), self._columns() - - def rows(self): - """ @rtype: int """ - return self._rows() - - def transpose(self , inplace = False): - """ - Will transpose the matrix. By default a transposed copy is returned. - """ - if inplace: - self._inplace_transpose( ) - return self - else: - return self._alloc_transpose( ) - - - def columns(self): - """ @rtype: int """ - return self._columns() - - def __eq__(self, other): - assert isinstance(other, Matrix) - return self._equal(other) - - def scaleColumn(self, column, factor): - if not 0 <= column < self.columns(): - raise IndexError("Expected column: [0,%d) got:%d" % (self.columns(), column)) - self._scale_column(column, factor) - - def scaleRow(self, row, factor): - if not 0 <= row < self.rows(): - raise IndexError("Expected row: [0,%d) got:%d" % (self.rows(), row)) - self._scale_row(row, factor) - - def setAll(self, value): - self._set_all(value) - - def copyColumn(self, target_column, src_column): - columns = self.columns() - if not 0 <= src_column < columns: - raise ValueError("src column:%d invalid" % src_column) - - if not 0 <= target_column < columns: - raise ValueError("target column:%d invalid" % target_column) - - if src_column != target_column: - # The underlying C function accepts column copy between matrices. - Matrix._copy_column(self, self, target_column, src_column) - - - def dumpCSV(self , filename): - self._dump_csv( filename ) - - - def prettyPrint(self, name, fmt="%6.3g"): - self._pretty_print(name, fmt) - - def fprint(self , fileH , fmt = "%g "): - """Will print ASCII representation of matrix. - - The fileH argument should point to an open Python - filehandle. If you supply a fmt string it is important that it - contains a separator, otherwise you might risk that elements - overlap in the output. For the matrix: - - [0 1 2] - m = [3 4 5] - [6 7 8] - - The code: - - with open("matrix.txt" , "w") as f: - m.fprintf( f ) - - The file 'matrix.txt' will look like: - - 0 1 2 - 3 4 5 - 6 7 8 - - """ - self._fprint( fmt , CFILE( fileH)) - - - def randomInit(self, rng): - self._random_init(rng) - - def free(self): - self._free() - - - diff --git a/ThirdParty/Ert/python/ecl/util/util/rng.py b/ThirdParty/Ert/python/ecl/util/util/rng.py index e03af1c3f2..ff46f30b0b 100644 --- a/ThirdParty/Ert/python/ecl/util/util/rng.py +++ b/ThirdParty/Ert/python/ecl/util/util/rng.py @@ -1,4 +1,4 @@ -# Copyright (C) 2011 Statoil ASA, Norway. +# Copyright (C) 2011 Equinor ASA, Norway. # # The file 'rng.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/util/util/stringlist.py b/ThirdParty/Ert/python/ecl/util/util/stringlist.py index 19d4de759e..3c98a202de 100644 --- a/ThirdParty/Ert/python/ecl/util/util/stringlist.py +++ b/ThirdParty/Ert/python/ecl/util/util/stringlist.py @@ -1,4 +1,4 @@ -# Copyright (C) 2011 Statoil ASA, Norway. +# Copyright (C) 2011 Equinor ASA, Norway. # # The file 'stringlist.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/util/util/time_vector.py b/ThirdParty/Ert/python/ecl/util/util/time_vector.py index cffcb411f8..d8e0425189 100644 --- a/ThirdParty/Ert/python/ecl/util/util/time_vector.py +++ b/ThirdParty/Ert/python/ecl/util/util/time_vector.py @@ -1,4 +1,4 @@ -# Copyright (C) 2014 Statoil ASA, Norway. +# Copyright (C) 2014 Equinor ASA, Norway. # # The file 'vector_template.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/util/util/util_func.py b/ThirdParty/Ert/python/ecl/util/util/util_func.py index cb7cf236d6..40acc3385b 100644 --- a/ThirdParty/Ert/python/ecl/util/util/util_func.py +++ b/ThirdParty/Ert/python/ecl/util/util/util_func.py @@ -1,4 +1,4 @@ -# Copyright (C) 2011 Statoil ASA, Norway. +# Copyright (C) 2011 Equinor ASA, Norway. # # The file 'util_func.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/util/util/vector_template.py b/ThirdParty/Ert/python/ecl/util/util/vector_template.py index ca4d1a506a..5693a64322 100644 --- a/ThirdParty/Ert/python/ecl/util/util/vector_template.py +++ b/ThirdParty/Ert/python/ecl/util/util/vector_template.py @@ -1,4 +1,4 @@ -# Copyright (C) 2014 Statoil ASA, Norway. +# Copyright (C) 2014 Equinor ASA, Norway. # # The file 'vector_template.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ecl/well/well_info.py b/ThirdParty/Ert/python/ecl/well/well_info.py index 938341ace0..e8e3dcc6b5 100644 --- a/ThirdParty/Ert/python/ecl/well/well_info.py +++ b/ThirdParty/Ert/python/ecl/well/well_info.py @@ -1,4 +1,4 @@ -# Copyright (C) 2017 Statoil ASA, Norway. +# Copyright (C) 2017 Equinor ASA, Norway. # # This file is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/ert/test/__init__.py b/ThirdParty/Ert/python/ert/test/__init__.py index bacdd1adf8..743e58fc12 100644 --- a/ThirdParty/Ert/python/ert/test/__init__.py +++ b/ThirdParty/Ert/python/ert/test/__init__.py @@ -3,7 +3,6 @@ from ecl.util.test import path_exists from ecl.util.test import ExtendedTestCase from ecl.util.test import SourceEnumerator from ecl.util.test import TestArea , TestAreaContext -from ecl.util.test import TempArea , TempAreaContext from ecl.util.test import ErtTestRunner from ecl.util.test import PathContext from ecl.util.test import LintTestCase diff --git a/ThirdParty/Ert/python/tests/__init__.py b/ThirdParty/Ert/python/tests/__init__.py index 918cbb6acc..4fb12b1cca 100644 --- a/ThirdParty/Ert/python/tests/__init__.py +++ b/ThirdParty/Ert/python/tests/__init__.py @@ -23,12 +23,12 @@ def source_root(): # Decorator which is used to mark either an entire test class or individual -# test methods as requiring Statoil testdata. If Statoil testdata has not been +# test methods as requiring Equinor testdata. If Equinor testdata has not been # configured as part of the build process these tests will be skipped. # -# Ideally the statoil_test() implementation should just be a suitable wrapper of: +# Ideally the equinor_test() implementation should just be a suitable wrapper of: # -# skipUnless(EclTest.STATOIL_DATA, "Missing Statoil testdata") +# skipUnless(EclTest.EQUINOR_DATA, "Missing Equinor testdata") # # but that has been surprisingly difficult to achieve. The current # implemenation is based on the skip() function from the unittest/case.py @@ -42,32 +42,32 @@ def source_root(): # class, that is not required when decorating method: # # -# @statoil_test() -# class StatoilTest(EclTest): +# @equinor_test() +# class EquinorTest(EclTest): # # This test class will be skipped entirely if we do not have access to -# # Statoil testdata. +# # Equinor testdata. # # # class XTest(EclTest): # -# @statoil_test +# @equinor_test # def test_method(self): -def statoil_test(): +def equinor_test(): """ - Will mark a test method or an entire test class as dependent on Statoil testdata. + Will mark a test method or an entire test class as dependent on Equinor testdata. """ def decorator(test_item): if not isinstance(test_item, type): - if not EclTest.STATOIL_DATA: + if not EclTest.EQUINOR_DATA: @functools.wraps(test_item) def skip_wrapper(*args, **kwargs): - raise SkipTest("Missing Statoil testdata") + raise SkipTest("Missing Equinor testdata") test_item = skip_wrapper - if not EclTest.STATOIL_DATA: + if not EclTest.EQUINOR_DATA: test_item.__unittest_skip__ = True - test_item.__unittest_skip_why__ = "Missing Statoil testdata" + test_item.__unittest_skip_why__ = "Missing Equinor testdata" return test_item return decorator @@ -77,6 +77,6 @@ def statoil_test(): class EclTest(ExtendedTestCase): SOURCE_ROOT = source_root() TESTDATA_ROOT = os.path.join(SOURCE_ROOT, "test-data") - STATOIL_DATA = os.path.islink(os.path.join(TESTDATA_ROOT, "Statoil")) + EQUINOR_DATA = os.path.islink(os.path.join(TESTDATA_ROOT, "Equinor")) diff --git a/ThirdParty/Ert/python/tests/bin_tests/test_summary_resample.py b/ThirdParty/Ert/python/tests/bin_tests/test_summary_resample.py index c265382c00..d4e0db52b9 100644 --- a/ThirdParty/Ert/python/tests/bin_tests/test_summary_resample.py +++ b/ThirdParty/Ert/python/tests/bin_tests/test_summary_resample.py @@ -1,4 +1,4 @@ -# Copyright (C) 2018 Statoil ASA, Norway. +# Copyright (C) 2018 Equinor ASA, Norway. # # This file is part of ERT - Ensemble based Reservoir Tool. # @@ -60,6 +60,7 @@ class SummaryResampleTest(EclTest): with TestAreaContext(""): self.case.fwrite() + # Too few arguments with self.assertRaises(CallError): subprocess.check_call([self.script]) diff --git a/ThirdParty/Ert/python/tests/ecl_tests/CMakeLists.txt b/ThirdParty/Ert/python/tests/ecl_tests/CMakeLists.txt index 5196dd1016..eec263e163 100644 --- a/ThirdParty/Ert/python/tests/ecl_tests/CMakeLists.txt +++ b/ThirdParty/Ert/python/tests/ecl_tests/CMakeLists.txt @@ -4,7 +4,7 @@ set(TEST_SOURCES test_ecl_ecl.py test_removed.py test_ecl_3dkw.py - test_ecl_file_statoil.py + test_ecl_file_equinor.py test_ecl_file.py test_ecl_init_file.py test_ecl_restart_file.py @@ -12,33 +12,33 @@ set(TEST_SOURCES test_ecl_sum.py test_ecl_sum_vector.py test_fault_blocks.py - test_fault_blocks_statoil.py + test_fault_blocks_equinor.py test_faults.py test_fortio.py - test_grdecl_statoil.py + test_grdecl_equinor.py test_grdecl.py test_grid.py test_grid_pandas.py test_cell.py - test_grid_statoil.py - test_grid_statoil_coarse.py - test_grid_statoil_dual.py - test_grid_statoil_large_case.py + test_grid_equinor.py + test_grid_equinor_coarse.py + test_grid_equinor_dual.py + test_grid_equinor_large_case.py test_grid_generator.py test_indexed_read.py - test_ecl_kw_statoil.py + test_ecl_kw_equinor.py test_ecl_kw.py test_kw_function.py test_layer.py test_npv.py test_region.py - test_region_statoil.py + test_region_equinor.py test_restart.py test_rft.py - test_rft_statoil.py + test_rft_equinor.py test_rft_cell.py - test_statoil_faults.py - test_sum_statoil.py + test_equinor_faults.py + test_sum_equinor.py test_ecl_util.py test_ecl_cmp.py test_sum.py @@ -83,24 +83,24 @@ if (INSTALL_ERT_LEGACY) endif() -addPythonTest(tests.ecl_tests.test_ecl_file_statoil.EclFileStatoilTest) -addPythonTest(tests.ecl_tests.test_grdecl_statoil.GRDECLStatoilTest) +addPythonTest(tests.ecl_tests.test_ecl_file_equinor.EclFileEquinorTest) +addPythonTest(tests.ecl_tests.test_grdecl_equinor.GRDECLEquinorTest) addPythonTest(tests.ecl_tests.test_grdecl.GRDECLTest) -addPythonTest(tests.ecl_tests.test_grid_statoil.GridTest) -addPythonTest(tests.ecl_tests.test_grid_statoil_coarse.GridCoarceTest) -addPythonTest(tests.ecl_tests.test_grid_statoil_dual.GridDualTest) -addPythonTest(tests.ecl_tests.test_grid_statoil_large_case.GridLargeCaseTest) -addPythonTest(tests.ecl_tests.test_ecl_kw_statoil.KWTest) +addPythonTest(tests.ecl_tests.test_grid_equinor.GridTest) +addPythonTest(tests.ecl_tests.test_grid_equinor_coarse.GridCoarceTest) +addPythonTest(tests.ecl_tests.test_grid_equinor_dual.GridDualTest) +addPythonTest(tests.ecl_tests.test_grid_equinor_large_case.GridLargeCaseTest) +addPythonTest(tests.ecl_tests.test_ecl_kw_equinor.KWTest) addPythonTest(tests.ecl_tests.test_ecl_init_file.InitFileTest) addPythonTest(tests.ecl_tests.test_ecl_restart_file.RestartFileTest) addPythonTest(tests.ecl_tests.test_restart.RestartTest ) -addPythonTest(tests.ecl_tests.test_region_statoil.RegionTest) -addPythonTest(tests.ecl_tests.test_rft_statoil.RFTTest) -addPythonTest(tests.ecl_tests.test_sum_statoil.SumTest) +addPythonTest(tests.ecl_tests.test_region_equinor.RegionTest) +addPythonTest(tests.ecl_tests.test_rft_equinor.RFTTest) +addPythonTest(tests.ecl_tests.test_sum_equinor.SumTest) addPythonTest(tests.ecl_tests.test_ecl_sum_vector.EclSumVectorTest) addPythonTest(tests.ecl_tests.test_ecl_sum.EclSumTest) -addPythonTest(tests.ecl_tests.test_statoil_faults.StatoilFaultTest) -addPythonTest(tests.ecl_tests.test_fault_blocks_statoil.FaultBlockTest) +addPythonTest(tests.ecl_tests.test_equinor_faults.EquinorFaultTest) +addPythonTest(tests.ecl_tests.test_fault_blocks_equinor.FaultBlockTest) addPythonTest(tests.ecl_tests.test_npv.NPVTest) addPythonTest(tests.ecl_tests.test_indexed_read.EclIndexedReadTest) addPythonTest(tests.ecl_tests.test_ecl_cmp.EclCmpTest) diff --git a/ThirdParty/Ert/python/tests/ecl_tests/test_cell.py b/ThirdParty/Ert/python/tests/ecl_tests/test_cell.py index 5b8f41e52b..55120ce5c2 100644 --- a/ThirdParty/Ert/python/tests/ecl_tests/test_cell.py +++ b/ThirdParty/Ert/python/tests/ecl_tests/test_cell.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright (C) 2017 Statoil ASA, Norway. +# Copyright (C) 2017 Equinor ASA, Norway. # # This file is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/tests/ecl_tests/test_debug.py b/ThirdParty/Ert/python/tests/ecl_tests/test_debug.py index 49e4f997f1..ef930ed46b 100644 --- a/ThirdParty/Ert/python/tests/ecl_tests/test_debug.py +++ b/ThirdParty/Ert/python/tests/ecl_tests/test_debug.py @@ -1,4 +1,4 @@ -# Copyright (C) 2017 Statoil ASA, Norway. +# Copyright (C) 2017 Equinor ASA, Norway. # # The file 'test_debug.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/tests/ecl_tests/test_deprecation.py b/ThirdParty/Ert/python/tests/ecl_tests/test_deprecation.py index 869b6a4168..1096fc5272 100644 --- a/ThirdParty/Ert/python/tests/ecl_tests/test_deprecation.py +++ b/ThirdParty/Ert/python/tests/ecl_tests/test_deprecation.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright (C) 2011 Statoil ASA, Norway. +# Copyright (C) 2011 Equinor ASA, Norway. # # The file 'test_deprecation.py' is part of ERT - Ensemble based Reservoir Tool. # @@ -43,7 +43,6 @@ class Deprecation_2_0_Test(EclTest): with openFortIO("TEST" , mode = FortIO.WRITE_MODE) as f: kw.fwrite( f ) - t.sync() f = EclFile( "TEST" ) class Deprecation_1_9_Test(EclTest): diff --git a/ThirdParty/Ert/python/tests/ecl_tests/test_ecl_3dkw.py b/ThirdParty/Ert/python/tests/ecl_tests/test_ecl_3dkw.py index e6a8fed20a..8c4f146743 100644 --- a/ThirdParty/Ert/python/tests/ecl_tests/test_ecl_3dkw.py +++ b/ThirdParty/Ert/python/tests/ecl_tests/test_ecl_3dkw.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright (C) 2011 Statoil ASA, Norway. +# Copyright (C) 2011 Equinor ASA, Norway. # # The file 'test_kw.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/tests/ecl_tests/test_ecl_cmp.py b/ThirdParty/Ert/python/tests/ecl_tests/test_ecl_cmp.py index 39adb1fcb9..3d90837248 100644 --- a/ThirdParty/Ert/python/tests/ecl_tests/test_ecl_cmp.py +++ b/ThirdParty/Ert/python/tests/ecl_tests/test_ecl_cmp.py @@ -1,4 +1,4 @@ -# Copyright (C) 2015 Statoil ASA, Norway. +# Copyright (C) 2015 Equinor ASA, Norway. # # The file 'test_ecl_cmp.py' is part of ERT - Ensemble based Reservoir Tool. # @@ -17,13 +17,13 @@ from ecl.util.test import TestAreaContext from ecl.util.test.ecl_mock import createEclSum from ecl.summary import EclCmp -from tests import EclTest, statoil_test +from tests import EclTest, equinor_test -@statoil_test() +@equinor_test() class EclCmpTest(EclTest): def setUp(self): - self.root1 = self.createTestPath("Statoil/ECLIPSE/Gurbat/ECLIPSE") - self.root2 = self.createTestPath("Statoil/ECLIPSE/Oseberg/F8MLT/F8MLT-F4") + self.root1 = self.createTestPath("Equinor/ECLIPSE/Gurbat/ECLIPSE") + self.root2 = self.createTestPath("Equinor/ECLIPSE/Oseberg/F8MLT/F8MLT-F4") def test_not_existing(self): diff --git a/ThirdParty/Ert/python/tests/ecl_tests/test_ecl_file.py b/ThirdParty/Ert/python/tests/ecl_tests/test_ecl_file.py index c04ef9ef9a..8038ad5711 100644 --- a/ThirdParty/Ert/python/tests/ecl_tests/test_ecl_file.py +++ b/ThirdParty/Ert/python/tests/ecl_tests/test_ecl_file.py @@ -1,4 +1,4 @@ -# Copyright (C) 2011 Statoil ASA, Norway. +# Copyright (C) 2011 Equinor ASA, Norway. # # The file 'sum_test.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/tests/ecl_tests/test_ecl_file_statoil.py b/ThirdParty/Ert/python/tests/ecl_tests/test_ecl_file_equinor.py similarity index 97% rename from ThirdParty/Ert/python/tests/ecl_tests/test_ecl_file_statoil.py rename to ThirdParty/Ert/python/tests/ecl_tests/test_ecl_file_equinor.py index 8cffcbc259..1c9e8bf4da 100644 --- a/ThirdParty/Ert/python/tests/ecl_tests/test_ecl_file_statoil.py +++ b/ThirdParty/Ert/python/tests/ecl_tests/test_ecl_file_equinor.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright (C) 2011 Statoil ASA, Norway. +# Copyright (C) 2011 Equinor ASA, Norway. # # The file 'sum_test.py' is part of ERT - Ensemble based Reservoir Tool. # @@ -22,14 +22,14 @@ from ecl import EclFileFlagEnum, EclFileEnum from ecl.eclfile import EclFile, FortIO, EclKW , openFortIO , openEclFile from ecl.util.test import TestAreaContext -from tests import EclTest, statoil_test +from tests import EclTest, equinor_test -@statoil_test() -class EclFileStatoilTest(EclTest): +@equinor_test() +class EclFileEquinorTest(EclTest): def setUp(self): - self.test_file = self.createTestPath("Statoil/ECLIPSE/Gurbat/ECLIPSE.UNRST") - self.test_fmt_file = self.createTestPath("Statoil/ECLIPSE/Gurbat/ECLIPSE.FUNRST") + self.test_file = self.createTestPath("Equinor/ECLIPSE/Gurbat/ECLIPSE.UNRST") + self.test_fmt_file = self.createTestPath("Equinor/ECLIPSE/Gurbat/ECLIPSE.FUNRST") def assertFileType(self , filename , expected): file_type , step , fmt_file = EclFile.getFileType(filename) @@ -159,7 +159,7 @@ class EclFileStatoilTest(EclTest): def test_ix_case(self): - f = EclFile( self.createTestPath( "Statoil/ECLIPSE/ix/summary/Create_Region_Around_Well.SMSPEC")) + f = EclFile( self.createTestPath( "Equinor/ECLIPSE/ix/summary/Create_Region_Around_Well.SMSPEC")) # Keywords self.assertTrue( "KEYWORDS" in f ) diff --git a/ThirdParty/Ert/python/tests/ecl_tests/test_ecl_init_file.py b/ThirdParty/Ert/python/tests/ecl_tests/test_ecl_init_file.py index 9be2c65c72..c17a2fa6ea 100644 --- a/ThirdParty/Ert/python/tests/ecl_tests/test_ecl_init_file.py +++ b/ThirdParty/Ert/python/tests/ecl_tests/test_ecl_init_file.py @@ -1,4 +1,4 @@ -# Copyright (C) 2015 Statoil ASA, Norway. +# Copyright (C) 2015 Equinor ASA, Norway. # # The file 'test_ecl_init_file.py' is part of ERT - Ensemble based Reservoir Tool. # @@ -15,18 +15,18 @@ # for more details. -from tests import EclTest, statoil_test +from tests import EclTest, equinor_test from ecl import EclFileFlagEnum from ecl.eclfile import Ecl3DKW, EclKW, EclInitFile, EclFile, FortIO from ecl.grid import EclGrid -@statoil_test() +@equinor_test() class InitFileTest(EclTest): def setUp(self): - self.grid_file = self.createTestPath("Statoil/ECLIPSE/Gurbat/ECLIPSE.EGRID") - self.init_file = self.createTestPath("Statoil/ECLIPSE/Gurbat/ECLIPSE.INIT") + self.grid_file = self.createTestPath("Equinor/ECLIPSE/Gurbat/ECLIPSE.EGRID") + self.init_file = self.createTestPath("Equinor/ECLIPSE/Gurbat/ECLIPSE.INIT") def test_wrong_type(self): diff --git a/ThirdParty/Ert/python/tests/ecl_tests/test_ecl_kw.py b/ThirdParty/Ert/python/tests/ecl_tests/test_ecl_kw.py index 7528b85b66..f2c084a5d4 100644 --- a/ThirdParty/Ert/python/tests/ecl_tests/test_ecl_kw.py +++ b/ThirdParty/Ert/python/tests/ecl_tests/test_ecl_kw.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright (C) 2011 Statoil ASA, Norway. +# Copyright (C) 2011 Equinor ASA, Norway. # # The file 'test_kw.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/tests/ecl_tests/test_ecl_kw_statoil.py b/ThirdParty/Ert/python/tests/ecl_tests/test_ecl_kw_equinor.py similarity index 91% rename from ThirdParty/Ert/python/tests/ecl_tests/test_ecl_kw_statoil.py rename to ThirdParty/Ert/python/tests/ecl_tests/test_ecl_kw_equinor.py index 13b2d5d292..8593a64dcb 100644 --- a/ThirdParty/Ert/python/tests/ecl_tests/test_ecl_kw_statoil.py +++ b/ThirdParty/Ert/python/tests/ecl_tests/test_ecl_kw_equinor.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright (C) 2011 Statoil ASA, Norway. +# Copyright (C) 2011 Equinor ASA, Norway. # # The file 'test_kw.py' is part of ERT - Ensemble based Reservoir Tool. # @@ -20,7 +20,7 @@ from ecl import EclDataType, EclFileFlagEnum from ecl.eclfile import EclKW, EclFile, FortIO from ecl.util.test import TestAreaContext -from tests import EclTest, statoil_test +from tests import EclTest, equinor_test def copy_long(): src = EclKW("NAME", 100, EclDataType.ECL_FLOAT) @@ -32,10 +32,10 @@ def copy_offset(): copy = src.sub_copy(200, 100) -@statoil_test() +@equinor_test() class KWTest(EclTest): def test_fortio_size( self ): - unrst_file_path = self.createTestPath("Statoil/ECLIPSE/Gurbat/ECLIPSE.UNRST") + unrst_file_path = self.createTestPath("Equinor/ECLIPSE/Gurbat/ECLIPSE.UNRST") unrst_file = EclFile(unrst_file_path) size = 0 for kw in unrst_file: @@ -48,7 +48,7 @@ class KWTest(EclTest): def test_sub_copy(self): - unrst_file_path = self.createTestPath("Statoil/ECLIPSE/Gurbat/ECLIPSE.UNRST") + unrst_file_path = self.createTestPath("Equinor/ECLIPSE/Gurbat/ECLIPSE.UNRST") unrst_file = EclFile(unrst_file_path) swat = unrst_file["SWAT"][0] @@ -89,7 +89,7 @@ class KWTest(EclTest): self.assertFalse(kw1.equal(kw2)) self.assertFalse(kw1.equal_numeric(kw2)) - unrst_file_path = self.createTestPath("Statoil/ECLIPSE/Gurbat/ECLIPSE.UNRST") + unrst_file_path = self.createTestPath("Equinor/ECLIPSE/Gurbat/ECLIPSE.UNRST") unrst_file = EclFile(unrst_file_path) kw1 = unrst_file["PRESSURE"][0] kw2 = kw1.deep_copy() diff --git a/ThirdParty/Ert/python/tests/ecl_tests/test_ecl_restart_file.py b/ThirdParty/Ert/python/tests/ecl_tests/test_ecl_restart_file.py index 690ac7ba52..cb3f437ee2 100644 --- a/ThirdParty/Ert/python/tests/ecl_tests/test_ecl_restart_file.py +++ b/ThirdParty/Ert/python/tests/ecl_tests/test_ecl_restart_file.py @@ -1,4 +1,4 @@ -# Copyright (C) 2015 Statoil ASA, Norway. +# Copyright (C) 2015 Equinor ASA, Norway. # # The file 'test_ecl_init_file.py' is part of ERT - Ensemble based Reservoir Tool. # @@ -15,19 +15,19 @@ # for more details. import datetime -from tests import EclTest, statoil_test +from tests import EclTest, equinor_test from ecl import EclFileFlagEnum from ecl.eclfile import Ecl3DKW , EclKW, EclRestartFile , EclFile, FortIO from ecl.grid import EclGrid -@statoil_test() +@equinor_test() class RestartFileTest(EclTest): def setUp(self): - self.grid_file = self.createTestPath("Statoil/ECLIPSE/Gurbat/ECLIPSE.EGRID") - self.unrst_file = self.createTestPath("Statoil/ECLIPSE/Gurbat/ECLIPSE.UNRST") - self.xrst_file0 = self.createTestPath("Statoil/ECLIPSE/Gurbat/ECLIPSE.X0000") - self.xrst_file10 = self.createTestPath("Statoil/ECLIPSE/Gurbat/ECLIPSE.X0010") - self.xrst_file20 = self.createTestPath("Statoil/ECLIPSE/Gurbat/ECLIPSE.X0020") + self.grid_file = self.createTestPath("Equinor/ECLIPSE/Gurbat/ECLIPSE.EGRID") + self.unrst_file = self.createTestPath("Equinor/ECLIPSE/Gurbat/ECLIPSE.UNRST") + self.xrst_file0 = self.createTestPath("Equinor/ECLIPSE/Gurbat/ECLIPSE.X0000") + self.xrst_file10 = self.createTestPath("Equinor/ECLIPSE/Gurbat/ECLIPSE.X0010") + self.xrst_file20 = self.createTestPath("Equinor/ECLIPSE/Gurbat/ECLIPSE.X0020") def test_load(self): diff --git a/ThirdParty/Ert/python/tests/ecl_tests/test_ecl_sum.py b/ThirdParty/Ert/python/tests/ecl_tests/test_ecl_sum.py index 80c69003b7..40c36bccda 100644 --- a/ThirdParty/Ert/python/tests/ecl_tests/test_ecl_sum.py +++ b/ThirdParty/Ert/python/tests/ecl_tests/test_ecl_sum.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright (C) 2014 Statoil ASA, Norway. +# Copyright (C) 2014 Equinor ASA, Norway. # # The file 'test_ecl_sum.py' is part of ERT - Ensemble based Reservoir Tool. # @@ -24,14 +24,14 @@ from cwrap import Prototype, load, open as copen from ecl.eclfile import EclFile, FortIO, openFortIO, openEclFile, EclKW from ecl.summary import EclSum, EclSumKeyWordVector from ecl.util.test import TestAreaContext -from tests import EclTest, statoil_test +from tests import EclTest, equinor_test -@statoil_test() +@equinor_test() class EclSumTest(EclTest): def setUp(self): - self.test_file = self.createTestPath("Statoil/ECLIPSE/Gurbat/ECLIPSE.SMSPEC") + self.test_file = self.createTestPath("Equinor/ECLIPSE/Gurbat/ECLIPSE.SMSPEC") self.ecl_sum = EclSum(self.test_file) @@ -71,7 +71,7 @@ class EclSumTest(EclTest): def test_truncated_smspec(self): with TestAreaContext("EclSum/truncated_smspec") as ta: ta.copy_file(self.test_file) - ta.copy_file(self.createTestPath("Statoil/ECLIPSE/Gurbat/ECLIPSE.UNSMRY")) + ta.copy_file(self.createTestPath("Equinor/ECLIPSE/Gurbat/ECLIPSE.UNSMRY")) file_size = os.path.getsize("ECLIPSE.SMSPEC") with open("ECLIPSE.SMSPEC","r+") as f: @@ -84,7 +84,7 @@ class EclSumTest(EclTest): def test_truncated_data(self): with TestAreaContext("EclSum/truncated_data") as ta: ta.copy_file(self.test_file) - ta.copy_file(self.createTestPath("Statoil/ECLIPSE/Gurbat/ECLIPSE.UNSMRY")) + ta.copy_file(self.createTestPath("Equinor/ECLIPSE/Gurbat/ECLIPSE.UNSMRY")) file_size = os.path.getsize("ECLIPSE.UNSMRY") @@ -98,7 +98,7 @@ class EclSumTest(EclTest): def test_missing_smspec_keyword(self): with TestAreaContext("EclSum/truncated_data") as ta: ta.copy_file(self.test_file) - ta.copy_file(self.createTestPath("Statoil/ECLIPSE/Gurbat/ECLIPSE.UNSMRY")) + ta.copy_file(self.createTestPath("Equinor/ECLIPSE/Gurbat/ECLIPSE.UNSMRY")) with openEclFile("ECLIPSE.SMSPEC") as f: kw_list = [] @@ -118,7 +118,7 @@ class EclSumTest(EclTest): def test_missing_unsmry_keyword(self): with TestAreaContext("EclSum/truncated_data") as ta: ta.copy_file(self.test_file) - ta.copy_file(self.createTestPath("Statoil/ECLIPSE/Gurbat/ECLIPSE.UNSMRY")) + ta.copy_file(self.createTestPath("Equinor/ECLIPSE/Gurbat/ECLIPSE.UNSMRY")) with openEclFile("ECLIPSE.UNSMRY") as f: kw_list = [] @@ -140,7 +140,7 @@ class EclSumTest(EclTest): def test_labscale(self): - case = self.createTestPath("Statoil/ECLIPSE/LabScale/HDMODEL") + case = self.createTestPath("Equinor/ECLIPSE/LabScale/HDMODEL") sum = EclSum(case, lazy_load=True) self.assertEqual(sum.getStartTime(), datetime.datetime(2013,1,1,0,0,0)) self.assertEqual(sum.getEndTime() , datetime.datetime(2013,1,1,19,30,0)) diff --git a/ThirdParty/Ert/python/tests/ecl_tests/test_ecl_sum_vector.py b/ThirdParty/Ert/python/tests/ecl_tests/test_ecl_sum_vector.py index 90e799eb1b..8a72dd0452 100644 --- a/ThirdParty/Ert/python/tests/ecl_tests/test_ecl_sum_vector.py +++ b/ThirdParty/Ert/python/tests/ecl_tests/test_ecl_sum_vector.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright (C) 2013 Statoil ASA, Norway. +# Copyright (C) 2013 Equinor ASA, Norway. # # The file 'test_ecl_sum_vector.py' is part of ERT - Ensemble based Reservoir Tool. # @@ -23,14 +23,14 @@ except ImportError: import warnings from ecl.summary import EclSumVector, EclSum -from tests import EclTest, statoil_test +from tests import EclTest, equinor_test -@statoil_test() +@equinor_test() class EclSumVectorTest(EclTest): def setUp(self): - self.test_file = self.createTestPath("Statoil/ECLIPSE/Gurbat/ECLIPSE.SMSPEC") + self.test_file = self.createTestPath("Equinor/ECLIPSE/Gurbat/ECLIPSE.SMSPEC") self.ecl_sum = EclSum(self.test_file) def test_reportOnly_warns(self): @@ -38,7 +38,7 @@ class EclSumVectorTest(EclTest): warnings.simplefilter("always") vector = EclSumVector(self.ecl_sum, "FOPT", True) - self.assertEqual(len(w), 2) + self.assertEqual(len(w), 1) assert issubclass(w[-1].category, DeprecationWarning) diff --git a/ThirdParty/Ert/python/tests/ecl_tests/test_ecl_util.py b/ThirdParty/Ert/python/tests/ecl_tests/test_ecl_util.py index fc5c03d7dc..522afd7c8f 100644 --- a/ThirdParty/Ert/python/tests/ecl_tests/test_ecl_util.py +++ b/ThirdParty/Ert/python/tests/ecl_tests/test_ecl_util.py @@ -1,4 +1,4 @@ -# Copyright (C) 2015 Statoil ASA, Norway. +# Copyright (C) 2015 Equinor ASA, Norway. # # The file 'sum_test.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/tests/ecl_tests/test_statoil_faults.py b/ThirdParty/Ert/python/tests/ecl_tests/test_equinor_faults.py similarity index 94% rename from ThirdParty/Ert/python/tests/ecl_tests/test_statoil_faults.py rename to ThirdParty/Ert/python/tests/ecl_tests/test_equinor_faults.py index 03c5b3210a..cdde627cb3 100644 --- a/ThirdParty/Ert/python/tests/ecl_tests/test_statoil_faults.py +++ b/ThirdParty/Ert/python/tests/ecl_tests/test_equinor_faults.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright (C) 2014 Statoil ASA, Norway. +# Copyright (C) 2014 Equinor ASA, Norway. # # The file 'test_faults.py' is part of ERT - Ensemble based Reservoir Tool. # @@ -26,13 +26,13 @@ from ecl import EclDataType from ecl.eclfile import EclKW from ecl.grid import EclGrid from ecl.grid.faults import FaultCollection, Fault, FaultLine, FaultSegment -from tests import EclTest, statoil_test +from tests import EclTest, equinor_test -@statoil_test() -class StatoilFaultTest(EclTest): +@equinor_test() +class EquinorFaultTest(EclTest): def loadGrid(self): - grid_file = self.createTestPath("Statoil/ECLIPSE/Faults/grid.grdecl") + grid_file = self.createTestPath("Equinor/ECLIPSE/Faults/grid.grdecl") fileH = copen(grid_file, "r") specgrid = EclKW.read_grdecl(fileH, "SPECGRID", ecl_type=EclDataType.ECL_INT, strict=False) zcorn = EclKW.read_grdecl(fileH, "ZCORN") @@ -46,7 +46,7 @@ class StatoilFaultTest(EclTest): def test_load(self): grid = self.loadGrid() - faults_file = self.createTestPath("Statoil/ECLIPSE/Faults/faults.grdecl") + faults_file = self.createTestPath("Equinor/ECLIPSE/Faults/faults.grdecl") faults = FaultCollection( grid , faults_file ) for fault in faults: for layer in fault: diff --git a/ThirdParty/Ert/python/tests/ecl_tests/test_fault_blocks.py b/ThirdParty/Ert/python/tests/ecl_tests/test_fault_blocks.py index 8e6ca732c4..7be4554098 100644 --- a/ThirdParty/Ert/python/tests/ecl_tests/test_fault_blocks.py +++ b/ThirdParty/Ert/python/tests/ecl_tests/test_fault_blocks.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright (C) 2014 Statoil ASA, Norway. +# Copyright (C) 2014 Equinor ASA, Norway. # # The file 'test_fault_blocks.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/tests/ecl_tests/test_fault_blocks_statoil.py b/ThirdParty/Ert/python/tests/ecl_tests/test_fault_blocks_equinor.py similarity index 85% rename from ThirdParty/Ert/python/tests/ecl_tests/test_fault_blocks_statoil.py rename to ThirdParty/Ert/python/tests/ecl_tests/test_fault_blocks_equinor.py index 4b72f27be6..1c5e760579 100644 --- a/ThirdParty/Ert/python/tests/ecl_tests/test_fault_blocks_statoil.py +++ b/ThirdParty/Ert/python/tests/ecl_tests/test_fault_blocks_equinor.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright (C) 2014 Statoil ASA, Norway. +# Copyright (C) 2014 Equinor ASA, Norway. # # The file 'test_fault_blocks.py' is part of ERT - Ensemble based Reservoir Tool. # @@ -22,17 +22,17 @@ except ImportError: from ecl import EclDataType from ecl.eclfile import EclKW from ecl.grid import EclGrid -from tests import EclTest, statoil_test +from tests import EclTest, equinor_test from ecl.grid.faults import FaultBlock, FaultBlockLayer from cwrap import open as copen -@statoil_test() +@equinor_test() class FaultBlockTest(EclTest): def setUp(self): - self.grid = EclGrid( self.createTestPath("Statoil/ECLIPSE/Mariner/MARINER.EGRID")) - fileH = copen( self.createTestPath("Statoil/ECLIPSE/Mariner/faultblock.grdecl") ) + self.grid = EclGrid( self.createTestPath("Equinor/ECLIPSE/Mariner/MARINER.EGRID")) + fileH = copen( self.createTestPath("Equinor/ECLIPSE/Mariner/faultblock.grdecl") ) self.kw = EclKW.read_grdecl( fileH , "FAULTBLK" , ecl_type = EclDataType.ECL_INT ) diff --git a/ThirdParty/Ert/python/tests/ecl_tests/test_faults.py b/ThirdParty/Ert/python/tests/ecl_tests/test_faults.py index 5a65e9a0b1..240204d367 100644 --- a/ThirdParty/Ert/python/tests/ecl_tests/test_faults.py +++ b/ThirdParty/Ert/python/tests/ecl_tests/test_faults.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright (C) 2014 Statoil ASA, Norway. +# Copyright (C) 2014 Equinor ASA, Norway. # # The file 'test_faults.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/tests/ecl_tests/test_fk_user_data.py b/ThirdParty/Ert/python/tests/ecl_tests/test_fk_user_data.py index d01c981463..3e484cac27 100644 --- a/ThirdParty/Ert/python/tests/ecl_tests/test_fk_user_data.py +++ b/ThirdParty/Ert/python/tests/ecl_tests/test_fk_user_data.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright (C) 2017 Statoil ASA, Norway. +# Copyright (C) 2017 Equinor ASA, Norway. # # The file 'test_ecl_cell_containment.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/tests/ecl_tests/test_fortio.py b/ThirdParty/Ert/python/tests/ecl_tests/test_fortio.py index 54a4b9fabe..842ac049b7 100644 --- a/ThirdParty/Ert/python/tests/ecl_tests/test_fortio.py +++ b/ThirdParty/Ert/python/tests/ecl_tests/test_fortio.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright (C) 2011 Statoil ASA, Norway. +# Copyright (C) 2011 Equinor ASA, Norway. # # This file is part of ERT - Ensemble based Reservoir Tool. # @@ -77,8 +77,7 @@ class FortIOTest(EclTest): kw1.fwrite(f) pos1 = f.getPosition( ) kw2.fwrite(f) - - t.sync( ) + # Truncate file in read mode; should fail hard. with openFortIO("file") as f: with self.assertRaises(IOError): @@ -121,8 +120,6 @@ class FortIOTest(EclTest): kw1.fwrite( f ) self.assertEqual( f.filename() , "file") - t.sync( ) - with openFortIO("file") as f: kw2 = EclKW.fread( f ) diff --git a/ThirdParty/Ert/python/tests/ecl_tests/test_geertsma.py b/ThirdParty/Ert/python/tests/ecl_tests/test_geertsma.py index f991e88704..12a36297d8 100644 --- a/ThirdParty/Ert/python/tests/ecl_tests/test_geertsma.py +++ b/ThirdParty/Ert/python/tests/ecl_tests/test_geertsma.py @@ -22,7 +22,7 @@ def create_init(grid, case): porv.fwrite(f) -def create_restart(grid, case, p1, p2=None): +def create_restart(grid, case, p1, p2=None, rporv1=None, rporv2=None): with openFortIO("%s.UNRST" % case, mode=FortIO.WRITE_MODE) as f: seq_hdr = EclKW("SEQNUM", 1, EclDataType.ECL_FLOAT) seq_hdr[0] = 10 @@ -39,6 +39,13 @@ def create_restart(grid, case, p1, p2=None): header.fwrite(f) p.fwrite(f) + if rporv1: + rp = EclKW("RPORV", grid.getNumActive(), EclDataType.ECL_FLOAT) + for idx, val in enumerate(rporv1): + rp[idx] = val + + rp.fwrite(f) + if p2: seq_hdr[0] = 20 header[66] = 2010 @@ -49,6 +56,13 @@ def create_restart(grid, case, p1, p2=None): header.fwrite(f) p.fwrite(f) + if rporv2: + rp = EclKW("RPORV", grid.getNumActive(), EclDataType.ECL_FLOAT) + for idx, val in enumerate(rporv2): + rp[idx] = val + + rp.fwrite(f) + class GeertsmaTest(EclTest): @@ -145,4 +159,62 @@ class GeertsmaTest(EclTest): dz = subsidence.evalGeertsma("S1", None, receiver, youngs_modulus, poisson_ratio, seabed) np.testing.assert_almost_equal(dz, 5.819790154474284e-08) + @staticmethod + def test_geertsma_kernel_seabed(): + grid = EclGrid.createRectangular(dims=(1, 1, 1), dV=(50, 50, 50)) + with TestAreaContext("Subsidence"): + p1 = [1] + create_restart(grid, "TEST", p1) + create_init(grid, "TEST") + init = EclFile("TEST.INIT") + restart_file = EclFile("TEST.UNRST") + + restart_view1 = restart_file.restartView(sim_time=datetime.date(2000, 1, 1)) + + subsidence = EclSubsidence(grid, init) + subsidence.add_survey_PRESSURE("S1", restart_view1) + + youngs_modulus = 5E8 + poisson_ratio = 0.3 + seabed = 300 + above = 100 + topres = 2000 + receiver = (1000, 1000, topres - seabed - above) + + dz = subsidence.evalGeertsma("S1", None, receiver, youngs_modulus, poisson_ratio, seabed) + np.testing.assert_almost_equal(dz, 5.819790154474284e-08) + + def test_geertsma_rporv_kernel_2_source_points_2_vintages(self): + grid = EclGrid.createRectangular(dims=(2, 1, 1), dV=(100, 100, 100)) + + with TestAreaContext("Subsidence"): + p1 = [1, 10] + p2 = [10, 20] + create_restart(grid, "TEST", + p1, p2, + rporv1=[10**5, 10**5], rporv2=[9*10**4, 9*10**4] + ) + create_init(grid, "TEST") + + init = EclFile("TEST.INIT") + restart_file = EclFile("TEST.UNRST") + + restart_view1 = restart_file.restartView(sim_time=datetime.date(2000, 1, 1)) + restart_view2 = restart_file.restartView(sim_time=datetime.date(2010, 1, 1)) + + subsidence = EclSubsidence(grid, init) + subsidence.add_survey_PRESSURE("S1", restart_view1) + subsidence.add_survey_PRESSURE("S2", restart_view2) + + youngs_modulus = 5E8 + poisson_ratio = 0.3 + seabed = 0 + receiver = (1000, 1000, 0) + + dz1 = subsidence.eval_geertsma_rporv("S1", None, receiver, youngs_modulus, poisson_ratio, seabed) + dz2 = subsidence.eval_geertsma_rporv("S2", None, receiver, youngs_modulus, poisson_ratio, seabed) + dz = subsidence.eval_geertsma_rporv("S1", "S2", receiver, youngs_modulus, poisson_ratio, seabed) + + np.testing.assert_almost_equal(dz, dz1-dz2) + self.assertTrue(dz > 0) diff --git a/ThirdParty/Ert/python/tests/ecl_tests/test_grdecl.py b/ThirdParty/Ert/python/tests/ecl_tests/test_grdecl.py index 58337e00ef..0473dbdc51 100644 --- a/ThirdParty/Ert/python/tests/ecl_tests/test_grdecl.py +++ b/ThirdParty/Ert/python/tests/ecl_tests/test_grdecl.py @@ -1,4 +1,4 @@ -# Copyright (C) 2018 Statoil ASA, Norway. +# Copyright (C) 2018 Equinor ASA, Norway. # # The file 'test_grdecl.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/tests/ecl_tests/test_grdecl_statoil.py b/ThirdParty/Ert/python/tests/ecl_tests/test_grdecl_equinor.py similarity index 93% rename from ThirdParty/Ert/python/tests/ecl_tests/test_grdecl_statoil.py rename to ThirdParty/Ert/python/tests/ecl_tests/test_grdecl_equinor.py index a627d84cd9..35273b2220 100644 --- a/ThirdParty/Ert/python/tests/ecl_tests/test_grdecl_statoil.py +++ b/ThirdParty/Ert/python/tests/ecl_tests/test_grdecl_equinor.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright (C) 2011 Statoil ASA, Norway. +# Copyright (C) 2011 Equinor ASA, Norway. # # The file 'sum_test.py' is part of ERT - Ensemble based Reservoir Tool. # @@ -18,15 +18,15 @@ import os from ecl.eclfile import EclKW, Ecl3DKW from ecl.grid import EclGrid -from tests import EclTest, statoil_test +from tests import EclTest, equinor_test from cwrap import open as copen -@statoil_test() -class GRDECLStatoilTest(EclTest): +@equinor_test() +class GRDECLEquinorTest(EclTest): def setUp(self): - self.src_file = self.createTestPath("Statoil/ECLIPSE/Gurbat/include/example_permx.GRDECL") + self.src_file = self.createTestPath("Equinor/ECLIPSE/Gurbat/include/example_permx.GRDECL") self.file_list = [] def addFile(self, filename): @@ -42,7 +42,7 @@ class GRDECLStatoilTest(EclTest): kw = EclKW.read_grdecl(copen(self.src_file, "r"), "PERMX") self.assertTrue(kw) - grid = EclGrid( self.createTestPath("Statoil/ECLIPSE/Gurbat/ECLIPSE" )) + grid = EclGrid( self.createTestPath("Equinor/ECLIPSE/Gurbat/ECLIPSE" )) kw = Ecl3DKW.read_grdecl(grid , copen(self.src_file, "r"), "PERMX") self.assertTrue( isinstance( kw , Ecl3DKW )) diff --git a/ThirdParty/Ert/python/tests/ecl_tests/test_grid.py b/ThirdParty/Ert/python/tests/ecl_tests/test_grid.py index b3df4dee7c..2095fa2378 100644 --- a/ThirdParty/Ert/python/tests/ecl_tests/test_grid.py +++ b/ThirdParty/Ert/python/tests/ecl_tests/test_grid.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright (C) 2014 Statoil ASA, Norway. +# Copyright (C) 2014 Equinor ASA, Norway. # # The file 'test_grid.py' is part of ERT - Ensemble based Reservoir Tool. # @@ -122,8 +122,8 @@ def average(points): return [elem/float(len(points)) for elem in p] # This test class should only have test cases which do not require -# external test data. Tests involving Statoil test data are in the -# test_grid_statoil module. +# external test data. Tests involving Equinor test data are in the +# test_grid_equinor module. class GridTest(EclTest): def test_oom_grid(self): diff --git a/ThirdParty/Ert/python/tests/ecl_tests/test_grid_statoil.py b/ThirdParty/Ert/python/tests/ecl_tests/test_grid_equinor.py similarity index 94% rename from ThirdParty/Ert/python/tests/ecl_tests/test_grid_statoil.py rename to ThirdParty/Ert/python/tests/ecl_tests/test_grid_equinor.py index a925b6ac0b..74a9c3a2bc 100644 --- a/ThirdParty/Ert/python/tests/ecl_tests/test_grid_statoil.py +++ b/ThirdParty/Ert/python/tests/ecl_tests/test_grid_equinor.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright (C) 2011 Statoil ASA, Norway. +# Copyright (C) 2011 Equinor ASA, Norway. # # The file 'test_grid.py' is part of ERT - Ensemble based Reservoir Tool. # @@ -30,21 +30,21 @@ from ecl.eclfile import EclKW, EclFile, openEclFile from ecl.grid import EclGrid from ecl.util.util import DoubleVector, IntVector from ecl.util.test import TestAreaContext -from tests import EclTest, statoil_test +from tests import EclTest, equinor_test -@statoil_test() +@equinor_test() class GridTest(EclTest): def egrid_file(self): - return self.createTestPath("Statoil/ECLIPSE/Gurbat/ECLIPSE.EGRID") + return self.createTestPath("Equinor/ECLIPSE/Gurbat/ECLIPSE.EGRID") def grid_file(self): - return self.createTestPath("Statoil/ECLIPSE/Gurbat/ECLIPSE.GRID") + return self.createTestPath("Equinor/ECLIPSE/Gurbat/ECLIPSE.GRID") def grdecl_file(self): - return self.createTestPath("Statoil/ECLIPSE/Gurbat/include/example_grid_sim.GRDECL") + return self.createTestPath("Equinor/ECLIPSE/Gurbat/include/example_grid_sim.GRDECL") def test_loadFromFile(self): g1 = EclGrid.loadFromFile( self.egrid_file() ) @@ -277,7 +277,7 @@ class GridTest(EclTest): @skipIf(EclTest.slowTestShouldNotRun(), "Slow test of numActive large memory skipped!") def test_num_active_large_memory(self): - case = self.createTestPath("Statoil/ECLIPSE/Gurbat/ECLIPSE") + case = self.createTestPath("Equinor/ECLIPSE/Gurbat/ECLIPSE") vecList = [] for i in range(12500): vec = DoubleVector() @@ -291,7 +291,7 @@ class GridTest(EclTest): def test_no_mapaxes_check_for_nan(self): - grid_paths = ["Statoil/ECLIPSE/NoMapaxes/ECLIPSE.EGRID", "Statoil/ECLIPSE/NoMapaxes/ECLIPSE.GRID"] + grid_paths = ["Equinor/ECLIPSE/NoMapaxes/ECLIPSE.EGRID", "Equinor/ECLIPSE/NoMapaxes/ECLIPSE.GRID"] for grid_path in grid_paths: test_grid_path = self.createTestPath(grid_path) @@ -309,7 +309,7 @@ class GridTest(EclTest): def test_valid_geometry(self): - grid = EclGrid( self.createTestPath("Statoil/ECLIPSE/GRID_INVALID_CELL/PRED_RESEST_0_R_13_0.GRID")) + grid = EclGrid( self.createTestPath("Equinor/ECLIPSE/GRID_INVALID_CELL/PRED_RESEST_0_R_13_0.GRID")) self.assertTrue( grid.validCellGeometry( ijk = (27,0,0)) ) self.assertFalse( grid.validCellGeometry( ijk = (0,0,0)) ) @@ -328,7 +328,7 @@ class GridTest(EclTest): def test_lgr_get(self): - grid = EclGrid(self.createTestPath("Statoil/ECLIPSE/Troll/MSW_LGR/2BRANCHES-CCEWELLPATH-NEW-SCH-TUNED-AR3.EGRID")) + grid = EclGrid(self.createTestPath("Equinor/ECLIPSE/Troll/MSW_LGR/2BRANCHES-CCEWELLPATH-NEW-SCH-TUNED-AR3.EGRID")) for (nr,name) in [ ( 104 , "LG003017"), (2 , "LG006024"), ( 4 , "LG005025"), diff --git a/ThirdParty/Ert/python/tests/ecl_tests/test_grid_statoil_coarse.py b/ThirdParty/Ert/python/tests/ecl_tests/test_grid_equinor_coarse.py similarity index 84% rename from ThirdParty/Ert/python/tests/ecl_tests/test_grid_statoil_coarse.py rename to ThirdParty/Ert/python/tests/ecl_tests/test_grid_equinor_coarse.py index 11f94ebc90..29029f0ad9 100644 --- a/ThirdParty/Ert/python/tests/ecl_tests/test_grid_statoil_coarse.py +++ b/ThirdParty/Ert/python/tests/ecl_tests/test_grid_equinor_coarse.py @@ -1,6 +1,6 @@ -# Copyright (C) 2018 Statoil ASA, Norway. +# Copyright (C) 2018 Equinor ASA, Norway. # -# The file 'test_grid_statoil_coarse.py' is part of ERT - Ensemble based Reservoir Tool. +# The file 'test_grid_equinor_coarse.py' is part of ERT - Ensemble based Reservoir Tool. # # ERT is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -18,17 +18,17 @@ import math from ecl.util.test import TestAreaContext from ecl.grid import EclGrid -from tests import EclTest, statoil_test +from tests import EclTest, equinor_test -@statoil_test() +@equinor_test() class GridCoarceTest(EclTest): def test_coarse(self): #work_area = TestArea("python/grid-test/testCoarse") with TestAreaContext("python/grid-test/testCoarse"): testGRID = True - g1 = EclGrid(self.createTestPath("Statoil/ECLIPSE/LGCcase/LGC_TESTCASE2.EGRID")) + g1 = EclGrid(self.createTestPath("Equinor/ECLIPSE/LGCcase/LGC_TESTCASE2.EGRID")) g1.save_EGRID("LGC.EGRID") g2 = EclGrid("LGC.EGRID") diff --git a/ThirdParty/Ert/python/tests/ecl_tests/test_grid_statoil_dual.py b/ThirdParty/Ert/python/tests/ecl_tests/test_grid_equinor_dual.py similarity index 84% rename from ThirdParty/Ert/python/tests/ecl_tests/test_grid_statoil_dual.py rename to ThirdParty/Ert/python/tests/ecl_tests/test_grid_equinor_dual.py index eeb907c075..d962448953 100644 --- a/ThirdParty/Ert/python/tests/ecl_tests/test_grid_statoil_dual.py +++ b/ThirdParty/Ert/python/tests/ecl_tests/test_grid_equinor_dual.py @@ -1,6 +1,6 @@ -# Copyright (C) 2018 Statoil ASA, Norway. +# Copyright (C) 2018 Equinor ASA, Norway. # -# The file 'test_grid_statoil_dual.py' is part of ERT - Ensemble based Reservoir Tool. +# The file 'test_grid_equinor_dual.py' is part of ERT - Ensemble based Reservoir Tool. # # ERT is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -18,16 +18,16 @@ import math from ecl.util.test import TestAreaContext from ecl.grid import EclGrid -from tests import EclTest, statoil_test +from tests import EclTest, equinor_test -@statoil_test() +@equinor_test() class GridDualTest(EclTest): def egrid_file(self): - return self.createTestPath("Statoil/ECLIPSE/Gurbat/ECLIPSE.EGRID") + return self.createTestPath("Equinor/ECLIPSE/Gurbat/ECLIPSE.EGRID") def grid_file(self): - return self.createTestPath("Statoil/ECLIPSE/Gurbat/ECLIPSE.GRID") + return self.createTestPath("Equinor/ECLIPSE/Gurbat/ECLIPSE.GRID") def test_dual(self): with TestAreaContext("python/grid-test/testDual"): @@ -39,11 +39,11 @@ class GridDualTest(EclTest): self.assertFalse(grid.dualGrid()) self.assertTrue(grid.getNumActiveFracture() == 0) - dgrid = EclGrid(self.createTestPath("Statoil/ECLIPSE/DualPoro/DUALPOR_MSW.EGRID")) + dgrid = EclGrid(self.createTestPath("Equinor/ECLIPSE/DualPoro/DUALPOR_MSW.EGRID")) self.assertTrue(dgrid.getNumActive() == dgrid.getNumActiveFracture()) self.assertTrue(dgrid.getNumActive() == 46118) - dgrid2 = EclGrid(self.createTestPath("Statoil/ECLIPSE/DualPoro/DUALPOR_MSW.GRID")) + dgrid2 = EclGrid(self.createTestPath("Equinor/ECLIPSE/DualPoro/DUALPOR_MSW.GRID")) self.assertTrue(dgrid.getNumActive() == dgrid.getNumActiveFracture()) self.assertTrue(dgrid.getNumActive() == 46118) self.assertTrue(dgrid.equal(dgrid2)) @@ -52,7 +52,7 @@ class GridDualTest(EclTest): # The DUAL_DIFF grid has been manipulated to create a # situation where some cells are only matrix active, and some # cells are only fracture active. - dgrid = EclGrid(self.createTestPath("Statoil/ECLIPSE/DualPoro/DUAL_DIFF.EGRID")) + dgrid = EclGrid(self.createTestPath("Equinor/ECLIPSE/DualPoro/DUAL_DIFF.EGRID")) self.assertTrue(dgrid.getNumActive() == 106) self.assertTrue(dgrid.getNumActiveFracture() == 105) diff --git a/ThirdParty/Ert/python/tests/ecl_tests/test_grid_statoil_large_case.py b/ThirdParty/Ert/python/tests/ecl_tests/test_grid_equinor_large_case.py similarity index 78% rename from ThirdParty/Ert/python/tests/ecl_tests/test_grid_statoil_large_case.py rename to ThirdParty/Ert/python/tests/ecl_tests/test_grid_equinor_large_case.py index 09b4b366df..3545e1b529 100644 --- a/ThirdParty/Ert/python/tests/ecl_tests/test_grid_statoil_large_case.py +++ b/ThirdParty/Ert/python/tests/ecl_tests/test_grid_equinor_large_case.py @@ -1,6 +1,6 @@ -# Copyright (C) 2018 Statoil ASA, Norway. +# Copyright (C) 2018 Equinor ASA, Norway. # -# The file 'test_grid_statoil_large_case.py' is part of ERT - Ensemble based Reservoir Tool. +# The file 'test_grid_equinor_large_case.py' is part of ERT - Ensemble based Reservoir Tool. # # ERT is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -18,12 +18,12 @@ import math from ecl.util.test import TestAreaContext from ecl.grid import EclGrid -from tests import EclTest, statoil_test +from tests import EclTest, equinor_test -@statoil_test() +@equinor_test() class GridLargeCaseTest(EclTest): def test_large_case(self): - grdecl_file = self.createTestPath("Statoil/ECLIPSE/1.6.0_issueGrdecl/test_aug2016_gridOnly.grdecl") + grdecl_file = self.createTestPath("Equinor/ECLIPSE/1.6.0_issueGrdecl/test_aug2016_gridOnly.grdecl") grid = EclGrid.loadFromGrdecl( grdecl_file ) diff --git a/ThirdParty/Ert/python/tests/ecl_tests/test_grid_generator.py b/ThirdParty/Ert/python/tests/ecl_tests/test_grid_generator.py index 9289003bc5..cf55ffcf43 100644 --- a/ThirdParty/Ert/python/tests/ecl_tests/test_grid_generator.py +++ b/ThirdParty/Ert/python/tests/ecl_tests/test_grid_generator.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright (C) 2017 Statoil ASA, Norway. +# Copyright (C) 2017 Equinor ASA, Norway. # # The file 'test_grid_generator.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/tests/ecl_tests/test_grid_pandas.py b/ThirdParty/Ert/python/tests/ecl_tests/test_grid_pandas.py index f02bdb8f17..f73e1b6b5f 100644 --- a/ThirdParty/Ert/python/tests/ecl_tests/test_grid_pandas.py +++ b/ThirdParty/Ert/python/tests/ecl_tests/test_grid_pandas.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright (C) 2018 Statoil ASA, Norway. +# Copyright (C) 2018 Equinor ASA, Norway. # # The file 'test_grid.pandas' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/tests/ecl_tests/test_kw_function.py b/ThirdParty/Ert/python/tests/ecl_tests/test_kw_function.py index 21f8452be8..5b42387c04 100644 --- a/ThirdParty/Ert/python/tests/ecl_tests/test_kw_function.py +++ b/ThirdParty/Ert/python/tests/ecl_tests/test_kw_function.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright (C) 2015 Statoil ASA, Norway. +# Copyright (C) 2015 Equinor ASA, Norway. # # The file 'test_kw_function.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/tests/ecl_tests/test_layer.py b/ThirdParty/Ert/python/tests/ecl_tests/test_layer.py index 0c8aabf6f7..9b4b6a55a3 100644 --- a/ThirdParty/Ert/python/tests/ecl_tests/test_layer.py +++ b/ThirdParty/Ert/python/tests/ecl_tests/test_layer.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright (C) 2014 Statoil ASA, Norway. +# Copyright (C) 2014 Equinor ASA, Norway. # # The file 'test_layer.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/tests/ecl_tests/test_npv.py b/ThirdParty/Ert/python/tests/ecl_tests/test_npv.py index 43bd77493f..1b64680e43 100644 --- a/ThirdParty/Ert/python/tests/ecl_tests/test_npv.py +++ b/ThirdParty/Ert/python/tests/ecl_tests/test_npv.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright (C) 2011 Statoil ASA, Norway. +# Copyright (C) 2011 Equinor ASA, Norway. # # The file 'sum_test.py' is part of ERT - Ensemble based Reservoir Tool. # @@ -29,11 +29,11 @@ from ecl.summary import EclNPV , NPVPriceVector from ecl.util.util import StringList, TimeVector, DoubleVector , CTime from ecl.util.test import TestAreaContext -from tests import EclTest, statoil_test +from tests import EclTest, equinor_test base = "ECLIPSE" -path = "Statoil/ECLIPSE/Gurbat" +path = "Equinor/ECLIPSE/Gurbat" case = "%s/%s" % (path, base) def callable(x): @@ -45,7 +45,7 @@ def linear1(x): def linear2(x): return 2*x -@statoil_test() +@equinor_test() class NPVTest(EclTest): def setUp(self): self.case = self.createTestPath(case) diff --git a/ThirdParty/Ert/python/tests/ecl_tests/test_region.py b/ThirdParty/Ert/python/tests/ecl_tests/test_region.py index 6c38697115..d077ae9dca 100644 --- a/ThirdParty/Ert/python/tests/ecl_tests/test_region.py +++ b/ThirdParty/Ert/python/tests/ecl_tests/test_region.py @@ -1,4 +1,4 @@ -# Copyright (C) 2017 Statoil ASA, Norway. +# Copyright (C) 2017 Equinor ASA, Norway. # # The file 'test_region.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/tests/ecl_tests/test_region_statoil.py b/ThirdParty/Ert/python/tests/ecl_tests/test_region_equinor.py similarity index 96% rename from ThirdParty/Ert/python/tests/ecl_tests/test_region_statoil.py rename to ThirdParty/Ert/python/tests/ecl_tests/test_region_equinor.py index 16fc04090a..2ede1f71e6 100644 --- a/ThirdParty/Ert/python/tests/ecl_tests/test_region_statoil.py +++ b/ThirdParty/Ert/python/tests/ecl_tests/test_region_equinor.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright (C) 2012 Statoil ASA, Norway. +# Copyright (C) 2012 Equinor ASA, Norway. # # The file 'test_region.py' is part of ERT - Ensemble based Reservoir Tool. # @@ -17,13 +17,13 @@ from ecl.eclfile import EclFile from ecl.grid import EclGrid, EclRegion from ecl.grid.faults import Layer -from tests import EclTest, statoil_test +from tests import EclTest, equinor_test -@statoil_test() +@equinor_test() class RegionTest(EclTest): def setUp(self): - case = self.createTestPath("Statoil/ECLIPSE/Gurbat/ECLIPSE") + case = self.createTestPath("Equinor/ECLIPSE/Gurbat/ECLIPSE") self.grid = EclGrid(case) self.rst_file = EclFile("%s.UNRST" % case) self.init_file = EclFile("%s.INIT" % case) @@ -166,7 +166,7 @@ class RegionTest(EclTest): def test_heidrun(self): - root = self.createTestPath("Statoil/ECLIPSE/Heidrun") + root = self.createTestPath("Equinor/ECLIPSE/Heidrun") grid = EclGrid( "%s/FF12_2013B2_AMAP_AOP-J15_NO62_MOVEX.EGRID" % root) polygon = [] diff --git a/ThirdParty/Ert/python/tests/ecl_tests/test_removed.py b/ThirdParty/Ert/python/tests/ecl_tests/test_removed.py index db480ffe82..9cc5eea2ae 100644 --- a/ThirdParty/Ert/python/tests/ecl_tests/test_removed.py +++ b/ThirdParty/Ert/python/tests/ecl_tests/test_removed.py @@ -16,8 +16,6 @@ class Removed_2_1_Test(EclTest): with openFortIO("TEST" , mode = FortIO.WRITE_MODE) as f: kw.fwrite( f ) - t.sync() - f = EclFile( "TEST" ) with self.assertRaises(NotImplementedError): f.select_block( "KW" , 100 ) @@ -33,4 +31,4 @@ class Removed_2_1_Test(EclTest): with self.assertRaises(NotImplementedError): EclFile.restart_block( "TEST" ) - + diff --git a/ThirdParty/Ert/python/tests/ecl_tests/test_restart.py b/ThirdParty/Ert/python/tests/ecl_tests/test_restart.py index 32fa276aec..c28164a1b1 100644 --- a/ThirdParty/Ert/python/tests/ecl_tests/test_restart.py +++ b/ThirdParty/Ert/python/tests/ecl_tests/test_restart.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright (C) 2011 Statoil ASA, Norway. +# Copyright (C) 2011 Equinor ASA, Norway. # # The file 'sum_test.py' is part of ERT - Ensemble based Reservoir Tool. # @@ -18,18 +18,18 @@ from _ctypes import ArgumentError import os import datetime from ecl.eclfile import EclFile -from tests import EclTest, statoil_test +from tests import EclTest, equinor_test -@statoil_test() +@equinor_test() class RestartTest(EclTest): def setUp(self): - self.xfile0 = self.createTestPath("Statoil/ECLIPSE/Gurbat/ECLIPSE.X0000") - self.u_file = self.createTestPath("Statoil/ECLIPSE/Gurbat/ECLIPSE.UNRST") - self.fmt_file = self.createTestPath("Statoil/ECLIPSE/Gurbat/ECLIPSE.FUNRST") - self.grid_file = self.createTestPath("Statoil/ECLIPSE/Gurbat/ECLIPSE.EGRID") + self.xfile0 = self.createTestPath("Equinor/ECLIPSE/Gurbat/ECLIPSE.X0000") + self.u_file = self.createTestPath("Equinor/ECLIPSE/Gurbat/ECLIPSE.UNRST") + self.fmt_file = self.createTestPath("Equinor/ECLIPSE/Gurbat/ECLIPSE.FUNRST") + self.grid_file = self.createTestPath("Equinor/ECLIPSE/Gurbat/ECLIPSE.EGRID") self.file_list = [] def addFile( self, filename ): diff --git a/ThirdParty/Ert/python/tests/ecl_tests/test_restart_head.py b/ThirdParty/Ert/python/tests/ecl_tests/test_restart_head.py index c1683f6d41..b92e3cabfe 100644 --- a/ThirdParty/Ert/python/tests/ecl_tests/test_restart_head.py +++ b/ThirdParty/Ert/python/tests/ecl_tests/test_restart_head.py @@ -1,4 +1,4 @@ -# Copyright (C) 2015 Statoil ASA, Norway. +# Copyright (C) 2015 Equinor ASA, Norway. # # The file 'test_ecl_init_file.py' is part of ERT - Ensemble based Reservoir Tool. # @@ -15,17 +15,17 @@ # for more details. import datetime -from tests import EclTest, statoil_test +from tests import EclTest, equinor_test from ecl import EclFileFlagEnum from ecl.eclfile import Ecl3DKW , EclKW, EclRestartFile , EclFile, FortIO from ecl.grid import EclGrid -@statoil_test() +@equinor_test() class RestartHeadTest(EclTest): def setUp(self): - self.grid_file = self.createTestPath("Statoil/ECLIPSE/Gurbat/ECLIPSE.EGRID") - self.unrst_file = self.createTestPath("Statoil/ECLIPSE/Gurbat/ECLIPSE.UNRST") - self.xrst_file0 = self.createTestPath("Statoil/ECLIPSE/Gurbat/ECLIPSE.X0000") + self.grid_file = self.createTestPath("Equinor/ECLIPSE/Gurbat/ECLIPSE.EGRID") + self.unrst_file = self.createTestPath("Equinor/ECLIPSE/Gurbat/ECLIPSE.UNRST") + self.xrst_file0 = self.createTestPath("Equinor/ECLIPSE/Gurbat/ECLIPSE.X0000") def test_headers(self): g = EclGrid( self.grid_file ) diff --git a/ThirdParty/Ert/python/tests/ecl_tests/test_rft.py b/ThirdParty/Ert/python/tests/ecl_tests/test_rft.py index b903f3d78f..f4bf29b003 100644 --- a/ThirdParty/Ert/python/tests/ecl_tests/test_rft.py +++ b/ThirdParty/Ert/python/tests/ecl_tests/test_rft.py @@ -1,19 +1,19 @@ #!/usr/bin/env python -# Copyright (C) 2016 Statoil ASA, Norway. -# +# Copyright (C) 2016 Equinor ASA, Norway. +# # The file 'test_rft.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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. +# +# ERT 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. +# +# ERT 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. import datetime @@ -32,5 +32,5 @@ class RFTTest(EclTest): def test_repr(self): rft = EclRFT( "WELL" , "RFT" , datetime.date(2015 , 10 , 1 ) , 100 ) - pfx = 'EclRFT(completed_cells = 0, date = 2015-10-01, RFT, MSW)' + pfx = 'EclRFT(completed_cells = 0, date = 2015-10-01, RFT)' self.assertEqual(pfx, repr(rft)[:len(pfx)]) diff --git a/ThirdParty/Ert/python/tests/ecl_tests/test_rft_cell.py b/ThirdParty/Ert/python/tests/ecl_tests/test_rft_cell.py index 67fb0c0062..ba0cc007bc 100644 --- a/ThirdParty/Ert/python/tests/ecl_tests/test_rft_cell.py +++ b/ThirdParty/Ert/python/tests/ecl_tests/test_rft_cell.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright (C) 2013 Statoil ASA, Norway. +# Copyright (C) 2013 Equinor ASA, Norway. # # The file 'test_rft_cell.py' is part of ERT - Ensemble based Reservoir Tool. # @@ -27,8 +27,8 @@ from tests import EclTest class RFTCellTest(EclTest): def setUp(self): - self.RFT_file = self.createTestPath("Statoil/ECLIPSE/Gurbat/ECLIPSE.RFT") - self.PLT_file = self.createTestPath("Statoil/ECLIPSE/RFT/TEST1_1A.RFT") + self.RFT_file = self.createTestPath("Equinor/ECLIPSE/Gurbat/ECLIPSE.RFT") + self.PLT_file = self.createTestPath("Equinor/ECLIPSE/RFT/TEST1_1A.RFT") def test_RFT_cell(self): i = 10 diff --git a/ThirdParty/Ert/python/tests/ecl_tests/test_rft_statoil.py b/ThirdParty/Ert/python/tests/ecl_tests/test_rft_equinor.py similarity index 81% rename from ThirdParty/Ert/python/tests/ecl_tests/test_rft_statoil.py rename to ThirdParty/Ert/python/tests/ecl_tests/test_rft_equinor.py index e097551a44..051ee0582a 100644 --- a/ThirdParty/Ert/python/tests/ecl_tests/test_rft_statoil.py +++ b/ThirdParty/Ert/python/tests/ecl_tests/test_rft_equinor.py @@ -1,7 +1,7 @@ #!/usr/bin/env python -# Copyright (C) 2011 Statoil ASA, Norway. +# Copyright (C) 2011 Equinor ASA, Norway. # -# The file 'test_rft_statoil.py' is part of ERT - Ensemble based Reservoir Tool. +# The file 'test_rft_equinor.py' is part of ERT - Ensemble based Reservoir Tool. # # ERT is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -18,14 +18,14 @@ from __future__ import print_function import datetime from ecl.rft import EclRFTFile, EclRFTCell, EclPLTCell, WellTrajectory -from tests import EclTest, statoil_test +from tests import EclTest, equinor_test -@statoil_test() +@equinor_test() class RFTTest(EclTest): def setUp(self): - self.RFT_file = self.createTestPath("Statoil/ECLIPSE/Gurbat/ECLIPSE.RFT") - self.PLT_file = self.createTestPath("Statoil/ECLIPSE/RFT/TEST1_1A.RFT") + self.RFT_file = self.createTestPath("Equinor/ECLIPSE/Gurbat/ECLIPSE.RFT") + self.PLT_file = self.createTestPath("Equinor/ECLIPSE/RFT/TEST1_1A.RFT") def test_RFT_load(self): @@ -53,10 +53,6 @@ class RFTTest(EclTest): for cell in rft: self.assertIsInstance(cell, EclRFTCell) - cell0 = rft.iget_sorted(0) - self.assertIsInstance(cell, EclRFTCell) - rft.sort() - for h in rftFile.getHeaders(): print(h) self.assertIsInstance(h[1], datetime.date) @@ -81,7 +77,7 @@ class RFTTest(EclTest): def test_basics(self): - wt = WellTrajectory(self.createTestPath("Statoil/ert-statoil/spotfire/gendata_rft_zone/E-3H.txt")) + wt = WellTrajectory(self.createTestPath("Equinor/ert-equinor/spotfire/gendata_rft_zone/E-3H.txt")) self.assertEqual(len(wt), 38) self.assertTrue(isinstance(str(wt), str)) self.assertTrue(isinstance(repr(wt), str)) @@ -92,12 +88,12 @@ class RFTTest(EclTest): WellTrajectory("/does/no/exist") with self.assertRaises(UserWarning): - WellTrajectory(self.createTestPath("Statoil/ert-statoil/spotfire/gendata_rft_zone/invalid_float.txt")) + WellTrajectory(self.createTestPath("Equinor/ert-equinor/spotfire/gendata_rft_zone/invalid_float.txt")) with self.assertRaises(UserWarning): - WellTrajectory(self.createTestPath("Statoil/ert-statoil/spotfire/gendata_rft_zone/missing_item.txt")) + WellTrajectory(self.createTestPath("Equinor/ert-equinor/spotfire/gendata_rft_zone/missing_item.txt")) - wt = WellTrajectory(self.createTestPath("Statoil/ert-statoil/spotfire/gendata_rft_zone/E-3H.txt")) + wt = WellTrajectory(self.createTestPath("Equinor/ert-equinor/spotfire/gendata_rft_zone/E-3H.txt")) self.assertEqual(len(wt), 38) with self.assertRaises(IndexError): @@ -115,7 +111,7 @@ class RFTTest(EclTest): def test_PLT(self): - rft_file = EclRFTFile(self.createTestPath("Statoil/ECLIPSE/Heidrun/RFT/2C3_MR61.RFT")) + rft_file = EclRFTFile(self.createTestPath("Equinor/ECLIPSE/Heidrun/RFT/2C3_MR61.RFT")) rft0 = rft_file[0] rft1 = rft_file[1] diff --git a/ThirdParty/Ert/python/tests/ecl_tests/test_sum.py b/ThirdParty/Ert/python/tests/ecl_tests/test_sum.py index b29c8e0da9..5c33c87d04 100644 --- a/ThirdParty/Ert/python/tests/ecl_tests/test_sum.py +++ b/ThirdParty/Ert/python/tests/ecl_tests/test_sum.py @@ -1,4 +1,4 @@ -# Copyright (C) 2011 Statoil ASA, Norway. +# Copyright (C) 2011 Equinor ASA, Norway. # # The file 'sum_test.py' is part of ERT - Ensemble based Reservoir Tool. # @@ -22,8 +22,19 @@ import csv import shutil import cwrap import stat +import pandas + +def assert_frame_equal(a,b): + if not a.equals(b): + raise AssertionError("Expected dataframes to be equal") + +try: + from pandas.testing import assert_frame_equal +except ImportError: + pass + from contextlib import contextmanager -from unittest import skipIf, skipUnless, skipIf +from unittest import skipIf, skipUnless from ecl import EclUnitTypeEnum from ecl import EclDataType @@ -78,6 +89,21 @@ def create_case(case = "CSV", restart_case = None, restart_step = -1, data_start restart_case = restart_case, restart_step = restart_step) +def create_case2(case = "CSV", restart_case = None, restart_step = -1, data_start = None): + length = 100 + return createEclSum(case , [("WOPT", "OPX" , 0, "SM3") , ("FOPR" , None , 0, "SM3/DAY"), ("BPR" , None , 10, "SM3"), ("RPR", None, 3, "BARS"), ("COPR", "OPX", 421, "BARS")], + sim_length_days = length, + num_report_step = 10, + num_mini_step = 10, + data_start = data_start, + func_table = {"FOPT" : fopt, + "FOPR" : fopr , + "FGPT" : fgpt }, + restart_case = restart_case, + restart_step = restart_step) + + + class SumTest(EclTest): @@ -101,19 +127,26 @@ class SumTest(EclTest): def test_identify_var_type(self): - self.assertEnumIsFullyDefined( EclSumVarType , "ecl_smspec_var_type" , "lib/include/ert/ecl/smspec_node.hpp") + self.assertEnumIsFullyDefined( EclSumVarType , "ecl_smspec_var_type" , "lib/include/ert/ecl/smspec_node.h") self.assertEqual( EclSum.varType( "WWCT:OP_X") , EclSumVarType.ECL_SMSPEC_WELL_VAR ) self.assertEqual( EclSum.varType( "RPR") , EclSumVarType.ECL_SMSPEC_REGION_VAR ) self.assertEqual( EclSum.varType( "WNEWTON") , EclSumVarType.ECL_SMSPEC_MISC_VAR ) self.assertEqual( EclSum.varType( "AARQ:4") , EclSumVarType.ECL_SMSPEC_AQUIFER_VAR ) + self.assertEqual( EclSum.varType("RXFT"), EclSumVarType.ECL_SMSPEC_REGION_2_REGION_VAR) + self.assertEqual( EclSum.varType("RxxFT"), EclSumVarType.ECL_SMSPEC_REGION_2_REGION_VAR) + self.assertEqual( EclSum.varType("RXFR"), EclSumVarType.ECL_SMSPEC_REGION_2_REGION_VAR) + self.assertEqual( EclSum.varType("RxxFR"), EclSumVarType.ECL_SMSPEC_REGION_2_REGION_VAR) + self.assertEqual( EclSum.varType("RORFR"), EclSumVarType.ECL_SMSPEC_REGION_VAR) + case = createEclSum("CSV" , [("FOPT", None , 0, "SM3") , ("FOPR" , None , 0, "SM3/DAY"), ("AARQ" , None , 10, "???"), - ("RGPT" , None ,1, "SM3")]) + ("RGPT" , None ,1, "SM3")]) node1 = case.smspec_node( "FOPT" ) self.assertEqual( node1.varType( ) , EclSumVarType.ECL_SMSPEC_FIELD_VAR ) + self.assertIsNone(node1.wgname) node2 = case.smspec_node( "AARQ:10" ) self.assertEqual( node2.varType( ) , EclSumVarType.ECL_SMSPEC_AQUIFER_VAR ) @@ -549,6 +582,24 @@ class SumTest(EclTest): self.assertEqual(len(case), rows) + def test_csv_load(self): + case = create_case2() + frame = case.pandas_frame() + ecl_sum = EclSum.from_pandas("PANDAS", frame, dims=[20,10,5]) + + for key in frame.columns: + self.assertTrue(key in ecl_sum) + + df = ecl_sum.pandas_frame() + assert_frame_equal(frame, df) + + ecl_sum_less = EclSum.from_pandas("PANDAS", frame, dims=[20,10,5], headers=['BPR:10', 'RPR:3,1,1', 'COPR:OPX:1,2,3']) + del frame['WOPT:OPX'] + del frame['FOPR'] + df_less = ecl_sum_less.pandas_frame() + assert_frame_equal(frame, df_less) + + def test_total_and_rate(self): self.assertTrue( EclSum.is_total("FOPT")) self.assertTrue( EclSum.is_total("WWPT:OP_3")) @@ -568,8 +619,6 @@ class SumTest(EclTest): for time_index,value in enumerate(fopr): self.assertEqual(fopr[time_index], value) - - def test_write_not_implemented(self): path = os.path.join(self.TESTDATA_ROOT, "local/ECLIPSE/cp_simple3/SIMPLE_SUMMARY3") case = EclSum( path, lazy_load=True ) @@ -578,10 +627,55 @@ class SumTest(EclTest): case.fwrite( ) - def test_directory_conflict(self): with TestAreaContext("dir_conflict"): case = create_case("UNITS") case.fwrite() os.mkdir("UNITS") case2 = EclSum("./UNITS") + + + def test_resample_extrapolate(self): + """ + Test resampling of summary with extrapolate option of lower and upper boundaries enabled + """ + from ecl.util.util import TimeVector, CTime + + time_points = TimeVector() + + path = os.path.join(self.TESTDATA_ROOT, "local/ECLIPSE/cp_simple3/SIMPLE_SUMMARY3") + ecl_sum = EclSum( path, lazy_load=True ) + + start_time = ecl_sum.get_data_start_time() - datetime.timedelta(seconds=86400) + end_time = ecl_sum.get_end_time() + datetime.timedelta(seconds=86400) + delta = end_time - start_time + + N = 25 + time_points.initRange( CTime(start_time), + CTime(end_time), + CTime(int(delta.total_seconds()/(N - 1)))) + time_points.append(CTime(end_time)) + resampled = ecl_sum.resample( "OUTPUT_CASE", time_points, lower_extrapolation=True, upper_extrapolation=True ) + + for key in ecl_sum.keys(): + self.assertIn( key, resampled ) + + self.assertEqual(ecl_sum.get_data_start_time() - datetime.timedelta(seconds=86400), resampled.get_data_start_time()) + + key_not_rate = "FOPT" + for time_index,t in enumerate(time_points): + if t < ecl_sum.get_data_start_time(): + self.assertFloatEqual(resampled.iget( key_not_rate, time_index), ecl_sum._get_first_value(key_not_rate)) + elif t > ecl_sum.get_end_time(): + self.assertFloatEqual(resampled.iget( key_not_rate, time_index), ecl_sum.get_last_value( key_not_rate)) + else: + self.assertFloatEqual(resampled.iget( key_not_rate, time_index), ecl_sum.get_interp_direct( key_not_rate, t)) + + key_rate = "FOPR" + for time_index,t in enumerate(time_points): + if t < ecl_sum.get_data_start_time(): + self.assertFloatEqual(resampled.iget( key_rate, time_index), 0) + elif t > ecl_sum.get_end_time(): + self.assertFloatEqual(resampled.iget( key_rate, time_index), 0) + else: + self.assertFloatEqual(resampled.iget( key_rate, time_index), ecl_sum.get_interp_direct( key_rate, t)) diff --git a/ThirdParty/Ert/python/tests/ecl_tests/test_sum_statoil.py b/ThirdParty/Ert/python/tests/ecl_tests/test_sum_equinor.py similarity index 93% rename from ThirdParty/Ert/python/tests/ecl_tests/test_sum_statoil.py rename to ThirdParty/Ert/python/tests/ecl_tests/test_sum_equinor.py index 477d5135e3..aa1e6454d8 100644 --- a/ThirdParty/Ert/python/tests/ecl_tests/test_sum_statoil.py +++ b/ThirdParty/Ert/python/tests/ecl_tests/test_sum_equinor.py @@ -1,4 +1,4 @@ -# Copyright (C) 2011 Statoil ASA, Norway. +# Copyright (C) 2011 Equinor ASA, Norway. # # The file 'sum_test.py' is part of ERT - Ensemble based Reservoir Tool. # @@ -26,11 +26,11 @@ from ecl import EclUnitTypeEnum from ecl.util.util import StringList, TimeVector, DoubleVector, CTime from ecl.util.test import TestAreaContext -from tests import EclTest, statoil_test +from tests import EclTest, equinor_test import csv base = "ECLIPSE" -path = "Statoil/ECLIPSE/Gurbat" +path = "Equinor/ECLIPSE/Gurbat" case = "%s/%s" % (path, base) @@ -42,7 +42,7 @@ def sum_get(*args): vec = sum[key] -@statoil_test() +@equinor_test() class SumTest(EclTest): def setUp(self): self.case = self.createTestPath(case) @@ -110,7 +110,7 @@ class SumTest(EclTest): def test_LLINEAR(self): - sum = EclSum( self.createTestPath("Statoil/ECLIPSE/Heidrun/LGRISSUE/EM-LTAA-ISEG_CARFIN_NWPROPS")) + sum = EclSum( self.createTestPath("Equinor/ECLIPSE/Heidrun/LGRISSUE/EM-LTAA-ISEG_CARFIN_NWPROPS")) self.assertTrue( sum.has_key("LLINEARS") ) @@ -163,7 +163,7 @@ class SumTest(EclTest): def test_dates2( self ): - sum = EclSum(self.createTestPath("Statoil/ECLIPSE/FF12/FF12_2013B3_AMAP2")) + sum = EclSum(self.createTestPath("Equinor/ECLIPSE/FF12/FF12_2013B3_AMAP2")) self.assertEqual(sum.end_date , datetime.date(2045, 1, 1)) @@ -216,9 +216,9 @@ class SumTest(EclTest): def test_restart(self): - hist = EclSum(self.createTestPath("Statoil/ECLIPSE/sum-restart/history/T07-4A-W2011-18-P1")) - base = EclSum(self.createTestPath("Statoil/ECLIPSE/sum-restart/prediction/BASECASE")) - pred = EclSum(self.createTestPath("Statoil/ECLIPSE/sum-restart/prediction/BASECASE"), include_restart=False) + hist = EclSum(self.createTestPath("Equinor/ECLIPSE/sum-restart/history/T07-4A-W2011-18-P1")) + base = EclSum(self.createTestPath("Equinor/ECLIPSE/sum-restart/prediction/BASECASE")) + pred = EclSum(self.createTestPath("Equinor/ECLIPSE/sum-restart/prediction/BASECASE"), include_restart=False) self.assertIsNotNone(hist) self.assertIsNotNone(base) @@ -311,7 +311,7 @@ class SumTest(EclTest): def test_segment(self): - sum = EclSum(self.createTestPath("Statoil/ECLIPSE/Oseberg/F8MLT/F8MLT-F4")) + sum = EclSum(self.createTestPath("Equinor/ECLIPSE/Oseberg/F8MLT/F8MLT-F4")) segment_vars = sum.keys("SOFR:F-8:*") self.assertIn("SOFR:F-8:1", segment_vars) for var in segment_vars: @@ -365,7 +365,7 @@ class SumTest(EclTest): # Loading this dataset is a test of loading a case where one report step is missing. def test_Heidrun(self): - sum = EclSum( self.createTestPath("Statoil/ECLIPSE/Heidrun/Summary/FF12_2013B3_CLEAN_RS")) + sum = EclSum( self.createTestPath("Equinor/ECLIPSE/Heidrun/Summary/FF12_2013B3_CLEAN_RS")) self.assertEqual( 452 , len(sum)) self.assertFloatEqual( 1.8533144e+8 , sum.last_value("FOPT")) @@ -422,13 +422,13 @@ class SumTest(EclTest): def test_aquifer(self): - case = EclSum( self.createTestPath( "Statoil/ECLIPSE/Aquifer/06_PRESSURE_R009-0")) + case = EclSum( self.createTestPath( "Equinor/ECLIPSE/Aquifer/06_PRESSURE_R009-0")) self.assertTrue( "AAQR:2" in case ) def test_restart_mapping(self): - history = EclSum( self.createTestPath( "Statoil/ECLIPSE/SummaryRestart/iter-1/NOR-2013A_R007-0") ) - total = EclSum( self.createTestPath( "Statoil/ECLIPSE/SummaryRestart/Prediction/NOR-2013A_R007_PRED-0") , include_restart = True) + history = EclSum( self.createTestPath( "Equinor/ECLIPSE/SummaryRestart/iter-1/NOR-2013A_R007-0") ) + total = EclSum( self.createTestPath( "Equinor/ECLIPSE/SummaryRestart/Prediction/NOR-2013A_R007_PRED-0") , include_restart = True) history_dates = history.get_dates( ) total_dates = total.get_dates( ) @@ -449,7 +449,7 @@ class SumTest(EclTest): def test_write(self): with TestAreaContext("my_space") as area: - intersect_summary = EclSum( self.createTestPath( "Statoil/ECLIPSE/SummaryRestart/iter-1/NOR-2013A_R007-0"), lazy_load=False ) + intersect_summary = EclSum( self.createTestPath( "Equinor/ECLIPSE/SummaryRestart/iter-1/NOR-2013A_R007-0"), lazy_load=False ) self.assertIsNotNone(intersect_summary) write_location = os.path.join(os.getcwd(), "CASE") @@ -459,7 +459,7 @@ class SumTest(EclTest): self.assertEqual(intersect_summary.keys(), reloaded_summary.keys()) def test_ix_case(self): - intersect_summary = EclSum(self.createTestPath("Statoil/ECLIPSE/ix/summary/CREATE_REGION_AROUND_WELL")) + intersect_summary = EclSum(self.createTestPath("Equinor/ECLIPSE/ix/summary/CREATE_REGION_AROUND_WELL")) self.assertIsNotNone(intersect_summary) self.assertTrue( @@ -467,7 +467,7 @@ class SumTest(EclTest): [intersect_summary.smspec_node(key).wgname for key in intersect_summary.keys()] ) - eclipse_summary = EclSum(self.createTestPath("Statoil/ECLIPSE/ix/summary/ECL100/E100_CREATE_REGION_AROUND_WELL")) + eclipse_summary = EclSum(self.createTestPath("Equinor/ECLIPSE/ix/summary/ECL100/E100_CREATE_REGION_AROUND_WELL")) self.assertIsNotNone(eclipse_summary) hwell_padder = lambda key : key if key.split(":")[-1] != "HWELL_PR" else key + "OD" @@ -478,8 +478,8 @@ class SumTest(EclTest): def test_ix_write(self): for data_set in [ - "Statoil/ECLIPSE/ix/summary/CREATE_REGION_AROUND_WELL", - "Statoil/ECLIPSE/ix/troll/IX_NOPH3_R04_75X75X1_GRID2.SMSPEC" + "Equinor/ECLIPSE/ix/summary/CREATE_REGION_AROUND_WELL", + "Equinor/ECLIPSE/ix/troll/IX_NOPH3_R04_75X75X1_GRID2.SMSPEC" ]: with TestAreaContext("my_space" + data_set.split("/")[-1]) as area: @@ -496,7 +496,7 @@ class SumTest(EclTest): ) def test_ix_caseII(self): - troll_summary = EclSum( self.createTestPath("Statoil/ECLIPSE/ix/troll/IX_NOPH3_R04_75X75X1_GRID2.SMSPEC")) + troll_summary = EclSum( self.createTestPath("Equinor/ECLIPSE/ix/troll/IX_NOPH3_R04_75X75X1_GRID2.SMSPEC")) self.assertIsNotNone(troll_summary) self.assertTrue("WMCTL:Q21BH1" in list(troll_summary.keys())) @@ -525,7 +525,6 @@ class SumTest(EclTest): for time_index,t in enumerate(time_points): self.assertFloatEqual(resampled.iget( key, time_index), self.ecl_sum.get_interp_direct( key, t)) - def test_summary_units(self): self.assertEqual(self.ecl_sum.unit_system, EclUnitTypeEnum.ECL_METRIC_UNITS) @@ -534,4 +533,4 @@ class SumTest(EclTest): # which was shut down brutally. This test verifies that we # can create a valid ecl_sum instance from what we find. def test_broken_case(self): - ecl_sum = EclSum( self.createTestPath("Statoil/ECLIPSE/SummaryFail3/COMBINED-AUTUMN2018_CARBSENS-0")) + ecl_sum = EclSum( self.createTestPath("Equinor/ECLIPSE/SummaryFail3/COMBINED-AUTUMN2018_CARBSENS-0")) diff --git a/ThirdParty/Ert/python/tests/global_tests/test_import.py b/ThirdParty/Ert/python/tests/global_tests/test_import.py index 6681589a8d..ef3c3b5eb5 100644 --- a/ThirdParty/Ert/python/tests/global_tests/test_import.py +++ b/ThirdParty/Ert/python/tests/global_tests/test_import.py @@ -1,4 +1,4 @@ -# Copyright (C) 2017 Statoil ASA, Norway. +# Copyright (C) 2017 Equinor ASA, Norway. # # This file is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/tests/global_tests/test_pylint.py b/ThirdParty/Ert/python/tests/global_tests/test_pylint.py index 1dac7dafaf..ce93f60934 100644 --- a/ThirdParty/Ert/python/tests/global_tests/test_pylint.py +++ b/ThirdParty/Ert/python/tests/global_tests/test_pylint.py @@ -1,4 +1,4 @@ -# Copyright (C) 2017 Statoil ASA, Norway. +# Copyright (C) 2017 Equinor ASA, Norway. # # This file is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/tests/legacy_tests/test_test.py b/ThirdParty/Ert/python/tests/legacy_tests/test_test.py index 1b75b2941f..ba588d6333 100644 --- a/ThirdParty/Ert/python/tests/legacy_tests/test_test.py +++ b/ThirdParty/Ert/python/tests/legacy_tests/test_test.py @@ -2,7 +2,6 @@ from ert.test import TestRun from ert.test import path_exists from ert.test import SourceEnumerator from ert.test import TestArea , TestAreaContext -from ert.test import TempArea , TempAreaContext from ert.test import ErtTestRunner from ert.test import PathContext from ert.test import LintTestCase diff --git a/ThirdParty/Ert/python/tests/util_tests/test_rng.py b/ThirdParty/Ert/python/tests/util_tests/test_rng.py index 2a4f786705..70148013c5 100644 --- a/ThirdParty/Ert/python/tests/util_tests/test_rng.py +++ b/ThirdParty/Ert/python/tests/util_tests/test_rng.py @@ -37,7 +37,6 @@ class RngTest(EclTest): with TestAreaContext("rng_state") as t: rng.saveState( "rng.txt" ) - t.sync() val1 = rng.getInt() val2 = rng.getInt() rng.loadState( "rng.txt" ) diff --git a/ThirdParty/Ert/python/tests/util_tests/test_vectors.py b/ThirdParty/Ert/python/tests/util_tests/test_vectors.py index 47d306aacd..e16cfcea75 100644 --- a/ThirdParty/Ert/python/tests/util_tests/test_vectors.py +++ b/ThirdParty/Ert/python/tests/util_tests/test_vectors.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright (C) 2011 Statoil ASA, Norway. +# Copyright (C) 2011 Equinor ASA, Norway. # # The file 'test_vectors.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/tests/util_tests/test_version.py b/ThirdParty/Ert/python/tests/util_tests/test_version.py index c0864b4a20..0a82658b86 100644 --- a/ThirdParty/Ert/python/tests/util_tests/test_version.py +++ b/ThirdParty/Ert/python/tests/util_tests/test_version.py @@ -1,4 +1,4 @@ -# Copyright (C) 2015 Statoil ASA, Norway. +# Copyright (C) 2015 Equinor ASA, Norway. # # The file 'test_version.py' is part of ERT - Ensemble based Reservoir Tool. # diff --git a/ThirdParty/Ert/python/tests/util_tests/test_work_area.py b/ThirdParty/Ert/python/tests/util_tests/test_work_area.py index 0d7a69bae5..1a89ac7621 100644 --- a/ThirdParty/Ert/python/tests/util_tests/test_work_area.py +++ b/ThirdParty/Ert/python/tests/util_tests/test_work_area.py @@ -1,21 +1,21 @@ #!/usr/bin/env python -# Copyright (C) 2014 Statoil ASA, Norway. -# +# Copyright (C) 2014 Equinor ASA, Norway. +# # The file 'test_work_area.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 +# +# ERT 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. +# +# ERT 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. -import os.path +import os.path import os try: @@ -23,7 +23,7 @@ try: except ImportError: from unittest import skipIf -from ecl.util.test import TestAreaContext, TempAreaContext +from ecl.util.test import TestAreaContext from tests import EclTest @@ -33,39 +33,20 @@ class WorkAreaTest(EclTest): with TestAreaContext("TestArea") as test_area: with open("test_file" , "w") as fileH: fileH.write("Something") - + self.assertTrue( os.path.isfile( "test_file") ) - + with self.assertRaises(IOError): full_path = test_area.getFullPath( "does/not/exists" ) with self.assertRaises(IOError): full_path = test_area.getFullPath( "/already/absolute" ) - + full_path = test_area.getFullPath( "test_file" ) self.assertTrue( os.path.isfile( full_path )) self.assertTrue( os.path.isabs( full_path )) - - def test_temp_area(self): - with TestAreaContext("TestArea") as test_area: - cwd = os.getcwd() - with open("file.txt" , "w") as f: - f.write("File") - - with TempAreaContext("TempArea") as temp_area: - self.assertEqual( cwd, os.getcwd()) - self.assertEqual( cwd, temp_area.get_cwd()) - temp_area.copy_file( "file.txt" ) - self.assertTrue( os.path.isfile( os.path.join( temp_area.getPath( ) , "file.txt"))) - - os.mkdir("tmp") - os.chdir("tmp") - - self.assertEqual( os.getcwd() , os.path.join( cwd , "tmp")) - - def test_IOError(self): with TestAreaContext("TestArea") as test_area: with self.assertRaises(IOError): @@ -86,40 +67,33 @@ class WorkAreaTest(EclTest): with self.assertRaises(IOError): test_area.copy_directory( "path1/file.txt" ) - - def test_sync(self): - with TestAreaContext("test_sync") as t: - with open("file.txt" , "w") as f: - f.write("content") - t.sync() - self.assertTrue( os.path.isfile( "file.txt")) - + def test_multiple_areas(self): original_dir = os.getcwd() context_dirs = [] for i in range(3): loop_dir = os.getcwd() - self.assertEqual(loop_dir, original_dir, + self.assertEqual(loop_dir, original_dir, 'Wrong folder before creating TestAreaContext. Loop: {} -- CWD: {} ' .format(i, loop_dir)) - + with TestAreaContext("test_multiple_areas") as t: t_dir = t.get_cwd() - - self.assertNotIn(t_dir, context_dirs, + + self.assertNotIn(t_dir, context_dirs, 'Multiple TestAreaContext objects in the same folder. Loop {} -- CWD: {}' .format(i, loop_dir)) context_dirs.append(t_dir) - + # It is possible to make the following assert fail, but whoever run the tests should # try really really hard to make that happen - self.assertNotEqual(t_dir, original_dir, + self.assertNotEqual(t_dir, original_dir, 'TestAreaContext in the current working directory. Loop: {} -- CWD: {}' - .format(i, loop_dir)) - + .format(i, loop_dir)) + loop_dir = os.getcwd() - self.assertEqual(loop_dir, original_dir, + self.assertEqual(loop_dir, original_dir, 'Wrong folder after creating TestAreaContext. Loop: {} -- CWD: {} ' .format(i, loop_dir)) - + diff --git a/ThirdParty/Ert/python/tests/well_tests/CMakeLists.txt b/ThirdParty/Ert/python/tests/well_tests/CMakeLists.txt index 00d362918c..f943b5d5f4 100644 --- a/ThirdParty/Ert/python/tests/well_tests/CMakeLists.txt +++ b/ThirdParty/Ert/python/tests/well_tests/CMakeLists.txt @@ -3,6 +3,7 @@ set(TEST_SOURCES test_ecl_well.py test_ecl_well2.py test_ecl_well3.py + test_well_missing_ICON.py ) add_python_package("python.tests.well_tests" ${PYTHON_INSTALL_PREFIX}/tests/well_tests "${TEST_SOURCES}" False) @@ -10,3 +11,4 @@ add_python_package("python.tests.well_tests" ${PYTHON_INSTALL_PREFIX}/tests/wel addPythonTest(tests.well_tests.test_ecl_well.EclWellTest) addPythonTest(tests.well_tests.test_ecl_well2.EclWellTest2) addPythonTest(tests.well_tests.test_ecl_well3.EclWellTest3) +addPythonTest(tests.well_tests.test_well_missing_ICON.EclWellICONTest) diff --git a/ThirdParty/Ert/python/tests/well_tests/test_ecl_well.py b/ThirdParty/Ert/python/tests/well_tests/test_ecl_well.py index cb3b5c3038..391fe05c52 100644 --- a/ThirdParty/Ert/python/tests/well_tests/test_ecl_well.py +++ b/ThirdParty/Ert/python/tests/well_tests/test_ecl_well.py @@ -2,11 +2,11 @@ import datetime from ecl import EclFileFlagEnum from ecl.eclfile import EclFile from ecl.grid import EclGrid -from tests import EclTest, statoil_test +from tests import EclTest, equinor_test from ecl.util.util.ctime import CTime from ecl.well import WellInfo, WellConnection, WellTypeEnum, WellConnectionDirectionEnum, WellSegment -@statoil_test() +@equinor_test() class EclWellTest(EclTest): ALL_WELLS = ['E5H', 'G1H', 'M41', 'J41', 'D10H', 'P41', 'L41', 'M42', 'S41', 'S13H', 'Q12HT2', 'O41', 'L11H', 'Q21H', 'E6CH', 'D4Y1H', 'D4Y2H', 'I13Y1H', 'Q21AY1H', 'F5AH', 'O14Y4HT2', 'K24Y1H', 'K24Y3H', 'S21H', 'N11H', @@ -39,8 +39,8 @@ class EclWellTest(EclTest): def getWellInfoWithNoWellSegments(self): """ @rtype: WellInfo """ if EclWellTest.__well_info_with_no_well_segments is None: - grid_path = self.createTestPath("Statoil/ECLIPSE/Troll/MSW/T07-4A-W2012-16-F3.EGRID") - rst_path_1 = self.createTestPath("Statoil/ECLIPSE/Troll/MSW/T07-4A-W2012-16-F3.X0135") + grid_path = self.createTestPath("Equinor/ECLIPSE/Troll/MSW/T07-4A-W2012-16-F3.EGRID") + rst_path_1 = self.createTestPath("Equinor/ECLIPSE/Troll/MSW/T07-4A-W2012-16-F3.X0135") grid = EclGrid(grid_path) @@ -54,8 +54,8 @@ class EclWellTest(EclTest): def getWellInfo(self): """ @rtype: WellInfo """ if EclWellTest.__well_info is None: - grid_path = self.createTestPath("Statoil/ECLIPSE/Troll/MSW/T07-4A-W2012-16-F3.EGRID") - rst_path_1 = self.createTestPath("Statoil/ECLIPSE/Troll/MSW/T07-4A-W2012-16-F3.X0135") + grid_path = self.createTestPath("Equinor/ECLIPSE/Troll/MSW/T07-4A-W2012-16-F3.EGRID") + rst_path_1 = self.createTestPath("Equinor/ECLIPSE/Troll/MSW/T07-4A-W2012-16-F3.X0135") grid = EclGrid(grid_path) @@ -68,7 +68,7 @@ class EclWellTest(EclTest): def test_no_such_well(self): - grid_path = self.createTestPath("Statoil/ECLIPSE/Gurbat/ECLIPSE.EGRID") + grid_path = self.createTestPath("Equinor/ECLIPSE/Gurbat/ECLIPSE.EGRID") rst_path1 = self.createTestPath("nosuch/path/ECLIPSE.X001") rst_path2 = self.createTestPath("nosuch/path/ECLIPSE.X002") grid = EclGrid(grid_path) @@ -78,11 +78,11 @@ class EclWellTest(EclTest): _ = WellInfo(grid, [rst_path1, rst_path2]) def test_construction(self): - grid_path = self.createTestPath("Statoil/ECLIPSE/Gurbat/ECLIPSE.EGRID") - rst_path_1 = self.createTestPath("Statoil/ECLIPSE/Gurbat/ECLIPSE.X0011") - rst_path_2 = self.createTestPath("Statoil/ECLIPSE/Gurbat/ECLIPSE.X0022") - rst_path_3 = self.createTestPath("Statoil/ECLIPSE/Gurbat/ECLIPSE.X0035") - rst_path_4 = self.createTestPath("Statoil/ECLIPSE/Gurbat/ECLIPSE.X0061") + grid_path = self.createTestPath("Equinor/ECLIPSE/Gurbat/ECLIPSE.EGRID") + rst_path_1 = self.createTestPath("Equinor/ECLIPSE/Gurbat/ECLIPSE.X0011") + rst_path_2 = self.createTestPath("Equinor/ECLIPSE/Gurbat/ECLIPSE.X0022") + rst_path_3 = self.createTestPath("Equinor/ECLIPSE/Gurbat/ECLIPSE.X0035") + rst_path_4 = self.createTestPath("Equinor/ECLIPSE/Gurbat/ECLIPSE.X0061") grid = EclGrid(grid_path) @@ -449,7 +449,7 @@ class EclWellTest(EclTest): def test_load_broken_direction(self): - grid_path = self.createTestPath("Statoil/ECLIPSE/icon-invalid-value/R6_HM2016B_FFP_BASE.EGRID") - rst_path = self.createTestPath("Statoil/ECLIPSE/icon-invalid-value/R6_HM2016B_FFP_BASE.UNRST") + grid_path = self.createTestPath("Equinor/ECLIPSE/icon-invalid-value/R6_HM2016B_FFP_BASE.EGRID") + rst_path = self.createTestPath("Equinor/ECLIPSE/icon-invalid-value/R6_HM2016B_FFP_BASE.UNRST") grid = EclGrid(grid_path) well_info = WellInfo(grid, rst_path) diff --git a/ThirdParty/Ert/python/tests/well_tests/test_ecl_well2.py b/ThirdParty/Ert/python/tests/well_tests/test_ecl_well2.py index 554e18bda2..2535228939 100644 --- a/ThirdParty/Ert/python/tests/well_tests/test_ecl_well2.py +++ b/ThirdParty/Ert/python/tests/well_tests/test_ecl_well2.py @@ -4,19 +4,19 @@ import os.path from ecl import EclFileFlagEnum from ecl.eclfile import EclFile from ecl.grid import EclGrid -from tests import EclTest, statoil_test +from tests import EclTest, equinor_test from ecl.util.util.ctime import CTime from ecl.well import WellInfo, WellConnection, WellTypeEnum, WellConnectionDirectionEnum, WellSegment -@statoil_test() +@equinor_test() class EclWellTest2(EclTest): grid = None def getGrid(self): if EclWellTest2.grid is None: - EclWellTest2.grid = EclGrid( self.createTestPath("Statoil/ECLIPSE/Troll/Ref2014/T07-4A-W2014-06.EGRID")) + EclWellTest2.grid = EclGrid( self.createTestPath("Equinor/ECLIPSE/Troll/Ref2014/T07-4A-W2014-06.EGRID")) return EclWellTest2.grid @@ -25,7 +25,7 @@ class EclWellTest2(EclTest): segment_length = [2660 , 20 , 121 , 1347.916 , 20.585 , 56.249 , 115.503 , 106.978 , 47.124 , 279.529, 128.534 , 165.33 , 59.97 , 936.719 ] - well_info = WellInfo( self.getGrid() , self.createTestPath( os.path.join("Statoil/ECLIPSE/Troll/Ref2014" , rst_file ))) + well_info = WellInfo( self.getGrid() , self.createTestPath( os.path.join("Equinor/ECLIPSE/Troll/Ref2014" , rst_file ))) well_time_line = well_info["F4BYH"] for well_state in well_time_line: self.assertTrue( well_state.isMultiSegmentWell() ) diff --git a/ThirdParty/Ert/python/tests/well_tests/test_ecl_well3.py b/ThirdParty/Ert/python/tests/well_tests/test_ecl_well3.py index 9252f111d6..027cfc47cf 100644 --- a/ThirdParty/Ert/python/tests/well_tests/test_ecl_well3.py +++ b/ThirdParty/Ert/python/tests/well_tests/test_ecl_well3.py @@ -4,18 +4,18 @@ import os.path from ecl.eclfile import EclFile from ecl.grid import EclGrid from ecl.summary import EclSum -from tests import EclTest, statoil_test +from tests import EclTest, equinor_test from ecl.util.util.ctime import CTime from ecl.well import WellInfo, WellConnection, WellTypeEnum, WellConnectionDirectionEnum, WellSegment -@statoil_test() +@equinor_test() class EclWellTest3(EclTest): grid = None def test_rates(self): - grid_path = self.createTestPath("Statoil/ECLIPSE/Gurbat/ECLIPSE.EGRID") - rst_path = self.createTestPath("Statoil/ECLIPSE/Gurbat/ECLIPSE.UNRST") - sum_path = self.createTestPath("Statoil/ECLIPSE/Gurbat/ECLIPSE.SMSPEC") + grid_path = self.createTestPath("Equinor/ECLIPSE/Gurbat/ECLIPSE.EGRID") + rst_path = self.createTestPath("Equinor/ECLIPSE/Gurbat/ECLIPSE.UNRST") + sum_path = self.createTestPath("Equinor/ECLIPSE/Gurbat/ECLIPSE.SMSPEC") grid = EclGrid(grid_path) well_info = WellInfo(grid, rst_path) diff --git a/ThirdParty/Ert/python/tests/well_tests/test_well_missing_ICON.py b/ThirdParty/Ert/python/tests/well_tests/test_well_missing_ICON.py new file mode 100644 index 0000000000..28cb69d1af --- /dev/null +++ b/ThirdParty/Ert/python/tests/well_tests/test_well_missing_ICON.py @@ -0,0 +1,28 @@ +import datetime +from tests import EclTest +from ecl.grid import EclGridGenerator +from ecl.well import WellInfo, WellConnection, WellTypeEnum, WellConnectionDirectionEnum, WellSegment + + + + +class EclWellICONTest(EclTest): + + def setUp(self): + self.grid = EclGridGenerator.create_rectangular((46,112,22), (1,1,1)) + self.rst_file_ICON0 = self.createTestPath("local/ECLIPSE/well/missing-ICON/ICON0.X0027") + self.rst_file_ICON1 = self.createTestPath("local/ECLIPSE/well/missing-ICON/ICON1.X0027") + + + def check_connections(self, well_info, expected): + well = well_info["B-2H"] + well_state = well[0] + self.assertEqual( well_state.hasGlobalConnections(), expected) + + + def test_missing_icon(self): + well_info_ICON0 = WellInfo(self.grid, self.rst_file_ICON0) + well_info_ICON1 = WellInfo(self.grid, self.rst_file_ICON1) + + self.check_connections(well_info_ICON0, False) + self.check_connections(well_info_ICON1, True) diff --git a/ThirdParty/Ert/python/txt-doc/README.txt b/ThirdParty/Ert/python/txt-doc/README.txt new file mode 100644 index 0000000000..7a7a6b294a --- /dev/null +++ b/ThirdParty/Ert/python/txt-doc/README.txt @@ -0,0 +1,4 @@ +The files 'devel.txt', 'import.txt', 'tips.txt' and 'install.txt' in the 'txt-doc/' +directory are old text files with documentation. The content of these files is - +to a varyiing degree - relevant and valuable, but it should be integrated into +the rst files, and then deleted. diff --git a/ThirdParty/Ert/python/doc/devel.txt b/ThirdParty/Ert/python/txt-doc/devel.txt similarity index 99% rename from ThirdParty/Ert/python/doc/devel.txt rename to ThirdParty/Ert/python/txt-doc/devel.txt index 7bae061d39..0b72477791 100644 --- a/ThirdParty/Ert/python/doc/devel.txt +++ b/ThirdParty/Ert/python/txt-doc/devel.txt @@ -13,7 +13,7 @@ Developer documentation 4.2 Prototyping 4.3 Python classes 5 Garbage collection and 'data_owner' - 6 Installation in Statoil + 6 Installation in Equinor @@ -210,12 +210,12 @@ The following excerpt from ecl_kw.y illustrates this: # Load the shared library import libecl <--- Step 1 - Class EclKW: <-------------· + Class EclKW: <-------------� # Pure Python code to implement the EclKW class, | # based on the functions prototyped below. | Step 3 - .... <-------------· + .... <-------------� - # Create a wrapper instance which wraps the libecl library. <--------· + # Create a wrapper instance which wraps the libecl library. <--------� cwrapper = CWrapper( libecl.lib ) | | # Register the type mapping "ecl_kw" <-> EclKW | Step 2 @@ -224,7 +224,7 @@ The following excerpt from ecl_kw.y illustrates this: # Prototype the functions needed to implement the Python class | cfunc.alloc_new = cwrapper.prototype("long ecl_kw_alloc( char* , int , int )") cfunc.free = cwrapper.prototype("void ecl_kw_free( ecl_kw )") | - .... <--------· + .... <--------� ------------------------------------------------------------ These three steps are described in more detail in 4.1 - 4.3 below. @@ -423,7 +423,7 @@ takeover' or 'orphaning' of objects). -6 Installation in Statoil +6 Installation in Equinor -In Statoil the ert Python libraries are installed in the /project/res +In Equinor the ert Python libraries are installed in the /project/res hierarchy. diff --git a/ThirdParty/Ert/python/doc/import.txt b/ThirdParty/Ert/python/txt-doc/import.txt similarity index 100% rename from ThirdParty/Ert/python/doc/import.txt rename to ThirdParty/Ert/python/txt-doc/import.txt diff --git a/ThirdParty/Ert/python/doc/install.txt b/ThirdParty/Ert/python/txt-doc/install.txt similarity index 100% rename from ThirdParty/Ert/python/doc/install.txt rename to ThirdParty/Ert/python/txt-doc/install.txt diff --git a/ThirdParty/Ert/docs/tips.txt b/ThirdParty/Ert/python/txt-doc/tips.txt similarity index 99% rename from ThirdParty/Ert/docs/tips.txt rename to ThirdParty/Ert/python/txt-doc/tips.txt index d6bf3c18dc..40e8b9c349 100644 --- a/ThirdParty/Ert/docs/tips.txt +++ b/ThirdParty/Ert/python/txt-doc/tips.txt @@ -4,7 +4,7 @@ Table of contents: 2. About gen_data / gen_param and gen_obs. 3. Some tips for implementing a obs_script 4. About the ERT filesystem - 5. Installing ERT software in Statoil + 5. Installing ERT software in Equinor ********************************************************************** @@ -440,7 +440,7 @@ program, the block_fs system then has an api for reading and writing The block_fs_driver/block_fs combination is quite complex, but it has not had any hickups for about 1.5 years of extensive use in -Statoil. Observe that if you pull the plug on ERT you might loose some +Equinor. Observe that if you pull the plug on ERT you might loose some of the data which has been stored with the block_fs driver, but partly written and malformed data will be detected and discarded at the next boot. You are therefore guaranteed (add as many quotes you like to the @@ -524,10 +524,10 @@ enkf_fs. Not very important functions, but convenient enough. ********************************************************************** -5. Installing ERT software in Statoil +5. Installing ERT software in Equinor ------------------------------------- -Installation of research software in Statoil is according to the +Installation of research software in Equinor is according to the general guideline: 1. Log in to a computer in Trondheim with the correct version of diff --git a/ThirdParty/Ert/redhat/ecl.spec b/ThirdParty/Ert/redhat/ecl.spec index cca9c92159..7c85366a8e 100644 --- a/ThirdParty/Ert/redhat/ecl.spec +++ b/ThirdParty/Ert/redhat/ecl.spec @@ -2,7 +2,7 @@ # spec file for package ecl # -%define tag final +%define tag rc1 Name: ecl Version: 2018.10 @@ -11,7 +11,7 @@ Summary: ECL library License: GPL-3+ Group: Development/Libraries/C and C++ Url: http://ert.nr.no -Source0: https://github.com/Statoil/libecl/archive/release/%{version}/%{tag}.tar.gz#/%{name}-%{version}.tar.gz +Source0: https://github.com/Equinor/libecl/archive/release/%{version}/%{tag}.tar.gz#/%{name}-%{version}.tar.gz BuildRequires: lapack-devel zlib-devel iputils BuildRequires: devtoolset-6-toolchain %{?!el6:BuildRequires: python-devel numpy python-pandas python-cwrap} diff --git a/ThirdParty/Ert/requirements.txt b/ThirdParty/Ert/requirements.txt index 4d44c49dca..303f7ff42b 100644 --- a/ThirdParty/Ert/requirements.txt +++ b/ThirdParty/Ert/requirements.txt @@ -1,3 +1,7 @@ cwrap numpy pandas +sphinx +future +six +functools32;python_version=='2.7' diff --git a/ThirdParty/Ert/script/download-pr b/ThirdParty/Ert/script/download-pr index 7e6f01ad12..fb82bb3940 100644 --- a/ThirdParty/Ert/script/download-pr +++ b/ThirdParty/Ert/script/download-pr @@ -4,7 +4,7 @@ import json import os import sys -url_fmt = "https://api.github.com/repos/Statoil/libecl/pulls/%d" +url_fmt = "https://api.github.com/repos/Equinor/libecl/pulls/%d" def getPRList( api_token, pr1, pr2): pr = pr1 @@ -38,7 +38,7 @@ def printPRList( pr_list , fileH): title = pr["title"] body = pr["body"] nr = pr["number"] - url = "https://github.com/Statoil/libecl/pull/{}/".format(nr) + url = "https://github.com/Equinor/libecl/pull/{}/".format(nr) try: title = str(title) diff --git a/ThirdParty/Ert/setup.py b/ThirdParty/Ert/setup.py index 5dacb9973b..ac71393d32 100644 --- a/ThirdParty/Ert/setup.py +++ b/ThirdParty/Ert/setup.py @@ -31,13 +31,13 @@ class CMakeBuild(build_ext): subprocess.check_call(['cmake', '--build', '.'] + build_args, cwd=self.build_temp) setup( - name='statoil_libecl', + name='equinor_libecl', version='0.1.1', author_email='chandan.nath@gmail.com', description='libecl', long_description=open("README.md", "r").read(), long_description_content_type="text/markdown", - url="https://github.com/statoil/libecl", + url="https://github.com/equinor/libecl", license="GNU General Public License, Version 3, 29 June 2007", packages=find_packages(where='python', exclude=["*.tests", "*.tests.*", "tests.*", "tests"]), package_dir={'': 'python'}, diff --git a/ThirdParty/Ert/test-data/README.txt b/ThirdParty/Ert/test-data/README.txt index 2e7e908124..182de174d3 100644 --- a/ThirdParty/Ert/test-data/README.txt +++ b/ThirdParty/Ert/test-data/README.txt @@ -2,11 +2,11 @@ This directory is meant as a holding place for test data for the ERT project. The local/ directory should contain test-data which is checked in an distributed as part of the solution. -In addition many of the tests expect to find a Statoil/ subdirectory -in the current directory. This directory should link to Statoil +In addition many of the tests expect to find a Equinor/ subdirectory +in the current directory. This directory should link to Equinor internal test data. This data is currently located on the enkf disk in -Bergen; before you can start using the Statoil specific test data you +Bergen; before you can start using the Equinor specific test data you must add the following symlink: - ln -s /ErtTestData Statoil + ln -s /ErtTestData Equinor diff --git a/ThirdParty/Ert/test-data/local/ECLIPSE/cp_simple3/SHORT.SMSPEC b/ThirdParty/Ert/test-data/local/ECLIPSE/cp_simple3/SHORT.SMSPEC new file mode 100644 index 0000000000000000000000000000000000000000..ffeee8809c9d3787541f14210e30b638f28527e5 GIT binary patch literal 64700 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 z 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 O2=mMO`u`pM`~Lu!y8uuC literal 0 HcmV?d00001 diff --git a/ThirdParty/Ert/test-data/local/ECLIPSE/cp_simple3/SIMPLE_SUMMARY3.DATA b/ThirdParty/Ert/test-data/local/ECLIPSE/cp_simple3/SIMPLE_SUMMARY3.DATA index ccfa835647..d1447bee5a 100644 --- a/ThirdParty/Ert/test-data/local/ECLIPSE/cp_simple3/SIMPLE_SUMMARY3.DATA +++ b/ThirdParty/Ert/test-data/local/ECLIPSE/cp_simple3/SIMPLE_SUMMARY3.DATA @@ -3,7 +3,7 @@ -- individual contents of the database are licensed under the Database Contents -- License: http://opendatacommons.org/licenses/dbcl/1.0/ --- Copyright (C) 2016 Statoil +-- Copyright (C) 2016 Equinor -- NOTE: This deck is currently not supported by the OPM -- simulator flow due to lack of support for LGR. diff --git a/ThirdParty/Ert/test-data/local/ECLIPSE/well/missing-ICON/ICON0.X0027 b/ThirdParty/Ert/test-data/local/ECLIPSE/well/missing-ICON/ICON0.X0027 new file mode 100644 index 0000000000000000000000000000000000000000..37ad813f10d487d0a83ae948be7b627ec7a30796 GIT binary patch literal 9280 zcmeHMO-NKx6uzc4{a6mEVP+&);-V4CexSfNzc_-Wgb}oih!!o{BxNlkT=qlK#?gf> zTa+zw5d;ZE(I%o6)v_=NLast9=bd}s_s+X_?j5C6 zxbt9dDxHcYl`0!%S)om-6{nz;DzBcxwahISURu#~8rY!J?Q41FkS?!;-U?I!y#V6Q zl3~>PflEO7EQ?p!2-O1Y)3$MF_ID3huG=`a^*|l48erecfC_*@yJ`Hc!yK2jupwsX zIdna+X%1hSWK7~#i30oPGvtqfe2^OoxGRw31uZ##B#!7JuC_@tK#mA zf@IUiTEYyt>rFV>eK_u|Md|~~AOvehs3m%)$K}SE@hFONRe?D7hbS56QJX7KJ*zse zyn0rPU(c}vFF)V<-roQEOXk5?+Nt03{!>FD;zcuG3;NUdIXC*>b=;{rFWM9#Sv$7* z?D*xVXp`T+((Vj+&utp7Jf~=rU#WJvUvw$|hdMt>`OViZ{fmz8P4|675a+9xXHt)~ z4qTjX?BDU1@kk8E{TzleQuk~5e*Eo!s~+up;dWi}JC^TPwBb9>ey2J=+wVU4Hab3i z#nJwv{m;Aq>B!B>!FZE1v)j2aef^}^{d~!M5*3F(q+`v=Np=-$?zl=V<8q$4FFfPC z)mrDHj8pu0PrhXRr%t#M%{Tr+S>pP&|JJPCFwaW z^^aG0DRqC&9%?~3+|}LDsn^kSEVB(ig(rV#$@$yT|HnWX=ZbLWkyKYB1Y6-ZxqW@r zC~RwhCV=}F?v)9aD**1pWiM{r-yn@f;8#?bVnq#Jqnr)Q;bJ!B#g;LeovmdtFu=2p zEx;;(`)~e2mwe-SiJX}%=3J98Vz^coF#|m3A^5&{cE?=fJi*+uxdsxf1jfKRL}~yy zuL(HU*<1q&Rsv;!>t-Xs+~WLJ1K2ebBv=WYfoeo-1|-+`zn7iY0;kyq1Ov>i?SSN3 ztu8O|eJJ nBC;#Z^Eto7BRh+>CnGxy?Zy4$hWJTCd%_Su6=^HlFQ4HjU3Hwz literal 0 HcmV?d00001 diff --git a/ThirdParty/Ert/test-data/local/ECLIPSE/well/missing-ICON/ICON1.X0027 b/ThirdParty/Ert/test-data/local/ECLIPSE/well/missing-ICON/ICON1.X0027 new file mode 100644 index 0000000000000000000000000000000000000000..7ed2efdc203e62e5762786591e8c7947eb484740 GIT binary patch literal 38168 zcmeI5ONbm*6oxB~W_(0v)I?(**bx@$ zNfzVMg~o+h2!a7caU-G&b*X3&BoKAsMu_LTUH_!*>8ks1#>C`YICHD3PTjBS?|S|B zRwq?ejqlpCf5+U8soAPpahU1K=2g|oC#|lkk!w%b-xXnc@tnV%ts_Na>`WBDY z)0bL(v&ERjehX{&ALX!pI$-gV#mGOF^gi5R)fS8U>Sf2QhWCNRCG|YE?HY@<7MEMV zzR2QY3ku7dwm&4a{JGMWS(~F@TD{IHjv`tD|WfQR3hyHCq5453}c8khmi{_ls zNA0K{lIpW+1<;5<<2NigK9;ihcd(RddRrH;0^xo$KD+m!>E6Al`k84H#O@iRTPC00 z7qsb~>Pa-oUBycG!?!4hx}V$`%4B_2?S9kyyihA|-=hzF{o6Z#Z9nks?}t7*I@euy z&yT-un3?Fc*8F!7uU@bF=7Aq}zPI{$)lDtTt~t8#*<&wHs&2~rzs&C*?Cp2c_G&*> zH|53VYkk$R{EzG7BbJxDTzu8j_s%`@i#5{yqj#L?^VGJ3FXp!WZ}PQ0YNH!Yhqn&t z^I)y>XK?=6`aJo}R{r+8 zEaabfJe0})g$dJYcd#B@bzynKbymmka@FDwZr5^u)_vvETYA_17*E&J!R?hUvGva^ zAKhZpAIZB_o?$wffZaU#&f-_`1-MVTXu!T zCJX!vUYTI}Vhen@ym+I(vBT(y$U)$Qo=44-TE+{}>$Bh=3 zS>V5ULf7#|e~J1`&gElG+i08Xg4HjJ2 z6kO~4SThm4EU5zAH#-&_TU_5(TlhWHMDViY3S4U~Znn^|#<-VX*OpvnZ_pIr*xG8L zV{J`6eS!N>Jo?CS)56QrE5MlioJIdJ$MYMX-6NO?UY1IMa1M_@vd|A#t(}>hdeB<8 zzS!#c%*0)D^v?~J>4`gr&YzvQytFf$YIqMG={2hJRsSNUS8Td!WU|=vdLuqS6W6-_Kw7>L$ z(jS`2Air%JhEVBeBtpLz<4PTil>MQfER$8Ov~~E6PRAmJL4GcScZ>MVP{$&LL4GcS zcM3LI+?2>5KbK*vcyR?>0aw5ka0OfeSHKl;1W}F;aXK`MLYScOVAix0JU1 zAU~JEcOVAueNfsMTme_W6*ylN z;5nM#+3`Dp6t6=*zAdMa4})=|6bAXZ44(I4;1g09R2#coj&~+?-n){ax%wU!gI11;h8zYASahWz8GQM z2!otl20l*={8&t@((ytu@MAGX>3E?S_^}wHbi7au{8)@pI$kJ7@NALqykNXActJ6! zWBb8&Ox#%zXxeUgI#h^cc(#9Y^mmz=Nv32?F zckKHhKbN6?hK{YvJN7XK`MC`Bmvn4h{?CONgZx|u`sn-MJ^mPj{7lB!d_A6yPGZsD z6l0N}$qG8b;645n2D;`l&`AvX=3@InelA1(aqI_uj4=lJxeS{1;tIF|u7E4x3gjxl za~t=z%@*MqF7j+mPVPMlpC`t0`a&4DTBI=8hurI=n4@t&o=P>dAsS?UYL;CYeK=5@%)J+AP1VlYihuKlS_S} z7%A^3m-<36Qha);FBBuirI=mP zek#H!^@U;tKNVq=`a&^+pNcR_eW4h^PemA|zEF(dry`6}UnoY3*D3XdVg#>a*Os=v zfKp#5M(`mKMyW3pBlwR9qtq9Q5xhZ!QR)lDNbv@xzEF&m=XUlr_a4QzueaE0k-{K9 zmtm`TNmF3Kr>CWRmMh>2xB_Qi0iH#8KAW=$&n1!PtWsYn#&Y^XF~WT=vLEE+-VgD4 zVx)MsQeP-W@ND{CtR7ZMeW4h^vsuG!&!nZkP>kT&B8*aBC`RyX5k{#m6eDE}tkf5Z zK^^OxDfNY7q>O=;`a&^MJR7;W=OEiIMv7-E^@U=jj8B#NLNQXtr%HXH7%AgZrM^&% zlyRw2UnoY(m{F-O6k|Dkp%^Kit<)Ea5&ACed}+J3yDv0>yj&;>;L}Gs7s}rHe!2o> I3XF9A27q0mlK=n! literal 0 HcmV?d00001 diff --git a/ThirdParty/Ert/test-data/local/util/latex/report_OK.tex b/ThirdParty/Ert/test-data/local/util/latex/report_OK.tex index 21c215939b..7c17203c07 100644 --- a/ThirdParty/Ert/test-data/local/util/latex/report_OK.tex +++ b/ThirdParty/Ert/test-data/local/util/latex/report_OK.tex @@ -1,7 +1,7 @@ \documentclass[screen,8pt]{beamer} \usepackage[T1]{fontenc} \usepackage[latin1]{inputenc} -\usetheme{statoil} +\usetheme{equinor} \usepackage{amsmath,amssymb,amsfonts} \usepackage{graphicx} \usepackage[tight]{subfigure} diff --git a/ThirdParty/Ert/test-data/local/util/latex/report_error.tex b/ThirdParty/Ert/test-data/local/util/latex/report_error.tex index 1a51a6bc7f..d09d5c3835 100644 --- a/ThirdParty/Ert/test-data/local/util/latex/report_error.tex +++ b/ThirdParty/Ert/test-data/local/util/latex/report_error.tex @@ -1,7 +1,7 @@ \documentclass[screen,8pt]{beamer} \usepackage[T1]{fontenc} \usepackage[latin1]{inputenc} -\usetheme{statoil} +\usetheme{equinor} \usepackage{amsmath,amssymb,amsfonts} \usepackage{graphicx} \usepackage[tight]{subfigure} From abe292024ccd1b3a778f5faae7c216c556c6afc9 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 9 May 2019 08:30:03 +0200 Subject: [PATCH 027/396] #4266 Apply formatting --- .../FileInterface/RifReaderEclipseSummary.cpp | 42 +++++++------------ 1 file changed, 14 insertions(+), 28 deletions(-) diff --git a/ApplicationCode/FileInterface/RifReaderEclipseSummary.cpp b/ApplicationCode/FileInterface/RifReaderEclipseSummary.cpp index b4cbe4780d..5c66ffcdc1 100644 --- a/ApplicationCode/FileInterface/RifReaderEclipseSummary.cpp +++ b/ApplicationCode/FileInterface/RifReaderEclipseSummary.cpp @@ -287,37 +287,31 @@ RifEclipseSummaryAddress addressFromErtSmSpecNode(const smspec_node_type* ertSum switch (smspec_node_get_var_type(ertSumVarNode)) { - case ECL_SMSPEC_AQUIFER_VAR: - { + case ECL_SMSPEC_AQUIFER_VAR: { sumCategory = RifEclipseSummaryAddress::SUMMARY_AQUIFER; aquiferNumber = smspec_node_get_num(ertSumVarNode); } break; - case ECL_SMSPEC_WELL_VAR: - { + case ECL_SMSPEC_WELL_VAR: { sumCategory = RifEclipseSummaryAddress::SUMMARY_WELL; wellName = wellNameFromNode(ertSumVarNode); } break; - case ECL_SMSPEC_REGION_VAR: - { + case ECL_SMSPEC_REGION_VAR: { sumCategory = RifEclipseSummaryAddress::SUMMARY_REGION; regionNumber = smspec_node_get_num(ertSumVarNode); } break; - case ECL_SMSPEC_FIELD_VAR: - { + case ECL_SMSPEC_FIELD_VAR: { sumCategory = RifEclipseSummaryAddress::SUMMARY_FIELD; } break; - case ECL_SMSPEC_GROUP_VAR: - { + case ECL_SMSPEC_GROUP_VAR: { sumCategory = RifEclipseSummaryAddress::SUMMARY_WELL_GROUP; wellGroupName = wellNameFromNode(ertSumVarNode); } break; - case ECL_SMSPEC_BLOCK_VAR: - { + case ECL_SMSPEC_BLOCK_VAR: { sumCategory = RifEclipseSummaryAddress::SUMMARY_BLOCK; const int* ijk = smspec_node_get_ijk(ertSumVarNode); @@ -326,8 +320,7 @@ RifEclipseSummaryAddress addressFromErtSmSpecNode(const smspec_node_type* ertSum cellK = ijk[2]; } break; - case ECL_SMSPEC_COMPLETION_VAR: - { + case ECL_SMSPEC_COMPLETION_VAR: { sumCategory = RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION; wellName = wellNameFromNode(ertSumVarNode); const int* ijk = smspec_node_get_ijk(ertSumVarNode); @@ -336,8 +329,7 @@ RifEclipseSummaryAddress addressFromErtSmSpecNode(const smspec_node_type* ertSum cellK = ijk[2]; } break; - case ECL_SMSPEC_LOCAL_BLOCK_VAR: - { + case ECL_SMSPEC_LOCAL_BLOCK_VAR: { sumCategory = RifEclipseSummaryAddress::SUMMARY_BLOCK_LGR; lgrName = lgrNameFromNode(ertSumVarNode); const int* ijk = smspec_node_get_lgr_ijk(ertSumVarNode); @@ -346,8 +338,7 @@ RifEclipseSummaryAddress addressFromErtSmSpecNode(const smspec_node_type* ertSum cellK = ijk[2]; } break; - case ECL_SMSPEC_LOCAL_COMPLETION_VAR: - { + case ECL_SMSPEC_LOCAL_COMPLETION_VAR: { sumCategory = RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION_LGR; wellName = wellNameFromNode(ertSumVarNode); lgrName = lgrNameFromNode(ertSumVarNode); @@ -357,34 +348,29 @@ RifEclipseSummaryAddress addressFromErtSmSpecNode(const smspec_node_type* ertSum cellK = ijk[2]; } break; - case ECL_SMSPEC_LOCAL_WELL_VAR: - { + case ECL_SMSPEC_LOCAL_WELL_VAR: { sumCategory = RifEclipseSummaryAddress::SUMMARY_WELL_LGR; wellName = wellNameFromNode(ertSumVarNode); lgrName = lgrNameFromNode(ertSumVarNode); } break; - case ECL_SMSPEC_NETWORK_VAR: - { + case ECL_SMSPEC_NETWORK_VAR: { sumCategory = RifEclipseSummaryAddress::SUMMARY_NETWORK; } break; - case ECL_SMSPEC_REGION_2_REGION_VAR: - { + case ECL_SMSPEC_REGION_2_REGION_VAR: { sumCategory = RifEclipseSummaryAddress::SUMMARY_REGION_2_REGION; regionNumber = smspec_node_get_R1(ertSumVarNode); regionNumber2 = smspec_node_get_R2(ertSumVarNode); } break; - case ECL_SMSPEC_SEGMENT_VAR: - { + case ECL_SMSPEC_SEGMENT_VAR: { sumCategory = RifEclipseSummaryAddress::SUMMARY_WELL_SEGMENT; wellName = wellNameFromNode(ertSumVarNode); wellSegmentNumber = smspec_node_get_num(ertSumVarNode); } break; - case ECL_SMSPEC_MISC_VAR: - { + case ECL_SMSPEC_MISC_VAR: { sumCategory = RifEclipseSummaryAddress::SUMMARY_MISC; } break; From 1ac2429f628f1f18bd953c25a7b5e06599503f91 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 9 May 2019 08:35:12 +0200 Subject: [PATCH 028/396] #4266 Updates related to libecl API changes --- .../FileInterface/RifReaderEclipseSummary.cpp | 102 +++++++++--------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/ApplicationCode/FileInterface/RifReaderEclipseSummary.cpp b/ApplicationCode/FileInterface/RifReaderEclipseSummary.cpp index 5c66ffcdc1..78bacce575 100644 --- a/ApplicationCode/FileInterface/RifReaderEclipseSummary.cpp +++ b/ApplicationCode/FileInterface/RifReaderEclipseSummary.cpp @@ -17,10 +17,8 @@ ///////////////////////////////////////////////////////////////////////////////// #include "RifReaderEclipseSummary.h" - #include "RiaFilePathTools.h" #include "RiaStringEncodingTools.h" - #include "RifEclipseSummaryTools.h" #include "RifReaderEclipseOutput.h" @@ -36,11 +34,8 @@ #include "ert/ecl/ecl_kw.h" #include "ert/ecl/ecl_kw_magic.h" #include "ert/ecl/ecl_sum.h" -#include "ert/ecl/smspec_node.h" +#include "ert/ecl/smspec_node.hpp" -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- std::vector getTimeSteps(ecl_sum_type* ecl_sum) { std::vector timeSteps; @@ -246,7 +241,7 @@ std::string stringFromPointer(const char* pointerToChar) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::string wellNameFromNode(const smspec_node_type* ertSumVarNode) +std::string wellNameFromNode(const ecl::smspec_node* ertSumVarNode) { return stringFromPointer(smspec_node_get_wgname(ertSumVarNode)); } @@ -254,7 +249,7 @@ std::string wellNameFromNode(const smspec_node_type* ertSumVarNode) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::string lgrNameFromNode(const smspec_node_type* ertSumVarNode) +std::string lgrNameFromNode(const ecl::smspec_node* ertSumVarNode) { return stringFromPointer(smspec_node_get_lgr_name(ertSumVarNode)); } @@ -262,9 +257,9 @@ std::string lgrNameFromNode(const smspec_node_type* ertSumVarNode) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RifEclipseSummaryAddress addressFromErtSmSpecNode(const smspec_node_type* ertSumVarNode) +RifEclipseSummaryAddress addressFromErtSmSpecNode(const ecl::smspec_node& ertSumVarNode) { - if (smspec_node_get_var_type(ertSumVarNode) == ECL_SMSPEC_INVALID_VAR) + if (ertSumVarNode.get_var_type() == ECL_SMSPEC_INVALID_VAR) { return RifEclipseSummaryAddress(); } @@ -283,23 +278,23 @@ RifEclipseSummaryAddress addressFromErtSmSpecNode(const smspec_node_type* ertSum int aquiferNumber(-1); bool isErrorResult(false); - quantityName = smspec_node_get_keyword(ertSumVarNode); + quantityName = stringFromPointer(ertSumVarNode.get_keyword()); - switch (smspec_node_get_var_type(ertSumVarNode)) + switch (ertSumVarNode.get_var_type()) { case ECL_SMSPEC_AQUIFER_VAR: { sumCategory = RifEclipseSummaryAddress::SUMMARY_AQUIFER; - aquiferNumber = smspec_node_get_num(ertSumVarNode); + aquiferNumber = ertSumVarNode.get_num(); } break; case ECL_SMSPEC_WELL_VAR: { sumCategory = RifEclipseSummaryAddress::SUMMARY_WELL; - wellName = wellNameFromNode(ertSumVarNode); + wellName = stringFromPointer(ertSumVarNode.get_wgname()); } break; case ECL_SMSPEC_REGION_VAR: { sumCategory = RifEclipseSummaryAddress::SUMMARY_REGION; - regionNumber = smspec_node_get_num(ertSumVarNode); + regionNumber = ertSumVarNode.get_num(); } break; case ECL_SMSPEC_FIELD_VAR: { @@ -308,50 +303,53 @@ RifEclipseSummaryAddress addressFromErtSmSpecNode(const smspec_node_type* ertSum break; case ECL_SMSPEC_GROUP_VAR: { sumCategory = RifEclipseSummaryAddress::SUMMARY_WELL_GROUP; - wellGroupName = wellNameFromNode(ertSumVarNode); + wellGroupName = stringFromPointer(ertSumVarNode.get_wgname()); } break; case ECL_SMSPEC_BLOCK_VAR: { sumCategory = RifEclipseSummaryAddress::SUMMARY_BLOCK; - const int* ijk = smspec_node_get_ijk(ertSumVarNode); - cellI = ijk[0]; - cellJ = ijk[1]; - cellK = ijk[2]; + auto ijk = ertSumVarNode.get_ijk(); + cellI = ijk[0]; + cellJ = ijk[1]; + cellK = ijk[2]; } break; case ECL_SMSPEC_COMPLETION_VAR: { - sumCategory = RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION; - wellName = wellNameFromNode(ertSumVarNode); - const int* ijk = smspec_node_get_ijk(ertSumVarNode); - cellI = ijk[0]; - cellJ = ijk[1]; - cellK = ijk[2]; + sumCategory = RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION; + wellName = stringFromPointer(ertSumVarNode.get_wgname()); + + auto ijk = ertSumVarNode.get_ijk(); + cellI = ijk[0]; + cellJ = ijk[1]; + cellK = ijk[2]; } break; case ECL_SMSPEC_LOCAL_BLOCK_VAR: { - sumCategory = RifEclipseSummaryAddress::SUMMARY_BLOCK_LGR; - lgrName = lgrNameFromNode(ertSumVarNode); - const int* ijk = smspec_node_get_lgr_ijk(ertSumVarNode); - cellI = ijk[0]; - cellJ = ijk[1]; - cellK = ijk[2]; + sumCategory = RifEclipseSummaryAddress::SUMMARY_BLOCK_LGR; + lgrName = stringFromPointer(ertSumVarNode.get_lgr_name()); + + auto ijk = ertSumVarNode.get_lgr_ijk(); + cellI = ijk[0]; + cellJ = ijk[1]; + cellK = ijk[2]; } break; case ECL_SMSPEC_LOCAL_COMPLETION_VAR: { - sumCategory = RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION_LGR; - wellName = wellNameFromNode(ertSumVarNode); - lgrName = lgrNameFromNode(ertSumVarNode); - const int* ijk = smspec_node_get_lgr_ijk(ertSumVarNode); - cellI = ijk[0]; - cellJ = ijk[1]; - cellK = ijk[2]; + sumCategory = RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION_LGR; + wellName = stringFromPointer(ertSumVarNode.get_wgname()); + lgrName = stringFromPointer(ertSumVarNode.get_lgr_name()); + + auto ijk = ertSumVarNode.get_lgr_ijk(); + cellI = ijk[0]; + cellJ = ijk[1]; + cellK = ijk[2]; } break; case ECL_SMSPEC_LOCAL_WELL_VAR: { sumCategory = RifEclipseSummaryAddress::SUMMARY_WELL_LGR; - wellName = wellNameFromNode(ertSumVarNode); - lgrName = lgrNameFromNode(ertSumVarNode); + wellName = stringFromPointer(ertSumVarNode.get_wgname()); + lgrName = stringFromPointer(ertSumVarNode.get_lgr_name()); } break; case ECL_SMSPEC_NETWORK_VAR: { @@ -360,14 +358,14 @@ RifEclipseSummaryAddress addressFromErtSmSpecNode(const smspec_node_type* ertSum break; case ECL_SMSPEC_REGION_2_REGION_VAR: { sumCategory = RifEclipseSummaryAddress::SUMMARY_REGION_2_REGION; - regionNumber = smspec_node_get_R1(ertSumVarNode); - regionNumber2 = smspec_node_get_R2(ertSumVarNode); + regionNumber = ertSumVarNode.get_R1(); + regionNumber2 = ertSumVarNode.get_R2(); } break; case ECL_SMSPEC_SEGMENT_VAR: { sumCategory = RifEclipseSummaryAddress::SUMMARY_WELL_SEGMENT; - wellName = wellNameFromNode(ertSumVarNode); - wellSegmentNumber = smspec_node_get_num(ertSumVarNode); + wellName = stringFromPointer(ertSumVarNode.get_wgname()); + wellSegmentNumber = ertSumVarNode.get_num(); } break; case ECL_SMSPEC_MISC_VAR: { @@ -415,8 +413,8 @@ bool RifReaderEclipseSummary::values(const RifEclipseSummaryAddress& resultAddre } else if (m_ecl_SmSpec) { - const smspec_node_type* ertSumVarNode = ecl_smspec_iget_node(m_ecl_SmSpec, variableIndex); - int paramsIndex = smspec_node_get_params_index(ertSumVarNode); + const ecl::smspec_node& ertSumVarNode = ecl_smspec_iget_node_w_node_index(m_ecl_SmSpec, variableIndex); + int paramsIndex = ertSumVarNode.get_params_index(); double_vector_type* dataValues = ecl_sum_alloc_data_vector(m_ecl_sum, paramsIndex, false); @@ -483,7 +481,7 @@ void RifReaderEclipseSummary::buildMetaData() int varCount = ecl_smspec_num_nodes(m_ecl_SmSpec); for (int i = 0; i < varCount; i++) { - const smspec_node_type* ertSumVarNode = ecl_smspec_iget_node(m_ecl_SmSpec, i); + const ecl::smspec_node& ertSumVarNode = ecl_smspec_iget_node_w_node_index(m_ecl_SmSpec, i); RifEclipseSummaryAddress addr = addressFromErtSmSpecNode(ertSumVarNode); m_allResultAddresses.insert(addr); m_resultAddressToErtNodeIdx[addr] = i; @@ -529,8 +527,8 @@ std::string RifReaderEclipseSummary::unitName(const RifEclipseSummaryAddress& re if (variableIndex < 0) return ""; - const smspec_node_type* ertSumVarNode = ecl_smspec_iget_node(m_ecl_SmSpec, variableIndex); - return smspec_node_get_unit(ertSumVarNode); + const ecl::smspec_node& ertSumVarNode = ecl_smspec_iget_node_w_node_index(m_ecl_SmSpec, variableIndex); + return ertSumVarNode.get_unit(); } //-------------------------------------------------------------------------------------------------- @@ -576,6 +574,7 @@ std::set RifReaderEclipseSummary::ValuesC //-------------------------------------------------------------------------------------------------- RifReaderEclipseSummary::ValuesCache::ValuesCache() { + // Register instance m_instances.insert(this); } @@ -584,6 +583,7 @@ RifReaderEclipseSummary::ValuesCache::ValuesCache() //-------------------------------------------------------------------------------------------------- RifReaderEclipseSummary::ValuesCache::~ValuesCache() { + // Deregister instance m_instances.erase(this); } @@ -631,7 +631,7 @@ void RifReaderEclipseSummary::ValuesCache::purge() //-------------------------------------------------------------------------------------------------- void RifReaderEclipseSummary::ValuesCache::purgeData() { - for (const auto& purgeAddr : m_purgeList) + for (const auto purgeAddr : m_purgeList) { m_cachedValues.erase(purgeAddr); } From 96a7f02abec499005dfebbf85c31aa9643eb40cf Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 1 Apr 2019 11:11:30 +0200 Subject: [PATCH 029/396] #4266 : flow diagnostics: Update related to API changes --- ApplicationCode/ReservoirDataModel/RigFlowDiagInterfaceTools.h | 2 +- .../opm/utility/ECLFluxCalc.cpp | 3 ++- .../opm/utility/ECLFluxCalc.hpp | 3 ++- .../opm-flowdiagnostics-applications/opm/utility/ECLGraph.cpp | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/ApplicationCode/ReservoirDataModel/RigFlowDiagInterfaceTools.h b/ApplicationCode/ReservoirDataModel/RigFlowDiagInterfaceTools.h index cb73761634..add3906ac9 100644 --- a/ApplicationCode/ReservoirDataModel/RigFlowDiagInterfaceTools.h +++ b/ApplicationCode/ReservoirDataModel/RigFlowDiagInterfaceTools.h @@ -110,7 +110,7 @@ namespace RigFlowDiagInterfaceTools { { auto satfunc = Opm::ECLSaturationFunc(G, init); - Opm::ECLFluxCalc calc(G, init, 9.80665); + Opm::ECLFluxCalc calc(G, init, 9.80665, false); auto getFlux = [&calc, &rstrt] (const Opm::ECLPhaseIndex p) diff --git a/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLFluxCalc.cpp b/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLFluxCalc.cpp index 5204570bf9..f0fd31c91f 100644 --- a/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLFluxCalc.cpp +++ b/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLFluxCalc.cpp @@ -185,7 +185,8 @@ namespace Opm ECLFluxCalc::ECLFluxCalc(const ECLGraph& graph, const ECLInitFileData& init, - const double grav) + const double grav, + const bool /* useEPS */) : graph_(graph) , satfunc_(graph, init) , rmap_(pvtnumVector(graph, init)) diff --git a/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLFluxCalc.hpp b/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLFluxCalc.hpp index 6d49425473..d9e666ea3e 100644 --- a/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLFluxCalc.hpp +++ b/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLFluxCalc.hpp @@ -56,7 +56,8 @@ namespace Opm /// result set. ECLFluxCalc(const ECLGraph& graph, const ECLInitFileData& init, - const double grav); + const double grav, + const bool useEPS); /// Retrive phase flux on all connections defined by \code /// graph.neighbours() \endcode. diff --git a/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLGraph.cpp b/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLGraph.cpp index 32b6739d32..528d977441 100644 --- a/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLGraph.cpp +++ b/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLGraph.cpp @@ -685,7 +685,7 @@ ECL::loadNNC(const ecl_grid_type* G, auto nncData = std::vector{}; - const auto numNNC = make_szt(ecl_nnc_export_get_size(G)); + const auto numNNC = make_szt(ecl_nnc_export_get_size(G, init)); if (numNNC > 0) { nncData.resize(numNNC); From a31d8cbea6290252d6175fd79c4ec38d4caf667d Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 9 May 2019 08:37:31 +0200 Subject: [PATCH 030/396] #4266 : libecl : Fix several crash issues --- ThirdParty/Ert/lib/ecl/ecl_smspec.cpp | 15 +++++++++++---- ThirdParty/Ert/lib/ecl/smspec_node.cpp | 10 +++++----- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/ThirdParty/Ert/lib/ecl/ecl_smspec.cpp b/ThirdParty/Ert/lib/ecl/ecl_smspec.cpp index ea0a095368..03b2536fb2 100644 --- a/ThirdParty/Ert/lib/ecl/ecl_smspec.cpp +++ b/ThirdParty/Ert/lib/ecl/ecl_smspec.cpp @@ -232,6 +232,8 @@ static const char* smspec_required_keywords[] = { namespace { const ecl::smspec_node * ecl_smspec_get_var_node( const node_map& mp, const char * var) { + if (!var) return nullptr; + const auto it = mp.find(var); if (it == mp.end()) return nullptr; @@ -699,10 +701,15 @@ static void ecl_smspec_install_special_keys( ecl_smspec_type * ecl_smspec , cons ecl_smspec_get_well_var_index( smspec , well_name , var ); */ - const char * well = smspec_node_get_wgname( &smspec_node ); - const char * group = well; - const int num = smspec_node_get_num(&smspec_node); - const char * keyword = smspec_node_get_keyword(&smspec_node); + std::string well; + if (smspec_node_get_wgname(&smspec_node)) well = smspec_node_get_wgname(&smspec_node); + + std::string group = well; + const int num = smspec_node_get_num(&smspec_node); + + std::string keyword; + if (smspec_node_get_keyword(&smspec_node)) keyword = smspec_node_get_keyword(&smspec_node); + ecl_smspec_var_type var_type = smspec_node_get_var_type(&smspec_node ); switch(var_type) { diff --git a/ThirdParty/Ert/lib/ecl/smspec_node.cpp b/ThirdParty/Ert/lib/ecl/smspec_node.cpp index ba4e9bfdae..a1c98178fb 100644 --- a/ThirdParty/Ert/lib/ecl/smspec_node.cpp +++ b/ThirdParty/Ert/lib/ecl/smspec_node.cpp @@ -329,7 +329,7 @@ std::string smspec_alloc_completion_ijk_key( const char * join_string , const st join_string , i , j , k ); else - return NULL; + return ""; } @@ -343,7 +343,7 @@ std::string smspec_alloc_completion_num_key( const char * join_string , const st join_string , num ); else - return NULL; + return ""; } /* @@ -406,7 +406,7 @@ std::string smspec_alloc_segment_key( const char * join_string , const std::stri join_string , num ); else - return NULL; + return ""; } @@ -419,7 +419,7 @@ std::string smspec_alloc_local_well_key( const char * join_string , const std::s join_string , wgname.c_str()); else - return NULL; + return ""; } std::string smspec_alloc_local_completion_key( const char * join_string, const std::string& keyword , const std::string& lgr_name , const std::string& wgname , int i , int j , int k) { @@ -433,7 +433,7 @@ std::string smspec_alloc_local_completion_key( const char * join_string, const s join_string , i,j,k); else - return NULL; + return ""; } /*****************************************************************/ From bddbbebdccd0997156bb16ec9f1172308cae8bba Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 9 May 2019 09:24:54 +0200 Subject: [PATCH 031/396] #4266 : libecl : Update patch file related to install --- patches/install-ert.patch | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/patches/install-ert.patch b/patches/install-ert.patch index c874f27eab..d794f8e25f 100644 --- a/patches/install-ert.patch +++ b/patches/install-ert.patch @@ -1,7 +1,7 @@ -From 57a5f7fc667d42a5405021c975dabc2db53079a4 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Jacob=20St=C3=B8ren?= -Date: Thu, 26 Oct 2017 17:16:42 +0200 -Subject: [PATCH] #2011 libecl: Add INSTALL_ERT to control install targets +From cff955fb7f4c0f87ce4164b58a5fd2359f1ee9d7 Mon Sep 17 00:00:00 2001 +From: Magne Sjaastad +Date: Thu, 9 May 2019 09:19:18 +0200 +Subject: [PATCH] tmp --- ThirdParty/Ert/CMakeLists.txt | 5 ++++- @@ -9,10 +9,10 @@ Subject: [PATCH] #2011 libecl: Add INSTALL_ERT to control install targets 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/ThirdParty/Ert/CMakeLists.txt b/ThirdParty/Ert/CMakeLists.txt -index ffb2de0f9..73fb3b30d 100644 +index 36417d18e..c8050a1ca 100644 --- a/ThirdParty/Ert/CMakeLists.txt +++ b/ThirdParty/Ert/CMakeLists.txt -@@ -363,6 +363,9 @@ if (BUILD_PYTHON) +@@ -346,6 +346,9 @@ if (ENABLE_PYTHON) endif() endif() @@ -24,10 +24,10 @@ index ffb2de0f9..73fb3b30d 100644 export(TARGETS ecl FILE eclConfig.cmake) export(PACKAGE ecl) diff --git a/ThirdParty/Ert/lib/CMakeLists.txt b/ThirdParty/Ert/lib/CMakeLists.txt -index 477f95530..2b91ee17f 100644 +index 079eb127d..ddf3e7821 100644 --- a/ThirdParty/Ert/lib/CMakeLists.txt +++ b/ThirdParty/Ert/lib/CMakeLists.txt -@@ -220,7 +220,7 @@ endif () +@@ -200,7 +200,7 @@ endif () set_target_properties(ecl PROPERTIES VERSION ${ECL_VERSION_MAJOR}.${ECL_VERSION_MINOR} SOVERSION ${ECL_VERSION_MAJOR}) @@ -36,14 +36,14 @@ index 477f95530..2b91ee17f 100644 install(TARGETS ecl EXPORT ecl-config ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} -@@ -245,6 +245,7 @@ if (ERT_BUILD_CXX) - PATTERN *.hpp +@@ -212,6 +212,7 @@ install(DIRECTORY include/ + install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/include/ + DESTINATION include ) - endif () +endif() if (NOT BUILD_TESTS) return () -- -2.16.2.windows.1 +2.21.0.windows.1 From 6f78404f922e3056c3b4e6942ece2e78701e3431 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 9 May 2019 09:25:31 +0200 Subject: [PATCH 032/396] #4266 : libecl : Applied patch related to install --- ThirdParty/Ert/CMakeLists.txt | 5 ++++- ThirdParty/Ert/lib/CMakeLists.txt | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/ThirdParty/Ert/CMakeLists.txt b/ThirdParty/Ert/CMakeLists.txt index 36417d18e7..c8050a1cae 100644 --- a/ThirdParty/Ert/CMakeLists.txt +++ b/ThirdParty/Ert/CMakeLists.txt @@ -346,6 +346,9 @@ if (ENABLE_PYTHON) endif() endif() -install(EXPORT ecl-config DESTINATION share/cmake/ecl) +if (INSTALL_ERT) + install(EXPORT ecl-config DESTINATION share/cmake/ecl) +endif() + export(TARGETS ecl FILE eclConfig.cmake) export(PACKAGE ecl) diff --git a/ThirdParty/Ert/lib/CMakeLists.txt b/ThirdParty/Ert/lib/CMakeLists.txt index 079eb127de..ddf3e78218 100644 --- a/ThirdParty/Ert/lib/CMakeLists.txt +++ b/ThirdParty/Ert/lib/CMakeLists.txt @@ -200,7 +200,7 @@ endif () set_target_properties(ecl PROPERTIES VERSION ${ECL_VERSION_MAJOR}.${ECL_VERSION_MINOR} SOVERSION ${ECL_VERSION_MAJOR}) - +if (INSTALL_ERT) install(TARGETS ecl EXPORT ecl-config ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} @@ -212,6 +212,7 @@ install(DIRECTORY include/ install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/include/ DESTINATION include ) +endif() if (NOT BUILD_TESTS) return () From e8c214a7e912efa0453deee207de178cb69b97be Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 9 May 2019 09:26:31 +0200 Subject: [PATCH 033/396] #4266 : libecl : Applied patch to avoid recompile at each commit --- ThirdParty/Ert/lib/CMakeLists.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ThirdParty/Ert/lib/CMakeLists.txt b/ThirdParty/Ert/lib/CMakeLists.txt index ddf3e78218..e537313011 100644 --- a/ThirdParty/Ert/lib/CMakeLists.txt +++ b/ThirdParty/Ert/lib/CMakeLists.txt @@ -179,6 +179,13 @@ target_include_directories(ecl ${CMAKE_CURRENT_BINARY_DIR}/include ) + +if (NOT INSTALL_ERT) + # set git info to zero, to avoid recompile of libecl files at every commit + set(GIT_COMMIT 0) + set(GIT_COMMIT_SHORT 0) +endif() + target_compile_definitions(ecl PRIVATE -DGIT_COMMIT=${GIT_COMMIT} -DGIT_COMMIT_SHORT=${GIT_COMMIT_SHORT} From 2af89b57de76b7e543f3753c9fd6c758f0710977 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 9 May 2019 09:27:36 +0200 Subject: [PATCH 034/396] #4266 : libecl : Applied patch for geomech --- ThirdParty/Ert/lib/ecl/ecl_rsthead.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/ThirdParty/Ert/lib/ecl/ecl_rsthead.cpp b/ThirdParty/Ert/lib/ecl/ecl_rsthead.cpp index d7bbb00e38..d4d5b1bf34 100644 --- a/ThirdParty/Ert/lib/ecl/ecl_rsthead.cpp +++ b/ThirdParty/Ert/lib/ecl/ecl_rsthead.cpp @@ -88,7 +88,10 @@ ecl_rsthead_type * ecl_rsthead_alloc_from_kw( int report_step , const ecl_kw_typ // The only derived quantity rsthead->sim_time = rsthead_date( rsthead->day , rsthead->month , rsthead->year ); } - rsthead->sim_days = ecl_kw_iget_double( doubhead_kw , DOUBHEAD_DAYS_INDEX ); + + if (doubhead_kw) + rsthead->sim_days = ecl_kw_iget_double( doubhead_kw , DOUBHEAD_DAYS_INDEX ); + if (logihead_kw) rsthead->dualp = ecl_kw_iget_bool( logihead_kw , LOGIHEAD_DUALP_INDEX); @@ -109,12 +112,15 @@ ecl_rsthead_type * ecl_rsthead_alloc_from_kw( int report_step , const ecl_kw_typ ecl_rsthead_type * ecl_rsthead_alloc( const ecl_file_view_type * rst_view, int report_step) { const ecl_kw_type * intehead_kw = ecl_file_view_iget_named_kw( rst_view , INTEHEAD_KW , 0); - const ecl_kw_type * doubhead_kw = ecl_file_view_iget_named_kw( rst_view , DOUBHEAD_KW , 0); + const ecl_kw_type * doubhead_kw = NULL; const ecl_kw_type * logihead_kw = NULL; if (ecl_file_view_has_kw(rst_view, LOGIHEAD_KW)) logihead_kw = ecl_file_view_iget_named_kw( rst_view , LOGIHEAD_KW , 0); + if (ecl_file_view_has_kw(rst_view, DOUBHEAD_KW)) + doubhead_kw = ecl_file_view_iget_named_kw(rst_view, DOUBHEAD_KW, 0); + if (ecl_file_view_has_kw( rst_view , SEQNUM_KW)) { const ecl_kw_type * seqnum_kw = ecl_file_view_iget_named_kw( rst_view , SEQNUM_KW , 0); report_step = ecl_kw_iget_int( seqnum_kw , 0); From 819744a03bc20e12ee5a1c1d136979e6afaadb10 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 9 May 2019 10:06:27 +0200 Subject: [PATCH 035/396] #4266 : opm-flowdiagnostics : Update to 8bb60d6111063f2b7557502ecaa329a2d5c13b41 --- ResInsightVersion.cmake | 2 +- .../opm-flowdiagnostics/dune.module | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ResInsightVersion.cmake b/ResInsightVersion.cmake index 7dc2ef9fb1..8366e96b03 100644 --- a/ResInsightVersion.cmake +++ b/ResInsightVersion.cmake @@ -21,7 +21,7 @@ set(NRLIB_GITHUB_SHA "ba35d4359882f1c6f5e9dc30eb95fe52af50fd6f") set(ECL_GITHUB_SHA "7f93730c08a4d981a4b738b42146d099977572ce") # https://github.com/OPM/opm-flowdiagnostics -set(OPM_FLOWDIAGNOSTICS_SHA "f8af0914f8b1ddcda41f040f539c945a6057f5e4") +set(OPM_FLOWDIAGNOSTICS_SHA "8bb60d6111063f2b7557502ecaa329a2d5c13b41") # https://github.com/OPM/opm-flowdiagnostics-applications set(OPM_FLOWDIAGNOSTICS_APPLICATIONS_SHA "24ff768dc509b6c6bbd0121ef46a5932fae92961") diff --git a/ThirdParty/custom-opm-flowdiagnostics/opm-flowdiagnostics/dune.module b/ThirdParty/custom-opm-flowdiagnostics/opm-flowdiagnostics/dune.module index 18e86045a3..316e7f79b6 100644 --- a/ThirdParty/custom-opm-flowdiagnostics/opm-flowdiagnostics/dune.module +++ b/ThirdParty/custom-opm-flowdiagnostics/opm-flowdiagnostics/dune.module @@ -5,8 +5,8 @@ Module: opm-flowdiagnostics Description: Open Porous Media Initiative flow diagnostics -Version: 2018.10-pre -Label: 2018.10-pre +Version: 2019.10-pre +Label: 2019.10-pre Maintainer: opm@opm-project.org MaintainerName: OPM community Url: http://opm-project.org From 1d574fd8c74679ea25eb9b2f090bd85e88183f0c Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 9 May 2019 10:09:06 +0200 Subject: [PATCH 036/396] #4266 : opm-flowdiagnostics-applications : Update to f57942a8cdf57422fabf3a4423d02a3e46e0be4e --- ResInsightVersion.cmake | 2 +- .../opm-flowdiagnostics-applications/dune.module | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ResInsightVersion.cmake b/ResInsightVersion.cmake index 8366e96b03..e76f28ad96 100644 --- a/ResInsightVersion.cmake +++ b/ResInsightVersion.cmake @@ -24,7 +24,7 @@ set(ECL_GITHUB_SHA "7f93730c08a4d981a4b738b42146d099977572ce") set(OPM_FLOWDIAGNOSTICS_SHA "8bb60d6111063f2b7557502ecaa329a2d5c13b41") # https://github.com/OPM/opm-flowdiagnostics-applications -set(OPM_FLOWDIAGNOSTICS_APPLICATIONS_SHA "24ff768dc509b6c6bbd0121ef46a5932fae92961") +set(OPM_FLOWDIAGNOSTICS_APPLICATIONS_SHA "f57942a8cdf57422fabf3a4423d02a3e46e0be4e") # https://github.com/OPM/opm-parser/blob/master/opm/parser/eclipse/Units/Units.hpp # This file was moved from opm-core to opm-parser october 2016 diff --git a/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/dune.module b/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/dune.module index 1d257c47cc..bf777a86fe 100644 --- a/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/dune.module +++ b/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/dune.module @@ -5,8 +5,8 @@ Module: opm-flowdiagnostics-applications Description: flow diagnostics applications and examples -Version: 2018.10-pre -Label: 2018.10-pre +Version: 2019.10-pre +Label: 2019.10-pre Maintainer: bard.skaflestad@sintef.no MaintainerName: BÃ¥rd Skaflestad Url: http://opm-project.org From d3f0d0159adb9c90b201926f526a742e4b28affd Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 9 May 2019 10:10:17 +0200 Subject: [PATCH 037/396] #4266 : libecl : Update libecl sha reference --- ResInsightVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ResInsightVersion.cmake b/ResInsightVersion.cmake index e76f28ad96..fa44eb6d43 100644 --- a/ResInsightVersion.cmake +++ b/ResInsightVersion.cmake @@ -18,7 +18,7 @@ set(NRLIB_GITHUB_SHA "ba35d4359882f1c6f5e9dc30eb95fe52af50fd6f") # https://github.com/Statoil/libecl # Note: # Apply patches fix-synthetic-odb-cases.patch and install-ert.patch after update -set(ECL_GITHUB_SHA "7f93730c08a4d981a4b738b42146d099977572ce") +set(ECL_GITHUB_SHA "0e1e780fd6f18ce93119061e36a4fca9711bc020") # https://github.com/OPM/opm-flowdiagnostics set(OPM_FLOWDIAGNOSTICS_SHA "8bb60d6111063f2b7557502ecaa329a2d5c13b41") From ca42f9a4ad38460ee7db1249dc86721dc847332b Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 9 May 2019 13:37:54 +0200 Subject: [PATCH 038/396] Remove unused functions --- .../FileInterface/RifReaderEclipseSummary.cpp | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/ApplicationCode/FileInterface/RifReaderEclipseSummary.cpp b/ApplicationCode/FileInterface/RifReaderEclipseSummary.cpp index 78bacce575..85164e0610 100644 --- a/ApplicationCode/FileInterface/RifReaderEclipseSummary.cpp +++ b/ApplicationCode/FileInterface/RifReaderEclipseSummary.cpp @@ -238,22 +238,6 @@ std::string stringFromPointer(const char* pointerToChar) return myString; } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -std::string wellNameFromNode(const ecl::smspec_node* ertSumVarNode) -{ - return stringFromPointer(smspec_node_get_wgname(ertSumVarNode)); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -std::string lgrNameFromNode(const ecl::smspec_node* ertSumVarNode) -{ - return stringFromPointer(smspec_node_get_lgr_name(ertSumVarNode)); -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- From 6fbb45be8812ac0ac3a624219e7b909df9eb1fc5 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 9 May 2019 13:39:00 +0200 Subject: [PATCH 039/396] #4397 ssihub : Avoid progress info when typing username and password --- .../RiuWellImportWizard.cpp | 46 +++++++++++++++---- .../RiuWellImportWizard.h | 2 + 2 files changed, 38 insertions(+), 10 deletions(-) diff --git a/ApplicationCode/WellPathImportSsihub/RiuWellImportWizard.cpp b/ApplicationCode/WellPathImportSsihub/RiuWellImportWizard.cpp index c9fa8714a8..a7d9093b93 100644 --- a/ApplicationCode/WellPathImportSsihub/RiuWellImportWizard.cpp +++ b/ApplicationCode/WellPathImportSsihub/RiuWellImportWizard.cpp @@ -56,7 +56,7 @@ RiuWellImportWizard::RiuWellImportWizard(const QString& webServiceAddress, const m_destinationFolder = downloadFolder; m_webServiceAddress = webServiceAddress; - m_myProgressDialog = new QProgressDialog(this); + m_myProgressDialog = nullptr; m_firstTimeRequestingAuthentication = true; @@ -164,7 +164,7 @@ void RiuWellImportWizard::httpFinished() m_file = nullptr; } m_reply->deleteLater(); - m_myProgressDialog->hide(); + hideProgressDialog(); return; } @@ -228,11 +228,11 @@ void RiuWellImportWizard::httpFinished() } } - m_myProgressDialog->setLabelText(QString("Downloaded well path : %1").arg(wellPathName)); + progressDialog()->setLabelText(QString("Downloaded well path : %1").arg(wellPathName)); } - int newValue = m_myProgressDialog->maximum() - m_wellRequestQueue.size(); - m_myProgressDialog->setValue(newValue); + int newValue = progressDialog()->maximum() - m_wellRequestQueue.size(); + progressDialog()->setValue(newValue); } m_reply->deleteLater(); @@ -370,6 +370,32 @@ QString RiuWellImportWizard::getValue(const QString& key, const QString& stringC } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QProgressDialog* RiuWellImportWizard::progressDialog() +{ + if (!m_myProgressDialog) + { + m_myProgressDialog = new QProgressDialog(this); + } + + return m_myProgressDialog; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuWellImportWizard::hideProgressDialog() +{ + if (m_myProgressDialog) + { + m_myProgressDialog->hide(); + + QCoreApplication::processEvents(); + } +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -476,9 +502,9 @@ void RiuWellImportWizard::downloadWellPaths() m_currentDownloadState = DOWNLOAD_WELL_PATH; - m_myProgressDialog->setMaximum(m_wellRequestQueue.size()); - m_myProgressDialog->setValue(0); - m_myProgressDialog->show(); + progressDialog()->setMaximum(m_wellRequestQueue.size()); + progressDialog()->setValue(0); + progressDialog()->show(); checkDownloadQueueAndIssueRequests(); @@ -505,7 +531,7 @@ void RiuWellImportWizard::checkDownloadQueueAndIssueRequests() if (m_currentDownloadState == DOWNLOAD_WELLS) { - m_myProgressDialog->hide(); + hideProgressDialog(); // Update UI with downloaded wells @@ -538,7 +564,7 @@ void RiuWellImportWizard::checkDownloadQueueAndIssueRequests() m_currentDownloadState = DOWNLOAD_UNDEFINED; - m_myProgressDialog->hide(); + hideProgressDialog(); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/WellPathImportSsihub/RiuWellImportWizard.h b/ApplicationCode/WellPathImportSsihub/RiuWellImportWizard.h index fea1daff9f..9981bdf504 100644 --- a/ApplicationCode/WellPathImportSsihub/RiuWellImportWizard.h +++ b/ApplicationCode/WellPathImportSsihub/RiuWellImportWizard.h @@ -228,6 +228,8 @@ private: QString getValue(const QString& key, const QString& stringContent); + QProgressDialog* progressDialog(); + void hideProgressDialog(); private: QString m_webServiceAddress; From a113ca5ff5e0b9482a748df4e4375f7ab8e6c6d7 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 9 May 2019 13:43:18 +0200 Subject: [PATCH 040/396] #4397 ssihub : Avoid caching of data --- .../WellPathCommands/RicWellPathsImportSsihubFeature.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ApplicationCode/Commands/WellPathCommands/RicWellPathsImportSsihubFeature.cpp b/ApplicationCode/Commands/WellPathCommands/RicWellPathsImportSsihubFeature.cpp index fe26085444..aa11da2c5d 100644 --- a/ApplicationCode/Commands/WellPathCommands/RicWellPathsImportSsihubFeature.cpp +++ b/ApplicationCode/Commands/WellPathCommands/RicWellPathsImportSsihubFeature.cpp @@ -89,7 +89,7 @@ void RicWellPathsImportSsihubFeature::onActionTriggered(bool isChecked) QString ssihubPassword = "resinsight"; #else QString ssihubUsername = app->cacheDataObject("ssihub_username").toString(); - QString ssihubPassword = app->cacheDataObject("ssihub_password").toString(); + QString ssihubPassword; #endif wellImportwizard.setCredentials(ssihubUsername, ssihubPassword); } @@ -104,7 +104,6 @@ void RicWellPathsImportSsihubFeature::onActionTriggered(bool isChecked) } app->setCacheDataObject("ssihub_username", wellImportwizard.field("username")); - app->setCacheDataObject("ssihub_password", wellImportwizard.field("password")); } else { From 45c5a950a4ef3c110dd1c9dfb5105edc0210a3db Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 10 May 2019 09:10:28 +0200 Subject: [PATCH 041/396] #4266 : libecl : Update version number in generated so --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b68717c2ad..318aba08ed 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -470,7 +470,7 @@ if (RESINSIGHT_PRIVATE_INSTALL) set(ERT_SHARED_LIB_FILES ${CMAKE_BINARY_DIR}/ThirdParty/Ert/${CMAKE_INSTALL_LIBDIR}/libecl.so ${CMAKE_BINARY_DIR}/ThirdParty/Ert/${CMAKE_INSTALL_LIBDIR}/libecl.so.2 - ${CMAKE_BINARY_DIR}/ThirdParty/Ert/${CMAKE_INSTALL_LIBDIR}/libecl.so.2.3 + ${CMAKE_BINARY_DIR}/ThirdParty/Ert/${CMAKE_INSTALL_LIBDIR}/libecl.so.2.4 ) install(FILES ${ERT_SHARED_LIB_FILES} DESTINATION ${RESINSIGHT_INSTALL_FOLDER} ) From b824f1d75f5a5d9a0fe7702026febbffcce036cf Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Mon, 13 May 2019 13:47:03 +0200 Subject: [PATCH 042/396] #4407 Make sure we convert fontInScene from point size to enum value from old registry settings --- ApplicationCode/Application/RiaApplication.cpp | 2 +- ApplicationCode/Application/RiaFontCache.h | 3 ++- ApplicationCode/Application/RiaPreferences.cpp | 13 +++++++++++++ ApplicationCode/Application/RiaPreferences.h | 1 + .../RicEditPreferencesFeature.cpp | 1 + 5 files changed, 18 insertions(+), 2 deletions(-) diff --git a/ApplicationCode/Application/RiaApplication.cpp b/ApplicationCode/Application/RiaApplication.cpp index 027e7d4a8e..b1494ec9e1 100644 --- a/ApplicationCode/Application/RiaApplication.cpp +++ b/ApplicationCode/Application/RiaApplication.cpp @@ -1299,7 +1299,7 @@ void RiaApplication::initialize() { m_preferences = new RiaPreferences; caf::PdmSettings::readFieldsFromApplicationStore(m_preferences); - + m_preferences->initAfterReadRecursively(); applyPreferences(nullptr); // Start with a project diff --git a/ApplicationCode/Application/RiaFontCache.h b/ApplicationCode/Application/RiaFontCache.h index dbd0b7e5fe..fee3429ede 100644 --- a/ApplicationCode/Application/RiaFontCache.h +++ b/ApplicationCode/Application/RiaFontCache.h @@ -45,7 +45,8 @@ public: FONT_SIZE_14, FONT_SIZE_16, FONT_SIZE_24, - FONT_SIZE_32 + FONT_SIZE_32, + MAX_FONT_SIZE = FONT_SIZE_32 }; typedef caf::AppEnum FontSizeType; diff --git a/ApplicationCode/Application/RiaPreferences.cpp b/ApplicationCode/Application/RiaPreferences.cpp index 51048614f3..1e6d595aed 100644 --- a/ApplicationCode/Application/RiaPreferences.cpp +++ b/ApplicationCode/Application/RiaPreferences.cpp @@ -289,6 +289,19 @@ QList RiaPreferences::calculateValueOptions(const caf::P return options; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaPreferences::initAfterRead() +{ + // If the stored font size is larger than the maximum enum value, the stored font size is actually point size + int defaultSceneFontEnumValue = static_cast(defaultSceneFontSize.v()); + if (defaultSceneFontEnumValue > (int) RiaFontCache::MAX_FONT_SIZE) + { + defaultSceneFontSize = RiaFontCache::fontSizeEnumFromPointSize(defaultSceneFontEnumValue); + } +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/Application/RiaPreferences.h b/ApplicationCode/Application/RiaPreferences.h index 3c7fe59dea..36e5b10e6d 100644 --- a/ApplicationCode/Application/RiaPreferences.h +++ b/ApplicationCode/Application/RiaPreferences.h @@ -110,6 +110,7 @@ protected: void defineEditorAttribute(const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute) override; void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) override; QList calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool * useOptionsOnly) override; + void initAfterRead() override; private: caf::PdmChildField m_readerSettings; diff --git a/ApplicationCode/Commands/ApplicationCommands/RicEditPreferencesFeature.cpp b/ApplicationCode/Commands/ApplicationCommands/RicEditPreferencesFeature.cpp index e3639c0ddb..dc099761d4 100644 --- a/ApplicationCode/Commands/ApplicationCommands/RicEditPreferencesFeature.cpp +++ b/ApplicationCode/Commands/ApplicationCommands/RicEditPreferencesFeature.cpp @@ -63,6 +63,7 @@ void RicEditPreferencesFeature::onActionTriggered(bool isChecked) { // Read back currently stored values using QSettings caf::PdmSettings::readFieldsFromApplicationStore(app->preferences()); + app->preferences()->initAfterReadRecursively(); } } From c8dbba61df37f9c04c3dfb1489fe7ea1a4f0d505 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 14 May 2019 11:09:26 +0200 Subject: [PATCH 043/396] Update issue templates --- .github/ISSUE_TEMPLATE/bug_report.md | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index b1fd9845b5..29c9a309b7 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -8,20 +8,7 @@ assignees: '' --- **Describe the bug** -A clear and concise description of what the bug is. **To Reproduce** -Steps to reproduce the behavior: -1. Go to '...' -2. Click on '....' -3. Scroll down to '....' -4. See error - -**Expected behavior** -A clear and concise description of what you expected to happen. **Screenshots** -If applicable, add screenshots to help explain your problem. - -**Additional context** -Add any other context about the problem here. From 1a67773acebe07d7fda7f4ba62fe4d22a53fda27 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 15 May 2019 07:35:53 +0200 Subject: [PATCH 044/396] #4410 Dock Window State : Remove obsolete functions --- .../Application/RiaGuiApplication.cpp | 22 ------------------- .../Application/RiaGuiApplication.h | 3 --- .../UserInterface/RiuMainWindow.cpp | 2 +- .../UserInterface/RiuPlotMainWindow.cpp | 4 ++-- 4 files changed, 3 insertions(+), 28 deletions(-) diff --git a/ApplicationCode/Application/RiaGuiApplication.cpp b/ApplicationCode/Application/RiaGuiApplication.cpp index 7b3e1d9d58..eacbdff6a7 100644 --- a/ApplicationCode/Application/RiaGuiApplication.cpp +++ b/ApplicationCode/Application/RiaGuiApplication.cpp @@ -1172,28 +1172,6 @@ std::vector RiaGuiApplication::recentFileActions() const return m_recentFileActionProvider->actions(); } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiaGuiApplication::saveMainWinGeoAndDockToolBarLayout() -{ - if (isMain3dWindowVisible()) - { - m_mainWindow->saveWinGeoAndDockToolBarLayout(); - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiaGuiApplication::savePlotWinGeoAndDockToolBarLayout() -{ - if (isMainPlotWindowVisible()) - { - m_mainPlotWindow->saveWinGeoAndDockToolBarLayout(); - } -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/Application/RiaGuiApplication.h b/ApplicationCode/Application/RiaGuiApplication.h index 1824ac3183..d7ea79341d 100644 --- a/ApplicationCode/Application/RiaGuiApplication.h +++ b/ApplicationCode/Application/RiaGuiApplication.h @@ -119,9 +119,6 @@ public: std::vector recentFileActions() const; - void saveMainWinGeoAndDockToolBarLayout(); - void savePlotWinGeoAndDockToolBarLayout(); - static void clearAllSelections(); void applyGuiPreferences(const RiaPreferences* oldPreferences = nullptr); diff --git a/ApplicationCode/UserInterface/RiuMainWindow.cpp b/ApplicationCode/UserInterface/RiuMainWindow.cpp index 26d94e4cf8..470db90091 100644 --- a/ApplicationCode/UserInterface/RiuMainWindow.cpp +++ b/ApplicationCode/UserInterface/RiuMainWindow.cpp @@ -272,7 +272,7 @@ void RiuMainWindow::closeEvent(QCloseEvent* event) { RiaGuiApplication* app = RiaGuiApplication::instance(); - app->saveMainWinGeoAndDockToolBarLayout(); + this->saveWinGeoAndDockToolBarLayout(); if (app->isMainPlotWindowVisible()) { diff --git a/ApplicationCode/UserInterface/RiuPlotMainWindow.cpp b/ApplicationCode/UserInterface/RiuPlotMainWindow.cpp index 4e06f9b0e3..3a4e73c6e9 100644 --- a/ApplicationCode/UserInterface/RiuPlotMainWindow.cpp +++ b/ApplicationCode/UserInterface/RiuPlotMainWindow.cpp @@ -178,9 +178,9 @@ void RiuPlotMainWindow::cleanUpTemporaryWidgets() //-------------------------------------------------------------------------------------------------- void RiuPlotMainWindow::closeEvent(QCloseEvent* event) { - RiaGuiApplication* app = RiaGuiApplication::instance(); + this->saveWinGeoAndDockToolBarLayout(); - app->savePlotWinGeoAndDockToolBarLayout(); + RiaGuiApplication* app = RiaGuiApplication::instance(); if (app->isMain3dWindowVisible()) { From bf6b5652b3791b4444801b2613463ec00e13859b Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 15 May 2019 09:45:44 +0200 Subject: [PATCH 045/396] #4410 Dock Window State : Give dock widgets unique names --- ApplicationCode/UserInterface/RiuPlotMainWindow.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ApplicationCode/UserInterface/RiuPlotMainWindow.cpp b/ApplicationCode/UserInterface/RiuPlotMainWindow.cpp index 3a4e73c6e9..3653bb29f2 100644 --- a/ApplicationCode/UserInterface/RiuPlotMainWindow.cpp +++ b/ApplicationCode/UserInterface/RiuPlotMainWindow.cpp @@ -383,7 +383,7 @@ void RiuPlotMainWindow::createDockPanels() { { QDockWidget* dockWidget = new QDockWidget("Plot Project Tree", this); - dockWidget->setObjectName("dockWidget"); + dockWidget->setObjectName("plotProjectTreeDockWidget"); dockWidget->setAllowedAreas(Qt::AllDockWidgetAreas); m_projectTreeView = new caf::PdmUiTreeView(this); @@ -420,7 +420,7 @@ void RiuPlotMainWindow::createDockPanels() { QDockWidget* dockWidget = new QDockWidget("Property Editor", this); - dockWidget->setObjectName("dockWidget"); + dockWidget->setObjectName("plotPropertyEditorDockWidget"); dockWidget->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); m_pdmUiPropertyView = new caf::PdmUiPropertyView(dockWidget); From 11433241fdc0cbdfa5e9ad6c94e551e108381ed2 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 15 May 2019 10:31:56 +0200 Subject: [PATCH 046/396] #4410 Dock Window State : Remove obsolete code --- .../UserInterface/RiuMainWindow.cpp | 38 +++++-------------- 1 file changed, 9 insertions(+), 29 deletions(-) diff --git a/ApplicationCode/UserInterface/RiuMainWindow.cpp b/ApplicationCode/UserInterface/RiuMainWindow.cpp index 470db90091..73f113e19a 100644 --- a/ApplicationCode/UserInterface/RiuMainWindow.cpp +++ b/ApplicationCode/UserInterface/RiuMainWindow.cpp @@ -661,26 +661,6 @@ void RiuMainWindow::createToolBars() refreshDrawStyleActions(); } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -class RiuDockWidget : public QDockWidget -{ -public: - explicit RiuDockWidget(const QString& title, QWidget* parent = nullptr, Qt::WindowFlags flags = nullptr) - : QDockWidget(title, parent, flags) - { - } - - void closeEvent(QCloseEvent* event) override - { - // This event is called when the user clicks the "x" in upper right corner to close the dock widget - RiuDockWidgetTools::instance()->setDockWidgetVisibility(objectName(), false); - - QDockWidget::closeEvent(event); - } -}; - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -689,7 +669,7 @@ void RiuMainWindow::createDockPanels() auto dwt = RiuDockWidgetTools::instance(); { - QDockWidget* dockWidget = new RiuDockWidget("Project Tree", this); + QDockWidget* dockWidget = new QDockWidget("Project Tree", this); dockWidget->setObjectName(dwt->projectTreeName()); dockWidget->setAllowedAreas(Qt::AllDockWidgetAreas); @@ -731,7 +711,7 @@ void RiuMainWindow::createDockPanels() #endif { - QDockWidget* dockWidget = new RiuDockWidget("Property Editor", this); + QDockWidget* dockWidget = new QDockWidget("Property Editor", this); dockWidget->setObjectName(dwt->propertyEditorName()); dockWidget->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); @@ -742,7 +722,7 @@ void RiuMainWindow::createDockPanels() } { - QDockWidget* dockWidget = new RiuDockWidget("Result Info", this); + QDockWidget* dockWidget = new QDockWidget("Result Info", this); dockWidget->setObjectName(dwt->resultInfoName()); dockWidget->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea | Qt::BottomDockWidgetArea); m_resultInfoPanel = new RiuResultInfoPanel(dockWidget); @@ -752,7 +732,7 @@ void RiuMainWindow::createDockPanels() } { - QDockWidget* dockWidget = new RiuDockWidget("Process Monitor", this); + QDockWidget* dockWidget = new QDockWidget("Process Monitor", this); dockWidget->setObjectName(dwt->processMonitorName()); dockWidget->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea | Qt::BottomDockWidgetArea); m_processMonitor = new RiuProcessMonitor(dockWidget); @@ -763,7 +743,7 @@ void RiuMainWindow::createDockPanels() } { - QDockWidget* dockWidget = new RiuDockWidget("Result Plot", this); + QDockWidget* dockWidget = new QDockWidget("Result Plot", this); dockWidget->setObjectName(dwt->resultPlotName()); dockWidget->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea | Qt::BottomDockWidgetArea); m_resultQwtPlot = new RiuResultQwtPlot(dockWidget); @@ -775,7 +755,7 @@ void RiuMainWindow::createDockPanels() #ifdef USE_ODB_API { - QDockWidget* dockWidget = new RiuDockWidget("Mohr's Circle Plot", this); + QDockWidget* dockWidget = new QDockWidget("Mohr's Circle Plot", this); dockWidget->setObjectName(dwt->mohrsCirclePlotName()); dockWidget->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea | Qt::BottomDockWidgetArea); m_mohrsCirclePlot = new RiuMohrsCirclePlot(dockWidget); @@ -789,7 +769,7 @@ void RiuMainWindow::createDockPanels() #endif { - QDockWidget* dockWidget = new RiuDockWidget("Relative Permeability Plot", this); + QDockWidget* dockWidget = new QDockWidget("Relative Permeability Plot", this); dockWidget->setObjectName(dwt->relPermPlotName()); dockWidget->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea | Qt::BottomDockWidgetArea); m_relPermPlotPanel = new RiuRelativePermeabilityPlotPanel(dockWidget); @@ -800,7 +780,7 @@ void RiuMainWindow::createDockPanels() } { - QDockWidget* dockWidget = new RiuDockWidget("PVT Plot", this); + QDockWidget* dockWidget = new QDockWidget("PVT Plot", this); dockWidget->setObjectName(dwt->pvtPlotName()); dockWidget->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea | Qt::BottomDockWidgetArea); m_pvtPlotPanel = new RiuPvtPlotPanel(dockWidget); @@ -811,7 +791,7 @@ void RiuMainWindow::createDockPanels() } { - QDockWidget* dockWidget = new RiuDockWidget("Messages", this); + QDockWidget* dockWidget = new QDockWidget("Messages", this); dockWidget->setObjectName(dwt->messagesName()); m_messagePanel = new RiuMessagePanel(dockWidget); dockWidget->setWidget(m_messagePanel); From a68650ebf8e71a6b5b0d4cc6c2614093b10e36d4 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 15 May 2019 10:35:52 +0200 Subject: [PATCH 047/396] #4410 Dock Window State : Remove obsolete code --- ApplicationCode/Application/RiaApplication.h | 1 - ApplicationCode/Application/RiaGuiApplication.cpp | 10 ---------- ApplicationCode/Application/RiaGuiApplication.h | 1 - 3 files changed, 12 deletions(-) diff --git a/ApplicationCode/Application/RiaApplication.h b/ApplicationCode/Application/RiaApplication.h index db3abccbcf..227b0b55c6 100644 --- a/ApplicationCode/Application/RiaApplication.h +++ b/ApplicationCode/Application/RiaApplication.h @@ -183,7 +183,6 @@ public: protected: // Protected implementation specific overrides virtual void invokeProcessEvents(QEventLoop::ProcessEventsFlags flags = QEventLoop::AllEvents) = 0; - virtual void onChangedActiveReservoirView() {} virtual void onFileSuccessfullyLoaded(const QString& fileName, RiaDefines::ImportFileType fileType) {} virtual void onProjectBeingOpened() {} virtual void onProjectOpened() = 0; diff --git a/ApplicationCode/Application/RiaGuiApplication.cpp b/ApplicationCode/Application/RiaGuiApplication.cpp index eacbdff6a7..16097110a4 100644 --- a/ApplicationCode/Application/RiaGuiApplication.cpp +++ b/ApplicationCode/Application/RiaGuiApplication.cpp @@ -192,8 +192,6 @@ RiaGuiApplication::RiaGuiApplication(int& argc, char** argv) //-------------------------------------------------------------------------------------------------- RiaGuiApplication::~RiaGuiApplication() { - RiuDockWidgetTools::instance()->saveDockWidgetsState(); - deleteMainPlotWindow(); deleteMainWindow(); @@ -1220,14 +1218,6 @@ void RiaGuiApplication::invokeProcessEvents(QEventLoop::ProcessEventsFlags flags processEvents(flags); } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiaGuiApplication::onChangedActiveReservoirView() -{ - RiuDockWidgetTools::instance()->changeDockWidgetVisibilityBasedOnView(activeReservoirView()); -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/Application/RiaGuiApplication.h b/ApplicationCode/Application/RiaGuiApplication.h index d7ea79341d..10a5f1d8e8 100644 --- a/ApplicationCode/Application/RiaGuiApplication.h +++ b/ApplicationCode/Application/RiaGuiApplication.h @@ -133,7 +133,6 @@ public: protected: // Protected RiaApplication overrides void invokeProcessEvents(QEventLoop::ProcessEventsFlags flags = QEventLoop::AllEvents) override; - void onChangedActiveReservoirView() override; void onFileSuccessfullyLoaded(const QString& fileName, RiaDefines::ImportFileType fileType) override; void onProjectBeingOpened() override; void onProjectOpeningError(const QString& errMsg); From f43edf3c7d0fabae9cfdb156897dd3d5f2eb143c Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 15 May 2019 10:47:30 +0200 Subject: [PATCH 048/396] #4410 Dock Window State : Create static functions instead of singleton --- .../Application/RiaGuiApplication.cpp | 22 +++- .../RicShowMainWindowFeature.cpp | 7 ++ .../UserInterface/RiuDockWidgetTools.cpp | 119 ++++++------------ .../UserInterface/RiuDockWidgetTools.h | 49 +++----- .../UserInterface/RiuMainWindow.cpp | 49 ++++---- .../UserInterface/RiuMainWindowBase.cpp | 38 +++++- .../UserInterface/RiuMainWindowBase.h | 3 + .../UserInterface/RiuPlotMainWindow.cpp | 2 + 8 files changed, 149 insertions(+), 140 deletions(-) diff --git a/ApplicationCode/Application/RiaGuiApplication.cpp b/ApplicationCode/Application/RiaGuiApplication.cpp index 16097110a4..947e7d34ad 100644 --- a/ApplicationCode/Application/RiaGuiApplication.cpp +++ b/ApplicationCode/Application/RiaGuiApplication.cpp @@ -566,7 +566,9 @@ void RiaGuiApplication::initialize() // Create main windows // The plot window is created to be able to set expanded state on created objects, but hidden by default getOrCreateAndShowMainWindow(); - getOrCreateMainPlotWindow(); + RiuPlotMainWindow* plotMainWindow = getOrCreateMainPlotWindow(); + plotMainWindow->hideAllDockWindows(); + RiaLogging::setLoggerInstance(new RiuMessagePanelLogger(m_mainWindow->messagePanel())); RiaLogging::loggerInstance()->setLevel(RI_LL_DEBUG); @@ -959,6 +961,11 @@ RiuMainWindow* RiaGuiApplication::getOrCreateAndShowMainWindow() { createMainWindow(); } + else + { + m_mainWindow->loadWinGeoAndDockToolBarLayout(); + } + return m_mainWindow; } @@ -1023,6 +1030,7 @@ void RiaGuiApplication::createMainPlotWindow() m_mainPlotWindow->setWindowTitle("Plots - ResInsight"); m_mainPlotWindow->setDefaultWindowSize(); m_mainPlotWindow->loadWinGeoAndDockToolBarLayout(); + m_mainPlotWindow->hideAllDockWindows(); } //-------------------------------------------------------------------------------------------------- @@ -1042,12 +1050,18 @@ void RiaGuiApplication::deleteMainPlotWindow() //-------------------------------------------------------------------------------------------------- RiuPlotMainWindow* RiaGuiApplication::getOrCreateAndShowMainPlotWindow() { + bool triggerReloadOfDockWidgetVisibilities = false; + if (!m_mainPlotWindow) { createMainPlotWindow(); m_mainPlotWindow->initializeGuiNewProjectLoaded(); loadAndUpdatePlotData(); } + else + { + triggerReloadOfDockWidgetVisibilities = !m_mainPlotWindow->isVisible(); + } if (m_mainPlotWindow->isMinimized()) { @@ -1061,6 +1075,12 @@ RiuPlotMainWindow* RiaGuiApplication::getOrCreateAndShowMainPlotWindow() m_mainPlotWindow->raise(); m_mainPlotWindow->activateWindow(); + + if (triggerReloadOfDockWidgetVisibilities) + { + m_mainPlotWindow->restoreDockWidgetVisibilities(); + } + return m_mainPlotWindow; } diff --git a/ApplicationCode/Commands/ApplicationCommands/RicShowMainWindowFeature.cpp b/ApplicationCode/Commands/ApplicationCommands/RicShowMainWindowFeature.cpp index d397c3f775..211f9e322e 100644 --- a/ApplicationCode/Commands/ApplicationCommands/RicShowMainWindowFeature.cpp +++ b/ApplicationCode/Commands/ApplicationCommands/RicShowMainWindowFeature.cpp @@ -43,6 +43,8 @@ void RicShowMainWindowFeature::onActionTriggered(bool isChecked) RiuMainWindow* mainWnd = RiuMainWindow::instance(); + bool triggerReloadOfDockWindowVisibilities = !mainWnd->isVisible(); + if (mainWnd->isMinimized()) { mainWnd->showNormal(); @@ -54,6 +56,11 @@ void RicShowMainWindowFeature::onActionTriggered(bool isChecked) } mainWnd->raise(); + + if (triggerReloadOfDockWindowVisibilities) + { + mainWnd->restoreDockWidgetVisibilities(); + } } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/UserInterface/RiuDockWidgetTools.cpp b/ApplicationCode/UserInterface/RiuDockWidgetTools.cpp index 6b3c9795ba..3a7264aa2f 100644 --- a/ApplicationCode/UserInterface/RiuDockWidgetTools.cpp +++ b/ApplicationCode/UserInterface/RiuDockWidgetTools.cpp @@ -31,25 +31,7 @@ //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RiuDockWidgetTools::RiuDockWidgetTools() -{ - loadDockWidgetsState(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -RiuDockWidgetTools* RiuDockWidgetTools::instance() -{ - static RiuDockWidgetTools staticInstance; - - return &staticInstance; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -QString RiuDockWidgetTools::projectTreeName() const +QString RiuDockWidgetTools::projectTreeName() { return "dockProjectTree"; } @@ -57,7 +39,7 @@ QString RiuDockWidgetTools::projectTreeName() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QString RiuDockWidgetTools::propertyEditorName() const +QString RiuDockWidgetTools::propertyEditorName() { return "dockpropertyEditor"; } @@ -65,7 +47,7 @@ QString RiuDockWidgetTools::propertyEditorName() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QString RiuDockWidgetTools::resultInfoName() const +QString RiuDockWidgetTools::resultInfoName() { return "dockResultInfo"; } @@ -73,7 +55,7 @@ QString RiuDockWidgetTools::resultInfoName() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QString RiuDockWidgetTools::processMonitorName() const +QString RiuDockWidgetTools::processMonitorName() { return "dockProcessMonitor"; } @@ -81,7 +63,7 @@ QString RiuDockWidgetTools::processMonitorName() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QString RiuDockWidgetTools::resultPlotName() const +QString RiuDockWidgetTools::resultPlotName() { return "dockResultPlot"; } @@ -89,7 +71,7 @@ QString RiuDockWidgetTools::resultPlotName() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QString RiuDockWidgetTools::relPermPlotName() const +QString RiuDockWidgetTools::relPermPlotName() { return "dockRelPermPlot"; } @@ -97,7 +79,7 @@ QString RiuDockWidgetTools::relPermPlotName() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QString RiuDockWidgetTools::pvtPlotName() const +QString RiuDockWidgetTools::pvtPlotName() { return "dockPvtPlot"; } @@ -105,7 +87,7 @@ QString RiuDockWidgetTools::pvtPlotName() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QString RiuDockWidgetTools::mohrsCirclePlotName() const +QString RiuDockWidgetTools::mohrsCirclePlotName() { return "dockMohrsCirclePlot"; } @@ -113,7 +95,7 @@ QString RiuDockWidgetTools::mohrsCirclePlotName() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QString RiuDockWidgetTools::messagesName() const +QString RiuDockWidgetTools::messagesName() { return "dockMessages"; } @@ -165,8 +147,8 @@ void RiuDockWidgetTools::setVisibleDockingWindowsForEclipse() } } - RiuDockWidgetTools::instance()->trySetDockWidgetVisibility(mainWindow, RiuDockWidgetTools::relPermPlotName(), true); - RiuDockWidgetTools::instance()->trySetDockWidgetVisibility(mainWindow, RiuDockWidgetTools::pvtPlotName(), true); + RiuDockWidgetTools::trySetDockWidgetVisibility(mainWindow, RiuDockWidgetTools::relPermPlotName(), true); + RiuDockWidgetTools::trySetDockWidgetVisibility(mainWindow, RiuDockWidgetTools::pvtPlotName(), true); } //-------------------------------------------------------------------------------------------------- @@ -176,7 +158,7 @@ void RiuDockWidgetTools::setVisibleDockingWindowsForGeoMech() { RiuMainWindow* mainWindow = RiuMainWindow::instance(); - RiuDockWidgetTools::instance()->trySetDockWidgetVisibility(mainWindow, RiuDockWidgetTools::mohrsCirclePlotName(), false); + RiuDockWidgetTools::trySetDockWidgetVisibility(mainWindow, RiuDockWidgetTools::mohrsCirclePlotName(), false); { QDockWidget* dockWidget = findDockWidget(mainWindow, RiuDockWidgetTools::relPermPlotName()); @@ -203,78 +185,57 @@ void RiuDockWidgetTools::trySetDockWidgetVisibility(const QObject* parent, const QDockWidget* dockWidget = findDockWidget(parent, dockWidgetName); if (dockWidget) { - bool unifiedIsVisible = isVisible; - - auto state = visibilityForWidget(dockWidgetName); - if (state != RiuDockWidgetTools::USER_DEFINED_UNKNOWN) - { - if (state == RiuDockWidgetTools::USER_DEFINED_ON) - { - unifiedIsVisible = true; - } - else if (state == RiuDockWidgetTools::USER_DEFINED_OFF) - { - unifiedIsVisible = false; - } - } - - dockWidget->setVisible(unifiedIsVisible); + dockWidget->setVisible(isVisible); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RiuDockWidgetTools::UserDefinedVisibility RiuDockWidgetTools::visibilityForWidget(const QString& objectName) +QVariant RiuDockWidgetTools::storeDockWidgetsVisibility(const QObject* parent) { - RiuDockWidgetTools::UserDefinedVisibility visibility = USER_DEFINED_UNKNOWN; + QMap widgetVisibility; - auto windowStateIt = m_userDefinedDockWidgetVisibility.find(objectName); - if (windowStateIt != m_userDefinedDockWidgetVisibility.end()) + QList dockWidgets = parent->findChildren(); + + for (QDockWidget* dock : dockWidgets) { - bool isVisible = windowStateIt.value().toBool(); - if (isVisible) + if (dock) { - visibility = USER_DEFINED_ON; - } - else - { - visibility = USER_DEFINED_OFF; + bool isVisible = dock->isVisible(); + widgetVisibility[dock->objectName()] = isVisible; + + // qDebug() << "Store " << dock->objectName() << " : " << (isVisible ? "visible" : "not visible"); } } - return visibility; + return QVariant(widgetVisibility); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RiuDockWidgetTools::setDockWidgetVisibility(const QString& dockingWindowName, bool isVisible) +void RiuDockWidgetTools::restoreDockWidgetsVisibility(const QObject* parent, QVariant widgetVisibilities) { - m_userDefinedDockWidgetVisibility[dockingWindowName] = isVisible; -} + QMap widgetVisibilityMap = widgetVisibilities.toMap(); -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuDockWidgetTools::loadDockWidgetsState() -{ - // Company and appname set through QCoreApplication - QSettings settings; + QList dockWidgets = parent->findChildren(); - m_userDefinedDockWidgetVisibility = settings.value("dockWindowStates").toMap(); -} + for (QDockWidget* dock : dockWidgets) + { + if (dock) + { + auto widgetVisibility = widgetVisibilityMap.find(dock->objectName()); -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuDockWidgetTools::saveDockWidgetsState() -{ - // Company and appname set through QCoreApplication - QSettings settings; + if (widgetVisibility != widgetVisibilityMap.end()) + { + bool isVisible = widgetVisibility.value().toBool(); + dock->setVisible(isVisible); - QVariant v(m_userDefinedDockWidgetVisibility); - settings.setValue("dockWindowStates", v); + // qDebug() << "Restore " << dock->objectName() << " : " << (isVisible ? "visible" : "not visible"); + } + } + } } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/UserInterface/RiuDockWidgetTools.h b/ApplicationCode/UserInterface/RiuDockWidgetTools.h index 7e59b3f798..7a53c34d0e 100644 --- a/ApplicationCode/UserInterface/RiuDockWidgetTools.h +++ b/ApplicationCode/UserInterface/RiuDockWidgetTools.h @@ -30,45 +30,32 @@ class Rim3dView; //================================================================================================== // -// +// // //================================================================================================== class RiuDockWidgetTools { public: - static RiuDockWidgetTools* instance(); + static QString projectTreeName(); + static QString propertyEditorName(); + static QString resultInfoName(); + static QString processMonitorName(); + static QString resultPlotName(); + static QString relPermPlotName(); + static QString pvtPlotName(); + static QString messagesName(); + static QString mohrsCirclePlotName(); - QString projectTreeName() const; - QString propertyEditorName() const; - QString resultInfoName() const; - QString processMonitorName() const; - QString resultPlotName() const; - QString relPermPlotName() const; - QString pvtPlotName() const; - QString messagesName() const; - QString mohrsCirclePlotName() const; + static QAction* toggleActionForWidget(const QObject* parent, const QString& dockWidgetName); - QAction* toggleActionForWidget(const QObject* parent, const QString& dockWidgetName); - void setDockWidgetVisibility(const QString& dockWidgetName, bool isVisible); - void changeDockWidgetVisibilityBasedOnView(Rim3dView* view); - void saveDockWidgetsState(); + static QVariant storeDockWidgetsVisibility(const QObject* parent); + static void restoreDockWidgetsVisibility(const QObject* parent, QVariant widgetVisibilities); private: - enum UserDefinedVisibility - { - USER_DEFINED_ON, - USER_DEFINED_OFF, - USER_DEFINED_UNKNOWN - }; + static void changeDockWidgetVisibilityBasedOnView(Rim3dView* view); - RiuDockWidgetTools(); - void setVisibleDockingWindowsForEclipse(); - void setVisibleDockingWindowsForGeoMech(); - void loadDockWidgetsState(); - UserDefinedVisibility visibilityForWidget(const QString& dockWidgetName); - static QDockWidget* findDockWidget(const QObject* parent, const QString& dockWidgetName); - void trySetDockWidgetVisibility(const QObject* parent, const QString& dockWidgetName, bool isVisible); - -private: - QMap m_userDefinedDockWidgetVisibility; + static void setVisibleDockingWindowsForEclipse(); + static void setVisibleDockingWindowsForGeoMech(); + static QDockWidget* findDockWidget(const QObject* parent, const QString& dockWidgetName); + static void trySetDockWidgetVisibility(const QObject* parent, const QString& dockWidgetName, bool isVisible); }; diff --git a/ApplicationCode/UserInterface/RiuMainWindow.cpp b/ApplicationCode/UserInterface/RiuMainWindow.cpp index 73f113e19a..2d8b5959e9 100644 --- a/ApplicationCode/UserInterface/RiuMainWindow.cpp +++ b/ApplicationCode/UserInterface/RiuMainWindow.cpp @@ -270,10 +270,10 @@ void RiuMainWindow::cleanupGuiBeforeProjectClose() //-------------------------------------------------------------------------------------------------- void RiuMainWindow::closeEvent(QCloseEvent* event) { - RiaGuiApplication* app = RiaGuiApplication::instance(); - this->saveWinGeoAndDockToolBarLayout(); + this->hideAllDockWindows(); + RiaGuiApplication* app = RiaGuiApplication::instance(); if (app->isMainPlotWindowVisible()) { event->ignore(); // Make Qt think we don't do anything, otherwise it closes the window. @@ -666,11 +666,9 @@ void RiuMainWindow::createToolBars() //-------------------------------------------------------------------------------------------------- void RiuMainWindow::createDockPanels() { - auto dwt = RiuDockWidgetTools::instance(); - { QDockWidget* dockWidget = new QDockWidget("Project Tree", this); - dockWidget->setObjectName(dwt->projectTreeName()); + dockWidget->setObjectName(RiuDockWidgetTools::projectTreeName()); dockWidget->setAllowedAreas(Qt::AllDockWidgetAreas); m_projectTreeView = new caf::PdmUiTreeView(this); @@ -712,7 +710,7 @@ void RiuMainWindow::createDockPanels() { QDockWidget* dockWidget = new QDockWidget("Property Editor", this); - dockWidget->setObjectName(dwt->propertyEditorName()); + dockWidget->setObjectName(RiuDockWidgetTools::propertyEditorName()); dockWidget->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); m_pdmUiPropertyView = new caf::PdmUiPropertyView(dockWidget); @@ -723,7 +721,7 @@ void RiuMainWindow::createDockPanels() { QDockWidget* dockWidget = new QDockWidget("Result Info", this); - dockWidget->setObjectName(dwt->resultInfoName()); + dockWidget->setObjectName(RiuDockWidgetTools::resultInfoName()); dockWidget->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea | Qt::BottomDockWidgetArea); m_resultInfoPanel = new RiuResultInfoPanel(dockWidget); dockWidget->setWidget(m_resultInfoPanel); @@ -733,7 +731,7 @@ void RiuMainWindow::createDockPanels() { QDockWidget* dockWidget = new QDockWidget("Process Monitor", this); - dockWidget->setObjectName(dwt->processMonitorName()); + dockWidget->setObjectName(RiuDockWidgetTools::processMonitorName()); dockWidget->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea | Qt::BottomDockWidgetArea); m_processMonitor = new RiuProcessMonitor(dockWidget); dockWidget->setWidget(m_processMonitor); @@ -744,7 +742,7 @@ void RiuMainWindow::createDockPanels() { QDockWidget* dockWidget = new QDockWidget("Result Plot", this); - dockWidget->setObjectName(dwt->resultPlotName()); + dockWidget->setObjectName(RiuDockWidgetTools::resultPlotName()); dockWidget->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea | Qt::BottomDockWidgetArea); m_resultQwtPlot = new RiuResultQwtPlot(dockWidget); dockWidget->setWidget(m_resultQwtPlot); @@ -756,7 +754,7 @@ void RiuMainWindow::createDockPanels() #ifdef USE_ODB_API { QDockWidget* dockWidget = new QDockWidget("Mohr's Circle Plot", this); - dockWidget->setObjectName(dwt->mohrsCirclePlotName()); + dockWidget->setObjectName(RiuDockWidgetTools::mohrsCirclePlotName()); dockWidget->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea | Qt::BottomDockWidgetArea); m_mohrsCirclePlot = new RiuMohrsCirclePlot(dockWidget); dockWidget->setWidget(m_mohrsCirclePlot); @@ -770,7 +768,7 @@ void RiuMainWindow::createDockPanels() { QDockWidget* dockWidget = new QDockWidget("Relative Permeability Plot", this); - dockWidget->setObjectName(dwt->relPermPlotName()); + dockWidget->setObjectName(RiuDockWidgetTools::relPermPlotName()); dockWidget->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea | Qt::BottomDockWidgetArea); m_relPermPlotPanel = new RiuRelativePermeabilityPlotPanel(dockWidget); dockWidget->setWidget(m_relPermPlotPanel); @@ -781,7 +779,7 @@ void RiuMainWindow::createDockPanels() { QDockWidget* dockWidget = new QDockWidget("PVT Plot", this); - dockWidget->setObjectName(dwt->pvtPlotName()); + dockWidget->setObjectName(RiuDockWidgetTools::pvtPlotName()); dockWidget->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea | Qt::BottomDockWidgetArea); m_pvtPlotPanel = new RiuPvtPlotPanel(dockWidget); dockWidget->setWidget(m_pvtPlotPanel); @@ -792,7 +790,7 @@ void RiuMainWindow::createDockPanels() { QDockWidget* dockWidget = new QDockWidget("Messages", this); - dockWidget->setObjectName(dwt->messagesName()); + dockWidget->setObjectName(RiuDockWidgetTools::messagesName()); m_messagePanel = new RiuMessagePanel(dockWidget); dockWidget->setWidget(m_messagePanel); addDockWidget(Qt::BottomDockWidgetArea, dockWidget); @@ -1349,8 +1347,7 @@ void appendToggleActionForDockingWidget(QMenu* menu, QWidget* parent, const QStr { if (menu) { - auto dwt = RiuDockWidgetTools::instance(); - QAction* action = dwt->toggleActionForWidget(parent, dockWidgetName); + QAction* action = RiuDockWidgetTools::toggleActionForWidget(parent, dockWidgetName); if (action) { // Some dock windows are depending on configuration (mohrs circle plot), so do not assert they exist @@ -1372,20 +1369,18 @@ void RiuMainWindow::slotBuildWindowActions() m_windowMenu->addSeparator(); } - auto dwt = RiuDockWidgetTools::instance(); - - appendToggleActionForDockingWidget(m_windowMenu, this, dwt->projectTreeName()); - appendToggleActionForDockingWidget(m_windowMenu, this, dwt->propertyEditorName()); - appendToggleActionForDockingWidget(m_windowMenu, this, dwt->messagesName()); - appendToggleActionForDockingWidget(m_windowMenu, this, dwt->processMonitorName()); + appendToggleActionForDockingWidget(m_windowMenu, this, RiuDockWidgetTools::projectTreeName()); + appendToggleActionForDockingWidget(m_windowMenu, this, RiuDockWidgetTools::propertyEditorName()); + appendToggleActionForDockingWidget(m_windowMenu, this, RiuDockWidgetTools::messagesName()); + appendToggleActionForDockingWidget(m_windowMenu, this, RiuDockWidgetTools::processMonitorName()); m_windowMenu->addSeparator(); - appendToggleActionForDockingWidget(m_windowMenu, this, dwt->resultInfoName()); - appendToggleActionForDockingWidget(m_windowMenu, this, dwt->resultPlotName()); - appendToggleActionForDockingWidget(m_windowMenu, this, dwt->relPermPlotName()); - appendToggleActionForDockingWidget(m_windowMenu, this, dwt->pvtPlotName()); - appendToggleActionForDockingWidget(m_windowMenu, this, dwt->mohrsCirclePlotName()); + appendToggleActionForDockingWidget(m_windowMenu, this, RiuDockWidgetTools::resultInfoName()); + appendToggleActionForDockingWidget(m_windowMenu, this, RiuDockWidgetTools::resultPlotName()); + appendToggleActionForDockingWidget(m_windowMenu, this, RiuDockWidgetTools::relPermPlotName()); + appendToggleActionForDockingWidget(m_windowMenu, this, RiuDockWidgetTools::pvtPlotName()); + appendToggleActionForDockingWidget(m_windowMenu, this, RiuDockWidgetTools::mohrsCirclePlotName()); m_windowMenu->addSeparator(); QAction* cascadeWindowsAction = new QAction("Cascade Windows", this); @@ -1780,7 +1775,7 @@ void RiuMainWindow::updateMemoryUsage() //-------------------------------------------------------------------------------------------------- void RiuMainWindow::showProcessMonitorDockPanel() { - showDockPanel(RiuDockWidgetTools::instance()->processMonitorName()); + showDockPanel(RiuDockWidgetTools::processMonitorName()); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/UserInterface/RiuMainWindowBase.cpp b/ApplicationCode/UserInterface/RiuMainWindowBase.cpp index 2e6004f59f..efa988bc1e 100644 --- a/ApplicationCode/UserInterface/RiuMainWindowBase.cpp +++ b/ApplicationCode/UserInterface/RiuMainWindowBase.cpp @@ -83,6 +83,8 @@ void RiuMainWindowBase::loadWinGeoAndDockToolBarLayout() } } } + + restoreDockWidgetVisibilities(); } //-------------------------------------------------------------------------------------------------- @@ -100,6 +102,24 @@ void RiuMainWindowBase::saveWinGeoAndDockToolBarLayout() settings.setValue(QString("%1/dockAndToolBarLayout").arg(registryFolderName()), layout); settings.setValue(QString("%1/isMaximized").arg(registryFolderName()), isMaximized()); + + if (this->isVisible()) + { + QVariant dockWindowVisibilities = RiuDockWidgetTools::storeDockWidgetsVisibility(this); + settings.setValue(QString("%1/dockWindowVisibilies").arg(registryFolderName()), dockWindowVisibilities); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuMainWindowBase::restoreDockWidgetVisibilities() +{ + // Company and appname set through QCoreApplication + QSettings settings; + + QVariant dockWindowVisibilities = settings.value(QString("%1/dockWindowVisibilies").arg(registryFolderName())); + RiuDockWidgetTools::restoreDockWidgetsVisibility(this, dockWindowVisibilities); } //-------------------------------------------------------------------------------------------------- @@ -119,6 +139,22 @@ void RiuMainWindowBase::showWindow() } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuMainWindowBase::closeAllDockWidgets() +{ + QList dockWidgets = findChildren(); + + for (QDockWidget* dock : dockWidgets) + { + if (dock) + { + dock->hide(); + } + } +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -225,8 +261,6 @@ void RiuMainWindowBase::slotDockWidgetToggleViewActionTriggered() // Raise the dock widget to make it visible if the widget is part of a tab widget dockWidget->raise(); } - - RiuDockWidgetTools::instance()->setDockWidgetVisibility(dockWidget->objectName(), dockWidget->isVisible()); } } diff --git a/ApplicationCode/UserInterface/RiuMainWindowBase.h b/ApplicationCode/UserInterface/RiuMainWindowBase.h index 1e41360426..9acb072ab4 100644 --- a/ApplicationCode/UserInterface/RiuMainWindowBase.h +++ b/ApplicationCode/UserInterface/RiuMainWindowBase.h @@ -56,8 +56,11 @@ public: RimMdiWindowGeometry windowGeometryForViewer(QWidget* viewer); void loadWinGeoAndDockToolBarLayout(); void saveWinGeoAndDockToolBarLayout(); + void restoreDockWidgetVisibilities(); void showWindow(); + void closeAllDockWidgets(); + caf::PdmUiTreeView* projectTreeView() { return m_projectTreeView;} void setExpanded(const caf::PdmUiItem* uiItem, bool expanded = true); diff --git a/ApplicationCode/UserInterface/RiuPlotMainWindow.cpp b/ApplicationCode/UserInterface/RiuPlotMainWindow.cpp index 3653bb29f2..1c3bd73ff5 100644 --- a/ApplicationCode/UserInterface/RiuPlotMainWindow.cpp +++ b/ApplicationCode/UserInterface/RiuPlotMainWindow.cpp @@ -180,6 +180,8 @@ void RiuPlotMainWindow::closeEvent(QCloseEvent* event) { this->saveWinGeoAndDockToolBarLayout(); + this->hideAllDockWindows(); + RiaGuiApplication* app = RiaGuiApplication::instance(); if (app->isMain3dWindowVisible()) From 6830d79de77c9bae32e0fb912d50e258c3083b77 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 15 May 2019 10:52:27 +0200 Subject: [PATCH 049/396] #4410 Dock Window State : Move plot widget names to DockWidgetTools --- .../UserInterface/RiuDockWidgetTools.cpp | 16 ++++++++++++++++ .../UserInterface/RiuDockWidgetTools.h | 3 +++ .../UserInterface/RiuPlotMainWindow.cpp | 5 +++-- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/ApplicationCode/UserInterface/RiuDockWidgetTools.cpp b/ApplicationCode/UserInterface/RiuDockWidgetTools.cpp index 3a7264aa2f..cf6a6d266e 100644 --- a/ApplicationCode/UserInterface/RiuDockWidgetTools.cpp +++ b/ApplicationCode/UserInterface/RiuDockWidgetTools.cpp @@ -92,6 +92,22 @@ QString RiuDockWidgetTools::mohrsCirclePlotName() return "dockMohrsCirclePlot"; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RiuDockWidgetTools::plotMainWindowProjectTreeName() +{ + return "plotMainWindow_dockProjectTree"; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RiuDockWidgetTools::plotMainWindowPropertyEditorName() +{ + return "plotMainWindow_dockPropertyEditor"; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/UserInterface/RiuDockWidgetTools.h b/ApplicationCode/UserInterface/RiuDockWidgetTools.h index 7a53c34d0e..7caef58e29 100644 --- a/ApplicationCode/UserInterface/RiuDockWidgetTools.h +++ b/ApplicationCode/UserInterface/RiuDockWidgetTools.h @@ -46,6 +46,9 @@ public: static QString messagesName(); static QString mohrsCirclePlotName(); + static QString plotMainWindowProjectTreeName(); + static QString plotMainWindowPropertyEditorName(); + static QAction* toggleActionForWidget(const QObject* parent, const QString& dockWidgetName); static QVariant storeDockWidgetsVisibility(const QObject* parent); diff --git a/ApplicationCode/UserInterface/RiuPlotMainWindow.cpp b/ApplicationCode/UserInterface/RiuPlotMainWindow.cpp index 1c3bd73ff5..9a38536d35 100644 --- a/ApplicationCode/UserInterface/RiuPlotMainWindow.cpp +++ b/ApplicationCode/UserInterface/RiuPlotMainWindow.cpp @@ -34,6 +34,7 @@ #include "RimWellLogCurveCommonDataSource.h" #include "RimWellLogPlot.h" +#include "RiuDockWidgetTools.h" #include "RiuDragDrop.h" #include "RiuMdiSubWindow.h" #include "RiuToolTipMenu.h" @@ -385,7 +386,7 @@ void RiuPlotMainWindow::createDockPanels() { { QDockWidget* dockWidget = new QDockWidget("Plot Project Tree", this); - dockWidget->setObjectName("plotProjectTreeDockWidget"); + dockWidget->setObjectName(RiuDockWidgetTools::plotMainWindowProjectTreeName()); dockWidget->setAllowedAreas(Qt::AllDockWidgetAreas); m_projectTreeView = new caf::PdmUiTreeView(this); @@ -422,7 +423,7 @@ void RiuPlotMainWindow::createDockPanels() { QDockWidget* dockWidget = new QDockWidget("Property Editor", this); - dockWidget->setObjectName("plotPropertyEditorDockWidget"); + dockWidget->setObjectName(RiuDockWidgetTools::plotMainWindowPropertyEditorName()); dockWidget->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); m_pdmUiPropertyView = new caf::PdmUiPropertyView(dockWidget); From 95124adca6c58e9c0f2670c497fb162d127bc694 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 15 May 2019 11:27:36 +0200 Subject: [PATCH 050/396] #4410 Dock Window State : Add features for default dock widget visibility --- .../CMakeLists_files.cmake | 4 ++ .../RicDefaultDockConfigEclipseFeature.cpp | 54 ++++++++++++++++++ .../RicDefaultDockConfigEclipseFeature.h | 34 +++++++++++ .../RicDefaultDockConfigGeoMechFeature.cpp | 49 ++++++++++++++++ .../RicDefaultDockConfigGeoMechFeature.h | 34 +++++++++++ .../UserInterface/RiuDockWidgetTools.cpp | 56 ++++++------------- .../UserInterface/RiuDockWidgetTools.h | 5 +- .../UserInterface/RiuMainWindow.cpp | 6 ++ 8 files changed, 201 insertions(+), 41 deletions(-) create mode 100644 ApplicationCode/Commands/ApplicationCommands/RicDefaultDockConfigEclipseFeature.cpp create mode 100644 ApplicationCode/Commands/ApplicationCommands/RicDefaultDockConfigEclipseFeature.h create mode 100644 ApplicationCode/Commands/ApplicationCommands/RicDefaultDockConfigGeoMechFeature.cpp create mode 100644 ApplicationCode/Commands/ApplicationCommands/RicDefaultDockConfigGeoMechFeature.h diff --git a/ApplicationCode/Commands/ApplicationCommands/CMakeLists_files.cmake b/ApplicationCode/Commands/ApplicationCommands/CMakeLists_files.cmake index 65f9e94ff4..108a396c04 100644 --- a/ApplicationCode/Commands/ApplicationCommands/CMakeLists_files.cmake +++ b/ApplicationCode/Commands/ApplicationCommands/CMakeLists_files.cmake @@ -16,6 +16,8 @@ ${CMAKE_CURRENT_LIST_DIR}/RicShowPlotDataFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicLaunchRegressionTestsFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicRunCommandFileFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicShowMemoryCleanupDialogFeature.h +${CMAKE_CURRENT_LIST_DIR}/RicDefaultDockConfigEclipseFeature.h +${CMAKE_CURRENT_LIST_DIR}/RicDefaultDockConfigGeoMechFeature.h ) set (SOURCE_GROUP_SOURCE_FILES @@ -35,6 +37,8 @@ ${CMAKE_CURRENT_LIST_DIR}/RicShowPlotDataFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicLaunchRegressionTestsFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicRunCommandFileFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicShowMemoryCleanupDialogFeature.cpp +${CMAKE_CURRENT_LIST_DIR}/RicDefaultDockConfigEclipseFeature.cpp +${CMAKE_CURRENT_LIST_DIR}/RicDefaultDockConfigGeoMechFeature.cpp ) list(APPEND CODE_HEADER_FILES diff --git a/ApplicationCode/Commands/ApplicationCommands/RicDefaultDockConfigEclipseFeature.cpp b/ApplicationCode/Commands/ApplicationCommands/RicDefaultDockConfigEclipseFeature.cpp new file mode 100644 index 0000000000..088d66e5cf --- /dev/null +++ b/ApplicationCode/Commands/ApplicationCommands/RicDefaultDockConfigEclipseFeature.cpp @@ -0,0 +1,54 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 "RicDefaultDockConfigEclipseFeature.h" + +#include "RiuDockWidgetTools.h" + +#include + +CAF_CMD_SOURCE_INIT(RicDefaultDockConfigEclipseFeature, "RicDefaultDockConfigEclipseFeature"); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RicDefaultDockConfigEclipseFeature::isCommandEnabled() +{ + return true; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicDefaultDockConfigEclipseFeature::onActionTriggered(bool isChecked) +{ + RiuDockWidgetTools::setVisibleDockingWindowsForEclipse(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicDefaultDockConfigEclipseFeature::setupActionLook(QAction* actionToSetup) +{ + QString menuText = "Default Window Visibility"; +#ifdef USE_ODB_API + menuText += " (Eclipse)"; +#endif + + actionToSetup->setText(menuText); +} diff --git a/ApplicationCode/Commands/ApplicationCommands/RicDefaultDockConfigEclipseFeature.h b/ApplicationCode/Commands/ApplicationCommands/RicDefaultDockConfigEclipseFeature.h new file mode 100644 index 0000000000..f0b72e9176 --- /dev/null +++ b/ApplicationCode/Commands/ApplicationCommands/RicDefaultDockConfigEclipseFeature.h @@ -0,0 +1,34 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 RicDefaultDockConfigEclipseFeature : public caf::CmdFeature +{ + CAF_CMD_HEADER_INIT; + +protected: + bool isCommandEnabled() override; + void onActionTriggered(bool isChecked) override; + void setupActionLook(QAction* actionToSetup) override; +}; diff --git a/ApplicationCode/Commands/ApplicationCommands/RicDefaultDockConfigGeoMechFeature.cpp b/ApplicationCode/Commands/ApplicationCommands/RicDefaultDockConfigGeoMechFeature.cpp new file mode 100644 index 0000000000..d3baa27d77 --- /dev/null +++ b/ApplicationCode/Commands/ApplicationCommands/RicDefaultDockConfigGeoMechFeature.cpp @@ -0,0 +1,49 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 "RicDefaultDockConfigGeoMechFeature.h" + +#include "RiuDockWidgetTools.h" + +#include + +CAF_CMD_SOURCE_INIT(RicDefaultDockConfigGeoMechFeature, "RicDefaultDockConfigGeoMechFeature"); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RicDefaultDockConfigGeoMechFeature::isCommandEnabled() +{ + return true; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicDefaultDockConfigGeoMechFeature::onActionTriggered(bool isChecked) +{ + RiuDockWidgetTools::setVisibleDockingWindowsForGeoMech(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicDefaultDockConfigGeoMechFeature::setupActionLook(QAction* actionToSetup) +{ + actionToSetup->setText("Default Window Visibility (Geo Mech)"); +} diff --git a/ApplicationCode/Commands/ApplicationCommands/RicDefaultDockConfigGeoMechFeature.h b/ApplicationCode/Commands/ApplicationCommands/RicDefaultDockConfigGeoMechFeature.h new file mode 100644 index 0000000000..18ea988516 --- /dev/null +++ b/ApplicationCode/Commands/ApplicationCommands/RicDefaultDockConfigGeoMechFeature.h @@ -0,0 +1,34 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 RicDefaultDockConfigGeoMechFeature : public caf::CmdFeature +{ + CAF_CMD_HEADER_INIT; + +protected: + bool isCommandEnabled() override; + void onActionTriggered(bool isChecked) override; + void setupActionLook(QAction* actionToSetup) override; +}; diff --git a/ApplicationCode/UserInterface/RiuDockWidgetTools.cpp b/ApplicationCode/UserInterface/RiuDockWidgetTools.cpp index cf6a6d266e..9bd51f29cc 100644 --- a/ApplicationCode/UserInterface/RiuDockWidgetTools.cpp +++ b/ApplicationCode/UserInterface/RiuDockWidgetTools.cpp @@ -155,16 +155,17 @@ void RiuDockWidgetTools::setVisibleDockingWindowsForEclipse() { RiuMainWindow* mainWindow = RiuMainWindow::instance(); - { - QDockWidget* dockWidget = findDockWidget(mainWindow, RiuDockWidgetTools::mohrsCirclePlotName()); - if (dockWidget) - { - dockWidget->hide(); - } - } - + RiuDockWidgetTools::trySetDockWidgetVisibility(mainWindow, RiuDockWidgetTools::projectTreeName(), true); + RiuDockWidgetTools::trySetDockWidgetVisibility(mainWindow, RiuDockWidgetTools::propertyEditorName(), true); + RiuDockWidgetTools::trySetDockWidgetVisibility(mainWindow, RiuDockWidgetTools::resultInfoName(), true); + RiuDockWidgetTools::trySetDockWidgetVisibility(mainWindow, RiuDockWidgetTools::processMonitorName(), true); + RiuDockWidgetTools::trySetDockWidgetVisibility(mainWindow, RiuDockWidgetTools::resultPlotName(), true); RiuDockWidgetTools::trySetDockWidgetVisibility(mainWindow, RiuDockWidgetTools::relPermPlotName(), true); RiuDockWidgetTools::trySetDockWidgetVisibility(mainWindow, RiuDockWidgetTools::pvtPlotName(), true); + RiuDockWidgetTools::trySetDockWidgetVisibility(mainWindow, RiuDockWidgetTools::messagesName(), true); + + + RiuDockWidgetTools::trySetDockWidgetVisibility(mainWindow, RiuDockWidgetTools::mohrsCirclePlotName(), false); } //-------------------------------------------------------------------------------------------------- @@ -174,23 +175,16 @@ void RiuDockWidgetTools::setVisibleDockingWindowsForGeoMech() { RiuMainWindow* mainWindow = RiuMainWindow::instance(); - RiuDockWidgetTools::trySetDockWidgetVisibility(mainWindow, RiuDockWidgetTools::mohrsCirclePlotName(), false); + RiuDockWidgetTools::trySetDockWidgetVisibility(mainWindow, RiuDockWidgetTools::projectTreeName(), true); + RiuDockWidgetTools::trySetDockWidgetVisibility(mainWindow, RiuDockWidgetTools::propertyEditorName(), true); + RiuDockWidgetTools::trySetDockWidgetVisibility(mainWindow, RiuDockWidgetTools::resultInfoName(), true); + RiuDockWidgetTools::trySetDockWidgetVisibility(mainWindow, RiuDockWidgetTools::processMonitorName(), true); + RiuDockWidgetTools::trySetDockWidgetVisibility(mainWindow, RiuDockWidgetTools::resultPlotName(), true); + RiuDockWidgetTools::trySetDockWidgetVisibility(mainWindow, RiuDockWidgetTools::relPermPlotName(), false); + RiuDockWidgetTools::trySetDockWidgetVisibility(mainWindow, RiuDockWidgetTools::pvtPlotName(), false); + RiuDockWidgetTools::trySetDockWidgetVisibility(mainWindow, RiuDockWidgetTools::messagesName(), true); - { - QDockWidget* dockWidget = findDockWidget(mainWindow, RiuDockWidgetTools::relPermPlotName()); - if (dockWidget) - { - dockWidget->hide(); - } - } - - { - QDockWidget* dockWidget = findDockWidget(mainWindow, RiuDockWidgetTools::pvtPlotName()); - if (dockWidget) - { - dockWidget->hide(); - } - } + RiuDockWidgetTools::trySetDockWidgetVisibility(mainWindow, RiuDockWidgetTools::mohrsCirclePlotName(), true); } //-------------------------------------------------------------------------------------------------- @@ -254,17 +248,3 @@ void RiuDockWidgetTools::restoreDockWidgetsVisibility(const QObject* parent, QVa } } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuDockWidgetTools::changeDockWidgetVisibilityBasedOnView(Rim3dView* view) -{ - if (dynamic_cast(view)) - { - setVisibleDockingWindowsForEclipse(); - } - else if (dynamic_cast(view)) - { - setVisibleDockingWindowsForGeoMech(); - } -} diff --git a/ApplicationCode/UserInterface/RiuDockWidgetTools.h b/ApplicationCode/UserInterface/RiuDockWidgetTools.h index 7caef58e29..613a39d977 100644 --- a/ApplicationCode/UserInterface/RiuDockWidgetTools.h +++ b/ApplicationCode/UserInterface/RiuDockWidgetTools.h @@ -54,11 +54,10 @@ public: static QVariant storeDockWidgetsVisibility(const QObject* parent); static void restoreDockWidgetsVisibility(const QObject* parent, QVariant widgetVisibilities); -private: - static void changeDockWidgetVisibilityBasedOnView(Rim3dView* view); - static void setVisibleDockingWindowsForEclipse(); static void setVisibleDockingWindowsForGeoMech(); + +private: static QDockWidget* findDockWidget(const QObject* parent, const QString& dockWidgetName); static void trySetDockWidgetVisibility(const QObject* parent, const QString& dockWidgetName, bool isVisible); }; diff --git a/ApplicationCode/UserInterface/RiuMainWindow.cpp b/ApplicationCode/UserInterface/RiuMainWindow.cpp index 2d8b5959e9..efd995ddc6 100644 --- a/ApplicationCode/UserInterface/RiuMainWindow.cpp +++ b/ApplicationCode/UserInterface/RiuMainWindow.cpp @@ -1367,6 +1367,12 @@ void RiuMainWindow::slotBuildWindowActions() caf::CmdFeatureManager* cmdFeatureMgr = caf::CmdFeatureManager::instance(); m_windowMenu->addAction(cmdFeatureMgr->action("RicShowPlotWindowFeature")); m_windowMenu->addSeparator(); + + m_windowMenu->addAction(cmdFeatureMgr->action("RicDefaultDockConfigEclipseFeature")); +#ifdef USE_ODB_API + m_windowMenu->addAction(cmdFeatureMgr->action("RicDefaultDockConfigGeoMechFeature")); +#endif + m_windowMenu->addSeparator(); } appendToggleActionForDockingWidget(m_windowMenu, this, RiuDockWidgetTools::projectTreeName()); From 699870c8c7a242daff3fe4d4d548814be1d7703c Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 15 May 2019 12:31:27 +0200 Subject: [PATCH 051/396] #4410 Dock Window State : Use hideAllDockWidgets() in base class --- .../Application/RiaGuiApplication.cpp | 10 +++--- .../Tools/RiaRegressionTestRunner.cpp | 2 +- .../RicfExportSnapshots.cpp | 2 +- .../UserInterface/RiuDockWidgetTools.cpp | 12 ++++--- .../UserInterface/RiuDockWidgetTools.h | 6 ++-- .../UserInterface/RiuMainWindow.cpp | 36 ++----------------- ApplicationCode/UserInterface/RiuMainWindow.h | 5 --- .../UserInterface/RiuMainWindowBase.cpp | 2 +- .../UserInterface/RiuMainWindowBase.h | 2 +- .../UserInterface/RiuPlotMainWindow.cpp | 15 +------- .../UserInterface/RiuPlotMainWindow.h | 2 -- 11 files changed, 22 insertions(+), 72 deletions(-) diff --git a/ApplicationCode/Application/RiaGuiApplication.cpp b/ApplicationCode/Application/RiaGuiApplication.cpp index 947e7d34ad..1ecd5b2d88 100644 --- a/ApplicationCode/Application/RiaGuiApplication.cpp +++ b/ApplicationCode/Application/RiaGuiApplication.cpp @@ -567,7 +567,7 @@ void RiaGuiApplication::initialize() // The plot window is created to be able to set expanded state on created objects, but hidden by default getOrCreateAndShowMainWindow(); RiuPlotMainWindow* plotMainWindow = getOrCreateMainPlotWindow(); - plotMainWindow->hideAllDockWindows(); + plotMainWindow->hideAllDockWidgets(); RiaLogging::setLoggerInstance(new RiuMessagePanelLogger(m_mainWindow->messagePanel())); RiaLogging::loggerInstance()->setLevel(RI_LL_DEBUG); @@ -808,7 +808,7 @@ RiaApplication::ApplicationStatus RiaGuiApplication::handleArguments(cvf::Progra { RiuMainWindow* mainWnd = RiuMainWindow::instance(); CVF_ASSERT(mainWnd); - mainWnd->hideAllDockWindows(); + mainWnd->hideAllDockWidgets(); // 2016-11-09 : Location of snapshot folder was previously located in 'snapshot' folder // relative to current working folder. Now harmonized to behave as RiuMainWindow::slotSnapshotAllViewsToFile() @@ -822,7 +822,7 @@ RiaApplication::ApplicationStatus RiaGuiApplication::handleArguments(cvf::Progra { if (mainPlotWindow()) { - mainPlotWindow()->hideAllDockWindows(); + mainPlotWindow()->hideAllDockWidgets(); // Will be saved relative to current directory RicSnapshotAllPlotsToFileFeature::saveAllPlots(); @@ -1030,7 +1030,7 @@ void RiaGuiApplication::createMainPlotWindow() m_mainPlotWindow->setWindowTitle("Plots - ResInsight"); m_mainPlotWindow->setDefaultWindowSize(); m_mainPlotWindow->loadWinGeoAndDockToolBarLayout(); - m_mainPlotWindow->hideAllDockWindows(); + m_mainPlotWindow->hideAllDockWidgets(); } //-------------------------------------------------------------------------------------------------- @@ -1645,7 +1645,7 @@ void RiaGuiApplication::runMultiCaseSnapshots(const QString& templateProje { if (!m_mainWindow) return; - m_mainWindow->hideAllDockWindows(); + m_mainWindow->hideAllDockWidgets(); const size_t numGridFiles = gridFileNames.size(); for (size_t i = 0; i < numGridFiles; i++) diff --git a/ApplicationCode/Application/Tools/RiaRegressionTestRunner.cpp b/ApplicationCode/Application/Tools/RiaRegressionTestRunner.cpp index 0fcdc3ec02..e286add669 100644 --- a/ApplicationCode/Application/Tools/RiaRegressionTestRunner.cpp +++ b/ApplicationCode/Application/Tools/RiaRegressionTestRunner.cpp @@ -641,7 +641,7 @@ void RiaRegressionTestRunner::executeRegressionTests(const QString& regressionTe RiuMainWindow* mainWnd = RiuMainWindow::instance(); if (mainWnd) { - mainWnd->hideAllDockWindows(); + mainWnd->hideAllDockWidgets(); mainWnd->statusBar()->close(); mainWnd->setDefaultWindowSize(); diff --git a/ApplicationCode/CommandFileInterface/RicfExportSnapshots.cpp b/ApplicationCode/CommandFileInterface/RicfExportSnapshots.cpp index bc3f8a6a46..430515db96 100644 --- a/ApplicationCode/CommandFileInterface/RicfExportSnapshots.cpp +++ b/ApplicationCode/CommandFileInterface/RicfExportSnapshots.cpp @@ -66,7 +66,7 @@ void RicfExportSnapshots::execute() RiuMainWindow* mainWnd = RiuMainWindow::instance(); CVF_ASSERT(mainWnd); - mainWnd->hideAllDockWindows(); + mainWnd->hideAllDockWidgets(); RiaGuiApplication::instance()->processEvents(); QString absolutePathToSnapshotDir = RicfCommandFileExecutor::instance()->getExportPath(RicfCommandFileExecutor::SNAPSHOTS); diff --git a/ApplicationCode/UserInterface/RiuDockWidgetTools.cpp b/ApplicationCode/UserInterface/RiuDockWidgetTools.cpp index 9bd51f29cc..b0b447bed4 100644 --- a/ApplicationCode/UserInterface/RiuDockWidgetTools.cpp +++ b/ApplicationCode/UserInterface/RiuDockWidgetTools.cpp @@ -235,15 +235,17 @@ void RiuDockWidgetTools::restoreDockWidgetsVisibility(const QObject* parent, QVa { if (dock) { - auto widgetVisibility = widgetVisibilityMap.find(dock->objectName()); + bool isVisible = true; + auto widgetVisibility = widgetVisibilityMap.find(dock->objectName()); if (widgetVisibility != widgetVisibilityMap.end()) { - bool isVisible = widgetVisibility.value().toBool(); - dock->setVisible(isVisible); - - // qDebug() << "Restore " << dock->objectName() << " : " << (isVisible ? "visible" : "not visible"); + isVisible = widgetVisibility.value().toBool(); } + + dock->setVisible(isVisible); + + // qDebug() << "Restore " << dock->objectName() << " : " << (isVisible ? "visible" : "not visible"); } } } diff --git a/ApplicationCode/UserInterface/RiuDockWidgetTools.h b/ApplicationCode/UserInterface/RiuDockWidgetTools.h index 613a39d977..341c539b54 100644 --- a/ApplicationCode/UserInterface/RiuDockWidgetTools.h +++ b/ApplicationCode/UserInterface/RiuDockWidgetTools.h @@ -54,10 +54,10 @@ public: static QVariant storeDockWidgetsVisibility(const QObject* parent); static void restoreDockWidgetsVisibility(const QObject* parent, QVariant widgetVisibilities); - static void setVisibleDockingWindowsForEclipse(); - static void setVisibleDockingWindowsForGeoMech(); + static void setVisibleDockingWindowsForEclipse(); + static void setVisibleDockingWindowsForGeoMech(); + static void trySetDockWidgetVisibility(const QObject* parent, const QString& dockWidgetName, bool isVisible); private: static QDockWidget* findDockWidget(const QObject* parent, const QString& dockWidgetName); - static void trySetDockWidgetVisibility(const QObject* parent, const QString& dockWidgetName, bool isVisible); }; diff --git a/ApplicationCode/UserInterface/RiuMainWindow.cpp b/ApplicationCode/UserInterface/RiuMainWindow.cpp index efd995ddc6..aa08af35c5 100644 --- a/ApplicationCode/UserInterface/RiuMainWindow.cpp +++ b/ApplicationCode/UserInterface/RiuMainWindow.cpp @@ -271,7 +271,7 @@ void RiuMainWindow::cleanupGuiBeforeProjectClose() void RiuMainWindow::closeEvent(QCloseEvent* event) { this->saveWinGeoAndDockToolBarLayout(); - this->hideAllDockWindows(); + this->hideAllDockWidgets(); RiaGuiApplication* app = RiaGuiApplication::instance(); if (app->isMainPlotWindowVisible()) @@ -1501,19 +1501,6 @@ void RiuMainWindow::slotSnapshotAllViewsToFile() RicSnapshotAllViewsToFileFeature::exportSnapshotOfAllViewsIntoFolder(absolutePathToSnapshotDir); } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuMainWindow::hideAllDockWindows() -{ - QList dockWidgets = findChildren(); - - for (auto* dockWidget : dockWidgets) - { - dockWidget->close(); - } -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -1675,25 +1662,6 @@ void RiuMainWindow::restoreTreeViewState() } } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuMainWindow::showDockPanel(const QString& dockPanelName) -{ - QList dockWidgets = findChildren(); - - foreach (QDockWidget* dock, dockWidgets) - { - if (dock && dock->objectName() == dockPanelName) - { - dock->show(); - dock->raise(); - - return; - } - } -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -1781,7 +1749,7 @@ void RiuMainWindow::updateMemoryUsage() //-------------------------------------------------------------------------------------------------- void RiuMainWindow::showProcessMonitorDockPanel() { - showDockPanel(RiuDockWidgetTools::processMonitorName()); + RiuDockWidgetTools::trySetDockWidgetVisibility(this, RiuDockWidgetTools::processMonitorName(), true); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/UserInterface/RiuMainWindow.h b/ApplicationCode/UserInterface/RiuMainWindow.h index e62fd33b4f..472b6ef297 100644 --- a/ApplicationCode/UserInterface/RiuMainWindow.h +++ b/ApplicationCode/UserInterface/RiuMainWindow.h @@ -99,9 +99,6 @@ public: RiuProcessMonitor* processMonitor(); - void hideAllDockWindows(); - - void selectedCases(std::vector& cases); void setDefaultWindowSize(); @@ -141,8 +138,6 @@ private: void restoreTreeViewState(); - void showDockPanel(const QString& dockPanelName); - void updateUiFieldsFromActiveResult(caf::PdmObjectHandle* objectToUpdate); private: diff --git a/ApplicationCode/UserInterface/RiuMainWindowBase.cpp b/ApplicationCode/UserInterface/RiuMainWindowBase.cpp index efa988bc1e..33c3e8e4e4 100644 --- a/ApplicationCode/UserInterface/RiuMainWindowBase.cpp +++ b/ApplicationCode/UserInterface/RiuMainWindowBase.cpp @@ -142,7 +142,7 @@ void RiuMainWindowBase::showWindow() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RiuMainWindowBase::closeAllDockWidgets() +void RiuMainWindowBase::hideAllDockWidgets() { QList dockWidgets = findChildren(); diff --git a/ApplicationCode/UserInterface/RiuMainWindowBase.h b/ApplicationCode/UserInterface/RiuMainWindowBase.h index 9acb072ab4..60d190478f 100644 --- a/ApplicationCode/UserInterface/RiuMainWindowBase.h +++ b/ApplicationCode/UserInterface/RiuMainWindowBase.h @@ -59,7 +59,7 @@ public: void restoreDockWidgetVisibilities(); void showWindow(); - void closeAllDockWidgets(); + void hideAllDockWidgets(); caf::PdmUiTreeView* projectTreeView() { return m_projectTreeView;} void setExpanded(const caf::PdmUiItem* uiItem, bool expanded = true); diff --git a/ApplicationCode/UserInterface/RiuPlotMainWindow.cpp b/ApplicationCode/UserInterface/RiuPlotMainWindow.cpp index 9a38536d35..6599646c1c 100644 --- a/ApplicationCode/UserInterface/RiuPlotMainWindow.cpp +++ b/ApplicationCode/UserInterface/RiuPlotMainWindow.cpp @@ -181,7 +181,7 @@ void RiuPlotMainWindow::closeEvent(QCloseEvent* event) { this->saveWinGeoAndDockToolBarLayout(); - this->hideAllDockWindows(); + this->hideAllDockWidgets(); RiaGuiApplication* app = RiaGuiApplication::instance(); @@ -769,19 +769,6 @@ void RiuPlotMainWindow::selectedObjectsChanged() } } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuPlotMainWindow::hideAllDockWindows() -{ - QList dockWidgets = findChildren(); - - for (int i = 0; i < dockWidgets.size(); i++) - { - dockWidgets[i]->close(); - } -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/UserInterface/RiuPlotMainWindow.h b/ApplicationCode/UserInterface/RiuPlotMainWindow.h index 7e19e9cd10..dc30696ddd 100644 --- a/ApplicationCode/UserInterface/RiuPlotMainWindow.h +++ b/ApplicationCode/UserInterface/RiuPlotMainWindow.h @@ -64,8 +64,6 @@ public: void addViewer(QWidget* viewer, const RimMdiWindowGeometry& windowsGeometry) override; void setActiveViewer(QWidget* subWindow) override; - void hideAllDockWindows(); - void setDefaultWindowSize(); void tileSubWindows() override; From a52afd7b34783660fd5cf3f1ccca70f6871915e9 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 15 May 2019 13:37:23 +0200 Subject: [PATCH 052/396] #4410 Dock Window State : Set default visibility of dock widgets --- .../Application/RiaGuiApplication.cpp | 1 + .../UserInterface/RiuDockWidgetTools.cpp | 96 ++++++++++++------- .../UserInterface/RiuDockWidgetTools.h | 12 ++- .../UserInterface/RiuMainWindow.cpp | 2 +- .../UserInterface/RiuMainWindowBase.cpp | 49 ++++++++-- .../UserInterface/RiuMainWindowBase.h | 1 + 6 files changed, 115 insertions(+), 46 deletions(-) diff --git a/ApplicationCode/Application/RiaGuiApplication.cpp b/ApplicationCode/Application/RiaGuiApplication.cpp index 1ecd5b2d88..17f3e2b4b2 100644 --- a/ApplicationCode/Application/RiaGuiApplication.cpp +++ b/ApplicationCode/Application/RiaGuiApplication.cpp @@ -1002,6 +1002,7 @@ void RiaGuiApplication::createMainWindow() m_mainWindow->setWindowTitle("ResInsight " + platform); m_mainWindow->setDefaultWindowSize(); m_mainWindow->setDefaultToolbarVisibility(); + m_mainWindow->storeDefaultDockWidgetVisibilitiesIfRequired(); m_mainWindow->loadWinGeoAndDockToolBarLayout(); m_mainWindow->showWindow(); } diff --git a/ApplicationCode/UserInterface/RiuDockWidgetTools.cpp b/ApplicationCode/UserInterface/RiuDockWidgetTools.cpp index b0b447bed4..8bf1e938fb 100644 --- a/ApplicationCode/UserInterface/RiuDockWidgetTools.cpp +++ b/ApplicationCode/UserInterface/RiuDockWidgetTools.cpp @@ -95,7 +95,7 @@ QString RiuDockWidgetTools::mohrsCirclePlotName() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QString RiuDockWidgetTools::plotMainWindowProjectTreeName() +QString RiuDockWidgetTools::plotMainWindowProjectTreeName() { return "plotMainWindow_dockProjectTree"; } @@ -103,7 +103,7 @@ QString RiuDockWidgetTools::plotMainWindowProjectTreeName() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QString RiuDockWidgetTools::plotMainWindowPropertyEditorName() +QString RiuDockWidgetTools::plotMainWindowPropertyEditorName() { return "plotMainWindow_dockPropertyEditor"; } @@ -116,6 +116,48 @@ QString RiuDockWidgetTools::messagesName() return "dockMessages"; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QMap RiuDockWidgetTools::widgetVisibilitiesForEclipse() +{ + QMap widgetVisibility; + + widgetVisibility[RiuDockWidgetTools::projectTreeName()] = true; + widgetVisibility[RiuDockWidgetTools::propertyEditorName()] = true; + widgetVisibility[RiuDockWidgetTools::resultInfoName()] = true; + widgetVisibility[RiuDockWidgetTools::processMonitorName()] = true; + widgetVisibility[RiuDockWidgetTools::resultPlotName()] = true; + widgetVisibility[RiuDockWidgetTools::relPermPlotName()] = true; + widgetVisibility[RiuDockWidgetTools::pvtPlotName()] = true; + widgetVisibility[RiuDockWidgetTools::messagesName()] = true; + + widgetVisibility[RiuDockWidgetTools::mohrsCirclePlotName()] = false; + + return widgetVisibility; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QMap RiuDockWidgetTools::widgetVisibilitiesForGeoMech() +{ + QMap widgetVisibility; + + widgetVisibility[RiuDockWidgetTools::projectTreeName()] = true; + widgetVisibility[RiuDockWidgetTools::propertyEditorName()] = true; + widgetVisibility[RiuDockWidgetTools::resultInfoName()] = true; + widgetVisibility[RiuDockWidgetTools::processMonitorName()] = true; + widgetVisibility[RiuDockWidgetTools::resultPlotName()] = true; + widgetVisibility[RiuDockWidgetTools::relPermPlotName()] = false; + widgetVisibility[RiuDockWidgetTools::pvtPlotName()] = false; + widgetVisibility[RiuDockWidgetTools::messagesName()] = true; + + widgetVisibility[RiuDockWidgetTools::mohrsCirclePlotName()] = true; + + return widgetVisibility; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -153,19 +195,10 @@ QAction* RiuDockWidgetTools::toggleActionForWidget(const QObject* parent, const //-------------------------------------------------------------------------------------------------- void RiuDockWidgetTools::setVisibleDockingWindowsForEclipse() { - RiuMainWindow* mainWindow = RiuMainWindow::instance(); + RiuMainWindow* mainWindow = RiuMainWindow::instance(); + auto widgetVisibilities = widgetVisibilitiesForEclipse(); - RiuDockWidgetTools::trySetDockWidgetVisibility(mainWindow, RiuDockWidgetTools::projectTreeName(), true); - RiuDockWidgetTools::trySetDockWidgetVisibility(mainWindow, RiuDockWidgetTools::propertyEditorName(), true); - RiuDockWidgetTools::trySetDockWidgetVisibility(mainWindow, RiuDockWidgetTools::resultInfoName(), true); - RiuDockWidgetTools::trySetDockWidgetVisibility(mainWindow, RiuDockWidgetTools::processMonitorName(), true); - RiuDockWidgetTools::trySetDockWidgetVisibility(mainWindow, RiuDockWidgetTools::resultPlotName(), true); - RiuDockWidgetTools::trySetDockWidgetVisibility(mainWindow, RiuDockWidgetTools::relPermPlotName(), true); - RiuDockWidgetTools::trySetDockWidgetVisibility(mainWindow, RiuDockWidgetTools::pvtPlotName(), true); - RiuDockWidgetTools::trySetDockWidgetVisibility(mainWindow, RiuDockWidgetTools::messagesName(), true); - - - RiuDockWidgetTools::trySetDockWidgetVisibility(mainWindow, RiuDockWidgetTools::mohrsCirclePlotName(), false); + applyDockWidgetVisibilities(mainWindow, widgetVisibilities); } //-------------------------------------------------------------------------------------------------- @@ -173,24 +206,16 @@ void RiuDockWidgetTools::setVisibleDockingWindowsForEclipse() //-------------------------------------------------------------------------------------------------- void RiuDockWidgetTools::setVisibleDockingWindowsForGeoMech() { - RiuMainWindow* mainWindow = RiuMainWindow::instance(); + RiuMainWindow* mainWindow = RiuMainWindow::instance(); + auto widgetVisibilities = widgetVisibilitiesForGeoMech(); - RiuDockWidgetTools::trySetDockWidgetVisibility(mainWindow, RiuDockWidgetTools::projectTreeName(), true); - RiuDockWidgetTools::trySetDockWidgetVisibility(mainWindow, RiuDockWidgetTools::propertyEditorName(), true); - RiuDockWidgetTools::trySetDockWidgetVisibility(mainWindow, RiuDockWidgetTools::resultInfoName(), true); - RiuDockWidgetTools::trySetDockWidgetVisibility(mainWindow, RiuDockWidgetTools::processMonitorName(), true); - RiuDockWidgetTools::trySetDockWidgetVisibility(mainWindow, RiuDockWidgetTools::resultPlotName(), true); - RiuDockWidgetTools::trySetDockWidgetVisibility(mainWindow, RiuDockWidgetTools::relPermPlotName(), false); - RiuDockWidgetTools::trySetDockWidgetVisibility(mainWindow, RiuDockWidgetTools::pvtPlotName(), false); - RiuDockWidgetTools::trySetDockWidgetVisibility(mainWindow, RiuDockWidgetTools::messagesName(), true); - - RiuDockWidgetTools::trySetDockWidgetVisibility(mainWindow, RiuDockWidgetTools::mohrsCirclePlotName(), true); + applyDockWidgetVisibilities(mainWindow, widgetVisibilities); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RiuDockWidgetTools::trySetDockWidgetVisibility(const QObject* parent, const QString& dockWidgetName, bool isVisible) +void RiuDockWidgetTools::setDockWidgetVisibility(const QObject* parent, const QString& dockWidgetName, bool isVisible) { QDockWidget* dockWidget = findDockWidget(parent, dockWidgetName); if (dockWidget) @@ -202,7 +227,7 @@ void RiuDockWidgetTools::trySetDockWidgetVisibility(const QObject* parent, const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QVariant RiuDockWidgetTools::storeDockWidgetsVisibility(const QObject* parent) +QVariant RiuDockWidgetTools::dockWidgetsVisibility(const QObject* parent) { QMap widgetVisibility; @@ -212,7 +237,7 @@ QVariant RiuDockWidgetTools::storeDockWidgetsVisibility(const QObject* parent) { if (dock) { - bool isVisible = dock->isVisible(); + bool isVisible = dock->isVisible(); widgetVisibility[dock->objectName()] = isVisible; // qDebug() << "Store " << dock->objectName() << " : " << (isVisible ? "visible" : "not visible"); @@ -225,10 +250,16 @@ QVariant RiuDockWidgetTools::storeDockWidgetsVisibility(const QObject* parent) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RiuDockWidgetTools::restoreDockWidgetsVisibility(const QObject* parent, QVariant widgetVisibilities) +QVariant RiuDockWidgetTools::defaultDockWidgetVisibilities() { - QMap widgetVisibilityMap = widgetVisibilities.toMap(); + return QVariant(widgetVisibilitiesForEclipse()); +} +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuDockWidgetTools::applyDockWidgetVisibilities(const QObject* parent, const QMap& widgetVisibilities) +{ QList dockWidgets = parent->findChildren(); for (QDockWidget* dock : dockWidgets) @@ -237,8 +268,8 @@ void RiuDockWidgetTools::restoreDockWidgetsVisibility(const QObject* parent, QVa { bool isVisible = true; - auto widgetVisibility = widgetVisibilityMap.find(dock->objectName()); - if (widgetVisibility != widgetVisibilityMap.end()) + auto widgetVisibility = widgetVisibilities.find(dock->objectName()); + if (widgetVisibility != widgetVisibilities.end()) { isVisible = widgetVisibility.value().toBool(); } @@ -249,4 +280,3 @@ void RiuDockWidgetTools::restoreDockWidgetsVisibility(const QObject* parent, QVa } } } - diff --git a/ApplicationCode/UserInterface/RiuDockWidgetTools.h b/ApplicationCode/UserInterface/RiuDockWidgetTools.h index 341c539b54..26f16b6509 100644 --- a/ApplicationCode/UserInterface/RiuDockWidgetTools.h +++ b/ApplicationCode/UserInterface/RiuDockWidgetTools.h @@ -51,13 +51,19 @@ public: static QAction* toggleActionForWidget(const QObject* parent, const QString& dockWidgetName); - static QVariant storeDockWidgetsVisibility(const QObject* parent); - static void restoreDockWidgetsVisibility(const QObject* parent, QVariant widgetVisibilities); + static QVariant dockWidgetsVisibility(const QObject* parent); + static QVariant defaultDockWidgetVisibilities(); static void setVisibleDockingWindowsForEclipse(); static void setVisibleDockingWindowsForGeoMech(); - static void trySetDockWidgetVisibility(const QObject* parent, const QString& dockWidgetName, bool isVisible); + + static void setDockWidgetVisibility(const QObject* parent, const QString& dockWidgetName, bool isVisible); + static void applyDockWidgetVisibilities(const QObject* parent, const QMap& visibilityMap); private: + static QMap widgetVisibilitiesForEclipse(); + static QMap widgetVisibilitiesForGeoMech(); + + static QDockWidget* findDockWidget(const QObject* parent, const QString& dockWidgetName); }; diff --git a/ApplicationCode/UserInterface/RiuMainWindow.cpp b/ApplicationCode/UserInterface/RiuMainWindow.cpp index aa08af35c5..dc2ba5afcb 100644 --- a/ApplicationCode/UserInterface/RiuMainWindow.cpp +++ b/ApplicationCode/UserInterface/RiuMainWindow.cpp @@ -1749,7 +1749,7 @@ void RiuMainWindow::updateMemoryUsage() //-------------------------------------------------------------------------------------------------- void RiuMainWindow::showProcessMonitorDockPanel() { - RiuDockWidgetTools::trySetDockWidgetVisibility(this, RiuDockWidgetTools::processMonitorName(), true); + RiuDockWidgetTools::setDockWidgetVisibility(this, RiuDockWidgetTools::processMonitorName(), true); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/UserInterface/RiuMainWindowBase.cpp b/ApplicationCode/UserInterface/RiuMainWindowBase.cpp index 33c3e8e4e4..4d04ff8272 100644 --- a/ApplicationCode/UserInterface/RiuMainWindowBase.cpp +++ b/ApplicationCode/UserInterface/RiuMainWindowBase.cpp @@ -24,8 +24,8 @@ #include "RiuDockWidgetTools.h" #include "RiuMdiSubWindow.h" -#include "RimViewWindow.h" #include "RimProject.h" +#include "RimViewWindow.h" #include "cafPdmObject.h" #include "cafPdmUiTreeView.h" @@ -87,6 +87,16 @@ void RiuMainWindowBase::loadWinGeoAndDockToolBarLayout() restoreDockWidgetVisibilities(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString mainWindowDockWidgetSettingsKey(const QString& settingsFolderName) +{ + QString key = settingsFolderName + "/dockWindowVisibilies"; + + return key; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -102,24 +112,44 @@ void RiuMainWindowBase::saveWinGeoAndDockToolBarLayout() settings.setValue(QString("%1/dockAndToolBarLayout").arg(registryFolderName()), layout); settings.setValue(QString("%1/isMaximized").arg(registryFolderName()), isMaximized()); - + if (this->isVisible()) { - QVariant dockWindowVisibilities = RiuDockWidgetTools::storeDockWidgetsVisibility(this); - settings.setValue(QString("%1/dockWindowVisibilies").arg(registryFolderName()), dockWindowVisibilities); + QVariant dockWindowVisibilities = RiuDockWidgetTools::dockWidgetsVisibility(this); + QString key = mainWindowDockWidgetSettingsKey(registryFolderName()); + + settings.setValue(key, dockWindowVisibilities); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RiuMainWindowBase::restoreDockWidgetVisibilities() +void RiuMainWindowBase::storeDefaultDockWidgetVisibilitiesIfRequired() +{ + QSettings settings; + + QString key = mainWindowDockWidgetSettingsKey(registryFolderName()); + + if (!settings.contains(key)) + { + QVariant dockWidgetVisibilities = RiuDockWidgetTools::defaultDockWidgetVisibilities(); + settings.setValue(key, dockWidgetVisibilities); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuMainWindowBase::restoreDockWidgetVisibilities() { // Company and appname set through QCoreApplication QSettings settings; - QVariant dockWindowVisibilities = settings.value(QString("%1/dockWindowVisibilies").arg(registryFolderName())); - RiuDockWidgetTools::restoreDockWidgetsVisibility(this, dockWindowVisibilities); + QString key = mainWindowDockWidgetSettingsKey(registryFolderName()); + + QVariant dockWindowVisibilities = settings.value(key); + RiuDockWidgetTools::applyDockWidgetVisibilities(this, dockWindowVisibilities.toMap()); } //-------------------------------------------------------------------------------------------------- @@ -142,7 +172,7 @@ void RiuMainWindowBase::showWindow() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RiuMainWindowBase::hideAllDockWidgets() +void RiuMainWindowBase::hideAllDockWidgets() { QList dockWidgets = findChildren(); @@ -272,7 +302,8 @@ void RiuMainWindowBase::addViewerToMdiArea(QMdiArea* mdiArea, const QPoint& subWindowPos, const QSize& subWindowSize) { - RiuMdiSubWindow* subWin = new RiuMdiSubWindow(nullptr, Qt::CustomizeWindowHint | Qt::WindowCloseButtonHint | Qt::WindowMaximizeButtonHint); + RiuMdiSubWindow* subWin = + new RiuMdiSubWindow(nullptr, Qt::CustomizeWindowHint | Qt::WindowCloseButtonHint | Qt::WindowMaximizeButtonHint); subWin->setAttribute(Qt::WA_DeleteOnClose); // Make sure the contained widget is destroyed when the MDI window is closed subWin->setWidget(viewer); diff --git a/ApplicationCode/UserInterface/RiuMainWindowBase.h b/ApplicationCode/UserInterface/RiuMainWindowBase.h index 60d190478f..34623f9395 100644 --- a/ApplicationCode/UserInterface/RiuMainWindowBase.h +++ b/ApplicationCode/UserInterface/RiuMainWindowBase.h @@ -56,6 +56,7 @@ public: RimMdiWindowGeometry windowGeometryForViewer(QWidget* viewer); void loadWinGeoAndDockToolBarLayout(); void saveWinGeoAndDockToolBarLayout(); + void storeDefaultDockWidgetVisibilitiesIfRequired(); void restoreDockWidgetVisibilities(); void showWindow(); From bfe8e7176a6f195b9ffebc070974f12efbc3c315 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 15 May 2019 13:54:05 +0200 Subject: [PATCH 053/396] #4410 Dock Window State : Restore dock widgets when opening main window --- .../Tools/RiaImportEclipseCaseTools.cpp | 7 ++- .../RicShowMainWindowFeature.cpp | 49 ++++++++++--------- .../RicShowMainWindowFeature.h | 3 ++ 3 files changed, 35 insertions(+), 24 deletions(-) diff --git a/ApplicationCode/Application/Tools/RiaImportEclipseCaseTools.cpp b/ApplicationCode/Application/Tools/RiaImportEclipseCaseTools.cpp index e4f477854d..be713ee899 100644 --- a/ApplicationCode/Application/Tools/RiaImportEclipseCaseTools.cpp +++ b/ApplicationCode/Application/Tools/RiaImportEclipseCaseTools.cpp @@ -18,6 +18,8 @@ #include "RiaImportEclipseCaseTools.h" +#include "ApplicationCommands/RicShowMainWindowFeature.h" + #include "SummaryPlotCommands/RicNewSummaryPlotFeature.h" #include "SummaryPlotCommands/RicNewSummaryCurveFeature.h" @@ -275,7 +277,10 @@ bool RiaImportEclipseCaseTools::openEclipseCaseShowTimeStepFilterImpl(const QStr return false; } - RiuMainWindow::instance()->show(); + if (RiaGuiApplication::isRunning()) + { + RicShowMainWindowFeature::showMainWindow(); + } analysisModels->cases.push_back(rimResultReservoir); diff --git a/ApplicationCode/Commands/ApplicationCommands/RicShowMainWindowFeature.cpp b/ApplicationCode/Commands/ApplicationCommands/RicShowMainWindowFeature.cpp index 211f9e322e..9052ec5cae 100644 --- a/ApplicationCode/Commands/ApplicationCommands/RicShowMainWindowFeature.cpp +++ b/ApplicationCode/Commands/ApplicationCommands/RicShowMainWindowFeature.cpp @@ -1,17 +1,17 @@ ///////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2016 Statoil ASA -// +// // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// +// // ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. -// -// See the GNU General Public License at +// +// See the GNU General Public License at // for more details. // ///////////////////////////////////////////////////////////////////////////////// @@ -27,24 +27,12 @@ CAF_CMD_SOURCE_INIT(RicShowMainWindowFeature, "RicShowMainWindowFeature"); //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- -bool RicShowMainWindowFeature::isCommandEnabled() +void RicShowMainWindowFeature::showMainWindow() { - return true; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RicShowMainWindowFeature::onActionTriggered(bool isChecked) -{ - this->disableModelChangeContribution(); - RiuMainWindow* mainWnd = RiuMainWindow::instance(); - bool triggerReloadOfDockWindowVisibilities = !mainWnd->isVisible(); - if (mainWnd->isMinimized()) { mainWnd->showNormal(); @@ -57,14 +45,29 @@ void RicShowMainWindowFeature::onActionTriggered(bool isChecked) mainWnd->raise(); - if (triggerReloadOfDockWindowVisibilities) - { - mainWnd->restoreDockWidgetVisibilities(); - } + mainWnd->restoreDockWidgetVisibilities(); } //-------------------------------------------------------------------------------------------------- -/// +/// +//-------------------------------------------------------------------------------------------------- +bool RicShowMainWindowFeature::isCommandEnabled() +{ + return true; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicShowMainWindowFeature::onActionTriggered(bool isChecked) +{ + this->disableModelChangeContribution(); + + RicShowMainWindowFeature::showMainWindow(); +} + +//-------------------------------------------------------------------------------------------------- +/// //-------------------------------------------------------------------------------------------------- void RicShowMainWindowFeature::setupActionLook(QAction* actionToSetup) { diff --git a/ApplicationCode/Commands/ApplicationCommands/RicShowMainWindowFeature.h b/ApplicationCode/Commands/ApplicationCommands/RicShowMainWindowFeature.h index 611ba8a3e8..4d7a17edfb 100644 --- a/ApplicationCode/Commands/ApplicationCommands/RicShowMainWindowFeature.h +++ b/ApplicationCode/Commands/ApplicationCommands/RicShowMainWindowFeature.h @@ -28,6 +28,9 @@ class RicShowMainWindowFeature : public caf::CmdFeature { CAF_CMD_HEADER_INIT; +public: + static void showMainWindow(); + protected: // Overrides bool isCommandEnabled() override; From 922386c673f0cfedc2a4c79ec715dd4a636a9aec Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Mon, 20 May 2019 13:21:02 +0200 Subject: [PATCH 054/396] #4416 First implementation of gRPC-based Python interface First implementation with Asynchronous gRPC server, a few services and some client python code. --- ApplicationCode/Adm/RiaVersionInfo.h.cmake | 4 + ApplicationCode/Adm/RiaVersionInfo.py.cmake | 21 + .../Application/RiaApplication.cpp | 30 ++ ApplicationCode/Application/RiaApplication.h | 15 +- .../Application/RiaConsoleApplication.cpp | 10 + .../Application/RiaConsoleApplication.h | 2 +- ApplicationCode/Application/RiaDefines.h | 9 + .../Application/RiaGuiApplication.cpp | 65 +++- .../Application/RiaGuiApplication.h | 14 +- ApplicationCode/Application/RiaMain.cpp | 9 +- .../Application/RiaPreferences.cpp | 11 +- ApplicationCode/Application/RiaPreferences.h | 3 + .../Application/Tools/RiaArgumentParser.cpp | 1 + ApplicationCode/CMakeLists.txt | 63 ++- .../CommandFileInterface/RicfSetTimeStep.cpp | 17 + .../CommandFileInterface/RicfSetTimeStep.h | 4 + .../RicEditPreferencesFeature.cpp | 1 + .../GrpcInterface/CMakeLists.cmake | 158 ++++++++ .../GrpcInterface/GrpcProtos/CaseInfo.proto | 31 ++ .../GrpcInterface/GrpcProtos/Commands.proto | 60 +++ .../GrpcInterface/GrpcProtos/Empty.proto | 7 + .../GrpcInterface/GrpcProtos/GridInfo.proto | 89 +++++ .../GrpcProtos/ProjectInfo.proto | 16 + .../GrpcInterface/GrpcProtos/ResInfo.proto | 15 + .../GrpcInterface/RiaGrpcCallbacks.h | 173 +++++++++ .../GrpcInterface/RiaGrpcCallbacks.inl | 239 ++++++++++++ .../GrpcInterface/RiaGrpcCommandService.cpp | 155 ++++++++ .../GrpcInterface/RiaGrpcCommandService.h | 58 +++ .../GrpcInterface/RiaGrpcGridInfoService.cpp | 283 ++++++++++++++ .../GrpcInterface/RiaGrpcGridInfoService.h | 80 ++++ .../RiaGrpcProjectInfoService.cpp | 249 ++++++++++++ .../GrpcInterface/RiaGrpcProjectInfoService.h | 51 +++ .../GrpcInterface/RiaGrpcResInfoService.cpp | 44 +++ .../GrpcInterface/RiaGrpcResInfoService.h | 50 +++ .../GrpcInterface/RiaGrpcServer.cpp | 366 ++++++++++++++++++ ApplicationCode/GrpcInterface/RiaGrpcServer.h | 53 +++ .../GrpcInterface/RiaGrpcServiceInterface.cpp | 54 +++ .../GrpcInterface/RiaGrpcServiceInterface.h | 43 ++ .../ReservoirDataModel/RigFlowDiagResults.cpp | 2 +- .../cafUserInterface/cafProgressInfo.cpp | 12 +- Fwk/AppFwk/cafUserInterface/cafProgressInfo.h | 4 +- GRPC_install_instructions.txt | 33 ++ Python/.gitignore | 3 + Python/api/ResInsight.py | 159 ++++++++ Python/api/__init__.py | 0 Python/examples/AllCases.py | 13 + Python/examples/CommandExample.py | 11 + Python/examples/GridInfoStreamingExample.py | 21 + Python/examples/ResultValues.py | 45 +++ Python/examples/SelectedCases.py | 14 + Python/tests/test_sample.py | 51 +++ 51 files changed, 2894 insertions(+), 27 deletions(-) create mode 100644 ApplicationCode/Adm/RiaVersionInfo.py.cmake create mode 100644 ApplicationCode/GrpcInterface/CMakeLists.cmake create mode 100644 ApplicationCode/GrpcInterface/GrpcProtos/CaseInfo.proto create mode 100644 ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto create mode 100644 ApplicationCode/GrpcInterface/GrpcProtos/Empty.proto create mode 100644 ApplicationCode/GrpcInterface/GrpcProtos/GridInfo.proto create mode 100644 ApplicationCode/GrpcInterface/GrpcProtos/ProjectInfo.proto create mode 100644 ApplicationCode/GrpcInterface/GrpcProtos/ResInfo.proto create mode 100644 ApplicationCode/GrpcInterface/RiaGrpcCallbacks.h create mode 100644 ApplicationCode/GrpcInterface/RiaGrpcCallbacks.inl create mode 100644 ApplicationCode/GrpcInterface/RiaGrpcCommandService.cpp create mode 100644 ApplicationCode/GrpcInterface/RiaGrpcCommandService.h create mode 100644 ApplicationCode/GrpcInterface/RiaGrpcGridInfoService.cpp create mode 100644 ApplicationCode/GrpcInterface/RiaGrpcGridInfoService.h create mode 100644 ApplicationCode/GrpcInterface/RiaGrpcProjectInfoService.cpp create mode 100644 ApplicationCode/GrpcInterface/RiaGrpcProjectInfoService.h create mode 100644 ApplicationCode/GrpcInterface/RiaGrpcResInfoService.cpp create mode 100644 ApplicationCode/GrpcInterface/RiaGrpcResInfoService.h create mode 100644 ApplicationCode/GrpcInterface/RiaGrpcServer.cpp create mode 100644 ApplicationCode/GrpcInterface/RiaGrpcServer.h create mode 100644 ApplicationCode/GrpcInterface/RiaGrpcServiceInterface.cpp create mode 100644 ApplicationCode/GrpcInterface/RiaGrpcServiceInterface.h create mode 100644 GRPC_install_instructions.txt create mode 100644 Python/.gitignore create mode 100644 Python/api/ResInsight.py create mode 100644 Python/api/__init__.py create mode 100644 Python/examples/AllCases.py create mode 100644 Python/examples/CommandExample.py create mode 100644 Python/examples/GridInfoStreamingExample.py create mode 100644 Python/examples/ResultValues.py create mode 100644 Python/examples/SelectedCases.py create mode 100644 Python/tests/test_sample.py diff --git a/ApplicationCode/Adm/RiaVersionInfo.h.cmake b/ApplicationCode/Adm/RiaVersionInfo.h.cmake index c638ee4fd7..befafb8ef0 100644 --- a/ApplicationCode/Adm/RiaVersionInfo.h.cmake +++ b/ApplicationCode/Adm/RiaVersionInfo.h.cmake @@ -27,4 +27,8 @@ #define PRODUCTVER "@PRODUCTVER@" #define STRPRODUCTVER "@STRPRODUCTVER@" +#define RESINSIGHT_MAJOR_VERSION @RESINSIGHT_MAJOR_VERSION@ +#define RESINSIGHT_MINOR_VERSION @RESINSIGHT_MINOR_VERSION@ +#define RESINSIGHT_PATCH_VERSION @RESINSIGHT_PATCH_VERSION@ + #define RESINSIGHT_OCTAVE_VERSION "@OCTAVE_VERSION_STRING@" diff --git a/ApplicationCode/Adm/RiaVersionInfo.py.cmake b/ApplicationCode/Adm/RiaVersionInfo.py.cmake new file mode 100644 index 0000000000..65841a4f1b --- /dev/null +++ b/ApplicationCode/Adm/RiaVersionInfo.py.cmake @@ -0,0 +1,21 @@ +# +# Copyright (C) 2019- 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. +# +# Python version of RiaVersionInfo.h +# Just sets version constants + +RESINSIGHT_MAJOR_VERSION = "@RESINSIGHT_MAJOR_VERSION@" +RESINSIGHT_MINOR_VERSION = "@RESINSIGHT_MINOR_VERSION@" +RESINSIGHT_PATCH_VERSION = "@RESINSIGHT_PATCH_VERSION@" diff --git a/ApplicationCode/Application/RiaApplication.cpp b/ApplicationCode/Application/RiaApplication.cpp index b1494ec9e1..4621e587bd 100644 --- a/ApplicationCode/Application/RiaApplication.cpp +++ b/ApplicationCode/Application/RiaApplication.cpp @@ -1292,6 +1292,36 @@ cvf::Font* RiaApplication::defaultWellLabelFont() return m_defaultWellLabelFont.p(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RiaApplication::initializeGrpcServer(const cvf::ProgramOptions& progOpt) +{ +#ifdef ENABLE_GRPC + if (!m_preferences->enableGrpcServer()) return false; + + int defaultPortNumber = m_preferences->defaultGrpcPortNumber(); + bool fixedPort = false; + if (cvf::Option o = progOpt.option("grpcserver")) + { + if (o.valueCount() == 1) + { + defaultPortNumber = o.value(0).toInt(defaultPortNumber); + fixedPort = true; + } + } + int portNumber = defaultPortNumber; + if (!fixedPort) + { + portNumber = RiaGrpcServer::findAvailablePortNumber(defaultPortNumber); + } + m_grpcServer.reset(new RiaGrpcServer(portNumber)); + return true; +#else + return false; +#endif +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/Application/RiaApplication.h b/ApplicationCode/Application/RiaApplication.h index 227b0b55c6..81660a925a 100644 --- a/ApplicationCode/Application/RiaApplication.h +++ b/ApplicationCode/Application/RiaApplication.h @@ -20,6 +20,9 @@ #pragma once #include "RiaDefines.h" +#ifdef ENABLE_GRPC +#include "RiaGrpcServer.h" +#endif #include "cafPdmField.h" #include "cafPdmObject.h" @@ -93,7 +96,7 @@ public: EXIT_COMPLETED, EXIT_WITH_ERROR }; - + public: static RiaApplication* instance(); RiaApplication(); @@ -171,6 +174,8 @@ public: cvf::Font* defaultAnnotationFont(); cvf::Font* defaultWellLabelFont(); + bool initializeGrpcServer(const cvf::ProgramOptions& progOpt); + // Public implementation specific overrides virtual void initialize(); virtual ApplicationStatus handleArguments(cvf::ProgramOptions* progOpt) = 0; @@ -178,8 +183,7 @@ public: virtual void addToRecentFiles(const QString& fileName) {} virtual void showInformationMessage(const QString& infoText) = 0; virtual void showErrorMessage(const QString& errMsg) = 0; - virtual void cleanupBeforeProgramExit() {} - + virtual void launchGrpcServer() = 0; protected: // Protected implementation specific overrides virtual void invokeProcessEvents(QEventLoop::ProcessEventsFlags flags = QEventLoop::AllEvents) = 0; @@ -203,11 +207,14 @@ protected: RiaSocketServer* m_socketServer; caf::UiProcess* m_workerProcess; +#ifdef ENABLE_GRPC + std::unique_ptr m_grpcServer; +#endif + // Execute for all settings std::list m_currentCaseIds; QString m_currentProgram; QStringList m_currentArguments; - RiaPreferences* m_preferences; std::map m_fileDialogDefaultDirectories; diff --git a/ApplicationCode/Application/RiaConsoleApplication.cpp b/ApplicationCode/Application/RiaConsoleApplication.cpp index 23f965d6e8..9a0f316fbd 100644 --- a/ApplicationCode/Application/RiaConsoleApplication.cpp +++ b/ApplicationCode/Application/RiaConsoleApplication.cpp @@ -339,6 +339,16 @@ void RiaConsoleApplication::showErrorMessage(const QString& errMsg) RiaLogging::error(errMsg); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaConsoleApplication::launchGrpcServer() +{ +#ifdef ENABLE_GRPC + m_grpcServer->run(); +#endif +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/Application/RiaConsoleApplication.h b/ApplicationCode/Application/RiaConsoleApplication.h index 006512a138..77100d4ab8 100644 --- a/ApplicationCode/Application/RiaConsoleApplication.h +++ b/ApplicationCode/Application/RiaConsoleApplication.h @@ -41,7 +41,7 @@ public: ApplicationStatus handleArguments(cvf::ProgramOptions* progOpt) override; void showInformationMessage(const QString& text) override; void showErrorMessage(const QString& errMsg) override; - + void launchGrpcServer() override; protected: // Protected implementation specific overrides void invokeProcessEvents(QEventLoop::ProcessEventsFlags flags = QEventLoop::AllEvents) override; diff --git a/ApplicationCode/Application/RiaDefines.h b/ApplicationCode/Application/RiaDefines.h index 968e80b337..653da2ee5c 100644 --- a/ApplicationCode/Application/RiaDefines.h +++ b/ApplicationCode/Application/RiaDefines.h @@ -170,6 +170,15 @@ namespace RiaDefines ImportFileType obtainFileTypeFromFileName(const QString& fileName); QString defaultDirectoryLabel(ImportFileType fileTypes); + enum CaseType + { + ECLIPSE_RESULT_CASE = 1, + ECLIPSE_INPUT_CASE = 2, + ECLIPSE_STAT_CASE = 3, + ECLIPSE_SOURCE_CASE = 4, + GEOMECH_ODB_CASE = 5 + }; + enum FontSettingType { SCENE_FONT, diff --git a/ApplicationCode/Application/RiaGuiApplication.cpp b/ApplicationCode/Application/RiaGuiApplication.cpp index 17f3e2b4b2..f5bdd0f50f 100644 --- a/ApplicationCode/Application/RiaGuiApplication.cpp +++ b/ApplicationCode/Application/RiaGuiApplication.cpp @@ -178,13 +178,11 @@ RiaGuiApplication::RiaGuiApplication(int& argc, char** argv) , m_mainWindow(nullptr) , m_mainPlotWindow(nullptr) { - // For idle processing - // m_idleTimerStarted = false; - installEventFilter(this); - setWindowIcon(QIcon(":/AppLogo48x48.png")); m_recentFileActionProvider = std::unique_ptr(new RiuRecentFileActionProvider); + + connect(this, SIGNAL(aboutToQuit()), this, SLOT(onProgramExit())); } //-------------------------------------------------------------------------------------------------- @@ -571,8 +569,8 @@ void RiaGuiApplication::initialize() RiaLogging::setLoggerInstance(new RiuMessagePanelLogger(m_mainWindow->messagePanel())); RiaLogging::loggerInstance()->setLevel(RI_LL_DEBUG); - m_socketServer = new RiaSocketServer(this); + } //-------------------------------------------------------------------------------------------------- @@ -1231,6 +1229,19 @@ void RiaGuiApplication::showErrorMessage(const QString& errMsg) errDialog.showMessage(errMsg); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaGuiApplication::launchGrpcServer() +{ +#ifdef ENABLE_GRPC + m_grpcServer->runInThread(); + m_idleTimer = new QTimer(this); + connect(m_idleTimer, SIGNAL(timeout()), this, SLOT(runIdleProcessing())); + m_idleTimer->start(0); +#endif +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -1367,10 +1378,14 @@ void RiaGuiApplication::onProjectClosed() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RiaGuiApplication::cleanupBeforeProgramExit() +void RiaGuiApplication::onProgramExit() { - closeAllWindows(); - invokeProcessEvents(); +#ifdef ENABLE_GRPC + if (m_grpcServer) + { + m_grpcServer->quit(); + } +#endif } //-------------------------------------------------------------------------------------------------- @@ -1575,6 +1590,27 @@ void RiaGuiApplication::applyGuiPreferences(const RiaPreferences* oldPreferences caf::PdmUiItem::enableExtraDebugText(m_preferences->appendFieldKeywordToToolTipText()); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaGuiApplication::updateGrpcServer() +{ +#ifdef ENABLE_GRPC + bool isGrpcRunning = m_grpcServer != nullptr && m_grpcServer->isRunning(); + bool shouldItBeRunning = m_preferences->enableGrpcServer(); + if (isGrpcRunning && !shouldItBeRunning) + { + m_grpcServer->quit(); + } + else if (!isGrpcRunning && shouldItBeRunning) + { + int portNumber = RiaGrpcServer::findAvailablePortNumber(m_preferences->defaultGrpcPortNumber()); + m_grpcServer.reset(new RiaGrpcServer(portNumber)); + m_grpcServer->runInThread(); + } +#endif +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -1637,6 +1673,19 @@ void RiaGuiApplication::slotWorkerProcessFinished(int exitCode, QProcess::ExitSt } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaGuiApplication::runIdleProcessing() +{ +#ifdef ENABLE_GRPC + if (!caf::ProgressInfoStatic::isRunning()) + { + m_grpcServer->processOneRequest(); + } +#endif +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/Application/RiaGuiApplication.h b/ApplicationCode/Application/RiaGuiApplication.h index 10a5f1d8e8..725d3f3db8 100644 --- a/ApplicationCode/Application/RiaGuiApplication.h +++ b/ApplicationCode/Application/RiaGuiApplication.h @@ -28,8 +28,10 @@ #include #include +#include #include #include +#include #include #include @@ -121,6 +123,7 @@ public: static void clearAllSelections(); void applyGuiPreferences(const RiaPreferences* oldPreferences = nullptr); + void updateGrpcServer(); // Public RiaApplication overrides void initialize() override; @@ -129,7 +132,7 @@ public: void addToRecentFiles(const QString& fileName) override; void showInformationMessage(const QString& text) override; void showErrorMessage(const QString& errMsg) override; - void cleanupBeforeProgramExit() override; + void launchGrpcServer() override; protected: // Protected RiaApplication overrides void invokeProcessEvents(QEventLoop::ProcessEventsFlags flags = QEventLoop::AllEvents) override; @@ -142,7 +145,7 @@ protected: void startMonitoringWorkProgress(caf::UiProcess* uiProcess) override; void stopMonitoringWorkProgress() override; -private: +private: void setWindowCaptionFromAppState(); void createMainWindow(); @@ -159,11 +162,16 @@ private: private slots: void slotWorkerProcessFinished(int exitCode, QProcess::ExitStatus exitStatus); + void runIdleProcessing(); + void onProgramExit(); private: RiuMainWindow* m_mainWindow; RiuPlotMainWindow* m_mainPlotWindow; - +#ifdef ENABLE_GRPC + QPointer m_idleTimer; +#endif + std::unique_ptr m_recentFileActionProvider; std::unique_ptr m_maximizeWindowGuard; diff --git a/ApplicationCode/Application/RiaMain.cpp b/ApplicationCode/Application/RiaMain.cpp index 6fee7d145b..18fefb4f09 100644 --- a/ApplicationCode/Application/RiaMain.cpp +++ b/ApplicationCode/Application/RiaMain.cpp @@ -41,11 +41,11 @@ int main(int argc, char *argv[]) RiaLogging::loggerInstance()->setLevel(RI_LL_DEBUG); std::unique_ptr app (createApplication(argc, argv)); - app->initialize(); cvf::ProgramOptions progOpt; + bool result = RiaArgumentParser::parseArguments(&progOpt); - bool result = RiaArgumentParser::parseArguments(&progOpt); + app->initialize(); if (!result) { @@ -60,7 +60,6 @@ int main(int argc, char *argv[]) app->showErrorMessage(RiaApplication::commandLineParameterHelp() + cvfqt::Utils::toQString(usageText) + unknownOptionsText.join("\n")); - app->cleanupBeforeProgramExit(); if (dynamic_cast(app.get()) == nullptr) { return 1; @@ -84,6 +83,10 @@ int main(int argc, char *argv[]) int exitCode = 0; try { + if (app->initializeGrpcServer(progOpt)) + { + app->launchGrpcServer(); + } exitCode = QCoreApplication::instance()->exec(); } catch (std::exception& exep ) diff --git a/ApplicationCode/Application/RiaPreferences.cpp b/ApplicationCode/Application/RiaPreferences.cpp index 1e6d595aed..ef2d39b419 100644 --- a/ApplicationCode/Application/RiaPreferences.cpp +++ b/ApplicationCode/Application/RiaPreferences.cpp @@ -51,6 +51,9 @@ RiaPreferences::RiaPreferences(void) { CAF_PDM_InitField(&navigationPolicy, "navigationPolicy", caf::AppEnum(RiaGuiApplication::NAVIGATION_POLICY_RMS), "Navigation Mode", "", "", ""); + CAF_PDM_InitField(&enableGrpcServer, "enableGrpcServer", true, "Enable gRPC script server", "", "Remote Procedure Call Scripting Engine", ""); + CAF_PDM_InitField(&defaultGrpcPortNumber, "defaultGrpcPort", 50051, "Default gRPC port", "", "", ""); + CAF_PDM_InitFieldNoDefault(&scriptDirectories, "scriptDirectory", "Shared Script Folder(s)", "", "", ""); scriptDirectories.uiCapability()->setUiEditorTypeName(caf::PdmUiFilePathEditor::uiEditorTypeName()); @@ -129,7 +132,7 @@ RiaPreferences::RiaPreferences(void) m_tabNames << "General"; m_tabNames << "Eclipse"; - m_tabNames << "Octave"; + m_tabNames << "Scripting"; if (RiaApplication::enableDevelopmentFeatures()) { m_tabNames << "System"; @@ -245,6 +248,12 @@ void RiaPreferences::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& } else if (uiConfigName == m_tabNames[2]) { +#ifdef ENABLE_GRPC + caf::PdmUiGroup* grpcGroup = uiOrdering.addNewGroup("gRPC Server"); + grpcGroup->add(&enableGrpcServer); + grpcGroup->add(&defaultGrpcPortNumber); +#endif + caf::PdmUiGroup* octaveGroup = uiOrdering.addNewGroup("Octave"); octaveGroup->add(&octaveExecutable); octaveGroup->add(&octaveShowHeaderInfoWhenExecutingScripts); diff --git a/ApplicationCode/Application/RiaPreferences.h b/ApplicationCode/Application/RiaPreferences.h index 36e5b10e6d..bbbab6108f 100644 --- a/ApplicationCode/Application/RiaPreferences.h +++ b/ApplicationCode/Application/RiaPreferences.h @@ -68,6 +68,9 @@ public: public: // Pdm Fields caf::PdmField > navigationPolicy; + caf::PdmField enableGrpcServer; + caf::PdmField defaultGrpcPortNumber; + caf::PdmField scriptDirectories; caf::PdmField scriptEditorExecutable; diff --git a/ApplicationCode/Application/Tools/RiaArgumentParser.cpp b/ApplicationCode/Application/Tools/RiaArgumentParser.cpp index 0e4f44e70e..4d100532c0 100644 --- a/ApplicationCode/Application/Tools/RiaArgumentParser.cpp +++ b/ApplicationCode/Application/Tools/RiaArgumentParser.cpp @@ -56,6 +56,7 @@ bool RiaArgumentParser::parseArguments(cvf::ProgramOptions* progOpt) { CVF_ASSERT(progOpt); + progOpt->registerOption("grpcserver", "[]", "Run as a GRPC server. Default port is 50051", cvf::ProgramOptions::SINGLE_VALUE); progOpt->registerOption("console", "", "Run as a console application without Graphics"); progOpt->registerOption("last", "", "Open last used project."); progOpt->registerOption("project", "", "Open project file .", cvf::ProgramOptions::SINGLE_VALUE); diff --git a/ApplicationCode/CMakeLists.txt b/ApplicationCode/CMakeLists.txt index 6285764a9c..cd404ae8d0 100644 --- a/ApplicationCode/CMakeLists.txt +++ b/ApplicationCode/CMakeLists.txt @@ -23,6 +23,9 @@ endif(Qt5Core_FOUND) CONFIGURE_FILE( ${CMAKE_SOURCE_DIR}/ApplicationCode/Adm/RiaVersionInfo.h.cmake ${CMAKE_BINARY_DIR}/Generated/RiaVersionInfo.h ) +CONFIGURE_FILE( ${CMAKE_SOURCE_DIR}/ApplicationCode/Adm/RiaVersionInfo.py.cmake + ${CMAKE_BINARY_DIR}/Python/generated/RiaVersionInfo.py +) if (MSVC AND (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 19.11)) # VS 2017 : Disable warnings from from gtest code, using deprecated code related to TR1 @@ -44,6 +47,7 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/Commands ${CMAKE_CURRENT_SOURCE_DIR}/Commands/EclipseCommands ${CMAKE_CURRENT_SOURCE_DIR}/FileInterface + ${CMAKE_CURRENT_SOURCE_DIR}/GrpcInterface ${CMAKE_CURRENT_SOURCE_DIR}/SocketInterface ${CMAKE_CURRENT_SOURCE_DIR}/Measurement ${CMAKE_CURRENT_SOURCE_DIR}/ModelVisualization @@ -97,6 +101,12 @@ list( APPEND CPP_SOURCES ${UNIT_TEST_FILES} ) +if (RESINSIGHT_ENABLE_GRPC) + list( APPEND REFERENCED_CMAKE_FILES + GrpcInterface/CMakeLists.cmake + ) +endif(RESINSIGHT_ENABLE_GRPC) + list( APPEND REFERENCED_CMAKE_FILES Application/CMakeLists_files.cmake Application/Tools/CMakeLists_files.cmake @@ -152,7 +162,7 @@ list( APPEND REFERENCED_CMAKE_FILES CommandFileInterface/Core/CMakeLists_files.cmake Commands/FractureCommands/CMakeLists_files.cmake ) - + option (RESINSIGHT_INCLUDE_APPLICATION_UNIT_TESTS "Include ApplicationCode Unit Tests" OFF) if (RESINSIGHT_INCLUDE_APPLICATION_UNIT_TESTS) add_definitions(-DUSE_UNIT_TESTS) @@ -230,7 +240,6 @@ if (RESINSIGHT_ENABLE_PROTOTYPE_FEATURE_SOURING) add_definitions(-DENABLE_SOURING) endif() - ############################################################################# # Qt specifics: Moc, ui, resources ############################################################################# @@ -306,11 +315,16 @@ source_group( "UnitTests" FILES ${UNIT_TEST_FILES} ) if (MSVC) set( EXE_FILES WIN32) + if (RESINSIGHT_ENABLE_GRPC) + # GRPC generates a lot of harmless warnings on MSVC + set_source_files_properties(${GRPC_CPP_SOURCES} PROPERTIES COMPILE_FLAGS "/wd4251 /wd4702 /wd4005 /wd4244 /wd4125") + endif(RESINSIGHT_ENABLE_GRPC) elseif (APPLE) set( EXE_FILES MACOSX_BUNDLE) endif() set( EXE_FILES ${EXE_FILES} + ${GRPC_HEADER_FILES} ${CPP_SOURCES} ${MOC_SOURCE_FILES} ${FORM_FILES_CPP} @@ -321,9 +335,23 @@ set( EXE_FILES ../ResInsightVersion.cmake .clang-format .clang-tidy + Adm/RiaVersionInfo.h.cmake ) -add_executable( ResInsight ${EXE_FILES} ) +if (RESINSIGHT_ENABLE_GRPC) + list(APPEND EXE_FILES + ${GRPC_CPP_SOURCES} + ${GRPC_HEADER_FILES} + ${GRPC_PYTHON_SOURCES_FULL_PATH} + Adm/RiaVersionInfo.py.cmake + ) + if (DEFINED GRPC_LIBRARY_DIRS) + message(STATUS "Using GRPC Library Dir: ${GRPC_LIBRARY_DIRS}") + link_directories("${GRPC_LIBRARY_DIRS}") + endif(DEFINED GRPC_LIBRARY_DIRS) +endif(RESINSIGHT_ENABLE_GRPC) + +add_executable( ResInsight ${EXE_FILES}) if (MSVC) # The following warnings are supposed to be used in ResInsight, but temporarily disabled to avoid too much noise @@ -376,6 +404,10 @@ set( LINK_LIBRARIES ${QT_LIBRARIES} ) +if (RESINSIGHT_ENABLE_GRPC) + list(APPEND LINK_LIBRARIES ${GRPC_LIBRARIES}) +endif() + # According to ivarun this is needed on OpenSuse, and Fedora. See: https://github.com/OPM/ResInsight/pull/7 if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") list(APPEND EXTERNAL_LINK_LIBRARIES @@ -502,6 +534,31 @@ foreach (FILE_TO_COPY ${RI_DLL_FILENAMES}) endif() endforeach() +# Copy all grpc libraries and python files +if (RESINSIGHT_ENABLE_GRPC) + if(UNIX) + foreach (GRPC_LIBRARY ${GRPC_LIBRARIES}) + add_custom_command(TARGET ResInsight POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${GRPC_INSTALL_PREFIX}/lib/lib${GRPC_LIBRARY}.so" + "${CMAKE_CURRENT_BINARY_DIR}/$" + ) + endforeach(GRPC_LIBRARY ${GRPC_LIBRARIES}) + endif(UNIX) + + if (PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) + add_custom_target(GeneratedPythonSources DEPENDS ${GRPC_GENERATED_PYTHON_SOURCES}) + add_dependencies(ResInsight GeneratedPythonSources) + + foreach (PYTHON_SCRIPT ${GRPC_PYTHON_SOURCES}) + if (EXISTS "${GRPC_PYTHON_SOURCE_PATH}/${PYTHON_SCRIPT}") + configure_file("${GRPC_PYTHON_SOURCE_PATH}/${PYTHON_SCRIPT}" + "${GRPC_PYTHON_DEST_PATH}/${PYTHON_SCRIPT}" + COPYONLY) + endif(EXISTS "${GRPC_PYTHON_SOURCE_PATH}/${PYTHON_SCRIPT}") + endforeach(PYTHON_SCRIPT ${GRPC_PYTHON_SOURCES}) + endif(PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) +endif(RESINSIGHT_ENABLE_GRPC) ############################################################################# # Install diff --git a/ApplicationCode/CommandFileInterface/RicfSetTimeStep.cpp b/ApplicationCode/CommandFileInterface/RicfSetTimeStep.cpp index a43b4e57f7..fedb30ca20 100644 --- a/ApplicationCode/CommandFileInterface/RicfSetTimeStep.cpp +++ b/ApplicationCode/CommandFileInterface/RicfSetTimeStep.cpp @@ -38,6 +38,22 @@ RicfSetTimeStep::RicfSetTimeStep() RICF_InitField(&m_timeStepIndex, "timeStep", -1, "Time Step Index", "", "", ""); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicfSetTimeStep::setCaseId(int caseId) +{ + m_caseId = caseId; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicfSetTimeStep::setTimeStepIndex(int timeStepIndex) +{ + m_timeStepIndex = timeStepIndex; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -66,5 +82,6 @@ void RicfSetTimeStep::execute() for (Rim3dView* view : eclipseCase->views()) { view->setCurrentTimeStepAndUpdate(m_timeStepIndex); + view->createDisplayModelAndRedraw(); } } diff --git a/ApplicationCode/CommandFileInterface/RicfSetTimeStep.h b/ApplicationCode/CommandFileInterface/RicfSetTimeStep.h index 51d362c237..39cd72a8d4 100644 --- a/ApplicationCode/CommandFileInterface/RicfSetTimeStep.h +++ b/ApplicationCode/CommandFileInterface/RicfSetTimeStep.h @@ -34,9 +34,13 @@ class RicfSetTimeStep : public RicfCommandObject public: RicfSetTimeStep(); + void setCaseId(int caseId); + void setTimeStepIndex(int timeStepIndex); + void execute() override; private: + caf::PdmField m_caseId; caf::PdmField m_timeStepIndex; }; diff --git a/ApplicationCode/Commands/ApplicationCommands/RicEditPreferencesFeature.cpp b/ApplicationCode/Commands/ApplicationCommands/RicEditPreferencesFeature.cpp index dc099761d4..242f73c849 100644 --- a/ApplicationCode/Commands/ApplicationCommands/RicEditPreferencesFeature.cpp +++ b/ApplicationCode/Commands/ApplicationCommands/RicEditPreferencesFeature.cpp @@ -58,6 +58,7 @@ void RicEditPreferencesFeature::onActionTriggered(bool isChecked) caf::PdmSettings::writeFieldsToApplicationStore(app->preferences()); app->applyPreferences(oldPreferences.get()); app->applyGuiPreferences(oldPreferences.get()); + app->updateGrpcServer(); } else { diff --git a/ApplicationCode/GrpcInterface/CMakeLists.cmake b/ApplicationCode/GrpcInterface/CMakeLists.cmake new file mode 100644 index 0000000000..52a1426218 --- /dev/null +++ b/ApplicationCode/GrpcInterface/CMakeLists.cmake @@ -0,0 +1,158 @@ +set ( SOURCE_GROUP_HEADER_FILES + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcServer.h + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcCallbacks.h + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcCallbacks.inl + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcServiceInterface.h + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcGridInfoService.h + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcProjectInfoService.h + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcCommandService.h + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcResInfoService.h +) + +set ( SOURCE_GROUP_SOURCE_FILES + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcServer.cpp + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcServiceInterface.cpp + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcGridInfoService.cpp + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcProjectInfoService.cpp + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcCommandService.cpp + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcResInfoService.cpp +) + +add_definitions(-DENABLE_GRPC) + +if (MSVC) + add_definitions(-D_WIN32_WINNT=0x600) + + # Find Protobuf installation + # Looks for protobuf-config.cmake file installed by Protobuf's cmake installation. + set(protobuf_MODULE_COMPATIBLE ON CACHE BOOL "") + find_package(Protobuf CONFIG 3.0 REQUIRED) + message(STATUS "Using protobuf ${protobuf_VERSION}") + + # Find gRPC installation + # Looks for gRPCConfig.cmake file installed by gRPC's cmake installation. + find_package(gRPC CONFIG REQUIRED NO_MODULE) + message(STATUS "Using gRPC ${gRPC_VERSION}") + + set(_PROTOBUF_LIBPROTOBUF protobuf::libprotobuf) + set(_PROTOBUF_PROTOC $) + + set(_GRPC_GRPCPP_UNSECURE gRPC::grpc++_unsecure gRPC::grpc_unsecure gRPC::gpr) + set(_GRPC_CPP_PLUGIN_EXECUTABLE $) + set(GRPC_LIBRARIES ${_GRPC_GRPCPP_UNSECURE} ${_PROTOBUF_LIBPROTOBUF}) + + if (MSVC) + set_target_properties(${GRPC_LIBRARIES} PROPERTIES + MAP_IMPORTED_CONFIG_MINSIZEREL RELEASE + MAP_IMPORTED_CONFIG_RELWITHDEBINFO RELEASE + ) + endif(MSVC) +else() + if (NOT DEFINED GRPC_INSTALL_PREFIX OR NOT EXISTS ${GRPC_INSTALL_PREFIX}) + message(FATAL_ERROR "You need a valid GRPC_INSTALL_PREFIX set to build with GRPC") + endif() + set(ENV{PKG_CONFIG_PATH} "${GRPC_INSTALL_PREFIX}/lib/pkgconfig") + find_package(PkgConfig REQUIRED) + pkg_check_modules(GRPC REQUIRED grpc++_unsecure>=1.20 grpc_unsecure gpr protobuf) + set(_PROTOBUF_PROTOC "${GRPC_INSTALL_PREFIX}/bin/protoc") + set(_GRPC_CPP_PLUGIN_EXECUTABLE "${GRPC_INSTALL_PREFIX}/bin/grpc_cpp_plugin") + include_directories(AFTER ${GRPC_INCLUDE_DIRS}) +endif() + +# Cannot use the nice new FindPackage modules for python since that is CMake 3.12+ +if(PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) + message(STATUS "Using Python ${PYTHON_EXECUTABLE}") +endif(PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) + +# Proto files +set(PROTO_FILES + "Empty" + "CaseInfo" + "GridInfo" + "ProjectInfo" + "Commands" + "ResInfo" +) + +set(GRPC_PYTHON_SOURCE_PATH "${CMAKE_SOURCE_DIR}/Python") +set(GRPC_PYTHON_DEST_PATH "${CMAKE_BINARY_DIR}/Python") + +foreach(proto_file ${PROTO_FILES}) + get_filename_component(rips_proto "${CMAKE_CURRENT_LIST_DIR}/GrpcProtos/${proto_file}.proto" ABSOLUTE) + get_filename_component(rips_proto_path "${rips_proto}" PATH) + + set(rips_proto_srcs "${CMAKE_BINARY_DIR}/Generated/${proto_file}.pb.cc") + set(rips_proto_hdrs "${CMAKE_BINARY_DIR}/Generated/${proto_file}.pb.h") + set(rips_grpc_srcs "${CMAKE_BINARY_DIR}/Generated/${proto_file}.grpc.pb.cc") + set(rips_grpc_hdrs "${CMAKE_BINARY_DIR}/Generated/${proto_file}.grpc.pb.h") + + add_custom_command( + OUTPUT "${rips_proto_srcs}" "${rips_proto_hdrs}" "${rips_grpc_srcs}" "${rips_grpc_hdrs}" + COMMAND ${_PROTOBUF_PROTOC} + ARGS --grpc_out "${CMAKE_BINARY_DIR}/Generated" + --cpp_out "${CMAKE_BINARY_DIR}/Generated" + -I "${rips_proto_path}" + --plugin=protoc-gen-grpc="${_GRPC_CPP_PLUGIN_EXECUTABLE}" + "${rips_proto}" + DEPENDS "${rips_proto}" + ) + + if (PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) + set(rips_proto_python "generated/${proto_file}_pb2.py") + set(rips_grpc_python "generated/${proto_file}_pb2_grpc.py") + + add_custom_command( + OUTPUT "${GRPC_PYTHON_SOURCE_PATH}/${rips_proto_python}" "${GRPC_PYTHON_SOURCE_PATH}/${rips_grpc_python}" + COMMAND ${PYTHON_EXECUTABLE} + ARGS -m grpc_tools.protoc + -I "${rips_proto_path}" + --python_out "${GRPC_PYTHON_SOURCE_PATH}/generated" + --grpc_python_out "${GRPC_PYTHON_SOURCE_PATH}/generated" + "${rips_proto}" + DEPENDS "${rips_proto}" + COMMENT "Generating ${rips_proto_python} and ${rips_grpc_python}" + VERBATIM + ) + list (APPEND GRPC_PYTHON_GENERATED_SOURCES + ${rips_proto_python} + ${rips_grpc_python} + ) + + endif(PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) + + list( APPEND GRPC_HEADER_FILES + ${rips_proto_hdrs} + ${rips_grpc_hdrs} + ) + + list( APPEND GRPC_CPP_SOURCES + ${rips_proto_srcs} + ${rips_grpc_srcs} + ) + +endforeach(proto_file) + +if (PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) + list(APPEND GRPC_PYTHON_SOURCES + ${GRPC_PYTHON_GENERATED_SOURCES} + "api/__init__.py" + "api/ResInsight.py" + "examples/CommandExample.py" + "examples/GridInfoStreamingExample.py" + "examples/ResultValues.py" + "examples/SelectedCases.py" + "examples/AllCases.py" + "tests/test_sample.py" + ) + + foreach(PYTHON_SCRIPT ${GRPC_PYTHON_SOURCES}) + list(APPEND GRPC_PYTHON_SOURCES_FULL_PATH "${GRPC_PYTHON_SOURCE_PATH}/${PYTHON_SCRIPT}") + endforeach() + source_group(TREE ${GRPC_PYTHON_SOURCE_PATH} FILES ${GRPC_PYTHON_SOURCES_FULL_PATH} PREFIX "Python") + +endif(PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) + +list ( APPEND GRPC_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES}) +list ( APPEND GRPC_CPP_SOURCES ${SOURCE_GROUP_SOURCE_FILES}) + +source_group( "GrpcInterface" FILES ${SOURCE_GROUP_HEADER_FILES} ${SOURCE_GROUP_SOURCE_FILES} ${CMAKE_CURRENT_LIST_DIR}/CMakeLists.cmake ) diff --git a/ApplicationCode/GrpcInterface/GrpcProtos/CaseInfo.proto b/ApplicationCode/GrpcInterface/GrpcProtos/CaseInfo.proto new file mode 100644 index 0000000000..e53946ef63 --- /dev/null +++ b/ApplicationCode/GrpcInterface/GrpcProtos/CaseInfo.proto @@ -0,0 +1,31 @@ +syntax = "proto3"; + +package rips; + +message Case { + int32 id = 1; +} + +message CaseInfo +{ + int32 id = 1; + int32 group_id = 2; + string name = 3; + string type = 4; +} + +message CaseInfos +{ + repeated CaseInfo case_info = 1; +} + +message CaseGroup +{ + int32 id = 1; + string name = 2; +} + +message CaseGroups +{ + repeated CaseGroup case_group = 1; +} \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto b/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto new file mode 100644 index 0000000000..14246a5b02 --- /dev/null +++ b/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto @@ -0,0 +1,60 @@ +syntax = "proto3"; + +import "Empty.proto"; + +package rips; + +service Commands +{ + rpc Execute(CommandParams) returns(Empty) {} +} + +message SetTimeStepParams +{ + int32 caseId = 1; + int32 timeStep = 2; +} + +message SetMainWindowSizeParams +{ + int32 height = 1; + int32 width = 2; +} + +message FilePathRequest +{ + string path = 1; +} + +message ReplaceCaseRequest +{ + string newGridFile = 1; + int32 caseId = 2; +} + +message ReplaceSourceCasesRequest +{ + string gridListFile = 1; +} + +message ExportMultiCaseRequest +{ + string gridListFile = 1; +} + +message CommandParams +{ + oneof params + { + SetTimeStepParams setTimeStep = 1; + SetMainWindowSizeParams setMainWindowSize = 2; + FilePathRequest openProject = 3; + Empty closeProject = 4; + FilePathRequest setStartDir = 5; + FilePathRequest loadCase = 6; + ReplaceCaseRequest replaceCase = 7; + ReplaceSourceCasesRequest replaceSourceCases = 8; + ExportMultiCaseRequest exportMultiCaseSnapshots = 9; + } +} + diff --git a/ApplicationCode/GrpcInterface/GrpcProtos/Empty.proto b/ApplicationCode/GrpcInterface/GrpcProtos/Empty.proto new file mode 100644 index 0000000000..7fd46ac602 --- /dev/null +++ b/ApplicationCode/GrpcInterface/GrpcProtos/Empty.proto @@ -0,0 +1,7 @@ +syntax = "proto3"; + +package rips; + +message Empty +{ +} diff --git a/ApplicationCode/GrpcInterface/GrpcProtos/GridInfo.proto b/ApplicationCode/GrpcInterface/GrpcProtos/GridInfo.proto new file mode 100644 index 0000000000..0baaf00d4b --- /dev/null +++ b/ApplicationCode/GrpcInterface/GrpcProtos/GridInfo.proto @@ -0,0 +1,89 @@ +syntax = "proto3"; + +import "CaseInfo.proto"; + +package rips; + +service GridInfo +{ + // This function returns a two dimensional matrix: One row for each grid, starting with the main grid. + rpc GetGridCount(Case) returns(GridCount) {} + rpc GetGridDimensions(Case) returns (GridDimensions) {} + rpc StreamActiveCellInfo(ActiveCellInfoRequest) returns (stream ActiveCellInfoArray) {} + rpc GetAllCoarseningInfoArray(Case) returns (CoarseningInfoArray) {} + rpc GetTimeSteps(Case) returns (TimeStepDates) {} + rpc GetTimeStepDaysSinceStart(Case) returns (DoubleDates) {} +} + +message GridCount +{ + int32 count = 1; +} + +message GridDimensions +{ + repeated Vec3i dimensions = 1; +} + +message Vec3i { + int32 i = 1; + int32 j = 2; + int32 k = 3; +} + +enum PorosityModelType +{ + MATRIX_MODEL = 0; + FRACTURE_MODEL = 1; +} + +message ActiveCellInfoRequest +{ + int32 case_id = 1; + PorosityModelType porosity_model = 2; +} + +message ActiveCellInfoArray +{ + repeated ActiveCellInfo data = 1; +} + +message ActiveCellInfo +{ + int32 grid_index = 1; + int32 parent_grid_index = 2; + int32 coarsening_box_index = 3; + Vec3i local_ijk = 4; + Vec3i parent_ijk = 5; +} + +message CoarseningInfoArray +{ + repeated CoarseningInfo data = 1; +} + +message CoarseningInfo +{ + Vec3i min = 1; + Vec3i max = 2; +} + +message TimeStepDates +{ + repeated TimeStepDate date = 1; +} + +message TimeStepDate +{ + int32 year = 1; + int32 month = 2; + int32 day = 3; + int32 hour = 4; + int32 minute = 5; + int32 second = 6; +} + +message DoubleDates +{ + repeated double date_decimal = 1; +} \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/GrpcProtos/ProjectInfo.proto b/ApplicationCode/GrpcInterface/GrpcProtos/ProjectInfo.proto new file mode 100644 index 0000000000..33c7a5f765 --- /dev/null +++ b/ApplicationCode/GrpcInterface/GrpcProtos/ProjectInfo.proto @@ -0,0 +1,16 @@ +syntax = "proto3"; + +import "CaseInfo.proto"; +import "Empty.proto"; + +package rips; + +service ProjectInfo { + rpc CurrentCase(Empty) returns (Case) {} + rpc CurrentCaseInfo(Empty) returns (CaseInfo) {} + rpc CaseInfoFromCase(Case) returns (CaseInfo) {} + rpc SelectedCases(Empty) returns (CaseInfos) {} + rpc AllCaseGroups(Empty) returns (CaseGroups) {} + rpc AllCases(Empty) returns (CaseInfos) {} + rpc CasesInGroup(CaseGroup) returns (CaseInfos) {} +} diff --git a/ApplicationCode/GrpcInterface/GrpcProtos/ResInfo.proto b/ApplicationCode/GrpcInterface/GrpcProtos/ResInfo.proto new file mode 100644 index 0000000000..f6d711155a --- /dev/null +++ b/ApplicationCode/GrpcInterface/GrpcProtos/ResInfo.proto @@ -0,0 +1,15 @@ +syntax = "proto3"; + +package rips; + +import "Empty.proto"; + +service ResInfo { + rpc GetVersion(Empty) returns (Version) {} +} + +message Version { + int32 major_version = 1; + int32 minor_version = 2; + int32 patch_version = 3; +} \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.h b/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.h new file mode 100644 index 0000000000..3d34a9e548 --- /dev/null +++ b/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.h @@ -0,0 +1,173 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 "RiaLogging.h" + +#include +#include +#include + +using grpc::CompletionQueue; +using grpc::ServerAsyncResponseWriter; +using grpc::ServerAsyncWriter; +using grpc::ServerCompletionQueue; +using grpc::ServerContext; +using grpc::ServerWriter; +using grpc::Status; + +class RiaGrpcServiceInterface; + +//================================================================================================== +// +// Base class for all gRPC-callbacks +// +//================================================================================================== +class RiaAbstractGrpcCallback +{ +public: + enum CallState + { + CREATE_HANDLER, + INIT_REQUEST, + PROCESS_REQUEST, + FINISH_REQUEST + }; + +public: + inline RiaAbstractGrpcCallback(); + + virtual ~RiaAbstractGrpcCallback() {} + virtual QString name() const = 0; + virtual RiaAbstractGrpcCallback* createNewFromThis() const = 0; + virtual void createRequestHandler(ServerCompletionQueue* completionQueue) = 0; + virtual void initRequest() = 0; + virtual void processRequest() = 0; + virtual void finishRequest() {} + + inline CallState callState() const; + inline const Status& status() const; + +protected: + inline void setCallState(CallState state); + +protected: + CallState m_state; + Status m_status; +}; + +//================================================================================================== +// +// Templated gRPC-callback base class +// +//================================================================================================== +template +class RiaGrpcRequestCallback : public RiaAbstractGrpcCallback +{ +public: + RiaGrpcRequestCallback(ServiceT* service); + + QString name() const override; + const RequestT& request() const; + ReplyT& reply(); + +protected: + virtual QString methodType() const = 0; + +protected: + ServiceT* m_service; + RequestT m_request; + ReplyT m_reply; +}; + +//================================================================================================== +// +// Templated gRPC-callback for non-streaming services +// +//================================================================================================== +template +class RiaGrpcCallback : public RiaGrpcRequestCallback +{ +public: + typedef ServerAsyncResponseWriter ResponseWriterT; + typedef std::function MethodImplT; + typedef std::function< + void(ServiceT&, ServerContext*, RequestT*, ResponseWriterT*, CompletionQueue*, ServerCompletionQueue*, void*)> + MethodRequestT; + + RiaGrpcCallback(ServiceT* service, MethodImplT methodImpl, MethodRequestT methodRequest); + + RiaAbstractGrpcCallback* createNewFromThis() const override; + void createRequestHandler(ServerCompletionQueue* completionQueue) override; + void initRequest() override; + void processRequest() override; + +protected: + virtual QString methodType() const; + +private: + ServerContext m_context; + ResponseWriterT m_responder; + MethodImplT m_methodImpl; + MethodRequestT m_methodRequest; +}; + +//================================================================================================== +// +// Templated *streaming* gRPC-callback calling service implementation callbacks +// +// The streaming callback needs a state handler for setting up and maintaining order. +// +// A fully functional stream handler needs to implement the following methods: +// 1. Default Constructor +// 2. grpc::Status init(const grpc::Message* request) +// 3. grpc::status assignReply(grpc::Message* reply) +// +//================================================================================================== + +//================================================================================================== +template +class RiaGrpcStreamCallback : public RiaGrpcRequestCallback +{ +public: + typedef ServerAsyncWriter ResponseWriterT; + typedef std::function MethodImplT; + typedef std::function< + void(ServiceT&, ServerContext*, RequestT*, ResponseWriterT*, CompletionQueue*, ServerCompletionQueue*, void*)> + MethodRequestT; + + RiaGrpcStreamCallback(ServiceT* service, MethodImplT methodImpl, MethodRequestT methodRequest, StateHandlerT* stateHandler); + + RiaAbstractGrpcCallback* createNewFromThis() const override; + void createRequestHandler(ServerCompletionQueue* completionQueue) override; + void initRequest() override; + void processRequest() override; + +protected: + virtual QString methodType() const; + +private: + ServerContext m_context; + ResponseWriterT m_responder; + MethodImplT m_methodImpl; + MethodRequestT m_methodRequest; + size_t m_dataCount; // This is used to keep track of progress. Only one item is sent for each invocation. + std::unique_ptr m_stateHandler; +}; + +#include "RiaGrpcCallbacks.inl" diff --git a/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.inl b/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.inl new file mode 100644 index 0000000000..fd5f3be865 --- /dev/null +++ b/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.inl @@ -0,0 +1,239 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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. +// +////////////////////////////////////////////////////////////////////////////////// + +inline RiaAbstractGrpcCallback::RiaAbstractGrpcCallback() + : m_state(CREATE_HANDLER) + , m_status(Status::OK) +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiaAbstractGrpcCallback::CallState RiaAbstractGrpcCallback::callState() const +{ + return m_state; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +const Status& RiaAbstractGrpcCallback::status() const +{ + return m_status; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +inline void RiaAbstractGrpcCallback::setCallState(CallState state) +{ + m_state = state; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +template +RiaGrpcRequestCallback::RiaGrpcRequestCallback(ServiceT* service) + : m_service(service) +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +template +QString RiaGrpcRequestCallback::name() const +{ + QString fullName = QString("%1:%2(%3, %4)") + .arg(typeid(ServiceT).name()) + .arg(methodType()) + .arg(typeid(RequestT).name()) + .arg(typeid(ReplyT).name()); + return fullName; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +template +const RequestT& RiaGrpcRequestCallback::request() const +{ + return m_request; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +template +ReplyT& RiaGrpcRequestCallback::reply() +{ + return m_reply; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +template +RiaGrpcCallback::RiaGrpcCallback(ServiceT* service, + MethodImplT methodImpl, + MethodRequestT methodRequest) + : RiaGrpcRequestCallback(service) + , m_responder(&m_context) + , m_methodImpl(methodImpl) + , m_methodRequest(methodRequest) +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +template +RiaAbstractGrpcCallback* RiaGrpcCallback::createNewFromThis() const +{ + return new RiaGrpcCallback(this->m_service, this->m_methodImpl, this->m_methodRequest); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +template +void RiaGrpcCallback::createRequestHandler(ServerCompletionQueue* completionQueue) +{ + m_methodRequest(*this->m_service, &m_context, &this->m_request, &m_responder, completionQueue, completionQueue, this); + this->setCallState(RiaAbstractGrpcCallback::INIT_REQUEST); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +template +void RiaGrpcCallback::initRequest() +{ + this->setCallState(RiaAbstractGrpcCallback::PROCESS_REQUEST); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +template +void RiaGrpcCallback::processRequest() +{ + this->m_status = m_methodImpl(*this->m_service, &m_context, &this->m_request, &this->m_reply); + m_responder.Finish(this->m_reply, this->m_status, this); + this->setCallState(RiaAbstractGrpcCallback::FINISH_REQUEST); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +template +QString RiaGrpcCallback::methodType() const +{ + return "RegularMethod"; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +template +RiaGrpcStreamCallback::RiaGrpcStreamCallback(ServiceT* service, + MethodImplT methodImpl, + MethodRequestT methodRequest, + StateHandlerT* stateHandler) + : RiaGrpcRequestCallback(service) + , m_responder(&m_context) + , m_methodImpl(methodImpl) + , m_methodRequest(methodRequest) + , m_dataCount(0u) + , m_stateHandler(stateHandler) +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +template +RiaAbstractGrpcCallback* RiaGrpcStreamCallback::createNewFromThis() const +{ + return new RiaGrpcStreamCallback( + this->m_service, m_methodImpl, m_methodRequest, new StateHandlerT); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +template +void RiaGrpcStreamCallback::createRequestHandler( + ServerCompletionQueue* completionQueue) +{ + m_methodRequest(*this->m_service, &m_context, &this->m_request, &m_responder, completionQueue, completionQueue, this); + this->setCallState(RiaAbstractGrpcCallback::INIT_REQUEST); +} + +//-------------------------------------------------------------------------------------------------- +/// Perform initialisation tasks at the time of receiving a request +//-------------------------------------------------------------------------------------------------- +template +void RiaGrpcStreamCallback::initRequest() +{ + this->m_status = m_stateHandler->init(&this->m_request); + this->setCallState(RiaAbstractGrpcCallback::PROCESS_REQUEST); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +template +void RiaGrpcStreamCallback::processRequest() +{ + this->m_reply = ReplyT(); // Make sure it is reset + + if (!this->m_status.ok()) + { + m_responder.Finish(this->m_status, this); + this->setCallState(RiaAbstractGrpcCallback::FINISH_REQUEST); + return; + } + + this->m_status = m_methodImpl(*this->m_service, &m_context, &this->m_request, &this->m_reply, m_stateHandler.get()); + if (this->m_status.ok()) + { + m_responder.Write(this->m_reply, this); + } + else + { + this->setCallState(RiaAbstractGrpcCallback::FINISH_REQUEST); + // Out of range means we're finished but it isn't an error + if (this->m_status.error_code() == grpc::OUT_OF_RANGE) + { + this->m_status = Status::OK; + } + m_responder.Finish(this->m_status, this); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +template +QString RiaGrpcStreamCallback::methodType() const +{ + return "StreamingMethod"; +} diff --git a/ApplicationCode/GrpcInterface/RiaGrpcCommandService.cpp b/ApplicationCode/GrpcInterface/RiaGrpcCommandService.cpp new file mode 100644 index 0000000000..4e5de80393 --- /dev/null +++ b/ApplicationCode/GrpcInterface/RiaGrpcCommandService.cpp @@ -0,0 +1,155 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 "RiaGrpcCommandService.h" + +#include "RiaLogging.h" + +#include "RiaGrpcCallbacks.h" + +#include "RicfSetTimeStep.h" + +#include "cafAssert.h" +#include "cafPdmDefaultObjectFactory.h" +#include "cafPdmValueField.h" + +using namespace rips; +using namespace google::protobuf; + +#ifdef WIN32 +#ifdef GetMessage +#undef GetMessage +#endif +#endif + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +grpc::Status RiaGrpcCommandService::Execute(grpc::ServerContext* context, const CommandParams* request, Empty* reply) +{ + auto requestDescriptor = request->GetDescriptor(); + RiaLogging::info(QString::fromStdString(requestDescriptor->name())); + + CommandParams::ParamsCase paramsCase = request->params_case(); + if (paramsCase != CommandParams::PARAMS_NOT_SET) + { + auto grpcOneOfMessage = requestDescriptor->FindFieldByNumber((int)paramsCase); + CAF_ASSERT(grpcOneOfMessage->type() == FieldDescriptor::TYPE_MESSAGE); + + const Message& params = request->GetReflection()->GetMessage(*request, grpcOneOfMessage); + QString grpcOneOfMessageName = QString::fromStdString(grpcOneOfMessage->name()); + RiaLogging::info(QString("Found Command: %1").arg(grpcOneOfMessageName)); + auto pdmObjectHandle = caf::PdmDefaultObjectFactory::instance()->create(grpcOneOfMessageName); + auto commandHandle = dynamic_cast(pdmObjectHandle); + if (commandHandle) + { + auto subMessageDescriptor = grpcOneOfMessage->message_type(); + int numParameters = subMessageDescriptor->field_count(); + for (int i = 0; i < numParameters; ++i) + { + auto parameter = subMessageDescriptor->field(i); + if (parameter) + { + QString parameterName = QString::fromStdString(parameter->name()); + auto pdmValueFieldHandle = dynamic_cast(pdmObjectHandle->findField(parameterName)); + if (pdmValueFieldHandle) + { + RiaLogging::info(QString("Found Matching Parameter: %1").arg(parameterName)); + assignFieldValue(pdmValueFieldHandle, params, parameter); + } + } + } + commandHandle->execute(); + + return Status::OK; + } + } + return grpc::Status(grpc::NOT_FOUND, "Command not found"); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RiaGrpcCommandService::createCallbacks() +{ + typedef RiaGrpcCommandService Self; + + return {new RiaGrpcCallback(this, &Self::Execute, &Self::RequestExecute)}; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaGrpcCommandService::assignFieldValue(caf::PdmValueField* pdmValueField, + const Message& params, + const FieldDescriptor* paramDescriptor) +{ + FieldDescriptor::Type fieldDataType = paramDescriptor->type(); + QVariant qValue; + switch (fieldDataType) + { + case FieldDescriptor::TYPE_BOOL: { + auto value = params.GetReflection()->GetBool(params, paramDescriptor); + qValue = QVariant(value); + break; + } + case FieldDescriptor::TYPE_INT32: { + int value = params.GetReflection()->GetInt32(params, paramDescriptor); + qValue = QVariant(value); + break; + } + case FieldDescriptor::TYPE_UINT32: { + uint value = params.GetReflection()->GetUInt32(params, paramDescriptor); + qValue = QVariant(value); + break; + } + case FieldDescriptor::TYPE_INT64: { + int64_t value = params.GetReflection()->GetInt64(params, paramDescriptor); + qValue = QVariant((qlonglong) value); + break; + } + case FieldDescriptor::TYPE_UINT64: { + uint64_t value = params.GetReflection()->GetUInt64(params, paramDescriptor); + qValue = QVariant((qulonglong) value); + break; + } + case FieldDescriptor::TYPE_STRING: { + auto value = params.GetReflection()->GetString(params, paramDescriptor); + qValue = QVariant(QString::fromStdString(value)); + break; + } + case FieldDescriptor::TYPE_FLOAT: { + auto value = params.GetReflection()->GetFloat(params, paramDescriptor); + qValue = QVariant(value); + break; + } + case FieldDescriptor::TYPE_DOUBLE: { + auto value = params.GetReflection()->GetDouble(params, paramDescriptor); + qValue = QVariant(value); + break; + } + case FieldDescriptor::TYPE_ENUM: { + auto value = params.GetReflection()->GetEnumValue(params, paramDescriptor); + qValue = QVariant(value); + break; + } + } + pdmValueField->setFromQVariant(qValue); +} + +static bool RiaGrpcCommandService_init = + RiaGrpcServiceFactory::instance()->registerCreator(typeid(RiaGrpcCommandService).hash_code()); diff --git a/ApplicationCode/GrpcInterface/RiaGrpcCommandService.h b/ApplicationCode/GrpcInterface/RiaGrpcCommandService.h new file mode 100644 index 0000000000..e11cbc080c --- /dev/null +++ b/ApplicationCode/GrpcInterface/RiaGrpcCommandService.h @@ -0,0 +1,58 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 "RiaGrpcServiceInterface.h" + +#include "Commands.grpc.pb.h" + +#include +#include + +namespace rips +{ +class Empty; +} + +namespace caf +{ +class PdmValueField; +} + +namespace google +{ +namespace protobuf +{ + class FieldDescriptor; + class Message; +} // namespace protobuf +} // namespace google + +class RiaAbstractGrpcCallback; + +class RiaGrpcCommandService : public rips::Commands::AsyncService, public RiaGrpcServiceInterface +{ +public: + grpc::Status Execute(grpc::ServerContext* context, const rips::CommandParams* request, rips::Empty* reply) override; + std::vector createCallbacks() override; + +private: + void assignFieldValue(caf::PdmValueField* pdmValueField, + const google::protobuf::Message& params, + const google::protobuf::FieldDescriptor* paramDescriptor); +}; diff --git a/ApplicationCode/GrpcInterface/RiaGrpcGridInfoService.cpp b/ApplicationCode/GrpcInterface/RiaGrpcGridInfoService.cpp new file mode 100644 index 0000000000..9fe8d03472 --- /dev/null +++ b/ApplicationCode/GrpcInterface/RiaGrpcGridInfoService.cpp @@ -0,0 +1,283 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 "RiaGrpcGridInfoService.h" +#include "RiaGrpcCallbacks.h" + +#include "RigActiveCellInfo.h" +#include "RigEclipseCaseData.h" +#include "RigMainGrid.h" + +#include "RimEclipseCase.h" +#include "RimGeoMechCase.h" + +#include // memcpy + +using namespace rips; + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiaActiveCellInfoStateHandler::RiaActiveCellInfoStateHandler() + : m_request(nullptr) + , m_eclipseCase(nullptr) + , m_activeCellInfo(nullptr) + , m_currentCellIdx(0u) +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +grpc::Status RiaActiveCellInfoStateHandler::init(const rips::ActiveCellInfoRequest* request) +{ + CAF_ASSERT(request); + m_request = request; + + m_porosityModel = RiaDefines::PorosityModelType(m_request->porosity_model()); + RimCase* rimCase = RiaGrpcServiceInterface::findCase(m_request->case_id()); + m_eclipseCase = dynamic_cast(rimCase); + + if (!m_eclipseCase) + { + return grpc::Status(grpc::NOT_FOUND, "Eclipse Case not found"); + } + + if (!m_eclipseCase->eclipseCaseData() || !m_eclipseCase->eclipseCaseData()->mainGrid()) + { + return grpc::Status(grpc::NOT_FOUND, "Eclipse Case Data not found"); + } + + m_activeCellInfo = m_eclipseCase->eclipseCaseData()->activeCellInfo(m_porosityModel); + + if (!m_activeCellInfo) + { + return grpc::Status(grpc::NOT_FOUND, "Active Cell Info not found"); + } + + size_t globalCoarseningBoxCount = 0; + + for (size_t gridIdx = 0; gridIdx < m_eclipseCase->eclipseCaseData()->gridCount(); gridIdx++) + { + m_globalCoarseningBoxIndexStart.push_back(globalCoarseningBoxCount); + + RigGridBase* grid = m_eclipseCase->eclipseCaseData()->grid(gridIdx); + + size_t localCoarseningBoxCount = grid->coarseningBoxCount(); + globalCoarseningBoxCount += localCoarseningBoxCount; + } + + return grpc::Status::OK; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +grpc::Status RiaActiveCellInfoStateHandler::assignNextActiveCellInfoData(rips::ActiveCellInfo* cellInfo) +{ + const std::vector& reservoirCells = m_eclipseCase->eclipseCaseData()->mainGrid()->globalCellArray(); + + while (m_currentCellIdx < reservoirCells.size()) + { + size_t cellIdxToTry = m_currentCellIdx++; + if (m_activeCellInfo->isActive(cellIdxToTry)) + { + assignActiveCellInfoData(cellInfo, reservoirCells, cellIdxToTry); + return grpc::Status::OK; + } + } + return Status(grpc::OUT_OF_RANGE, "We've reached the end. This is not an error but means transmission is finished"); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaActiveCellInfoStateHandler::assignActiveCellInfoData(rips::ActiveCellInfo* cellInfo, + const std::vector& reservoirCells, + size_t cellIdx) +{ + RigGridBase* grid = reservoirCells[cellIdx].hostGrid(); + CVF_ASSERT(grid != nullptr); + size_t cellIndex = reservoirCells[cellIdx].gridLocalCellIndex(); + + size_t i, j, k; + grid->ijkFromCellIndex(cellIndex, &i, &j, &k); + + size_t pi, pj, pk; + RigGridBase* parentGrid = nullptr; + + if (grid->isMainGrid()) + { + pi = i; + pj = j; + pk = k; + parentGrid = grid; + } + else + { + size_t parentCellIdx = reservoirCells[cellIdx].parentCellIndex(); + parentGrid = (static_cast(grid))->parentGrid(); + CVF_ASSERT(parentGrid != nullptr); + parentGrid->ijkFromCellIndex(parentCellIdx, &pi, &pj, &pk); + } + + cellInfo->set_grid_index((int)grid->gridIndex()); + cellInfo->set_parent_grid_index((int)parentGrid->gridIndex()); + + size_t coarseningIdx = reservoirCells[cellIdx].coarseningBoxIndex(); + if (coarseningIdx != cvf::UNDEFINED_SIZE_T) + { + size_t globalCoarseningIdx = m_globalCoarseningBoxIndexStart[grid->gridIndex()] + coarseningIdx; + cellInfo->set_coarsening_box_index((int)globalCoarseningIdx); + } + else + { + cellInfo->set_coarsening_box_index(-1); + } + { + rips::Vec3i* local_ijk = new rips::Vec3i; + local_ijk->set_i((int)i); + local_ijk->set_j((int)j); + local_ijk->set_k((int)k); + cellInfo->set_allocated_local_ijk(local_ijk); + } + { + rips::Vec3i* parent_ijk = new rips::Vec3i; + parent_ijk->set_i((int)pi); + parent_ijk->set_j((int)pj); + parent_ijk->set_k((int)pk); + cellInfo->set_allocated_parent_ijk(parent_ijk); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RigActiveCellInfo* RiaActiveCellInfoStateHandler::activeCellInfo() const +{ + return m_activeCellInfo; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +const std::vector& RiaActiveCellInfoStateHandler::reservoirCells() const +{ + const std::vector& reservoirCells = m_eclipseCase->eclipseCaseData()->mainGrid()->globalCellArray(); + return reservoirCells; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +grpc::Status RiaActiveCellInfoStateHandler::assignReply(rips::ActiveCellInfoArray* reply) +{ + const size_t packageSize = RiaGrpcServiceInterface::numberOfMessagesForByteCount(sizeof(rips::ActiveCellInfoArray)); + size_t packageIndex = 0u; + reply->mutable_data()->Reserve((int)packageSize); + for (; packageIndex < packageSize && m_currentCellIdx < m_activeCellInfo->reservoirCellCount(); ++packageIndex) + { + rips::ActiveCellInfo singleCellInfo; + grpc::Status singleCellInfoStatus = assignNextActiveCellInfoData(&singleCellInfo); + if (singleCellInfoStatus.ok()) + { + rips::ActiveCellInfo* allocCellInfo = reply->add_data(); + *allocCellInfo = singleCellInfo; + } + else + { + break; + } + } + if (packageIndex > 0u) + { + return Status::OK; + } + return Status(grpc::OUT_OF_RANGE, "We've reached the end. This is not an error but means transmission is finished"); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +grpc::Status RiaGrpcGridInfoService::GetGridCount(grpc::ServerContext* context, const rips::Case* request, rips::GridCount* reply) +{ + RimCase* rimCase = findCase(request->id()); + + RimEclipseCase* eclipseCase = dynamic_cast(rimCase); + size_t gridCount = 0u; + if (eclipseCase) + { + gridCount = eclipseCase->mainGrid()->gridCount(); + reply->set_count((int)gridCount); + return Status::OK; + } + return grpc::Status(grpc::NOT_FOUND, "Eclipse Case not found"); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +grpc::Status RiaGrpcGridInfoService::GetGridDimensions(grpc::ServerContext* context, + const rips::Case* request, + rips::GridDimensions* reply) +{ + RimCase* rimCase = findCase(request->id()); + + RimEclipseCase* eclipseCase = dynamic_cast(rimCase); + if (eclipseCase) + { + size_t gridCount = eclipseCase->mainGrid()->gridCount(); + for (size_t i = 0; i < gridCount; ++i) + { + const RigGridBase* grid = eclipseCase->mainGrid()->gridByIndex(i); + rips::Vec3i* dimensions = reply->add_dimensions(); + dimensions->set_i((int)grid->cellCountI()); + dimensions->set_j((int)grid->cellCountJ()); + dimensions->set_k((int)grid->cellCountK()); + } + return grpc::Status::OK; + } + + return grpc::Status(grpc::NOT_FOUND, "Eclipse Case not found"); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +grpc::Status RiaGrpcGridInfoService::StreamActiveCellInfo(grpc::ServerContext* context, + const rips::ActiveCellInfoRequest* request, + rips::ActiveCellInfoArray* reply, + RiaActiveCellInfoStateHandler* stateHandler) +{ + return stateHandler->assignReply(reply); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RiaGrpcGridInfoService::createCallbacks() +{ + typedef RiaGrpcGridInfoService Self; + + return {new RiaGrpcCallback(this, &Self::GetGridCount, &Self::RequestGetGridCount), + new RiaGrpcCallback(this, &Self::GetGridDimensions, &Self::RequestGetGridDimensions), + new RiaGrpcStreamCallback( + this, &Self::StreamActiveCellInfo, &Self::RequestStreamActiveCellInfo, new RiaActiveCellInfoStateHandler)}; +} + +static bool RiaGrpcGridInfoService_init = + RiaGrpcServiceFactory::instance()->registerCreator(typeid(RiaGrpcGridInfoService).hash_code()); diff --git a/ApplicationCode/GrpcInterface/RiaGrpcGridInfoService.h b/ApplicationCode/GrpcInterface/RiaGrpcGridInfoService.h new file mode 100644 index 0000000000..a37d52c080 --- /dev/null +++ b/ApplicationCode/GrpcInterface/RiaGrpcGridInfoService.h @@ -0,0 +1,80 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 "GridInfo.grpc.pb.h" + +#include "RiaGrpcServiceInterface.h" +#include "RiaPorosityModel.h" + +#include + +namespace rips +{ +class Case; +} + +class RiaAbstractGrpcCallback; +class RigCell; +class RigActiveCellInfo; +class RimEclipseCase; + +//================================================================================================== +// +// State handler for streaming of active cell info +// +//================================================================================================== +class RiaActiveCellInfoStateHandler +{ +public: + typedef grpc::Status Status; + + RiaActiveCellInfoStateHandler(); + + Status init(const rips::ActiveCellInfoRequest* request); + Status assignNextActiveCellInfoData(rips::ActiveCellInfo* cellInfo); + void assignActiveCellInfoData(rips::ActiveCellInfo* cellInfo, const std::vector& reservoirCells, size_t cellIdx); + Status assignReply(rips::ActiveCellInfoArray* reply); + RigActiveCellInfo* activeCellInfo() const; + const std::vector& reservoirCells() const; + +protected: + const rips::ActiveCellInfoRequest* m_request; + RimEclipseCase* m_eclipseCase; + RiaDefines::PorosityModelType m_porosityModel; + RigActiveCellInfo* m_activeCellInfo; + std::vector m_globalCoarseningBoxIndexStart; + size_t m_currentCellIdx; +}; + +//================================================================================================== +// +// gRPC-service answering requests about grid information for a given case +// +//================================================================================================== +class RiaGrpcGridInfoService final : public rips::GridInfo::AsyncService, public RiaGrpcServiceInterface +{ +public: + grpc::Status GetGridCount(grpc::ServerContext* context, const rips::Case* request, rips::GridCount* reply) override; + grpc::Status GetGridDimensions(grpc::ServerContext* context, const rips::Case* request, rips::GridDimensions* reply) override; + grpc::Status StreamActiveCellInfo(grpc::ServerContext* context, + const rips::ActiveCellInfoRequest* request, + rips::ActiveCellInfoArray* reply, + RiaActiveCellInfoStateHandler* stateHandler); + std::vector createCallbacks() override; +}; diff --git a/ApplicationCode/GrpcInterface/RiaGrpcProjectInfoService.cpp b/ApplicationCode/GrpcInterface/RiaGrpcProjectInfoService.cpp new file mode 100644 index 0000000000..1e60b77b44 --- /dev/null +++ b/ApplicationCode/GrpcInterface/RiaGrpcProjectInfoService.cpp @@ -0,0 +1,249 @@ +#include "RiaGrpcProjectInfoService.h" + +#include "RiaApplication.h" +#include "RiaGrpcCallbacks.h" +#include "RiaSocketTools.h" + +#include "RimCase.h" +#include "RimCaseCollection.h" +#include "RimEclipseCase.h" +#include "RimEclipseCaseCollection.h" +#include "RimGeoMechCase.h" +#include "RimGridView.h" +#include "RimIdenticalGridCaseGroup.h" +#include "RimOilField.h" +#include "RimProject.h" + +#include "cafSelectionManager.h" + +#include "CaseInfo.grpc.pb.h" + +using grpc::ServerCompletionQueue; +using grpc::ServerContext; +using grpc::Status; + +using namespace rips; + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +Status RiaGrpcProjectInfoService::CurrentCase(ServerContext* context, const rips::Empty* request, rips::Case* reply) +{ + RimGridView* view = RiaApplication::instance()->activeGridView(); + if (view) + { + RimCase* currentCase = view->ownerCase(); + if (currentCase) + { + reply->set_id(currentCase->caseId()); + return Status::OK; + } + } + return Status(grpc::NOT_FOUND, "No current case found"); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +Status RiaGrpcProjectInfoService::CurrentCaseInfo(ServerContext* context, const rips::Empty* request, rips::CaseInfo* reply) +{ + RimGridView* view = RiaApplication::instance()->activeGridView(); + if (view) + { + RimCase* currentCase = view->ownerCase(); + if (currentCase) + { + qint64 caseId = currentCase->caseId(); + qint64 caseGroupId = -1; + QString caseName, caseType; + RiaSocketTools::getCaseInfoFromCase(currentCase, caseId, caseName, caseType, caseGroupId); + + reply->set_id(caseId); + reply->set_group_id(caseGroupId); + reply->set_name(caseName.toStdString()); + reply->set_type(caseType.toStdString()); + return Status::OK; + } + } + return Status(grpc::NOT_FOUND, "No current case found"); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +grpc::Status + RiaGrpcProjectInfoService::CaseInfoFromCase(grpc::ServerContext* context, const rips::Case* request, rips::CaseInfo* reply) +{ + RimCase* rimCase = findCase(request->id()); + if (rimCase) + { + qint64 caseId = rimCase->caseId(); + qint64 caseGroupId = -1; + QString caseName, caseType; + RiaSocketTools::getCaseInfoFromCase(rimCase, caseId, caseName, caseType, caseGroupId); + + reply->set_id(caseId); + reply->set_group_id(caseGroupId); + reply->set_name(caseName.toStdString()); + reply->set_type(caseType.toStdString()); + return Status::OK; + } + return Status(grpc::NOT_FOUND, "No cases found"); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +Status RiaGrpcProjectInfoService::SelectedCases(ServerContext* context, const rips::Empty* request, rips::CaseInfos* reply) +{ + std::vector cases; + caf::SelectionManager::instance()->objectsByType(&cases); + + if (cases.empty()) + { + return Status(grpc::NOT_FOUND, "No cases selected"); + } + + for (RimCase* rimCase : cases) + { + qint64 caseId = rimCase->caseId(); + qint64 caseGroupId = -1; + QString caseName, caseType; + RiaSocketTools::getCaseInfoFromCase(rimCase, caseId, caseName, caseType, caseGroupId); + + rips::CaseInfo* caseInfo = reply->add_case_info(); + caseInfo->set_id(caseId); + caseInfo->set_group_id(caseGroupId); + caseInfo->set_name(caseName.toStdString()); + caseInfo->set_type(caseType.toStdString()); + } + return Status::OK; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +grpc::Status + RiaGrpcProjectInfoService::AllCaseGroups(grpc::ServerContext* context, const rips::Empty* request, rips::CaseGroups* reply) +{ + RimProject* proj = RiaApplication::instance()->project(); + RimEclipseCaseCollection* analysisModels = + (proj && proj->activeOilField()) ? proj->activeOilField()->analysisModels() : nullptr; + if (analysisModels) + { + for (RimIdenticalGridCaseGroup* cg : analysisModels->caseGroups()) + { + rips::CaseGroup* caseGroup = reply->add_case_group(); + caseGroup->set_id(cg->groupId()); + caseGroup->set_name(cg->name().toStdString()); + } + return Status::OK; + } + return Status(grpc::NOT_FOUND, "No case groups found"); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +grpc::Status RiaGrpcProjectInfoService::AllCases(grpc::ServerContext* context, const rips::Empty* request, rips::CaseInfos* reply) +{ + std::vector cases; + RiaApplication::instance()->project()->allCases(cases); + + if (cases.empty()) + { + return Status(grpc::NOT_FOUND, "No cases found"); + } + + for (RimCase* rimCase : cases) + { + qint64 caseId = rimCase->caseId(); + qint64 caseGroupId = -1; + QString caseName, caseType; + RiaSocketTools::getCaseInfoFromCase(rimCase, caseId, caseName, caseType, caseGroupId); + + rips::CaseInfo* caseInfo = reply->add_case_info(); + caseInfo->set_id(caseId); + caseInfo->set_group_id(caseGroupId); + caseInfo->set_name(caseName.toStdString()); + caseInfo->set_type(caseType.toStdString()); + } + return Status::OK; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +grpc::Status + RiaGrpcProjectInfoService::CasesInGroup(grpc::ServerContext* context, const rips::CaseGroup* request, rips::CaseInfos* reply) +{ + RimProject* proj = RiaApplication::instance()->project(); + RimEclipseCaseCollection* analysisModels = + (proj && proj->activeOilField()) ? proj->activeOilField()->analysisModels() : nullptr; + if (analysisModels) + { + int groupId = request->id(); + RimIdenticalGridCaseGroup* caseGroup = nullptr; + + for (size_t i = 0; i < analysisModels->caseGroups().size(); i++) + { + RimIdenticalGridCaseGroup* cg = analysisModels->caseGroups()[i]; + + if (groupId == cg->groupId()) + { + caseGroup = cg; + } + } + + std::vector cases; + if (caseGroup) + { + for (size_t i = 0; i < caseGroup->statisticsCaseCollection()->reservoirs.size(); i++) + { + cases.push_back(caseGroup->statisticsCaseCollection()->reservoirs[i]); + } + + for (size_t i = 0; i < caseGroup->caseCollection()->reservoirs.size(); i++) + { + cases.push_back(caseGroup->caseCollection()->reservoirs[i]); + } + } + if (!cases.empty()) + { + for (RimCase* rimCase : cases) + { + qint64 caseId = rimCase->caseId(); + qint64 caseGroupId = -1; + QString caseName, caseType; + RiaSocketTools::getCaseInfoFromCase(rimCase, caseId, caseName, caseType, caseGroupId); + + rips::CaseInfo* caseInfo = reply->add_case_info(); + caseInfo->set_id(caseId); + caseInfo->set_group_id(caseGroupId); + caseInfo->set_name(caseName.toStdString()); + caseInfo->set_type(caseType.toStdString()); + } + } + } + return Status(grpc::NOT_FOUND, "No cases found"); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RiaGrpcProjectInfoService::createCallbacks() +{ + typedef RiaGrpcProjectInfoService Self; + + return { + new RiaGrpcCallback(this, &Self::CurrentCase, &Self::RequestCurrentCase), + new RiaGrpcCallback(this, &Self::CurrentCaseInfo, &Self::RequestCurrentCaseInfo), + new RiaGrpcCallback(this, &Self::CaseInfoFromCase, &Self::RequestCaseInfoFromCase), + new RiaGrpcCallback(this, &Self::SelectedCases, &Self::RequestSelectedCases), + new RiaGrpcCallback(this, &Self::AllCaseGroups, &Self::RequestAllCaseGroups), + new RiaGrpcCallback(this, &Self::AllCases, &Self::RequestAllCases), + new RiaGrpcCallback(this, &Self::CasesInGroup, &Self::RequestCasesInGroup)}; +} + +static bool RiaGrpcProjectInfoService_init = + RiaGrpcServiceFactory::instance()->registerCreator(typeid(RiaGrpcProjectInfoService).hash_code()); diff --git a/ApplicationCode/GrpcInterface/RiaGrpcProjectInfoService.h b/ApplicationCode/GrpcInterface/RiaGrpcProjectInfoService.h new file mode 100644 index 0000000000..b9db1a5375 --- /dev/null +++ b/ApplicationCode/GrpcInterface/RiaGrpcProjectInfoService.h @@ -0,0 +1,51 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 "ProjectInfo.grpc.pb.h" +#include "RiaGrpcServiceInterface.h" + +#include + +namespace rips +{ +class Empty; +class CaseInfo; +} // namespace rips + +class RiaAbstractGrpcCallback; + +//================================================================================================== +// +// gRPC-service answering requests about project information +// +//================================================================================================== +class RiaGrpcProjectInfoService final : public rips::ProjectInfo::AsyncService, public RiaGrpcServiceInterface +{ +public: + grpc::Status CurrentCase(grpc::ServerContext* context, const rips::Empty* request, rips::Case* reply) override; + grpc::Status CurrentCaseInfo(grpc::ServerContext* context, const rips::Empty* request, rips::CaseInfo* reply) override; + grpc::Status CaseInfoFromCase(grpc::ServerContext* context, const rips::Case* request, rips::CaseInfo* reply) override; + grpc::Status SelectedCases(grpc::ServerContext* context, const rips::Empty* request, rips::CaseInfos* reply) override; + grpc::Status AllCaseGroups(grpc::ServerContext* context, const rips::Empty* request, rips::CaseGroups* reply) override; + grpc::Status AllCases(grpc::ServerContext* context, const rips::Empty* request, rips::CaseInfos* reply) override; + grpc::Status CasesInGroup(grpc::ServerContext* context, const rips::CaseGroup* request, rips::CaseInfos* reply) override; + +public: + std::vector createCallbacks() override; +}; diff --git a/ApplicationCode/GrpcInterface/RiaGrpcResInfoService.cpp b/ApplicationCode/GrpcInterface/RiaGrpcResInfoService.cpp new file mode 100644 index 0000000000..6523f12073 --- /dev/null +++ b/ApplicationCode/GrpcInterface/RiaGrpcResInfoService.cpp @@ -0,0 +1,44 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 "RiaGrpcResInfoService.h" + +#include "RiaVersionInfo.h" +#include "RiaGrpcCallbacks.h" + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +grpc::Status RiaGrpcResInfoService::GetVersion(grpc::ServerContext* context, const rips::Empty* request, rips::Version* reply) +{ + reply->set_major_version(RESINSIGHT_MAJOR_VERSION); + reply->set_minor_version(RESINSIGHT_MINOR_VERSION); + reply->set_patch_version(RESINSIGHT_PATCH_VERSION); + return grpc::Status::OK; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RiaGrpcResInfoService::createCallbacks() +{ + typedef RiaGrpcResInfoService Self; + return { new RiaGrpcCallback(this, &Self::GetVersion, &Self::RequestGetVersion) }; +} + +static bool RiaGrpcResInfoService_init = + RiaGrpcServiceFactory::instance()->registerCreator(typeid(RiaGrpcResInfoService).hash_code()); diff --git a/ApplicationCode/GrpcInterface/RiaGrpcResInfoService.h b/ApplicationCode/GrpcInterface/RiaGrpcResInfoService.h new file mode 100644 index 0000000000..0f48ff3485 --- /dev/null +++ b/ApplicationCode/GrpcInterface/RiaGrpcResInfoService.h @@ -0,0 +1,50 @@ +#pragma once + +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 "RiaGrpcServiceInterface.h" + +#include "ResInfo.grpc.pb.h" + +#include +#include + +namespace rips +{ +class Empty; +class Version; +} + +namespace caf +{ +class PdmValueField; +} + +class RiaAbstractGrpcCallback; + +class RiaGrpcResInfoService : public rips::ResInfo::AsyncService, public RiaGrpcServiceInterface +{ +public: + grpc::Status GetVersion(grpc::ServerContext* context, const rips::Empty* request, rips::Version* reply) override; + std::vector createCallbacks() override; + +}; + + diff --git a/ApplicationCode/GrpcInterface/RiaGrpcServer.cpp b/ApplicationCode/GrpcInterface/RiaGrpcServer.cpp new file mode 100644 index 0000000000..7109cc2e33 --- /dev/null +++ b/ApplicationCode/GrpcInterface/RiaGrpcServer.cpp @@ -0,0 +1,366 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 "RiaGrpcServer.h" + +#include "RiaApplication.h" +#include "RiaDefines.h" + +#include "RiaGrpcCallbacks.h" +#include "RiaGrpcServiceInterface.h" +#include "RiaGrpcGridInfoService.h" + +#include "RigCaseCellResultsData.h" +#include "RigMainGrid.h" +#include "RimEclipseCase.h" +#include "RimProject.h" + +#include "cafAssert.h" + +#include +#include + +#include + +using grpc::CompletionQueue; +using grpc::Server; +using grpc::ServerAsyncResponseWriter; +using grpc::ServerBuilder; +using grpc::ServerCompletionQueue; +using grpc::ServerContext; +using grpc::Status; + +//================================================================================================== +// +// The GRPC server implementation +// +//================================================================================================== +class RiaGrpcServerImpl +{ +public: + RiaGrpcServerImpl(int portNumber); + ~RiaGrpcServerImpl(); + int portNumber() const; + bool isRunning() const; + void run(); + void runInThread(); + void initialize(); + void processOneRequest(); + void quit(); + int currentPortNumber; + +private: + void waitForNextRequest(); + void process(RiaAbstractGrpcCallback* method); + +private: + int m_portNumber; + std::unique_ptr m_completionQueue; + std::unique_ptr m_server; + std::list> m_services; + std::list m_unprocessedRequests; + std::mutex m_requestMutex; + std::thread m_thread; +}; + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiaGrpcServerImpl::RiaGrpcServerImpl(int portNumber) + : m_portNumber(portNumber) +{} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiaGrpcServerImpl::~RiaGrpcServerImpl() +{ + quit(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +int RiaGrpcServerImpl::portNumber() const +{ + return m_portNumber; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RiaGrpcServerImpl::isRunning() const +{ + return m_server != nullptr; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaGrpcServerImpl::run() +{ + initialize(); + while (true) + { + waitForNextRequest(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaGrpcServerImpl::runInThread() +{ + initialize(); + m_thread = std::thread(&RiaGrpcServerImpl::waitForNextRequest, this); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaGrpcServerImpl::initialize() +{ + CAF_ASSERT(m_portNumber > 0 && m_portNumber <= (int) std::numeric_limits::max()); + + QString serverAddress = QString("localhost:%1").arg(m_portNumber); + + ServerBuilder builder; + builder.AddListeningPort(serverAddress.toStdString(), grpc::InsecureServerCredentials()); + + for (auto key : RiaGrpcServiceFactory::instance()->allKeys()) + { + std::shared_ptr service(RiaGrpcServiceFactory::instance()->create(key)); + builder.RegisterService(dynamic_cast(service.get())); + m_services.push_back(service); + } + + m_completionQueue = builder.AddCompletionQueue(); + m_server = builder.BuildAndStart(); + + CVF_ASSERT(m_server); + RiaLogging::info(QString("Server listening on %1").arg(serverAddress)); + + // Spawn new CallData instances to serve new clients. + for (auto service : m_services) + { + for (auto callback : service->createCallbacks()) + { + process(callback); + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaGrpcServerImpl::processOneRequest() +{ + std::lock_guard requestLock(m_requestMutex); + if (!m_unprocessedRequests.empty()) + { + RiaAbstractGrpcCallback* method = m_unprocessedRequests.front(); + m_unprocessedRequests.pop_front(); + process(method); + } +} + +//-------------------------------------------------------------------------------------------------- +/// Gracefully shut down the GRPC server. The internal order is important. +//-------------------------------------------------------------------------------------------------- +void RiaGrpcServerImpl::quit() +{ + if (m_server) + { + RiaLogging::info("Shutting down gRPC server"); + // Clear unhandled requests + while (!m_unprocessedRequests.empty()) + { + RiaAbstractGrpcCallback* method = m_unprocessedRequests.front(); + m_unprocessedRequests.pop_front(); + delete method; + } + + // Shutdown server and queue + m_server->Shutdown(); + m_completionQueue->Shutdown(); + + // Wait for thread to join after handling the shutdown call + m_thread.join(); + + // Must destroy server before services + m_server.reset(); + m_completionQueue.reset(); + + // Finally clear services + m_services.clear(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaGrpcServerImpl::waitForNextRequest() +{ + void* tag; + bool ok = false; + + while (m_completionQueue->Next(&tag, &ok)) + { + RiaAbstractGrpcCallback* method = static_cast(tag); + if (ok) + { + std::lock_guard requestLock(m_requestMutex); + m_unprocessedRequests.push_back(method); + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaGrpcServerImpl::process(RiaAbstractGrpcCallback* method) +{ + if (method->callState() == RiaAbstractGrpcCallback::CREATE_HANDLER) + { + RiaLogging::debug(QString("Initialising request handler for: %1").arg(method->name())); + method->createRequestHandler(m_completionQueue.get()); + } + else if (method->callState() == RiaAbstractGrpcCallback::INIT_REQUEST) + { + // Perform initialization and immediately process the first request + // The initialization is necessary for streaming services. + RiaLogging::info(QString("Starting handling: %1").arg(method->name())); + method->initRequest(); + method->processRequest(); + } + else if (method->callState() == RiaAbstractGrpcCallback::PROCESS_REQUEST) + { + method->processRequest(); + } + else + { + RiaLogging::info(QString("Finished handling: %1").arg(method->name())); + method->finishRequest(); + process(method->createNewFromThis()); + delete method; + } +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiaGrpcServer::RiaGrpcServer(int portNumber) +{ + m_serverImpl = new RiaGrpcServerImpl(portNumber); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiaGrpcServer::~RiaGrpcServer() +{ + delete m_serverImpl; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +int RiaGrpcServer::portNumber() const +{ + if (m_serverImpl) return m_serverImpl->portNumber(); + + return 0; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RiaGrpcServer::isRunning() const +{ + if (m_serverImpl) return m_serverImpl->isRunning(); + + return false; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaGrpcServer::run() +{ + m_serverImpl->run(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaGrpcServer::runInThread() +{ + m_serverImpl->runInThread(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaGrpcServer::initialize() +{ + m_serverImpl->initialize(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaGrpcServer::processOneRequest() +{ + m_serverImpl->processOneRequest(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaGrpcServer::quit() +{ + if (m_serverImpl) + m_serverImpl->quit(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +int RiaGrpcServer::findAvailablePortNumber(int defaultPortNumber) +{ + int startPort = 50051; + + if (defaultPortNumber > 0 && defaultPortNumber < (int)std::numeric_limits::max()) + { + startPort = defaultPortNumber; + } + + int endPort = std::min(startPort + 100, (int)std::numeric_limits::max()); + + QTcpServer serverTest; + quint16 port = static_cast(startPort); + for (; port <= static_cast(endPort); ++port) + { + if (serverTest.listen(QHostAddress::LocalHost, port)) + { + return static_cast(port); + } + } + return -1; +} diff --git a/ApplicationCode/GrpcInterface/RiaGrpcServer.h b/ApplicationCode/GrpcInterface/RiaGrpcServer.h new file mode 100644 index 0000000000..90f27321e3 --- /dev/null +++ b/ApplicationCode/GrpcInterface/RiaGrpcServer.h @@ -0,0 +1,53 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 "RiaLogging.h" + +#include +#include +#include +#include + +class RiaGrpcServerImpl; + +//================================================================================================== +// +// The GRPC server. +// +//================================================================================================== +class RiaGrpcServer +{ +public: + RiaGrpcServer(int portNumber); + ~RiaGrpcServer(); + + int portNumber() const; + bool isRunning() const; + void run(); + void runInThread(); + void processOneRequest(); + void quit(); + static int findAvailablePortNumber(int defaultPortNumber); + +private: + void initialize(); + +private: + RiaGrpcServerImpl* m_serverImpl; +}; \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/RiaGrpcServiceInterface.cpp b/ApplicationCode/GrpcInterface/RiaGrpcServiceInterface.cpp new file mode 100644 index 0000000000..063cbafd0a --- /dev/null +++ b/ApplicationCode/GrpcInterface/RiaGrpcServiceInterface.cpp @@ -0,0 +1,54 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 "RiaGrpcServiceInterface.h" + +#include "RiaApplication.h" +#include "RimProject.h" +#include "RimCase.h" + +#include + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimCase* RiaGrpcServiceInterface::findCase(int caseId) +{ + std::vector cases; + RiaApplication::instance()->project()->allCases(cases); + + for (RimCase* rimCase : cases) + { + if (caseId == rimCase->caseId()) + { + return rimCase; + } + } + return nullptr; +} + +//-------------------------------------------------------------------------------------------------- +/// Find the number of messages that will fit in the given bytes. +/// The default argument is meant to be a sensible size for GRPC. +//-------------------------------------------------------------------------------------------------- +size_t RiaGrpcServiceInterface::numberOfMessagesForByteCount(size_t messageSize, + size_t numBytesWantedInPackage /*= 64 * 1024u*/) +{ + size_t messageCount = numBytesWantedInPackage / messageSize; + return messageCount; +} + diff --git a/ApplicationCode/GrpcInterface/RiaGrpcServiceInterface.h b/ApplicationCode/GrpcInterface/RiaGrpcServiceInterface.h new file mode 100644 index 0000000000..0d5383ed39 --- /dev/null +++ b/ApplicationCode/GrpcInterface/RiaGrpcServiceInterface.h @@ -0,0 +1,43 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 + +class RiaAbstractGrpcCallback; +class RimCase; + +//================================================================================================== +// +// gRPC-service interface which all gRPC-services has to implement +// +//================================================================================================== +class RiaGrpcServiceInterface +{ +public: + virtual std::vector createCallbacks() = 0; + virtual ~RiaGrpcServiceInterface() = default; + static RimCase* findCase(int caseId); + static size_t numberOfMessagesForByteCount(size_t messageSize, size_t byteCount = 64 * 1024u); +}; + +#include "cafFactory.h" +typedef caf::Factory RiaGrpcServiceFactory; + diff --git a/ApplicationCode/ReservoirDataModel/RigFlowDiagResults.cpp b/ApplicationCode/ReservoirDataModel/RigFlowDiagResults.cpp index 65bc42d058..eb22352fba 100644 --- a/ApplicationCode/ReservoirDataModel/RigFlowDiagResults.cpp +++ b/ApplicationCode/ReservoirDataModel/RigFlowDiagResults.cpp @@ -703,7 +703,7 @@ double RigFlowDiagResults::maxAbsPairFlux(int timeStepIndex) calculateNativeResultsIfNotPreviouslyAttempted(timeStepIndex, RigFlowDiagResultAddress::PHASE_ALL); double maxFlux = 0.0; - if (timeStepIndex < m_injProdPairFluxCommunicationTimesteps.size()) + if ((size_t) timeStepIndex < m_injProdPairFluxCommunicationTimesteps.size()) { for (const auto& commPair : m_injProdPairFluxCommunicationTimesteps[timeStepIndex][RigFlowDiagResultAddress::PHASE_ALL]) { diff --git a/Fwk/AppFwk/cafUserInterface/cafProgressInfo.cpp b/Fwk/AppFwk/cafUserInterface/cafProgressInfo.cpp index d730a475e2..872b48430a 100644 --- a/Fwk/AppFwk/cafUserInterface/cafProgressInfo.cpp +++ b/Fwk/AppFwk/cafUserInterface/cafProgressInfo.cpp @@ -456,6 +456,7 @@ namespace caf { //================================================================================================== bool ProgressInfoStatic::s_disabled = false; + bool ProgressInfoStatic::s_running = false; //-------------------------------------------------------------------------------------------------- /// @@ -488,7 +489,7 @@ namespace caf { } } } - + s_running = true; maxProgressStack_v.push_back(maxProgressValue); progressStack_v.push_back(0); progressSpanStack_v.push_back(1); @@ -610,6 +611,14 @@ namespace caf { } + //-------------------------------------------------------------------------------------------------- + /// + //-------------------------------------------------------------------------------------------------- + bool ProgressInfoStatic::isRunning() + { + return s_running; + } + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -652,6 +661,7 @@ namespace caf { { dialog->reset(); dialog->close(); + s_running = false; } } else diff --git a/Fwk/AppFwk/cafUserInterface/cafProgressInfo.h b/Fwk/AppFwk/cafUserInterface/cafProgressInfo.h index 135df74094..63e093d20f 100644 --- a/Fwk/AppFwk/cafUserInterface/cafProgressInfo.h +++ b/Fwk/AppFwk/cafUserInterface/cafProgressInfo.h @@ -85,14 +85,14 @@ public: static void setProgress(size_t progressValue); static void incrementProgress(); static void setNextProgressIncrement(size_t nextStepSize); - + static bool isRunning(); static void finished(); private: static bool isUpdatePossible(); private: friend class ProgressInfoBlocker; - + static bool s_running; static bool s_disabled; }; diff --git a/GRPC_install_instructions.txt b/GRPC_install_instructions.txt new file mode 100644 index 0000000000..147bf85090 --- /dev/null +++ b/GRPC_install_instructions.txt @@ -0,0 +1,33 @@ +########## Windows using vcpkg ################### +1. Clone VCPKG +git clone https://github.com/microsoft/vcpkg.git + +4. Install VCPKG from within vcpkg folder: +.\boostrap-vcpkg.sh +5. Perform integrated install (as admin) within vcpkg folder. Not sure if it is necessary. +.\vcpkg integrate install +5. Install GRPC +.\vcpkg install grpc --triplet x64-windows +6. Run cmake with -DCMAKE_TOOLCHAIN_FILE=LOCATION_OF_VCPKG/buildsystems/vcpkg.cmake + This can be set on the configure dialog that comes up when you press configure with a fresh build folder. +7. Enable GRPC by setting RESINSIGHT_ENABLE_GRPC = true +8. Make sure the python executable is found by setting PYTHON_EXECUTABLE=LOCATION_OF_PYTHON.EXE + +############ Linux as STANDALONE GPRC (using GRPC_INSTALL_PREFIX=/opt/grpc as an example) ############### +1. Clone grpc +https://github.com/grpc/grpc.git +2. From within grpc folder, check out stable version of grpc and initialise repo: +git checkout v1.20.1 +git submodule init +git submodule update +3. Make sure you're building with devtools-3, since you'll be using that for ResInsight too +scl enable devtoolset-3 bash +make prefix=/opt/grpc +sudo make prefix=/opt/grpc install +3. Install protobuf (still within grpc folder) +cd third_party/protobuf +sudo make prefix=/opt/grpc install +4. Install grpcio-tools for Python (this may have to be done as root user): +pip install grpcio-tools +5. Run cmake making sure GRPC_INSTALL_PREFIX is set to /opt/grpc, PYTHON_EXECUTABLE set to a good python 3 and RESINSIGHT_ENABLE_GRPC = true + diff --git a/Python/.gitignore b/Python/.gitignore new file mode 100644 index 0000000000..71b76e8465 --- /dev/null +++ b/Python/.gitignore @@ -0,0 +1,3 @@ +__pycache__ +.pytest_cache +generated \ No newline at end of file diff --git a/Python/api/ResInsight.py b/Python/api/ResInsight.py new file mode 100644 index 0000000000..c869fa029c --- /dev/null +++ b/Python/api/ResInsight.py @@ -0,0 +1,159 @@ +from __future__ import print_function + +import grpc +import os +import sys +import socket + +sys.path.insert(1, os.path.join(sys.path[0], '../generated')) + +import Empty_pb2 +import CaseInfo_pb2 +import CaseInfo_pb2_grpc +import Commands_pb2 +import Commands_pb2_grpc +import GridInfo_pb2 +import GridInfo_pb2_grpc +import ProjectInfo_pb2 +import ProjectInfo_pb2_grpc +import ResInfo_pb2 +import ResInfo_pb2_grpc +import RiaVersionInfo + +MAX_MESSAGE_LENGTH = 128 * 1024 * 1024 + +class ResInfo: + def __init__(self, channel): + self.resInfo = ResInfo_pb2_grpc.ResInfoStub(channel) + def versionMessage(self): + return self.resInfo.GetVersion(Empty_pb2.Empty()) + def majorVersion(self): + return self.versionMessage().major_version + def minorVersion(self): + return self.versionMessage().minor_version + def patchVersion(self): + return self.versionMessage().patch_version + def versionString(self): + return str(self.majorVersion()) + "." + str(self.minorVersion()) + "." + str(self.patchVersion()) + +class CommandExecutor: + def __init__(self, channel): + self.commands = Commands_pb2_grpc.CommandsStub(channel) + + def execute(self, commandParams): + try: + self.commands.Execute(commandParams) + except grpc.RpcError as e: + if e.code() == grpc.StatusCode.NOT_FOUND: + print("Command not found") + else: + print("Other error") + + def setTimeStep(self, caseId, timeStep): + return self.execute(Commands_pb2.CommandParams(setTimeStep=Commands_pb2.SetTimeStepParams(caseId=caseId, timeStep=timeStep))) + + def setMainWindowSize(self, width, height): + return self.execute(Commands_pb2.CommandParams(setMainWindowSize=Commands_pb2.SetMainWindowSizeParams(width=width, height=height))) + + def openProject(self, path): + return self.execute(Commands_pb2.CommandParams(openProject=Commands_pb2.FilePathRequest(path=path))) + + def loadCase(self, path): + return self.execute(Commands_pb2.CommandParams(loadCase=Commands_pb2.FilePathRequest(path=path))) + + def closeProject(self): + return self.execute(Commands_pb2.CommandParams(closeProject=Empty_pb2.Empty())) + +class GridInfo: + def __init__(self, channel): + self.gridInfo = GridInfo_pb2_grpc.GridInfoStub(channel) + + def getGridCount(self, caseId=0): + return self.gridInfo.GetGridCount(CaseInfo_pb2.Case(id=caseId)).count + + def getGridDimensions(self, caseId=0): + return self.gridInfo.GetGridDimensions(CaseInfo_pb2.Case(id=caseId)).dimensions + + def streamActiveCellInfo(self, caseId=0): + return self.gridInfo.StreamActiveCellInfo(CaseInfo_pb2.Case(id=caseId)) + +class ProjectInfo: + def __init__(self, channel): + self.projectInfo = ProjectInfo_pb2_grpc.ProjectInfoStub(channel) + def selectedCases(self): + selected = self.projectInfo.SelectedCases(Empty_pb2.Empty()) + if selected is not None: + return selected.case_info + else: + return None + def allCases(self): + cases = self.projectInfo.AllCases(Empty_pb2.Empty()) + if cases is not None: + return allCases.case_info + else: + return None + +class Instance: + @staticmethod + def is_port_in_use(port): + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: + s.settimeout(0.2) + return s.connect_ex(('localhost', port)) == 0 + + @staticmethod + def launch(): + port = 50051 + portEnv = os.environ.get('RESINSIGHT_GRPC_PORT') + if portEnv: + port = int(portEnv) + + resInsightExecutable = os.environ.get('RESINSIGHT_EXECUTABLE') + if resInsightExecutable is None: + print('Error: Could not launch any ResInsight instances because RESINSIGHT_EXECUTABLE is not set') + return None + + while Instance.is_port_in_use(port): + port += 1 + + print('Port ' + str(port)) + print('Trying to launch', resInsightExecutable) + pid = os.spawnl(os.P_NOWAIT, resInsightExecutable, " --grpcserver " + str(port)) + print(pid) + return Instance(port) + + @staticmethod + def find(startPort = 50051, endPort = 50071): + portEnv = os.environ.get('RESINSIGHT_GRPC_PORT') + if portEnv: + startPort = int(portEnv) + endPort = startPort + 20 + + for tryPort in range(startPort, endPort): + if Instance.is_port_in_use(tryPort): + return Instance(tryPort) + + print('Error: Could not find any ResInsight instances responding between ports ' + str(startPort) + ' and ' + str(endPort)) + return None + + def __init__(self, port = 50051): + location = "localhost:" + str(port) + self.channel = grpc.insecure_channel(location, options=[('grpc.max_receive_message_length', MAX_MESSAGE_LENGTH)]) + + # Main version check package + self.resInfo = ResInfo(self.channel) + try: + majorVersionOk = self.resInfo.majorVersion() == int(RiaVersionInfo.RESINSIGHT_MAJOR_VERSION) + minorVersionOk = self.resInfo.minorVersion() == int(RiaVersionInfo.RESINSIGHT_MINOR_VERSION) + if not (majorVersionOk and minorVersionOk): + raise Exception('Version of ResInsight does not match version of Python API') + except grpc.RpcError as e: + if e.code() == grpc.StatusCode.UNAVAILABLE: + print('Info: Could not find any instances at port ' + str(port)) + except Exception as e: + print('Error:', e) + + # Service packages + self.commands = CommandExecutor(self.channel) + self.gridInfo = GridInfo(self.channel) + self.projectInfo = ProjectInfo(self.channel) + \ No newline at end of file diff --git a/Python/api/__init__.py b/Python/api/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/Python/examples/AllCases.py b/Python/examples/AllCases.py new file mode 100644 index 0000000000..3ee8615c8b --- /dev/null +++ b/Python/examples/AllCases.py @@ -0,0 +1,13 @@ +import sys +import os +sys.path.insert(1, os.path.join(sys.path[0], '../api')) + +import ResInsight + +resInsight = ResInsight.Instance.find() +if resInsight is not None: + caseInfos = resInsight.projectInfo.allCases() + + print ("Got " + str(len(caseInfos)) + " cases: ") + for caseInfo in caseInfos: + print(caseInfo.name) diff --git a/Python/examples/CommandExample.py b/Python/examples/CommandExample.py new file mode 100644 index 0000000000..cca0159775 --- /dev/null +++ b/Python/examples/CommandExample.py @@ -0,0 +1,11 @@ +import sys +import os +sys.path.insert(1, os.path.join(sys.path[0], '../api')) +import ResInsight + +# Load instance +resInsight = ResInsight.Instance.find() + +# Run a couple of commands +resInsight.commands.setTimeStep(caseId=0, timeStep=3) +resInsight.commands.setMainWindowSize(width=800, height=500) \ No newline at end of file diff --git a/Python/examples/GridInfoStreamingExample.py b/Python/examples/GridInfoStreamingExample.py new file mode 100644 index 0000000000..999dc7f25c --- /dev/null +++ b/Python/examples/GridInfoStreamingExample.py @@ -0,0 +1,21 @@ +import sys +import os +sys.path.insert(1, os.path.join(sys.path[0], '../api')) +import ResInsight + +resInsight = ResInsight.Instance.find() +#gridCount = resInsight.gridInfo.getGridCount(caseId=0) +#gridDimensions = resInsight.gridInfo.getAllGridDimensions(caseId=0) + +activeCellInfoChunks = resInsight.gridInfo.streamActiveCellInfo(caseId=0) + +#print("Number of grids: " + str(gridCount)) +#print(gridDimensions) + +receivedActiveCells = [] +for activeCellChunk in activeCellInfoChunks: + for activeCell in activeCellChunk.data: + receivedActiveCells.append(activeCell) +print("Number of active cells: " + str(len(receivedActiveCells))) +print("First active cell: ") +print(receivedActiveCells[0]) diff --git a/Python/examples/ResultValues.py b/Python/examples/ResultValues.py new file mode 100644 index 0000000000..ef9a16b2d9 --- /dev/null +++ b/Python/examples/ResultValues.py @@ -0,0 +1,45 @@ +from ResInsight import ResInsight +import grpc +import logging +import sys + +def run(): + # NOTE(gRPC Python Team): .close() is possible on a channel and should be + # used in circumstances in which the with statement does not fit the needs + # of the code. + logging.basicConfig() + + try: + port = 50051 + if len(sys.argv) > 1: + port = sys.argv[1] + resInsight = ResInsight("localhost:" + port) + timeStepsInfo = resInsight.grid.numberOfTimeSteps(ResInsight.Case(id=0)) + print ("Number of time steps: " + str(timeStepsInfo.value)) + resultsAllTimeSteps = [] + for timeStep in range(0, timeStepsInfo.value - 1): + results = resInsight.grid.results(ResInsight.ResultRequest(ResInsight.Case(id=0), ResInsight.ResultAddress(0, "SOIL"), timeStep)) + print ("Got " + str(len(results.value)) + " values") + resultsAllTimeSteps.append(results.value) + + print("Have stored results array containing " + str(len(resultsAllTimeSteps)) + " time steps") + + print("Looking for first cell with a decent SOIL value") + indexFirstProperCell = 0 + for i in range(0, len(resultsAllTimeSteps[0])): + result = resultsAllTimeSteps[0][i] + if indexFirstProperCell == 0 and result > 0.01: + indexFirstProperCell = i + + for resultsForTimeStep in resultsAllTimeSteps: + print ("Result for cell " + str(indexFirstProperCell) + ": " + str(resultsForTimeStep[indexFirstProperCell])) + + except grpc.RpcError as e: + if e.code() == grpc.StatusCode.NOT_FOUND: + print("Case id not found") + else: + logging.error('Other error: %s', e) + + +if __name__ == '__main__': + run() diff --git a/Python/examples/SelectedCases.py b/Python/examples/SelectedCases.py new file mode 100644 index 0000000000..4fc50426ec --- /dev/null +++ b/Python/examples/SelectedCases.py @@ -0,0 +1,14 @@ +import sys +import os +sys.path.insert(1, os.path.join(sys.path[0], '../api')) + +import ResInsight + +resInsight = ResInsight.Instance.find() +if resInsight is not None: + caseInfos = resInsight.projectInfo.selectedCases() + + print ("Got " + str(len(caseInfos)) + " cases: ") + for caseInfo in caseInfos: + print(caseInfo.name) + diff --git a/Python/tests/test_sample.py b/Python/tests/test_sample.py new file mode 100644 index 0000000000..8a0206c83c --- /dev/null +++ b/Python/tests/test_sample.py @@ -0,0 +1,51 @@ + +import os, sys + +# Add the 'api' path to system path to be able to import modules from the 'api' folder +# python current working directory must be 'tests' +sys.path.insert(1, os.path.join(sys.path[0], '..\\api')) + +import ResInsight + +resInsight = ResInsight.Instance() + + +# content of test_sample.py +def getActiveCellCount(caseId): + activeCellInfoChunks = resInsight.gridInfo.streamActiveCellInfo(caseId) + + receivedActiveCells = [] + for activeCellChunk in activeCellInfoChunks: + for activeCell in activeCellChunk.data: + receivedActiveCells.append(activeCell) + return len(receivedActiveCells) + +def myOpenProject(filepath): + resInsight = ResInsight.Instance() + #resInsight.commands.setMainWindowSize(width=800, height=500) + resInsight.commands.openProject(filepath) + +def test_openProjectAndCountCells(): + testRepositoryRoot = "d:\\gitroot-ceesol\\ResInsight-regression-test" + + #casePath = testRepositoryRoot + "\\ModelData\\TEST10K_FLT_LGR_NNC\\TEST10K_FLT_LGR_NNC.EGRID" + #openEclipseCase(casePath) + +# projectPath = testRepositoryRoot + "\\ProjectFiles\\ProjectFilesSmallTests\\TestCase_10K_Complete\\RegressionTest.rsp" +# projectPath = testRepositoryRoot + "\\ProjectFiles\\ProjectFilesSmallTests\\TestCase_Norne\\RegressionTest.rsp" + projectPath = testRepositoryRoot + "\\ProjectFiles\\ProjectFilesSmallTests\\TestCase_10K_Watertight\\RegressionTest.rsp" + myOpenProject(projectPath) + + assert getActiveCellCount(0) == 11125 + + + +def test_openCaseAndCountCells(): + testRepositoryRoot = "d:\\gitroot-ceesol\\ResInsight-regression-test" + + casePath = testRepositoryRoot + "\\ModelData\\TEST10K_FLT_LGR_NNC\\TEST10K_FLT_LGR_NNC.EGRID" + resInsight.commands.loadCase(casePath) + + assert getActiveCellCount(0) == 11125 + + resInsight.commands.closeProject() From 8b5b15c3d25ab652775b9f275d0fad4f6576dca6 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 20 May 2019 15:11:35 +0200 Subject: [PATCH 055/396] Update GRPC_install_instructions.txt --- GRPC_install_instructions.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GRPC_install_instructions.txt b/GRPC_install_instructions.txt index 147bf85090..689a4f540c 100644 --- a/GRPC_install_instructions.txt +++ b/GRPC_install_instructions.txt @@ -3,7 +3,7 @@ git clone https://github.com/microsoft/vcpkg.git 4. Install VCPKG from within vcpkg folder: -.\boostrap-vcpkg.sh +.\boostrap-vcpkg.bat 5. Perform integrated install (as admin) within vcpkg folder. Not sure if it is necessary. .\vcpkg integrate install 5. Install GRPC From 4aad1e61d1230a34d336e6855f433359b6a514bf Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Mon, 20 May 2019 14:24:53 +0200 Subject: [PATCH 056/396] Fix tabs in CMakefiles --- ApplicationCode/CMakeLists.txt | 160 ++++++------- .../GrpcInterface/CMakeLists.cmake | 226 +++++++++--------- 2 files changed, 193 insertions(+), 193 deletions(-) diff --git a/ApplicationCode/CMakeLists.txt b/ApplicationCode/CMakeLists.txt index cd404ae8d0..0167332191 100644 --- a/ApplicationCode/CMakeLists.txt +++ b/ApplicationCode/CMakeLists.txt @@ -6,15 +6,15 @@ project (ApplicationCode) find_package( OpenGL ) if (RESINSIGHT_BUILD_WITH_QT5) - find_package(Qt5 COMPONENTS Core QUIET) + find_package(Qt5 COMPONENTS Core QUIET) endif(RESINSIGHT_BUILD_WITH_QT5) if (Qt5Core_FOUND) - find_package(Qt5 CONFIG REQUIRED Core Gui OpenGL Network Script Widgets) + find_package(Qt5 CONFIG REQUIRED Core Gui OpenGL Network Script Widgets) set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Network Qt5::OpenGL Qt5::Script Qt5::Widgets) else() set (QT_COMPONENTS_REQUIRED QtCore QtGui QtMain QtOpenGl QtNetwork QtScript) - find_package(Qt4 COMPONENTS ${QT_COMPONENTS_REQUIRED} REQUIRED) + find_package(Qt4 COMPONENTS ${QT_COMPONENTS_REQUIRED} REQUIRED) include(${QT_USE_FILE}) endif(Qt5Core_FOUND) @@ -47,7 +47,7 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/Commands ${CMAKE_CURRENT_SOURCE_DIR}/Commands/EclipseCommands ${CMAKE_CURRENT_SOURCE_DIR}/FileInterface - ${CMAKE_CURRENT_SOURCE_DIR}/GrpcInterface + ${CMAKE_CURRENT_SOURCE_DIR}/GrpcInterface ${CMAKE_CURRENT_SOURCE_DIR}/SocketInterface ${CMAKE_CURRENT_SOURCE_DIR}/Measurement ${CMAKE_CURRENT_SOURCE_DIR}/ModelVisualization @@ -61,7 +61,7 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/ProjectDataModel/Annotations ${CMAKE_CURRENT_SOURCE_DIR}/ProjectDataModel/Completions ${CMAKE_CURRENT_SOURCE_DIR}/ProjectDataModel/Flow - ${CMAKE_CURRENT_SOURCE_DIR}/ProjectDataModel/GridCrossPlots + ${CMAKE_CURRENT_SOURCE_DIR}/ProjectDataModel/GridCrossPlots ${CMAKE_CURRENT_SOURCE_DIR}/ProjectDataModel/Measurement ${CMAKE_CURRENT_SOURCE_DIR}/ProjectDataModel/Summary @@ -102,9 +102,9 @@ list( APPEND CPP_SOURCES ) if (RESINSIGHT_ENABLE_GRPC) - list( APPEND REFERENCED_CMAKE_FILES - GrpcInterface/CMakeLists.cmake - ) + list( APPEND REFERENCED_CMAKE_FILES + GrpcInterface/CMakeLists.cmake + ) endif(RESINSIGHT_ENABLE_GRPC) list( APPEND REFERENCED_CMAKE_FILES @@ -118,8 +118,8 @@ list( APPEND REFERENCED_CMAKE_FILES FileInterface/CMakeLists_files.cmake ProjectDataModel/CMakeLists_files.cmake - ProjectDataModel/GridCrossPlots/CMakeLists_files.cmake - ProjectDataModel/GridCrossPlots/CellFilters/CMakeLists_files.cmake + ProjectDataModel/GridCrossPlots/CMakeLists_files.cmake + ProjectDataModel/GridCrossPlots/CellFilters/CMakeLists_files.cmake ProjectDataModel/Summary/CMakeLists_files.cmake ProjectDataModel/Flow/CMakeLists_files.cmake ProjectDataModel/Annotations/CMakeLists_files.cmake @@ -145,7 +145,7 @@ list( APPEND REFERENCED_CMAKE_FILES Commands/EclipseCommands/EclipseWell/CMakeLists_files.cmake Commands/ExportCommands/CMakeLists_files.cmake Commands/FlowCommands/CMakeLists_files.cmake - Commands/GridCrossPlotCommands/CMakeLists_files.cmake + Commands/GridCrossPlotCommands/CMakeLists_files.cmake Commands/HoloLensCommands/CMakeLists_files.cmake Commands/IntersectionBoxCommands/CMakeLists_files.cmake Commands/IntersectionViewCommands/CMakeLists_files.cmake @@ -162,7 +162,7 @@ list( APPEND REFERENCED_CMAKE_FILES CommandFileInterface/Core/CMakeLists_files.cmake Commands/FractureCommands/CMakeLists_files.cmake ) - + option (RESINSIGHT_INCLUDE_APPLICATION_UNIT_TESTS "Include ApplicationCode Unit Tests" OFF) if (RESINSIGHT_INCLUDE_APPLICATION_UNIT_TESTS) add_definitions(-DUSE_UNIT_TESTS) @@ -254,10 +254,10 @@ set ( QT_MOC_HEADERS ) if (Qt5Core_FOUND) - qt5_wrap_cpp(MOC_SOURCE_FILES ${QT_MOC_HEADERS} ) + qt5_wrap_cpp(MOC_SOURCE_FILES ${QT_MOC_HEADERS} ) qt5_wrap_ui( FORM_FILES_CPP ${QT_UI_FILES} ) else() - qt4_wrap_cpp(MOC_SOURCE_FILES ${QT_MOC_HEADERS} ) + qt4_wrap_cpp(MOC_SOURCE_FILES ${QT_MOC_HEADERS} ) qt4_wrap_ui( FORM_FILES_CPP ${QT_UI_FILES} ) endif() @@ -276,15 +276,15 @@ set( QRC_FILES # Runs RCC on specified files if ( NOT CMAKE_AUTOMOC) - if (Qt5Core_FOUND) - qt5_add_resources( QRC_FILES_CPP - ${QRC_FILES} - ) - else() - qt4_add_resources( QRC_FILES_CPP - ${QRC_FILES} - ) - endif(Qt5Core_FOUND) + if (Qt5Core_FOUND) + qt5_add_resources( QRC_FILES_CPP + ${QRC_FILES} + ) + else() + qt4_add_resources( QRC_FILES_CPP + ${QRC_FILES} + ) + endif(Qt5Core_FOUND) endif(NOT CMAKE_AUTOMOC) # Adding resource (RC) files for Windows @@ -315,16 +315,16 @@ source_group( "UnitTests" FILES ${UNIT_TEST_FILES} ) if (MSVC) set( EXE_FILES WIN32) - if (RESINSIGHT_ENABLE_GRPC) - # GRPC generates a lot of harmless warnings on MSVC - set_source_files_properties(${GRPC_CPP_SOURCES} PROPERTIES COMPILE_FLAGS "/wd4251 /wd4702 /wd4005 /wd4244 /wd4125") - endif(RESINSIGHT_ENABLE_GRPC) + if (RESINSIGHT_ENABLE_GRPC) + # GRPC generates a lot of harmless warnings on MSVC + set_source_files_properties(${GRPC_CPP_SOURCES} PROPERTIES COMPILE_FLAGS "/wd4251 /wd4702 /wd4005 /wd4244 /wd4125") + endif(RESINSIGHT_ENABLE_GRPC) elseif (APPLE) set( EXE_FILES MACOSX_BUNDLE) endif() set( EXE_FILES ${EXE_FILES} - ${GRPC_HEADER_FILES} + ${GRPC_HEADER_FILES} ${CPP_SOURCES} ${MOC_SOURCE_FILES} ${FORM_FILES_CPP} @@ -335,20 +335,20 @@ set( EXE_FILES ../ResInsightVersion.cmake .clang-format .clang-tidy - Adm/RiaVersionInfo.h.cmake + Adm/RiaVersionInfo.h.cmake ) if (RESINSIGHT_ENABLE_GRPC) - list(APPEND EXE_FILES - ${GRPC_CPP_SOURCES} - ${GRPC_HEADER_FILES} - ${GRPC_PYTHON_SOURCES_FULL_PATH} - Adm/RiaVersionInfo.py.cmake - ) - if (DEFINED GRPC_LIBRARY_DIRS) - message(STATUS "Using GRPC Library Dir: ${GRPC_LIBRARY_DIRS}") - link_directories("${GRPC_LIBRARY_DIRS}") - endif(DEFINED GRPC_LIBRARY_DIRS) + list(APPEND EXE_FILES + ${GRPC_CPP_SOURCES} + ${GRPC_HEADER_FILES} + ${GRPC_PYTHON_SOURCES_FULL_PATH} + Adm/RiaVersionInfo.py.cmake + ) + if (DEFINED GRPC_LIBRARY_DIRS) + message(STATUS "Using GRPC Library Dir: ${GRPC_LIBRARY_DIRS}") + link_directories("${GRPC_LIBRARY_DIRS}") + endif(DEFINED GRPC_LIBRARY_DIRS) endif(RESINSIGHT_ENABLE_GRPC) add_executable( ResInsight ${EXE_FILES}) @@ -362,9 +362,9 @@ if (MSVC) set_target_properties(ResInsight PROPERTIES COMPILE_FLAGS "/W4 /wd4190 /wd4100 /wd4127 /wd4245") 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 local function has been removed + # The following warning is generated over 800 times from a qwt header only using VS2015 + # Disabling temporarily + # warning C4505 'function' : unreferenced local function has been removed set_target_properties(ResInsight PROPERTIES COMPILE_FLAGS "/wd4505") endif() @@ -405,7 +405,7 @@ set( LINK_LIBRARIES ) if (RESINSIGHT_ENABLE_GRPC) - list(APPEND LINK_LIBRARIES ${GRPC_LIBRARIES}) + list(APPEND LINK_LIBRARIES ${GRPC_LIBRARIES}) endif() # According to ivarun this is needed on OpenSuse, and Fedora. See: https://github.com/OPM/ResInsight/pull/7 @@ -481,19 +481,19 @@ endif() if (MSVC) # Qt DLLs - if (Qt5Core_FOUND) + if (Qt5Core_FOUND) message(STATUS "Creating post build step for copying Qt DLLs") - foreach (qtlib ${QT_LIBRARIES}) - add_custom_command(TARGET ResInsight POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_if_different $ $ - ) - endforeach(qtlib) - else() - set (QTLIBLIST QtCore4 QtCored4 QtGui4 QtGuid4 QtOpenGl4 QtOpenGld4 QtNetwork4 QtNetworkd4 QtScript4 QtScriptd4 QtScriptTools4 QtScriptToolsd4) - foreach (qtlib ${QTLIBLIST}) - list(APPEND RI_DLL_FILENAMES ${QT_BINARY_DIR}/${qtlib}.dll) - endforeach( qtlib ) - endif() + foreach (qtlib ${QT_LIBRARIES}) + add_custom_command(TARGET ResInsight POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different $ $ + ) + endforeach(qtlib) + else() + set (QTLIBLIST QtCore4 QtCored4 QtGui4 QtGuid4 QtOpenGl4 QtOpenGld4 QtNetwork4 QtNetworkd4 QtScript4 QtScriptd4 QtScriptTools4 QtScriptToolsd4) + foreach (qtlib ${QTLIBLIST}) + list(APPEND RI_DLL_FILENAMES ${QT_BINARY_DIR}/${qtlib}.dll) + endforeach( qtlib ) + endif() # Odb Dlls if (RESINSIGHT_USE_ODB_API) # Find all the dlls @@ -536,28 +536,28 @@ endforeach() # Copy all grpc libraries and python files if (RESINSIGHT_ENABLE_GRPC) - if(UNIX) - foreach (GRPC_LIBRARY ${GRPC_LIBRARIES}) - add_custom_command(TARGET ResInsight POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_if_different - "${GRPC_INSTALL_PREFIX}/lib/lib${GRPC_LIBRARY}.so" - "${CMAKE_CURRENT_BINARY_DIR}/$" - ) - endforeach(GRPC_LIBRARY ${GRPC_LIBRARIES}) - endif(UNIX) + if(UNIX) + foreach (GRPC_LIBRARY ${GRPC_LIBRARIES}) + add_custom_command(TARGET ResInsight POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${GRPC_INSTALL_PREFIX}/lib/lib${GRPC_LIBRARY}.so" + "${CMAKE_CURRENT_BINARY_DIR}/$" + ) + endforeach(GRPC_LIBRARY ${GRPC_LIBRARIES}) + endif(UNIX) - if (PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) - add_custom_target(GeneratedPythonSources DEPENDS ${GRPC_GENERATED_PYTHON_SOURCES}) - add_dependencies(ResInsight GeneratedPythonSources) + if (PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) + add_custom_target(GeneratedPythonSources DEPENDS ${GRPC_GENERATED_PYTHON_SOURCES}) + add_dependencies(ResInsight GeneratedPythonSources) - foreach (PYTHON_SCRIPT ${GRPC_PYTHON_SOURCES}) - if (EXISTS "${GRPC_PYTHON_SOURCE_PATH}/${PYTHON_SCRIPT}") - configure_file("${GRPC_PYTHON_SOURCE_PATH}/${PYTHON_SCRIPT}" - "${GRPC_PYTHON_DEST_PATH}/${PYTHON_SCRIPT}" - COPYONLY) - endif(EXISTS "${GRPC_PYTHON_SOURCE_PATH}/${PYTHON_SCRIPT}") - endforeach(PYTHON_SCRIPT ${GRPC_PYTHON_SOURCES}) - endif(PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) + foreach (PYTHON_SCRIPT ${GRPC_PYTHON_SOURCES}) + if (EXISTS "${GRPC_PYTHON_SOURCE_PATH}/${PYTHON_SCRIPT}") + configure_file("${GRPC_PYTHON_SOURCE_PATH}/${PYTHON_SCRIPT}" + "${GRPC_PYTHON_DEST_PATH}/${PYTHON_SCRIPT}" + COPYONLY) + endif(EXISTS "${GRPC_PYTHON_SOURCE_PATH}/${PYTHON_SCRIPT}") + endforeach(PYTHON_SCRIPT ${GRPC_PYTHON_SOURCES}) + endif(PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) endif(RESINSIGHT_ENABLE_GRPC) ############################################################################# @@ -633,12 +633,12 @@ if (RESINSIGHT_PRIVATE_INSTALL) COMMAND set PATH=%PATH%$${qt5_install_prefix}/bin COMMAND Qt5::windeployqt - --no-compiler-runtime - --no-system-d3d-compiler - --no-quick-import - --no-translations + --no-compiler-runtime + --no-system-d3d-compiler + --no-quick-import + --no-translations --verbose 0 - --dir "${CMAKE_CURRENT_BINARY_DIR}/windeployqt" + --dir "${CMAKE_CURRENT_BINARY_DIR}/windeployqt" "$/$" ) diff --git a/ApplicationCode/GrpcInterface/CMakeLists.cmake b/ApplicationCode/GrpcInterface/CMakeLists.cmake index 52a1426218..4bbfe27473 100644 --- a/ApplicationCode/GrpcInterface/CMakeLists.cmake +++ b/ApplicationCode/GrpcInterface/CMakeLists.cmake @@ -1,154 +1,154 @@ set ( SOURCE_GROUP_HEADER_FILES - ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcServer.h - ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcCallbacks.h - ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcCallbacks.inl - ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcServiceInterface.h - ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcGridInfoService.h - ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcProjectInfoService.h - ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcCommandService.h - ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcResInfoService.h + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcServer.h + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcCallbacks.h + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcCallbacks.inl + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcServiceInterface.h + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcGridInfoService.h + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcProjectInfoService.h + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcCommandService.h + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcResInfoService.h ) set ( SOURCE_GROUP_SOURCE_FILES - ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcServer.cpp - ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcServiceInterface.cpp - ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcGridInfoService.cpp - ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcProjectInfoService.cpp - ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcCommandService.cpp - ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcResInfoService.cpp + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcServer.cpp + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcServiceInterface.cpp + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcGridInfoService.cpp + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcProjectInfoService.cpp + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcCommandService.cpp + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcResInfoService.cpp ) add_definitions(-DENABLE_GRPC) if (MSVC) - add_definitions(-D_WIN32_WINNT=0x600) + add_definitions(-D_WIN32_WINNT=0x600) - # Find Protobuf installation - # Looks for protobuf-config.cmake file installed by Protobuf's cmake installation. - set(protobuf_MODULE_COMPATIBLE ON CACHE BOOL "") - find_package(Protobuf CONFIG 3.0 REQUIRED) - message(STATUS "Using protobuf ${protobuf_VERSION}") + # Find Protobuf installation + # Looks for protobuf-config.cmake file installed by Protobuf's cmake installation. + set(protobuf_MODULE_COMPATIBLE ON CACHE BOOL "") + find_package(Protobuf CONFIG 3.0 REQUIRED) + message(STATUS "Using protobuf ${protobuf_VERSION}") - # Find gRPC installation - # Looks for gRPCConfig.cmake file installed by gRPC's cmake installation. - find_package(gRPC CONFIG REQUIRED NO_MODULE) - message(STATUS "Using gRPC ${gRPC_VERSION}") + # Find gRPC installation + # Looks for gRPCConfig.cmake file installed by gRPC's cmake installation. + find_package(gRPC CONFIG REQUIRED NO_MODULE) + message(STATUS "Using gRPC ${gRPC_VERSION}") - set(_PROTOBUF_LIBPROTOBUF protobuf::libprotobuf) - set(_PROTOBUF_PROTOC $) + set(_PROTOBUF_LIBPROTOBUF protobuf::libprotobuf) + set(_PROTOBUF_PROTOC $) - set(_GRPC_GRPCPP_UNSECURE gRPC::grpc++_unsecure gRPC::grpc_unsecure gRPC::gpr) - set(_GRPC_CPP_PLUGIN_EXECUTABLE $) - set(GRPC_LIBRARIES ${_GRPC_GRPCPP_UNSECURE} ${_PROTOBUF_LIBPROTOBUF}) + set(_GRPC_GRPCPP_UNSECURE gRPC::grpc++_unsecure gRPC::grpc_unsecure gRPC::gpr) + set(_GRPC_CPP_PLUGIN_EXECUTABLE $) + set(GRPC_LIBRARIES ${_GRPC_GRPCPP_UNSECURE} ${_PROTOBUF_LIBPROTOBUF}) - if (MSVC) - set_target_properties(${GRPC_LIBRARIES} PROPERTIES - MAP_IMPORTED_CONFIG_MINSIZEREL RELEASE - MAP_IMPORTED_CONFIG_RELWITHDEBINFO RELEASE - ) - endif(MSVC) + if (MSVC) + set_target_properties(${GRPC_LIBRARIES} PROPERTIES + MAP_IMPORTED_CONFIG_MINSIZEREL RELEASE + MAP_IMPORTED_CONFIG_RELWITHDEBINFO RELEASE + ) + endif(MSVC) else() - if (NOT DEFINED GRPC_INSTALL_PREFIX OR NOT EXISTS ${GRPC_INSTALL_PREFIX}) - message(FATAL_ERROR "You need a valid GRPC_INSTALL_PREFIX set to build with GRPC") - endif() - set(ENV{PKG_CONFIG_PATH} "${GRPC_INSTALL_PREFIX}/lib/pkgconfig") - find_package(PkgConfig REQUIRED) - pkg_check_modules(GRPC REQUIRED grpc++_unsecure>=1.20 grpc_unsecure gpr protobuf) - set(_PROTOBUF_PROTOC "${GRPC_INSTALL_PREFIX}/bin/protoc") - set(_GRPC_CPP_PLUGIN_EXECUTABLE "${GRPC_INSTALL_PREFIX}/bin/grpc_cpp_plugin") - include_directories(AFTER ${GRPC_INCLUDE_DIRS}) + if (NOT DEFINED GRPC_INSTALL_PREFIX OR NOT EXISTS ${GRPC_INSTALL_PREFIX}) + message(FATAL_ERROR "You need a valid GRPC_INSTALL_PREFIX set to build with GRPC") + endif() + set(ENV{PKG_CONFIG_PATH} "${GRPC_INSTALL_PREFIX}/lib/pkgconfig") + find_package(PkgConfig REQUIRED) + pkg_check_modules(GRPC REQUIRED grpc++_unsecure>=1.20 grpc_unsecure gpr protobuf) + set(_PROTOBUF_PROTOC "${GRPC_INSTALL_PREFIX}/bin/protoc") + set(_GRPC_CPP_PLUGIN_EXECUTABLE "${GRPC_INSTALL_PREFIX}/bin/grpc_cpp_plugin") + include_directories(AFTER ${GRPC_INCLUDE_DIRS}) endif() # Cannot use the nice new FindPackage modules for python since that is CMake 3.12+ if(PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) - message(STATUS "Using Python ${PYTHON_EXECUTABLE}") + message(STATUS "Using Python ${PYTHON_EXECUTABLE}") endif(PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) # Proto files set(PROTO_FILES - "Empty" - "CaseInfo" - "GridInfo" - "ProjectInfo" - "Commands" - "ResInfo" + "Empty" + "CaseInfo" + "GridInfo" + "ProjectInfo" + "Commands" + "ResInfo" ) set(GRPC_PYTHON_SOURCE_PATH "${CMAKE_SOURCE_DIR}/Python") set(GRPC_PYTHON_DEST_PATH "${CMAKE_BINARY_DIR}/Python") foreach(proto_file ${PROTO_FILES}) - get_filename_component(rips_proto "${CMAKE_CURRENT_LIST_DIR}/GrpcProtos/${proto_file}.proto" ABSOLUTE) - get_filename_component(rips_proto_path "${rips_proto}" PATH) + get_filename_component(rips_proto "${CMAKE_CURRENT_LIST_DIR}/GrpcProtos/${proto_file}.proto" ABSOLUTE) + get_filename_component(rips_proto_path "${rips_proto}" PATH) - set(rips_proto_srcs "${CMAKE_BINARY_DIR}/Generated/${proto_file}.pb.cc") - set(rips_proto_hdrs "${CMAKE_BINARY_DIR}/Generated/${proto_file}.pb.h") - set(rips_grpc_srcs "${CMAKE_BINARY_DIR}/Generated/${proto_file}.grpc.pb.cc") - set(rips_grpc_hdrs "${CMAKE_BINARY_DIR}/Generated/${proto_file}.grpc.pb.h") - - add_custom_command( - OUTPUT "${rips_proto_srcs}" "${rips_proto_hdrs}" "${rips_grpc_srcs}" "${rips_grpc_hdrs}" - COMMAND ${_PROTOBUF_PROTOC} - ARGS --grpc_out "${CMAKE_BINARY_DIR}/Generated" - --cpp_out "${CMAKE_BINARY_DIR}/Generated" - -I "${rips_proto_path}" - --plugin=protoc-gen-grpc="${_GRPC_CPP_PLUGIN_EXECUTABLE}" - "${rips_proto}" - DEPENDS "${rips_proto}" - ) - - if (PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) - set(rips_proto_python "generated/${proto_file}_pb2.py") - set(rips_grpc_python "generated/${proto_file}_pb2_grpc.py") + set(rips_proto_srcs "${CMAKE_BINARY_DIR}/Generated/${proto_file}.pb.cc") + set(rips_proto_hdrs "${CMAKE_BINARY_DIR}/Generated/${proto_file}.pb.h") + set(rips_grpc_srcs "${CMAKE_BINARY_DIR}/Generated/${proto_file}.grpc.pb.cc") + set(rips_grpc_hdrs "${CMAKE_BINARY_DIR}/Generated/${proto_file}.grpc.pb.h") + + add_custom_command( + OUTPUT "${rips_proto_srcs}" "${rips_proto_hdrs}" "${rips_grpc_srcs}" "${rips_grpc_hdrs}" + COMMAND ${_PROTOBUF_PROTOC} + ARGS --grpc_out "${CMAKE_BINARY_DIR}/Generated" + --cpp_out "${CMAKE_BINARY_DIR}/Generated" + -I "${rips_proto_path}" + --plugin=protoc-gen-grpc="${_GRPC_CPP_PLUGIN_EXECUTABLE}" + "${rips_proto}" + DEPENDS "${rips_proto}" + ) + + if (PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) + set(rips_proto_python "generated/${proto_file}_pb2.py") + set(rips_grpc_python "generated/${proto_file}_pb2_grpc.py") - add_custom_command( - OUTPUT "${GRPC_PYTHON_SOURCE_PATH}/${rips_proto_python}" "${GRPC_PYTHON_SOURCE_PATH}/${rips_grpc_python}" - COMMAND ${PYTHON_EXECUTABLE} - ARGS -m grpc_tools.protoc - -I "${rips_proto_path}" - --python_out "${GRPC_PYTHON_SOURCE_PATH}/generated" - --grpc_python_out "${GRPC_PYTHON_SOURCE_PATH}/generated" - "${rips_proto}" - DEPENDS "${rips_proto}" - COMMENT "Generating ${rips_proto_python} and ${rips_grpc_python}" - VERBATIM - ) - list (APPEND GRPC_PYTHON_GENERATED_SOURCES - ${rips_proto_python} - ${rips_grpc_python} - ) + add_custom_command( + OUTPUT "${GRPC_PYTHON_SOURCE_PATH}/${rips_proto_python}" "${GRPC_PYTHON_SOURCE_PATH}/${rips_grpc_python}" + COMMAND ${PYTHON_EXECUTABLE} + ARGS -m grpc_tools.protoc + -I "${rips_proto_path}" + --python_out "${GRPC_PYTHON_SOURCE_PATH}/generated" + --grpc_python_out "${GRPC_PYTHON_SOURCE_PATH}/generated" + "${rips_proto}" + DEPENDS "${rips_proto}" + COMMENT "Generating ${rips_proto_python} and ${rips_grpc_python}" + VERBATIM + ) + list (APPEND GRPC_PYTHON_GENERATED_SOURCES + ${rips_proto_python} + ${rips_grpc_python} + ) - endif(PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) + endif(PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) - list( APPEND GRPC_HEADER_FILES - ${rips_proto_hdrs} - ${rips_grpc_hdrs} - ) - - list( APPEND GRPC_CPP_SOURCES - ${rips_proto_srcs} - ${rips_grpc_srcs} - ) + list( APPEND GRPC_HEADER_FILES + ${rips_proto_hdrs} + ${rips_grpc_hdrs} + ) + + list( APPEND GRPC_CPP_SOURCES + ${rips_proto_srcs} + ${rips_grpc_srcs} + ) endforeach(proto_file) if (PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) - list(APPEND GRPC_PYTHON_SOURCES - ${GRPC_PYTHON_GENERATED_SOURCES} - "api/__init__.py" - "api/ResInsight.py" - "examples/CommandExample.py" - "examples/GridInfoStreamingExample.py" - "examples/ResultValues.py" - "examples/SelectedCases.py" - "examples/AllCases.py" - "tests/test_sample.py" - ) + list(APPEND GRPC_PYTHON_SOURCES + ${GRPC_PYTHON_GENERATED_SOURCES} + "api/__init__.py" + "api/ResInsight.py" + "examples/CommandExample.py" + "examples/GridInfoStreamingExample.py" + "examples/ResultValues.py" + "examples/SelectedCases.py" + "examples/AllCases.py" + "tests/test_sample.py" + ) - foreach(PYTHON_SCRIPT ${GRPC_PYTHON_SOURCES}) - list(APPEND GRPC_PYTHON_SOURCES_FULL_PATH "${GRPC_PYTHON_SOURCE_PATH}/${PYTHON_SCRIPT}") - endforeach() - source_group(TREE ${GRPC_PYTHON_SOURCE_PATH} FILES ${GRPC_PYTHON_SOURCES_FULL_PATH} PREFIX "Python") + foreach(PYTHON_SCRIPT ${GRPC_PYTHON_SOURCES}) + list(APPEND GRPC_PYTHON_SOURCES_FULL_PATH "${GRPC_PYTHON_SOURCE_PATH}/${PYTHON_SCRIPT}") + endforeach() + source_group(TREE ${GRPC_PYTHON_SOURCE_PATH} FILES ${GRPC_PYTHON_SOURCES_FULL_PATH} PREFIX "Python") endif(PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) From b44f0a2029e4551fb57b87811ce31ba18056775c Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Mon, 20 May 2019 14:32:29 +0200 Subject: [PATCH 057/396] #4418 Handle all queued gRPC requests per main loop iteration * This means a streaming request should be completed in one main loop iteration --- ApplicationCode/Application/RiaGuiApplication.cpp | 2 +- ApplicationCode/GrpcInterface/RiaGrpcServer.cpp | 12 +++++++----- ApplicationCode/GrpcInterface/RiaGrpcServer.h | 2 +- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/ApplicationCode/Application/RiaGuiApplication.cpp b/ApplicationCode/Application/RiaGuiApplication.cpp index f5bdd0f50f..36a3b71ed4 100644 --- a/ApplicationCode/Application/RiaGuiApplication.cpp +++ b/ApplicationCode/Application/RiaGuiApplication.cpp @@ -1681,7 +1681,7 @@ void RiaGuiApplication::runIdleProcessing() #ifdef ENABLE_GRPC if (!caf::ProgressInfoStatic::isRunning()) { - m_grpcServer->processOneRequest(); + m_grpcServer->processRequests(); } #endif } diff --git a/ApplicationCode/GrpcInterface/RiaGrpcServer.cpp b/ApplicationCode/GrpcInterface/RiaGrpcServer.cpp index 7109cc2e33..128c6c81c5 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcServer.cpp +++ b/ApplicationCode/GrpcInterface/RiaGrpcServer.cpp @@ -31,6 +31,7 @@ #include "RimProject.h" #include "cafAssert.h" +#include "cafProgressInfo.h" #include #include @@ -60,7 +61,7 @@ public: void run(); void runInThread(); void initialize(); - void processOneRequest(); + void processRequests(); void quit(); int currentPortNumber; @@ -168,10 +169,11 @@ void RiaGrpcServerImpl::initialize() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RiaGrpcServerImpl::processOneRequest() +void RiaGrpcServerImpl::processRequests() { std::lock_guard requestLock(m_requestMutex); - if (!m_unprocessedRequests.empty()) + + while (!m_unprocessedRequests.empty()) { RiaAbstractGrpcCallback* method = m_unprocessedRequests.front(); m_unprocessedRequests.pop_front(); @@ -325,9 +327,9 @@ void RiaGrpcServer::initialize() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RiaGrpcServer::processOneRequest() +void RiaGrpcServer::processRequests() { - m_serverImpl->processOneRequest(); + m_serverImpl->processRequests(); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/GrpcInterface/RiaGrpcServer.h b/ApplicationCode/GrpcInterface/RiaGrpcServer.h index 90f27321e3..0812d6ee2d 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcServer.h +++ b/ApplicationCode/GrpcInterface/RiaGrpcServer.h @@ -41,7 +41,7 @@ public: bool isRunning() const; void run(); void runInThread(); - void processOneRequest(); + void processRequests(); void quit(); static int findAvailablePortNumber(int defaultPortNumber); From 177a54615b0e8d8b5efaad3ab81a97c4ee26622a Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Mon, 20 May 2019 15:17:04 +0200 Subject: [PATCH 058/396] Remove Python sources groups on Linux to fix build issue --- ApplicationCode/GrpcInterface/CMakeLists.cmake | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ApplicationCode/GrpcInterface/CMakeLists.cmake b/ApplicationCode/GrpcInterface/CMakeLists.cmake index 4bbfe27473..33cb451201 100644 --- a/ApplicationCode/GrpcInterface/CMakeLists.cmake +++ b/ApplicationCode/GrpcInterface/CMakeLists.cmake @@ -1,3 +1,5 @@ +cmake_minimum_required (VERSION 2.8.12) + set ( SOURCE_GROUP_HEADER_FILES ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcServer.h ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcCallbacks.h @@ -148,7 +150,9 @@ if (PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) foreach(PYTHON_SCRIPT ${GRPC_PYTHON_SOURCES}) list(APPEND GRPC_PYTHON_SOURCES_FULL_PATH "${GRPC_PYTHON_SOURCE_PATH}/${PYTHON_SCRIPT}") endforeach() +if (MSVC) source_group(TREE ${GRPC_PYTHON_SOURCE_PATH} FILES ${GRPC_PYTHON_SOURCES_FULL_PATH} PREFIX "Python") +endif(MSVC) endif(PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) From 1a7d5781d8d784c1355791c27df50c9f11eeb603 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Mon, 20 May 2019 15:22:54 +0200 Subject: [PATCH 059/396] Add comment about scl enable rh-python35 bash to instructions --- GRPC_install_instructions.txt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/GRPC_install_instructions.txt b/GRPC_install_instructions.txt index 689a4f540c..e290776e68 100644 --- a/GRPC_install_instructions.txt +++ b/GRPC_install_instructions.txt @@ -24,10 +24,12 @@ git submodule update scl enable devtoolset-3 bash make prefix=/opt/grpc sudo make prefix=/opt/grpc install -3. Install protobuf (still within grpc folder) +4. Install protobuf (still within grpc folder) cd third_party/protobuf sudo make prefix=/opt/grpc install -4. Install grpcio-tools for Python (this may have to be done as root user): +5. Make sure you have a Python 3 version available in your paths. +I.e.: "sudo yum install rh-python35" and then "scl enable rh-python35 bash" +6. Install grpcio-tools for Python (this may have to be done as root user): pip install grpcio-tools -5. Run cmake making sure GRPC_INSTALL_PREFIX is set to /opt/grpc, PYTHON_EXECUTABLE set to a good python 3 and RESINSIGHT_ENABLE_GRPC = true +7. Run cmake making sure GRPC_INSTALL_PREFIX is set to /opt/grpc, PYTHON_EXECUTABLE set to a good python 3 and RESINSIGHT_ENABLE_GRPC = true From 5e23bd55789785319ec236e306901e48c5766bfe Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Mon, 20 May 2019 15:28:07 +0200 Subject: [PATCH 060/396] #4427 Add proto files to IDE project --- ApplicationCode/CMakeLists.txt | 2 +- ApplicationCode/GrpcInterface/CMakeLists.cmake | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/ApplicationCode/CMakeLists.txt b/ApplicationCode/CMakeLists.txt index 0167332191..6fab5e36ce 100644 --- a/ApplicationCode/CMakeLists.txt +++ b/ApplicationCode/CMakeLists.txt @@ -324,7 +324,6 @@ elseif (APPLE) endif() set( EXE_FILES ${EXE_FILES} - ${GRPC_HEADER_FILES} ${CPP_SOURCES} ${MOC_SOURCE_FILES} ${FORM_FILES_CPP} @@ -343,6 +342,7 @@ if (RESINSIGHT_ENABLE_GRPC) ${GRPC_CPP_SOURCES} ${GRPC_HEADER_FILES} ${GRPC_PYTHON_SOURCES_FULL_PATH} + ${GRPC_PROTO_FILES_FULL_PATH} Adm/RiaVersionInfo.py.cmake ) if (DEFINED GRPC_LIBRARY_DIRS) diff --git a/ApplicationCode/GrpcInterface/CMakeLists.cmake b/ApplicationCode/GrpcInterface/CMakeLists.cmake index 33cb451201..86f489db42 100644 --- a/ApplicationCode/GrpcInterface/CMakeLists.cmake +++ b/ApplicationCode/GrpcInterface/CMakeLists.cmake @@ -83,6 +83,8 @@ foreach(proto_file ${PROTO_FILES}) get_filename_component(rips_proto "${CMAKE_CURRENT_LIST_DIR}/GrpcProtos/${proto_file}.proto" ABSOLUTE) get_filename_component(rips_proto_path "${rips_proto}" PATH) + list(APPEND GRPC_PROTO_FILES_FULL_PATH ${rips_proto}) + set(rips_proto_srcs "${CMAKE_BINARY_DIR}/Generated/${proto_file}.pb.cc") set(rips_proto_hdrs "${CMAKE_BINARY_DIR}/Generated/${proto_file}.pb.h") set(rips_grpc_srcs "${CMAKE_BINARY_DIR}/Generated/${proto_file}.grpc.pb.cc") @@ -160,3 +162,4 @@ list ( APPEND GRPC_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES}) list ( APPEND GRPC_CPP_SOURCES ${SOURCE_GROUP_SOURCE_FILES}) source_group( "GrpcInterface" FILES ${SOURCE_GROUP_HEADER_FILES} ${SOURCE_GROUP_SOURCE_FILES} ${CMAKE_CURRENT_LIST_DIR}/CMakeLists.cmake ) +source_group( "GrpcInterface\\GrpcProtos" FILES ${GRPC_PROTO_FILES_FULL_PATH} ) \ No newline at end of file From c4a4ceef29351be6f94105e99d088ad0ab355ddd Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Mon, 20 May 2019 15:43:18 +0200 Subject: [PATCH 061/396] Link grpc libraries statically on UNIX/Linux --- ApplicationCode/CMakeLists.txt | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/ApplicationCode/CMakeLists.txt b/ApplicationCode/CMakeLists.txt index 6fab5e36ce..14f6331524 100644 --- a/ApplicationCode/CMakeLists.txt +++ b/ApplicationCode/CMakeLists.txt @@ -347,7 +347,7 @@ if (RESINSIGHT_ENABLE_GRPC) ) if (DEFINED GRPC_LIBRARY_DIRS) message(STATUS "Using GRPC Library Dir: ${GRPC_LIBRARY_DIRS}") - link_directories("${GRPC_LIBRARY_DIRS}") + link_directories(${GRPC_LIBRARY_DIRS}) endif(DEFINED GRPC_LIBRARY_DIRS) endif(RESINSIGHT_ENABLE_GRPC) @@ -405,7 +405,13 @@ set( LINK_LIBRARIES ) if (RESINSIGHT_ENABLE_GRPC) - list(APPEND LINK_LIBRARIES ${GRPC_LIBRARIES}) + if (UNIX) + foreach(GRPC_LIBRARY ${GRPC_LIBRARIES}) + list(APPEND LINK_LIBRARIES "${GRPC_LIBRARY_DIRS}/lib${GRPC_LIBRARY}.a") + endforeach() + else() + list(APPEND LINK_LIBRARIES ${GRPC_LIBRARIES}) + endif() endif() # According to ivarun this is needed on OpenSuse, and Fedora. See: https://github.com/OPM/ResInsight/pull/7 @@ -536,16 +542,6 @@ endforeach() # Copy all grpc libraries and python files if (RESINSIGHT_ENABLE_GRPC) - if(UNIX) - foreach (GRPC_LIBRARY ${GRPC_LIBRARIES}) - add_custom_command(TARGET ResInsight POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_if_different - "${GRPC_INSTALL_PREFIX}/lib/lib${GRPC_LIBRARY}.so" - "${CMAKE_CURRENT_BINARY_DIR}/$" - ) - endforeach(GRPC_LIBRARY ${GRPC_LIBRARIES}) - endif(UNIX) - if (PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) add_custom_target(GeneratedPythonSources DEPENDS ${GRPC_GENERATED_PYTHON_SOURCES}) add_dependencies(ResInsight GeneratedPythonSources) From 86e202aed0ee835aef27fc405e57d18d7f873042 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Tue, 21 May 2019 13:40:42 +0200 Subject: [PATCH 062/396] #4430 Implement GetAvailableProperties() and GetActiveCellResults() --- ApplicationCode/CMakeLists.txt | 2 +- .../GrpcInterface/CMakeLists.cmake | 4 + .../GrpcInterface/GrpcProtos/Properties.proto | 69 +++++ .../GrpcInterface/RiaGrpcGridInfoService.h | 3 +- .../RiaGrpcPropertiesService.cpp | 145 ++++++++++ .../GrpcInterface/RiaGrpcPropertiesService.h | 59 ++++ Python/api/ResInsight.py | 271 ++++++++++-------- Python/examples/ResultValues.py | 56 +--- 8 files changed, 440 insertions(+), 169 deletions(-) create mode 100644 ApplicationCode/GrpcInterface/GrpcProtos/Properties.proto create mode 100644 ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp create mode 100644 ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.h diff --git a/ApplicationCode/CMakeLists.txt b/ApplicationCode/CMakeLists.txt index 14f6331524..1db2e1b44b 100644 --- a/ApplicationCode/CMakeLists.txt +++ b/ApplicationCode/CMakeLists.txt @@ -24,7 +24,7 @@ CONFIGURE_FILE( ${CMAKE_SOURCE_DIR}/ApplicationCode/Adm/RiaVersionInfo.h.cmake ${CMAKE_BINARY_DIR}/Generated/RiaVersionInfo.h ) CONFIGURE_FILE( ${CMAKE_SOURCE_DIR}/ApplicationCode/Adm/RiaVersionInfo.py.cmake - ${CMAKE_BINARY_DIR}/Python/generated/RiaVersionInfo.py + ${CMAKE_SOURCE_DIR}/Python/generated/RiaVersionInfo.py ) if (MSVC AND (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 19.11)) diff --git a/ApplicationCode/GrpcInterface/CMakeLists.cmake b/ApplicationCode/GrpcInterface/CMakeLists.cmake index 86f489db42..5d09be5bb4 100644 --- a/ApplicationCode/GrpcInterface/CMakeLists.cmake +++ b/ApplicationCode/GrpcInterface/CMakeLists.cmake @@ -9,6 +9,7 @@ set ( SOURCE_GROUP_HEADER_FILES ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcProjectInfoService.h ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcCommandService.h ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcResInfoService.h + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcPropertiesService.h ) set ( SOURCE_GROUP_SOURCE_FILES @@ -18,6 +19,7 @@ set ( SOURCE_GROUP_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcProjectInfoService.cpp ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcCommandService.cpp ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcResInfoService.cpp + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcPropertiesService.cpp ) add_definitions(-DENABLE_GRPC) @@ -74,6 +76,7 @@ set(PROTO_FILES "ProjectInfo" "Commands" "ResInfo" + "Properties" ) set(GRPC_PYTHON_SOURCE_PATH "${CMAKE_SOURCE_DIR}/Python") @@ -139,6 +142,7 @@ endforeach(proto_file) if (PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) list(APPEND GRPC_PYTHON_SOURCES ${GRPC_PYTHON_GENERATED_SOURCES} + "generated/RiaVersionInfo.py" "api/__init__.py" "api/ResInsight.py" "examples/CommandExample.py" diff --git a/ApplicationCode/GrpcInterface/GrpcProtos/Properties.proto b/ApplicationCode/GrpcInterface/GrpcProtos/Properties.proto new file mode 100644 index 0000000000..c44909615d --- /dev/null +++ b/ApplicationCode/GrpcInterface/GrpcProtos/Properties.proto @@ -0,0 +1,69 @@ +syntax = "proto3"; + +import "Empty.proto"; +import "CaseInfo.proto"; +import "GridInfo.proto"; + +package rips; + +service Properties +{ + rpc GetAvailableProperties(PropertiesRequest) returns (AvailableProperties) {} + rpc GetActiveCellResults(ResultRequest) returns (stream ResultReplyArray) {} + rpc GetGridResults(ResultRequest) returns (stream ResultReplyArray) {} + rpc SetActiveCellResults(stream ResultRequestArray) returns (Empty) {} + rpc SetGridResults(stream ResultRequestArray) returns (Empty) {} +} + +enum PropertyType +{ + DYNAMIC_NATIVE = 0; + STATIC_NATIVE = 1; + SOURSIMRL = 2; + GENERATED = 3; + INPUT_PROPERTY = 4; + FORMATION_NAMES = 5; + FLOW_DIAGNOSTICS = 6; + INJECTION_FLOODING = 7; + REMOVED = 8; + UNDEFINED = 999; +} + +message PropertiesRequest +{ + Case request_case = 1; + PropertyType property_type = 2; + PorosityModelType porosity_model = 3; +} + +message AvailableProperties +{ + repeated string property_names = 1; +} + +message ResultRequest +{ + Case request_case = 1; + PropertyType property_type = 2; + string property_name = 3; + int32 time_step = 4; + int32 grid_index = 5; + PorosityModelType porosity_model = 6; +} + +message TimeStep +{ + int32 index = 1; +} + +message ResultRequestArray +{ + repeated double values = 1; + Case request_case = 2; + TimeStep time_step = 3; +} + +message ResultReplyArray +{ + repeated double values = 1; +} diff --git a/ApplicationCode/GrpcInterface/RiaGrpcGridInfoService.h b/ApplicationCode/GrpcInterface/RiaGrpcGridInfoService.h index a37d52c080..b73c724977 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcGridInfoService.h +++ b/ApplicationCode/GrpcInterface/RiaGrpcGridInfoService.h @@ -41,9 +41,8 @@ class RimEclipseCase; //================================================================================================== class RiaActiveCellInfoStateHandler { -public: typedef grpc::Status Status; - +public: RiaActiveCellInfoStateHandler(); Status init(const rips::ActiveCellInfoRequest* request); diff --git a/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp b/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp new file mode 100644 index 0000000000..d5bfd68d2f --- /dev/null +++ b/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp @@ -0,0 +1,145 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 "RiaGrpcPropertiesService.h" + +#include "RiaGrpcGridInfoService.h" +#include "RiaGrpcCallbacks.h" + +#include "RigCaseCellResultsData.h" +#include "RigEclipseCaseData.h" +#include "RigEclipseResultAddress.h" + +#include "RimEclipseCase.h" + +using namespace rips; + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiaActiveCellResultsStateHandler::RiaActiveCellResultsStateHandler() + : m_request(nullptr) + , m_resultValues(nullptr) + , m_currentCellIdx(0u) +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +grpc::Status RiaActiveCellResultsStateHandler::init(const ResultRequest* request) +{ + int caseId = request->request_case().id(); + RimEclipseCase* eclipseCase = dynamic_cast(RiaGrpcServiceInterface::findCase(caseId)); + if (eclipseCase) + { + auto porosityModel = static_cast(request->porosity_model()); + auto resultData = eclipseCase->eclipseCaseData()->results(porosityModel); + auto resultType = static_cast(request->property_type()); + size_t timeStep = static_cast(request->time_step()); + RigEclipseResultAddress resAddr(resultType, QString::fromStdString(request->property_name())); + + if (resultData->hasResultEntry(resAddr)) + { + if (timeStep < (int)resultData->timeStepCount(resAddr)) + { + m_resultValues = &resultData->cellScalarResults(resAddr, timeStep); + return grpc::Status::OK; + } + return grpc::Status(grpc::NOT_FOUND, "No such time step"); + } + return grpc::Status(grpc::NOT_FOUND, "No such result"); + } + return grpc::Status(grpc::NOT_FOUND, "Couldn't find an Eclipse case matching the case Id"); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +grpc::Status RiaActiveCellResultsStateHandler::assignReply(ResultReplyArray* reply) +{ + if (m_resultValues) + { + const size_t packageSize = RiaGrpcServiceInterface::numberOfMessagesForByteCount(sizeof(rips::ResultReplyArray)); + size_t packageIndex = 0u; + reply->mutable_values()->Reserve((int)packageSize); + for (; packageIndex < packageSize && m_currentCellIdx < m_resultValues->size(); ++packageIndex, ++m_currentCellIdx) + { + reply->add_values(m_resultValues->at(m_currentCellIdx)); + } + if (packageIndex > 0u) + { + return grpc::Status::OK; + } + return grpc::Status(grpc::OUT_OF_RANGE, "We've reached the end. This is not an error but means transmission is finished"); + } + return grpc::Status(grpc::NOT_FOUND, "No result values found"); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +grpc::Status RiaGrpcPropertiesService::GetAvailableProperties(grpc::ServerContext* context, + const PropertiesRequest* request, + AvailableProperties* reply) +{ + int caseId = request->request_case().id(); + RimEclipseCase* eclipseCase = dynamic_cast(RiaGrpcServiceInterface::findCase(caseId)); + if (eclipseCase) + { + auto porosityModel = static_cast(request->porosity_model()); + auto resultData = eclipseCase->eclipseCaseData()->results(porosityModel); + auto resultType = static_cast(request->property_type()); + QStringList resultNames = resultData->resultNames(resultType); + if (!resultNames.empty()) + { + for (QString resultName : resultNames) + { + reply->add_property_names(resultName.toStdString()); + } + return grpc::Status::OK; + } + return grpc::Status(grpc::NOT_FOUND, "Could not find any results matching result type"); + } + return grpc::Status(grpc::NOT_FOUND, "No such case"); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +grpc::Status RiaGrpcPropertiesService::GetActiveCellResults(grpc::ServerContext* context, + const ResultRequest* request, + ResultReplyArray* reply, + RiaActiveCellResultsStateHandler* stateHandler) +{ + return stateHandler->assignReply(reply); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RiaGrpcPropertiesService::createCallbacks() +{ + typedef RiaGrpcPropertiesService Self; + + return { new RiaGrpcCallback(this, &Self::GetAvailableProperties, &Self::RequestGetAvailableProperties), + new RiaGrpcStreamCallback( + this, &Self::GetActiveCellResults, &Self::RequestGetActiveCellResults, new RiaActiveCellResultsStateHandler) + }; +} + +static bool RiaGrpcPropertiesService_init = RiaGrpcServiceFactory::instance()->registerCreator(typeid(RiaGrpcPropertiesService).hash_code()); \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.h b/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.h new file mode 100644 index 0000000000..30b82ab7e5 --- /dev/null +++ b/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.h @@ -0,0 +1,59 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 "RiaGrpcServiceInterface.h" + +#include "Properties.grpc.pb.h" + +#include +#include + +class RiaActiveCellResultsStateHandler +{ + typedef grpc::Status Status; +public: + RiaActiveCellResultsStateHandler(); + + Status init(const rips::ResultRequest* request); + Status assignReply(rips::ResultReplyArray* reply); + +private: + const rips::ResultRequest* m_request; + const std::vector* m_resultValues; + size_t m_currentCellIdx; +}; + +//================================================================================================== +// +// gRPC-service answering requests about property information for a given case and time step +// +//================================================================================================== +class RiaGrpcPropertiesService final : public rips::Properties::AsyncService, public RiaGrpcServiceInterface +{ +public: + grpc::Status GetAvailableProperties(grpc::ServerContext* context, + const rips::PropertiesRequest* request, + rips::AvailableProperties* reply) override; + grpc::Status GetActiveCellResults(grpc::ServerContext* context, + const rips::ResultRequest* request, + rips::ResultReplyArray* reply, + RiaActiveCellResultsStateHandler* stateHandler); + + std::vector createCallbacks() override; +}; + diff --git a/Python/api/ResInsight.py b/Python/api/ResInsight.py index c869fa029c..df468d90e8 100644 --- a/Python/api/ResInsight.py +++ b/Python/api/ResInsight.py @@ -7,7 +7,7 @@ import socket sys.path.insert(1, os.path.join(sys.path[0], '../generated')) -import Empty_pb2 +from Empty_pb2 import Empty import CaseInfo_pb2 import CaseInfo_pb2_grpc import Commands_pb2 @@ -18,142 +18,163 @@ import ProjectInfo_pb2 import ProjectInfo_pb2_grpc import ResInfo_pb2 import ResInfo_pb2_grpc +import Properties_pb2 +import Properties_pb2_grpc import RiaVersionInfo -MAX_MESSAGE_LENGTH = 128 * 1024 * 1024 - class ResInfo: - def __init__(self, channel): - self.resInfo = ResInfo_pb2_grpc.ResInfoStub(channel) - def versionMessage(self): - return self.resInfo.GetVersion(Empty_pb2.Empty()) - def majorVersion(self): - return self.versionMessage().major_version - def minorVersion(self): - return self.versionMessage().minor_version - def patchVersion(self): - return self.versionMessage().patch_version - def versionString(self): - return str(self.majorVersion()) + "." + str(self.minorVersion()) + "." + str(self.patchVersion()) + def __init__(self, channel): + self.resInfo = ResInfo_pb2_grpc.ResInfoStub(channel) + def versionMessage(self): + return self.resInfo.GetVersion(Empty()) + def majorVersion(self): + return self.versionMessage().major_version + def minorVersion(self): + return self.versionMessage().minor_version + def patchVersion(self): + return self.versionMessage().patch_version + def versionString(self): + return str(self.majorVersion()) + "." + str(self.minorVersion()) + "." + str(self.patchVersion()) class CommandExecutor: - def __init__(self, channel): - self.commands = Commands_pb2_grpc.CommandsStub(channel) - - def execute(self, commandParams): - try: - self.commands.Execute(commandParams) - except grpc.RpcError as e: - if e.code() == grpc.StatusCode.NOT_FOUND: - print("Command not found") - else: - print("Other error") + def __init__(self, channel): + self.commands = Commands_pb2_grpc.CommandsStub(channel) + + def execute(self, commandParams): + try: + self.commands.Execute(commandParams) + except grpc.RpcError as e: + if e.code() == grpc.StatusCode.NOT_FOUND: + print("Command not found") + else: + print("Other error") - def setTimeStep(self, caseId, timeStep): - return self.execute(Commands_pb2.CommandParams(setTimeStep=Commands_pb2.SetTimeStepParams(caseId=caseId, timeStep=timeStep))) - - def setMainWindowSize(self, width, height): - return self.execute(Commands_pb2.CommandParams(setMainWindowSize=Commands_pb2.SetMainWindowSizeParams(width=width, height=height))) + def setTimeStep(self, caseId, timeStep): + return self.execute(Commands_pb2.CommandParams(setTimeStep=Commands_pb2.SetTimeStepParams(caseId=caseId, timeStep=timeStep))) + + def setMainWindowSize(self, width, height): + return self.execute(Commands_pb2.CommandParams(setMainWindowSize=Commands_pb2.SetMainWindowSizeParams(width=width, height=height))) - def openProject(self, path): - return self.execute(Commands_pb2.CommandParams(openProject=Commands_pb2.FilePathRequest(path=path))) + def openProject(self, path): + return self.execute(Commands_pb2.CommandParams(openProject=Commands_pb2.FilePathRequest(path=path))) - def loadCase(self, path): - return self.execute(Commands_pb2.CommandParams(loadCase=Commands_pb2.FilePathRequest(path=path))) - - def closeProject(self): - return self.execute(Commands_pb2.CommandParams(closeProject=Empty_pb2.Empty())) + def loadCase(self, path): + return self.execute(Commands_pb2.CommandParams(loadCase=Commands_pb2.FilePathRequest(path=path))) + + def closeProject(self): + return self.execute(Commands_pb2.CommandParams(closeProject=Empty())) class GridInfo: - def __init__(self, channel): - self.gridInfo = GridInfo_pb2_grpc.GridInfoStub(channel) - - def getGridCount(self, caseId=0): - return self.gridInfo.GetGridCount(CaseInfo_pb2.Case(id=caseId)).count - - def getGridDimensions(self, caseId=0): - return self.gridInfo.GetGridDimensions(CaseInfo_pb2.Case(id=caseId)).dimensions - - def streamActiveCellInfo(self, caseId=0): - return self.gridInfo.StreamActiveCellInfo(CaseInfo_pb2.Case(id=caseId)) - + def __init__(self, channel): + self.gridInfo = GridInfo_pb2_grpc.GridInfoStub(channel) + + def getGridCount(self, caseId=0): + return self.gridInfo.GetGridCount(CaseInfo_pb2.Case(id=caseId)).count + + def getGridDimensions(self, caseId=0): + return self.gridInfo.GetGridDimensions(CaseInfo_pb2.Case(id=caseId)).dimensions + + def streamActiveCellInfo(self, caseId=0): + return self.gridInfo.StreamActiveCellInfo(CaseInfo_pb2.Case(id=caseId)) + class ProjectInfo: - def __init__(self, channel): - self.projectInfo = ProjectInfo_pb2_grpc.ProjectInfoStub(channel) - def selectedCases(self): - selected = self.projectInfo.SelectedCases(Empty_pb2.Empty()) - if selected is not None: - return selected.case_info - else: - return None - def allCases(self): - cases = self.projectInfo.AllCases(Empty_pb2.Empty()) - if cases is not None: - return allCases.case_info - else: - return None - + def __init__(self, channel): + self.projectInfo = ProjectInfo_pb2_grpc.ProjectInfoStub(channel) + def selectedCases(self): + selected = self.projectInfo.SelectedCases(Empty()) + if selected is not None: + return selected.case_info + else: + return None + def allCases(self): + cases = self.projectInfo.AllCases(Empty()) + if cases is not None: + return allCases.case_info + else: + return None + +class Properties: + def __init__(self, channel): + self.properties = Properties_pb2_grpc.PropertiesStub(channel) + def availableProperties(self, caseId, propertyType, porosityModel = 'MATRIX_MODEL'): + propertyTypeEnum = Properties_pb2.PropertyType.Value(propertyType) + porosityModelEnum = GridInfo_pb2.PorosityModelType.Value(porosityModel) + request = Properties_pb2.PropertiesRequest (request_case = CaseInfo_pb2.Case(id=caseId), + property_type = propertyTypeEnum, + porosity_model = porosityModelEnum) + return self.properties.GetAvailableProperties(request).property_names + def activeCellResults(self, caseId, propertyType, propertyName, timeStep, porosityModel = 'MATRIX_MODEL'): + propertyTypeEnum = Properties_pb2.PropertyType.Value(propertyType) + porosityModelEnum = GridInfo_pb2.PorosityModelType.Value(porosityModel) + request = Properties_pb2.ResultRequest(request_case = CaseInfo_pb2.Case(id=caseId), + property_type = propertyTypeEnum, + property_name = propertyName, + time_step = timeStep, + porosity_model = porosityModelEnum) + return self.properties.GetActiveCellResults(request) + class Instance: - @staticmethod - def is_port_in_use(port): - with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: - s.settimeout(0.2) - return s.connect_ex(('localhost', port)) == 0 - - @staticmethod - def launch(): - port = 50051 - portEnv = os.environ.get('RESINSIGHT_GRPC_PORT') - if portEnv: - port = int(portEnv) - - resInsightExecutable = os.environ.get('RESINSIGHT_EXECUTABLE') - if resInsightExecutable is None: - print('Error: Could not launch any ResInsight instances because RESINSIGHT_EXECUTABLE is not set') - return None - - while Instance.is_port_in_use(port): - port += 1 + @staticmethod + def is_port_in_use(port): + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: + s.settimeout(0.2) + return s.connect_ex(('localhost', port)) == 0 + + @staticmethod + def launch(): + port = 50051 + portEnv = os.environ.get('RESINSIGHT_GRPC_PORT') + if portEnv: + port = int(portEnv) + + resInsightExecutable = os.environ.get('RESINSIGHT_EXECUTABLE') + if resInsightExecutable is None: + print('Error: Could not launch any ResInsight instances because RESINSIGHT_EXECUTABLE is not set') + return None + + while Instance.is_port_in_use(port): + port += 1 - print('Port ' + str(port)) - print('Trying to launch', resInsightExecutable) - pid = os.spawnl(os.P_NOWAIT, resInsightExecutable, " --grpcserver " + str(port)) - print(pid) - return Instance(port) - - @staticmethod - def find(startPort = 50051, endPort = 50071): - portEnv = os.environ.get('RESINSIGHT_GRPC_PORT') - if portEnv: - startPort = int(portEnv) - endPort = startPort + 20 - - for tryPort in range(startPort, endPort): - if Instance.is_port_in_use(tryPort): - return Instance(tryPort) - - print('Error: Could not find any ResInsight instances responding between ports ' + str(startPort) + ' and ' + str(endPort)) - return None + print('Port ' + str(port)) + print('Trying to launch', resInsightExecutable) + pid = os.spawnl(os.P_NOWAIT, resInsightExecutable, " --grpcserver " + str(port)) + print(pid) + return Instance(port) + + @staticmethod + def find(startPort = 50051, endPort = 50071): + portEnv = os.environ.get('RESINSIGHT_GRPC_PORT') + if portEnv: + startPort = int(portEnv) + endPort = startPort + 20 + + for tryPort in range(startPort, endPort): + if Instance.is_port_in_use(tryPort): + return Instance(tryPort) + + print('Error: Could not find any ResInsight instances responding between ports ' + str(startPort) + ' and ' + str(endPort)) + return None - def __init__(self, port = 50051): - location = "localhost:" + str(port) - self.channel = grpc.insecure_channel(location, options=[('grpc.max_receive_message_length', MAX_MESSAGE_LENGTH)]) + def __init__(self, port = 50051): + location = "localhost:" + str(port) + self.channel = grpc.insecure_channel(location) - # Main version check package - self.resInfo = ResInfo(self.channel) - try: - majorVersionOk = self.resInfo.majorVersion() == int(RiaVersionInfo.RESINSIGHT_MAJOR_VERSION) - minorVersionOk = self.resInfo.minorVersion() == int(RiaVersionInfo.RESINSIGHT_MINOR_VERSION) - if not (majorVersionOk and minorVersionOk): - raise Exception('Version of ResInsight does not match version of Python API') - except grpc.RpcError as e: - if e.code() == grpc.StatusCode.UNAVAILABLE: - print('Info: Could not find any instances at port ' + str(port)) - except Exception as e: - print('Error:', e) - - # Service packages - self.commands = CommandExecutor(self.channel) - self.gridInfo = GridInfo(self.channel) - self.projectInfo = ProjectInfo(self.channel) - \ No newline at end of file + # Main version check package + self.resInfo = ResInfo(self.channel) + try: + majorVersionOk = self.resInfo.majorVersion() == int(RiaVersionInfo.RESINSIGHT_MAJOR_VERSION) + minorVersionOk = self.resInfo.minorVersion() == int(RiaVersionInfo.RESINSIGHT_MINOR_VERSION) + if not (majorVersionOk and minorVersionOk): + raise Exception('Version of ResInsight does not match version of Python API') + except grpc.RpcError as e: + if e.code() == grpc.StatusCode.UNAVAILABLE: + print('Info: Could not find any instances at port ' + str(port)) + except Exception as e: + print('Error:', e) + + # Service packages + self.commands = CommandExecutor(self.channel) + self.gridInfo = GridInfo(self.channel) + self.projectInfo = ProjectInfo(self.channel) + self.properties = Properties(self.channel) + \ No newline at end of file diff --git a/Python/examples/ResultValues.py b/Python/examples/ResultValues.py index ef9a16b2d9..efd09c7ff9 100644 --- a/Python/examples/ResultValues.py +++ b/Python/examples/ResultValues.py @@ -1,45 +1,19 @@ -from ResInsight import ResInsight -import grpc -import logging import sys - -def run(): - # NOTE(gRPC Python Team): .close() is possible on a channel and should be - # used in circumstances in which the with statement does not fit the needs - # of the code. - logging.basicConfig() - - try: - port = 50051 - if len(sys.argv) > 1: - port = sys.argv[1] - resInsight = ResInsight("localhost:" + port) - timeStepsInfo = resInsight.grid.numberOfTimeSteps(ResInsight.Case(id=0)) - print ("Number of time steps: " + str(timeStepsInfo.value)) - resultsAllTimeSteps = [] - for timeStep in range(0, timeStepsInfo.value - 1): - results = resInsight.grid.results(ResInsight.ResultRequest(ResInsight.Case(id=0), ResInsight.ResultAddress(0, "SOIL"), timeStep)) - print ("Got " + str(len(results.value)) + " values") - resultsAllTimeSteps.append(results.value) +import os +sys.path.insert(1, os.path.join(sys.path[0], '../api')) +import ResInsight - print("Have stored results array containing " + str(len(resultsAllTimeSteps)) + " time steps") +resInsight = ResInsight.Instance.find() +#gridCount = resInsight.gridInfo.getGridCount(caseId=0) +#gridDimensions = resInsight.gridInfo.getAllGridDimensions(caseId=0) - print("Looking for first cell with a decent SOIL value") - indexFirstProperCell = 0 - for i in range(0, len(resultsAllTimeSteps[0])): - result = resultsAllTimeSteps[0][i] - if indexFirstProperCell == 0 and result > 0.01: - indexFirstProperCell = i - - for resultsForTimeStep in resultsAllTimeSteps: - print ("Result for cell " + str(indexFirstProperCell) + ": " + str(resultsForTimeStep[indexFirstProperCell])) - - except grpc.RpcError as e: - if e.code() == grpc.StatusCode.NOT_FOUND: - print("Case id not found") - else: - logging.error('Other error: %s', e) +resultChunks = resInsight.properties.activeCellResults(0, 'DYNAMIC_NATIVE', 'SOIL', 2) - -if __name__ == '__main__': - run() +results = [] +for resultChunk in resultChunks: + for value in resultChunk.values: + results.append(value) +print("Number of active cells: " + str(len(results))) +print("15th active cell: ") +for result in results: + print(result) From d1a07998614f2a80cab0592c225c84fa798a5159 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Tue, 21 May 2019 16:33:41 +0200 Subject: [PATCH 063/396] Implemented getGridCellResults() --- .../RiaGrpcPropertiesService.cpp | 192 +++++++++++++----- .../GrpcInterface/RiaGrpcPropertiesService.h | 20 +- .../RigResultAccessorFactory.h | 8 +- Python/api/ResInsight.py | 10 + Python/examples/ResultValues.py | 17 +- 5 files changed, 173 insertions(+), 74 deletions(-) diff --git a/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp b/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp index d5bfd68d2f..9d482965a8 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp +++ b/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp @@ -17,78 +17,150 @@ ////////////////////////////////////////////////////////////////////////////////// #include "RiaGrpcPropertiesService.h" -#include "RiaGrpcGridInfoService.h" #include "RiaGrpcCallbacks.h" +#include "RiaGrpcGridInfoService.h" +#include "RigActiveCellInfo.h" +#include "RigActiveCellsResultAccessor.h" +#include "RigAllGridCellsResultAccessor.h" #include "RigCaseCellResultsData.h" #include "RigEclipseCaseData.h" #include "RigEclipseResultAddress.h" +#include "RigMainGrid.h" +#include "RigResultAccessor.h" +#include "RigResultAccessorFactory.h" #include "RimEclipseCase.h" using namespace rips; //-------------------------------------------------------------------------------------------------- +/// Abstract handler base class for streaming cell results to client /// //-------------------------------------------------------------------------------------------------- -RiaActiveCellResultsStateHandler::RiaActiveCellResultsStateHandler() - : m_request(nullptr) - , m_resultValues(nullptr) - , m_currentCellIdx(0u) -{ -} -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -grpc::Status RiaActiveCellResultsStateHandler::init(const ResultRequest* request) +class RiaCellResultsStateHandler { - int caseId = request->request_case().id(); - RimEclipseCase* eclipseCase = dynamic_cast(RiaGrpcServiceInterface::findCase(caseId)); - if (eclipseCase) + typedef grpc::Status Status; + +public: + //-------------------------------------------------------------------------------------------------- + /// + //-------------------------------------------------------------------------------------------------- + RiaCellResultsStateHandler() + : m_request(nullptr) + , m_currentCellIdx(0u) { - auto porosityModel = static_cast(request->porosity_model()); - auto resultData = eclipseCase->eclipseCaseData()->results(porosityModel); - auto resultType = static_cast(request->property_type()); - size_t timeStep = static_cast(request->time_step()); - RigEclipseResultAddress resAddr(resultType, QString::fromStdString(request->property_name())); - - if (resultData->hasResultEntry(resAddr)) - { - if (timeStep < (int)resultData->timeStepCount(resAddr)) - { - m_resultValues = &resultData->cellScalarResults(resAddr, timeStep); - return grpc::Status::OK; - } - return grpc::Status(grpc::NOT_FOUND, "No such time step"); - } - return grpc::Status(grpc::NOT_FOUND, "No such result"); } - return grpc::Status(grpc::NOT_FOUND, "Couldn't find an Eclipse case matching the case Id"); -} -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -grpc::Status RiaActiveCellResultsStateHandler::assignReply(ResultReplyArray* reply) -{ - if (m_resultValues) + //-------------------------------------------------------------------------------------------------- + /// + //-------------------------------------------------------------------------------------------------- + Status init(const ResultRequest* request) { - const size_t packageSize = RiaGrpcServiceInterface::numberOfMessagesForByteCount(sizeof(rips::ResultReplyArray)); + int caseId = request->request_case().id(); + RimEclipseCase* eclipseCase = dynamic_cast(RiaGrpcServiceInterface::findCase(caseId)); + if (eclipseCase) + { + auto porosityModel = static_cast(request->porosity_model()); + auto caseData = eclipseCase->eclipseCaseData(); + auto resultData = caseData->results(porosityModel); + auto resultType = static_cast(request->property_type()); + size_t timeStep = static_cast(request->time_step()); + RigEclipseResultAddress resAddr(resultType, QString::fromStdString(request->property_name())); + + if (resultData->ensureKnownResultLoaded(resAddr)) + { + if (timeStep < (int)resultData->timeStepCount(resAddr)) + { + initResultAccess(caseData, request->grid_index(), porosityModel, timeStep, resAddr); + return grpc::Status::OK; + } + return grpc::Status(grpc::NOT_FOUND, "No such time step"); + } + return grpc::Status(grpc::NOT_FOUND, "No such result"); + } + return grpc::Status(grpc::NOT_FOUND, "Couldn't find an Eclipse case matching the case Id"); + } + + //-------------------------------------------------------------------------------------------------- + /// + //-------------------------------------------------------------------------------------------------- + Status assignReply(ResultReplyArray* reply) + { + const size_t packageSize = RiaGrpcServiceInterface::numberOfMessagesForByteCount(sizeof(rips::ResultReplyArray)); size_t packageIndex = 0u; reply->mutable_values()->Reserve((int)packageSize); - for (; packageIndex < packageSize && m_currentCellIdx < m_resultValues->size(); ++packageIndex, ++m_currentCellIdx) + for (; packageIndex < packageSize && m_currentCellIdx < m_cellCount; ++packageIndex, ++m_currentCellIdx) { - reply->add_values(m_resultValues->at(m_currentCellIdx)); + reply->add_values(cellResult(m_currentCellIdx)); } if (packageIndex > 0u) { return grpc::Status::OK; } - return grpc::Status(grpc::OUT_OF_RANGE, "We've reached the end. This is not an error but means transmission is finished"); + return grpc::Status(grpc::OUT_OF_RANGE, + "We've reached the end. This is not an error but means transmission is finished"); } - return grpc::Status(grpc::NOT_FOUND, "No result values found"); -} + +protected: + virtual void initResultAccess(RigEclipseCaseData* caseData, + size_t gridIndex, + RiaDefines::PorosityModelType porosityModel, + size_t timeStepIndex, + RigEclipseResultAddress resVarAddr) = 0; + virtual double cellResult(size_t currentCellIndex) const = 0; + +protected: + const rips::ResultRequest* m_request; + size_t m_currentCellIdx; + size_t m_cellCount; +}; + +class RiaActiveCellResultsStateHandler : public RiaCellResultsStateHandler +{ +protected: + void initResultAccess(RigEclipseCaseData* caseData, + size_t gridIndex, + RiaDefines::PorosityModelType porosityModel, + size_t timeStepIndex, + RigEclipseResultAddress resVarAddr) override + { + auto activeCellInfo = caseData->activeCellInfo(porosityModel); + m_resultValues = &(caseData->results(porosityModel)->cellScalarResults(resVarAddr, timeStepIndex)); + m_cellCount = activeCellInfo->reservoirActiveCellCount(); + } + + double cellResult(size_t currentCellIndex) const override + { + return (*m_resultValues)[currentCellIndex]; + } + +private: + const std::vector* m_resultValues; +}; + +class RiaGridCellResultsStateHandler : public RiaCellResultsStateHandler +{ +protected: + void initResultAccess(RigEclipseCaseData* caseData, + size_t gridIndex, + RiaDefines::PorosityModelType porosityModel, + size_t timeStepIndex, + RigEclipseResultAddress resVarAddr) override + { + m_resultAccessor = RigResultAccessorFactory::createFromResultAddress(caseData, gridIndex, porosityModel, timeStepIndex, resVarAddr); + m_cellCount = caseData->grid(gridIndex)->cellCount(); + } + + double cellResult(size_t currentCellIndex) const override + { + return m_resultAccessor->cellScalar(currentCellIndex); + } + +private: + cvf::ref m_resultAccessor; +}; //-------------------------------------------------------------------------------------------------- /// @@ -121,10 +193,22 @@ grpc::Status RiaGrpcPropertiesService::GetAvailableProperties(grpc::ServerContex //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -grpc::Status RiaGrpcPropertiesService::GetActiveCellResults(grpc::ServerContext* context, - const ResultRequest* request, - ResultReplyArray* reply, - RiaActiveCellResultsStateHandler* stateHandler) +grpc::Status RiaGrpcPropertiesService::GetActiveCellResults(grpc::ServerContext* context, + const ResultRequest* request, + ResultReplyArray* reply, + RiaActiveCellResultsStateHandler* stateHandler) +{ + return stateHandler->assignReply(reply); +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +grpc::Status RiaGrpcPropertiesService::GetGridResults(grpc::ServerContext* context, + const rips::ResultRequest* request, + rips::ResultReplyArray* reply, + RiaGridCellResultsStateHandler* stateHandler) { return stateHandler->assignReply(reply); } @@ -136,10 +220,14 @@ std::vector RiaGrpcPropertiesService::createCallbacks( { typedef RiaGrpcPropertiesService Self; - return { new RiaGrpcCallback(this, &Self::GetAvailableProperties, &Self::RequestGetAvailableProperties), - new RiaGrpcStreamCallback( - this, &Self::GetActiveCellResults, &Self::RequestGetActiveCellResults, new RiaActiveCellResultsStateHandler) + return {new RiaGrpcCallback( + this, &Self::GetAvailableProperties, &Self::RequestGetAvailableProperties), + new RiaGrpcStreamCallback( + this, &Self::GetActiveCellResults, &Self::RequestGetActiveCellResults, new RiaActiveCellResultsStateHandler), + new RiaGrpcStreamCallback( + this, &Self::GetGridResults, &Self::RequestGetGridResults, new RiaGridCellResultsStateHandler) }; } -static bool RiaGrpcPropertiesService_init = RiaGrpcServiceFactory::instance()->registerCreator(typeid(RiaGrpcPropertiesService).hash_code()); \ No newline at end of file +static bool RiaGrpcPropertiesService_init = + RiaGrpcServiceFactory::instance()->registerCreator(typeid(RiaGrpcPropertiesService).hash_code()); \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.h b/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.h index 30b82ab7e5..64d4ed6306 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.h +++ b/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.h @@ -23,20 +23,8 @@ #include #include -class RiaActiveCellResultsStateHandler -{ - typedef grpc::Status Status; -public: - RiaActiveCellResultsStateHandler(); - - Status init(const rips::ResultRequest* request); - Status assignReply(rips::ResultReplyArray* reply); - -private: - const rips::ResultRequest* m_request; - const std::vector* m_resultValues; - size_t m_currentCellIdx; -}; +class RiaActiveCellResultsStateHandler; +class RiaGridCellResultsStateHandler; //================================================================================================== // @@ -53,6 +41,10 @@ public: const rips::ResultRequest* request, rips::ResultReplyArray* reply, RiaActiveCellResultsStateHandler* stateHandler); + grpc::Status GetGridResults(grpc::ServerContext* context, + const rips::ResultRequest* request, + rips::ResultReplyArray* reply, + RiaGridCellResultsStateHandler* stateHandler); std::vector createCallbacks() override; }; diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.h b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.h index 212ecad96d..128b816fc7 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.h +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.h @@ -2,17 +2,17 @@ // // Copyright (C) Statoil ASA // Copyright (C) Ceetron Solutions AS -// +// // 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 +// +// See the GNU General Public License at // for more details. // ///////////////////////////////////////////////////////////////////////////////// diff --git a/Python/api/ResInsight.py b/Python/api/ResInsight.py index df468d90e8..783457839f 100644 --- a/Python/api/ResInsight.py +++ b/Python/api/ResInsight.py @@ -112,6 +112,16 @@ class Properties: time_step = timeStep, porosity_model = porosityModelEnum) return self.properties.GetActiveCellResults(request) + def gridCellResults(self, caseId, propertyType, propertyName, timeStep, gridIndex = 0, porosityModel = 'MATRIX_MODEL'): + propertyTypeEnum = Properties_pb2.PropertyType.Value(propertyType) + porosityModelEnum = GridInfo_pb2.PorosityModelType.Value(porosityModel) + request = Properties_pb2.ResultRequest(request_case = CaseInfo_pb2.Case(id=caseId), + property_type = propertyTypeEnum, + property_name = propertyName, + time_step = timeStep, + grid_index = gridIndex, + porosity_model = porosityModelEnum) + return self.properties.GetGridResults(request) class Instance: @staticmethod diff --git a/Python/examples/ResultValues.py b/Python/examples/ResultValues.py index efd09c7ff9..dada3b7227 100644 --- a/Python/examples/ResultValues.py +++ b/Python/examples/ResultValues.py @@ -13,7 +13,16 @@ results = [] for resultChunk in resultChunks: for value in resultChunk.values: results.append(value) -print("Number of active cells: " + str(len(results))) -print("15th active cell: ") -for result in results: - print(result) +print("Transferred " + str(len(results)) + " cell results") +print("30th active cell: ") +print(results[29]) + +resultChunks = resInsight.properties.gridCellResults(0, 'DYNAMIC_NATIVE', 'SOIL', 2) + +results = [] +for resultChunk in resultChunks: + for value in resultChunk.values: + results.append(value) +print("Transferred " + str(len(results)) + " cell results") +print("124498th cell: ") +print(results[124498]) From ac18bc20ec315250870b0105d65a531dd2f4d7a6 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Wed, 22 May 2019 08:30:22 +0200 Subject: [PATCH 064/396] Remove requirement of assignReply from StateHandler template-interface * This is handled internally and is not required by the interface --- ApplicationCode/GrpcInterface/RiaGrpcCallbacks.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.h b/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.h index 3d34a9e548..ba9645e814 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.h +++ b/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.h @@ -129,14 +129,13 @@ private: //================================================================================================== // -// Templated *streaming* gRPC-callback calling service implementation callbacks +// Templated bi-directional *streaming* gRPC-callback calling service implementation callbacks // // The streaming callback needs a state handler for setting up and maintaining order. // // A fully functional stream handler needs to implement the following methods: // 1. Default Constructor // 2. grpc::Status init(const grpc::Message* request) -// 3. grpc::status assignReply(grpc::Message* reply) // //================================================================================================== From 90af7a2e6b439afc7da9c0300e41ad2c9efa6253 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Wed, 22 May 2019 08:45:25 +0200 Subject: [PATCH 065/396] gRPC: Cleanup streaming callback. DataCount storage is not necessary --- ApplicationCode/GrpcInterface/RiaGrpcCallbacks.h | 5 +---- ApplicationCode/GrpcInterface/RiaGrpcCallbacks.inl | 1 - 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.h b/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.h index ba9645e814..cfdfb2f34b 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.h +++ b/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.h @@ -129,7 +129,7 @@ private: //================================================================================================== // -// Templated bi-directional *streaming* gRPC-callback calling service implementation callbacks +// Templated server *streaming* gRPC-callback calling service implementation callbacks // // The streaming callback needs a state handler for setting up and maintaining order. // @@ -137,8 +137,6 @@ private: // 1. Default Constructor // 2. grpc::Status init(const grpc::Message* request) // -//================================================================================================== - //================================================================================================== template class RiaGrpcStreamCallback : public RiaGrpcRequestCallback @@ -165,7 +163,6 @@ private: ResponseWriterT m_responder; MethodImplT m_methodImpl; MethodRequestT m_methodRequest; - size_t m_dataCount; // This is used to keep track of progress. Only one item is sent for each invocation. std::unique_ptr m_stateHandler; }; diff --git a/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.inl b/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.inl index fd5f3be865..9a41879e62 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.inl +++ b/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.inl @@ -161,7 +161,6 @@ RiaGrpcStreamCallback::RiaGrpcStreamC , m_responder(&m_context) , m_methodImpl(methodImpl) , m_methodRequest(methodRequest) - , m_dataCount(0u) , m_stateHandler(stateHandler) { } From c30721593eb29681b11adacaf59b11a680054d24 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Wed, 22 May 2019 15:30:09 +0200 Subject: [PATCH 066/396] #4430 Implement client -> server streaming framework and SetActiveCellProperty --- .../GrpcInterface/GrpcProtos/GridInfo.proto | 10 +- .../GrpcInterface/GrpcProtos/Properties.proto | 18 +-- .../GrpcInterface/RiaGrpcCallbacks.h | 63 +++++++-- .../GrpcInterface/RiaGrpcCallbacks.inl | 126 +++++++++++++++++- .../GrpcInterface/RiaGrpcGridInfoService.cpp | 26 ++-- .../GrpcInterface/RiaGrpcGridInfoService.h | 18 +-- .../RiaGrpcPropertiesService.cpp | 107 ++++++++++++--- .../GrpcInterface/RiaGrpcPropertiesService.h | 9 +- .../GrpcInterface/RiaGrpcServer.cpp | 20 ++- Python/api/ResInsight.py | 57 +++++++- Python/examples/GridInfoStreamingExample.py | 2 +- Python/examples/SetResultValues.py | 16 +++ 12 files changed, 391 insertions(+), 81 deletions(-) create mode 100644 Python/examples/SetResultValues.py diff --git a/ApplicationCode/GrpcInterface/GrpcProtos/GridInfo.proto b/ApplicationCode/GrpcInterface/GrpcProtos/GridInfo.proto index 0baaf00d4b..5344e57617 100644 --- a/ApplicationCode/GrpcInterface/GrpcProtos/GridInfo.proto +++ b/ApplicationCode/GrpcInterface/GrpcProtos/GridInfo.proto @@ -9,7 +9,7 @@ service GridInfo // This function returns a two dimensional matrix: One row for each grid, starting with the main grid. rpc GetGridCount(Case) returns(GridCount) {} rpc GetGridDimensions(Case) returns (GridDimensions) {} - rpc StreamActiveCellInfo(ActiveCellInfoRequest) returns (stream ActiveCellInfoArray) {} + rpc GetCellInfoForActiveCells(CellInfoRequest) returns (stream CellInfoArray) {} rpc GetAllCoarseningInfoArray(Case) returns (CoarseningInfoArray) {} rpc GetTimeSteps(Case) returns (TimeStepDates) {} rpc GetTimeStepDaysSinceStart(Case) returns (DoubleDates) {} @@ -37,18 +37,18 @@ enum PorosityModelType FRACTURE_MODEL = 1; } -message ActiveCellInfoRequest +message CellInfoRequest { int32 case_id = 1; PorosityModelType porosity_model = 2; } -message ActiveCellInfoArray +message CellInfoArray { - repeated ActiveCellInfo data = 1; + repeated CellInfo data = 1; } -message ActiveCellInfo +message CellInfo { int32 grid_index = 1; int32 parent_grid_index = 2; diff --git a/ApplicationCode/GrpcInterface/GrpcProtos/Properties.proto b/ApplicationCode/GrpcInterface/GrpcProtos/Properties.proto index c44909615d..ac91299841 100644 --- a/ApplicationCode/GrpcInterface/GrpcProtos/Properties.proto +++ b/ApplicationCode/GrpcInterface/GrpcProtos/Properties.proto @@ -9,10 +9,10 @@ package rips; service Properties { rpc GetAvailableProperties(PropertiesRequest) returns (AvailableProperties) {} - rpc GetActiveCellResults(ResultRequest) returns (stream ResultReplyArray) {} - rpc GetGridResults(ResultRequest) returns (stream ResultReplyArray) {} - rpc SetActiveCellResults(stream ResultRequestArray) returns (Empty) {} - rpc SetGridResults(stream ResultRequestArray) returns (Empty) {} + rpc GetActiveCellResults(ResultRequest) returns (stream ResultArray) {} + rpc GetGridResults(ResultRequest) returns (stream ResultArray) {} + rpc SetActiveCellResults(stream ResultRequestChunk) returns (Empty) {} + rpc SetGridResults(stream ResultRequestChunk) returns (Empty) {} } enum PropertyType @@ -56,14 +56,14 @@ message TimeStep int32 index = 1; } -message ResultRequestArray +message ResultRequestChunk { - repeated double values = 1; - Case request_case = 2; - TimeStep time_step = 3; + // Params needs to be sent in the first message + ResultRequest params = 1; + ResultArray values = 2; } -message ResultReplyArray +message ResultArray { repeated double values = 1; } diff --git a/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.h b/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.h index cfdfb2f34b..14b9449694 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.h +++ b/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.h @@ -25,6 +25,7 @@ using grpc::CompletionQueue; using grpc::ServerAsyncResponseWriter; +using grpc::ServerAsyncReader; using grpc::ServerAsyncWriter; using grpc::ServerCompletionQueue; using grpc::ServerContext; @@ -44,7 +45,8 @@ public: enum CallState { CREATE_HANDLER, - INIT_REQUEST, + INIT_REQUEST_STARTED, + INIT_REQUEST_COMPLETED, PROCESS_REQUEST, FINISH_REQUEST }; @@ -56,9 +58,10 @@ public: virtual QString name() const = 0; virtual RiaAbstractGrpcCallback* createNewFromThis() const = 0; virtual void createRequestHandler(ServerCompletionQueue* completionQueue) = 0; - virtual void initRequest() = 0; - virtual void processRequest() = 0; - virtual void finishRequest() {} + virtual void onInitRequestStarted() {} + virtual void onInitRequestCompleted() = 0; + virtual void onProcessRequest() = 0; + virtual void onFinishRequest() {} inline CallState callState() const; inline const Status& status() const; @@ -114,8 +117,8 @@ public: RiaAbstractGrpcCallback* createNewFromThis() const override; void createRequestHandler(ServerCompletionQueue* completionQueue) override; - void initRequest() override; - void processRequest() override; + void onInitRequestCompleted() override; + void onProcessRequest() override; protected: virtual QString methodType() const; @@ -133,7 +136,7 @@ private: // // The streaming callback needs a state handler for setting up and maintaining order. // -// A fully functional stream handler needs to implement the following methods: +// A fully functional state handler needs to implement the following methods: // 1. Default Constructor // 2. grpc::Status init(const grpc::Message* request) // @@ -152,8 +155,8 @@ public: RiaAbstractGrpcCallback* createNewFromThis() const override; void createRequestHandler(ServerCompletionQueue* completionQueue) override; - void initRequest() override; - void processRequest() override; + void onInitRequestCompleted() override; + void onProcessRequest() override; protected: virtual QString methodType() const; @@ -166,4 +169,46 @@ private: std::unique_ptr m_stateHandler; }; +//================================================================================================== +// +// Templated client *streaming* gRPC-callback calling service implementation callbacks +// +// The streaming callback needs a state handler for setting up and maintaining order. +// +// A fully functional state handler needs to implement the following methods: +// 1. Default Constructor +// 2. grpc::Status init(const grpc::Message* request) +// 3. void finish() any updates required after completion +// +//================================================================================================== +template +class RiaGrpcClientStreamCallback : public RiaGrpcRequestCallback +{ +public: + typedef ServerAsyncReader RequestReaderT; + typedef std::function MethodImplT; + typedef std::function< + void(ServiceT&, ServerContext*, RequestReaderT*, CompletionQueue*, ServerCompletionQueue*, void*)> + MethodRequestT; + + RiaGrpcClientStreamCallback(ServiceT* service, MethodImplT methodImpl, MethodRequestT methodRequest, StateHandlerT* stateHandler); + + RiaAbstractGrpcCallback* createNewFromThis() const override; + void createRequestHandler(ServerCompletionQueue* completionQueue) override; + void onInitRequestStarted() override; + void onInitRequestCompleted() override; + void onProcessRequest() override; + void onFinishRequest() override; + +protected: + virtual QString methodType() const; + +private: + ServerContext m_context; + RequestReaderT m_reader; + MethodImplT m_methodImpl; + MethodRequestT m_methodRequest; + std::unique_ptr m_stateHandler; +}; + #include "RiaGrpcCallbacks.inl" diff --git a/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.inl b/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.inl index 9a41879e62..e5c47b625e 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.inl +++ b/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.inl @@ -116,24 +116,26 @@ RiaAbstractGrpcCallback* RiaGrpcCallback::createNewF template void RiaGrpcCallback::createRequestHandler(ServerCompletionQueue* completionQueue) { + // The Request-method is where the request gets filled in with data from the gRPC stack: m_methodRequest(*this->m_service, &m_context, &this->m_request, &m_responder, completionQueue, completionQueue, this); - this->setCallState(RiaAbstractGrpcCallback::INIT_REQUEST); + this->setCallState(RiaAbstractGrpcCallback::INIT_REQUEST_COMPLETED); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- template -void RiaGrpcCallback::initRequest() +void RiaGrpcCallback::onInitRequestCompleted() { this->setCallState(RiaAbstractGrpcCallback::PROCESS_REQUEST); + this->onProcessRequest(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- template -void RiaGrpcCallback::processRequest() +void RiaGrpcCallback::onProcessRequest() { this->m_status = m_methodImpl(*this->m_service, &m_context, &this->m_request, &this->m_reply); m_responder.Finish(this->m_reply, this->m_status, this); @@ -183,24 +185,25 @@ void RiaGrpcStreamCallback::createReq ServerCompletionQueue* completionQueue) { m_methodRequest(*this->m_service, &m_context, &this->m_request, &m_responder, completionQueue, completionQueue, this); - this->setCallState(RiaAbstractGrpcCallback::INIT_REQUEST); + this->setCallState(RiaAbstractGrpcCallback::INIT_REQUEST_COMPLETED); } //-------------------------------------------------------------------------------------------------- /// Perform initialisation tasks at the time of receiving a request //-------------------------------------------------------------------------------------------------- template -void RiaGrpcStreamCallback::initRequest() +void RiaGrpcStreamCallback::onInitRequestCompleted() { this->m_status = m_stateHandler->init(&this->m_request); this->setCallState(RiaAbstractGrpcCallback::PROCESS_REQUEST); + this->onProcessRequest(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- template -void RiaGrpcStreamCallback::processRequest() +void RiaGrpcStreamCallback::onProcessRequest() { this->m_reply = ReplyT(); // Make sure it is reset @@ -236,3 +239,114 @@ QString RiaGrpcStreamCallback::method { return "StreamingMethod"; } + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +template +RiaGrpcClientStreamCallback::RiaGrpcClientStreamCallback(ServiceT* service, + MethodImplT methodImpl, + MethodRequestT methodRequest, + StateHandlerT* stateHandler) + : RiaGrpcRequestCallback(service) + , m_reader(&m_context) + , m_methodImpl(methodImpl) + , m_methodRequest(methodRequest) + , m_stateHandler(stateHandler) +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +template +RiaAbstractGrpcCallback* RiaGrpcClientStreamCallback::createNewFromThis() const +{ + return new RiaGrpcClientStreamCallback( + this->m_service, m_methodImpl, m_methodRequest, new StateHandlerT); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +template +void RiaGrpcClientStreamCallback::createRequestHandler( + ServerCompletionQueue* completionQueue) +{ + m_methodRequest(*this->m_service, &m_context, &this->m_reader, completionQueue, completionQueue, this); + this->setCallState(RiaAbstractGrpcCallback::INIT_REQUEST_STARTED); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +template +void RiaGrpcClientStreamCallback::onInitRequestStarted() +{ + this->setCallState(RiaAbstractGrpcCallback::INIT_REQUEST_COMPLETED); + m_reader.Read(&m_request, this); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +template +void RiaGrpcClientStreamCallback::onInitRequestCompleted() +{ + this->setCallState(RiaAbstractGrpcCallback::PROCESS_REQUEST); + this->m_status = m_stateHandler->init(&this->m_request); // Fully received the stream package so can now init + m_reader.Read(&m_request, this); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +template +void RiaGrpcClientStreamCallback::onProcessRequest() +{ + this->m_reply = ReplyT(); // Make sure it is reset + + if (!this->m_status.ok()) + { + m_reader.Finish(this->m_reply, this->m_status, this); + this->setCallState(RiaAbstractGrpcCallback::FINISH_REQUEST); + return; + } + + this->m_status = m_methodImpl(*this->m_service, &m_context, &this->m_request, &this->m_reply, m_stateHandler.get()); + if (!this->m_status.ok()) + { + this->setCallState(RiaAbstractGrpcCallback::FINISH_REQUEST); + if (this->m_status.error_code() == grpc::OUT_OF_RANGE) + { + m_reader.Finish(this->m_reply, grpc::Status::OK, this); + } + else + { + m_reader.FinishWithError(this->m_status, this); + } + } + else + { + m_reader.Read(&this->m_request, this); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +template +void RiaGrpcClientStreamCallback::onFinishRequest() +{ + m_stateHandler->finish(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +template +QString RiaGrpcClientStreamCallback::methodType() const +{ + return "ClientStreamingMethod"; +} diff --git a/ApplicationCode/GrpcInterface/RiaGrpcGridInfoService.cpp b/ApplicationCode/GrpcInterface/RiaGrpcGridInfoService.cpp index 9fe8d03472..e6c17815a6 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcGridInfoService.cpp +++ b/ApplicationCode/GrpcInterface/RiaGrpcGridInfoService.cpp @@ -43,7 +43,7 @@ RiaActiveCellInfoStateHandler::RiaActiveCellInfoStateHandler() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -grpc::Status RiaActiveCellInfoStateHandler::init(const rips::ActiveCellInfoRequest* request) +grpc::Status RiaActiveCellInfoStateHandler::init(const rips::CellInfoRequest* request) { CAF_ASSERT(request); m_request = request; @@ -87,7 +87,7 @@ grpc::Status RiaActiveCellInfoStateHandler::init(const rips::ActiveCellInfoReque //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -grpc::Status RiaActiveCellInfoStateHandler::assignNextActiveCellInfoData(rips::ActiveCellInfo* cellInfo) +grpc::Status RiaActiveCellInfoStateHandler::assignNextActiveCellInfoData(rips::CellInfo* cellInfo) { const std::vector& reservoirCells = m_eclipseCase->eclipseCaseData()->mainGrid()->globalCellArray(); @@ -96,7 +96,7 @@ grpc::Status RiaActiveCellInfoStateHandler::assignNextActiveCellInfoData(rips::A size_t cellIdxToTry = m_currentCellIdx++; if (m_activeCellInfo->isActive(cellIdxToTry)) { - assignActiveCellInfoData(cellInfo, reservoirCells, cellIdxToTry); + assignCellInfoData(cellInfo, reservoirCells, cellIdxToTry); return grpc::Status::OK; } } @@ -106,7 +106,7 @@ grpc::Status RiaActiveCellInfoStateHandler::assignNextActiveCellInfoData(rips::A //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RiaActiveCellInfoStateHandler::assignActiveCellInfoData(rips::ActiveCellInfo* cellInfo, +void RiaActiveCellInfoStateHandler::assignCellInfoData(rips::CellInfo* cellInfo, const std::vector& reservoirCells, size_t cellIdx) { @@ -184,18 +184,18 @@ const std::vector& RiaActiveCellInfoStateHandler::reservoirCells() cons //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -grpc::Status RiaActiveCellInfoStateHandler::assignReply(rips::ActiveCellInfoArray* reply) +grpc::Status RiaActiveCellInfoStateHandler::assignReply(rips::CellInfoArray* reply) { - const size_t packageSize = RiaGrpcServiceInterface::numberOfMessagesForByteCount(sizeof(rips::ActiveCellInfoArray)); + const size_t packageSize = RiaGrpcServiceInterface::numberOfMessagesForByteCount(sizeof(rips::CellInfoArray)); size_t packageIndex = 0u; reply->mutable_data()->Reserve((int)packageSize); for (; packageIndex < packageSize && m_currentCellIdx < m_activeCellInfo->reservoirCellCount(); ++packageIndex) { - rips::ActiveCellInfo singleCellInfo; + rips::CellInfo singleCellInfo; grpc::Status singleCellInfoStatus = assignNextActiveCellInfoData(&singleCellInfo); if (singleCellInfoStatus.ok()) { - rips::ActiveCellInfo* allocCellInfo = reply->add_data(); + rips::CellInfo* allocCellInfo = reply->add_data(); *allocCellInfo = singleCellInfo; } else @@ -258,9 +258,9 @@ grpc::Status RiaGrpcGridInfoService::GetGridDimensions(grpc::ServerContext* //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -grpc::Status RiaGrpcGridInfoService::StreamActiveCellInfo(grpc::ServerContext* context, - const rips::ActiveCellInfoRequest* request, - rips::ActiveCellInfoArray* reply, +grpc::Status RiaGrpcGridInfoService::GetCellInfoForActiveCells(grpc::ServerContext* context, + const rips::CellInfoRequest* request, + rips::CellInfoArray* reply, RiaActiveCellInfoStateHandler* stateHandler) { return stateHandler->assignReply(reply); @@ -275,8 +275,8 @@ std::vector RiaGrpcGridInfoService::createCallbacks() return {new RiaGrpcCallback(this, &Self::GetGridCount, &Self::RequestGetGridCount), new RiaGrpcCallback(this, &Self::GetGridDimensions, &Self::RequestGetGridDimensions), - new RiaGrpcStreamCallback( - this, &Self::StreamActiveCellInfo, &Self::RequestStreamActiveCellInfo, new RiaActiveCellInfoStateHandler)}; + new RiaGrpcStreamCallback( + this, &Self::GetCellInfoForActiveCells, &Self::RequestGetCellInfoForActiveCells, new RiaActiveCellInfoStateHandler)}; } static bool RiaGrpcGridInfoService_init = diff --git a/ApplicationCode/GrpcInterface/RiaGrpcGridInfoService.h b/ApplicationCode/GrpcInterface/RiaGrpcGridInfoService.h index b73c724977..b08bdd8d93 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcGridInfoService.h +++ b/ApplicationCode/GrpcInterface/RiaGrpcGridInfoService.h @@ -45,15 +45,15 @@ class RiaActiveCellInfoStateHandler public: RiaActiveCellInfoStateHandler(); - Status init(const rips::ActiveCellInfoRequest* request); - Status assignNextActiveCellInfoData(rips::ActiveCellInfo* cellInfo); - void assignActiveCellInfoData(rips::ActiveCellInfo* cellInfo, const std::vector& reservoirCells, size_t cellIdx); - Status assignReply(rips::ActiveCellInfoArray* reply); + Status init(const rips::CellInfoRequest* request); + Status assignNextActiveCellInfoData(rips::CellInfo* cellInfo); + void assignCellInfoData(rips::CellInfo* cellInfo, const std::vector& reservoirCells, size_t cellIdx); + Status assignReply(rips::CellInfoArray* reply); RigActiveCellInfo* activeCellInfo() const; const std::vector& reservoirCells() const; protected: - const rips::ActiveCellInfoRequest* m_request; + const rips::CellInfoRequest* m_request; RimEclipseCase* m_eclipseCase; RiaDefines::PorosityModelType m_porosityModel; RigActiveCellInfo* m_activeCellInfo; @@ -71,9 +71,9 @@ class RiaGrpcGridInfoService final : public rips::GridInfo::AsyncService, public public: grpc::Status GetGridCount(grpc::ServerContext* context, const rips::Case* request, rips::GridCount* reply) override; grpc::Status GetGridDimensions(grpc::ServerContext* context, const rips::Case* request, rips::GridDimensions* reply) override; - grpc::Status StreamActiveCellInfo(grpc::ServerContext* context, - const rips::ActiveCellInfoRequest* request, - rips::ActiveCellInfoArray* reply, - RiaActiveCellInfoStateHandler* stateHandler); + grpc::Status GetCellInfoForActiveCells(grpc::ServerContext* context, + const rips::CellInfoRequest* request, + rips::CellInfoArray* reply, + RiaActiveCellInfoStateHandler* stateHandler); std::vector createCallbacks() override; }; diff --git a/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp b/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp index 9d482965a8..8d3bcf06b4 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp +++ b/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp @@ -29,7 +29,10 @@ #include "RigMainGrid.h" #include "RigResultAccessor.h" #include "RigResultAccessorFactory.h" +#include "RigResultModifier.h" +#include "RigResultModifierFactory.h" +#include "Rim3dView.h" #include "RimEclipseCase.h" using namespace rips; @@ -58,12 +61,13 @@ public: //-------------------------------------------------------------------------------------------------- Status init(const ResultRequest* request) { - int caseId = request->request_case().id(); - RimEclipseCase* eclipseCase = dynamic_cast(RiaGrpcServiceInterface::findCase(caseId)); - if (eclipseCase) + int caseId = request->request_case().id(); + m_eclipseCase = dynamic_cast(RiaGrpcServiceInterface::findCase(caseId)); + + if (m_eclipseCase) { auto porosityModel = static_cast(request->porosity_model()); - auto caseData = eclipseCase->eclipseCaseData(); + auto caseData = m_eclipseCase->eclipseCaseData(); auto resultData = caseData->results(porosityModel); auto resultType = static_cast(request->property_type()); size_t timeStep = static_cast(request->time_step()); @@ -83,12 +87,24 @@ public: return grpc::Status(grpc::NOT_FOUND, "Couldn't find an Eclipse case matching the case Id"); } + //-------------------------------------------------------------------------------------------------- + /// Client streamers need to be initialised with the encapsulated parameters + //-------------------------------------------------------------------------------------------------- + Status init(const ResultRequestChunk* request) + { + if (request->has_params()) + { + return init(&(request->params())); + } + return grpc::Status(grpc::INVALID_ARGUMENT, "Need to have ResultRequest parameters in first message"); + } + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- - Status assignReply(ResultReplyArray* reply) + Status assignStreamReply(ResultArray* reply) { - const size_t packageSize = RiaGrpcServiceInterface::numberOfMessagesForByteCount(sizeof(rips::ResultReplyArray)); + const size_t packageSize = RiaGrpcServiceInterface::numberOfMessagesForByteCount(sizeof(rips::ResultArray)); size_t packageIndex = 0u; reply->mutable_values()->Reserve((int)packageSize); for (; packageIndex < packageSize && m_currentCellIdx < m_cellCount; ++packageIndex, ++m_currentCellIdx) @@ -103,6 +119,40 @@ public: "We've reached the end. This is not an error but means transmission is finished"); } + //-------------------------------------------------------------------------------------------------- + /// + //-------------------------------------------------------------------------------------------------- + Status receiveStreamRequest(const ResultRequestChunk* request) + { + if (request->has_values()) + { + auto values = request->values().values(); + for (int i = 0; i < values.size() && m_currentCellIdx < m_cellCount; ++i, ++m_currentCellIdx) + { + setCellResult(m_currentCellIdx, values[i]); + } + if (m_currentCellIdx == m_cellCount - 1) + { + return grpc::Status(grpc::OUT_OF_RANGE, "All values have been written"); + } + + return Status::OK; + } + return grpc::Status(grpc::OUT_OF_RANGE, "No messages to write"); + } + + //-------------------------------------------------------------------------------------------------- + /// + //-------------------------------------------------------------------------------------------------- + void finish() + { + for (Rim3dView* view : m_eclipseCase->views()) + { + view->setCurrentTimeStepAndUpdate(view->currentTimeStep()); + view->createDisplayModelAndRedraw(); + } + } + protected: virtual void initResultAccess(RigEclipseCaseData* caseData, size_t gridIndex, @@ -110,9 +160,11 @@ protected: size_t timeStepIndex, RigEclipseResultAddress resVarAddr) = 0; virtual double cellResult(size_t currentCellIndex) const = 0; + virtual void setCellResult(size_t currentCellIndex, double value) = 0; protected: const rips::ResultRequest* m_request; + RimEclipseCase* m_eclipseCase; size_t m_currentCellIdx; size_t m_cellCount; }; @@ -127,7 +179,7 @@ protected: RigEclipseResultAddress resVarAddr) override { auto activeCellInfo = caseData->activeCellInfo(porosityModel); - m_resultValues = &(caseData->results(porosityModel)->cellScalarResults(resVarAddr, timeStepIndex)); + m_resultValues = &(caseData->results(porosityModel)->modifiableCellScalarResult(resVarAddr, timeStepIndex)); m_cellCount = activeCellInfo->reservoirActiveCellCount(); } @@ -136,8 +188,13 @@ protected: return (*m_resultValues)[currentCellIndex]; } + void setCellResult(size_t currentCellIndex, double value) override + { + (*m_resultValues)[currentCellIndex] = value; + } + private: - const std::vector* m_resultValues; + std::vector* m_resultValues; }; class RiaGridCellResultsStateHandler : public RiaCellResultsStateHandler @@ -150,6 +207,7 @@ protected: RigEclipseResultAddress resVarAddr) override { m_resultAccessor = RigResultAccessorFactory::createFromResultAddress(caseData, gridIndex, porosityModel, timeStepIndex, resVarAddr); + m_resultModifier = RigResultModifierFactory::createResultModifier(caseData, gridIndex, porosityModel, timeStepIndex, resVarAddr); m_cellCount = caseData->grid(gridIndex)->cellCount(); } @@ -158,8 +216,14 @@ protected: return m_resultAccessor->cellScalar(currentCellIndex); } + void setCellResult(size_t currentCellIndex, double value) override + { + return m_resultModifier->setCellScalar(currentCellIndex, value); + } + private: cvf::ref m_resultAccessor; + cvf::ref m_resultModifier; }; //-------------------------------------------------------------------------------------------------- @@ -195,10 +259,10 @@ grpc::Status RiaGrpcPropertiesService::GetAvailableProperties(grpc::ServerContex //-------------------------------------------------------------------------------------------------- grpc::Status RiaGrpcPropertiesService::GetActiveCellResults(grpc::ServerContext* context, const ResultRequest* request, - ResultReplyArray* reply, + ResultArray* reply, RiaActiveCellResultsStateHandler* stateHandler) { - return stateHandler->assignReply(reply); + return stateHandler->assignStreamReply(reply); } @@ -207,10 +271,21 @@ grpc::Status RiaGrpcPropertiesService::GetActiveCellResults(grpc::ServerContext* //-------------------------------------------------------------------------------------------------- grpc::Status RiaGrpcPropertiesService::GetGridResults(grpc::ServerContext* context, const rips::ResultRequest* request, - rips::ResultReplyArray* reply, + rips::ResultArray* reply, RiaGridCellResultsStateHandler* stateHandler) { - return stateHandler->assignReply(reply); + return stateHandler->assignStreamReply(reply); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +grpc::Status RiaGrpcPropertiesService::SetActiveCellResults(grpc::ServerContext* context, + const rips::ResultRequestChunk* request, + rips::Empty* reply, + RiaActiveCellResultsStateHandler* stateHandler) +{ + return stateHandler->receiveStreamRequest(request); } //-------------------------------------------------------------------------------------------------- @@ -222,10 +297,12 @@ std::vector RiaGrpcPropertiesService::createCallbacks( return {new RiaGrpcCallback( this, &Self::GetAvailableProperties, &Self::RequestGetAvailableProperties), - new RiaGrpcStreamCallback( + new RiaGrpcStreamCallback( this, &Self::GetActiveCellResults, &Self::RequestGetActiveCellResults, new RiaActiveCellResultsStateHandler), - new RiaGrpcStreamCallback( - this, &Self::GetGridResults, &Self::RequestGetGridResults, new RiaGridCellResultsStateHandler) + new RiaGrpcStreamCallback( + this, &Self::GetGridResults, &Self::RequestGetGridResults, new RiaGridCellResultsStateHandler), + new RiaGrpcClientStreamCallback( + this, &Self::SetActiveCellResults, &Self::RequestSetActiveCellResults, new RiaActiveCellResultsStateHandler) }; } diff --git a/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.h b/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.h index 64d4ed6306..c62d83f2d3 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.h +++ b/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.h @@ -39,13 +39,16 @@ public: rips::AvailableProperties* reply) override; grpc::Status GetActiveCellResults(grpc::ServerContext* context, const rips::ResultRequest* request, - rips::ResultReplyArray* reply, + rips::ResultArray* reply, RiaActiveCellResultsStateHandler* stateHandler); grpc::Status GetGridResults(grpc::ServerContext* context, const rips::ResultRequest* request, - rips::ResultReplyArray* reply, + rips::ResultArray* reply, RiaGridCellResultsStateHandler* stateHandler); - + grpc::Status SetActiveCellResults(grpc::ServerContext* context, + const rips::ResultRequestChunk* request, + rips::Empty* reply, + RiaActiveCellResultsStateHandler* stateHandler); std::vector createCallbacks() override; }; diff --git a/ApplicationCode/GrpcInterface/RiaGrpcServer.cpp b/ApplicationCode/GrpcInterface/RiaGrpcServer.cpp index 128c6c81c5..8acbe4a04b 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcServer.cpp +++ b/ApplicationCode/GrpcInterface/RiaGrpcServer.cpp @@ -63,7 +63,7 @@ public: void initialize(); void processRequests(); void quit(); - int currentPortNumber; + int currentPortNumber; private: void waitForNextRequest(); @@ -242,22 +242,28 @@ void RiaGrpcServerImpl::process(RiaAbstractGrpcCallback* method) RiaLogging::debug(QString("Initialising request handler for: %1").arg(method->name())); method->createRequestHandler(m_completionQueue.get()); } - else if (method->callState() == RiaAbstractGrpcCallback::INIT_REQUEST) + else if (method->callState() == RiaAbstractGrpcCallback::INIT_REQUEST_STARTED) { // Perform initialization and immediately process the first request // The initialization is necessary for streaming services. - RiaLogging::info(QString("Starting handling: %1").arg(method->name())); - method->initRequest(); - method->processRequest(); + method->onInitRequestStarted(); + + } + else if (method->callState() == RiaAbstractGrpcCallback::INIT_REQUEST_COMPLETED) + { + // Perform initialization and immediately process the first request + // The initialization is necessary for streaming services. + RiaLogging::info(QString("Initialising handling: %1").arg(method->name())); + method->onInitRequestCompleted(); } else if (method->callState() == RiaAbstractGrpcCallback::PROCESS_REQUEST) { - method->processRequest(); + method->onProcessRequest(); } else { RiaLogging::info(QString("Finished handling: %1").arg(method->name())); - method->finishRequest(); + method->onFinishRequest(); process(method->createNewFromThis()); delete method; } diff --git a/Python/api/ResInsight.py b/Python/api/ResInsight.py index 783457839f..e3b1d99784 100644 --- a/Python/api/ResInsight.py +++ b/Python/api/ResInsight.py @@ -4,6 +4,8 @@ import grpc import os import sys import socket +import logging + sys.path.insert(1, os.path.join(sys.path[0], '../generated')) @@ -68,14 +70,14 @@ class GridInfo: def __init__(self, channel): self.gridInfo = GridInfo_pb2_grpc.GridInfoStub(channel) - def getGridCount(self, caseId=0): + def gridCount(self, caseId=0): return self.gridInfo.GetGridCount(CaseInfo_pb2.Case(id=caseId)).count - def getGridDimensions(self, caseId=0): + def gridDimensions(self, caseId=0): return self.gridInfo.GetGridDimensions(CaseInfo_pb2.Case(id=caseId)).dimensions - def streamActiveCellInfo(self, caseId=0): - return self.gridInfo.StreamActiveCellInfo(CaseInfo_pb2.Case(id=caseId)) + def cellInfoForActiveCells(self, caseId=0): + return self.gridInfo.GetCellInfoForActiveCells(CaseInfo_pb2.Case(id=caseId)) class ProjectInfo: def __init__(self, channel): @@ -96,6 +98,33 @@ class ProjectInfo: class Properties: def __init__(self, channel): self.properties = Properties_pb2_grpc.PropertiesStub(channel) + + def generateResultRequestArrays(self, array, parameters): + # Each double is 8 bytes. A good chunk size is 64KiB = 65536B + # Meaning ideal number of doubles would be 8192. + # However we need overhead space, so if we choose 8160 in chunk size + # We have 256B left for overhead which should be plenty + chunkSize = 8000 + index = -1 + while index < len(array): + chunk = Properties_pb2.ResultRequestChunk() + if index is -1: + chunk.params.CopyFrom(parameters) + print("Added parameters") + index += 1; + else: + actualChunkSize = min(len(array) - index + 1, chunkSize) + chunk.values.CopyFrom(Properties_pb2.ResultArray(values = array[index:index+actualChunkSize])) + print("Added values") + index += actualChunkSize + + print(index) + yield chunk + # Final empty message to signal completion + chunk = Properties_pb2.ResultRequestChunk() + yield chunk + print("finished") + def availableProperties(self, caseId, propertyType, porosityModel = 'MATRIX_MODEL'): propertyTypeEnum = Properties_pb2.PropertyType.Value(propertyType) porosityModelEnum = GridInfo_pb2.PorosityModelType.Value(porosityModel) @@ -122,6 +151,25 @@ class Properties: grid_index = gridIndex, porosity_model = porosityModelEnum) return self.properties.GetGridResults(request) + def setActiveCellResults(self, values, caseId, propertyType, propertyName, timeStep, gridIndex = 0, porosityModel = 'MATRIX_MODEL'): + propertyTypeEnum = Properties_pb2.PropertyType.Value(propertyType) + porosityModelEnum = GridInfo_pb2.PorosityModelType.Value(porosityModel) + print (propertyName) + request = Properties_pb2.ResultRequest(request_case = CaseInfo_pb2.Case(id=caseId), + property_type = propertyTypeEnum, + property_name = propertyName, + time_step = timeStep, + grid_index = gridIndex, + porosity_model = porosityModelEnum) + try: + request_iterator = self.generateResultRequestArrays(values, request) + print("Starting to send data") + self.properties.SetActiveCellResults(request_iterator) + except grpc.RpcError as e: + if e.code() == grpc.StatusCode.NOT_FOUND: + print("Command not found") + else: + print("Other error", e) class Instance: @staticmethod @@ -166,6 +214,7 @@ class Instance: return None def __init__(self, port = 50051): + logging.basicConfig() location = "localhost:" + str(port) self.channel = grpc.insecure_channel(location) diff --git a/Python/examples/GridInfoStreamingExample.py b/Python/examples/GridInfoStreamingExample.py index 999dc7f25c..4a9c753d0a 100644 --- a/Python/examples/GridInfoStreamingExample.py +++ b/Python/examples/GridInfoStreamingExample.py @@ -7,7 +7,7 @@ resInsight = ResInsight.Instance.find() #gridCount = resInsight.gridInfo.getGridCount(caseId=0) #gridDimensions = resInsight.gridInfo.getAllGridDimensions(caseId=0) -activeCellInfoChunks = resInsight.gridInfo.streamActiveCellInfo(caseId=0) +activeCellInfoChunks = resInsight.gridInfo.cellInfoForActiveCells(caseId=0) #print("Number of grids: " + str(gridCount)) #print(gridDimensions) diff --git a/Python/examples/SetResultValues.py b/Python/examples/SetResultValues.py new file mode 100644 index 0000000000..a9ec77698f --- /dev/null +++ b/Python/examples/SetResultValues.py @@ -0,0 +1,16 @@ +import sys +import os +sys.path.insert(1, os.path.join(sys.path[0], '../api')) +import ResInsight + +resInsight = ResInsight.Instance.find() +#gridCount = resInsight.gridInfo.getGridCount(caseId=0) +#gridDimensions = resInsight.gridInfo.getAllGridDimensions(caseId=0) + +values = [] +for i in range(0, 11124): + values.append(i % 2 * 0.5); + +print("Applying all values to time step 0") +resInsight.properties.setActiveCellResults(values, 0, 'DYNAMIC_NATIVE', 'SOIL', 0) + From 690ab840c503ec40597838525d3045418d325a1d Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Wed, 22 May 2019 16:03:03 +0200 Subject: [PATCH 067/396] Minor gRPC updates --- .../GrpcInterface/GrpcProtos/GridInfo.proto | 7 +++ .../GrpcInterface/RiaGrpcGridInfoService.cpp | 49 +++++++++++++++++++ .../GrpcInterface/RiaGrpcGridInfoService.h | 5 +- Python/api/ResInsight.py | 18 +++++-- Python/examples/GridInfoStreamingExample.py | 6 ++- Python/examples/SetResultValues.py | 13 +++-- 6 files changed, 88 insertions(+), 10 deletions(-) diff --git a/ApplicationCode/GrpcInterface/GrpcProtos/GridInfo.proto b/ApplicationCode/GrpcInterface/GrpcProtos/GridInfo.proto index 5344e57617..add8d75fd1 100644 --- a/ApplicationCode/GrpcInterface/GrpcProtos/GridInfo.proto +++ b/ApplicationCode/GrpcInterface/GrpcProtos/GridInfo.proto @@ -9,6 +9,7 @@ service GridInfo // This function returns a two dimensional matrix: One row for each grid, starting with the main grid. rpc GetGridCount(Case) returns(GridCount) {} rpc GetGridDimensions(Case) returns (GridDimensions) {} + rpc GetCellCount(CellInfoRequest) returns (CellCount) {} rpc GetCellInfoForActiveCells(CellInfoRequest) returns (stream CellInfoArray) {} rpc GetAllCoarseningInfoArray(Case) returns (CoarseningInfoArray) {} rpc GetTimeSteps(Case) returns (TimeStepDates) {} @@ -31,6 +32,12 @@ message Vec3i { int32 k = 3; } +message CellCount +{ + int32 active_cell_count = 1; + int32 reservoir_cell_count = 2; +} + enum PorosityModelType { MATRIX_MODEL = 0; diff --git a/ApplicationCode/GrpcInterface/RiaGrpcGridInfoService.cpp b/ApplicationCode/GrpcInterface/RiaGrpcGridInfoService.cpp index e6c17815a6..9f04df35b6 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcGridInfoService.cpp +++ b/ApplicationCode/GrpcInterface/RiaGrpcGridInfoService.cpp @@ -255,6 +255,53 @@ grpc::Status RiaGrpcGridInfoService::GetGridDimensions(grpc::ServerContext* return grpc::Status(grpc::NOT_FOUND, "Eclipse Case not found"); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +grpc::Status RiaGrpcGridInfoService::GetCellCount(grpc::ServerContext* context, const rips::CellInfoRequest* request, rips::CellCount* reply) +{ + RimCase* rimCase = findCase(request->case_id()); + + RimEclipseCase* eclipseCase = dynamic_cast(rimCase); + if (eclipseCase) + { + auto porosityModel = RiaDefines::PorosityModelType(request->porosity_model()); + RigActiveCellInfo* activeCellInfo = eclipseCase->eclipseCaseData()->activeCellInfo(porosityModel); + reply->set_active_cell_count((int) activeCellInfo->reservoirActiveCellCount()); + reply->set_reservoir_cell_count((int) activeCellInfo->reservoirCellCount()); + return grpc::Status::OK; + } + return grpc::Status(grpc::NOT_FOUND, "Eclipse Case not found"); +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +grpc::Status +RiaGrpcGridInfoService::GetTimeSteps(grpc::ServerContext* context, const rips::Case* request, rips::TimeStepDates* reply) +{ + RimCase* rimCase = findCase(request->id()); + + RimEclipseCase* eclipseCase = dynamic_cast(rimCase); + if (eclipseCase) + { + std::vector timeStepDates = eclipseCase->timeStepDates(); + for (QDateTime dateTime : timeStepDates) + { + rips::TimeStepDate* date = reply->add_date(); + date->set_year(dateTime.date().year()); + date->set_month(dateTime.date().month()); + date->set_day(dateTime.date().day()); + date->set_hour(dateTime.time().hour()); + date->set_minute(dateTime.time().minute()); + date->set_second(dateTime.time().second()); + } + return grpc::Status::OK; + } + return grpc::Status(grpc::NOT_FOUND, "Eclipse Case not found"); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -275,6 +322,8 @@ std::vector RiaGrpcGridInfoService::createCallbacks() return {new RiaGrpcCallback(this, &Self::GetGridCount, &Self::RequestGetGridCount), new RiaGrpcCallback(this, &Self::GetGridDimensions, &Self::RequestGetGridDimensions), + new RiaGrpcCallback(this, &Self::GetCellCount, &Self::RequestGetCellCount), + new RiaGrpcCallback(this, &Self::GetTimeSteps, &Self::RequestGetTimeSteps), new RiaGrpcStreamCallback( this, &Self::GetCellInfoForActiveCells, &Self::RequestGetCellInfoForActiveCells, new RiaActiveCellInfoStateHandler)}; } diff --git a/ApplicationCode/GrpcInterface/RiaGrpcGridInfoService.h b/ApplicationCode/GrpcInterface/RiaGrpcGridInfoService.h index b08bdd8d93..828dd9e1da 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcGridInfoService.h +++ b/ApplicationCode/GrpcInterface/RiaGrpcGridInfoService.h @@ -71,9 +71,12 @@ class RiaGrpcGridInfoService final : public rips::GridInfo::AsyncService, public public: grpc::Status GetGridCount(grpc::ServerContext* context, const rips::Case* request, rips::GridCount* reply) override; grpc::Status GetGridDimensions(grpc::ServerContext* context, const rips::Case* request, rips::GridDimensions* reply) override; + grpc::Status GetCellCount(grpc::ServerContext* context, const rips::CellInfoRequest* request, rips::CellCount* reply) override; + grpc::Status GetTimeSteps(grpc::ServerContext* context, const rips::Case* request, rips::TimeStepDates* reply) override; + grpc::Status GetCellInfoForActiveCells(grpc::ServerContext* context, const rips::CellInfoRequest* request, rips::CellInfoArray* reply, - RiaActiveCellInfoStateHandler* stateHandler); + RiaActiveCellInfoStateHandler* stateHandler); std::vector createCallbacks() override; }; diff --git a/Python/api/ResInsight.py b/Python/api/ResInsight.py index e3b1d99784..1ea89097c4 100644 --- a/Python/api/ResInsight.py +++ b/Python/api/ResInsight.py @@ -76,9 +76,21 @@ class GridInfo: def gridDimensions(self, caseId=0): return self.gridInfo.GetGridDimensions(CaseInfo_pb2.Case(id=caseId)).dimensions - def cellInfoForActiveCells(self, caseId=0): - return self.gridInfo.GetCellInfoForActiveCells(CaseInfo_pb2.Case(id=caseId)) - + def cellCount(self, caseId=0, porosityModel='MATRIX_MODEL'): + porosityModelEnum = GridInfo_pb2.PorosityModelType.Value(porosityModel) + request = GridInfo_pb2.CellInfoRequest(case_id=caseId, + porosity_model=porosityModel) + return self.gridInfo.GetCellCount(request) + + def cellInfoForActiveCells(self, caseId=0, porosityModel='MATRIX_MODEL'): + porosityModelEnum = GridInfo_pb2.PorosityModelType.Value(porosityModel) + request = GridInfo_pb2.CellInfoRequest(case_id=caseId, + porosity_model=porosityModel) + return self.gridInfo.GetCellInfoForActiveCells(request) + + def timeSteps(self, caseId=0): + return self.gridInfo.GetTimeSteps(CaseInfo_pb2.Case(id=caseId)) + class ProjectInfo: def __init__(self, channel): self.projectInfo = ProjectInfo_pb2_grpc.ProjectInfoStub(channel) diff --git a/Python/examples/GridInfoStreamingExample.py b/Python/examples/GridInfoStreamingExample.py index 4a9c753d0a..9df2a9fa70 100644 --- a/Python/examples/GridInfoStreamingExample.py +++ b/Python/examples/GridInfoStreamingExample.py @@ -7,6 +7,9 @@ resInsight = ResInsight.Instance.find() #gridCount = resInsight.gridInfo.getGridCount(caseId=0) #gridDimensions = resInsight.gridInfo.getAllGridDimensions(caseId=0) +cellCounts = resInsight.gridInfo.cellCount(caseId=0) +print("Number of active cells: " + str(cellCounts.active_cell_count)) + activeCellInfoChunks = resInsight.gridInfo.cellInfoForActiveCells(caseId=0) #print("Number of grids: " + str(gridCount)) @@ -16,6 +19,7 @@ receivedActiveCells = [] for activeCellChunk in activeCellInfoChunks: for activeCell in activeCellChunk.data: receivedActiveCells.append(activeCell) -print("Number of active cells: " + str(len(receivedActiveCells))) + +assert(cellCounts.active_cell_count == len(receivedActiveCells)) print("First active cell: ") print(receivedActiveCells[0]) diff --git a/Python/examples/SetResultValues.py b/Python/examples/SetResultValues.py index a9ec77698f..d17b0f8e1b 100644 --- a/Python/examples/SetResultValues.py +++ b/Python/examples/SetResultValues.py @@ -4,13 +4,16 @@ sys.path.insert(1, os.path.join(sys.path[0], '../api')) import ResInsight resInsight = ResInsight.Instance.find() -#gridCount = resInsight.gridInfo.getGridCount(caseId=0) -#gridDimensions = resInsight.gridInfo.getAllGridDimensions(caseId=0) + +activeCellCount = resInsight.gridInfo.cellCount(caseId=0).active_cell_count values = [] -for i in range(0, 11124): +for i in range(0, activeCellCount): values.append(i % 2 * 0.5); -print("Applying all values to time step 0") -resInsight.properties.setActiveCellResults(values, 0, 'DYNAMIC_NATIVE', 'SOIL', 0) + +timeSteps = resInsight.gridInfo.timeSteps(caseId=0) +for i in range(0, len(timeSteps)): + print("Applying values to all time step " + str(i)) + resInsight.properties.setActiveCellResults(values, 0, 'DYNAMIC_NATIVE', 'SOIL', i) From df405dd396f38d5a7c5073cc1f4689f684862476 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 23 May 2019 13:45:21 +0200 Subject: [PATCH 068/396] #4437 Make sure formation colors are available and visible for all time step --- ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp index c0aceb7c4d..0ffc4c55a9 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp @@ -90,7 +90,7 @@ cvf::ref RigResultAccessorFactory::createFromResultAddress(co } size_t adjustedTimeStepIndex = timeStepIndex; - if (resVarAddr.m_resultCatType == RiaDefines::STATIC_NATIVE) + if (resVarAddr.m_resultCatType == RiaDefines::STATIC_NATIVE || resVarAddr.m_resultCatType == RiaDefines::FORMATION_NAMES) { adjustedTimeStepIndex = 0; } From 0cb2194bfb8922b45d047d24a5ff90ec48df8760 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 23 May 2019 14:14:51 +0200 Subject: [PATCH 069/396] #4445 Active cells : Always use PORV if present --- ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp b/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp index fdf5313d0f..c93d7fbfd7 100644 --- a/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp +++ b/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp @@ -2183,14 +2183,16 @@ ecl_grid_type* RifReaderEclipseOutput::loadMainGrid() const ecl_grid_type* mainEclGrid = nullptr; { - if (m_ecl_init_file && RifEclipseOutputFileTools::isExportedFromIntersect(m_ecl_init_file)) + if (m_ecl_init_file) { ecl_kw_type* actnumFromPorv = RifEclipseOutputFileTools::createActnumFromPorv(m_ecl_init_file); if (actnumFromPorv) { int* actnum_values = ecl_kw_get_int_ptr(actnumFromPorv); - - mainEclGrid = ecl_grid_alloc_ext_actnum(RiaStringEncodingTools::toNativeEncoded(m_fileName).data(), actnum_values); + if (actnum_values) + { + mainEclGrid = ecl_grid_alloc_ext_actnum(RiaStringEncodingTools::toNativeEncoded(m_fileName).data(), actnum_values); + } ecl_kw_free(actnumFromPorv); } From 6ad0c8fbe1ab6fc54d2be9f236816f9fa3d96513 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Thu, 23 May 2019 09:58:04 +0200 Subject: [PATCH 070/396] gRPC: Fix up comments and clean up callback code --- .../Application/RiaGuiApplication.cpp | 2 +- .../GrpcInterface/RiaGrpcCallbacks.h | 13 ++- .../GrpcInterface/RiaGrpcCallbacks.inl | 99 +++++++++++-------- .../GrpcInterface/RiaGrpcServer.cpp | 24 ++--- ApplicationCode/GrpcInterface/RiaGrpcServer.h | 2 +- 5 files changed, 79 insertions(+), 61 deletions(-) diff --git a/ApplicationCode/Application/RiaGuiApplication.cpp b/ApplicationCode/Application/RiaGuiApplication.cpp index 36a3b71ed4..e249339fb7 100644 --- a/ApplicationCode/Application/RiaGuiApplication.cpp +++ b/ApplicationCode/Application/RiaGuiApplication.cpp @@ -1681,7 +1681,7 @@ void RiaGuiApplication::runIdleProcessing() #ifdef ENABLE_GRPC if (!caf::ProgressInfoStatic::isRunning()) { - m_grpcServer->processRequests(); + m_grpcServer->processAllQueuedRequests(); } #endif } diff --git a/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.h b/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.h index 14b9449694..53a6986dac 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.h +++ b/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.h @@ -59,7 +59,7 @@ public: virtual RiaAbstractGrpcCallback* createNewFromThis() const = 0; virtual void createRequestHandler(ServerCompletionQueue* completionQueue) = 0; virtual void onInitRequestStarted() {} - virtual void onInitRequestCompleted() = 0; + virtual void onInitRequestCompleted() {} virtual void onProcessRequest() = 0; virtual void onFinishRequest() {} @@ -67,7 +67,7 @@ public: inline const Status& status() const; protected: - inline void setCallState(CallState state); + inline void setNextCallState(CallState state); protected: CallState m_state; @@ -117,7 +117,6 @@ public: RiaAbstractGrpcCallback* createNewFromThis() const override; void createRequestHandler(ServerCompletionQueue* completionQueue) override; - void onInitRequestCompleted() override; void onProcessRequest() override; protected: @@ -132,11 +131,11 @@ private: //================================================================================================== // -// Templated server *streaming* gRPC-callback calling service implementation callbacks +// Templated server->client *streaming* gRPC-callback calling service implementation callbacks // // The streaming callback needs a state handler for setting up and maintaining order. // -// A fully functional state handler needs to implement the following methods: +// A fully functional state handler for server->client streaming needs to implement the following methods: // 1. Default Constructor // 2. grpc::Status init(const grpc::Message* request) // @@ -171,11 +170,11 @@ private: //================================================================================================== // -// Templated client *streaming* gRPC-callback calling service implementation callbacks +// Templated client->server *streaming* gRPC-callback calling service implementation callbacks // // The streaming callback needs a state handler for setting up and maintaining order. // -// A fully functional state handler needs to implement the following methods: +// A fully functional state handler for client->server streaming needs to implement the following methods: // 1. Default Constructor // 2. grpc::Status init(const grpc::Message* request) // 3. void finish() any updates required after completion diff --git a/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.inl b/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.inl index e5c47b625e..059eb72d2c 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.inl +++ b/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.inl @@ -41,7 +41,7 @@ const Status& RiaAbstractGrpcCallback::status() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -inline void RiaAbstractGrpcCallback::setCallState(CallState state) +inline void RiaAbstractGrpcCallback::setNextCallState(CallState state) { m_state = state; } @@ -116,19 +116,10 @@ RiaAbstractGrpcCallback* RiaGrpcCallback::createNewF template void RiaGrpcCallback::createRequestHandler(ServerCompletionQueue* completionQueue) { - // The Request-method is where the request gets filled in with data from the gRPC stack: + // The Request-method is where the service gets registered to respond to a given request. m_methodRequest(*this->m_service, &m_context, &this->m_request, &m_responder, completionQueue, completionQueue, this); - this->setCallState(RiaAbstractGrpcCallback::INIT_REQUEST_COMPLETED); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -template -void RiaGrpcCallback::onInitRequestCompleted() -{ - this->setCallState(RiaAbstractGrpcCallback::PROCESS_REQUEST); - this->onProcessRequest(); + // Simple unary requests don't need initialisation, so proceed to process as soon as a request turns up. + this->setNextCallState(RiaAbstractGrpcCallback::PROCESS_REQUEST); } //-------------------------------------------------------------------------------------------------- @@ -137,9 +128,13 @@ void RiaGrpcCallback::onInitRequestCompleted() template void RiaGrpcCallback::onProcessRequest() { + // Call request handler method this->m_status = m_methodImpl(*this->m_service, &m_context, &this->m_request, &this->m_reply); + // Simply unary requests are finished as soon as you've done any processing. + // So next time we receive a new tag on the command queue we should proceed to finish. + this->setNextCallState(RiaAbstractGrpcCallback::FINISH_REQUEST); + // Finish will push this callback back on the command queue (now with Finish as the call state). m_responder.Finish(this->m_reply, this->m_status, this); - this->setCallState(RiaAbstractGrpcCallback::FINISH_REQUEST); } //-------------------------------------------------------------------------------------------------- @@ -184,49 +179,62 @@ template::createRequestHandler( ServerCompletionQueue* completionQueue) { + // The Request-method is where the service gets registered to respond to a given request. m_methodRequest(*this->m_service, &m_context, &this->m_request, &m_responder, completionQueue, completionQueue, this); - this->setCallState(RiaAbstractGrpcCallback::INIT_REQUEST_COMPLETED); + // Server->Client Streaming requests require initialisation. However, we receive the complete request immediately. + // So can proceed directly to completion of the init request. + this->setNextCallState(RiaAbstractGrpcCallback::INIT_REQUEST_COMPLETED); } //-------------------------------------------------------------------------------------------------- -/// Perform initialisation tasks at the time of receiving a request +/// Perform initialisation tasks at the time of receiving a complete request //-------------------------------------------------------------------------------------------------- template void RiaGrpcStreamCallback::onInitRequestCompleted() { + // Initialise streaming state handler this->m_status = m_stateHandler->init(&this->m_request); - this->setCallState(RiaAbstractGrpcCallback::PROCESS_REQUEST); + + if (!this->m_status.ok()) + { + // We have an error. Proceed to finish and report the status + this->setNextCallState(RiaAbstractGrpcCallback::FINISH_REQUEST); + m_responder.Finish(this->m_status, this); + return; + } + + // Move on to processing and perform the first processing immediately since the client will + // not request anything more. + this->setNextCallState(RiaAbstractGrpcCallback::PROCESS_REQUEST); this->onProcessRequest(); } //-------------------------------------------------------------------------------------------------- -/// +/// Process a streaming request and send one package //-------------------------------------------------------------------------------------------------- template void RiaGrpcStreamCallback::onProcessRequest() { this->m_reply = ReplyT(); // Make sure it is reset - - if (!this->m_status.ok()) - { - m_responder.Finish(this->m_status, this); - this->setCallState(RiaAbstractGrpcCallback::FINISH_REQUEST); - return; - } - + + // Call request handler method this->m_status = m_methodImpl(*this->m_service, &m_context, &this->m_request, &this->m_reply, m_stateHandler.get()); + if (this->m_status.ok()) { + // The write call will send data to client AND put this callback back on the command queue + // so that this method gets called again to send the next stream package. m_responder.Write(this->m_reply, this); } else { - this->setCallState(RiaAbstractGrpcCallback::FINISH_REQUEST); + this->setNextCallState(RiaAbstractGrpcCallback::FINISH_REQUEST); // Out of range means we're finished but it isn't an error if (this->m_status.error_code() == grpc::OUT_OF_RANGE) { this->m_status = Status::OK; } + // Finish will put this callback back on the command queue, now with a finish state. m_responder.Finish(this->m_status, this); } } @@ -274,8 +282,11 @@ template::createRequestHandler( ServerCompletionQueue* completionQueue) { + // The Request-method is where the service gets registered to respond to a given request. m_methodRequest(*this->m_service, &m_context, &this->m_reader, completionQueue, completionQueue, this); - this->setCallState(RiaAbstractGrpcCallback::INIT_REQUEST_STARTED); + // The client->server streaming requires initialisation and each request package is streamed asynchronously + // So we need to start and complete the init request. + this->setNextCallState(RiaAbstractGrpcCallback::INIT_REQUEST_STARTED); } //-------------------------------------------------------------------------------------------------- @@ -284,7 +295,9 @@ void RiaGrpcClientStreamCallback::cre template void RiaGrpcClientStreamCallback::onInitRequestStarted() { - this->setCallState(RiaAbstractGrpcCallback::INIT_REQUEST_COMPLETED); + this->setNextCallState(RiaAbstractGrpcCallback::INIT_REQUEST_COMPLETED); + // The read call will start reading the request data and push this callback back onto the command queue + // when the read call is completed. m_reader.Read(&m_request, this); } @@ -294,8 +307,19 @@ void RiaGrpcClientStreamCallback::onI template void RiaGrpcClientStreamCallback::onInitRequestCompleted() { - this->setCallState(RiaAbstractGrpcCallback::PROCESS_REQUEST); - this->m_status = m_stateHandler->init(&this->m_request); // Fully received the stream package so can now init + this->setNextCallState(RiaAbstractGrpcCallback::PROCESS_REQUEST); + // Fully received the stream package so can now init + this->m_status = m_stateHandler->init(&this->m_request); + + if (!this->m_status.ok()) + { + // We have an error. Proceed to finish and report the status + m_reader.FinishWithError(this->m_status, this); + this->setNextCallState(RiaAbstractGrpcCallback::FINISH_REQUEST); + return; + } + + // Start reading and push this back onto the command queue. m_reader.Read(&m_request, this); } @@ -306,18 +330,13 @@ template::onProcessRequest() { this->m_reply = ReplyT(); // Make sure it is reset - - if (!this->m_status.ok()) - { - m_reader.Finish(this->m_reply, this->m_status, this); - this->setCallState(RiaAbstractGrpcCallback::FINISH_REQUEST); - return; - } - + + // Call request handler method this->m_status = m_methodImpl(*this->m_service, &m_context, &this->m_request, &this->m_reply, m_stateHandler.get()); + if (!this->m_status.ok()) { - this->setCallState(RiaAbstractGrpcCallback::FINISH_REQUEST); + this->setNextCallState(RiaAbstractGrpcCallback::FINISH_REQUEST); if (this->m_status.error_code() == grpc::OUT_OF_RANGE) { m_reader.Finish(this->m_reply, grpc::Status::OK, this); diff --git a/ApplicationCode/GrpcInterface/RiaGrpcServer.cpp b/ApplicationCode/GrpcInterface/RiaGrpcServer.cpp index 8acbe4a04b..dfba26d327 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcServer.cpp +++ b/ApplicationCode/GrpcInterface/RiaGrpcServer.cpp @@ -61,7 +61,7 @@ public: void run(); void runInThread(); void initialize(); - void processRequests(); + void processAllQueuedRequests(); void quit(); int currentPortNumber; @@ -169,7 +169,7 @@ void RiaGrpcServerImpl::initialize() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RiaGrpcServerImpl::processRequests() +void RiaGrpcServerImpl::processAllQueuedRequests() { std::lock_guard requestLock(m_requestMutex); @@ -182,7 +182,8 @@ void RiaGrpcServerImpl::processRequests() } //-------------------------------------------------------------------------------------------------- -/// Gracefully shut down the GRPC server. The internal order is important. +/// Gracefully shut down the GRPC server. +/// BE VERY CAREFUL ABOUT CHANGING THE ORDER IN THIS METHOD. IT IS IMPORTANT! //-------------------------------------------------------------------------------------------------- void RiaGrpcServerImpl::quit() { @@ -214,7 +215,8 @@ void RiaGrpcServerImpl::quit() } //-------------------------------------------------------------------------------------------------- -/// +/// Block and wait for requests from the client from the command queue. +/// The requests are pushed onto the Unprocessed Request queue which are handled in processRequests //-------------------------------------------------------------------------------------------------- void RiaGrpcServerImpl::waitForNextRequest() { @@ -233,26 +235,24 @@ void RiaGrpcServerImpl::waitForNextRequest() } //-------------------------------------------------------------------------------------------------- -/// +/// The handling of calls pushed onto the command queue. We only get one queued callback per client request. +/// The gRPC calls triggered in the callback will see each callback pushed back onto the command queue. +/// The call state will then determine what the callback should do next. //-------------------------------------------------------------------------------------------------- void RiaGrpcServerImpl::process(RiaAbstractGrpcCallback* method) { if (method->callState() == RiaAbstractGrpcCallback::CREATE_HANDLER) { - RiaLogging::debug(QString("Initialising request handler for: %1").arg(method->name())); + RiaLogging::debug(QString("Creating request handler for: %1").arg(method->name())); method->createRequestHandler(m_completionQueue.get()); } else if (method->callState() == RiaAbstractGrpcCallback::INIT_REQUEST_STARTED) { - // Perform initialization and immediately process the first request - // The initialization is necessary for streaming services. method->onInitRequestStarted(); } else if (method->callState() == RiaAbstractGrpcCallback::INIT_REQUEST_COMPLETED) { - // Perform initialization and immediately process the first request - // The initialization is necessary for streaming services. RiaLogging::info(QString("Initialising handling: %1").arg(method->name())); method->onInitRequestCompleted(); } @@ -333,9 +333,9 @@ void RiaGrpcServer::initialize() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RiaGrpcServer::processRequests() +void RiaGrpcServer::processAllQueuedRequests() { - m_serverImpl->processRequests(); + m_serverImpl->processAllQueuedRequests(); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/GrpcInterface/RiaGrpcServer.h b/ApplicationCode/GrpcInterface/RiaGrpcServer.h index 0812d6ee2d..bb74ced170 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcServer.h +++ b/ApplicationCode/GrpcInterface/RiaGrpcServer.h @@ -41,7 +41,7 @@ public: bool isRunning() const; void run(); void runInThread(); - void processRequests(); + void processAllQueuedRequests(); void quit(); static int findAvailablePortNumber(int defaultPortNumber); From e29c7acc03529a9b054de2a89925d8aa0ead195a Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Thu, 23 May 2019 09:58:22 +0200 Subject: [PATCH 071/396] gRPC: fix python client script code --- Python/api/ResInsight.py | 2 +- Python/examples/SetResultValues.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Python/api/ResInsight.py b/Python/api/ResInsight.py index 1ea89097c4..b85ed9ea98 100644 --- a/Python/api/ResInsight.py +++ b/Python/api/ResInsight.py @@ -103,7 +103,7 @@ class ProjectInfo: def allCases(self): cases = self.projectInfo.AllCases(Empty()) if cases is not None: - return allCases.case_info + return cases.case_info else: return None diff --git a/Python/examples/SetResultValues.py b/Python/examples/SetResultValues.py index d17b0f8e1b..e9b45668aa 100644 --- a/Python/examples/SetResultValues.py +++ b/Python/examples/SetResultValues.py @@ -13,7 +13,7 @@ for i in range(0, activeCellCount): timeSteps = resInsight.gridInfo.timeSteps(caseId=0) -for i in range(0, len(timeSteps)): +for i in range(0, len(timeSteps.date)): print("Applying values to all time step " + str(i)) resInsight.properties.setActiveCellResults(values, 0, 'DYNAMIC_NATIVE', 'SOIL', i) From 650af20e062cc95629093354fcf9390f176323b7 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Thu, 23 May 2019 13:59:19 +0200 Subject: [PATCH 072/396] #4429 Implement return status handling for command file interface --- .../Core/CMakeLists_files.cmake | 2 + .../Core/RicfCommandObject.h | 3 +- .../Core/RicfCommandResponse.cpp | 86 ++++++++++++++++++ .../Core/RicfCommandResponse.h | 59 ++++++++++++ .../CommandFileInterface/RicfCloseProject.cpp | 3 +- .../CommandFileInterface/RicfCloseProject.h | 2 +- .../RicfComputeCaseGroupStatistics.cpp | 14 ++- .../RicfComputeCaseGroupStatistics.h | 2 +- .../RicfCreateLgrForCompletions.cpp | 89 ++++++++++-------- .../RicfCreateLgrForCompletions.h | 2 +- .../RicfCreateMultipleFractures.cpp | 90 +++++++++++-------- .../RicfCreateMultipleFractures.h | 2 +- .../RicfCreateSaturationPressurePlots.cpp | 39 +++++--- .../RicfCreateSaturationPressurePlots.h | 2 +- .../RicfExportLgrForCompletions.cpp | 71 ++++++++------- .../RicfExportLgrForCompletions.h | 2 +- .../CommandFileInterface/RicfExportMsw.cpp | 14 +-- .../CommandFileInterface/RicfExportMsw.h | 2 +- .../RicfExportMultiCaseSnapshots.cpp | 19 ++-- .../RicfExportMultiCaseSnapshots.h | 2 +- .../RicfExportProperty.cpp | 28 ++++-- .../CommandFileInterface/RicfExportProperty.h | 2 +- .../RicfExportPropertyInViews.cpp | 36 +++++--- .../RicfExportPropertyInViews.h | 2 +- .../RicfExportSimWellFractureCompletions.cpp | 20 +++-- .../RicfExportSimWellFractureCompletions.h | 2 +- .../RicfExportSnapshots.cpp | 9 +- .../RicfExportSnapshots.h | 2 +- .../RicfExportVisibleCells.cpp | 14 +-- .../RicfExportVisibleCells.h | 2 +- .../RicfExportWellPathCompletions.cpp | 15 +++- .../RicfExportWellPathCompletions.h | 2 +- .../RicfExportWellPaths.cpp | 37 ++++---- .../RicfExportWellPaths.h | 2 +- .../CommandFileInterface/RicfLoadCase.cpp | 7 +- .../CommandFileInterface/RicfLoadCase.h | 2 +- .../CommandFileInterface/RicfOpenProject.cpp | 9 +- .../CommandFileInterface/RicfOpenProject.h | 2 +- .../CommandFileInterface/RicfReplaceCase.cpp | 24 +++-- .../CommandFileInterface/RicfReplaceCase.h | 4 +- .../RicfReplaceSourceCases.cpp | 20 +++-- .../RicfReplaceSourceCases.h | 2 +- .../RicfRunOctaveScript.cpp | 9 +- .../RicfRunOctaveScript.h | 2 +- .../RicfScaleFractureTemplate.cpp | 18 ++-- .../RicfScaleFractureTemplate.h | 2 +- .../RicfSetExportFolder.cpp | 7 +- .../RicfSetExportFolder.h | 2 +- .../RicfSetFractureContainment.cpp | 18 ++-- .../RicfSetFractureContainment.h | 2 +- .../RicfSetMainWindowSize.cpp | 3 +- .../RicfSetMainWindowSize.h | 2 +- .../CommandFileInterface/RicfSetStartDir.cpp | 19 +++- .../CommandFileInterface/RicfSetStartDir.h | 2 +- .../CommandFileInterface/RicfSetTimeStep.cpp | 20 ++++- .../CommandFileInterface/RicfSetTimeStep.h | 2 +- .../RicEclipseCellResultToFileImpl.cpp | 19 ++-- .../RicEclipseCellResultToFileImpl.h | 9 +- .../RicSaveEclipseInputPropertyFeature.cpp | 14 ++- ...icSaveEclipseResultAsInputPropertyExec.cpp | 6 +- .../GrpcInterface/RiaGrpcCommandService.cpp | 11 ++- 61 files changed, 639 insertions(+), 276 deletions(-) create mode 100644 ApplicationCode/CommandFileInterface/Core/RicfCommandResponse.cpp create mode 100644 ApplicationCode/CommandFileInterface/Core/RicfCommandResponse.h diff --git a/ApplicationCode/CommandFileInterface/Core/CMakeLists_files.cmake b/ApplicationCode/CommandFileInterface/Core/CMakeLists_files.cmake index 73e259c8d1..cbb3dbe6cb 100644 --- a/ApplicationCode/CommandFileInterface/Core/CMakeLists_files.cmake +++ b/ApplicationCode/CommandFileInterface/Core/CMakeLists_files.cmake @@ -1,6 +1,7 @@ set (SOURCE_GROUP_HEADER_FILES ${CMAKE_CURRENT_LIST_DIR}/RicfCommandObject.h +${CMAKE_CURRENT_LIST_DIR}/RicfCommandResponse.h ${CMAKE_CURRENT_LIST_DIR}/RicfFieldCapability.h ${CMAKE_CURRENT_LIST_DIR}/RicfFieldHandle.h ${CMAKE_CURRENT_LIST_DIR}/RicfObjectCapability.h @@ -10,6 +11,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RicfMessages.h set (SOURCE_GROUP_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/RicfCommandObject.cpp +${CMAKE_CURRENT_LIST_DIR}/RicfCommandResponse.cpp ${CMAKE_CURRENT_LIST_DIR}/RicfFieldCapability.cpp ${CMAKE_CURRENT_LIST_DIR}/RicfFieldHandle.cpp ${CMAKE_CURRENT_LIST_DIR}/RicfObjectCapability.cpp diff --git a/ApplicationCode/CommandFileInterface/Core/RicfCommandObject.h b/ApplicationCode/CommandFileInterface/Core/RicfCommandObject.h index 00ab0a316d..1007e9ac16 100644 --- a/ApplicationCode/CommandFileInterface/Core/RicfCommandObject.h +++ b/ApplicationCode/CommandFileInterface/Core/RicfCommandObject.h @@ -20,6 +20,7 @@ #include "cafPdmObject.h" #include "RicfObjectCapability.h" #include "RicfFieldCapability.h" +#include "RicfCommandResponse.h" #define RICF_InitField(field, keyword, default, uiName, iconResourceName, toolTip, whatsThis) \ CAF_PDM_InitField(field, keyword, default, uiName, iconResourceName, toolTip, whatsThis); \ @@ -37,7 +38,7 @@ public: RicfCommandObject(); ~RicfCommandObject() override; - virtual void execute() = 0; + virtual RicfCommandResponse execute() = 0; }; diff --git a/ApplicationCode/CommandFileInterface/Core/RicfCommandResponse.cpp b/ApplicationCode/CommandFileInterface/Core/RicfCommandResponse.cpp new file mode 100644 index 0000000000..95fabe9e42 --- /dev/null +++ b/ApplicationCode/CommandFileInterface/Core/RicfCommandResponse.cpp @@ -0,0 +1,86 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 "RicfCommandResponse.h" + + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RicfCommandResponse::RicfCommandResponse(Status status, const QString& message) +{ + updateStatus(status, message); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RicfCommandResponse::Status RicfCommandResponse::status() const +{ + return m_status; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RicfCommandResponse::message() const +{ + return m_messages.join("\n"); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +caf::PdmObject* RicfCommandResponse::result() const +{ + return m_result.p(); +} + +//-------------------------------------------------------------------------------------------------- +/// Takes ownership of the result object +//-------------------------------------------------------------------------------------------------- +void RicfCommandResponse::setResult(caf::PdmObject* result) +{ + m_result = result; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicfCommandResponse::updateStatus(Status status, const QString& message) +{ + m_status = std::max(m_status, status); + if (!message.isEmpty()) + m_messages.push_back(QString("%1:%2").arg(statusLabel(status)).arg(message)); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RicfCommandResponse::statusLabel(Status status) +{ + switch (status) + { + case COMMAND_WARNING: + return "WARNING"; + case COMMAND_ERROR: + return "ERROR"; + default: + return ""; + } +} diff --git a/ApplicationCode/CommandFileInterface/Core/RicfCommandResponse.h b/ApplicationCode/CommandFileInterface/Core/RicfCommandResponse.h new file mode 100644 index 0000000000..da11b09b30 --- /dev/null +++ b/ApplicationCode/CommandFileInterface/Core/RicfCommandResponse.h @@ -0,0 +1,59 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 "cafPdmObject.h" +#include "cafPdmPointer.h" + +#include +#include + +#include + +//================================================================================================== +// +// Command response which contains status and possibly a result +// +//================================================================================================== +class RicfCommandResponse +{ +public: + // Status in order of severity from ok to critical + enum Status + { + COMMAND_OK, + COMMAND_WARNING, + COMMAND_ERROR + }; +public: + RicfCommandResponse(Status status = COMMAND_OK, const QString& message=""); + + Status status() const; + QString message() const; + caf::PdmObject* result() const; + void setResult(caf::PdmObject* result); + void updateStatus(Status status, const QString& message); + +private: + static QString statusLabel(Status status); +private: + Status m_status; + QStringList m_messages; + caf::PdmPointer m_result; +}; + diff --git a/ApplicationCode/CommandFileInterface/RicfCloseProject.cpp b/ApplicationCode/CommandFileInterface/RicfCloseProject.cpp index e16e1f9fb0..8b27e8f1d7 100644 --- a/ApplicationCode/CommandFileInterface/RicfCloseProject.cpp +++ b/ApplicationCode/CommandFileInterface/RicfCloseProject.cpp @@ -32,7 +32,8 @@ RicfCloseProject::RicfCloseProject() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicfCloseProject::execute() +RicfCommandResponse RicfCloseProject::execute() { RiaApplication::instance()->closeProject(); + return RicfCommandResponse(); } diff --git a/ApplicationCode/CommandFileInterface/RicfCloseProject.h b/ApplicationCode/CommandFileInterface/RicfCloseProject.h index 1494d13fe1..04c4cba920 100644 --- a/ApplicationCode/CommandFileInterface/RicfCloseProject.h +++ b/ApplicationCode/CommandFileInterface/RicfCloseProject.h @@ -34,7 +34,7 @@ class RicfCloseProject : public RicfCommandObject public: RicfCloseProject(); - void execute() override; + RicfCommandResponse execute() override; private: }; diff --git a/ApplicationCode/CommandFileInterface/RicfComputeCaseGroupStatistics.cpp b/ApplicationCode/CommandFileInterface/RicfComputeCaseGroupStatistics.cpp index 115481cc78..02d7a3eb9b 100644 --- a/ApplicationCode/CommandFileInterface/RicfComputeCaseGroupStatistics.cpp +++ b/ApplicationCode/CommandFileInterface/RicfComputeCaseGroupStatistics.cpp @@ -43,8 +43,10 @@ RicfComputeCaseGroupStatistics::RicfComputeCaseGroupStatistics() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicfComputeCaseGroupStatistics::execute() +RicfCommandResponse RicfComputeCaseGroupStatistics::execute() { + RicfCommandResponse response; + for (int caseId : m_caseIds()) { bool foundCase = false; @@ -61,7 +63,9 @@ void RicfComputeCaseGroupStatistics::execute() } else { - RiaLogging::warning(QString("computeCaseGroupStatistics: Found case with ID %1, but it is not a statistics case, cannot compute statistics.").arg(caseId)); + QString warning = QString("computeCaseGroupStatistics: Found case with ID %1, but it is not a statistics case, cannot compute statistics.").arg(caseId); + RiaLogging::warning(warning); + response.updateStatus(RicfCommandResponse::COMMAND_WARNING, warning); } foundCase = true; break; @@ -73,7 +77,11 @@ void RicfComputeCaseGroupStatistics::execute() if (!foundCase) { - RiaLogging::warning(QString("computeCaseGroupStatistics: Could not find statistics case with ID %1.").arg(caseId)); + QString warning = QString("computeCaseGroupStatistics: Could not find statistics case with ID %1.").arg(caseId); + + RiaLogging::warning(warning); + response.updateStatus(RicfCommandResponse::COMMAND_WARNING, warning); } } + return response; } diff --git a/ApplicationCode/CommandFileInterface/RicfComputeCaseGroupStatistics.h b/ApplicationCode/CommandFileInterface/RicfComputeCaseGroupStatistics.h index 70c9508dab..a546676229 100644 --- a/ApplicationCode/CommandFileInterface/RicfComputeCaseGroupStatistics.h +++ b/ApplicationCode/CommandFileInterface/RicfComputeCaseGroupStatistics.h @@ -34,7 +34,7 @@ class RicfComputeCaseGroupStatistics : public RicfCommandObject public: RicfComputeCaseGroupStatistics(); - void execute() override; + RicfCommandResponse execute() override; private: caf::PdmField< std::vector > m_caseIds; diff --git a/ApplicationCode/CommandFileInterface/RicfCreateLgrForCompletions.cpp b/ApplicationCode/CommandFileInterface/RicfCreateLgrForCompletions.cpp index 101dd1ff78..4c47b87a4e 100644 --- a/ApplicationCode/CommandFileInterface/RicfCreateLgrForCompletions.cpp +++ b/ApplicationCode/CommandFileInterface/RicfCreateLgrForCompletions.cpp @@ -59,7 +59,7 @@ RicfCreateLgrForCompletions::RicfCreateLgrForCompletions() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicfCreateLgrForCompletions::execute() +RicfCommandResponse RicfCreateLgrForCompletions::execute() { using TOOLS = RicfApplicationTools; @@ -71,54 +71,65 @@ void RicfCreateLgrForCompletions::execute() wellPaths = TOOLS::wellPathsFromNames(TOOLS::toQStringList(m_wellPathNames), &wellsNotFound); if (!wellsNotFound.empty()) { - RiaLogging::error(QString("createLgrForCompletions: These well paths were not found: ") + wellsNotFound.join(", ")); + QString error = QString("createLgrForCompletions: These well paths were not found: ") + wellsNotFound.join(", "); + RiaLogging::error(error); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, error); } } - if (!wellPaths.empty()) + if (wellPaths.empty()) { - caf::CmdFeatureManager* commandManager = caf::CmdFeatureManager::instance(); - auto feature = dynamic_cast(commandManager->getCommandFeature("RicCreateTemporaryLgrFeature")); + QString error("No well paths found"); + RiaLogging::error(error); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, error); + } - RimEclipseCase* eclipseCase = nullptr; + caf::CmdFeatureManager* commandManager = caf::CmdFeatureManager::instance(); + auto feature = dynamic_cast(commandManager->getCommandFeature("RicCreateTemporaryLgrFeature")); + + RimEclipseCase* eclipseCase = nullptr; + { + for (RimEclipseCase* c : RiaApplication::instance()->project()->activeOilField()->analysisModels->cases()) { - for (RimEclipseCase* c : RiaApplication::instance()->project()->activeOilField()->analysisModels->cases()) + if (c->caseId() == m_caseId()) { - if (c->caseId() == m_caseId()) - { - eclipseCase = c; - break; - } - } - if (!eclipseCase) - { - RiaLogging::error(QString("createLgrForCompletions: Could not find case with ID %1").arg(m_caseId())); - return; + eclipseCase = c; + break; } } - - RicDeleteTemporaryLgrsFeature::deleteAllTemporaryLgrs(eclipseCase); - - caf::VecIjk lgrCellCounts(m_refinementI, m_refinementJ, m_refinementK); - QStringList wellsIntersectingOtherLgrs; - - feature->createLgrsForWellPaths( - wellPaths, - eclipseCase, - m_timeStep, - lgrCellCounts, - m_splitType(), - {RigCompletionData::PERFORATION, RigCompletionData::FRACTURE, RigCompletionData::FISHBONES}, - &wellsIntersectingOtherLgrs); - - feature->updateViews(eclipseCase); - - if (!wellsIntersectingOtherLgrs.empty()) + if (!eclipseCase) { - auto wellsList = wellsIntersectingOtherLgrs.join(", "); - RiaLogging::error( - "createLgrForCompletions: No LGRs created for some wells due to existing intersecting LGR(s).Affected wells : " + - wellsList); + QString error(QString("createLgrForCompletions: Could not find case with ID %1").arg(m_caseId())); + RiaLogging::error(error); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, error); } } + + RicDeleteTemporaryLgrsFeature::deleteAllTemporaryLgrs(eclipseCase); + + caf::VecIjk lgrCellCounts(m_refinementI, m_refinementJ, m_refinementK); + QStringList wellsIntersectingOtherLgrs; + + feature->createLgrsForWellPaths( + wellPaths, + eclipseCase, + m_timeStep, + lgrCellCounts, + m_splitType(), + {RigCompletionData::PERFORATION, RigCompletionData::FRACTURE, RigCompletionData::FISHBONES}, + &wellsIntersectingOtherLgrs); + + feature->updateViews(eclipseCase); + + RicfCommandResponse response; + if (!wellsIntersectingOtherLgrs.empty()) + { + auto wellsList = wellsIntersectingOtherLgrs.join(", "); + QString warning( + "createLgrForCompletions: No LGRs created for some wells due to existing intersecting LGR(s).Affected wells : " + + wellsList); + RiaLogging::warning(warning); + response.updateStatus(RicfCommandResponse::COMMAND_WARNING, warning); + } + return response; } diff --git a/ApplicationCode/CommandFileInterface/RicfCreateLgrForCompletions.h b/ApplicationCode/CommandFileInterface/RicfCreateLgrForCompletions.h index f2cb8938af..c6a12b68d4 100644 --- a/ApplicationCode/CommandFileInterface/RicfCreateLgrForCompletions.h +++ b/ApplicationCode/CommandFileInterface/RicfCreateLgrForCompletions.h @@ -39,7 +39,7 @@ class RicfCreateLgrForCompletions : public RicfCommandObject public: RicfCreateLgrForCompletions(); - void execute() override; + RicfCommandResponse execute() override; private: caf::PdmField m_caseId; diff --git a/ApplicationCode/CommandFileInterface/RicfCreateMultipleFractures.cpp b/ApplicationCode/CommandFileInterface/RicfCreateMultipleFractures.cpp index 8e4a75bab5..d1e45a495a 100644 --- a/ApplicationCode/CommandFileInterface/RicfCreateMultipleFractures.cpp +++ b/ApplicationCode/CommandFileInterface/RicfCreateMultipleFractures.cpp @@ -74,7 +74,7 @@ RicfCreateMultipleFractures::RicfCreateMultipleFractures() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicfCreateMultipleFractures::execute() +RicfCommandResponse RicfCreateMultipleFractures::execute() { using TOOLS = RicfApplicationTools; @@ -92,54 +92,71 @@ void RicfCreateMultipleFractures::execute() wellPaths = TOOLS::wellPathsFromNames(TOOLS::toQStringList(m_wellPathNames), &wellsNotFound); if (!wellsNotFound.empty()) { - RiaLogging::error(QString("createMultipleFractures: These well paths were not found: ") + wellsNotFound.join(", ")); + QString error = QString("createMultipleFractures: These well paths were not found: %1").arg(wellsNotFound.join(", ")); + RiaLogging::error(error); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, error); } } if (!gridCase) { - RiaLogging::error(QString("createMultipleFractures: Could not find case with ID %1").arg(m_caseId)); + QString error = QString("createMultipleFractures: Could not find case with ID %1").arg(m_caseId); + RiaLogging::error(error); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, error); } if (!fractureTemplate) { - RiaLogging::error(QString("createMultipleFractures: Could not find fracture template with ID %1").arg(m_templateId)); + QString error = QString("createMultipleFractures: Could not find fracture template with ID %1").arg(m_templateId); + RiaLogging::error(error); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, error); } - if (gridCase && fractureTemplate && !wellPaths.empty() && validateArguments()) + if (wellPaths.empty()) { - RicCreateMultipleFracturesOptionItemUi* options = new RicCreateMultipleFracturesOptionItemUi(); - caf::CmdFeatureManager* commandManager = caf::CmdFeatureManager::instance(); - auto feature = dynamic_cast(commandManager->getCommandFeature("RicCreateMultipleFracturesFeature")); - - // Default layers - int topLayer = m_topLayer; - int baseLayer = m_baseLayer; - if (feature && (topLayer < 0 || baseLayer < 0)) - { - auto ijkRange = feature->ijkRangeForGrid(gridCase); - if (topLayer < 0) topLayer = static_cast(ijkRange.first.z()); - if (baseLayer < 0) baseLayer = static_cast(ijkRange.second.z()); - } - options->setValues(topLayer, baseLayer, fractureTemplate, m_spacing); - - settings->clearWellPaths(); - for (auto wellPath : wellPaths) - { - settings->addWellPath(wellPath); - } - - settings->setValues(gridCase, m_minDistFromWellTd, m_maxFracturesPerWell); - settings->clearOptions(); - settings->insertOptionItem(nullptr, options); - - - if (feature) - { - if (m_action == MultipleFractures::APPEND_FRACTURES) feature->appendFractures(); - if (m_action == MultipleFractures::REPLACE_FRACTURES) feature->replaceFractures(); - } + QString error("createMultipleFractures: No wellpaths found"); + RiaLogging::error(error); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, error); } + + if (!validateArguments()) + { + QString error("createMultipleFractures: Mandatory argument(s) missing"); + RiaLogging::error(error); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, error); + } + + RicCreateMultipleFracturesOptionItemUi* options = new RicCreateMultipleFracturesOptionItemUi(); + caf::CmdFeatureManager* commandManager = caf::CmdFeatureManager::instance(); + auto feature = dynamic_cast(commandManager->getCommandFeature("RicCreateMultipleFracturesFeature")); + + // Default layers + int topLayer = m_topLayer; + int baseLayer = m_baseLayer; + if (feature && (topLayer < 0 || baseLayer < 0)) + { + auto ijkRange = feature->ijkRangeForGrid(gridCase); + if (topLayer < 0) topLayer = static_cast(ijkRange.first.z()); + if (baseLayer < 0) baseLayer = static_cast(ijkRange.second.z()); + } + options->setValues(topLayer, baseLayer, fractureTemplate, m_spacing); + + settings->clearWellPaths(); + for (auto wellPath : wellPaths) + { + settings->addWellPath(wellPath); + } + + settings->setValues(gridCase, m_minDistFromWellTd, m_maxFracturesPerWell); + settings->clearOptions(); + settings->insertOptionItem(nullptr, options); + + if (feature) + { + if (m_action == MultipleFractures::APPEND_FRACTURES) feature->appendFractures(); + if (m_action == MultipleFractures::REPLACE_FRACTURES) feature->replaceFractures(); + } + return RicfCommandResponse(); } @@ -154,7 +171,6 @@ bool RicfCreateMultipleFractures::validateArguments() const if (valid) return true; - RiaLogging::error(QString("createMultipleFractures: Mandatory argument(s) missing")); return false; } diff --git a/ApplicationCode/CommandFileInterface/RicfCreateMultipleFractures.h b/ApplicationCode/CommandFileInterface/RicfCreateMultipleFractures.h index cc1cbf3b5d..802c614f69 100644 --- a/ApplicationCode/CommandFileInterface/RicfCreateMultipleFractures.h +++ b/ApplicationCode/CommandFileInterface/RicfCreateMultipleFractures.h @@ -49,7 +49,7 @@ class RicfCreateMultipleFractures : public RicfCommandObject public: RicfCreateMultipleFractures(); - void execute() override; + RicfCommandResponse execute() override; private: bool validateArguments() const; diff --git a/ApplicationCode/CommandFileInterface/RicfCreateSaturationPressurePlots.cpp b/ApplicationCode/CommandFileInterface/RicfCreateSaturationPressurePlots.cpp index 622c4272a6..375e9ce9b9 100644 --- a/ApplicationCode/CommandFileInterface/RicfCreateSaturationPressurePlots.cpp +++ b/ApplicationCode/CommandFileInterface/RicfCreateSaturationPressurePlots.cpp @@ -42,7 +42,7 @@ RicfCreateSaturationPressurePlots::RicfCreateSaturationPressurePlots() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicfCreateSaturationPressurePlots::execute() +RicfCommandResponse RicfCreateSaturationPressurePlots::execute() { std::vector caseIds = m_caseIds(); if (caseIds.empty()) @@ -58,21 +58,32 @@ void RicfCreateSaturationPressurePlots::execute() } } - RimProject* project = RiaApplication::instance()->project(); - if (project) + if (caseIds.empty()) { - auto eclipeCases = project->eclipseCases(); - for (auto c : eclipeCases) - { - auto eclipseResultCase = dynamic_cast(c); - if (!eclipseResultCase) continue; + QString error("createSaturationPressurePlots: No cases found"); + RiaLogging::error(error); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, error); + } - for (auto caseId : caseIds) + RimProject* project = RiaApplication::instance()->project(); + if (!project) + { + QString error("No project loaded"); + RiaLogging::error(error); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, error); + } + + auto eclipeCases = project->eclipseCases(); + for (auto c : eclipeCases) + { + auto eclipseResultCase = dynamic_cast(c); + if (!eclipseResultCase) continue; + + for (auto caseId : caseIds) + { + if (c->caseId == caseId) { - if (c->caseId == caseId) - { - RicCreateSaturationPressurePlotsFeature::createPlots(eclipseResultCase); - } + RicCreateSaturationPressurePlotsFeature::createPlots(eclipseResultCase); } } } @@ -80,4 +91,6 @@ void RicfCreateSaturationPressurePlots::execute() RimSaturationPressurePlotCollection* collection = project->mainPlotCollection()->saturationPressurePlotCollection(); collection->updateAllRequiredEditors(); RiaGuiApplication::instance()->getOrCreateAndShowMainPlotWindow(); + + return RicfCommandResponse(); } diff --git a/ApplicationCode/CommandFileInterface/RicfCreateSaturationPressurePlots.h b/ApplicationCode/CommandFileInterface/RicfCreateSaturationPressurePlots.h index 8194c52303..52ad9d5bf3 100644 --- a/ApplicationCode/CommandFileInterface/RicfCreateSaturationPressurePlots.h +++ b/ApplicationCode/CommandFileInterface/RicfCreateSaturationPressurePlots.h @@ -34,7 +34,7 @@ class RicfCreateSaturationPressurePlots : public RicfCommandObject public: RicfCreateSaturationPressurePlots(); - void execute() override; + RicfCommandResponse execute() override; private: caf::PdmField< std::vector > m_caseIds; diff --git a/ApplicationCode/CommandFileInterface/RicfExportLgrForCompletions.cpp b/ApplicationCode/CommandFileInterface/RicfExportLgrForCompletions.cpp index f89522f5c8..adbf69495b 100644 --- a/ApplicationCode/CommandFileInterface/RicfExportLgrForCompletions.cpp +++ b/ApplicationCode/CommandFileInterface/RicfExportLgrForCompletions.cpp @@ -59,7 +59,7 @@ RicfExportLgrForCompletions::RicfExportLgrForCompletions() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicfExportLgrForCompletions::execute() +RicfCommandResponse RicfExportLgrForCompletions::execute() { using TOOLS = RicfApplicationTools; @@ -71,38 +71,49 @@ void RicfExportLgrForCompletions::execute() wellPaths = TOOLS::wellPathsFromNames(TOOLS::toQStringList(m_wellPathNames), &wellsNotFound); if (!wellsNotFound.empty()) { - RiaLogging::error(QString("exportLgrForCompletions: These well paths were not found: ") + wellsNotFound.join(", ")); + QString error(QString("exportLgrForCompletions: These well paths were not found: ") + wellsNotFound.join(", ")); + RiaLogging::error(error); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, error); } } - if (!wellPaths.empty()) + if (wellPaths.empty()) { - QString exportFolder = RicfCommandFileExecutor::instance()->getExportPath(RicfCommandFileExecutor::LGRS); - if (exportFolder.isNull()) - { - exportFolder = RiaApplication::instance()->createAbsolutePathFromProjectRelativePath("LGR"); - } - - caf::CmdFeatureManager* commandManager = caf::CmdFeatureManager::instance(); - auto feature = dynamic_cast(commandManager->getCommandFeature("RicExportLgrFeature")); - - RimEclipseCase* eclipseCase = TOOLS::caseFromId(m_caseId()); - if (!eclipseCase) - { - RiaLogging::error(QString("exportLgrForCompletions: Could not find case with ID %1").arg(m_caseId())); - return; - } - - caf::VecIjk lgrCellCounts(m_refinementI, m_refinementJ, m_refinementK); - QStringList wellsIntersectingOtherLgrs; - - feature->exportLgrsForWellPaths(exportFolder, wellPaths, eclipseCase, m_timeStep, lgrCellCounts, m_splitType(), - {RigCompletionData::PERFORATION, RigCompletionData::FRACTURE, RigCompletionData::FISHBONES}, &wellsIntersectingOtherLgrs); - - if (!wellsIntersectingOtherLgrs.empty()) - { - auto wellsList = wellsIntersectingOtherLgrs.join(", "); - RiaLogging::error("exportLgrForCompletions: No export for some wells due to existing intersecting LGR(s).Affected wells : " + wellsList); - } + QString error("exportLgrForCompletions: Could not find any well paths"); + RiaLogging::error(error); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, error); } + + QString exportFolder = RicfCommandFileExecutor::instance()->getExportPath(RicfCommandFileExecutor::LGRS); + if (exportFolder.isNull()) + { + exportFolder = RiaApplication::instance()->createAbsolutePathFromProjectRelativePath("LGR"); + } + + caf::CmdFeatureManager* commandManager = caf::CmdFeatureManager::instance(); + auto feature = dynamic_cast(commandManager->getCommandFeature("RicExportLgrFeature")); + + RimEclipseCase* eclipseCase = TOOLS::caseFromId(m_caseId()); + if (!eclipseCase) + { + QString error(QString("exportLgrForCompletions: Could not find case with ID %1").arg(m_caseId())); + RiaLogging::error(error); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, error); + } + + caf::VecIjk lgrCellCounts(m_refinementI, m_refinementJ, m_refinementK); + QStringList wellsIntersectingOtherLgrs; + + feature->exportLgrsForWellPaths(exportFolder, wellPaths, eclipseCase, m_timeStep, lgrCellCounts, m_splitType(), + {RigCompletionData::PERFORATION, RigCompletionData::FRACTURE, RigCompletionData::FISHBONES}, &wellsIntersectingOtherLgrs); + + RicfCommandResponse response; + if (!wellsIntersectingOtherLgrs.empty()) + { + auto wellsList = wellsIntersectingOtherLgrs.join(", "); + QString warning("exportLgrForCompletions: No export for some wells due to existing intersecting LGR(s).Affected wells : " + wellsList); + RiaLogging::warning(warning); + response.updateStatus(RicfCommandResponse::COMMAND_WARNING, warning); + } + return response; } diff --git a/ApplicationCode/CommandFileInterface/RicfExportLgrForCompletions.h b/ApplicationCode/CommandFileInterface/RicfExportLgrForCompletions.h index b747cc16f8..a3e1d515f3 100644 --- a/ApplicationCode/CommandFileInterface/RicfExportLgrForCompletions.h +++ b/ApplicationCode/CommandFileInterface/RicfExportLgrForCompletions.h @@ -42,7 +42,7 @@ class RicfExportLgrForCompletions : public RicfCommandObject public: RicfExportLgrForCompletions(); - void execute() override; + RicfCommandResponse execute() override; private: caf::PdmField m_caseId; diff --git a/ApplicationCode/CommandFileInterface/RicfExportMsw.cpp b/ApplicationCode/CommandFileInterface/RicfExportMsw.cpp index d7e8f47720..8608ab7be1 100644 --- a/ApplicationCode/CommandFileInterface/RicfExportMsw.cpp +++ b/ApplicationCode/CommandFileInterface/RicfExportMsw.cpp @@ -55,7 +55,7 @@ RicfExportMsw::RicfExportMsw() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicfExportMsw::execute() +RicfCommandResponse RicfExportMsw::execute() { using TOOLS = RicfApplicationTools; @@ -64,8 +64,9 @@ void RicfExportMsw::execute() auto eclipseCase = TOOLS::caseFromId(m_caseId()); if (!eclipseCase) { - RiaLogging::error(QString("exportMsw: Could not find case with ID %1.").arg(m_caseId())); - return; + QString error = QString("exportMsw: Could not find case with ID %1.").arg(m_caseId()); + RiaLogging::error(error); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, error); } QString exportFolder = RicfCommandFileExecutor::instance()->getExportPath(RicfCommandFileExecutor::COMPLETIONS); @@ -83,9 +84,12 @@ void RicfExportMsw::execute() RimWellPath* wellPath = RiaApplication::instance()->project()->wellPathByName(m_wellPathName); if (!wellPath) { - RiaLogging::error(QString("exportMsw: Could not find well path with name %1").arg(m_wellPathName())); - return; + QString error = QString("exportMsw: Could not find well path with name %1").arg(m_wellPathName()); + RiaLogging::error(error); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, error); } RicWellPathExportMswCompletionsImpl::exportWellSegmentsForAllCompletions(exportSettings, { wellPath }); + + return RicfCommandResponse(); } diff --git a/ApplicationCode/CommandFileInterface/RicfExportMsw.h b/ApplicationCode/CommandFileInterface/RicfExportMsw.h index 6a95cd2464..71871fd89d 100644 --- a/ApplicationCode/CommandFileInterface/RicfExportMsw.h +++ b/ApplicationCode/CommandFileInterface/RicfExportMsw.h @@ -36,7 +36,7 @@ class RicfExportMsw : public RicfCommandObject public: RicfExportMsw(); - void execute() override; + RicfCommandResponse execute() override; private: caf::PdmField m_caseId; diff --git a/ApplicationCode/CommandFileInterface/RicfExportMultiCaseSnapshots.cpp b/ApplicationCode/CommandFileInterface/RicfExportMultiCaseSnapshots.cpp index c56bc5da49..98d48c4c06 100644 --- a/ApplicationCode/CommandFileInterface/RicfExportMultiCaseSnapshots.cpp +++ b/ApplicationCode/CommandFileInterface/RicfExportMultiCaseSnapshots.cpp @@ -37,27 +37,32 @@ RicfExportMultiCaseSnapshots::RicfExportMultiCaseSnapshots() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicfExportMultiCaseSnapshots::execute() +RicfCommandResponse RicfExportMultiCaseSnapshots::execute() { RiaGuiApplication* app = RiaGuiApplication::instance(); if (!app) { - RiaLogging::error("exportMultiCaseSnapshots: Requires GUI Application"); - return; + QString error("exportMultiCaseSnapshots: Requires GUI Application"); + RiaLogging::error(error); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, error); } if (m_gridListFile().isNull()) { - RiaLogging::error("exportMultiCaseSnapshots: Required parameter gridListFile."); - return; + QString error("exportMultiCaseSnapshots: Required parameter gridListFile."); + RiaLogging::error(error); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, error); } QString lastProjectPath = RicfCommandFileExecutor::instance()->getLastProjectPath(); if (lastProjectPath.isNull()) { - RiaLogging::error("exportMultiCaseSnapshots: 'openProject' must be called before 'exportMultiCaseSnapshots' to specify project file to replace cases in."); - return; + QString error("exportMultiCaseSnapshots: 'openProject' must be called before 'exportMultiCaseSnapshots' to specify project file to replace cases in."); + RiaLogging::error(error); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, error); } std::vector listFileNames = RiaApplication::readFileListFromTextFile(m_gridListFile()); app->runMultiCaseSnapshots(lastProjectPath, listFileNames, RicfCommandFileExecutor::instance()->getExportPath(RicfCommandFileExecutor::SNAPSHOTS)); + + return RicfCommandResponse(); } diff --git a/ApplicationCode/CommandFileInterface/RicfExportMultiCaseSnapshots.h b/ApplicationCode/CommandFileInterface/RicfExportMultiCaseSnapshots.h index ce639542b7..18925ef697 100644 --- a/ApplicationCode/CommandFileInterface/RicfExportMultiCaseSnapshots.h +++ b/ApplicationCode/CommandFileInterface/RicfExportMultiCaseSnapshots.h @@ -34,7 +34,7 @@ class RicfExportMultiCaseSnapshots : public RicfCommandObject public: RicfExportMultiCaseSnapshots(); - void execute() override; + RicfCommandResponse execute() override; private: caf::PdmField m_gridListFile; diff --git a/ApplicationCode/CommandFileInterface/RicfExportProperty.cpp b/ApplicationCode/CommandFileInterface/RicfExportProperty.cpp index 63a0f54f1e..d7c5c9678d 100644 --- a/ApplicationCode/CommandFileInterface/RicfExportProperty.cpp +++ b/ApplicationCode/CommandFileInterface/RicfExportProperty.cpp @@ -59,7 +59,7 @@ RicfExportProperty::RicfExportProperty() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicfExportProperty::execute() +RicfCommandResponse RicfExportProperty::execute() { using TOOLS = RicfApplicationTools; @@ -67,16 +67,18 @@ void RicfExportProperty::execute() { if (!eclipseCase) { - RiaLogging::error(QString("exportProperty: Could not find case with ID %1").arg(m_caseId())); - return; + QString error = QString("exportProperty: Could not find case with ID %1").arg(m_caseId()); + RiaLogging::error(error); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, error); } if (!eclipseCase->eclipseCaseData()) { if (!eclipseCase->openReserviorCase()) { - RiaLogging::error(QString("exportProperty: Could not find eclipseCaseData with ID %1").arg(m_caseId())); - return; + QString error = QString("exportProperty: Could not find eclipseCaseData with ID %1").arg(m_caseId()); + RiaLogging::error(error); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, error); } } } @@ -87,8 +89,9 @@ void RicfExportProperty::execute() if (!cellResultsData->ensureKnownResultLoaded(RigEclipseResultAddress(m_propertyName))) { - RiaLogging::error(QString("exportProperty: Could not find result property : %1").arg(m_propertyName())); - return; + QString error = QString("exportProperty: Could not find result property : %1").arg(m_propertyName()); + RiaLogging::error(error); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, error); } QString filePath = m_exportFileName; @@ -106,6 +109,13 @@ void RicfExportProperty::execute() eclipseKeyword = m_propertyName; } - RicEclipseCellResultToFileImpl::writePropertyToTextFile( - filePath, eclipseCase->eclipseCaseData(), m_timeStepIndex, m_propertyName, eclipseKeyword, m_undefinedValue); + QString errMsg; + if (!RicEclipseCellResultToFileImpl::writePropertyToTextFile( + filePath, eclipseCase->eclipseCaseData(), m_timeStepIndex, m_propertyName, eclipseKeyword, m_undefinedValue, + &errMsg)) + { + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, errMsg); + } + + return RicfCommandResponse(); } diff --git a/ApplicationCode/CommandFileInterface/RicfExportProperty.h b/ApplicationCode/CommandFileInterface/RicfExportProperty.h index 950deec96c..72e0f918e1 100644 --- a/ApplicationCode/CommandFileInterface/RicfExportProperty.h +++ b/ApplicationCode/CommandFileInterface/RicfExportProperty.h @@ -38,7 +38,7 @@ class RicfExportProperty : public RicfCommandObject public: RicfExportProperty(); - void execute() override; + RicfCommandResponse execute() override; private: caf::PdmField m_caseId; diff --git a/ApplicationCode/CommandFileInterface/RicfExportPropertyInViews.cpp b/ApplicationCode/CommandFileInterface/RicfExportPropertyInViews.cpp index ca82410244..7c95e141ef 100644 --- a/ApplicationCode/CommandFileInterface/RicfExportPropertyInViews.cpp +++ b/ApplicationCode/CommandFileInterface/RicfExportPropertyInViews.cpp @@ -55,15 +55,16 @@ RicfExportPropertyInViews::RicfExportPropertyInViews() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicfExportPropertyInViews::execute() +RicfCommandResponse RicfExportPropertyInViews::execute() { using TOOLS = RicfApplicationTools; RimEclipseCase* eclipseCase = TOOLS::caseFromId(m_caseId()); if (!eclipseCase) { - RiaLogging::error(QString("exportProperty: Could not find case with ID %1").arg(m_caseId())); - return; + QString error(QString("exportProperty: Could not find case with ID %1").arg(m_caseId())); + RiaLogging::error(error); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, error); } std::vector viewsForExport; @@ -95,6 +96,8 @@ void RicfExportPropertyInViews::execute() } } + RicfCommandResponse response; + for (const auto& view : viewsForExport) { cvf::ref resultAccessor = nullptr; @@ -109,11 +112,12 @@ void RicfExportPropertyInViews::execute() if (resultAccessor.isNull()) { - RiaLogging::error(QString("exportProperty: Could not find property. Case ID %1, time step %2, property '%3'") + QString warning = QString("exportProperty: Could not find property. Case ID %1, time step %2, property '%3'") .arg(m_caseId) .arg(view->currentTimeStep()) - .arg(propertyName)); - + .arg(propertyName); + RiaLogging::warning(warning); + response.updateStatus(RicfCommandResponse::COMMAND_WARNING, warning); continue; } @@ -128,11 +132,19 @@ void RicfExportPropertyInViews::execute() fileName = caf::Utils::makeValidFileBasename(fileName); const QString filePath = propertiesDir.filePath(fileName); - RicEclipseCellResultToFileImpl::writeResultToTextFile(filePath, - eclipseCase->eclipseCaseData(), - resultAccessor.p(), - propertyName, - m_undefinedValue, - "exportPropertiesInViews"); + QString errorMsg; + + bool worked = RicEclipseCellResultToFileImpl::writeResultToTextFile(filePath, + eclipseCase->eclipseCaseData(), + resultAccessor.p(), + propertyName, + m_undefinedValue, + "exportPropertiesInViews", + &errorMsg); + if (!worked) + { + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, errorMsg); + } } + return response; } diff --git a/ApplicationCode/CommandFileInterface/RicfExportPropertyInViews.h b/ApplicationCode/CommandFileInterface/RicfExportPropertyInViews.h index 0d02b4f866..896d489582 100644 --- a/ApplicationCode/CommandFileInterface/RicfExportPropertyInViews.h +++ b/ApplicationCode/CommandFileInterface/RicfExportPropertyInViews.h @@ -40,7 +40,7 @@ class RicfExportPropertyInViews : public RicfCommandObject public: RicfExportPropertyInViews(); - void execute() override; + RicfCommandResponse execute() override; private: caf::PdmField m_caseId; diff --git a/ApplicationCode/CommandFileInterface/RicfExportSimWellFractureCompletions.cpp b/ApplicationCode/CommandFileInterface/RicfExportSimWellFractureCompletions.cpp index f8e4cacd9d..0b233c5594 100644 --- a/ApplicationCode/CommandFileInterface/RicfExportSimWellFractureCompletions.cpp +++ b/ApplicationCode/CommandFileInterface/RicfExportSimWellFractureCompletions.cpp @@ -56,7 +56,7 @@ RicfExportSimWellFractureCompletions::RicfExportSimWellFractureCompletions() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicfExportSimWellFractureCompletions::execute() +RicfCommandResponse RicfExportSimWellFractureCompletions::execute() { using TOOLS = RicfApplicationTools; @@ -71,8 +71,9 @@ void RicfExportSimWellFractureCompletions::execute() auto eclipseCase = TOOLS::caseFromId(m_caseId()); if (!eclipseCase) { - RiaLogging::error(QString("exportSimWellCompletions: Could not find case with ID %1").arg(m_caseId())); - return; + QString error = QString("exportSimWellCompletions: Could not find case with ID %1").arg(m_caseId()); + RiaLogging::error(error); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, error); } exportSettings->caseToApply = eclipseCase; } @@ -95,10 +96,13 @@ void RicfExportSimWellFractureCompletions::execute() } if (views.empty()) { - RiaLogging::error(QString("exportSimWellCompletions: Could not find any views named \"%1\" in the case with ID %2").arg(m_viewName).arg(m_caseId())); - return; + QString error = QString("exportSimWellCompletions: Could not find any views named \"%1\" in the case with ID %2").arg(m_viewName).arg(m_caseId()); + RiaLogging::error(error); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, error); } + RicfCommandResponse response; + std::vector simWells; if (m_simWellNames().empty()) { @@ -126,7 +130,9 @@ void RicfExportSimWellFractureCompletions::execute() } else { - RiaLogging::warning(QString("exportSimWellCompletions: Could not find well with name %1 in view \"%2\" on case with ID %2").arg(wellPathName).arg(m_viewName).arg(m_caseId())); + QString warning = QString("exportSimWellCompletions: Could not find well with name %1 in view \"%2\" on case with ID %2").arg(wellPathName).arg(m_viewName).arg(m_caseId()); + RiaLogging::warning(warning); + response.updateStatus(RicfCommandResponse::COMMAND_WARNING, warning); } } } @@ -135,4 +141,6 @@ void RicfExportSimWellFractureCompletions::execute() std::vector wellPaths; RicWellPathExportCompletionDataFeatureImpl::exportCompletions(wellPaths, simWells, *exportSettings); + + return response; } diff --git a/ApplicationCode/CommandFileInterface/RicfExportSimWellFractureCompletions.h b/ApplicationCode/CommandFileInterface/RicfExportSimWellFractureCompletions.h index b98e4d3e71..2b49b7d9f6 100644 --- a/ApplicationCode/CommandFileInterface/RicfExportSimWellFractureCompletions.h +++ b/ApplicationCode/CommandFileInterface/RicfExportSimWellFractureCompletions.h @@ -37,7 +37,7 @@ class RicfExportSimWellFractureCompletions : public RicfCommandObject public: RicfExportSimWellFractureCompletions(); - void execute() override; + RicfCommandResponse execute() override; private: caf::PdmField m_caseId; diff --git a/ApplicationCode/CommandFileInterface/RicfExportSnapshots.cpp b/ApplicationCode/CommandFileInterface/RicfExportSnapshots.cpp index 430515db96..97bd0b507d 100644 --- a/ApplicationCode/CommandFileInterface/RicfExportSnapshots.cpp +++ b/ApplicationCode/CommandFileInterface/RicfExportSnapshots.cpp @@ -56,12 +56,13 @@ RicfExportSnapshots::RicfExportSnapshots() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicfExportSnapshots::execute() +RicfCommandResponse RicfExportSnapshots::execute() { if (!RiaGuiApplication::isRunning()) { - RiaLogging::error(QString("RicfExportSnapshot: Command cannot run without a GUI")); - return; + QString error("RicfExportSnapshot: Command cannot run without a GUI"); + RiaLogging::error(error); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, error); } RiuMainWindow* mainWnd = RiuMainWindow::instance(); @@ -85,4 +86,6 @@ void RicfExportSnapshots::execute() mainWnd->loadWinGeoAndDockToolBarLayout(); RiaGuiApplication::instance()->processEvents(); + + return RicfCommandResponse(); } diff --git a/ApplicationCode/CommandFileInterface/RicfExportSnapshots.h b/ApplicationCode/CommandFileInterface/RicfExportSnapshots.h index fcfac350f7..0c302e3a82 100644 --- a/ApplicationCode/CommandFileInterface/RicfExportSnapshots.h +++ b/ApplicationCode/CommandFileInterface/RicfExportSnapshots.h @@ -44,7 +44,7 @@ public: public: RicfExportSnapshots(); - void execute() override; + RicfCommandResponse execute() override; private: caf::PdmField m_type; diff --git a/ApplicationCode/CommandFileInterface/RicfExportVisibleCells.cpp b/ApplicationCode/CommandFileInterface/RicfExportVisibleCells.cpp index ecd1d4c6de..e383e773b6 100644 --- a/ApplicationCode/CommandFileInterface/RicfExportVisibleCells.cpp +++ b/ApplicationCode/CommandFileInterface/RicfExportVisibleCells.cpp @@ -75,19 +75,21 @@ RicfExportVisibleCells::RicfExportVisibleCells() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicfExportVisibleCells::execute() +RicfCommandResponse RicfExportVisibleCells::execute() { if (m_caseId < 0 || m_viewName().isEmpty()) { - RiaLogging::error("exportVisibleCells: CaseId or view name not specified"); - return; + QString error("exportVisibleCells: CaseId or view name not specified"); + RiaLogging::error(error); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, error); } auto eclipseView = RicfApplicationTools::viewFromCaseIdAndViewName(m_caseId, m_viewName); if (!eclipseView) { - RiaLogging::error(QString("exportVisibleCells: Could not find view '%1' in case ID %2").arg(m_viewName).arg(m_caseId)); - return; + QString error(QString("exportVisibleCells: Could not find view '%1' in case ID %2").arg(m_viewName).arg(m_caseId)); + RiaLogging::error(error); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, error); } QString exportFolder = RicfCommandFileExecutor::instance()->getExportPath(RicfCommandFileExecutor::CELLS); @@ -101,6 +103,8 @@ void RicfExportVisibleCells::execute() RicSaveEclipseInputVisibleCellsUi exportSettings; buildExportSettings(exportFolder, &exportSettings); RicSaveEclipseInputVisibleCellsFeature::executeCommand(eclipseView, exportSettings, "exportVisibleCells"); + + return RicfCommandResponse(); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/CommandFileInterface/RicfExportVisibleCells.h b/ApplicationCode/CommandFileInterface/RicfExportVisibleCells.h index e5bb4986e9..1945090d47 100644 --- a/ApplicationCode/CommandFileInterface/RicfExportVisibleCells.h +++ b/ApplicationCode/CommandFileInterface/RicfExportVisibleCells.h @@ -45,7 +45,7 @@ class RicfExportVisibleCells : public RicfCommandObject public: RicfExportVisibleCells(); - void execute() override; + RicfCommandResponse execute() override; private: void buildExportSettings(const QString& exportFolder, RicSaveEclipseInputVisibleCellsUi* exportSettings); diff --git a/ApplicationCode/CommandFileInterface/RicfExportWellPathCompletions.cpp b/ApplicationCode/CommandFileInterface/RicfExportWellPathCompletions.cpp index dd55cdc43d..ade3cf3247 100644 --- a/ApplicationCode/CommandFileInterface/RicfExportWellPathCompletions.cpp +++ b/ApplicationCode/CommandFileInterface/RicfExportWellPathCompletions.cpp @@ -65,7 +65,7 @@ RicfExportWellPathCompletions::RicfExportWellPathCompletions() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicfExportWellPathCompletions::execute() +RicfCommandResponse RicfExportWellPathCompletions::execute() { using TOOLS = RicfApplicationTools; @@ -101,8 +101,9 @@ void RicfExportWellPathCompletions::execute() auto eclipseCase = TOOLS::caseFromId(m_caseId()); if (!eclipseCase) { - RiaLogging::error(QString("exportWellPathCompletions: Could not find case with ID %1").arg(m_caseId())); - return; + QString error = QString("exportWellPathCompletions: Could not find case with ID %1").arg(m_caseId()); + RiaLogging::error(error); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, error); } exportSettings->caseToApply = eclipseCase; } @@ -114,6 +115,8 @@ void RicfExportWellPathCompletions::execute() } exportSettings->folder = exportFolder; + RicfCommandResponse response; + std::vector wellPaths; if (m_wellPathNames().empty()) { @@ -136,7 +139,9 @@ void RicfExportWellPathCompletions::execute() } else { - RiaLogging::warning(QString("exportWellPathCompletions: Could not find well path with name %1").arg(wellPathName)); + QString warning = QString("exportWellPathCompletions: Could not find well path with name %1").arg(wellPathName); + RiaLogging::warning(warning); + response.updateStatus(RicfCommandResponse::COMMAND_WARNING, warning); } } } @@ -144,4 +149,6 @@ void RicfExportWellPathCompletions::execute() std::vector simWells; RicWellPathExportCompletionDataFeatureImpl::exportCompletions(wellPaths, simWells, *exportSettings); + + return response; } diff --git a/ApplicationCode/CommandFileInterface/RicfExportWellPathCompletions.h b/ApplicationCode/CommandFileInterface/RicfExportWellPathCompletions.h index 1d8e9128d1..d6cafdb063 100644 --- a/ApplicationCode/CommandFileInterface/RicfExportWellPathCompletions.h +++ b/ApplicationCode/CommandFileInterface/RicfExportWellPathCompletions.h @@ -37,7 +37,7 @@ class RicfExportWellPathCompletions : public RicfCommandObject public: RicfExportWellPathCompletions(); - void execute() override; + RicfCommandResponse execute() override; private: caf::PdmField m_caseId; diff --git a/ApplicationCode/CommandFileInterface/RicfExportWellPaths.cpp b/ApplicationCode/CommandFileInterface/RicfExportWellPaths.cpp index 59f630c3a1..3609679609 100644 --- a/ApplicationCode/CommandFileInterface/RicfExportWellPaths.cpp +++ b/ApplicationCode/CommandFileInterface/RicfExportWellPaths.cpp @@ -52,7 +52,7 @@ RicfExportWellPaths::RicfExportWellPaths() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicfExportWellPaths::execute() +RicfCommandResponse RicfExportWellPaths::execute() { using TOOLS = RicfApplicationTools; @@ -64,27 +64,34 @@ void RicfExportWellPaths::execute() wellPaths = TOOLS::wellPathsFromNames(TOOLS::toQStringList(m_wellPathNames), &wellsNotFound); if (!wellsNotFound.empty()) { - RiaLogging::error(QString("exportWellPaths: These well paths were not found: ") + wellsNotFound.join(", ")); + QString error(QString("exportWellPaths: These well paths were not found: ") + wellsNotFound.join(", ")); + RiaLogging::error(error); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, error); } } - if (!wellPaths.empty()) + if (wellPaths.empty()) { - QString exportFolder = RicfCommandFileExecutor::instance()->getExportPath(RicfCommandFileExecutor::WELLPATHS); - if (exportFolder.isNull()) - { - exportFolder = RiaApplication::instance()->createAbsolutePathFromProjectRelativePath("wellpaths"); - } + QString error("No well paths found"); + RiaLogging::error(error); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, error); + } - caf::CmdFeatureManager* commandManager = caf::CmdFeatureManager::instance(); - auto feature = dynamic_cast(commandManager->getCommandFeature("RicExportSelectedWellPathsFeature")); + QString exportFolder = RicfCommandFileExecutor::instance()->getExportPath(RicfCommandFileExecutor::WELLPATHS); + if (exportFolder.isNull()) + { + exportFolder = RiaApplication::instance()->createAbsolutePathFromProjectRelativePath("wellpaths"); + } - for (const auto wellPath : wellPaths) + caf::CmdFeatureManager* commandManager = caf::CmdFeatureManager::instance(); + auto feature = dynamic_cast(commandManager->getCommandFeature("RicExportSelectedWellPathsFeature")); + + for (const auto wellPath : wellPaths) + { + if (wellPath) { - if (wellPath) - { - feature->exportWellPath(wellPath, m_mdStepSize, exportFolder, false); - } + feature->exportWellPath(wellPath, m_mdStepSize, exportFolder, false); } } + return RicfCommandResponse(); } diff --git a/ApplicationCode/CommandFileInterface/RicfExportWellPaths.h b/ApplicationCode/CommandFileInterface/RicfExportWellPaths.h index 6c1ee4dc5c..e3f68ac63b 100644 --- a/ApplicationCode/CommandFileInterface/RicfExportWellPaths.h +++ b/ApplicationCode/CommandFileInterface/RicfExportWellPaths.h @@ -37,7 +37,7 @@ class RicfExportWellPaths : public RicfCommandObject public: RicfExportWellPaths(); - void execute() override; + RicfCommandResponse execute() override; private: caf::PdmField> m_wellPathNames; diff --git a/ApplicationCode/CommandFileInterface/RicfLoadCase.cpp b/ApplicationCode/CommandFileInterface/RicfLoadCase.cpp index fc80ad6a49..462b2270e9 100644 --- a/ApplicationCode/CommandFileInterface/RicfLoadCase.cpp +++ b/ApplicationCode/CommandFileInterface/RicfLoadCase.cpp @@ -37,11 +37,14 @@ RicfLoadCase::RicfLoadCase() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicfLoadCase::execute() +RicfCommandResponse RicfLoadCase::execute() { bool ok = RiaImportEclipseCaseTools::openEclipseCasesFromFile(QStringList({m_path()}), nullptr, true); if (!ok) { - RiaLogging::error(QString("loadCase: Unable to load case from %1").arg(m_path())); + QString error = QString("loadCase: Unable to load case from %1").arg(m_path()); + RiaLogging::error(error); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, error); } + return RicfCommandResponse(); } diff --git a/ApplicationCode/CommandFileInterface/RicfLoadCase.h b/ApplicationCode/CommandFileInterface/RicfLoadCase.h index 34dfa3fd1c..c65ec2034d 100644 --- a/ApplicationCode/CommandFileInterface/RicfLoadCase.h +++ b/ApplicationCode/CommandFileInterface/RicfLoadCase.h @@ -34,7 +34,7 @@ class RicfLoadCase : public RicfCommandObject public: RicfLoadCase(); - void execute() override; + RicfCommandResponse execute() override; private: caf::PdmField m_path; diff --git a/ApplicationCode/CommandFileInterface/RicfOpenProject.cpp b/ApplicationCode/CommandFileInterface/RicfOpenProject.cpp index bffdbff2ab..b086baaa1a 100644 --- a/ApplicationCode/CommandFileInterface/RicfOpenProject.cpp +++ b/ApplicationCode/CommandFileInterface/RicfOpenProject.cpp @@ -40,7 +40,7 @@ RicfOpenProject::RicfOpenProject() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicfOpenProject::execute() +RicfCommandResponse RicfOpenProject::execute() { QString projectPath = m_path; QFileInfo projectPathInfo(projectPath); @@ -52,8 +52,9 @@ void RicfOpenProject::execute() bool ok = RiaApplication::instance()->loadProject(projectPath); if (!ok) { - RiaLogging::error(QString("openProject: Unable to open project at %1").arg(m_path())); - return; + QString errMsg = QString("openProject: Unable to open project at %1").arg(m_path()); + RiaLogging::error(errMsg); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, errMsg); } if (RiaRegressionTestRunner::instance()->isRunningRegressionTests()) @@ -62,4 +63,6 @@ void RicfOpenProject::execute() } RicfCommandFileExecutor::instance()->setLastProjectPath(projectPath); + + return RicfCommandResponse(); } diff --git a/ApplicationCode/CommandFileInterface/RicfOpenProject.h b/ApplicationCode/CommandFileInterface/RicfOpenProject.h index 4584818fbd..e09014e27c 100644 --- a/ApplicationCode/CommandFileInterface/RicfOpenProject.h +++ b/ApplicationCode/CommandFileInterface/RicfOpenProject.h @@ -34,7 +34,7 @@ class RicfOpenProject : public RicfCommandObject public: RicfOpenProject(); - void execute() override; + RicfCommandResponse execute() override; private: caf::PdmField m_path; diff --git a/ApplicationCode/CommandFileInterface/RicfReplaceCase.cpp b/ApplicationCode/CommandFileInterface/RicfReplaceCase.cpp index 4cfe9c5b92..dd9c2f6502 100644 --- a/ApplicationCode/CommandFileInterface/RicfReplaceCase.cpp +++ b/ApplicationCode/CommandFileInterface/RicfReplaceCase.cpp @@ -56,10 +56,11 @@ QString RicfSingleCaseReplace::filePath() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicfSingleCaseReplace::execute() +RicfCommandResponse RicfSingleCaseReplace::execute() { // Never call execute on this object, information is aggregated into RicfMultiCaseReplace CAF_ASSERT(false); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, "Never call execute on a RicfSingleCaseReplace object"); } @@ -85,19 +86,21 @@ void RicfMultiCaseReplace::setCaseReplacePairs(const std::map& cas //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicfMultiCaseReplace::execute() +RicfCommandResponse RicfMultiCaseReplace::execute() { if (m_caseIdToGridFileNameMap.empty()) { - RiaLogging::error("replaceCaseImpl: No replacements available."); - return; + QString errMsg("replaceCaseImpl: No replacements available."); + RiaLogging::error(errMsg); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, errMsg); } QString lastProjectPath = RicfCommandFileExecutor::instance()->getLastProjectPath(); if (lastProjectPath.isNull()) { - RiaLogging::error("replaceCase: 'openProject' must be called before 'replaceCase' to specify project file to replace case in."); - return; + QString errMsg("replaceCase: 'openProject' must be called before 'replaceCase' to specify project file to replace case in."); + RiaLogging::error(errMsg); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, errMsg); } cvf::ref projectModifier = new RiaProjectModifier; @@ -115,5 +118,12 @@ void RicfMultiCaseReplace::execute() } } - RiaApplication::instance()->loadProject(lastProjectPath, RiaApplication::PLA_NONE, projectModifier.p()); + if (!RiaApplication::instance()->loadProject(lastProjectPath, RiaApplication::PLA_NONE, projectModifier.p())) + { + QString errMsg("Could not reload project"); + RiaLogging::error(errMsg); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, errMsg); + } + + return RicfCommandResponse(); } diff --git a/ApplicationCode/CommandFileInterface/RicfReplaceCase.h b/ApplicationCode/CommandFileInterface/RicfReplaceCase.h index 791ece466d..6d579b13b2 100644 --- a/ApplicationCode/CommandFileInterface/RicfReplaceCase.h +++ b/ApplicationCode/CommandFileInterface/RicfReplaceCase.h @@ -40,7 +40,7 @@ public: int caseId() const; QString filePath() const; - void execute() override; + RicfCommandResponse execute() override; private: caf::PdmField m_newGridFile; @@ -63,7 +63,7 @@ public: void setCaseReplacePairs(const std::map& caseIdToGridFileNameMap); - void execute() override; + RicfCommandResponse execute() override; private: std::map m_caseIdToGridFileNameMap; diff --git a/ApplicationCode/CommandFileInterface/RicfReplaceSourceCases.cpp b/ApplicationCode/CommandFileInterface/RicfReplaceSourceCases.cpp index caa8ddd240..c0a5a8a3fb 100644 --- a/ApplicationCode/CommandFileInterface/RicfReplaceSourceCases.cpp +++ b/ApplicationCode/CommandFileInterface/RicfReplaceSourceCases.cpp @@ -38,19 +38,21 @@ RicfReplaceSourceCases::RicfReplaceSourceCases() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicfReplaceSourceCases::execute() +RicfCommandResponse RicfReplaceSourceCases::execute() { if (m_gridListFile().isNull()) { - RiaLogging::error("replaceSourceCases: Required parameter gridListFile."); - return; + QString error("replaceSourceCases: Required parameter gridListFile."); + RiaLogging::error(error); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, error); } QString lastProjectPath = RicfCommandFileExecutor::instance()->getLastProjectPath(); if (lastProjectPath.isNull()) { - RiaLogging::error("replaceSourceCases: 'openProject' must be called before 'replaceSourceCases' to specify project file to replace cases in."); - return; + QString error("replaceSourceCases: 'openProject' must be called before 'replaceSourceCases' to specify project file to replace cases in."); + RiaLogging::error(error); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, error); } cvf::ref projectModifier = new RiaProjectModifier; @@ -65,5 +67,11 @@ void RicfReplaceSourceCases::execute() projectModifier->setReplaceSourceCasesById(m_caseGroupId(), listFileNames); } - RiaApplication::instance()->loadProject(lastProjectPath, RiaApplication::PLA_CALCULATE_STATISTICS, projectModifier.p()); + if (!RiaApplication::instance()->loadProject(lastProjectPath, RiaApplication::PLA_CALCULATE_STATISTICS, projectModifier.p())) + { + QString error("Could not reload project"); + RiaLogging::error(error); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, error); + } + return RicfCommandResponse(); } diff --git a/ApplicationCode/CommandFileInterface/RicfReplaceSourceCases.h b/ApplicationCode/CommandFileInterface/RicfReplaceSourceCases.h index f4d4cf6d6b..d8dba57e60 100644 --- a/ApplicationCode/CommandFileInterface/RicfReplaceSourceCases.h +++ b/ApplicationCode/CommandFileInterface/RicfReplaceSourceCases.h @@ -34,7 +34,7 @@ class RicfReplaceSourceCases : public RicfCommandObject public: RicfReplaceSourceCases(); - void execute() override; + RicfCommandResponse execute() override; private: caf::PdmField m_gridListFile; diff --git a/ApplicationCode/CommandFileInterface/RicfRunOctaveScript.cpp b/ApplicationCode/CommandFileInterface/RicfRunOctaveScript.cpp index f04871e673..c9cf89e180 100644 --- a/ApplicationCode/CommandFileInterface/RicfRunOctaveScript.cpp +++ b/ApplicationCode/CommandFileInterface/RicfRunOctaveScript.cpp @@ -42,7 +42,7 @@ RicfRunOctaveScript::RicfRunOctaveScript() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicfRunOctaveScript::execute() +RicfCommandResponse RicfRunOctaveScript::execute() { QString octavePath = RiaApplication::instance()->octavePath(); @@ -71,12 +71,17 @@ void RicfRunOctaveScript::execute() { ok = RiaApplication::instance()->launchProcessForMultipleCases(octavePath, processArguments, caseIds); } + + RicfCommandResponse response; if (!ok) { - RiaLogging::error(QString("runOctaveScript: Could not execute script %1").arg(m_path())); + QString error = QString("runOctaveScript: Could not execute script %1").arg(m_path()); + RiaLogging::error(error); + response.updateStatus(RicfCommandResponse::COMMAND_ERROR, error); } else { RiaApplication::instance()->waitForProcess(); } + return response; } diff --git a/ApplicationCode/CommandFileInterface/RicfRunOctaveScript.h b/ApplicationCode/CommandFileInterface/RicfRunOctaveScript.h index 54d1fba458..58aa7254f3 100644 --- a/ApplicationCode/CommandFileInterface/RicfRunOctaveScript.h +++ b/ApplicationCode/CommandFileInterface/RicfRunOctaveScript.h @@ -34,7 +34,7 @@ class RicfRunOctaveScript : public RicfCommandObject public: RicfRunOctaveScript(); - void execute() override; + RicfCommandResponse execute() override; private: caf::PdmField m_path; diff --git a/ApplicationCode/CommandFileInterface/RicfScaleFractureTemplate.cpp b/ApplicationCode/CommandFileInterface/RicfScaleFractureTemplate.cpp index 82e3ef6c9a..2f4c99820d 100644 --- a/ApplicationCode/CommandFileInterface/RicfScaleFractureTemplate.cpp +++ b/ApplicationCode/CommandFileInterface/RicfScaleFractureTemplate.cpp @@ -49,20 +49,22 @@ RicfScaleFractureTemplate::RicfScaleFractureTemplate() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicfScaleFractureTemplate::execute() +RicfCommandResponse RicfScaleFractureTemplate::execute() { if (m_id < 0) { - RiaLogging::error("scaleFractureTemplate: Fracture template id not specified"); - return; + QString error("scaleFractureTemplate: Fracture template id not specified"); + RiaLogging::error(error); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, error); } RimProject* project = RiaApplication::instance()->project(); if (!project) { - RiaLogging::error("scaleFractureTemplate: Project not found"); - return; + QString error("scaleFractureTemplate: Project not found"); + RiaLogging::error(error); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, error); } RimFractureTemplateCollection* templColl = @@ -71,12 +73,14 @@ void RicfScaleFractureTemplate::execute() if (!templ) { - RiaLogging::error(QString("scaleFractureTemplate: Fracture template not found. Id=%1").arg(m_id)); - return; + QString error = QString("scaleFractureTemplate: Fracture template not found. Id=%1").arg(m_id); + RiaLogging::error(error); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, error); } templ->setScaleFactors(m_halfLengthScaleFactor, m_heightScaleFactor, m_dFactorScaleFactor, m_conductivityScaleFactor); templ->loadDataAndUpdateGeometryHasChanged(); + return RicfCommandResponse(); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/CommandFileInterface/RicfScaleFractureTemplate.h b/ApplicationCode/CommandFileInterface/RicfScaleFractureTemplate.h index 7fa09a3e64..f61ff29383 100644 --- a/ApplicationCode/CommandFileInterface/RicfScaleFractureTemplate.h +++ b/ApplicationCode/CommandFileInterface/RicfScaleFractureTemplate.h @@ -36,7 +36,7 @@ class RicfScaleFractureTemplate : public RicfCommandObject public: RicfScaleFractureTemplate(); - void execute() override; + RicfCommandResponse execute() override; private: void initAfterRead() override; diff --git a/ApplicationCode/CommandFileInterface/RicfSetExportFolder.cpp b/ApplicationCode/CommandFileInterface/RicfSetExportFolder.cpp index f285511c1b..7c7cf9d2eb 100644 --- a/ApplicationCode/CommandFileInterface/RicfSetExportFolder.cpp +++ b/ApplicationCode/CommandFileInterface/RicfSetExportFolder.cpp @@ -40,7 +40,7 @@ RicfSetExportFolder::RicfSetExportFolder() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicfSetExportFolder::execute() +RicfCommandResponse RicfSetExportFolder::execute() { if (m_createFolder) { @@ -52,11 +52,14 @@ void RicfSetExportFolder::execute() if (!dir.exists(m_path)) { - RiaLogging::error("Could not create folder : " + m_path); + QString error = QString("Could not create folder : %1").arg(m_path); + RiaLogging::error(error); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, error); } } } RicfCommandFileExecutor* executor = RicfCommandFileExecutor::instance(); executor->setExportPath(m_type(), m_path); + return RicfCommandResponse(); } diff --git a/ApplicationCode/CommandFileInterface/RicfSetExportFolder.h b/ApplicationCode/CommandFileInterface/RicfSetExportFolder.h index 7e2a1efed9..231e3164f7 100644 --- a/ApplicationCode/CommandFileInterface/RicfSetExportFolder.h +++ b/ApplicationCode/CommandFileInterface/RicfSetExportFolder.h @@ -36,7 +36,7 @@ class RicfSetExportFolder : public RicfCommandObject public: RicfSetExportFolder(); - void execute() override; + RicfCommandResponse execute() override; private: caf::PdmField m_type; diff --git a/ApplicationCode/CommandFileInterface/RicfSetFractureContainment.cpp b/ApplicationCode/CommandFileInterface/RicfSetFractureContainment.cpp index d9ae34a3ff..31355857c7 100644 --- a/ApplicationCode/CommandFileInterface/RicfSetFractureContainment.cpp +++ b/ApplicationCode/CommandFileInterface/RicfSetFractureContainment.cpp @@ -41,20 +41,22 @@ RicfSetFractureContainment::RicfSetFractureContainment() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicfSetFractureContainment::execute() +RicfCommandResponse RicfSetFractureContainment::execute() { if (m_id < 0 || m_topLayer < 0 || m_baseLayer < 0) { - RiaLogging::error("setFractureContainment: Required argument missing"); - return; + QString error("setFractureContainment: Required argument missing"); + RiaLogging::error(error); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, error); } RimProject* project = RiaApplication::instance()->project(); if (!project) { - RiaLogging::error("setFractureContainment: Project not found"); - return; + QString error("setFractureContainment: Project not found"); + RiaLogging::error(error); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, error); } RimFractureTemplateCollection* templColl = !project->allFractureTemplateCollections().empty() ? project->allFractureTemplateCollections()[0] : nullptr; @@ -62,11 +64,13 @@ void RicfSetFractureContainment::execute() if (!templ) { - RiaLogging::error(QString("setFractureContainment: Fracture template not found. Id=%1").arg(m_id)); - return; + QString error = QString("setFractureContainment: Fracture template not found. Id=%1").arg(m_id); + RiaLogging::error(error); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, error); } templ->setContainmentTopKLayer(m_topLayer); templ->setContainmentBaseKLayer(m_baseLayer); templ->loadDataAndUpdateGeometryHasChanged(); + return RicfCommandResponse(); } diff --git a/ApplicationCode/CommandFileInterface/RicfSetFractureContainment.h b/ApplicationCode/CommandFileInterface/RicfSetFractureContainment.h index 1389a88819..57693b5bfc 100644 --- a/ApplicationCode/CommandFileInterface/RicfSetFractureContainment.h +++ b/ApplicationCode/CommandFileInterface/RicfSetFractureContainment.h @@ -36,7 +36,7 @@ class RicfSetFractureContainment : public RicfCommandObject public: RicfSetFractureContainment(); - void execute() override; + RicfCommandResponse execute() override; private: caf::PdmField m_id; diff --git a/ApplicationCode/CommandFileInterface/RicfSetMainWindowSize.cpp b/ApplicationCode/CommandFileInterface/RicfSetMainWindowSize.cpp index 2dea85c837..443f86e2ea 100644 --- a/ApplicationCode/CommandFileInterface/RicfSetMainWindowSize.cpp +++ b/ApplicationCode/CommandFileInterface/RicfSetMainWindowSize.cpp @@ -35,7 +35,8 @@ RicfSetMainWindowSize::RicfSetMainWindowSize() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicfSetMainWindowSize::execute() +RicfCommandResponse RicfSetMainWindowSize::execute() { RiuMainWindow::instance()->resize(m_width, m_height); + return RicfCommandResponse(); } diff --git a/ApplicationCode/CommandFileInterface/RicfSetMainWindowSize.h b/ApplicationCode/CommandFileInterface/RicfSetMainWindowSize.h index ddce5cd87e..d047bec3ef 100644 --- a/ApplicationCode/CommandFileInterface/RicfSetMainWindowSize.h +++ b/ApplicationCode/CommandFileInterface/RicfSetMainWindowSize.h @@ -34,7 +34,7 @@ class RicfSetMainWindowSize : public RicfCommandObject public: RicfSetMainWindowSize(); - void execute() override; + RicfCommandResponse execute() override; private: caf::PdmField m_height; diff --git a/ApplicationCode/CommandFileInterface/RicfSetStartDir.cpp b/ApplicationCode/CommandFileInterface/RicfSetStartDir.cpp index b019ae65a9..812fe7646b 100644 --- a/ApplicationCode/CommandFileInterface/RicfSetStartDir.cpp +++ b/ApplicationCode/CommandFileInterface/RicfSetStartDir.cpp @@ -20,6 +20,8 @@ #include "RiaApplication.h" +#include + CAF_PDM_SOURCE_INIT(RicfSetStartDir, "setStartDir"); //-------------------------------------------------------------------------------------------------- @@ -33,7 +35,22 @@ RicfSetStartDir::RicfSetStartDir() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicfSetStartDir::execute() +RicfCommandResponse RicfSetStartDir::execute() { + QDir directory(m_path); + if (!directory.exists()) + { + QString error = QString("Path does not exist: %1").arg(m_path); + RiaLogging::error(error); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, error); + } + if (!directory.isReadable()) + { + QString error = QString("Path does not exist: %1").arg(m_path); + RiaLogging::error(error); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, error); + } + RiaApplication::instance()->setStartDir(m_path); + return RicfCommandResponse(); } diff --git a/ApplicationCode/CommandFileInterface/RicfSetStartDir.h b/ApplicationCode/CommandFileInterface/RicfSetStartDir.h index 91fc11a52e..b26183538d 100644 --- a/ApplicationCode/CommandFileInterface/RicfSetStartDir.h +++ b/ApplicationCode/CommandFileInterface/RicfSetStartDir.h @@ -34,7 +34,7 @@ class RicfSetStartDir : public RicfCommandObject public: RicfSetStartDir(); - void execute() override; + RicfCommandResponse execute() override; private: caf::PdmField m_path; diff --git a/ApplicationCode/CommandFileInterface/RicfSetTimeStep.cpp b/ApplicationCode/CommandFileInterface/RicfSetTimeStep.cpp index fedb30ca20..22655a6cdc 100644 --- a/ApplicationCode/CommandFileInterface/RicfSetTimeStep.cpp +++ b/ApplicationCode/CommandFileInterface/RicfSetTimeStep.cpp @@ -57,7 +57,7 @@ void RicfSetTimeStep::setTimeStepIndex(int timeStepIndex) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicfSetTimeStep::execute() +RicfCommandResponse RicfSetTimeStep::execute() { RimEclipseCase* eclipseCase = nullptr; @@ -74,14 +74,28 @@ void RicfSetTimeStep::execute() } if (!foundCase) { - RiaLogging::error(QString("setTimeStep: Could not find case with ID %1").arg(m_caseId())); - return; + QString error = QString("setTimeStep: Could not find case with ID %1").arg(m_caseId()); + RiaLogging::error(error); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, error); } } + int maxTimeStep = eclipseCase->timeStepStrings().size() - 1; + if (m_timeStepIndex() > maxTimeStep) + { + QString error = QString("setTimeStep: Step %1 is larger than the maximum of %2 for case %3") + .arg(m_timeStepIndex()) + .arg(maxTimeStep) + .arg(m_caseId()); + RiaLogging::error(error); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, error); + } + for (Rim3dView* view : eclipseCase->views()) { view->setCurrentTimeStepAndUpdate(m_timeStepIndex); view->createDisplayModelAndRedraw(); } + + return RicfCommandResponse(); } diff --git a/ApplicationCode/CommandFileInterface/RicfSetTimeStep.h b/ApplicationCode/CommandFileInterface/RicfSetTimeStep.h index 39cd72a8d4..69e7c9b89d 100644 --- a/ApplicationCode/CommandFileInterface/RicfSetTimeStep.h +++ b/ApplicationCode/CommandFileInterface/RicfSetTimeStep.h @@ -37,7 +37,7 @@ public: void setCaseId(int caseId); void setTimeStepIndex(int timeStepIndex); - void execute() override; + RicfCommandResponse execute() override; private: diff --git a/ApplicationCode/Commands/ExportCommands/RicEclipseCellResultToFileImpl.cpp b/ApplicationCode/Commands/ExportCommands/RicEclipseCellResultToFileImpl.cpp index dc9230b846..3647b6fb00 100644 --- a/ApplicationCode/Commands/ExportCommands/RicEclipseCellResultToFileImpl.cpp +++ b/ApplicationCode/Commands/ExportCommands/RicEclipseCellResultToFileImpl.cpp @@ -39,7 +39,8 @@ bool RicEclipseCellResultToFileImpl::writePropertyToTextFile(const QString& size_t timeStep, const QString& resultName, const QString& eclipseKeyword, - const double undefinedValue) + const double undefinedValue, + QString* errorMsg) { CVF_TIGHT_ASSERT(eclipseCase); if (!eclipseCase) return false; @@ -52,7 +53,7 @@ bool RicEclipseCellResultToFileImpl::writePropertyToTextFile(const QString& } return writeResultToTextFile( - fileName, eclipseCase, resultAccessor.p(), eclipseKeyword, undefinedValue, "writePropertyToTextFile"); + fileName, eclipseCase, resultAccessor.p(), eclipseKeyword, undefinedValue, "writePropertyToTextFile", errorMsg); } //-------------------------------------------------------------------------------------------------- @@ -64,7 +65,8 @@ bool RicEclipseCellResultToFileImpl::writeBinaryResultToTextFile(const QString& RimEclipseResultDefinition* resultDefinition, const QString& eclipseKeyword, const double undefinedValue, - const QString& logPrefix) + const QString& logPrefix, + QString* errorMsg) { CVF_TIGHT_ASSERT(eclipseCase); @@ -75,7 +77,7 @@ bool RicEclipseCellResultToFileImpl::writeBinaryResultToTextFile(const QString& return false; } - return writeResultToTextFile(fileName, eclipseCase, resultAccessor.p(), eclipseKeyword, undefinedValue, logPrefix); + return writeResultToTextFile(fileName, eclipseCase, resultAccessor.p(), eclipseKeyword, undefinedValue, logPrefix, errorMsg); } //-------------------------------------------------------------------------------------------------- @@ -86,18 +88,21 @@ bool RicEclipseCellResultToFileImpl::writeResultToTextFile(const QString& f RigResultAccessor* resultAccessor, const QString& eclipseKeyword, const double undefinedValue, - const QString& logPrefix) + const QString& logPrefix, + QString* errorMsg) { + CAF_ASSERT(errorMsg != nullptr); + if (!resultAccessor) { - RiaLogging::error(logPrefix + QString(" : : Could not access result data for '%1'").arg(fileName)); + *errorMsg = QString(logPrefix + QString(" : : Could not access result data for '%1'").arg(fileName)); return false; } QFile file(fileName); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { - RiaLogging::error(logPrefix + QString(" : Could not open file '%1'. Do the folder exist?").arg(fileName)); + *errorMsg = QString(logPrefix + QString(" : Could not open file '%1'. Do the folder exist?").arg(fileName)); return false; } diff --git a/ApplicationCode/Commands/ExportCommands/RicEclipseCellResultToFileImpl.h b/ApplicationCode/Commands/ExportCommands/RicEclipseCellResultToFileImpl.h index 56e8237ee1..d9a59da195 100644 --- a/ApplicationCode/Commands/ExportCommands/RicEclipseCellResultToFileImpl.h +++ b/ApplicationCode/Commands/ExportCommands/RicEclipseCellResultToFileImpl.h @@ -39,7 +39,8 @@ public: size_t timeStep, const QString& resultName, const QString& eclipseKeyword, - const double undefinedValue); + const double undefinedValue, + QString* errorMsg); static bool writeBinaryResultToTextFile(const QString& fileName, RigEclipseCaseData* eclipseCase, @@ -47,14 +48,16 @@ public: RimEclipseResultDefinition* resultDefinition, const QString& eclipseKeyword, const double undefinedValue, - const QString& logPrefix); + const QString& logPrefix, + QString* errorMsg); static bool writeResultToTextFile(const QString& fileName, RigEclipseCaseData* eclipseCase, RigResultAccessor* resultAccessor, const QString& eclipseKeyword, const double undefinedValue, - const QString& logPrefix); + const QString& logPrefix, + QString* errorMsg); static void writeDataToTextFile(QFile* file, const QString& eclipseKeyword, const std::vector& resultData); }; diff --git a/ApplicationCode/Commands/ExportCommands/RicSaveEclipseInputPropertyFeature.cpp b/ApplicationCode/Commands/ExportCommands/RicSaveEclipseInputPropertyFeature.cpp index 93b33d4da0..7bd9cb2ea1 100644 --- a/ApplicationCode/Commands/ExportCommands/RicSaveEclipseInputPropertyFeature.cpp +++ b/ApplicationCode/Commands/ExportCommands/RicSaveEclipseInputPropertyFeature.cpp @@ -107,20 +107,26 @@ void RicSaveEclipseInputPropertyFeature::onActionTriggered(bool isChecked) { const double undefinedValue = 0.0; - bool isOk = RicEclipseCellResultToFileImpl::writePropertyToTextFile(exportSettings.fileName, + QString errorMsg; + bool isOk = RicEclipseCellResultToFileImpl::writePropertyToTextFile(exportSettings.fileName, inputReservoir->eclipseCaseData(), 0, inputProperty->resultName, exportSettings.eclipseKeyword, - undefinedValue); + undefinedValue, + &errorMsg); if (isOk) { - inputProperty->fileName = exportSettings.fileName; + inputProperty->fileName = exportSettings.fileName; inputProperty->eclipseKeyword = exportSettings.eclipseKeyword; - inputProperty->resolvedState = RimEclipseInputProperty::RESOLVED; + inputProperty->resolvedState = RimEclipseInputProperty::RESOLVED; inputProperty->updateConnectedEditors(); } + else + { + RiaLogging::error(errorMsg); + } } } diff --git a/ApplicationCode/Commands/ExportCommands/RicSaveEclipseResultAsInputPropertyExec.cpp b/ApplicationCode/Commands/ExportCommands/RicSaveEclipseResultAsInputPropertyExec.cpp index 0628968c45..9df0ea81ac 100644 --- a/ApplicationCode/Commands/ExportCommands/RicSaveEclipseResultAsInputPropertyExec.cpp +++ b/ApplicationCode/Commands/ExportCommands/RicSaveEclipseResultAsInputPropertyExec.cpp @@ -97,10 +97,12 @@ void RicSaveEclipseResultAsInputPropertyExec::redo() { size_t timeStep = m_cellColors->reservoirView()->currentTimeStep(); - bool isOk = RicEclipseCellResultToFileImpl::writeBinaryResultToTextFile(exportSettings.fileName, m_cellColors->reservoirView()->eclipseCase()->eclipseCaseData(), timeStep, m_cellColors, exportSettings.eclipseKeyword, exportSettings.undefinedValue, "saveEclipseResultAsInputPropertyExec"); + QString errMsg; + bool isOk = RicEclipseCellResultToFileImpl::writeBinaryResultToTextFile(exportSettings.fileName, m_cellColors->reservoirView()->eclipseCase()->eclipseCaseData(), timeStep, m_cellColors, exportSettings.eclipseKeyword, exportSettings.undefinedValue, "saveEclipseResultAsInputPropertyExec", &errMsg); if (!isOk) { - RiaLogging::error("Failed to exported current result to " + exportSettings.fileName); + QString fullError = QString("Failed to exported current result to %1. Error was: %2").arg(exportSettings.fileName).arg(errMsg); + RiaLogging::error(fullError); } } } diff --git a/ApplicationCode/GrpcInterface/RiaGrpcCommandService.cpp b/ApplicationCode/GrpcInterface/RiaGrpcCommandService.cpp index 4e5de80393..9534651fc6 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcCommandService.cpp +++ b/ApplicationCode/GrpcInterface/RiaGrpcCommandService.cpp @@ -73,8 +73,15 @@ grpc::Status RiaGrpcCommandService::Execute(grpc::ServerContext* context, const } } } - commandHandle->execute(); - + RicfCommandResponse response = commandHandle->execute(); + if (response.status() == RicfCommandResponse::COMMAND_ERROR) + { + return grpc::Status(grpc::FAILED_PRECONDITION, response.message().toStdString()); + } + else if (response.status() == RicfCommandResponse::COMMAND_WARNING) + { + context->AddInitialMetadata("warning", response.message().toStdString()); + } return Status::OK; } } From cc031e78956493b5f7f599a74fb1f2928a6b5baf Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Thu, 23 May 2019 16:46:50 +0200 Subject: [PATCH 073/396] #4429 Implement return values from the gRPC Command execution --- .../Tools/RiaImportEclipseCaseTools.cpp | 28 +++-- .../Tools/RiaImportEclipseCaseTools.h | 10 +- .../CommandFileInterface/RicfLoadCase.cpp | 20 +++- .../CommandFileInterface/RicfLoadCase.h | 9 ++ .../RicImportEclipseCasesFeature.cpp | 6 +- .../Commands/RicImportGeneralDataFeature.cpp | 6 +- .../GrpcInterface/GrpcProtos/Commands.proto | 12 +- .../GrpcInterface/RiaGrpcCommandService.cpp | 113 ++++++++++++++++-- .../GrpcInterface/RiaGrpcCommandService.h | 18 +-- Python/api/ResInsight.py | 6 +- 10 files changed, 185 insertions(+), 43 deletions(-) diff --git a/ApplicationCode/Application/Tools/RiaImportEclipseCaseTools.cpp b/ApplicationCode/Application/Tools/RiaImportEclipseCaseTools.cpp index be713ee899..a51ad88209 100644 --- a/ApplicationCode/Application/Tools/RiaImportEclipseCaseTools.cpp +++ b/ApplicationCode/Application/Tools/RiaImportEclipseCaseTools.cpp @@ -69,7 +69,7 @@ //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool RiaImportEclipseCaseTools::openEclipseCasesFromFile(const QStringList& fileNames, QStringList* openedFiles, bool noDialog) +bool RiaImportEclipseCaseTools::openEclipseCasesFromFile(const QStringList& fileNames, FileCaseIdMap* openedFilesOut, bool noDialog) { RiaApplication* app = RiaApplication::instance(); RimProject* project = app->project(); @@ -80,12 +80,15 @@ bool RiaImportEclipseCaseTools::openEclipseCasesFromFile(const QStringList& file selector.determineFilesToImportFromGridFiles(fileNames); std::vector summaryFileInfos = selector.summaryFileInfos(); + FileCaseIdMap openedFiles; + // Import eclipse case files for (const QString& gridCaseFile : selector.gridCaseFiles()) { - if (RiaImportEclipseCaseTools::openEclipseCaseFromFile(gridCaseFile)) + int caseId = RiaImportEclipseCaseTools::openEclipseCaseFromFile(gridCaseFile); + if (caseId >= 0) { - if(openedFiles) openedFiles->push_back(gridCaseFile); + openedFiles.insert(std::make_pair(gridCaseFile, caseId)); } } @@ -178,13 +181,18 @@ bool RiaImportEclipseCaseTools::openEclipseCasesFromFile(const QStringList& file RiuPlotMainWindowTools::refreshToolbars(); - return true; + if (openedFilesOut) + { + *openedFilesOut = openedFiles; + } + + return !openedFiles.empty(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool RiaImportEclipseCaseTools::openEclipseCaseFromFile(const QString& fileName) +int RiaImportEclipseCaseTools::openEclipseCaseFromFile(const QString& fileName) { if (!caf::Utils::fileExists(fileName)) return false; @@ -198,7 +206,7 @@ bool RiaImportEclipseCaseTools::openEclipseCaseShowTimeStepFilter(const QString& { if (!caf::Utils::fileExists(fileName)) return false; - return RiaImportEclipseCaseTools::openEclipseCaseShowTimeStepFilterImpl(fileName, true); + return RiaImportEclipseCaseTools::openEclipseCaseShowTimeStepFilterImpl(fileName, true) >= 0; } //-------------------------------------------------------------------------------------------------- @@ -259,7 +267,7 @@ bool RiaImportEclipseCaseTools::openMockModel(const QString& name) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool RiaImportEclipseCaseTools::openEclipseCaseShowTimeStepFilterImpl(const QString& fileName, bool showTimeStepFilter) +int RiaImportEclipseCaseTools::openEclipseCaseShowTimeStepFilterImpl(const QString& fileName, bool showTimeStepFilter) { QFileInfo gridFileName(fileName); QString caseName = gridFileName.completeBaseName(); @@ -274,7 +282,7 @@ bool RiaImportEclipseCaseTools::openEclipseCaseShowTimeStepFilterImpl(const QStr if (analysisModels == nullptr) { delete rimResultReservoir; - return false; + return -1; } if (RiaGuiApplication::isRunning()) @@ -290,7 +298,7 @@ bool RiaImportEclipseCaseTools::openEclipseCaseShowTimeStepFilterImpl(const QStr delete rimResultReservoir; - return false; + return -1; } RimEclipseView* riv = rimResultReservoir->createAndAddReservoirView(); @@ -306,7 +314,7 @@ bool RiaImportEclipseCaseTools::openEclipseCaseShowTimeStepFilterImpl(const QStr RiuMainWindow::instance()->selectAsCurrentItem(riv->cellResult()); - return true; + return rimResultReservoir->caseId(); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/Application/Tools/RiaImportEclipseCaseTools.h b/ApplicationCode/Application/Tools/RiaImportEclipseCaseTools.h index e0bf0ec6db..e46620e3db 100644 --- a/ApplicationCode/Application/Tools/RiaImportEclipseCaseTools.h +++ b/ApplicationCode/Application/Tools/RiaImportEclipseCaseTools.h @@ -18,6 +18,8 @@ #pragma once +#include + class QString; class QStringList; @@ -27,7 +29,9 @@ class QStringList; class RiaImportEclipseCaseTools { public: - static bool openEclipseCasesFromFile(const QStringList& fileNames, QStringList* openedFiles = nullptr, bool noDialog = false); + typedef std::map FileCaseIdMap; + + static bool openEclipseCasesFromFile(const QStringList& fileNames, FileCaseIdMap* openedFilesOut = nullptr, bool noDialog = false); static bool openEclipseCaseShowTimeStepFilter(const QString& fileName); static bool openEclipseInputCaseFromFileNames(const QStringList& fileNames, QString* fileContainingGrid = nullptr); @@ -36,7 +40,7 @@ public: static bool addEclipseCases(const QStringList& fileNames); private: - static bool openEclipseCaseFromFile(const QString& fileName); - static bool openEclipseCaseShowTimeStepFilterImpl(const QString& fileName, bool showTimeStepFilter); + static int openEclipseCaseFromFile(const QString& fileName); + static int openEclipseCaseShowTimeStepFilterImpl(const QString& fileName, bool showTimeStepFilter); }; diff --git a/ApplicationCode/CommandFileInterface/RicfLoadCase.cpp b/ApplicationCode/CommandFileInterface/RicfLoadCase.cpp index 462b2270e9..f2d4fe8a1a 100644 --- a/ApplicationCode/CommandFileInterface/RicfLoadCase.cpp +++ b/ApplicationCode/CommandFileInterface/RicfLoadCase.cpp @@ -24,6 +24,17 @@ #include +CAF_PDM_SOURCE_INIT(RicfLoadCaseResult, "loadCaseResult"); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RicfLoadCaseResult::RicfLoadCaseResult(int caseId) +{ + CAF_PDM_InitObject("case_result", "", "", ""); + CAF_PDM_InitField(&this->caseId, "id", caseId, "", "", "", ""); +} + CAF_PDM_SOURCE_INIT(RicfLoadCase, "loadCase"); //-------------------------------------------------------------------------------------------------- @@ -39,12 +50,17 @@ RicfLoadCase::RicfLoadCase() //-------------------------------------------------------------------------------------------------- RicfCommandResponse RicfLoadCase::execute() { - bool ok = RiaImportEclipseCaseTools::openEclipseCasesFromFile(QStringList({m_path()}), nullptr, true); + RiaImportEclipseCaseTools::FileCaseIdMap fileCaseIdMap; + bool ok = RiaImportEclipseCaseTools::openEclipseCasesFromFile(QStringList({m_path()}), &fileCaseIdMap, true); if (!ok) { QString error = QString("loadCase: Unable to load case from %1").arg(m_path()); RiaLogging::error(error); return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, error); } - return RicfCommandResponse(); + CAF_ASSERT(fileCaseIdMap.size() == 1u); + RicfLoadCaseResult result; + RicfCommandResponse response; + response.setResult(new RicfLoadCaseResult(fileCaseIdMap.begin()->second)); + return response; } diff --git a/ApplicationCode/CommandFileInterface/RicfLoadCase.h b/ApplicationCode/CommandFileInterface/RicfLoadCase.h index c65ec2034d..4e5ab85852 100644 --- a/ApplicationCode/CommandFileInterface/RicfLoadCase.h +++ b/ApplicationCode/CommandFileInterface/RicfLoadCase.h @@ -22,6 +22,15 @@ #include "cafPdmField.h" +class RicfLoadCaseResult : public caf::PdmObject +{ + CAF_PDM_HEADER_INIT; +public: + RicfLoadCaseResult(int caseId = -1); +public: + caf::PdmField caseId; +}; + //================================================================================================== // // diff --git a/ApplicationCode/Commands/EclipseCommands/RicImportEclipseCasesFeature.cpp b/ApplicationCode/Commands/EclipseCommands/RicImportEclipseCasesFeature.cpp index 39cbbec3b6..9bd97423a1 100644 --- a/ApplicationCode/Commands/EclipseCommands/RicImportEclipseCasesFeature.cpp +++ b/ApplicationCode/Commands/EclipseCommands/RicImportEclipseCasesFeature.cpp @@ -68,12 +68,12 @@ void RicImportEclipseCasesFeature::onActionTriggered(bool isChecked) // Remember the path to next time app->setLastUsedDialogDirectory("BINARY_GRID", QFileInfo(result.rootDir).absoluteFilePath()); - QStringList newCaseFiles; + RiaImportEclipseCaseTools::FileCaseIdMap newCaseFiles; RiaImportEclipseCaseTools::openEclipseCasesFromFile(result.files, &newCaseFiles); - for (const auto newCaseFile : newCaseFiles) + for (const auto newCaseFileAndId : newCaseFiles) { - RiaApplication::instance()->addToRecentFiles(newCaseFile); + RiaApplication::instance()->addToRecentFiles(newCaseFileAndId.first); } } diff --git a/ApplicationCode/Commands/RicImportGeneralDataFeature.cpp b/ApplicationCode/Commands/RicImportGeneralDataFeature.cpp index d84ee40e6d..18405e67b7 100644 --- a/ApplicationCode/Commands/RicImportGeneralDataFeature.cpp +++ b/ApplicationCode/Commands/RicImportGeneralDataFeature.cpp @@ -184,12 +184,12 @@ void RicImportGeneralDataFeature::openFileDialog(ImportFileType fileTypes) //-------------------------------------------------------------------------------------------------- bool RicImportGeneralDataFeature::openEclipseCaseFromFileNames(const QStringList& fileNames) { - QStringList newCaseFiles; + RiaImportEclipseCaseTools::FileCaseIdMap newCaseFiles; if (RiaImportEclipseCaseTools::openEclipseCasesFromFile(fileNames, &newCaseFiles)) { - for (const auto newCaseFile : newCaseFiles) + for (const auto newCaseFileAndId : newCaseFiles) { - RiaApplication::instance()->addToRecentFiles(newCaseFile); + RiaApplication::instance()->addToRecentFiles(newCaseFileAndId.first); } return true; } diff --git a/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto b/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto index 14246a5b02..5ed6f82204 100644 --- a/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto +++ b/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto @@ -1,12 +1,13 @@ syntax = "proto3"; +import "CaseInfo.proto"; import "Empty.proto"; package rips; service Commands { - rpc Execute(CommandParams) returns(Empty) {} + rpc Execute(CommandParams) returns(CommandReply) {} } message SetTimeStepParams @@ -58,3 +59,12 @@ message CommandParams } } +message CommandReply +{ + oneof result + { + Empty emptyResult = 1; + Case loadCaseResult = 2; + } +} + diff --git a/ApplicationCode/GrpcInterface/RiaGrpcCommandService.cpp b/ApplicationCode/GrpcInterface/RiaGrpcCommandService.cpp index 9534651fc6..09d2b5851a 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcCommandService.cpp +++ b/ApplicationCode/GrpcInterface/RiaGrpcCommandService.cpp @@ -39,7 +39,7 @@ using namespace google::protobuf; //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -grpc::Status RiaGrpcCommandService::Execute(grpc::ServerContext* context, const CommandParams* request, Empty* reply) +grpc::Status RiaGrpcCommandService::Execute(grpc::ServerContext* context, const CommandParams* request, CommandReply* reply) { auto requestDescriptor = request->GetDescriptor(); RiaLogging::info(QString::fromStdString(requestDescriptor->name())); @@ -69,19 +69,22 @@ grpc::Status RiaGrpcCommandService::Execute(grpc::ServerContext* context, const if (pdmValueFieldHandle) { RiaLogging::info(QString("Found Matching Parameter: %1").arg(parameterName)); - assignFieldValue(pdmValueFieldHandle, params, parameter); + assignPdmFieldValue(pdmValueFieldHandle, params, parameter); } } } RicfCommandResponse response = commandHandle->execute(); if (response.status() == RicfCommandResponse::COMMAND_ERROR) { - return grpc::Status(grpc::FAILED_PRECONDITION, response.message().toStdString()); + return grpc::Status(grpc::FAILED_PRECONDITION, response.message().toStdString()); } else if (response.status() == RicfCommandResponse::COMMAND_WARNING) { context->AddInitialMetadata("warning", response.message().toStdString()); } + + assignResultToReply(response.result(), reply); + return Status::OK; } } @@ -95,15 +98,15 @@ std::vector RiaGrpcCommandService::createCallbacks() { typedef RiaGrpcCommandService Self; - return {new RiaGrpcCallback(this, &Self::Execute, &Self::RequestExecute)}; + return {new RiaGrpcCallback(this, &Self::Execute, &Self::RequestExecute)}; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RiaGrpcCommandService::assignFieldValue(caf::PdmValueField* pdmValueField, - const Message& params, - const FieldDescriptor* paramDescriptor) +void RiaGrpcCommandService::assignPdmFieldValue(caf::PdmValueField* pdmValueField, + const Message& params, + const FieldDescriptor* paramDescriptor) { FieldDescriptor::Type fieldDataType = paramDescriptor->type(); QVariant qValue; @@ -116,7 +119,7 @@ void RiaGrpcCommandService::assignFieldValue(caf::PdmValueField* pdmValueFiel } case FieldDescriptor::TYPE_INT32: { int value = params.GetReflection()->GetInt32(params, paramDescriptor); - qValue = QVariant(value); + qValue = QVariant(value); break; } case FieldDescriptor::TYPE_UINT32: { @@ -126,12 +129,12 @@ void RiaGrpcCommandService::assignFieldValue(caf::PdmValueField* pdmValueFiel } case FieldDescriptor::TYPE_INT64: { int64_t value = params.GetReflection()->GetInt64(params, paramDescriptor); - qValue = QVariant((qlonglong) value); + qValue = QVariant((qlonglong)value); break; } case FieldDescriptor::TYPE_UINT64: { uint64_t value = params.GetReflection()->GetUInt64(params, paramDescriptor); - qValue = QVariant((qulonglong) value); + qValue = QVariant((qulonglong)value); break; } case FieldDescriptor::TYPE_STRING: { @@ -158,5 +161,95 @@ void RiaGrpcCommandService::assignFieldValue(caf::PdmValueField* pdmValueFiel pdmValueField->setFromQVariant(qValue); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaGrpcCommandService::assignGrpcFieldValue(google::protobuf::Message* reply, + const google::protobuf::FieldDescriptor* fieldDescriptor, + const caf::PdmValueField* pdmValueField) +{ + FieldDescriptor::Type fieldDataType = fieldDescriptor->type(); + QVariant qValue = pdmValueField->toQVariant(); + switch (fieldDataType) + { + case FieldDescriptor::TYPE_BOOL: { + reply->GetReflection()->SetBool(reply, fieldDescriptor, qValue.toBool()); + break; + } + case FieldDescriptor::TYPE_INT32: { + reply->GetReflection()->SetInt32(reply, fieldDescriptor, qValue.toInt()); + break; + } + case FieldDescriptor::TYPE_UINT32: { + reply->GetReflection()->SetUInt32(reply, fieldDescriptor, qValue.toUInt()); + break; + } + case FieldDescriptor::TYPE_INT64: { + reply->GetReflection()->SetInt64(reply, fieldDescriptor, qValue.toLongLong()); + break; + } + case FieldDescriptor::TYPE_UINT64: { + reply->GetReflection()->SetUInt64(reply, fieldDescriptor, qValue.toULongLong()); + break; + } + case FieldDescriptor::TYPE_STRING: { + reply->GetReflection()->SetString(reply, fieldDescriptor, qValue.toString().toStdString()); + break; + } + case FieldDescriptor::TYPE_FLOAT: { + reply->GetReflection()->SetFloat(reply, fieldDescriptor, qValue.toFloat()); + break; + } + case FieldDescriptor::TYPE_DOUBLE: { + reply->GetReflection()->SetDouble(reply, fieldDescriptor, qValue.toDouble()); + break; + } + case FieldDescriptor::TYPE_ENUM: { + reply->GetReflection()->SetEnumValue(reply, fieldDescriptor, qValue.toInt()); + break; + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaGrpcCommandService::assignResultToReply(const caf::PdmObject* result, CommandReply* reply) +{ + if (!result) + { + reply->set_allocated_emptyresult(new Empty); + return; + } + + QString resultType = result->classKeyword(); + + auto replyDescriptor = reply->GetDescriptor(); + auto oneofDescriptor = replyDescriptor->FindOneofByName("result"); + const FieldDescriptor* matchingOneOf = nullptr; + for (int fieldIndex = 0; fieldIndex < oneofDescriptor->field_count(); ++fieldIndex) + { + auto fieldDescriptor = oneofDescriptor->field(fieldIndex); + if (fieldDescriptor->name() == resultType.toStdString()) + { + matchingOneOf = fieldDescriptor; + break; + } + } + + CAF_ASSERT(matchingOneOf); + Message* message = reply->GetReflection()->MutableMessage(reply, matchingOneOf); + CAF_ASSERT(message); + auto resultDescriptor = message->GetDescriptor(); + + for (int fieldIndex = 0; fieldIndex < resultDescriptor->field_count(); ++fieldIndex) + { + auto fieldDescriptor = resultDescriptor->field(fieldIndex); + const auto pdmField = + dynamic_cast(result->findField(QString::fromStdString(fieldDescriptor->name()))); + assignGrpcFieldValue(message, fieldDescriptor, pdmField); + } +} + static bool RiaGrpcCommandService_init = RiaGrpcServiceFactory::instance()->registerCreator(typeid(RiaGrpcCommandService).hash_code()); diff --git a/ApplicationCode/GrpcInterface/RiaGrpcCommandService.h b/ApplicationCode/GrpcInterface/RiaGrpcCommandService.h index e11cbc080c..81914b2d1d 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcCommandService.h +++ b/ApplicationCode/GrpcInterface/RiaGrpcCommandService.h @@ -24,14 +24,10 @@ #include #include -namespace rips -{ -class Empty; -} - namespace caf { class PdmValueField; +class PdmObject; } namespace google @@ -48,11 +44,15 @@ class RiaAbstractGrpcCallback; class RiaGrpcCommandService : public rips::Commands::AsyncService, public RiaGrpcServiceInterface { public: - grpc::Status Execute(grpc::ServerContext* context, const rips::CommandParams* request, rips::Empty* reply) override; + grpc::Status Execute(grpc::ServerContext* context, const rips::CommandParams* request, rips::CommandReply* reply) override; std::vector createCallbacks() override; private: - void assignFieldValue(caf::PdmValueField* pdmValueField, - const google::protobuf::Message& params, - const google::protobuf::FieldDescriptor* paramDescriptor); + void assignPdmFieldValue(caf::PdmValueField* pdmValueField, + const google::protobuf::Message& params, + const google::protobuf::FieldDescriptor* paramDescriptor); + void assignGrpcFieldValue(google::protobuf::Message* reply, + const google::protobuf::FieldDescriptor* fieldDescriptor, + const caf::PdmValueField* pdmValueField); + void assignResultToReply(const caf::PdmObject* result, rips::CommandReply* reply); }; diff --git a/Python/api/ResInsight.py b/Python/api/ResInsight.py index b85ed9ea98..02d401dc9e 100644 --- a/Python/api/ResInsight.py +++ b/Python/api/ResInsight.py @@ -44,7 +44,7 @@ class CommandExecutor: def execute(self, commandParams): try: - self.commands.Execute(commandParams) + return self.commands.Execute(commandParams) except grpc.RpcError as e: if e.code() == grpc.StatusCode.NOT_FOUND: print("Command not found") @@ -61,7 +61,9 @@ class CommandExecutor: return self.execute(Commands_pb2.CommandParams(openProject=Commands_pb2.FilePathRequest(path=path))) def loadCase(self, path): - return self.execute(Commands_pb2.CommandParams(loadCase=Commands_pb2.FilePathRequest(path=path))) + commandReply = self.execute(Commands_pb2.CommandParams(loadCase=Commands_pb2.FilePathRequest(path=path))) + assert commandReply.HasField("loadCaseResult") + return commandReply.loadCaseResult.id def closeProject(self): return self.execute(Commands_pb2.CommandParams(closeProject=Empty())) From 79645ceed94dbb0397c770d23ab48ee2d1ebadc0 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Fri, 24 May 2019 07:55:15 +0200 Subject: [PATCH 074/396] gRPC: Fix Linux build issues --- ApplicationCode/CMakeLists.txt | 2 ++ ApplicationCode/GrpcInterface/RiaGrpcCallbacks.inl | 4 ++-- ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/ApplicationCode/CMakeLists.txt b/ApplicationCode/CMakeLists.txt index 1db2e1b44b..7b13bdf5f1 100644 --- a/ApplicationCode/CMakeLists.txt +++ b/ApplicationCode/CMakeLists.txt @@ -321,6 +321,8 @@ if (MSVC) endif(RESINSIGHT_ENABLE_GRPC) elseif (APPLE) set( EXE_FILES MACOSX_BUNDLE) +else() + set_source_files_properties(${GRPC_CPP_SOURCES} PROPERTIES COMPILE_FLAGS "-Woverloaded-virtual") endif() set( EXE_FILES ${EXE_FILES} diff --git a/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.inl b/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.inl index 059eb72d2c..4bc11a8bdb 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.inl +++ b/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.inl @@ -298,7 +298,7 @@ void RiaGrpcClientStreamCallback::onI this->setNextCallState(RiaAbstractGrpcCallback::INIT_REQUEST_COMPLETED); // The read call will start reading the request data and push this callback back onto the command queue // when the read call is completed. - m_reader.Read(&m_request, this); + m_reader.Read(&this->m_request, this); } //-------------------------------------------------------------------------------------------------- @@ -320,7 +320,7 @@ void RiaGrpcClientStreamCallback::onI } // Start reading and push this back onto the command queue. - m_reader.Read(&m_request, this); + m_reader.Read(&this->m_request, this); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp b/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp index 8d3bcf06b4..07817130c8 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp +++ b/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp @@ -75,7 +75,7 @@ public: if (resultData->ensureKnownResultLoaded(resAddr)) { - if (timeStep < (int)resultData->timeStepCount(resAddr)) + if (timeStep < resultData->timeStepCount(resAddr)) { initResultAccess(caseData, request->grid_index(), porosityModel, timeStep, resAddr); return grpc::Status::OK; From e8a54d8aa8ce6e4d60bf630fbd20935e4af7c24c Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Fri, 24 May 2019 08:53:29 +0200 Subject: [PATCH 075/396] Fix build issues following command feature changes --- .../RicExportCompletionDataSettingsUi.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ApplicationCode/Commands/CompletionExportCommands/RicExportCompletionDataSettingsUi.h b/ApplicationCode/Commands/CompletionExportCommands/RicExportCompletionDataSettingsUi.h index f9c72863d6..94d3bc1658 100644 --- a/ApplicationCode/Commands/CompletionExportCommands/RicExportCompletionDataSettingsUi.h +++ b/ApplicationCode/Commands/CompletionExportCommands/RicExportCompletionDataSettingsUi.h @@ -32,6 +32,7 @@ class RicExportCompletionDataSettingsUi : public RicCaseAndFileExportSettingsUi { CAF_PDM_HEADER_INIT; public: + // Exported in .proto file. Do not change without changing .proto enum ExportSplit { UNIFIED_FILE, SPLIT_ON_WELL, @@ -39,6 +40,7 @@ public: }; typedef caf::AppEnum ExportSplitType; + // Exported in .proto file. Do not change without changing .proto enum CompdatExport { TRANSMISSIBILITIES, WPIMULT_AND_DEFAULT_CONNECTION_FACTORS, @@ -49,6 +51,7 @@ public: }; typedef caf::AppEnum CompdatExportType; + // Exported in .proto file. Do not change without changing .proto enum CombinationMode { INDIVIDUALLY, From c2996bf63876e86ecca700a267899df1dbb1afe9 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Fri, 24 May 2019 08:58:04 +0200 Subject: [PATCH 076/396] Further build fixes related to RiaLogging --- .../RicfExportSnapshots.h | 1 + .../CommandFileInterface/RicfSetStartDir.cpp | 1 + .../RicSaveEclipseInputPropertyFeature.cpp | 1 + .../GrpcInterface/GrpcProtos/Commands.proto | 123 +++++++++++++++--- 4 files changed, 105 insertions(+), 21 deletions(-) diff --git a/ApplicationCode/CommandFileInterface/RicfExportSnapshots.h b/ApplicationCode/CommandFileInterface/RicfExportSnapshots.h index 0c302e3a82..2d2a706043 100644 --- a/ApplicationCode/CommandFileInterface/RicfExportSnapshots.h +++ b/ApplicationCode/CommandFileInterface/RicfExportSnapshots.h @@ -33,6 +33,7 @@ class RicfExportSnapshots : public RicfCommandObject CAF_PDM_HEADER_INIT; public: + // Values are exposed in gRPC .proto. Do not change without also changing .proto enum SnapshotsType { VIEWS, diff --git a/ApplicationCode/CommandFileInterface/RicfSetStartDir.cpp b/ApplicationCode/CommandFileInterface/RicfSetStartDir.cpp index 812fe7646b..31a66b1787 100644 --- a/ApplicationCode/CommandFileInterface/RicfSetStartDir.cpp +++ b/ApplicationCode/CommandFileInterface/RicfSetStartDir.cpp @@ -19,6 +19,7 @@ #include "RicfSetStartDir.h" #include "RiaApplication.h" +#include "RiaLogging.h" #include diff --git a/ApplicationCode/Commands/ExportCommands/RicSaveEclipseInputPropertyFeature.cpp b/ApplicationCode/Commands/ExportCommands/RicSaveEclipseInputPropertyFeature.cpp index 7bd9cb2ea1..ecdfd1435c 100644 --- a/ApplicationCode/Commands/ExportCommands/RicSaveEclipseInputPropertyFeature.cpp +++ b/ApplicationCode/Commands/ExportCommands/RicSaveEclipseInputPropertyFeature.cpp @@ -20,6 +20,7 @@ #include "RicSaveEclipseInputPropertyFeature.h" #include "RiaApplication.h" +#include "RiaLogging.h" #include "RicExportFeatureImpl.h" #include "RicEclipseCellResultToFileImpl.h" diff --git a/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto b/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto index 5ed6f82204..88971c0417 100644 --- a/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto +++ b/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto @@ -10,18 +10,6 @@ service Commands rpc Execute(CommandParams) returns(CommandReply) {} } -message SetTimeStepParams -{ - int32 caseId = 1; - int32 timeStep = 2; -} - -message SetMainWindowSizeParams -{ - int32 height = 1; - int32 width = 2; -} - message FilePathRequest { string path = 1; @@ -43,19 +31,112 @@ message ExportMultiCaseRequest string gridListFile = 1; } +enum SnapshotType +{ + VIEWS = 0; + PLOTS = 1; + ALL = 2; +} + +message ExportSnapshotsRequest +{ + SnapshotType type = 1; + string prefix = 2; +} + +message ExportPropertyRequest +{ + int32 caseId = 1; + int32 timeStep = 2; + string property = 3; + string eclipseKeyword = 4; + double undefinedValue = 5; + string exportFile = 6; +} + +message ExportPropertyInViewsRequest +{ + int32 caseId = 1; + repeated string viewNames = 2; + double undefinedValue = 3; +} + +enum CompdatExportSplit +{ + UNIFIED_FILE = 0; + SPLIT_ON_WELL = 1; + SPLIT_ON_WELL_AND_COMPLETION_TYPE = 2; +} + +enum CompdatExportType +{ + TRANSMISSIBILITIES = 0; + WPIMULT_AND_DEFAULT_CONNECTION_FACTORS = 1; + NO_COMPLETIONS = 2; +} + +enum CompdatCombinationMode +{ + INDIVIDUALLY = 0; + COMBINED = 1; +} + +message ExportWellPathCompRequest +{ + int32 caseId = 1; + int32 timeStep = 2; + repeated string wellPathNames = 3; + CompdatExportSplit fileSplit = 4; + CompdatExportType compdatExport = 5; + bool includePerforations = 6; + bool includeFishbones = 7; + bool excludeMainBoreForFishbones = 8; + CompdatCombinationMode combinationMode = 9; +} + + +message SetTimeStepParams +{ + int32 caseId = 1; + int32 timeStep = 2; +} + +message SetMainWindowSizeParams +{ + int32 height = 1; + int32 width = 2; +} + + message CommandParams { oneof params { - SetTimeStepParams setTimeStep = 1; - SetMainWindowSizeParams setMainWindowSize = 2; - FilePathRequest openProject = 3; - Empty closeProject = 4; - FilePathRequest setStartDir = 5; - FilePathRequest loadCase = 6; - ReplaceCaseRequest replaceCase = 7; - ReplaceSourceCasesRequest replaceSourceCases = 8; - ExportMultiCaseRequest exportMultiCaseSnapshots = 9; + FilePathRequest openProject = 1; + Empty closeProject = 2; + FilePathRequest setStartDir = 3; + FilePathRequest loadCase = 4; + ReplaceCaseRequest replaceCase = 5; + ReplaceSourceCasesRequest replaceSourceCases = 6; + ExportMultiCaseRequest exportMultiCaseSnapshots = 7; + ExportSnapshotsRequest exportSnapshots = 8; + ExportPropertyRequest exportProperty = 9; + ExportPropertyInViewsRequest exportPropertyInViews = 10; + ExportWellPathCompRequest exportWellPathCompletions = 11; + //ExportSimWellPathFracRequest exportSimWellFractureCompletions = 12; + //ExportMswRequest exportMsw = 13; + //ExportWellPathRequest exportWellPaths = 14; + //ExportVisibleCellsRequest exportVisibleCells = 15; + //SetExportFolderRequest setExportFolder = 16; + //RunOctaveScriptRequest runOctaveScript = 17; + SetMainWindowSizeParams setMainWindowSize = 18; + //ComputeCaseGroupStatRequest computeCaseGroupStatistics = 19; + SetTimeStepParams setTimeStep = 20; + //ScaleFractureTemplateRequest scaleFractureTemplate = 21; + //SetFracContainmentRequest setFractureContainment = 22; + //CreateMultipleFracRequest createMultipleFractures = 23; + //CreateLgrForCompRequest createLgrForCompletions = 24; + //CreateSatPressPlotRequest createSaturationPressurePlots = 25; } } From 3345eb5170ed8fd4694b25b44183517a0d400969 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Fri, 24 May 2019 09:17:57 +0200 Subject: [PATCH 077/396] Fix unit tests following CommandObject::execute changes --- .../UnitTests/RifcCommandCore-Test.cpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/ApplicationCode/UnitTests/RifcCommandCore-Test.cpp b/ApplicationCode/UnitTests/RifcCommandCore-Test.cpp index 020f873705..aa342003c8 100644 --- a/ApplicationCode/UnitTests/RifcCommandCore-Test.cpp +++ b/ApplicationCode/UnitTests/RifcCommandCore-Test.cpp @@ -19,10 +19,12 @@ public: RICF_InitField(&m_boolArgument, "BoolArgument", false, "BoolArgument", "", "", ""); } - void execute() override { std::cout << "TestCommand1::execute(" << "\"" << m_textArgument().toStdString() << "\", " - << m_doubleArgument() << ", " - << m_intArgument << ", " - << m_boolArgument << ");" << std::endl; } + RicfCommandResponse execute() override { + std::cout << "TestCommand1::execute(" + << "\"" << m_textArgument().toStdString() << "\", " << m_doubleArgument() << ", " << m_intArgument << ", " + << m_boolArgument << ");" << std::endl; + return RicfCommandResponse(); + } caf::PdmField m_textArgument; caf::PdmField m_doubleArgument; @@ -45,9 +47,13 @@ public: RICF_InitField(&m_boolArgument, "ba", false,"BoolArgument", "", "", ""); } - void execute() override { std::cout << "TC2::execute(" << "\"" << m_textArgument().toStdString() << "\", " + RicfCommandResponse execute() override + { + std::cout << "TC2::execute(" << "\"" << m_textArgument().toStdString() << "\", " << m_doubleArgument() << ", " - << m_intArgument() << ", " << m_boolArgument() << ");" << std::endl; } + << m_intArgument() << ", " << m_boolArgument() << ");" << std::endl; + return RicfCommandResponse(); + } caf::PdmField m_textArgument; caf::PdmField m_doubleArgument; From 7b88d71f70f06bf5e2bebeca61c59c4e55c49893 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 24 May 2019 11:21:04 +0200 Subject: [PATCH 078/396] Upped to 2019.04.0-dev.02 --- ResInsightVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ResInsightVersion.cmake b/ResInsightVersion.cmake index fa44eb6d43..bc584775b5 100644 --- a/ResInsightVersion.cmake +++ b/ResInsightVersion.cmake @@ -10,7 +10,7 @@ set(RESINSIGHT_VERSION_TEXT "-dev") # 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 ".01") +set(RESINSIGHT_DEV_VERSION ".02") # https://github.com/CRAVA/crava/tree/master/libs/nrlib set(NRLIB_GITHUB_SHA "ba35d4359882f1c6f5e9dc30eb95fe52af50fd6f") From c7f8edad04e380cb283c26776ff3ce57c1836da4 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Fri, 24 May 2019 11:13:12 +0200 Subject: [PATCH 079/396] #4428 implement all command file commands as gRPC services --- .../GrpcInterface/GrpcProtos/Commands.proto | 160 ++++++++++++++++-- 1 file changed, 144 insertions(+), 16 deletions(-) diff --git a/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto b/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto index 88971c0417..1465550aa2 100644 --- a/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto +++ b/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto @@ -5,6 +5,10 @@ import "Empty.proto"; package rips; +/* + * The Commands service handles generic ResInsight RicfCommandObject-commands + * The CommandParams is used to deduce command name from the chosen oneof-message + * .. and the parameters are in the oneof-message itself. */ service Commands { rpc Execute(CommandParams) returns(CommandReply) {} @@ -94,11 +98,59 @@ message ExportWellPathCompRequest CompdatCombinationMode combinationMode = 9; } - -message SetTimeStepParams +message ExportSimWellPathFracRequest { - int32 caseId = 1; - int32 timeStep = 2; + int32 caseId = 1; + string viewName = 2; + int32 timeStep = 3; + repeated string simulationWellNames = 4; + CompdatExportSplit fileSplit = 5; + CompdatExportType compdatExport = 6; +} + +message ExportMswRequest +{ + int32 caseId = 1; + string wellPath = 2; +} + +message ExportWellPathRequest +{ + repeated string wellPathNames = 1; + double mdStepSize = 2; +} + +message ExportVisibleCellsRequest +{ + int32 caseId = 1; + string viewName = 2; + string exportKeyword = 3; + int32 visibleActiveCellsValue = 4; + int32 hiddenActiveCellsValue = 5; + int32 inactiveCellsValue = 6; +} + +enum ExportFolderType { + COMPLETIONS = 0; + SNAPSHOTS = 1; + PROPERTIES = 2; + STATISTICS = 3; + WELLPATHS = 4; + CELLS = 5; + LGRS = 6; +} + +message SetExportFolderRequest +{ + ExportFolderType type = 1; + string path = 2; + bool createFolder = 3; +} + +message RunOctaveScriptRequest +{ + string path = 1; + repeated int32 caseIds = 2; } message SetMainWindowSizeParams @@ -107,9 +159,83 @@ message SetMainWindowSizeParams int32 width = 2; } +message ComputeCaseGroupStatRequest +{ + repeated int32 caseIds = 1; +} +message SetTimeStepParams +{ + int32 caseId = 1; + int32 timeStep = 2; +} + +message ScaleFractureTemplateRequest +{ + int32 id = 1; + double halfLength = 2; + double height = 3; +} + +message SetFracContainmentRequest +{ + int32 id = 1; + int32 topLayer = 2; + int32 baseLayer = 3; +} + +enum MultipleFracAction +{ + NONE = 0; + APPEND_FRACTURES = 1; + REPLACE_FRACTURES = 2; +} + +message CreateMultipleFracRequest +{ + int32 caseId = 1; + int32 templateId = 2; + repeated string wellPathNames = 3; + double minDistFromWellTd = 4; + int32 maxFracturesPerWell = 5; + int32 topLayer = 6; + int32 baseLayer = 7; + int32 spacing = 8; + MultipleFracAction action = 9; +} + +enum LgrSplitType +{ + LGR_PER_CELL = 0; + LGR_PER_COMPLETION = 1; + LGR_PER_WELL = 2; +} + +message CreateLgrForCompRequest +{ + int32 caseId = 1; + int32 timeStep = 2; + repeated string wellPathNames = 3; + int32 refinementI = 4; + int32 refinementJ = 5; + int32 refinementK = 6; + LgrSplitType splitType = 7; +} + +message CreateSatPressPlotRequest +{ + repeated int32 caseIds = 1; +} + +/* CommandParams handles both command name and parameters in one. + * The message type and content is used as parameters and + * the name of the variable is used to find the command name. */ message CommandParams { + /* Since only one of these oneof-parameters can be set, we know which + * command to run from the name of parameter. I.e. if openProject is set + * we will run the RicfOpenProject command with the parameters set in + * the FilePathRequest message. */ oneof params { FilePathRequest openProject = 1; @@ -123,23 +249,25 @@ message CommandParams ExportPropertyRequest exportProperty = 9; ExportPropertyInViewsRequest exportPropertyInViews = 10; ExportWellPathCompRequest exportWellPathCompletions = 11; - //ExportSimWellPathFracRequest exportSimWellFractureCompletions = 12; - //ExportMswRequest exportMsw = 13; - //ExportWellPathRequest exportWellPaths = 14; - //ExportVisibleCellsRequest exportVisibleCells = 15; - //SetExportFolderRequest setExportFolder = 16; - //RunOctaveScriptRequest runOctaveScript = 17; + ExportSimWellPathFracRequest exportSimWellFractureCompletions = 12; + ExportMswRequest exportMsw = 13; + ExportWellPathRequest exportWellPaths = 14; + ExportVisibleCellsRequest exportVisibleCells = 15; + SetExportFolderRequest setExportFolder = 16; + RunOctaveScriptRequest runOctaveScript = 17; SetMainWindowSizeParams setMainWindowSize = 18; - //ComputeCaseGroupStatRequest computeCaseGroupStatistics = 19; + ComputeCaseGroupStatRequest computeCaseGroupStatistics = 19; SetTimeStepParams setTimeStep = 20; - //ScaleFractureTemplateRequest scaleFractureTemplate = 21; - //SetFracContainmentRequest setFractureContainment = 22; - //CreateMultipleFracRequest createMultipleFractures = 23; - //CreateLgrForCompRequest createLgrForCompletions = 24; - //CreateSatPressPlotRequest createSaturationPressurePlots = 25; + ScaleFractureTemplateRequest scaleFractureTemplate = 21; + SetFracContainmentRequest setFractureContainment = 22; + CreateMultipleFracRequest createMultipleFractures = 23; + CreateLgrForCompRequest createLgrForCompletions = 24; + CreateSatPressPlotRequest createSaturationPressurePlots = 25; } } +/* Command reply handles the return values for the generic command + * The name of the variable is used to map to the cafPdmObject classKeyword */ message CommandReply { oneof result From af054fb95ef62e88865de35cf9d792388943c823 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Fri, 24 May 2019 12:19:44 +0200 Subject: [PATCH 080/396] #4428 Implement support for repeated fields as parameters and add exportWellPaths to client library --- .../GrpcInterface/RiaGrpcCommandService.cpp | 118 ++++++++++++------ .../GrpcInterface/RiaGrpcCommandService.h | 6 + Python/api/ResInsight.py | 23 ++-- Python/examples/CommandExample.py | 3 +- 4 files changed, 106 insertions(+), 44 deletions(-) diff --git a/ApplicationCode/GrpcInterface/RiaGrpcCommandService.cpp b/ApplicationCode/GrpcInterface/RiaGrpcCommandService.cpp index 09d2b5851a..683187c066 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcCommandService.cpp +++ b/ApplicationCode/GrpcInterface/RiaGrpcCommandService.cpp @@ -25,7 +25,9 @@ #include "cafAssert.h" #include "cafPdmDefaultObjectFactory.h" +#include "cafPdmDataValueField.h" #include "cafPdmValueField.h" +#include using namespace rips; using namespace google::protobuf; @@ -101,6 +103,29 @@ std::vector RiaGrpcCommandService::createCallbacks() return {new RiaGrpcCallback(this, &Self::Execute, &Self::RequestExecute)}; } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +template +caf::PdmField* RiaGrpcCommandService::dataValueField(caf::PdmValueField* valueField) +{ + caf::PdmField* dataValField = dynamic_cast*>(valueField); + CAF_ASSERT(dataValField); + return dataValField; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +template +const caf::PdmField* RiaGrpcCommandService::constDataValueField(const caf::PdmValueField* valueField) +{ + const caf::PdmField* dataValField = dynamic_cast*>(valueField); + CAF_ASSERT(dataValField); + return dataValField; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -109,56 +134,77 @@ void RiaGrpcCommandService::assignPdmFieldValue(caf::PdmValueField* pdmValueF const FieldDescriptor* paramDescriptor) { FieldDescriptor::Type fieldDataType = paramDescriptor->type(); - QVariant qValue; + const Reflection* reflection = params.GetReflection(); + switch (fieldDataType) { case FieldDescriptor::TYPE_BOOL: { - auto value = params.GetReflection()->GetBool(params, paramDescriptor); - qValue = QVariant(value); + auto value = reflection->GetBool(params, paramDescriptor); + auto dataField = dataValueField(pdmValueField); + dataField->setValue(value); break; } case FieldDescriptor::TYPE_INT32: { - int value = params.GetReflection()->GetInt32(params, paramDescriptor); - qValue = QVariant(value); + if (paramDescriptor->is_repeated()) + { + RepeatedFieldRef repeatedField = + reflection->GetRepeatedFieldRef(params, paramDescriptor); + auto dataField = dataValueField>(pdmValueField); + dataField->setValue(std::vector(repeatedField.begin(), repeatedField.end())); + } + else + { + int value = reflection->GetInt32(params, paramDescriptor); + auto dataField = dataValueField(pdmValueField); + dataField->setValue(value); + } break; } case FieldDescriptor::TYPE_UINT32: { - uint value = params.GetReflection()->GetUInt32(params, paramDescriptor); - qValue = QVariant(value); - break; - } - case FieldDescriptor::TYPE_INT64: { - int64_t value = params.GetReflection()->GetInt64(params, paramDescriptor); - qValue = QVariant((qlonglong)value); - break; - } - case FieldDescriptor::TYPE_UINT64: { - uint64_t value = params.GetReflection()->GetUInt64(params, paramDescriptor); - qValue = QVariant((qulonglong)value); + uint value = reflection->GetUInt32(params, paramDescriptor); + auto dataField = dataValueField(pdmValueField); + dataField->setValue(value); break; } case FieldDescriptor::TYPE_STRING: { - auto value = params.GetReflection()->GetString(params, paramDescriptor); - qValue = QVariant(QString::fromStdString(value)); + if (paramDescriptor->is_repeated()) + { + RepeatedFieldRef repeatedField = + reflection->GetRepeatedFieldRef(params, paramDescriptor); + std::vector stringVector; + for (const std::string& string : repeatedField) + { + stringVector.push_back(QString::fromStdString(string)); + } + auto dataField = dataValueField>(pdmValueField); + dataField->setValue(stringVector); + } + else + { + auto value = QString::fromStdString(reflection->GetString(params, paramDescriptor)); + auto dataField = dataValueField(pdmValueField); + dataField->setValue(value); + } break; } case FieldDescriptor::TYPE_FLOAT: { - auto value = params.GetReflection()->GetFloat(params, paramDescriptor); - qValue = QVariant(value); + auto value = reflection->GetFloat(params, paramDescriptor); + auto dataField = dataValueField(pdmValueField); + dataField->setValue(value); break; } case FieldDescriptor::TYPE_DOUBLE: { - auto value = params.GetReflection()->GetDouble(params, paramDescriptor); - qValue = QVariant(value); + auto value = reflection->GetDouble(params, paramDescriptor); + auto dataField = dataValueField(pdmValueField); + dataField->setValue(value); break; } case FieldDescriptor::TYPE_ENUM: { - auto value = params.GetReflection()->GetEnumValue(params, paramDescriptor); - qValue = QVariant(value); + auto value = reflection->GetEnumValue(params, paramDescriptor); + pdmValueField->setFromQVariant(QVariant(value)); break; } } - pdmValueField->setFromQVariant(qValue); } //-------------------------------------------------------------------------------------------------- @@ -170,42 +216,44 @@ void RiaGrpcCommandService::assignGrpcFieldValue(google::protobuf::Message* { FieldDescriptor::Type fieldDataType = fieldDescriptor->type(); QVariant qValue = pdmValueField->toQVariant(); + + auto reflection = reply->GetReflection(); switch (fieldDataType) { case FieldDescriptor::TYPE_BOOL: { - reply->GetReflection()->SetBool(reply, fieldDescriptor, qValue.toBool()); + reflection->SetBool(reply, fieldDescriptor, qValue.toBool()); break; } case FieldDescriptor::TYPE_INT32: { - reply->GetReflection()->SetInt32(reply, fieldDescriptor, qValue.toInt()); + reflection->SetInt32(reply, fieldDescriptor, qValue.toInt()); break; } case FieldDescriptor::TYPE_UINT32: { - reply->GetReflection()->SetUInt32(reply, fieldDescriptor, qValue.toUInt()); + reflection->SetUInt32(reply, fieldDescriptor, qValue.toUInt()); break; } case FieldDescriptor::TYPE_INT64: { - reply->GetReflection()->SetInt64(reply, fieldDescriptor, qValue.toLongLong()); + reflection->SetInt64(reply, fieldDescriptor, qValue.toLongLong()); break; } case FieldDescriptor::TYPE_UINT64: { - reply->GetReflection()->SetUInt64(reply, fieldDescriptor, qValue.toULongLong()); + reflection->SetUInt64(reply, fieldDescriptor, qValue.toULongLong()); break; } case FieldDescriptor::TYPE_STRING: { - reply->GetReflection()->SetString(reply, fieldDescriptor, qValue.toString().toStdString()); + reflection->SetString(reply, fieldDescriptor, qValue.toString().toStdString()); break; } case FieldDescriptor::TYPE_FLOAT: { - reply->GetReflection()->SetFloat(reply, fieldDescriptor, qValue.toFloat()); + reflection->SetFloat(reply, fieldDescriptor, qValue.toFloat()); break; } case FieldDescriptor::TYPE_DOUBLE: { - reply->GetReflection()->SetDouble(reply, fieldDescriptor, qValue.toDouble()); + reflection->SetDouble(reply, fieldDescriptor, qValue.toDouble()); break; } case FieldDescriptor::TYPE_ENUM: { - reply->GetReflection()->SetEnumValue(reply, fieldDescriptor, qValue.toInt()); + reflection->SetEnumValue(reply, fieldDescriptor, qValue.toInt()); break; } } diff --git a/ApplicationCode/GrpcInterface/RiaGrpcCommandService.h b/ApplicationCode/GrpcInterface/RiaGrpcCommandService.h index 81914b2d1d..d763f5b751 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcCommandService.h +++ b/ApplicationCode/GrpcInterface/RiaGrpcCommandService.h @@ -28,6 +28,8 @@ namespace caf { class PdmValueField; class PdmObject; +template +class PdmField; } namespace google @@ -48,6 +50,10 @@ public: std::vector createCallbacks() override; private: + template + static caf::PdmField* dataValueField(caf::PdmValueField* valueField); + template + static const caf::PdmField* constDataValueField(const caf::PdmValueField* valueField); void assignPdmFieldValue(caf::PdmValueField* pdmValueField, const google::protobuf::Message& params, const google::protobuf::FieldDescriptor* paramDescriptor); diff --git a/Python/api/ResInsight.py b/Python/api/ResInsight.py index 02d401dc9e..5ae13daec2 100644 --- a/Python/api/ResInsight.py +++ b/Python/api/ResInsight.py @@ -12,8 +12,8 @@ sys.path.insert(1, os.path.join(sys.path[0], '../generated')) from Empty_pb2 import Empty import CaseInfo_pb2 import CaseInfo_pb2_grpc -import Commands_pb2 -import Commands_pb2_grpc +import Commands_pb2 as Cmd +import Commands_pb2_grpc as CmdRpc import GridInfo_pb2 import GridInfo_pb2_grpc import ProjectInfo_pb2 @@ -40,7 +40,7 @@ class ResInfo: class CommandExecutor: def __init__(self, channel): - self.commands = Commands_pb2_grpc.CommandsStub(channel) + self.commands = CmdRpc.CommandsStub(channel) def execute(self, commandParams): try: @@ -52,21 +52,28 @@ class CommandExecutor: print("Other error") def setTimeStep(self, caseId, timeStep): - return self.execute(Commands_pb2.CommandParams(setTimeStep=Commands_pb2.SetTimeStepParams(caseId=caseId, timeStep=timeStep))) + return self.execute(Cmd.CommandParams(setTimeStep=Cmd.SetTimeStepParams(caseId=caseId, timeStep=timeStep))) def setMainWindowSize(self, width, height): - return self.execute(Commands_pb2.CommandParams(setMainWindowSize=Commands_pb2.SetMainWindowSizeParams(width=width, height=height))) + return self.execute(Cmd.CommandParams(setMainWindowSize=Cmd.SetMainWindowSizeParams(width=width, height=height))) def openProject(self, path): - return self.execute(Commands_pb2.CommandParams(openProject=Commands_pb2.FilePathRequest(path=path))) + return self.execute(Cmd.CommandParams(openProject=Cmd.FilePathRequest(path=path))) def loadCase(self, path): - commandReply = self.execute(Commands_pb2.CommandParams(loadCase=Commands_pb2.FilePathRequest(path=path))) + commandReply = self.execute(Cmd.CommandParams(loadCase=Cmd.FilePathRequest(path=path))) assert commandReply.HasField("loadCaseResult") return commandReply.loadCaseResult.id def closeProject(self): - return self.execute(Commands_pb2.CommandParams(closeProject=Empty())) + return self.execute(Cmd.CommandParams(closeProject=Empty())) + + def exportWellPaths(self, wellPaths=[], mdStepSize=5.0): + if isinstance(wellPaths, str): + wellPathArray = [str] + elif isinstance(wellPaths, list): + wellPathArray = wellPaths + return self.execute(Cmd.CommandParams(exportWellPaths=Cmd.ExportWellPathRequest(wellPathNames=wellPathArray, mdStepSize=mdStepSize))) class GridInfo: def __init__(self, channel): diff --git a/Python/examples/CommandExample.py b/Python/examples/CommandExample.py index cca0159775..f34fdd8a9d 100644 --- a/Python/examples/CommandExample.py +++ b/Python/examples/CommandExample.py @@ -8,4 +8,5 @@ resInsight = ResInsight.Instance.find() # Run a couple of commands resInsight.commands.setTimeStep(caseId=0, timeStep=3) -resInsight.commands.setMainWindowSize(width=800, height=500) \ No newline at end of file +resInsight.commands.setMainWindowSize(width=800, height=500) +resInsight.commands.exportWellPaths() \ No newline at end of file From 7c475e72e48d2ffec66fb5778e7e1a0d28a9801c Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Wed, 22 May 2019 19:31:12 +0200 Subject: [PATCH 081/396] gRPC: Add SetResultValues.py example --- ApplicationCode/GrpcInterface/CMakeLists.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/ApplicationCode/GrpcInterface/CMakeLists.cmake b/ApplicationCode/GrpcInterface/CMakeLists.cmake index 5d09be5bb4..f3e6e911b8 100644 --- a/ApplicationCode/GrpcInterface/CMakeLists.cmake +++ b/ApplicationCode/GrpcInterface/CMakeLists.cmake @@ -150,6 +150,7 @@ if (PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) "examples/ResultValues.py" "examples/SelectedCases.py" "examples/AllCases.py" + "examples/SetResultValues.py" "tests/test_sample.py" ) From 9ac15ec55350cac99356822f73c1f96a0158fec6 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Wed, 22 May 2019 19:58:12 +0200 Subject: [PATCH 082/396] gRPC: Add SetGridProperties.py example --- .../GrpcInterface/RiaGrpcPropertiesService.cpp | 16 +++++++++++++++- .../GrpcInterface/RiaGrpcPropertiesService.h | 14 +++++++++----- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp b/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp index 07817130c8..c59c4e560a 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp +++ b/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp @@ -288,6 +288,17 @@ grpc::Status RiaGrpcPropertiesService::SetActiveCellResults(grpc::ServerContext* return stateHandler->receiveStreamRequest(request); } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +grpc::Status RiaGrpcPropertiesService::SetGridResults(grpc::ServerContext* context, + const rips::ResultRequestChunk* request, + rips::Empty* reply, + RiaGridCellResultsStateHandler* stateHandler) +{ + return stateHandler->receiveStreamRequest(request); +} //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -302,9 +313,12 @@ std::vector RiaGrpcPropertiesService::createCallbacks( new RiaGrpcStreamCallback( this, &Self::GetGridResults, &Self::RequestGetGridResults, new RiaGridCellResultsStateHandler), new RiaGrpcClientStreamCallback( - this, &Self::SetActiveCellResults, &Self::RequestSetActiveCellResults, new RiaActiveCellResultsStateHandler) + this, &Self::SetActiveCellResults, &Self::RequestSetActiveCellResults, new RiaActiveCellResultsStateHandler), + new RiaGrpcClientStreamCallback( + this, &Self::SetGridResults, &Self::RequestSetGridResults, new RiaGridCellResultsStateHandler) }; } + static bool RiaGrpcPropertiesService_init = RiaGrpcServiceFactory::instance()->registerCreator(typeid(RiaGrpcPropertiesService).hash_code()); \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.h b/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.h index c62d83f2d3..2fee1d0833 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.h +++ b/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.h @@ -34,21 +34,25 @@ class RiaGridCellResultsStateHandler; class RiaGrpcPropertiesService final : public rips::Properties::AsyncService, public RiaGrpcServiceInterface { public: - grpc::Status GetAvailableProperties(grpc::ServerContext* context, + grpc::Status GetAvailableProperties(grpc::ServerContext* context, const rips::PropertiesRequest* request, - rips::AvailableProperties* reply) override; + rips::AvailableProperties* reply) override; grpc::Status GetActiveCellResults(grpc::ServerContext* context, const rips::ResultRequest* request, - rips::ResultArray* reply, + rips::ResultArray* reply, RiaActiveCellResultsStateHandler* stateHandler); grpc::Status GetGridResults(grpc::ServerContext* context, const rips::ResultRequest* request, - rips::ResultArray* reply, + rips::ResultArray* reply, RiaGridCellResultsStateHandler* stateHandler); grpc::Status SetActiveCellResults(grpc::ServerContext* context, const rips::ResultRequestChunk* request, rips::Empty* reply, RiaActiveCellResultsStateHandler* stateHandler); + grpc::Status SetGridResults(grpc::ServerContext* context, + const rips::ResultRequestChunk* request, + rips::Empty* reply, + RiaGridCellResultsStateHandler* stateHandler); + std::vector createCallbacks() override; }; - From c9d56bda9cde941b6864527d79638e8d56024fad Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Wed, 22 May 2019 20:23:49 +0200 Subject: [PATCH 083/396] gRPC: Move all python code into the ApplicationCode/GrpcInterface folder --- ApplicationCode/CMakeLists.txt | 3 --- .../GrpcInterface/CMakeLists.cmake | 11 ++++++--- .../GrpcInterface/Python}/.gitignore | 0 .../GrpcInterface/Python}/api/ResInsight.py | 24 ++++++++++++++----- .../GrpcInterface/Python}/api/__init__.py | 0 .../Python}/examples/AllCases.py | 0 .../Python}/examples/CommandExample.py | 0 .../examples/GridInfoStreamingExample.py | 0 .../Python}/examples/ResultValues.py | 0 .../Python}/examples/SelectedCases.py | 0 .../examples/SetActiveCellProperties.py | 0 .../Python/examples/SetGridProperties.py | 16 +++++++++++++ .../Python}/tests/test_sample.py | 0 13 files changed, 42 insertions(+), 12 deletions(-) rename {Python => ApplicationCode/GrpcInterface/Python}/.gitignore (100%) rename {Python => ApplicationCode/GrpcInterface/Python}/api/ResInsight.py (90%) rename {Python => ApplicationCode/GrpcInterface/Python}/api/__init__.py (100%) rename {Python => ApplicationCode/GrpcInterface/Python}/examples/AllCases.py (100%) rename {Python => ApplicationCode/GrpcInterface/Python}/examples/CommandExample.py (100%) rename {Python => ApplicationCode/GrpcInterface/Python}/examples/GridInfoStreamingExample.py (100%) rename {Python => ApplicationCode/GrpcInterface/Python}/examples/ResultValues.py (100%) rename {Python => ApplicationCode/GrpcInterface/Python}/examples/SelectedCases.py (100%) rename Python/examples/SetResultValues.py => ApplicationCode/GrpcInterface/Python/examples/SetActiveCellProperties.py (100%) create mode 100644 ApplicationCode/GrpcInterface/Python/examples/SetGridProperties.py rename {Python => ApplicationCode/GrpcInterface/Python}/tests/test_sample.py (100%) diff --git a/ApplicationCode/CMakeLists.txt b/ApplicationCode/CMakeLists.txt index 7b13bdf5f1..2daa688287 100644 --- a/ApplicationCode/CMakeLists.txt +++ b/ApplicationCode/CMakeLists.txt @@ -23,9 +23,6 @@ endif(Qt5Core_FOUND) CONFIGURE_FILE( ${CMAKE_SOURCE_DIR}/ApplicationCode/Adm/RiaVersionInfo.h.cmake ${CMAKE_BINARY_DIR}/Generated/RiaVersionInfo.h ) -CONFIGURE_FILE( ${CMAKE_SOURCE_DIR}/ApplicationCode/Adm/RiaVersionInfo.py.cmake - ${CMAKE_SOURCE_DIR}/Python/generated/RiaVersionInfo.py -) if (MSVC AND (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 19.11)) # VS 2017 : Disable warnings from from gtest code, using deprecated code related to TR1 diff --git a/ApplicationCode/GrpcInterface/CMakeLists.cmake b/ApplicationCode/GrpcInterface/CMakeLists.cmake index f3e6e911b8..ccb0d89738 100644 --- a/ApplicationCode/GrpcInterface/CMakeLists.cmake +++ b/ApplicationCode/GrpcInterface/CMakeLists.cmake @@ -79,7 +79,7 @@ set(PROTO_FILES "Properties" ) -set(GRPC_PYTHON_SOURCE_PATH "${CMAKE_SOURCE_DIR}/Python") +set(GRPC_PYTHON_SOURCE_PATH "${CMAKE_CURRENT_LIST_DIR}/Python") set(GRPC_PYTHON_DEST_PATH "${CMAKE_BINARY_DIR}/Python") foreach(proto_file ${PROTO_FILES}) @@ -150,7 +150,8 @@ if (PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) "examples/ResultValues.py" "examples/SelectedCases.py" "examples/AllCases.py" - "examples/SetResultValues.py" + "examples/SetActiveCellProperties.py" + "examples/SetGridProperties.py" "tests/test_sample.py" ) @@ -158,7 +159,7 @@ if (PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) list(APPEND GRPC_PYTHON_SOURCES_FULL_PATH "${GRPC_PYTHON_SOURCE_PATH}/${PYTHON_SCRIPT}") endforeach() if (MSVC) - source_group(TREE ${GRPC_PYTHON_SOURCE_PATH} FILES ${GRPC_PYTHON_SOURCES_FULL_PATH} PREFIX "Python") + source_group(TREE ${GRPC_PYTHON_SOURCE_PATH} FILES ${GRPC_PYTHON_SOURCES_FULL_PATH} PREFIX "GrpcInterface\\Python") endif(MSVC) endif(PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) @@ -166,5 +167,9 @@ endif(PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) list ( APPEND GRPC_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES}) list ( APPEND GRPC_CPP_SOURCES ${SOURCE_GROUP_SOURCE_FILES}) +CONFIGURE_FILE( ${CMAKE_SOURCE_DIR}/ApplicationCode/Adm/RiaVersionInfo.py.cmake + ${GRPC_PYTHON_SOURCE_PATH}/generated/RiaVersionInfo.py +) + source_group( "GrpcInterface" FILES ${SOURCE_GROUP_HEADER_FILES} ${SOURCE_GROUP_SOURCE_FILES} ${CMAKE_CURRENT_LIST_DIR}/CMakeLists.cmake ) source_group( "GrpcInterface\\GrpcProtos" FILES ${GRPC_PROTO_FILES_FULL_PATH} ) \ No newline at end of file diff --git a/Python/.gitignore b/ApplicationCode/GrpcInterface/Python/.gitignore similarity index 100% rename from Python/.gitignore rename to ApplicationCode/GrpcInterface/Python/.gitignore diff --git a/Python/api/ResInsight.py b/ApplicationCode/GrpcInterface/Python/api/ResInsight.py similarity index 90% rename from Python/api/ResInsight.py rename to ApplicationCode/GrpcInterface/Python/api/ResInsight.py index 5ae13daec2..7e8485d093 100644 --- a/Python/api/ResInsight.py +++ b/ApplicationCode/GrpcInterface/Python/api/ResInsight.py @@ -131,20 +131,16 @@ class Properties: chunk = Properties_pb2.ResultRequestChunk() if index is -1: chunk.params.CopyFrom(parameters) - print("Added parameters") index += 1; else: actualChunkSize = min(len(array) - index + 1, chunkSize) chunk.values.CopyFrom(Properties_pb2.ResultArray(values = array[index:index+actualChunkSize])) - print("Added values") index += actualChunkSize - print(index) yield chunk # Final empty message to signal completion chunk = Properties_pb2.ResultRequestChunk() yield chunk - print("finished") def availableProperties(self, caseId, propertyType, porosityModel = 'MATRIX_MODEL'): propertyTypeEnum = Properties_pb2.PropertyType.Value(propertyType) @@ -175,7 +171,6 @@ class Properties: def setActiveCellResults(self, values, caseId, propertyType, propertyName, timeStep, gridIndex = 0, porosityModel = 'MATRIX_MODEL'): propertyTypeEnum = Properties_pb2.PropertyType.Value(propertyType) porosityModelEnum = GridInfo_pb2.PorosityModelType.Value(porosityModel) - print (propertyName) request = Properties_pb2.ResultRequest(request_case = CaseInfo_pb2.Case(id=caseId), property_type = propertyTypeEnum, property_name = propertyName, @@ -184,7 +179,6 @@ class Properties: porosity_model = porosityModelEnum) try: request_iterator = self.generateResultRequestArrays(values, request) - print("Starting to send data") self.properties.SetActiveCellResults(request_iterator) except grpc.RpcError as e: if e.code() == grpc.StatusCode.NOT_FOUND: @@ -192,6 +186,24 @@ class Properties: else: print("Other error", e) + def setGridResults(self, values, caseId, propertyType, propertyName, timeStep, gridIndex = 0, porosityModel = 'MATRIX_MODEL'): + propertyTypeEnum = Properties_pb2.PropertyType.Value(propertyType) + porosityModelEnum = GridInfo_pb2.PorosityModelType.Value(porosityModel) + request = Properties_pb2.ResultRequest(request_case = CaseInfo_pb2.Case(id=caseId), + property_type = propertyTypeEnum, + property_name = propertyName, + time_step = timeStep, + grid_index = gridIndex, + porosity_model = porosityModelEnum) + try: + request_iterator = self.generateResultRequestArrays(values, request) + self.properties.SetGridResults(request_iterator) + except grpc.RpcError as e: + if e.code() == grpc.StatusCode.NOT_FOUND: + print("Command not found") + else: + print("Other error", e) + class Instance: @staticmethod def is_port_in_use(port): diff --git a/Python/api/__init__.py b/ApplicationCode/GrpcInterface/Python/api/__init__.py similarity index 100% rename from Python/api/__init__.py rename to ApplicationCode/GrpcInterface/Python/api/__init__.py diff --git a/Python/examples/AllCases.py b/ApplicationCode/GrpcInterface/Python/examples/AllCases.py similarity index 100% rename from Python/examples/AllCases.py rename to ApplicationCode/GrpcInterface/Python/examples/AllCases.py diff --git a/Python/examples/CommandExample.py b/ApplicationCode/GrpcInterface/Python/examples/CommandExample.py similarity index 100% rename from Python/examples/CommandExample.py rename to ApplicationCode/GrpcInterface/Python/examples/CommandExample.py diff --git a/Python/examples/GridInfoStreamingExample.py b/ApplicationCode/GrpcInterface/Python/examples/GridInfoStreamingExample.py similarity index 100% rename from Python/examples/GridInfoStreamingExample.py rename to ApplicationCode/GrpcInterface/Python/examples/GridInfoStreamingExample.py diff --git a/Python/examples/ResultValues.py b/ApplicationCode/GrpcInterface/Python/examples/ResultValues.py similarity index 100% rename from Python/examples/ResultValues.py rename to ApplicationCode/GrpcInterface/Python/examples/ResultValues.py diff --git a/Python/examples/SelectedCases.py b/ApplicationCode/GrpcInterface/Python/examples/SelectedCases.py similarity index 100% rename from Python/examples/SelectedCases.py rename to ApplicationCode/GrpcInterface/Python/examples/SelectedCases.py diff --git a/Python/examples/SetResultValues.py b/ApplicationCode/GrpcInterface/Python/examples/SetActiveCellProperties.py similarity index 100% rename from Python/examples/SetResultValues.py rename to ApplicationCode/GrpcInterface/Python/examples/SetActiveCellProperties.py diff --git a/ApplicationCode/GrpcInterface/Python/examples/SetGridProperties.py b/ApplicationCode/GrpcInterface/Python/examples/SetGridProperties.py new file mode 100644 index 0000000000..bf15573601 --- /dev/null +++ b/ApplicationCode/GrpcInterface/Python/examples/SetGridProperties.py @@ -0,0 +1,16 @@ +import sys +import os +sys.path.insert(1, os.path.join(sys.path[0], '../api')) +import ResInsight + +resInsight = ResInsight.Instance.find() + +totalCellCount = resInsight.gridInfo.cellCount(caseId=0).reservoir_cell_count + +values = [] +for i in range(0, totalCellCount): + values.append(i % 2 * 0.75); + +print("Applying values to full grid") +resInsight.properties.setGridResults(values, 0, 'DYNAMIC_NATIVE', 'SOIL', 0) + diff --git a/Python/tests/test_sample.py b/ApplicationCode/GrpcInterface/Python/tests/test_sample.py similarity index 100% rename from Python/tests/test_sample.py rename to ApplicationCode/GrpcInterface/Python/tests/test_sample.py From 14ff796392f0a13461cd5076237814538cefec58 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Mon, 27 May 2019 07:29:20 +0200 Subject: [PATCH 084/396] gRPC: renames --- .../GrpcInterface/RiaGrpcCallbacks.h | 40 +++++------ .../GrpcInterface/RiaGrpcCallbacks.inl | 72 +++++++++---------- .../GrpcInterface/RiaGrpcCommandService.cpp | 5 +- .../GrpcInterface/RiaGrpcCommandService.h | 4 +- .../GrpcInterface/RiaGrpcGridInfoService.cpp | 12 ++-- .../GrpcInterface/RiaGrpcGridInfoService.h | 4 +- .../RiaGrpcProjectInfoService.cpp | 16 ++--- .../GrpcInterface/RiaGrpcProjectInfoService.h | 4 +- .../RiaGrpcPropertiesService.cpp | 8 +-- .../GrpcInterface/RiaGrpcPropertiesService.h | 2 +- .../GrpcInterface/RiaGrpcResInfoService.cpp | 4 +- .../GrpcInterface/RiaGrpcResInfoService.h | 4 +- .../GrpcInterface/RiaGrpcServer.cpp | 34 +++++---- .../GrpcInterface/RiaGrpcServiceInterface.h | 4 +- 14 files changed, 109 insertions(+), 104 deletions(-) diff --git a/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.h b/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.h index 53a6986dac..d830280c39 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.h +++ b/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.h @@ -39,7 +39,7 @@ class RiaGrpcServiceInterface; // Base class for all gRPC-callbacks // //================================================================================================== -class RiaAbstractGrpcCallback +class RiaGrpcCallbackInterface { public: enum CallState @@ -52,16 +52,16 @@ public: }; public: - inline RiaAbstractGrpcCallback(); + inline RiaGrpcCallbackInterface(); - virtual ~RiaAbstractGrpcCallback() {} - virtual QString name() const = 0; - virtual RiaAbstractGrpcCallback* createNewFromThis() const = 0; - virtual void createRequestHandler(ServerCompletionQueue* completionQueue) = 0; - virtual void onInitRequestStarted() {} - virtual void onInitRequestCompleted() {} - virtual void onProcessRequest() = 0; - virtual void onFinishRequest() {} + virtual ~RiaGrpcCallbackInterface() {} + virtual QString name() const = 0; + virtual RiaGrpcCallbackInterface* createNewFromThis() const = 0; + virtual void createRequestHandler(ServerCompletionQueue* completionQueue) = 0; + virtual void onInitRequestStarted() {} + virtual void onInitRequestCompleted() {} + virtual void onProcessRequest() = 0; + virtual void onFinishRequest() {} inline CallState callState() const; inline const Status& status() const; @@ -80,10 +80,10 @@ protected: // //================================================================================================== template -class RiaGrpcRequestCallback : public RiaAbstractGrpcCallback +class RiaGrpcServiceCallback : public RiaGrpcCallbackInterface { public: - RiaGrpcRequestCallback(ServiceT* service); + RiaGrpcServiceCallback(ServiceT* service); QString name() const override; const RequestT& request() const; @@ -104,7 +104,7 @@ protected: // //================================================================================================== template -class RiaGrpcCallback : public RiaGrpcRequestCallback +class RiaGrpcUnaryCallback : public RiaGrpcServiceCallback { public: typedef ServerAsyncResponseWriter ResponseWriterT; @@ -113,9 +113,9 @@ public: void(ServiceT&, ServerContext*, RequestT*, ResponseWriterT*, CompletionQueue*, ServerCompletionQueue*, void*)> MethodRequestT; - RiaGrpcCallback(ServiceT* service, MethodImplT methodImpl, MethodRequestT methodRequest); + RiaGrpcUnaryCallback(ServiceT* service, MethodImplT methodImpl, MethodRequestT methodRequest); - RiaAbstractGrpcCallback* createNewFromThis() const override; + RiaGrpcCallbackInterface* createNewFromThis() const override; void createRequestHandler(ServerCompletionQueue* completionQueue) override; void onProcessRequest() override; @@ -141,7 +141,7 @@ private: // //================================================================================================== template -class RiaGrpcStreamCallback : public RiaGrpcRequestCallback +class RiaGrpcServerStreamCallback : public RiaGrpcServiceCallback { public: typedef ServerAsyncWriter ResponseWriterT; @@ -150,9 +150,9 @@ public: void(ServiceT&, ServerContext*, RequestT*, ResponseWriterT*, CompletionQueue*, ServerCompletionQueue*, void*)> MethodRequestT; - RiaGrpcStreamCallback(ServiceT* service, MethodImplT methodImpl, MethodRequestT methodRequest, StateHandlerT* stateHandler); + RiaGrpcServerStreamCallback(ServiceT* service, MethodImplT methodImpl, MethodRequestT methodRequest, StateHandlerT* stateHandler); - RiaAbstractGrpcCallback* createNewFromThis() const override; + RiaGrpcCallbackInterface* createNewFromThis() const override; void createRequestHandler(ServerCompletionQueue* completionQueue) override; void onInitRequestCompleted() override; void onProcessRequest() override; @@ -181,7 +181,7 @@ private: // //================================================================================================== template -class RiaGrpcClientStreamCallback : public RiaGrpcRequestCallback +class RiaGrpcClientStreamCallback : public RiaGrpcServiceCallback { public: typedef ServerAsyncReader RequestReaderT; @@ -192,7 +192,7 @@ public: RiaGrpcClientStreamCallback(ServiceT* service, MethodImplT methodImpl, MethodRequestT methodRequest, StateHandlerT* stateHandler); - RiaAbstractGrpcCallback* createNewFromThis() const override; + RiaGrpcCallbackInterface* createNewFromThis() const override; void createRequestHandler(ServerCompletionQueue* completionQueue) override; void onInitRequestStarted() override; void onInitRequestCompleted() override; diff --git a/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.inl b/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.inl index 4bc11a8bdb..2cbeb7798e 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.inl +++ b/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.inl @@ -16,7 +16,7 @@ // ////////////////////////////////////////////////////////////////////////////////// -inline RiaAbstractGrpcCallback::RiaAbstractGrpcCallback() +inline RiaGrpcCallbackInterface::RiaGrpcCallbackInterface() : m_state(CREATE_HANDLER) , m_status(Status::OK) { @@ -25,7 +25,7 @@ inline RiaAbstractGrpcCallback::RiaAbstractGrpcCallback() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RiaAbstractGrpcCallback::CallState RiaAbstractGrpcCallback::callState() const +RiaGrpcCallbackInterface::CallState RiaGrpcCallbackInterface::callState() const { return m_state; } @@ -33,7 +33,7 @@ RiaAbstractGrpcCallback::CallState RiaAbstractGrpcCallback::callState() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -const Status& RiaAbstractGrpcCallback::status() const +const Status& RiaGrpcCallbackInterface::status() const { return m_status; } @@ -41,7 +41,7 @@ const Status& RiaAbstractGrpcCallback::status() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -inline void RiaAbstractGrpcCallback::setNextCallState(CallState state) +inline void RiaGrpcCallbackInterface::setNextCallState(CallState state) { m_state = state; } @@ -50,7 +50,7 @@ inline void RiaAbstractGrpcCallback::setNextCallState(CallState state) /// //-------------------------------------------------------------------------------------------------- template -RiaGrpcRequestCallback::RiaGrpcRequestCallback(ServiceT* service) +RiaGrpcServiceCallback::RiaGrpcServiceCallback(ServiceT* service) : m_service(service) { } @@ -59,7 +59,7 @@ RiaGrpcRequestCallback::RiaGrpcRequestCallback(Servi /// //-------------------------------------------------------------------------------------------------- template -QString RiaGrpcRequestCallback::name() const +QString RiaGrpcServiceCallback::name() const { QString fullName = QString("%1:%2(%3, %4)") .arg(typeid(ServiceT).name()) @@ -73,7 +73,7 @@ QString RiaGrpcRequestCallback::name() const /// //-------------------------------------------------------------------------------------------------- template -const RequestT& RiaGrpcRequestCallback::request() const +const RequestT& RiaGrpcServiceCallback::request() const { return m_request; } @@ -82,7 +82,7 @@ const RequestT& RiaGrpcRequestCallback::request() co /// //-------------------------------------------------------------------------------------------------- template -ReplyT& RiaGrpcRequestCallback::reply() +ReplyT& RiaGrpcServiceCallback::reply() { return m_reply; } @@ -91,10 +91,10 @@ ReplyT& RiaGrpcRequestCallback::reply() /// //-------------------------------------------------------------------------------------------------- template -RiaGrpcCallback::RiaGrpcCallback(ServiceT* service, +RiaGrpcUnaryCallback::RiaGrpcUnaryCallback(ServiceT* service, MethodImplT methodImpl, MethodRequestT methodRequest) - : RiaGrpcRequestCallback(service) + : RiaGrpcServiceCallback(service) , m_responder(&m_context) , m_methodImpl(methodImpl) , m_methodRequest(methodRequest) @@ -105,34 +105,34 @@ RiaGrpcCallback::RiaGrpcCallback(ServiceT* serv /// //-------------------------------------------------------------------------------------------------- template -RiaAbstractGrpcCallback* RiaGrpcCallback::createNewFromThis() const +RiaGrpcCallbackInterface* RiaGrpcUnaryCallback::createNewFromThis() const { - return new RiaGrpcCallback(this->m_service, this->m_methodImpl, this->m_methodRequest); + return new RiaGrpcUnaryCallback(this->m_service, this->m_methodImpl, this->m_methodRequest); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- template -void RiaGrpcCallback::createRequestHandler(ServerCompletionQueue* completionQueue) +void RiaGrpcUnaryCallback::createRequestHandler(ServerCompletionQueue* completionQueue) { // The Request-method is where the service gets registered to respond to a given request. m_methodRequest(*this->m_service, &m_context, &this->m_request, &m_responder, completionQueue, completionQueue, this); // Simple unary requests don't need initialisation, so proceed to process as soon as a request turns up. - this->setNextCallState(RiaAbstractGrpcCallback::PROCESS_REQUEST); + this->setNextCallState(RiaGrpcCallbackInterface::PROCESS_REQUEST); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- template -void RiaGrpcCallback::onProcessRequest() +void RiaGrpcUnaryCallback::onProcessRequest() { // Call request handler method this->m_status = m_methodImpl(*this->m_service, &m_context, &this->m_request, &this->m_reply); // Simply unary requests are finished as soon as you've done any processing. // So next time we receive a new tag on the command queue we should proceed to finish. - this->setNextCallState(RiaAbstractGrpcCallback::FINISH_REQUEST); + this->setNextCallState(RiaGrpcCallbackInterface::FINISH_REQUEST); // Finish will push this callback back on the command queue (now with Finish as the call state). m_responder.Finish(this->m_reply, this->m_status, this); } @@ -141,7 +141,7 @@ void RiaGrpcCallback::onProcessRequest() /// //-------------------------------------------------------------------------------------------------- template -QString RiaGrpcCallback::methodType() const +QString RiaGrpcUnaryCallback::methodType() const { return "RegularMethod"; } @@ -150,11 +150,11 @@ QString RiaGrpcCallback::methodType() const /// //-------------------------------------------------------------------------------------------------- template -RiaGrpcStreamCallback::RiaGrpcStreamCallback(ServiceT* service, +RiaGrpcServerStreamCallback::RiaGrpcServerStreamCallback(ServiceT* service, MethodImplT methodImpl, MethodRequestT methodRequest, StateHandlerT* stateHandler) - : RiaGrpcRequestCallback(service) + : RiaGrpcServiceCallback(service) , m_responder(&m_context) , m_methodImpl(methodImpl) , m_methodRequest(methodRequest) @@ -166,9 +166,9 @@ RiaGrpcStreamCallback::RiaGrpcStreamC /// //-------------------------------------------------------------------------------------------------- template -RiaAbstractGrpcCallback* RiaGrpcStreamCallback::createNewFromThis() const +RiaGrpcCallbackInterface* RiaGrpcServerStreamCallback::createNewFromThis() const { - return new RiaGrpcStreamCallback( + return new RiaGrpcServerStreamCallback( this->m_service, m_methodImpl, m_methodRequest, new StateHandlerT); } @@ -176,21 +176,21 @@ RiaAbstractGrpcCallback* RiaGrpcStreamCallback -void RiaGrpcStreamCallback::createRequestHandler( +void RiaGrpcServerStreamCallback::createRequestHandler( ServerCompletionQueue* completionQueue) { // The Request-method is where the service gets registered to respond to a given request. m_methodRequest(*this->m_service, &m_context, &this->m_request, &m_responder, completionQueue, completionQueue, this); // Server->Client Streaming requests require initialisation. However, we receive the complete request immediately. // So can proceed directly to completion of the init request. - this->setNextCallState(RiaAbstractGrpcCallback::INIT_REQUEST_COMPLETED); + this->setNextCallState(RiaGrpcCallbackInterface::INIT_REQUEST_COMPLETED); } //-------------------------------------------------------------------------------------------------- /// Perform initialisation tasks at the time of receiving a complete request //-------------------------------------------------------------------------------------------------- template -void RiaGrpcStreamCallback::onInitRequestCompleted() +void RiaGrpcServerStreamCallback::onInitRequestCompleted() { // Initialise streaming state handler this->m_status = m_stateHandler->init(&this->m_request); @@ -198,14 +198,14 @@ void RiaGrpcStreamCallback::onInitReq if (!this->m_status.ok()) { // We have an error. Proceed to finish and report the status - this->setNextCallState(RiaAbstractGrpcCallback::FINISH_REQUEST); + this->setNextCallState(RiaGrpcCallbackInterface::FINISH_REQUEST); m_responder.Finish(this->m_status, this); return; } // Move on to processing and perform the first processing immediately since the client will // not request anything more. - this->setNextCallState(RiaAbstractGrpcCallback::PROCESS_REQUEST); + this->setNextCallState(RiaGrpcCallbackInterface::PROCESS_REQUEST); this->onProcessRequest(); } @@ -213,7 +213,7 @@ void RiaGrpcStreamCallback::onInitReq /// Process a streaming request and send one package //-------------------------------------------------------------------------------------------------- template -void RiaGrpcStreamCallback::onProcessRequest() +void RiaGrpcServerStreamCallback::onProcessRequest() { this->m_reply = ReplyT(); // Make sure it is reset @@ -228,7 +228,7 @@ void RiaGrpcStreamCallback::onProcess } else { - this->setNextCallState(RiaAbstractGrpcCallback::FINISH_REQUEST); + this->setNextCallState(RiaGrpcCallbackInterface::FINISH_REQUEST); // Out of range means we're finished but it isn't an error if (this->m_status.error_code() == grpc::OUT_OF_RANGE) { @@ -243,7 +243,7 @@ void RiaGrpcStreamCallback::onProcess /// //-------------------------------------------------------------------------------------------------- template -QString RiaGrpcStreamCallback::methodType() const +QString RiaGrpcServerStreamCallback::methodType() const { return "StreamingMethod"; } @@ -257,7 +257,7 @@ RiaGrpcClientStreamCallback::RiaGrpcC MethodImplT methodImpl, MethodRequestT methodRequest, StateHandlerT* stateHandler) - : RiaGrpcRequestCallback(service) + : RiaGrpcServiceCallback(service) , m_reader(&m_context) , m_methodImpl(methodImpl) , m_methodRequest(methodRequest) @@ -269,7 +269,7 @@ RiaGrpcClientStreamCallback::RiaGrpcC /// //-------------------------------------------------------------------------------------------------- template -RiaAbstractGrpcCallback* RiaGrpcClientStreamCallback::createNewFromThis() const +RiaGrpcCallbackInterface* RiaGrpcClientStreamCallback::createNewFromThis() const { return new RiaGrpcClientStreamCallback( this->m_service, m_methodImpl, m_methodRequest, new StateHandlerT); @@ -286,7 +286,7 @@ void RiaGrpcClientStreamCallback::cre m_methodRequest(*this->m_service, &m_context, &this->m_reader, completionQueue, completionQueue, this); // The client->server streaming requires initialisation and each request package is streamed asynchronously // So we need to start and complete the init request. - this->setNextCallState(RiaAbstractGrpcCallback::INIT_REQUEST_STARTED); + this->setNextCallState(RiaGrpcCallbackInterface::INIT_REQUEST_STARTED); } //-------------------------------------------------------------------------------------------------- @@ -295,7 +295,7 @@ void RiaGrpcClientStreamCallback::cre template void RiaGrpcClientStreamCallback::onInitRequestStarted() { - this->setNextCallState(RiaAbstractGrpcCallback::INIT_REQUEST_COMPLETED); + this->setNextCallState(RiaGrpcCallbackInterface::INIT_REQUEST_COMPLETED); // The read call will start reading the request data and push this callback back onto the command queue // when the read call is completed. m_reader.Read(&this->m_request, this); @@ -307,7 +307,7 @@ void RiaGrpcClientStreamCallback::onI template void RiaGrpcClientStreamCallback::onInitRequestCompleted() { - this->setNextCallState(RiaAbstractGrpcCallback::PROCESS_REQUEST); + this->setNextCallState(RiaGrpcCallbackInterface::PROCESS_REQUEST); // Fully received the stream package so can now init this->m_status = m_stateHandler->init(&this->m_request); @@ -315,7 +315,7 @@ void RiaGrpcClientStreamCallback::onI { // We have an error. Proceed to finish and report the status m_reader.FinishWithError(this->m_status, this); - this->setNextCallState(RiaAbstractGrpcCallback::FINISH_REQUEST); + this->setNextCallState(RiaGrpcCallbackInterface::FINISH_REQUEST); return; } @@ -336,7 +336,7 @@ void RiaGrpcClientStreamCallback::onP if (!this->m_status.ok()) { - this->setNextCallState(RiaAbstractGrpcCallback::FINISH_REQUEST); + this->setNextCallState(RiaGrpcCallbackInterface::FINISH_REQUEST); if (this->m_status.error_code() == grpc::OUT_OF_RANGE) { m_reader.Finish(this->m_reply, grpc::Status::OK, this); diff --git a/ApplicationCode/GrpcInterface/RiaGrpcCommandService.cpp b/ApplicationCode/GrpcInterface/RiaGrpcCommandService.cpp index 683187c066..cf65a5d44e 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcCommandService.cpp +++ b/ApplicationCode/GrpcInterface/RiaGrpcCommandService.cpp @@ -32,6 +32,7 @@ using namespace rips; using namespace google::protobuf; +// Windows may define GetMessage as a Macro and this is in direct conflict with the gRPC GetMessage calls. #ifdef WIN32 #ifdef GetMessage #undef GetMessage @@ -96,11 +97,11 @@ grpc::Status RiaGrpcCommandService::Execute(grpc::ServerContext* context, const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::vector RiaGrpcCommandService::createCallbacks() +std::vector RiaGrpcCommandService::createCallbacks() { typedef RiaGrpcCommandService Self; - return {new RiaGrpcCallback(this, &Self::Execute, &Self::RequestExecute)}; + return {new RiaGrpcUnaryCallback(this, &Self::Execute, &Self::RequestExecute)}; } diff --git a/ApplicationCode/GrpcInterface/RiaGrpcCommandService.h b/ApplicationCode/GrpcInterface/RiaGrpcCommandService.h index d763f5b751..5ddb222afd 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcCommandService.h +++ b/ApplicationCode/GrpcInterface/RiaGrpcCommandService.h @@ -41,13 +41,13 @@ namespace protobuf } // namespace protobuf } // namespace google -class RiaAbstractGrpcCallback; +class RiaGrpcCallbackInterface; class RiaGrpcCommandService : public rips::Commands::AsyncService, public RiaGrpcServiceInterface { public: grpc::Status Execute(grpc::ServerContext* context, const rips::CommandParams* request, rips::CommandReply* reply) override; - std::vector createCallbacks() override; + std::vector createCallbacks() override; private: template diff --git a/ApplicationCode/GrpcInterface/RiaGrpcGridInfoService.cpp b/ApplicationCode/GrpcInterface/RiaGrpcGridInfoService.cpp index 9f04df35b6..e7be462ad4 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcGridInfoService.cpp +++ b/ApplicationCode/GrpcInterface/RiaGrpcGridInfoService.cpp @@ -316,15 +316,15 @@ grpc::Status RiaGrpcGridInfoService::GetCellInfoForActiveCells(grpc::ServerConte //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::vector RiaGrpcGridInfoService::createCallbacks() +std::vector RiaGrpcGridInfoService::createCallbacks() { typedef RiaGrpcGridInfoService Self; - return {new RiaGrpcCallback(this, &Self::GetGridCount, &Self::RequestGetGridCount), - new RiaGrpcCallback(this, &Self::GetGridDimensions, &Self::RequestGetGridDimensions), - new RiaGrpcCallback(this, &Self::GetCellCount, &Self::RequestGetCellCount), - new RiaGrpcCallback(this, &Self::GetTimeSteps, &Self::RequestGetTimeSteps), - new RiaGrpcStreamCallback( + return {new RiaGrpcUnaryCallback(this, &Self::GetGridCount, &Self::RequestGetGridCount), + new RiaGrpcUnaryCallback(this, &Self::GetGridDimensions, &Self::RequestGetGridDimensions), + new RiaGrpcUnaryCallback(this, &Self::GetCellCount, &Self::RequestGetCellCount), + new RiaGrpcUnaryCallback(this, &Self::GetTimeSteps, &Self::RequestGetTimeSteps), + new RiaGrpcServerStreamCallback( this, &Self::GetCellInfoForActiveCells, &Self::RequestGetCellInfoForActiveCells, new RiaActiveCellInfoStateHandler)}; } diff --git a/ApplicationCode/GrpcInterface/RiaGrpcGridInfoService.h b/ApplicationCode/GrpcInterface/RiaGrpcGridInfoService.h index 828dd9e1da..104efd439b 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcGridInfoService.h +++ b/ApplicationCode/GrpcInterface/RiaGrpcGridInfoService.h @@ -29,7 +29,7 @@ namespace rips class Case; } -class RiaAbstractGrpcCallback; +class RiaGrpcCallbackInterface; class RigCell; class RigActiveCellInfo; class RimEclipseCase; @@ -78,5 +78,5 @@ public: const rips::CellInfoRequest* request, rips::CellInfoArray* reply, RiaActiveCellInfoStateHandler* stateHandler); - std::vector createCallbacks() override; + std::vector createCallbacks() override; }; diff --git a/ApplicationCode/GrpcInterface/RiaGrpcProjectInfoService.cpp b/ApplicationCode/GrpcInterface/RiaGrpcProjectInfoService.cpp index 1e60b77b44..bd802730f3 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcProjectInfoService.cpp +++ b/ApplicationCode/GrpcInterface/RiaGrpcProjectInfoService.cpp @@ -231,18 +231,18 @@ grpc::Status //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::vector RiaGrpcProjectInfoService::createCallbacks() +std::vector RiaGrpcProjectInfoService::createCallbacks() { typedef RiaGrpcProjectInfoService Self; return { - new RiaGrpcCallback(this, &Self::CurrentCase, &Self::RequestCurrentCase), - new RiaGrpcCallback(this, &Self::CurrentCaseInfo, &Self::RequestCurrentCaseInfo), - new RiaGrpcCallback(this, &Self::CaseInfoFromCase, &Self::RequestCaseInfoFromCase), - new RiaGrpcCallback(this, &Self::SelectedCases, &Self::RequestSelectedCases), - new RiaGrpcCallback(this, &Self::AllCaseGroups, &Self::RequestAllCaseGroups), - new RiaGrpcCallback(this, &Self::AllCases, &Self::RequestAllCases), - new RiaGrpcCallback(this, &Self::CasesInGroup, &Self::RequestCasesInGroup)}; + new RiaGrpcUnaryCallback(this, &Self::CurrentCase, &Self::RequestCurrentCase), + new RiaGrpcUnaryCallback(this, &Self::CurrentCaseInfo, &Self::RequestCurrentCaseInfo), + new RiaGrpcUnaryCallback(this, &Self::CaseInfoFromCase, &Self::RequestCaseInfoFromCase), + new RiaGrpcUnaryCallback(this, &Self::SelectedCases, &Self::RequestSelectedCases), + new RiaGrpcUnaryCallback(this, &Self::AllCaseGroups, &Self::RequestAllCaseGroups), + new RiaGrpcUnaryCallback(this, &Self::AllCases, &Self::RequestAllCases), + new RiaGrpcUnaryCallback(this, &Self::CasesInGroup, &Self::RequestCasesInGroup)}; } static bool RiaGrpcProjectInfoService_init = diff --git a/ApplicationCode/GrpcInterface/RiaGrpcProjectInfoService.h b/ApplicationCode/GrpcInterface/RiaGrpcProjectInfoService.h index b9db1a5375..92ab551cf7 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcProjectInfoService.h +++ b/ApplicationCode/GrpcInterface/RiaGrpcProjectInfoService.h @@ -28,7 +28,7 @@ class Empty; class CaseInfo; } // namespace rips -class RiaAbstractGrpcCallback; +class RiaGrpcCallbackInterface; //================================================================================================== // @@ -47,5 +47,5 @@ public: grpc::Status CasesInGroup(grpc::ServerContext* context, const rips::CaseGroup* request, rips::CaseInfos* reply) override; public: - std::vector createCallbacks() override; + std::vector createCallbacks() override; }; diff --git a/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp b/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp index c59c4e560a..8b3a4be4c3 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp +++ b/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp @@ -302,15 +302,15 @@ grpc::Status RiaGrpcPropertiesService::SetGridResults(grpc::ServerContext* //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::vector RiaGrpcPropertiesService::createCallbacks() +std::vector RiaGrpcPropertiesService::createCallbacks() { typedef RiaGrpcPropertiesService Self; - return {new RiaGrpcCallback( + return {new RiaGrpcUnaryCallback( this, &Self::GetAvailableProperties, &Self::RequestGetAvailableProperties), - new RiaGrpcStreamCallback( + new RiaGrpcServerStreamCallback( this, &Self::GetActiveCellResults, &Self::RequestGetActiveCellResults, new RiaActiveCellResultsStateHandler), - new RiaGrpcStreamCallback( + new RiaGrpcServerStreamCallback( this, &Self::GetGridResults, &Self::RequestGetGridResults, new RiaGridCellResultsStateHandler), new RiaGrpcClientStreamCallback( this, &Self::SetActiveCellResults, &Self::RequestSetActiveCellResults, new RiaActiveCellResultsStateHandler), diff --git a/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.h b/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.h index 2fee1d0833..827b5a8b66 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.h +++ b/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.h @@ -54,5 +54,5 @@ public: rips::Empty* reply, RiaGridCellResultsStateHandler* stateHandler); - std::vector createCallbacks() override; + std::vector createCallbacks() override; }; diff --git a/ApplicationCode/GrpcInterface/RiaGrpcResInfoService.cpp b/ApplicationCode/GrpcInterface/RiaGrpcResInfoService.cpp index 6523f12073..c9503b40c7 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcResInfoService.cpp +++ b/ApplicationCode/GrpcInterface/RiaGrpcResInfoService.cpp @@ -34,10 +34,10 @@ grpc::Status RiaGrpcResInfoService::GetVersion(grpc::ServerContext* context, con //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::vector RiaGrpcResInfoService::createCallbacks() +std::vector RiaGrpcResInfoService::createCallbacks() { typedef RiaGrpcResInfoService Self; - return { new RiaGrpcCallback(this, &Self::GetVersion, &Self::RequestGetVersion) }; + return { new RiaGrpcUnaryCallback(this, &Self::GetVersion, &Self::RequestGetVersion) }; } static bool RiaGrpcResInfoService_init = diff --git a/ApplicationCode/GrpcInterface/RiaGrpcResInfoService.h b/ApplicationCode/GrpcInterface/RiaGrpcResInfoService.h index 0f48ff3485..41b1fbaf20 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcResInfoService.h +++ b/ApplicationCode/GrpcInterface/RiaGrpcResInfoService.h @@ -37,13 +37,13 @@ namespace caf class PdmValueField; } -class RiaAbstractGrpcCallback; +class RiaGrpcCallbackInterface; class RiaGrpcResInfoService : public rips::ResInfo::AsyncService, public RiaGrpcServiceInterface { public: grpc::Status GetVersion(grpc::ServerContext* context, const rips::Empty* request, rips::Version* reply) override; - std::vector createCallbacks() override; + std::vector createCallbacks() override; }; diff --git a/ApplicationCode/GrpcInterface/RiaGrpcServer.cpp b/ApplicationCode/GrpcInterface/RiaGrpcServer.cpp index dfba26d327..4af25b1eff 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcServer.cpp +++ b/ApplicationCode/GrpcInterface/RiaGrpcServer.cpp @@ -63,18 +63,17 @@ public: void initialize(); void processAllQueuedRequests(); void quit(); - int currentPortNumber; private: void waitForNextRequest(); - void process(RiaAbstractGrpcCallback* method); + void process(RiaGrpcCallbackInterface* method); private: int m_portNumber; std::unique_ptr m_completionQueue; std::unique_ptr m_server; std::list> m_services; - std::list m_unprocessedRequests; + std::list m_unprocessedRequests; std::mutex m_requestMutex; std::thread m_thread; }; @@ -171,12 +170,17 @@ void RiaGrpcServerImpl::initialize() //-------------------------------------------------------------------------------------------------- void RiaGrpcServerImpl::processAllQueuedRequests() { - std::lock_guard requestLock(m_requestMutex); - - while (!m_unprocessedRequests.empty()) + std::list waitingRequests; { - RiaAbstractGrpcCallback* method = m_unprocessedRequests.front(); - m_unprocessedRequests.pop_front(); + // Block only while transferring the unprocessed requests to a local function list + std::lock_guard requestLock(m_requestMutex); + waitingRequests.swap(m_unprocessedRequests); + } + // Now free to receive new requests from client while processing the current ones. + while (!waitingRequests.empty()) + { + RiaGrpcCallbackInterface* method = waitingRequests.front(); + waitingRequests.pop_front(); process(method); } } @@ -193,7 +197,7 @@ void RiaGrpcServerImpl::quit() // Clear unhandled requests while (!m_unprocessedRequests.empty()) { - RiaAbstractGrpcCallback* method = m_unprocessedRequests.front(); + RiaGrpcCallbackInterface* method = m_unprocessedRequests.front(); m_unprocessedRequests.pop_front(); delete method; } @@ -225,7 +229,7 @@ void RiaGrpcServerImpl::waitForNextRequest() while (m_completionQueue->Next(&tag, &ok)) { - RiaAbstractGrpcCallback* method = static_cast(tag); + RiaGrpcCallbackInterface* method = static_cast(tag); if (ok) { std::lock_guard requestLock(m_requestMutex); @@ -239,24 +243,24 @@ void RiaGrpcServerImpl::waitForNextRequest() /// The gRPC calls triggered in the callback will see each callback pushed back onto the command queue. /// The call state will then determine what the callback should do next. //-------------------------------------------------------------------------------------------------- -void RiaGrpcServerImpl::process(RiaAbstractGrpcCallback* method) +void RiaGrpcServerImpl::process(RiaGrpcCallbackInterface* method) { - if (method->callState() == RiaAbstractGrpcCallback::CREATE_HANDLER) + if (method->callState() == RiaGrpcCallbackInterface::CREATE_HANDLER) { RiaLogging::debug(QString("Creating request handler for: %1").arg(method->name())); method->createRequestHandler(m_completionQueue.get()); } - else if (method->callState() == RiaAbstractGrpcCallback::INIT_REQUEST_STARTED) + else if (method->callState() == RiaGrpcCallbackInterface::INIT_REQUEST_STARTED) { method->onInitRequestStarted(); } - else if (method->callState() == RiaAbstractGrpcCallback::INIT_REQUEST_COMPLETED) + else if (method->callState() == RiaGrpcCallbackInterface::INIT_REQUEST_COMPLETED) { RiaLogging::info(QString("Initialising handling: %1").arg(method->name())); method->onInitRequestCompleted(); } - else if (method->callState() == RiaAbstractGrpcCallback::PROCESS_REQUEST) + else if (method->callState() == RiaGrpcCallbackInterface::PROCESS_REQUEST) { method->onProcessRequest(); } diff --git a/ApplicationCode/GrpcInterface/RiaGrpcServiceInterface.h b/ApplicationCode/GrpcInterface/RiaGrpcServiceInterface.h index 0d5383ed39..3795ea57f1 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcServiceInterface.h +++ b/ApplicationCode/GrpcInterface/RiaGrpcServiceInterface.h @@ -21,7 +21,7 @@ #include -class RiaAbstractGrpcCallback; +class RiaGrpcCallbackInterface; class RimCase; //================================================================================================== @@ -32,7 +32,7 @@ class RimCase; class RiaGrpcServiceInterface { public: - virtual std::vector createCallbacks() = 0; + virtual std::vector createCallbacks() = 0; virtual ~RiaGrpcServiceInterface() = default; static RimCase* findCase(int caseId); static size_t numberOfMessagesForByteCount(size_t messageSize, size_t byteCount = 64 * 1024u); From 32bc4320c9482f034dbcce4e339bf269795a504e Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Mon, 27 May 2019 07:29:56 +0200 Subject: [PATCH 085/396] gRPC: UML diagrams --- doc/grpc_sequence.plantuml | 57 ++++++++++++++++++++++++++++++++++++++ doc/grpc_server.plantuml | 56 +++++++++++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+) create mode 100644 doc/grpc_sequence.plantuml create mode 100644 doc/grpc_server.plantuml diff --git a/doc/grpc_sequence.plantuml b/doc/grpc_sequence.plantuml new file mode 100644 index 0000000000..410ad9d269 --- /dev/null +++ b/doc/grpc_sequence.plantuml @@ -0,0 +1,57 @@ +@startuml + +actor Client + +box "Server Side" #LightBlue + participant Server order 20 + participant Service order 40 + participant Callback order 30 + participant ServerThread order 10 + +Server -> Service : Create +activate Server +Server -> Callback : Create(Service) +Server -> ServerThread : Launch +activate ServerThread +deactivate Server +Client -> ServerThread: Request #1 +ServerThread -> Server : Queue(Request #1) +Server -> Server : Scheduled +activate Server +Server->ServerThread : Block +deactivate ServerThread +Server -> Server : Take Requests +Server->ServerThread : Unblock +activate ServerThread +Server -> Callback : Init(Request #1) +activate Callback +Server -> Callback : Process(Request #1) +Callback -> Service : Method +activate Service +return Result +deactivate Service +Client -> ServerThread: Request #2 +Callback --> Server : Finish #1 +deactivate Callback +Server --> Client : Reply #1 +deactivate Server +ServerThread -> Server : Queue(Request #2) +Server -> Server : Scheduled +activate Server +Server->ServerThread : Block +deactivate ServerThread +Server->Server : Take Requests +Server->ServerThread : Unblock +activate ServerThread +Server -> Callback : Process(Request #2) +activate Callback +Server -> Callback : Init(Request #1) +Callback -> Service : Method +activate Service +return Result +Callback --> Server : Finish #2 +deactivate Callback +Server --> Client : Reply #2 +deactivate Server +deactivate ServerThread +@enduml diff --git a/doc/grpc_server.plantuml b/doc/grpc_server.plantuml new file mode 100644 index 0000000000..1e428834a5 --- /dev/null +++ b/doc/grpc_server.plantuml @@ -0,0 +1,56 @@ +@startuml + + +package GrpcServices +{ + class RiaGrpcServiceInterface + class RiaGrpcStreamService + { + GetStream(Request*, Reply*, StateHandler*) + RequestGetStream(...) + SetStream(Request*, Reply*, StateHandler*) + RequestSetStream(...) + } + RiaGrpcServiceInterface <|-- RiaGrpcStreamService + +} + +package GrpcCallbacks +{ + class RiaGrpcCallbackInterface + + class RiaGrpcClientStreamCallback + { + + } + + class RiaGrpcServerStreamCallback + { + + } + + RiaGrpcCallbackInterface <|-- RiaGrpcServerStreamCallback + RiaGrpcCallbackInterface <|-- RiaGrpcClientStreamCallback + + + + RiaGrpcServerStreamCallback --> RiaGrpcStreamService::RequestGetStream : registers + RiaGrpcServerStreamCallback --> RiaGrpcStreamService::GetStream : sends N chunks + RiaGrpcClientStreamCallback --> RiaGrpcStreamService::RequestSetStream : registers + RiaGrpcClientStreamCallback --> RiaGrpcStreamService::SetStream : gets N chunks +} + +package GrpcServer +{ + class RiaGrpcServer + RiaGrpcServer "1" *-- "many" RiaGrpcServiceInterface : contains + RiaGrpcServer "1" *-- "many" RiaGrpcCallbackInterface : contains + +} + +package ResInsight { + RiaApplication --> RiaGrpcServer +} + + +@enduml From 9be3972dc4d4b76688f26a4d7eef3818bb7c8f43 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 27 May 2019 13:05:21 +0200 Subject: [PATCH 086/396] Add setting of required environment variable --- GRPC_install_instructions.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/GRPC_install_instructions.txt b/GRPC_install_instructions.txt index e290776e68..3c7a8d9293 100644 --- a/GRPC_install_instructions.txt +++ b/GRPC_install_instructions.txt @@ -15,18 +15,19 @@ git clone https://github.com/microsoft/vcpkg.git ############ Linux as STANDALONE GPRC (using GRPC_INSTALL_PREFIX=/opt/grpc as an example) ############### 1. Clone grpc -https://github.com/grpc/grpc.git +git clone https://github.com/grpc/grpc.git 2. From within grpc folder, check out stable version of grpc and initialise repo: git checkout v1.20.1 git submodule init git submodule update 3. Make sure you're building with devtools-3, since you'll be using that for ResInsight too scl enable devtoolset-3 bash +export PROTOBUF_CONFIG_OPTS="--prefix=/opt/grpc" make prefix=/opt/grpc sudo make prefix=/opt/grpc install 4. Install protobuf (still within grpc folder) cd third_party/protobuf -sudo make prefix=/opt/grpc install +sudo make install 5. Make sure you have a Python 3 version available in your paths. I.e.: "sudo yum install rh-python35" and then "scl enable rh-python35 bash" 6. Install grpcio-tools for Python (this may have to be done as root user): From af83ee310f4e8cf9844214dbb6b08e14399c0ee1 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Mon, 27 May 2019 08:28:23 +0200 Subject: [PATCH 087/396] #4435 Make sure we don't ask user about changes to preferences that haven't been changed --- .../Application/RiaGuiApplication.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/ApplicationCode/Application/RiaGuiApplication.cpp b/ApplicationCode/Application/RiaGuiApplication.cpp index e249339fb7..b8e2cdfaa1 100644 --- a/ApplicationCode/Application/RiaGuiApplication.cpp +++ b/ApplicationCode/Application/RiaGuiApplication.cpp @@ -1435,15 +1435,21 @@ void RiaGuiApplication::applyGuiPreferences(const RiaPreferences* oldPreferences auto rim3dView = dynamic_cast(viewWindow); if (rim3dView) { - if (rim3dView->meshMode() != oldPreferences->defaultMeshModeType()) + if (m_preferences->defaultMeshModeType() != oldPreferences->defaultMeshModeType() && + rim3dView->meshMode() != oldPreferences->defaultMeshModeType() && + rim3dView->meshMode() != m_preferences->defaultMeshModeType()) { existingViewsWithDifferentMeshLines = true; } - if (rim3dView->backgroundColor() != oldPreferences->defaultViewerBackgroundColor()) + if (m_preferences->defaultViewerBackgroundColor() != oldPreferences->defaultViewerBackgroundColor() && + rim3dView->backgroundColor() != oldPreferences->defaultViewerBackgroundColor() && + rim3dView->backgroundColor() != m_preferences->defaultViewerBackgroundColor()) { existingViewsWithCustomColors = true; } - if (rim3dView->scaleZ() != static_cast(oldPreferences->defaultScaleFactorZ)) + if (m_preferences->defaultScaleFactorZ() != oldPreferences->defaultScaleFactorZ() && + rim3dView->scaleZ() != static_cast(oldPreferences->defaultScaleFactorZ) && + rim3dView->scaleZ() != static_cast(m_preferences->defaultScaleFactorZ)) { existingViewsWithCustomZScale = true; } @@ -1458,7 +1464,9 @@ void RiaGuiApplication::applyGuiPreferences(const RiaPreferences* oldPreferences RimEclipseView* eclipseView = dynamic_cast(rim3dView); if (eclipseView) { - if (eclipseView->wellCollection()->wellLabelColor() != oldPreferences->defaultWellLabelColor()) + if (m_preferences->defaultWellLabelColor() != oldPreferences->defaultWellLabelColor() && + eclipseView->wellCollection()->wellLabelColor() != oldPreferences->defaultWellLabelColor() && + eclipseView->wellCollection()->wellLabelColor() != m_preferences->defaultWellLabelColor()) { existingViewsWithCustomColors = true; } From bbe3e7ff048845e01e0dfda4fcc46b6a05ce0545 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Mon, 27 May 2019 09:23:44 +0200 Subject: [PATCH 088/396] #4440 Update legend ranges when changing oil column data --- .../ProjectDataModel/RimContourMapProjection.cpp | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimContourMapProjection.cpp b/ApplicationCode/ProjectDataModel/RimContourMapProjection.cpp index e60aab03c1..6ddd2684c4 100644 --- a/ApplicationCode/ProjectDataModel/RimContourMapProjection.cpp +++ b/ApplicationCode/ProjectDataModel/RimContourMapProjection.cpp @@ -113,9 +113,11 @@ void RimContourMapProjection::generateResultsIfNecessary(int timeStep) updateGridInformation(); progress.setProgress(10); - if (gridMappingNeedsUpdating() || mapCellVisibilityNeedsUpdating()) + if (gridMappingNeedsUpdating() || mapCellVisibilityNeedsUpdating() || resultVariableChanged()) { clearResults(); + clearTimeStepRange(); + m_projected3dGridIndices = generateGridMapping(); progress.setProgress(20); m_mapCellVisibility = getMapCellVisibility(); @@ -126,12 +128,6 @@ void RimContourMapProjection::generateResultsIfNecessary(int timeStep) progress.setProgress(30); } - if (resultVariableChanged()) - { - clearResults(); - clearTimeStepRange(); - } - if (resultsNeedsUpdating(timeStep)) { clearGeometry(); From 6d969263d5fea0ff522787b7ebf43007d9c2a44f Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Mon, 27 May 2019 10:16:44 +0200 Subject: [PATCH 089/396] Hide GPRC warnings on Linux --- ApplicationCode/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ApplicationCode/CMakeLists.txt b/ApplicationCode/CMakeLists.txt index 2daa688287..f76aa79436 100644 --- a/ApplicationCode/CMakeLists.txt +++ b/ApplicationCode/CMakeLists.txt @@ -319,7 +319,7 @@ if (MSVC) elseif (APPLE) set( EXE_FILES MACOSX_BUNDLE) else() - set_source_files_properties(${GRPC_CPP_SOURCES} PROPERTIES COMPILE_FLAGS "-Woverloaded-virtual") + set_source_files_properties(${GRPC_CPP_SOURCES} PROPERTIES COMPILE_FLAGS "-Wno-overloaded-virtual") endif() set( EXE_FILES ${EXE_FILES} From debf15bbbe55680afc434984317d31340a3220c6 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Mon, 27 May 2019 14:08:35 +0200 Subject: [PATCH 090/396] Fix test filter in regression test runner --- ApplicationCode/Application/Tools/RiaRegressionTestRunner.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ApplicationCode/Application/Tools/RiaRegressionTestRunner.cpp b/ApplicationCode/Application/Tools/RiaRegressionTestRunner.cpp index e286add669..26e344fee8 100644 --- a/ApplicationCode/Application/Tools/RiaRegressionTestRunner.cpp +++ b/ApplicationCode/Application/Tools/RiaRegressionTestRunner.cpp @@ -603,7 +603,8 @@ QFileInfoList RiaRegressionTestRunner::subDirectoriesForTestExecution(const QDir for (const auto& s : m_testFilter) { QString trimmed = s.trimmed(); - if (anyMatchFound || baseName.contains(trimmed, Qt::CaseInsensitive)) + if ((m_appendAllTestsAfterLastItemInFilter && anyMatchFound) || + baseName.contains(trimmed, Qt::CaseInsensitive)) { foldersMatchingTestFilter.push_back(fi); anyMatchFound = true; From 6864888591ac9e06472ee4c586fa6982973d678b Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Mon, 27 May 2019 14:10:21 +0200 Subject: [PATCH 091/396] Add CAF_ASSERT to RigCaseCellResultsData::statistics * Currently the code crashes in a dual porosity case. * This commit doesn't fix the problem but adds an assert which triggers instead of just crashing --- ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp b/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp index d6f363f4cd..948cdc0059 100644 --- a/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp @@ -2808,7 +2808,9 @@ void RigCaseCellResultsData::assignValuesToTemporaryLgrs(const QString& re //-------------------------------------------------------------------------------------------------- RigStatisticsDataCache* RigCaseCellResultsData::statistics(const RigEclipseResultAddress& resVarAddr) { - return m_statisticsDataCache[findScalarResultIndexFromAddress(resVarAddr)].p(); + size_t scalarResultIndex = findScalarResultIndexFromAddress(resVarAddr); + CAF_ASSERT(scalarResultIndex < m_statisticsDataCache.size()); + return m_statisticsDataCache[scalarResultIndex].p(); } From f8b8f4d7c8eda6dcc95592ff476779d6059ecf57 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Mon, 27 May 2019 16:13:41 +0200 Subject: [PATCH 092/396] #4436 Issue refreshToolbar after creating well log extraction curve --- .../WellLogCommands/RicNewWellLogCurveExtractionFeature.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ApplicationCode/Commands/WellLogCommands/RicNewWellLogCurveExtractionFeature.cpp b/ApplicationCode/Commands/WellLogCommands/RicNewWellLogCurveExtractionFeature.cpp index ac23136346..72e166aacc 100644 --- a/ApplicationCode/Commands/WellLogCommands/RicNewWellLogCurveExtractionFeature.cpp +++ b/ApplicationCode/Commands/WellLogCommands/RicNewWellLogCurveExtractionFeature.cpp @@ -39,6 +39,7 @@ #include "RiuPlotMainWindow.h" #include "Riu3dSelectionManager.h" +#include "RiuPlotMainWindowTools.h" #include "cafSelectionManager.h" @@ -106,6 +107,7 @@ void RicNewWellLogCurveExtractionFeature::onActionTriggered(bool isChecked) plotCurve->updateConnectedEditors(); } } + RiuPlotMainWindowTools::refreshToolbars(); } //-------------------------------------------------------------------------------------------------- From 2648997377489a07a1b7330a7a1a8f6a0f932a7b Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 28 May 2019 10:56:25 +0200 Subject: [PATCH 093/396] Update GRPC_install_instructions.txt --- GRPC_install_instructions.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GRPC_install_instructions.txt b/GRPC_install_instructions.txt index 3c7a8d9293..26dc03497c 100644 --- a/GRPC_install_instructions.txt +++ b/GRPC_install_instructions.txt @@ -11,7 +11,7 @@ git clone https://github.com/microsoft/vcpkg.git 6. Run cmake with -DCMAKE_TOOLCHAIN_FILE=LOCATION_OF_VCPKG/buildsystems/vcpkg.cmake This can be set on the configure dialog that comes up when you press configure with a fresh build folder. 7. Enable GRPC by setting RESINSIGHT_ENABLE_GRPC = true -8. Make sure the python executable is found by setting PYTHON_EXECUTABLE=LOCATION_OF_PYTHON.EXE +8. Make sure the python executable is found by setting -DPYTHON_EXECUTABLE=LOCATION_OF_PYTHON.EXE ############ Linux as STANDALONE GPRC (using GRPC_INSTALL_PREFIX=/opt/grpc as an example) ############### 1. Clone grpc From c7a9f645753a5fee5b561a45e28e149886a08404 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 28 May 2019 14:55:28 +0200 Subject: [PATCH 094/396] Update GRPC_install_instructions.txt --- GRPC_install_instructions.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/GRPC_install_instructions.txt b/GRPC_install_instructions.txt index 26dc03497c..7deba5e702 100644 --- a/GRPC_install_instructions.txt +++ b/GRPC_install_instructions.txt @@ -11,7 +11,11 @@ git clone https://github.com/microsoft/vcpkg.git 6. Run cmake with -DCMAKE_TOOLCHAIN_FILE=LOCATION_OF_VCPKG/buildsystems/vcpkg.cmake This can be set on the configure dialog that comes up when you press configure with a fresh build folder. 7. Enable GRPC by setting RESINSIGHT_ENABLE_GRPC = true -8. Make sure the python executable is found by setting -DPYTHON_EXECUTABLE=LOCATION_OF_PYTHON.EXE +8. Python + - Install Python 3 + - Execute the following using the Python3 + python -m pip install grpcio-tools + - Make sure the python executable is found by setting -DPYTHON_EXECUTABLE=LOCATION_OF_PYTHON.EXE ############ Linux as STANDALONE GPRC (using GRPC_INSTALL_PREFIX=/opt/grpc as an example) ############### 1. Clone grpc From 8f3eb6a7488d575f794c1ed6c404ad1ab8f2f625 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Tue, 28 May 2019 09:08:32 +0200 Subject: [PATCH 095/396] Add Qt5 test to AppFwk main CMakeLists.txt and update CAF to use CEE_USE_QT5 --- CMakeLists.txt | 17 ++++++------ Fwk/AppFwk/CMakeLists.txt | 8 +++++- Fwk/AppFwk/CommonCode/CMakeLists.txt | 23 +++++++++------- Fwk/AppFwk/cafAnimControl/CMakeLists.txt | 26 ++++++++++--------- Fwk/AppFwk/cafCommand/CMakeLists.txt | 20 +++++++++----- Fwk/AppFwk/cafPdmCvf/CMakeLists.txt | 20 +++++++------- Fwk/AppFwk/cafProjectDataModel/CMakeLists.txt | 20 ++++++++------ .../cafPdmCore/CMakeLists.txt | 19 ++++++++------ .../cafPdmUiCore/CMakeLists.txt | 26 ++++++++++--------- .../cafPdmXml/CMakeLists.txt | 19 ++++++++------ Fwk/AppFwk/cafUserInterface/CMakeLists.txt | 21 ++++++++------- Fwk/AppFwk/cafViewer/CMakeLists.txt | 23 +++++++++------- Fwk/AppFwk/cafVizExtensions/CMakeLists.txt | 20 +++++++------- 13 files changed, 151 insertions(+), 111 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 318aba08ed..73de2888a5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -332,6 +332,15 @@ set_property(TARGET PROPERTY FOLDER "Thirdparty" ) + +################################################################################ +# App and Viz Framework Qt5 setting +################################################################################ +if (RESINSIGHT_BUILD_WITH_QT5) + set(CEE_USE_QT5 ON) +endif(RESINSIGHT_BUILD_WITH_QT5) + + ################################################################################ # Vizualization Framework ################################################################################ @@ -357,10 +366,6 @@ if (CMAKE_COMPILER_IS_GNUCC) endif() -if (RESINSIGHT_BUILD_WITH_QT5) - set(CEE_USE_QT5 ON) -endif(RESINSIGHT_BUILD_WITH_QT5) - add_subdirectory(${VIZ_MODULES_FOLDER_NAME}/LibCore) add_subdirectory(${VIZ_MODULES_FOLDER_NAME}/LibGeometry) add_subdirectory(${VIZ_MODULES_FOLDER_NAME}/LibRender) @@ -385,10 +390,6 @@ set_property(TARGET # Application Framework ################################################################################ -if (RESINSIGHT_BUILD_WITH_QT5) - set(CAF_USE_QT5 ON) -endif(RESINSIGHT_BUILD_WITH_QT5) - add_subdirectory(Fwk/AppFwk/cafAnimControl) add_subdirectory(Fwk/AppFwk/cafViewer) diff --git a/Fwk/AppFwk/CMakeLists.txt b/Fwk/AppFwk/CMakeLists.txt index 0fb421f1f8..0ecc7049e1 100644 --- a/Fwk/AppFwk/CMakeLists.txt +++ b/Fwk/AppFwk/CMakeLists.txt @@ -8,7 +8,13 @@ if (MSVC AND (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 19.11)) message("Add flag to disable warings from gtest - _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING") endif() -find_package(Qt5Core CONFIG QUIET) +# Qt +option(CEE_USE_QT5 "Use Qt5" OFF) + +if (CEE_USE_QT5) + find_package(Qt5Core CONFIG QUIET) +endif(CEE_USE_QT5) + if (Qt5Core_FOUND) find_package(Qt5 CONFIG REQUIRED Core Gui OpenGL Widgets) else() diff --git a/Fwk/AppFwk/CommonCode/CMakeLists.txt b/Fwk/AppFwk/CommonCode/CMakeLists.txt index 520f0ff860..0ebb007610 100644 --- a/Fwk/AppFwk/CommonCode/CMakeLists.txt +++ b/Fwk/AppFwk/CommonCode/CMakeLists.txt @@ -3,12 +3,19 @@ cmake_minimum_required (VERSION 2.8.12) project (CommonCode) # Qt -if (CAF_USE_QT5) - find_package(Qt5 COMPONENTS Core Gui OpenGL Widgets REQUIRED) +option(CEE_USE_QT5 "Use Qt5" OFF) + +if (CEE_USE_QT5) + find_package(Qt5Core CONFIG QUIET) +endif(CEE_USE_QT5) + +if (Qt5Core_FOUND) + find_package(Qt5 CONFIG REQUIRED Core Gui OpenGL Widgets) + set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::OpenGL Qt5::Widgets) else() - find_package(Qt4 COMPONENTS QtCore QtGui QtMain QtOpenGl REQUIRED) + find_package(Qt4 COMPONENTS QtCore QtGui QtMain QtOpenGl REQUIRED) include(${QT_USE_FILE}) -endif(CAF_USE_QT5) +endif(Qt5Core_FOUND) # Open GL find_package( OpenGL ) @@ -19,11 +26,11 @@ set( MOC_HEADER_FILES ) if ( NOT CMAKE_AUTOMOC ) - if (CAF_USE_QT5) + if (CEE_USE_QT5) qt5_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) else() qt4_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) - endif(CAF_USE_QT5) + endif(CEE_USE_QT5) endif() @@ -63,10 +70,6 @@ target_include_directories(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR} ) -if (CAF_USE_QT5) - set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::OpenGL Qt5::Widgets) -endif(CAF_USE_QT5) - target_link_libraries ( ${PROJECT_NAME} LibCore LibGeometry diff --git a/Fwk/AppFwk/cafAnimControl/CMakeLists.txt b/Fwk/AppFwk/cafAnimControl/CMakeLists.txt index bcefe1d8dc..803fac3c32 100644 --- a/Fwk/AppFwk/cafAnimControl/CMakeLists.txt +++ b/Fwk/AppFwk/cafAnimControl/CMakeLists.txt @@ -3,13 +3,19 @@ cmake_minimum_required (VERSION 2.8.12) project (cafAnimControl) # Qt -if (CAF_USE_QT5) - find_package(Qt5 COMPONENTS Core Gui OpenGL Widgets REQUIRED) -else() - find_package(Qt4 COMPONENTS QtCore QtGui QtMain REQUIRED) - include(${QT_USE_FILE}) -endif(CAF_USE_QT5) +option(CEE_USE_QT5 "Use Qt5" OFF) +if (CEE_USE_QT5) + find_package(Qt5Core CONFIG QUIET) +endif(CEE_USE_QT5) + +if (Qt5Core_FOUND) + find_package(Qt5 CONFIG REQUIRED Core Gui Widgets) + set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets) +else() + find_package(Qt4 COMPONENTS QtCore QtGui QtMain REQUIRED) + include(${QT_USE_FILE}) +endif(Qt5Core_FOUND) set( MOC_HEADER_FILES cafFrameAnimationControl.h @@ -17,11 +23,11 @@ set( MOC_HEADER_FILES cafPopupMenuButton.h ) -if (CAF_USE_QT5) +if (CEE_USE_QT5) qt5_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) else() qt4_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) -endif(CAF_USE_QT5) +endif(CEE_USE_QT5) # NOTE! Resources in this subfolder appends to the variable QRC_FILES in parent scope # CMakeList.txt in the application folder (parent scope) must use the following syntax @@ -57,10 +63,6 @@ target_include_directories(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR} ) -if (CAF_USE_QT5) - set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets) -endif(CAF_USE_QT5) - target_link_libraries(${PROJECT_NAME} ${QT_LIBRARIES}) if (MSVC) diff --git a/Fwk/AppFwk/cafCommand/CMakeLists.txt b/Fwk/AppFwk/cafCommand/CMakeLists.txt index 67e76d35d2..c2158272b1 100644 --- a/Fwk/AppFwk/cafCommand/CMakeLists.txt +++ b/Fwk/AppFwk/cafCommand/CMakeLists.txt @@ -1,12 +1,19 @@ cmake_minimum_required (VERSION 2.8.12) # Qt -if (CAF_USE_QT5) - find_package(Qt5 COMPONENTS Core Gui OpenGL Widgets REQUIRED) +option(CEE_USE_QT5 "Use Qt5" OFF) + +if (CEE_USE_QT5) + find_package(Qt5Core CONFIG QUIET) +endif(CEE_USE_QT5) + +if (Qt5Core_FOUND) + find_package(Qt5 CONFIG REQUIRED Core Gui Widgets) + set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets) else() - find_package(Qt4 COMPONENTS QtCore QtGui QtMain REQUIRED) + find_package(Qt4 COMPONENTS QtCore QtGui QtMain REQUIRED) include(${QT_USE_FILE}) -endif(CAF_USE_QT5) +endif(Qt5Core_FOUND) project (cafCommand) @@ -17,12 +24,11 @@ set (MOC_HEADER_FILES cafCmdFeatureManager.h ) -if (CAF_USE_QT5) +if (CEE_USE_QT5) qt5_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) - set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets) else() qt4_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) -endif(CAF_USE_QT5) +endif(CEE_USE_QT5) set( PROJECT_FILES diff --git a/Fwk/AppFwk/cafPdmCvf/CMakeLists.txt b/Fwk/AppFwk/cafPdmCvf/CMakeLists.txt index b5723987c4..10fd9b66bf 100644 --- a/Fwk/AppFwk/cafPdmCvf/CMakeLists.txt +++ b/Fwk/AppFwk/cafPdmCvf/CMakeLists.txt @@ -3,12 +3,19 @@ cmake_minimum_required (VERSION 2.8.12) project (cafPdmCvf) # Qt -if (CAF_USE_QT5) - find_package(Qt5 COMPONENTS Core Gui Widgets REQUIRED) +option(CEE_USE_QT5 "Use Qt5" OFF) + +if (CEE_USE_QT5) + find_package(Qt5Core CONFIG QUIET) +endif(CEE_USE_QT5) + +if (Qt5Core_FOUND) + find_package(Qt5 CONFIG REQUIRED Core Gui Widgets) + set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets) else() - find_package(Qt4 COMPONENTS QtCore QtGui QtMain REQUIRED) + find_package(Qt4 COMPONENTS QtCore QtGui QtMain REQUIRED) include(${QT_USE_FILE}) -endif(CAF_USE_QT5) +endif(Qt5Core_FOUND) add_definitions(-DCVF_USING_CMAKE) @@ -40,11 +47,6 @@ target_include_directories(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR} ) -if (CAF_USE_QT5) - set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets) -endif(CAF_USE_QT5) - - target_link_libraries ( ${PROJECT_NAME} cafUserInterface LibCore diff --git a/Fwk/AppFwk/cafProjectDataModel/CMakeLists.txt b/Fwk/AppFwk/cafProjectDataModel/CMakeLists.txt index 2158d47e6e..bf6fd891f8 100644 --- a/Fwk/AppFwk/cafProjectDataModel/CMakeLists.txt +++ b/Fwk/AppFwk/cafProjectDataModel/CMakeLists.txt @@ -3,12 +3,20 @@ cmake_minimum_required (VERSION 2.8.12) project (cafProjectDataModel) # Qt -if (CAF_USE_QT5) - find_package(Qt5 COMPONENTS Core Gui Widgets REQUIRED) +option(CEE_USE_QT5 "Use Qt5" OFF) + +if (CEE_USE_QT5) + find_package(Qt5Core CONFIG QUIET) +endif(CEE_USE_QT5) + +if (Qt5Core_FOUND) + find_package(Qt5 CONFIG REQUIRED Core Gui Widgets) + set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets) else() - find_package(Qt4 COMPONENTS QtCore QtGui REQUIRED) + find_package(Qt4 COMPONENTS QtCore QtGui REQUIRED) include(${QT_USE_FILE}) -endif(CAF_USE_QT5) +endif(Qt5Core_FOUND) + set( PROJECT_FILES cafFactory.h @@ -25,10 +33,6 @@ add_library( ${PROJECT_NAME} ${PROJECT_FILES} ) -if (CAF_USE_QT5) - set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets) -endif(CAF_USE_QT5) - target_link_libraries ( ${PROJECT_NAME} cafPdmUiCore cafPdmXml diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/CMakeLists.txt b/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/CMakeLists.txt index a7ed64a1a3..9127f513c6 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/CMakeLists.txt +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/CMakeLists.txt @@ -3,12 +3,19 @@ cmake_minimum_required (VERSION 2.8.12) project (cafPdmCore) # Qt -if (CAF_USE_QT5) - find_package(Qt5 COMPONENTS Core REQUIRED) +option(CEE_USE_QT5 "Use Qt5" OFF) + +if (CEE_USE_QT5) + find_package(Qt5Core CONFIG QUIET) +endif(CEE_USE_QT5) + +if (Qt5Core_FOUND) + find_package(Qt5 CONFIG REQUIRED Core) + set(QT_LIBRARIES Qt5::Core) else() - find_package(Qt4 COMPONENTS QtCore REQUIRED) + find_package(Qt4 COMPONENTS QtCore REQUIRED) include(${QT_USE_FILE}) -endif(CAF_USE_QT5) +endif(Qt5Core_FOUND) set( PROJECT_FILES @@ -64,10 +71,6 @@ target_include_directories(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR} ) -if (CAF_USE_QT5) - set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets) -endif(CAF_USE_QT5) - target_link_libraries(${PROJECT_NAME} ${QT_LIBRARIES}) if (MSVC) diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/CMakeLists.txt b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/CMakeLists.txt index 5b4305ef87..58254620b8 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/CMakeLists.txt +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/CMakeLists.txt @@ -3,13 +3,19 @@ cmake_minimum_required (VERSION 2.8.12) project (cafPdmUiCore) # Qt -if (CAF_USE_QT5) - find_package(Qt5 COMPONENTS Core Gui Widgets REQUIRED) -else() - find_package(Qt4 COMPONENTS QtCore QtGui REQUIRED) - include(${QT_USE_FILE}) -endif(CAF_USE_QT5) +option(CEE_USE_QT5 "Use Qt5" OFF) +if (CEE_USE_QT5) + find_package(Qt5Core CONFIG QUIET) +endif(CEE_USE_QT5) + +if (Qt5Core_FOUND) + find_package(Qt5 CONFIG REQUIRED Core Gui Widgets) + set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets) +else() + find_package(Qt4 COMPONENTS QtCore QtGui REQUIRED) + include(${QT_USE_FILE}) +endif(Qt5Core_FOUND) include_directories ( .. @@ -25,11 +31,11 @@ set (MOC_HEADER_FILES # Run MOC on the headers add_definitions(-DCVF_USING_CMAKE) -if (CAF_USE_QT5) +if (CEE_USE_QT5) qt5_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) else() qt4_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) -endif(CAF_USE_QT5) +endif(CEE_USE_QT5) set( PROJECT_FILES @@ -86,10 +92,6 @@ add_library( ${PROJECT_NAME} ${MOC_SOURCE_FILES} ) -if (CAF_USE_QT5) - set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets) -endif(CAF_USE_QT5) - target_link_libraries ( ${PROJECT_NAME} cafPdmCore ${QT_LIBRARIES} diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmXml/CMakeLists.txt b/Fwk/AppFwk/cafProjectDataModel/cafPdmXml/CMakeLists.txt index a734681847..8a46c2984f 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmXml/CMakeLists.txt +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmXml/CMakeLists.txt @@ -3,12 +3,19 @@ cmake_minimum_required (VERSION 2.8.12) project (cafPdmXml) # Qt -if (CAF_USE_QT5) - find_package(Qt5 COMPONENTS Core Xml REQUIRED) +option(CEE_USE_QT5 "Use Qt5" OFF) + +if (CEE_USE_QT5) + find_package(Qt5Core CONFIG QUIET) +endif(CEE_USE_QT5) + +if (Qt5Core_FOUND) + find_package(Qt5 CONFIG REQUIRED Core Xml) + set(QT_LIBRARIES Qt5::Core Qt5::Xml) else() - find_package(Qt4 COMPONENTS QtCore QtXml REQUIRED) + find_package(Qt4 COMPONENTS QtCore QtXml REQUIRED) include(${QT_USE_FILE}) -endif(CAF_USE_QT5) +endif(Qt5Core_FOUND) include_directories ( .. @@ -48,10 +55,6 @@ add_library( ${PROJECT_NAME} ${PROJECT_FILES} ) -if (CAF_USE_QT5) - set(QT_LIBRARIES Qt5::Core Qt5::Xml) -endif(CAF_USE_QT5) - target_link_libraries ( ${PROJECT_NAME} cafPdmCore ${QT_LIBRARIES} diff --git a/Fwk/AppFwk/cafUserInterface/CMakeLists.txt b/Fwk/AppFwk/cafUserInterface/CMakeLists.txt index 954afb1457..c5fe918919 100644 --- a/Fwk/AppFwk/cafUserInterface/CMakeLists.txt +++ b/Fwk/AppFwk/cafUserInterface/CMakeLists.txt @@ -8,12 +8,19 @@ endif (MSVC) project (cafUserInterface) # Qt -if (CAF_USE_QT5) - find_package(Qt5 COMPONENTS Core Gui Widgets REQUIRED) +option(CEE_USE_QT5 "Use Qt5" OFF) + +if (CEE_USE_QT5) + find_package(Qt5Core CONFIG QUIET) +endif(CEE_USE_QT5) + +if (Qt5Core_FOUND) + find_package(Qt5 CONFIG REQUIRED Core Gui Widgets) + set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets) else() find_package(Qt4 COMPONENTS QtCore QtGui QtMain REQUIRED) include(${QT_USE_FILE}) -endif(CAF_USE_QT5) +endif(Qt5Core_FOUND) # These headers need to go through Qt's MOC compiler set (MOC_HEADER_FILES @@ -55,11 +62,11 @@ set (MOC_HEADER_FILES ) if ( NOT CMAKE_AUTOMOC ) - if (CAF_USE_QT5) + if (CEE_USE_QT5) qt5_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) else() qt4_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) - endif(CAF_USE_QT5) + endif(CEE_USE_QT5) endif() @@ -180,10 +187,6 @@ target_include_directories(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR} ) -if (CAF_USE_QT5) - set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets) -endif(CAF_USE_QT5) - target_link_libraries ( ${PROJECT_NAME} cafProjectDataModel ${QT_LIBRARIES} diff --git a/Fwk/AppFwk/cafViewer/CMakeLists.txt b/Fwk/AppFwk/cafViewer/CMakeLists.txt index d08144d34e..5adb82f5f0 100644 --- a/Fwk/AppFwk/cafViewer/CMakeLists.txt +++ b/Fwk/AppFwk/cafViewer/CMakeLists.txt @@ -3,12 +3,19 @@ cmake_minimum_required (VERSION 2.8.12) project (cafViewer) # Qt -if (CAF_USE_QT5) - find_package(Qt5 COMPONENTS Core Gui OpenGL Widgets REQUIRED) +option(CEE_USE_QT5 "Use Qt5" OFF) + +if (CEE_USE_QT5) + find_package(Qt5Core CONFIG QUIET) +endif(CEE_USE_QT5) + +if (Qt5Core_FOUND) + find_package(Qt5 CONFIG REQUIRED Core Gui Widgets OpenGL) + set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets Qt5::OpenGL) else() - find_package(Qt4 COMPONENTS QtCore QtGui QtMain QtOpenGl REQUIRED) + find_package(Qt4 COMPONENTS QtCore QtGui QtMain QtOpenGl REQUIRED) include(${QT_USE_FILE}) -endif(CAF_USE_QT5) +endif(Qt5Core_FOUND) # These headers need to go through Qt's MOC compiler set( MOC_HEADER_FILES @@ -16,11 +23,11 @@ set( MOC_HEADER_FILES ) if ( NOT CMAKE_AUTOMOC ) - if (CAF_USE_QT5) + if (CEE_USE_QT5) qt5_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) else() qt4_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) - endif(CAF_USE_QT5) + endif(CEE_USE_QT5) endif() @@ -48,10 +55,6 @@ target_include_directories(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR} ) -if (CAF_USE_QT5) - set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::OpenGL Qt5::Widgets) -endif(CAF_USE_QT5) - target_link_libraries ( ${PROJECT_NAME} LibCore LibGeometry diff --git a/Fwk/AppFwk/cafVizExtensions/CMakeLists.txt b/Fwk/AppFwk/cafVizExtensions/CMakeLists.txt index de2c6a8bf7..0fce4a32ab 100644 --- a/Fwk/AppFwk/cafVizExtensions/CMakeLists.txt +++ b/Fwk/AppFwk/cafVizExtensions/CMakeLists.txt @@ -6,12 +6,19 @@ project (cafVizExtensions) find_package( OpenGL ) # Qt -if (CAF_USE_QT5) - find_package(Qt5 COMPONENTS Core Gui OpenGL Widgets REQUIRED) +option(CEE_USE_QT5 "Use Qt5" OFF) + +if (CEE_USE_QT5) + find_package(Qt5Core CONFIG QUIET) +endif(CEE_USE_QT5) + +if (Qt5Core_FOUND) + find_package(Qt5 CONFIG REQUIRED Core Gui Widgets OpenGL) + set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets Qt5::OpenGL) else() - find_package(Qt4 COMPONENTS QtCore QtGui QtMain QtOpenGl REQUIRED) + find_package(Qt4 COMPONENTS QtCore QtGui QtMain QtOpenGl REQUIRED) include(${QT_USE_FILE}) -endif(CAF_USE_QT5) +endif(Qt5Core_FOUND) add_library( ${PROJECT_NAME} cafDisplayCoordTransform.cpp @@ -51,11 +58,6 @@ target_include_directories(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR} ) - -if (CAF_USE_QT5) - set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::OpenGL Qt5::Widgets) -endif(CAF_USE_QT5) - target_link_libraries ( ${PROJECT_NAME} LibCore LibGeometry From 0544b19afe07c0e3acba5bd21568ab5a496fe61e Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Tue, 28 May 2019 10:48:41 +0200 Subject: [PATCH 096/396] Fix carriage return difference in CafPdmModel_UnitTests --- .../cafProjectDataModel_UnitTests/cafPdmBasicTest.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Fwk/AppFwk/cafProjectDataModel/cafProjectDataModel_UnitTests/cafPdmBasicTest.cpp b/Fwk/AppFwk/cafProjectDataModel/cafProjectDataModel_UnitTests/cafPdmBasicTest.cpp index fd63e90882..3ef78d1d41 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafProjectDataModel_UnitTests/cafPdmBasicTest.cpp +++ b/Fwk/AppFwk/cafProjectDataModel/cafProjectDataModel_UnitTests/cafPdmBasicTest.cpp @@ -580,7 +580,7 @@ TEST(BaseTest, ReadWrite) // Write file QFile xmlFile("PdmTestFil2.xml"); - xmlFile.open(QIODevice::WriteOnly); + xmlFile.open(QIODevice::WriteOnly | QIODevice::Text); xmlDoc.writeFile(&xmlFile); xmlFile.close(); } @@ -590,8 +590,8 @@ TEST(BaseTest, ReadWrite) QFile f1("PdmTestFil.xml"); QFile f2("PdmTestFil2.xml"); - f1.open(QIODevice::ReadOnly); - f2.open(QIODevice::ReadOnly); + f1.open(QIODevice::ReadOnly | QIODevice::Text); + f2.open(QIODevice::ReadOnly | QIODevice::Text); QByteArray ba1 = f1.readAll(); QByteArray ba2 = f2.readAll(); bool equal = ba1 == ba2; @@ -672,7 +672,7 @@ TEST(BaseTest, ReadWrite) // Write the edited document QFile f3("PdmTestFilWithError.xml"); - f3.open(QIODevice::WriteOnly); + f3.open(QIODevice::WriteOnly | QIODevice::Text); f3.write(ba1); f3.close(); From 10afe4987b349eb3b178b15b41affa0049cdbe0a Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Tue, 28 May 2019 10:50:39 +0200 Subject: [PATCH 097/396] #4448 Clean up CAF Qt5-enabling/detection --- Fwk/AppFwk/CMakeLists.txt | 9 +-- Fwk/AppFwk/CommonCode/CMakeLists.txt | 34 ++++----- Fwk/AppFwk/cafAnimControl/CMakeLists.txt | 20 ++---- Fwk/AppFwk/cafCommand/CMakeLists.txt | 22 ++---- Fwk/AppFwk/cafPdmCvf/CMakeLists.txt | 10 ++- Fwk/AppFwk/cafProjectDataModel/CMakeLists.txt | 11 +-- .../cafPdmCore/CMakeLists.txt | 9 +-- .../cafPdmUiCore/CMakeLists.txt | 34 ++++----- .../cafPdmXml/CMakeLists.txt | 10 +-- .../CMakeLists.txt | 26 +++---- .../cafTestApplication/CMakeLists.txt | 55 ++++++--------- .../cafTestCvfApplication/CMakeLists.txt | 69 +++++++------------ Fwk/AppFwk/cafUserInterface/CMakeLists.txt | 36 ++++------ .../cafUserInterface_UnitTests/CMakeLists.txt | 24 +++---- Fwk/AppFwk/cafViewer/CMakeLists.txt | 30 +++----- Fwk/AppFwk/cafVizExtensions/CMakeLists.txt | 10 ++- 16 files changed, 149 insertions(+), 260 deletions(-) diff --git a/Fwk/AppFwk/CMakeLists.txt b/Fwk/AppFwk/CMakeLists.txt index 0ecc7049e1..4b1ccbb5b1 100644 --- a/Fwk/AppFwk/CMakeLists.txt +++ b/Fwk/AppFwk/CMakeLists.txt @@ -12,15 +12,12 @@ endif() option(CEE_USE_QT5 "Use Qt5" OFF) if (CEE_USE_QT5) - find_package(Qt5Core CONFIG QUIET) -endif(CEE_USE_QT5) - -if (Qt5Core_FOUND) - find_package(Qt5 CONFIG REQUIRED Core Gui OpenGL Widgets) + find_package(Qt5 COMPONENTS REQUIRED Core Gui OpenGL Widgets) + set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::OpenGL Qt5::Widgets) else() find_package(Qt4 COMPONENTS QtCore QtGui QtMain QtOpenGl REQUIRED) include(${QT_USE_FILE}) -endif(Qt5Core_FOUND) +endif(CEE_USE_QT5) if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") set(CMAKE_CXX_FLAGS "-std=c++0x") diff --git a/Fwk/AppFwk/CommonCode/CMakeLists.txt b/Fwk/AppFwk/CommonCode/CMakeLists.txt index 0ebb007610..6fe78fd8f6 100644 --- a/Fwk/AppFwk/CommonCode/CMakeLists.txt +++ b/Fwk/AppFwk/CommonCode/CMakeLists.txt @@ -2,37 +2,27 @@ cmake_minimum_required (VERSION 2.8.12) project (CommonCode) -# Qt -option(CEE_USE_QT5 "Use Qt5" OFF) - -if (CEE_USE_QT5) - find_package(Qt5Core CONFIG QUIET) -endif(CEE_USE_QT5) - -if (Qt5Core_FOUND) - find_package(Qt5 CONFIG REQUIRED Core Gui OpenGL Widgets) - set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::OpenGL Qt5::Widgets) -else() - find_package(Qt4 COMPONENTS QtCore QtGui QtMain QtOpenGl REQUIRED) - include(${QT_USE_FILE}) -endif(Qt5Core_FOUND) - # Open GL find_package( OpenGL ) +# Qt + # These headers need to go through Qt's MOC compiler set( MOC_HEADER_FILES cafMessagePanel.h ) -if ( NOT CMAKE_AUTOMOC ) - if (CEE_USE_QT5) - qt5_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) - else() - qt4_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) - endif(CEE_USE_QT5) -endif() +option(CEE_USE_QT5 "Use Qt5" OFF) +if (CEE_USE_QT5) + find_package(Qt5 COMPONENTS REQUIRED Core Gui Widgets OpenGL) + set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets Qt5::OpenGL) + qt5_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) +else() + find_package(Qt4 COMPONENTS QtCore QtGui QtMain QtOpenGl REQUIRED) + include(${QT_USE_FILE}) + qt4_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) +endif(CEE_USE_QT5) add_library( ${PROJECT_NAME} cafEffectCache.cpp diff --git a/Fwk/AppFwk/cafAnimControl/CMakeLists.txt b/Fwk/AppFwk/cafAnimControl/CMakeLists.txt index 803fac3c32..7c8be9ae6c 100644 --- a/Fwk/AppFwk/cafAnimControl/CMakeLists.txt +++ b/Fwk/AppFwk/cafAnimControl/CMakeLists.txt @@ -3,29 +3,21 @@ cmake_minimum_required (VERSION 2.8.12) project (cafAnimControl) # Qt -option(CEE_USE_QT5 "Use Qt5" OFF) - -if (CEE_USE_QT5) - find_package(Qt5Core CONFIG QUIET) -endif(CEE_USE_QT5) - -if (Qt5Core_FOUND) - find_package(Qt5 CONFIG REQUIRED Core Gui Widgets) - set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets) -else() - find_package(Qt4 COMPONENTS QtCore QtGui QtMain REQUIRED) - include(${QT_USE_FILE}) -endif(Qt5Core_FOUND) - set( MOC_HEADER_FILES cafFrameAnimationControl.h cafAnimationToolBar.h cafPopupMenuButton.h ) +option(CEE_USE_QT5 "Use Qt5" OFF) + if (CEE_USE_QT5) + find_package(Qt5 COMPONENTS REQUIRED Core Gui Widgets) + set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets) qt5_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) else() + find_package(Qt4 COMPONENTS QtCore QtGui QtMain REQUIRED) + include(${QT_USE_FILE}) qt4_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) endif(CEE_USE_QT5) diff --git a/Fwk/AppFwk/cafCommand/CMakeLists.txt b/Fwk/AppFwk/cafCommand/CMakeLists.txt index c2158272b1..9ab9f8261e 100644 --- a/Fwk/AppFwk/cafCommand/CMakeLists.txt +++ b/Fwk/AppFwk/cafCommand/CMakeLists.txt @@ -1,20 +1,5 @@ cmake_minimum_required (VERSION 2.8.12) -# Qt -option(CEE_USE_QT5 "Use Qt5" OFF) - -if (CEE_USE_QT5) - find_package(Qt5Core CONFIG QUIET) -endif(CEE_USE_QT5) - -if (Qt5Core_FOUND) - find_package(Qt5 CONFIG REQUIRED Core Gui Widgets) - set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets) -else() - find_package(Qt4 COMPONENTS QtCore QtGui QtMain REQUIRED) - include(${QT_USE_FILE}) -endif(Qt5Core_FOUND) - project (cafCommand) @@ -24,9 +9,16 @@ set (MOC_HEADER_FILES cafCmdFeatureManager.h ) +# Qt +option(CEE_USE_QT5 "Use Qt5" OFF) + if (CEE_USE_QT5) + find_package(Qt5 COMPONENTS REQUIRED Core Gui Widgets) + set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets) qt5_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) else() + find_package(Qt4 COMPONENTS QtCore QtGui QtMain REQUIRED) + include(${QT_USE_FILE}) qt4_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) endif(CEE_USE_QT5) diff --git a/Fwk/AppFwk/cafPdmCvf/CMakeLists.txt b/Fwk/AppFwk/cafPdmCvf/CMakeLists.txt index 10fd9b66bf..1a0f8d0c35 100644 --- a/Fwk/AppFwk/cafPdmCvf/CMakeLists.txt +++ b/Fwk/AppFwk/cafPdmCvf/CMakeLists.txt @@ -6,16 +6,14 @@ project (cafPdmCvf) option(CEE_USE_QT5 "Use Qt5" OFF) if (CEE_USE_QT5) - find_package(Qt5Core CONFIG QUIET) -endif(CEE_USE_QT5) - -if (Qt5Core_FOUND) - find_package(Qt5 CONFIG REQUIRED Core Gui Widgets) + find_package(Qt5 COMPONENTS REQUIRED Core Gui Widgets) set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets) + qt5_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) else() find_package(Qt4 COMPONENTS QtCore QtGui QtMain REQUIRED) include(${QT_USE_FILE}) -endif(Qt5Core_FOUND) + qt4_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) +endif(CEE_USE_QT5) add_definitions(-DCVF_USING_CMAKE) diff --git a/Fwk/AppFwk/cafProjectDataModel/CMakeLists.txt b/Fwk/AppFwk/cafProjectDataModel/CMakeLists.txt index bf6fd891f8..6f760559b0 100644 --- a/Fwk/AppFwk/cafProjectDataModel/CMakeLists.txt +++ b/Fwk/AppFwk/cafProjectDataModel/CMakeLists.txt @@ -6,17 +6,12 @@ project (cafProjectDataModel) option(CEE_USE_QT5 "Use Qt5" OFF) if (CEE_USE_QT5) - find_package(Qt5Core CONFIG QUIET) -endif(CEE_USE_QT5) - -if (Qt5Core_FOUND) - find_package(Qt5 CONFIG REQUIRED Core Gui Widgets) + find_package(Qt5 COMPONENTS REQUIRED Core Gui Widgets) set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets) else() - find_package(Qt4 COMPONENTS QtCore QtGui REQUIRED) + find_package(Qt4 COMPONENTS REQUIRED QtCore QtGui) include(${QT_USE_FILE}) -endif(Qt5Core_FOUND) - +endif(CEE_USE_QT5) set( PROJECT_FILES cafFactory.h diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/CMakeLists.txt b/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/CMakeLists.txt index 9127f513c6..f8c2898012 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/CMakeLists.txt +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/CMakeLists.txt @@ -1,21 +1,16 @@ cmake_minimum_required (VERSION 2.8.12) - project (cafPdmCore) # Qt option(CEE_USE_QT5 "Use Qt5" OFF) if (CEE_USE_QT5) - find_package(Qt5Core CONFIG QUIET) -endif(CEE_USE_QT5) - -if (Qt5Core_FOUND) - find_package(Qt5 CONFIG REQUIRED Core) + find_package(Qt5 COMPONENTS REQUIRED Core) set(QT_LIBRARIES Qt5::Core) else() find_package(Qt4 COMPONENTS QtCore REQUIRED) include(${QT_USE_FILE}) -endif(Qt5Core_FOUND) +endif(CEE_USE_QT5) set( PROJECT_FILES diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/CMakeLists.txt b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/CMakeLists.txt index 58254620b8..7ad8a54821 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/CMakeLists.txt +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/CMakeLists.txt @@ -2,25 +2,6 @@ cmake_minimum_required (VERSION 2.8.12) project (cafPdmUiCore) -# Qt -option(CEE_USE_QT5 "Use Qt5" OFF) - -if (CEE_USE_QT5) - find_package(Qt5Core CONFIG QUIET) -endif(CEE_USE_QT5) - -if (Qt5Core_FOUND) - find_package(Qt5 CONFIG REQUIRED Core Gui Widgets) - set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets) -else() - find_package(Qt4 COMPONENTS QtCore QtGui REQUIRED) - include(${QT_USE_FILE}) -endif(Qt5Core_FOUND) - -include_directories ( - .. -) - # These headers need to go through Qt's MOC compiler set (MOC_HEADER_FILES cafPdmUiEditorHandle.h @@ -29,14 +10,25 @@ set (MOC_HEADER_FILES cafQShortenedLabel.h ) -# Run MOC on the headers -add_definitions(-DCVF_USING_CMAKE) +# Qt +option(CEE_USE_QT5 "Use Qt5" OFF) + if (CEE_USE_QT5) + find_package(Qt5 COMPONENTS REQUIRED Core Gui Widgets) + set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets) qt5_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) else() + find_package(Qt4 COMPONENTS QtCore QtGui QtMain REQUIRED) + include(${QT_USE_FILE}) qt4_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) endif(CEE_USE_QT5) +include_directories ( + .. +) + +add_definitions(-DCVF_USING_CMAKE) + set( PROJECT_FILES cafInternalPdmFieldTypeSpecializations.h diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmXml/CMakeLists.txt b/Fwk/AppFwk/cafProjectDataModel/cafPdmXml/CMakeLists.txt index 8a46c2984f..6cf05f2cf2 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmXml/CMakeLists.txt +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmXml/CMakeLists.txt @@ -6,16 +6,12 @@ project (cafPdmXml) option(CEE_USE_QT5 "Use Qt5" OFF) if (CEE_USE_QT5) - find_package(Qt5Core CONFIG QUIET) -endif(CEE_USE_QT5) - -if (Qt5Core_FOUND) - find_package(Qt5 CONFIG REQUIRED Core Xml) - set(QT_LIBRARIES Qt5::Core Qt5::Xml) + find_package(Qt5 COMPONENTS REQUIRED Core Xml) + set(QT_LIBRARIES Qt5::Core Qt5::Xml) else() find_package(Qt4 COMPONENTS QtCore QtXml REQUIRED) include(${QT_USE_FILE}) -endif(Qt5Core_FOUND) +endif(CEE_USE_QT5) include_directories ( .. diff --git a/Fwk/AppFwk/cafProjectDataModel/cafProjectDataModel_UnitTests/CMakeLists.txt b/Fwk/AppFwk/cafProjectDataModel/cafProjectDataModel_UnitTests/CMakeLists.txt index d675cf7e2f..673b7861ff 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafProjectDataModel_UnitTests/CMakeLists.txt +++ b/Fwk/AppFwk/cafProjectDataModel/cafProjectDataModel_UnitTests/CMakeLists.txt @@ -2,13 +2,17 @@ cmake_minimum_required (VERSION 2.8.12) project ( cafProjectDataModel_UnitTests ) -find_package(Qt5Core CONFIG QUIET) -if (Qt5Core_FOUND) - find_package(Qt5 CONFIG REQUIRED Core Xml) +# Qt +option(CEE_USE_QT5 "Use Qt5" OFF) + +if (CEE_USE_QT5) + find_package(Qt5 COMPONENTS REQUIRED Core Xml Gui) + set(QT_LIBRARIES Qt5::Core Qt5::Xml Qt5::Gui) else() - find_package(Qt4 COMPONENTS QtCore QtXml REQUIRED) - include(${QT_USE_FILE}) -endif(Qt5Core_FOUND) + find_package(Qt4 COMPONENTS REQUIRED QtCore QtXml QtGui) + include(${QT_USE_FILE}) +endif(CEE_USE_QT5) + if (MSVC AND (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 19.11)) # VS 2017 : Disable warnings from from gtest code, using deprecated code related to TR1 @@ -34,10 +38,6 @@ add_executable (${PROJECT_NAME} gtest/gtest-all.cpp ) -if (Qt5Core_FOUND) - set(QT_LIBRARIES Qt5::Core Qt5::Xml) -endif() - target_link_libraries ( ${PROJECT_NAME} cafProjectDataModel ${QT_LIBRARIES} @@ -47,7 +47,7 @@ target_link_libraries ( ${PROJECT_NAME} source_group("" FILES ${PROJECT_FILES}) # Copy Qt Dlls -if (Qt5Core_FOUND) +if (CEE_USE_QT5) foreach (qtlib ${QT_LIBRARIES}) add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different $ $ @@ -57,7 +57,7 @@ if (Qt5Core_FOUND) else() # Copy Qt Dlls if (MSVC) - set (QTLIBLIST QtCore QtGui) + set (QTLIBLIST QtCore QtXml) foreach (qtlib ${QTLIBLIST}) # Debug @@ -67,4 +67,4 @@ else() execute_process(COMMAND cmake -E copy_if_different ${QT_BINARY_DIR}/${qtlib}4.dll ${CMAKE_BINARY_DIR}/Release/${qtlib}4.dll) endforeach( qtlib ) endif(MSVC) -endif(Qt5Core_FOUND) \ No newline at end of file +endif(CEE_USE_QT5) \ No newline at end of file diff --git a/Fwk/AppFwk/cafTests/cafTestApplication/CMakeLists.txt b/Fwk/AppFwk/cafTests/cafTestApplication/CMakeLists.txt index 4a79920601..ae86aea5b6 100644 --- a/Fwk/AppFwk/cafTests/cafTestApplication/CMakeLists.txt +++ b/Fwk/AppFwk/cafTests/cafTestApplication/CMakeLists.txt @@ -6,18 +6,6 @@ project ( cafTestApplication ) find_package( OpenGL ) # Qt -find_package(Qt5Core CONFIG QUIET) -if (Qt5Core_FOUND) - find_package(Qt5 CONFIG REQUIRED Core Gui OpenGL Widgets) -else() - find_package(Qt4 COMPONENTS QtCore QtGui QtMain QtOpenGl REQUIRED) - include(${QT_USE_FILE}) -endif(Qt5Core_FOUND) - - - - -option(USE_COMMAND_FRAMEWORK "Use Caf Command Framework" ON) # Qt MOC set (MOC_HEADER_FILES @@ -27,25 +15,26 @@ set (MOC_HEADER_FILES MenuItemProducer.h ) -if ( NOT CMAKE_AUTOMOC ) - if (Qt5Core_FOUND) - qt5_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) - else() - qt4_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) - endif() -endif() - # Resource file set( QRC_FILES textedit.qrc ) -# Runs RCC on specified files -if (Qt5Core_FOUND) +option(CEE_USE_QT5 "Use Qt5" OFF) + +if (CEE_USE_QT5) + find_package(Qt5 COMPONENTS REQUIRED Core Gui Widgets OpenGL) + set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets Qt5::OpenGL) + qt5_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) qt5_add_resources( QRC_FILES_CPP ${QRC_FILES} ) else() + find_package(Qt4 COMPONENTS REQUIRED QtCore QtGui QtMain QtOpenGl) + include(${QT_USE_FILE}) + qt4_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) qt4_add_resources( QRC_FILES_CPP ${QRC_FILES} ) -endif() +endif(CEE_USE_QT5) + +option(USE_COMMAND_FRAMEWORK "Use Caf Command Framework" ON) if (USE_COMMAND_FRAMEWORK) include_directories ( @@ -100,28 +89,24 @@ target_link_libraries ( ${PROJECT_NAME} source_group("" FILES ${PROJECT_FILES}) -# Copy Qt Dlls -if (Qt5Core_FOUND) +if (CEE_USE_QT5) foreach (qtlib ${QT_LIBRARIES}) add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different $ $ - ) + ) endforeach(qtlib) - # Copy Qt Dlls else() # Copy Qt Dlls if (MSVC) - set (QTLIBLIST QtCore QtGui QtOpenGl ) + set (QTLIBLIST QtCore QtGui QtOpenGl QtXml) foreach (qtlib ${QTLIBLIST}) - - # Debug - execute_process(COMMAND cmake -E copy_if_different ${QT_BINARY_DIR}/${qtlib}d4.dll ${CMAKE_BINARY_DIR}/Debug/${qtlib}d4.dll) - - # Release - execute_process(COMMAND cmake -E copy_if_different ${QT_BINARY_DIR}/${qtlib}4.dll ${CMAKE_BINARY_DIR}/Release/${qtlib}4.dll) + add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${QT_BINARY_DIR}/$,${qtlib}d4.dll,${qtlib}4.dll> $ + ) endforeach( qtlib ) endif(MSVC) -endif(Qt5Core_FOUND) +endif(CEE_USE_QT5) + # cotire if (COMMAND caf_apply_cotire) diff --git a/Fwk/AppFwk/cafTests/cafTestCvfApplication/CMakeLists.txt b/Fwk/AppFwk/cafTests/cafTestCvfApplication/CMakeLists.txt index 3109c0531f..e5380aed1f 100644 --- a/Fwk/AppFwk/cafTests/cafTestCvfApplication/CMakeLists.txt +++ b/Fwk/AppFwk/cafTests/cafTestCvfApplication/CMakeLists.txt @@ -1,46 +1,38 @@ cmake_minimum_required (VERSION 2.8) -# Qt -find_package(Qt5 CONFIG COMPONENTS Core) -if (Qt5Core_FOUND) - find_package(Qt5 CONFIG REQUIRED Core Gui OpenGl Widgets) -else() - find_package(Qt4 COMPONENTS QtCore QtGui QtMain QtOpenGl REQUIRED) - include(${QT_USE_FILE}) -endif(Qt5Core_FOUND) - project ( cafTestCvfApplication ) -option(USE_COMMAND_FRAMEWORK "Use Caf Command Framework" ON) - # Qt MOC set ( MOC_HEADER_FILES MainWindow.h WidgetLayoutTest.h ) -if (Qt5Core_FOUND) - qt5_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) -else() - qt4_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) -endif() - # Resource file set( QRC_FILES textedit.qrc ) -# Runs RCC on specified files -if (Qt5Core_FOUND) - qt5_add_resources( QRC_FILES_CPP - ${QRC_FILES} - ) +# Qt +option(CEE_USE_QT5 "Use Qt5" OFF) + +if (CEE_USE_QT5) + find_package(Qt5 COMPONENTS REQUIRED Core Gui Widgets OpenGL) + set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets Qt5::OpenGL) + qt5_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) + qt5_add_resources( QRC_FILES_CPP ${QRC_FILES} ) else() - qt4_add_resources( QRC_FILES_CPP - ${QRC_FILES} - ) -endif() + find_package(Qt4 COMPONENTS REQUIRED QtCore QtGui QtMain QtOpenGl) + include(${QT_USE_FILE}) + qt4_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) + qt4_add_resources( QRC_FILES_CPP ${QRC_FILES} ) +endif(CEE_USE_QT5) + + + + +option(USE_COMMAND_FRAMEWORK "Use Caf Command Framework" ON) include_directories ( ${LibCore_SOURCE_DIR} @@ -86,11 +78,6 @@ add_executable ( ${PROJECT_NAME} ${QRC_FILES_CPP} ) - -if (Qt5Core_FOUND) - set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::OpenGl Qt5::Widgets) -endif() - set (TAP_LINK_LIBRARIES cafUserInterface cafPdmXml @@ -112,25 +99,21 @@ target_link_libraries ( ${PROJECT_NAME} source_group("" FILES ${PROJECT_FILES}) -# Copy Qt Dlls -if (Qt5Core_FOUND) +if (CEE_USE_QT5) foreach (qtlib ${QT_LIBRARIES}) add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different $ $ - ) + ) endforeach(qtlib) - # Copy Qt Dlls else() # Copy Qt Dlls if (MSVC) - set (QTLIBLIST QtCore QtGui QtOpenGl ) + set (QTLIBLIST QtCore QtGui QtOpenGl) foreach (qtlib ${QTLIBLIST}) - - # Debug - execute_process(COMMAND cmake -E copy_if_different ${QT_BINARY_DIR}/${qtlib}d4.dll ${CMAKE_BINARY_DIR}/Debug/${qtlib}d4.dll) - - # Release - execute_process(COMMAND cmake -E copy_if_different ${QT_BINARY_DIR}/${qtlib}4.dll ${CMAKE_BINARY_DIR}/Release/${qtlib}4.dll) + add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${QT_BINARY_DIR}/$,${qtlib}d4.dll,${qtlib}4.dll> $ + ) endforeach( qtlib ) endif(MSVC) -endif(Qt5Core_FOUND) +endif(CEE_USE_QT5) + diff --git a/Fwk/AppFwk/cafUserInterface/CMakeLists.txt b/Fwk/AppFwk/cafUserInterface/CMakeLists.txt index c5fe918919..4c254fcbc4 100644 --- a/Fwk/AppFwk/cafUserInterface/CMakeLists.txt +++ b/Fwk/AppFwk/cafUserInterface/CMakeLists.txt @@ -1,27 +1,12 @@ cmake_minimum_required (VERSION 2.8.12) +project (cafUserInterface) + if (MSVC) # Define this one to tell windows.h to not define min() and max() as macros add_definitions(-DNOMINMAX) endif (MSVC) -project (cafUserInterface) - -# Qt -option(CEE_USE_QT5 "Use Qt5" OFF) - -if (CEE_USE_QT5) - find_package(Qt5Core CONFIG QUIET) -endif(CEE_USE_QT5) - -if (Qt5Core_FOUND) - find_package(Qt5 CONFIG REQUIRED Core Gui Widgets) - set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets) -else() - find_package(Qt4 COMPONENTS QtCore QtGui QtMain REQUIRED) - include(${QT_USE_FILE}) -endif(Qt5Core_FOUND) - # These headers need to go through Qt's MOC compiler set (MOC_HEADER_FILES cafPdmUiCheckBoxDelegate.h @@ -61,14 +46,17 @@ set (MOC_HEADER_FILES cafPdmUiPickableLineEditor.h ) -if ( NOT CMAKE_AUTOMOC ) - if (CEE_USE_QT5) - qt5_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) - else() - qt4_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) - endif(CEE_USE_QT5) -endif() +option(CEE_USE_QT5 "Use Qt5" OFF) +if (CEE_USE_QT5) + find_package(Qt5 COMPONENTS REQUIRED Core Gui Widgets) + set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets) + qt5_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) +else() + find_package(Qt4 COMPONENTS QtCore QtGui QtMain REQUIRED) + include(${QT_USE_FILE}) + qt4_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) +endif(CEE_USE_QT5) set( PROJECT_FILES diff --git a/Fwk/AppFwk/cafUserInterface/cafUserInterface_UnitTests/CMakeLists.txt b/Fwk/AppFwk/cafUserInterface/cafUserInterface_UnitTests/CMakeLists.txt index 214fc545bc..b2a22f0f40 100644 --- a/Fwk/AppFwk/cafUserInterface/cafUserInterface_UnitTests/CMakeLists.txt +++ b/Fwk/AppFwk/cafUserInterface/cafUserInterface_UnitTests/CMakeLists.txt @@ -1,20 +1,22 @@ cmake_minimum_required (VERSION 2.8.12) -find_package(Qt5 CONFIG COMPONENTS Core) -if (Qt5Core_FOUND) - find_package(Qt5 CONFIG REQUIRED Core Gui Widgets) -else() - find_package(Qt4 COMPONENTS QtCore QtGui QtMain REQUIRED) - include(${QT_USE_FILE}) -endif(Qt5Core_FOUND) - project ( cafUserInterface_UnitTests ) +# Qt +option(CEE_USE_QT5 "Use Qt5" OFF) + +if (CEE_USE_QT5) + find_package(Qt5 COMPONENTS REQUIRED Core Gui Widgets) + set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets) +else() + find_package(Qt4 COMPONENTS QtCore QtGui QtMain REQUIRED) + include(${QT_USE_FILE}) +endif(CEE_USE_QT5) + include_directories ( ${CMAKE_CURRENT_SOURCE_DIR} ) - set( PROJECT_FILES cafUserInterface_UnitTests.cpp @@ -32,10 +34,6 @@ add_executable (${PROJECT_NAME} source_group("" FILES ${PROJECT_FILES}) -if (Qt5Core_FOUND) - set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets) -endif() - target_link_libraries ( ${PROJECT_NAME} cafUserInterface ${QT_LIBRARIES} diff --git a/Fwk/AppFwk/cafViewer/CMakeLists.txt b/Fwk/AppFwk/cafViewer/CMakeLists.txt index 5adb82f5f0..02a7fa0977 100644 --- a/Fwk/AppFwk/cafViewer/CMakeLists.txt +++ b/Fwk/AppFwk/cafViewer/CMakeLists.txt @@ -3,33 +3,23 @@ cmake_minimum_required (VERSION 2.8.12) project (cafViewer) # Qt -option(CEE_USE_QT5 "Use Qt5" OFF) - -if (CEE_USE_QT5) - find_package(Qt5Core CONFIG QUIET) -endif(CEE_USE_QT5) - -if (Qt5Core_FOUND) - find_package(Qt5 CONFIG REQUIRED Core Gui Widgets OpenGL) - set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets Qt5::OpenGL) -else() - find_package(Qt4 COMPONENTS QtCore QtGui QtMain QtOpenGl REQUIRED) - include(${QT_USE_FILE}) -endif(Qt5Core_FOUND) # These headers need to go through Qt's MOC compiler set( MOC_HEADER_FILES cafViewer.h ) -if ( NOT CMAKE_AUTOMOC ) - if (CEE_USE_QT5) - qt5_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) - else() - qt4_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) - endif(CEE_USE_QT5) -endif() +option(CEE_USE_QT5 "Use Qt5" OFF) +if (CEE_USE_QT5) + find_package(Qt5 COMPONENTS REQUIRED Core Gui Widgets OpenGL) + set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets Qt5::OpenGL) + qt5_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) +else() + find_package(Qt4 COMPONENTS QtCore QtGui QtMain QtOpenGl REQUIRED) + include(${QT_USE_FILE}) + qt4_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) +endif(CEE_USE_QT5) add_library( ${PROJECT_NAME} cafCadNavigation.cpp diff --git a/Fwk/AppFwk/cafVizExtensions/CMakeLists.txt b/Fwk/AppFwk/cafVizExtensions/CMakeLists.txt index 0fce4a32ab..2cfb626515 100644 --- a/Fwk/AppFwk/cafVizExtensions/CMakeLists.txt +++ b/Fwk/AppFwk/cafVizExtensions/CMakeLists.txt @@ -9,16 +9,14 @@ find_package( OpenGL ) option(CEE_USE_QT5 "Use Qt5" OFF) if (CEE_USE_QT5) - find_package(Qt5Core CONFIG QUIET) -endif(CEE_USE_QT5) - -if (Qt5Core_FOUND) - find_package(Qt5 CONFIG REQUIRED Core Gui Widgets OpenGL) + find_package(Qt5 COMPONENTS REQUIRED Core Gui Widgets OpenGL) set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets Qt5::OpenGL) + qt5_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) else() find_package(Qt4 COMPONENTS QtCore QtGui QtMain QtOpenGl REQUIRED) include(${QT_USE_FILE}) -endif(Qt5Core_FOUND) + qt4_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) +endif(CEE_USE_QT5) add_library( ${PROJECT_NAME} cafDisplayCoordTransform.cpp From 6839e826134b03872b84736983585d97f9c7eef1 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Tue, 28 May 2019 12:21:54 +0200 Subject: [PATCH 098/396] #4448 Clean up Qt5-detection CVF --- Fwk/VizFwk/LibGuiQt/CMakeLists.txt | 22 +++-------- .../TestApps/Qt/QtMinimal/CMakeLists.txt | 33 +++++----------- .../TestApps/Qt/QtMultiView/CMakeLists.txt | 39 +++++++------------ .../Qt/QtSnippetRunner/CMakeLists.txt | 35 ++++++----------- .../Tests/LibGuiQt_UnitTests/CMakeLists.txt | 15 ++----- 5 files changed, 46 insertions(+), 98 deletions(-) diff --git a/Fwk/VizFwk/LibGuiQt/CMakeLists.txt b/Fwk/VizFwk/LibGuiQt/CMakeLists.txt index f1d63e863c..6a9bab1c42 100644 --- a/Fwk/VizFwk/LibGuiQt/CMakeLists.txt +++ b/Fwk/VizFwk/LibGuiQt/CMakeLists.txt @@ -2,7 +2,6 @@ cmake_minimum_required(VERSION 2.8.12) project(LibGuiQt) - # We're getting too much trouble from Qt using strict set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CEE_BASE_CXX_FLAGS}") @@ -10,10 +9,14 @@ if (CMAKE_COMPILER_IS_GNUCXX) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-long-long") endif() +find_package(OpenGL) + +# Qt if (CEE_USE_QT5) - find_package(Qt5 COMPONENTS Core Gui OpenGL Widgets REQUIRED) + find_package(Qt5 COMPONENTS REQUIRED Core Gui Widgets OpenGL) + set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets Qt5::OpenGL) else() - find_package(Qt4 COMPONENTS QtCore QtGui QtOpenGL REQUIRED) + find_package(Qt4 COMPONENTS QtCore QtGui QtOpenGl REQUIRED) include(${QT_USE_FILE}) endif(CEE_USE_QT5) @@ -44,19 +47,6 @@ target_include_directories(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR} ) -if ( NOT CMAKE_AUTOMOC ) - if (CEE_USE_QT5) - qt5_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) - - else() - qt4_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) - endif() -endif() - -if (CEE_USE_QT5) - set(QT_LIBRARIES Qt5::Core Qt5::OpenGL Qt5::Widgets) -endif() - target_link_libraries ( ${PROJECT_NAME} LibCore LibGeometry diff --git a/Fwk/VizFwk/TestApps/Qt/QtMinimal/CMakeLists.txt b/Fwk/VizFwk/TestApps/Qt/QtMinimal/CMakeLists.txt index c5c3adb36d..dafadcbc16 100644 --- a/Fwk/VizFwk/TestApps/Qt/QtMinimal/CMakeLists.txt +++ b/Fwk/VizFwk/TestApps/Qt/QtMinimal/CMakeLists.txt @@ -12,16 +12,6 @@ endif() find_package(OpenGL) -if (CEE_USE_QT5) - find_package(Qt5 COMPONENTS Core Gui OpenGL Widgets REQUIRED) -else() - find_package(Qt4 COMPONENTS QtCore QtGui QtOpenGL REQUIRED) - include(${QT_USE_FILE}) - if (QT4_FOUND) - message(STATUS "Found Qt4") - endif(QT4_FOUND) -endif(CEE_USE_QT5) - include_directories(${LibCore_SOURCE_DIR}) include_directories(${LibGeometry_SOURCE_DIR}) include_directories(${LibRender_SOURCE_DIR}) @@ -43,17 +33,18 @@ QMMainWindow.h QMWidget.h ) -# Run MOC on the headers -add_definitions(-DCVF_USING_CMAKE) -set(MOC_SOURCE_FILES) +# Qt if (CEE_USE_QT5) + find_package(Qt5 COMPONENTS REQUIRED Core Gui Widgets OpenGL) + set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets Qt5::OpenGL) qt5_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) - set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::OpenGL Qt5::Widgets) else() + find_package(Qt4 COMPONENTS QtCore QtGui QtOpenGl REQUIRED) + include(${QT_USE_FILE}) qt4_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) -endif() - +endif(CEE_USE_QT5) +add_definitions(-DCVF_USING_CMAKE) add_executable(${PROJECT_NAME} ${CEE_SOURCE_FILES} ${MOC_SOURCE_FILES}) target_link_libraries(${PROJECT_NAME} ${CEE_LIBS} ${OPENGL_LIBRARIES} ${QT_LIBRARIES}) @@ -64,18 +55,14 @@ if (CEE_USE_QT5) COMMAND ${CMAKE_COMMAND} -E copy_if_different $ $ ) endforeach(qtlib) - # Copy Qt Dlls else() # Copy Qt Dlls if (MSVC) set (QTLIBLIST QtCore QtGui QtOpenGl) foreach (qtlib ${QTLIBLIST}) - - # Debug - execute_process(COMMAND cmake -E copy_if_different ${QT_BINARY_DIR}/${qtlib}d4.dll ${CMAKE_BINARY_DIR}/Debug/${qtlib}d4.dll) - - # Release - execute_process(COMMAND cmake -E copy_if_different ${QT_BINARY_DIR}/${qtlib}4.dll ${CMAKE_BINARY_DIR}/Release/${qtlib}4.dll) + add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${QT_BINARY_DIR}/$,${qtlib}d4.dll,${qtlib}4.dll> $ + ) endforeach( qtlib ) endif(MSVC) endif(CEE_USE_QT5) diff --git a/Fwk/VizFwk/TestApps/Qt/QtMultiView/CMakeLists.txt b/Fwk/VizFwk/TestApps/Qt/QtMultiView/CMakeLists.txt index 2f05703921..7f2a8dc366 100644 --- a/Fwk/VizFwk/TestApps/Qt/QtMultiView/CMakeLists.txt +++ b/Fwk/VizFwk/TestApps/Qt/QtMultiView/CMakeLists.txt @@ -12,16 +12,6 @@ endif() find_package(OpenGL) -if (CEE_USE_QT5) - find_package(Qt5 COMPONENTS Core Gui OpenGL Widgets REQUIRED) -else() - find_package(Qt4 COMPONENTS QtCore QtGui QtOpenGL REQUIRED) - include(${QT_USE_FILE}) - if (QT4_FOUND) - message(STATUS "Found Qt4") - endif(QT4_FOUND) -endif(CEE_USE_QT5) - include_directories(${LibCore_SOURCE_DIR}) include_directories(${LibGeometry_SOURCE_DIR}) include_directories(${LibRender_SOURCE_DIR}) @@ -31,7 +21,6 @@ include_directories(${LibUtilities_SOURCE_DIR}) set(CEE_LIBS LibUtilities LibGuiQt LibViewing LibRender LibGeometry LibIo LibCore) - set(CEE_SOURCE_FILES QMVFactory.cpp QMVMain.cpp @@ -45,37 +34,37 @@ QMVMainWindow.h QMVWidget.h ) -# Run MOC on the headers -add_definitions(-DCVF_USING_CMAKE) -set(MOC_SOURCE_FILES) +# Qt if (CEE_USE_QT5) + find_package(Qt5 COMPONENTS REQUIRED Core Gui Widgets OpenGL) + set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets Qt5::OpenGL) qt5_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) - set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::OpenGL Qt5::Widgets) else() + find_package(Qt4 COMPONENTS QtCore QtGui QtOpenGl REQUIRED) + include(${QT_USE_FILE}) qt4_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) endif(CEE_USE_QT5) +# Run MOC on the headers +add_definitions(-DCVF_USING_CMAKE) + add_executable(${PROJECT_NAME} ${CEE_SOURCE_FILES} ${MOC_SOURCE_FILES}) target_link_libraries(${PROJECT_NAME} ${CEE_LIBS} ${OPENGL_LIBRARIES} ${QT_LIBRARIES}) if (CEE_USE_QT5) foreach (qtlib ${QT_LIBRARIES}) - add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_if_different $ $ + add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different $ $ ) endforeach(qtlib) - # Copy Qt Dlls else() # Copy Qt Dlls if (MSVC) set (QTLIBLIST QtCore QtGui QtOpenGl) foreach (qtlib ${QTLIBLIST}) - - # Debug - execute_process(COMMAND cmake -E copy_if_different ${QT_BINARY_DIR}/${qtlib}d4.dll ${CMAKE_BINARY_DIR}/Debug/${qtlib}d4.dll) - - # Release - execute_process(COMMAND cmake -E copy_if_different ${QT_BINARY_DIR}/${qtlib}4.dll ${CMAKE_BINARY_DIR}/Release/${qtlib}4.dll) + add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${QT_BINARY_DIR}/$,${qtlib}d4.dll,${qtlib}4.dll> $ + ) endforeach( qtlib ) endif(MSVC) -endif(CEE_USE_QT5) \ No newline at end of file +endif(CEE_USE_QT5) diff --git a/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/CMakeLists.txt b/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/CMakeLists.txt index db9697617c..dc39caff7c 100644 --- a/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/CMakeLists.txt +++ b/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/CMakeLists.txt @@ -12,16 +12,6 @@ endif() find_package(OpenGL) -if (CEE_USE_QT5) - find_package(Qt5 COMPONENTS Core Gui OpenGL Widgets REQUIRED) -else() - find_package(Qt4 COMPONENTS QtCore QtGui QtOpenGL REQUIRED) - include(${QT_USE_FILE}) - if (QT4_FOUND) - message(STATUS "Found Qt4") - endif(QT4_FOUND) -endif(CEE_USE_QT5) - include_directories(${LibCore_SOURCE_DIR}) include_directories(${LibGeometry_SOURCE_DIR}) include_directories(${LibRender_SOURCE_DIR}) @@ -55,38 +45,37 @@ QSRRunPanel.h QSRSnippetWidget.h ) -# Run MOC on the headers -add_definitions(-DCVF_USING_CMAKE) -set(MOC_SOURCE_FILES) +# Qt if (CEE_USE_QT5) + find_package(Qt5 COMPONENTS REQUIRED Core Gui Widgets OpenGL) + set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets Qt5::OpenGL) qt5_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) - set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::OpenGL Qt5::Widgets) else() + find_package(Qt4 COMPONENTS QtCore QtGui QtOpenGl REQUIRED) + include(${QT_USE_FILE}) qt4_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) endif(CEE_USE_QT5) +add_definitions(-DCVF_USING_CMAKE) add_executable(${PROJECT_NAME} ${CEE_SOURCE_FILES} ${MOC_SOURCE_FILES}) target_link_libraries(${PROJECT_NAME} ${CEE_LIBS} ${OPENGL_LIBRARIES} ${QT_LIBRARIES}) + if (CEE_USE_QT5) foreach (qtlib ${QT_LIBRARIES}) - add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_if_different $ $ + add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different $ $ ) endforeach(qtlib) - # Copy Qt Dlls else() # Copy Qt Dlls if (MSVC) set (QTLIBLIST QtCore QtGui QtOpenGl) foreach (qtlib ${QTLIBLIST}) - - # Debug - execute_process(COMMAND cmake -E copy_if_different ${QT_BINARY_DIR}/${qtlib}d4.dll ${CMAKE_BINARY_DIR}/Debug/${qtlib}d4.dll) - - # Release - execute_process(COMMAND cmake -E copy_if_different ${QT_BINARY_DIR}/${qtlib}4.dll ${CMAKE_BINARY_DIR}/Release/${qtlib}4.dll) + add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${QT_BINARY_DIR}/$,${qtlib}d4.dll,${qtlib}4.dll> $ + ) endforeach( qtlib ) endif(MSVC) endif(CEE_USE_QT5) diff --git a/Fwk/VizFwk/Tests/LibGuiQt_UnitTests/CMakeLists.txt b/Fwk/VizFwk/Tests/LibGuiQt_UnitTests/CMakeLists.txt index 073d674b64..ca3ceaa3e0 100644 --- a/Fwk/VizFwk/Tests/LibGuiQt_UnitTests/CMakeLists.txt +++ b/Fwk/VizFwk/Tests/LibGuiQt_UnitTests/CMakeLists.txt @@ -4,17 +4,15 @@ project(LibGuiQt_UnitTests) # Compile flags should already be setup by caller - find_package(OpenGL) +# Qt if (CEE_USE_QT5) - find_package(Qt5 COMPONENTS Core Gui OpenGL Widgets REQUIRED) + find_package(Qt5 COMPONENTS REQUIRED Core Gui Widgets OpenGL) + set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets Qt5::OpenGL) else() - find_package(Qt4 COMPONENTS QtCore QtGui QtOpenGL REQUIRED) + find_package(Qt4 COMPONENTS QtCore QtGui QtOpenGl REQUIRED) include(${QT_USE_FILE}) - if (QT4_FOUND) - message(STATUS "Found Qt4") - endif(QT4_FOUND) endif(CEE_USE_QT5) include_directories(${LibCore_SOURCE_DIR}) @@ -34,11 +32,6 @@ cvfqtUtils-Test.cpp LibGuiQt_UnitTests.cpp ) -if (CEE_USE_QT5) - set(QT_LIBRARIES Qt5::Core Qt5::OpenGL Qt5::Widgets) -endif(CEE_USE_QT5) - - if (MSVC AND (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 19.11)) # VS 2017 : Disable warnings from from gtest code, using deprecated code related to TR1 add_definitions(-D_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING) From 6ba9d42b452996a966590a8fc158678fdf5478ca Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Tue, 28 May 2019 12:57:56 +0200 Subject: [PATCH 099/396] #4448 Move Resinsight from -std=c++0x to -std=c++11 on GNU CXX --- CMakeLists.txt | 2 +- Fwk/VizFwk/LibCore/cvfColor3.cpp | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 73de2888a5..44918e5bca 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,7 +24,7 @@ elseif(MSVC) endif() if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") - set(CMAKE_CXX_FLAGS "-DCVF_LINUX -pipe -Wextra -Woverloaded-virtual -Wformat -std=c++0x") + set(CMAKE_CXX_FLAGS "-DCVF_LINUX -pipe -Wextra -Woverloaded-virtual -Wformat -std=c++11") set(CMAKE_CXX_FLAGS_DEBUG "-ggdb -g3 -O0 -DDEBUG -D_DEBUG") set(CMAKE_CXX_FLAGS_RELEASE "-O2 -DNO_DEBUG") endif() diff --git a/Fwk/VizFwk/LibCore/cvfColor3.cpp b/Fwk/VizFwk/LibCore/cvfColor3.cpp index 4860282867..3ba9726cb4 100644 --- a/Fwk/VizFwk/LibCore/cvfColor3.cpp +++ b/Fwk/VizFwk/LibCore/cvfColor3.cpp @@ -362,7 +362,8 @@ Color3ub::Color3ub(ColorIdent colorIdent) case YELLOW_GREEN: set(154, 205, 50); break; case CEETRON: set( 81, 134, 148); break; - default: CVF_FAIL_MSG("Unknown ColorIdent"); + default: set(0, 0, 0); + CVF_FAIL_MSG("Unknown ColorIdent"); } } From a54e3f30c45506cf5e8a1fc1df07bc068a5ab2e2 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Tue, 28 May 2019 12:36:33 +0200 Subject: [PATCH 100/396] Fix CVF compile flags on GNUCXX --- Fwk/VizFwk/CMake/Utils/ceeDetermineCompilerFlags.cmake | 2 +- Fwk/VizFwk/LibRender/cvfOverlayScalarMapperLegend.cpp | 8 ++++---- Fwk/VizFwk/LibRender/cvfScalarMapperContinuousLog.cpp | 6 +++--- Fwk/VizFwk/LibRender/cvfScalarMapperRangeBased.cpp | 8 ++++---- Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/CMakeLists.txt | 2 +- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Fwk/VizFwk/CMake/Utils/ceeDetermineCompilerFlags.cmake b/Fwk/VizFwk/CMake/Utils/ceeDetermineCompilerFlags.cmake index ae8dc3fcbb..c435f5d675 100644 --- a/Fwk/VizFwk/CMake/Utils/ceeDetermineCompilerFlags.cmake +++ b/Fwk/VizFwk/CMake/Utils/ceeDetermineCompilerFlags.cmake @@ -34,7 +34,7 @@ option(CEE_WARNINGS_AS_ERRORS "Make all warnings into errors" ON) if (CMAKE_COMPILER_IS_GNUCXX) # Setup our BASE compile flags - set(CEE_BASE_CXX_FLAGS "-Wall -Wextra -pedantic") + set(CEE_BASE_CXX_FLAGS "-Wall -Wextra -pedantic -std=c++11") if (CEE_WARNINGS_AS_ERRORS) set(CEE_BASE_CXX_FLAGS "-Werror ${CEE_BASE_CXX_FLAGS}") diff --git a/Fwk/VizFwk/LibRender/cvfOverlayScalarMapperLegend.cpp b/Fwk/VizFwk/LibRender/cvfOverlayScalarMapperLegend.cpp index aeec596c62..f2d22c006c 100644 --- a/Fwk/VizFwk/LibRender/cvfOverlayScalarMapperLegend.cpp +++ b/Fwk/VizFwk/LibRender/cvfOverlayScalarMapperLegend.cpp @@ -423,8 +423,8 @@ void OverlayScalarMapperLegend::renderLegend(OpenGLContext* oglContext, OverlayC for (iPx = 0; iPx < legendHeightPixelCount; iPx++) { const Color3ub& clr = m_scalarMapper->mapToColor(m_scalarMapper->domainValue((iPx+0.5)/legendHeightPixelCount)); - float y0 = static_cast(layout->legendRect.min().y() + iPx); - float y1 = static_cast(layout->legendRect.min().y() + iPx + 1); + float y0 = layout->legendRect.min().y() + static_cast(iPx); + float y1 = layout->legendRect.min().y() + static_cast(iPx + 1); // Dynamic coordinates for rectangle v0[1] = v1[1] = y0; @@ -575,8 +575,8 @@ void OverlayScalarMapperLegend::renderLegendImmediateMode(OpenGLContext* oglCont for (iPx = 0; iPx < legendHeightPixelCount; iPx++) { const Color3ub& clr = m_scalarMapper->mapToColor(m_scalarMapper->domainValue((iPx+0.5)/legendHeightPixelCount)); - float y0 = static_cast(layout->legendRect.min().y() + iPx); - float y1 = static_cast(layout->legendRect.min().y() + iPx + 1); + float y0 = layout->legendRect.min().y() + static_cast(iPx); + float y1 = layout->legendRect.min().y() + static_cast(iPx + 1); // Dynamic coordinates for rectangle v0[1] = v1[1] = y0; diff --git a/Fwk/VizFwk/LibRender/cvfScalarMapperContinuousLog.cpp b/Fwk/VizFwk/LibRender/cvfScalarMapperContinuousLog.cpp index ebb43da216..588a1b5fcb 100644 --- a/Fwk/VizFwk/LibRender/cvfScalarMapperContinuousLog.cpp +++ b/Fwk/VizFwk/LibRender/cvfScalarMapperContinuousLog.cpp @@ -53,9 +53,9 @@ namespace cvf { /// Configured by specifying a number of level colors and a min/max range. //================================================================================================== ScalarMapperContinuousLog::ScalarMapperContinuousLog() - : m_hasNegativeRange(false), - m_logRange(0.0), - m_logRangeMin(0.0) + : m_logRange(0.0) + , m_logRangeMin(0.0) + , m_hasNegativeRange(false) { } diff --git a/Fwk/VizFwk/LibRender/cvfScalarMapperRangeBased.cpp b/Fwk/VizFwk/LibRender/cvfScalarMapperRangeBased.cpp index 3f2467ce55..8a89eaa670 100644 --- a/Fwk/VizFwk/LibRender/cvfScalarMapperRangeBased.cpp +++ b/Fwk/VizFwk/LibRender/cvfScalarMapperRangeBased.cpp @@ -55,8 +55,8 @@ ScalarMapperRangeBased::ScalarMapperRangeBased() m_rangeMax(cvf::UNDEFINED_DOUBLE), m_decadeLevelCount(1), m_levelCount(8), - m_textureSize(2048), // Large enough, I guess and a power of two - m_adjustLevels(true) + m_adjustLevels(true), + m_textureSize(2048) // Large enough, I guess and a power of two { m_interpolatedUserGradientColors.resize(m_textureSize); m_interpolatedUserGradientColors.setAll(Color3ub::WHITE); @@ -220,7 +220,7 @@ void ScalarMapperRangeBased::majorTickValues( std::vector* domainValues) domainValues->push_back(domainValue(0)); if (m_levelCount > 1) { - double stepSizeNorm = 1.0/m_levelCount; + double stepSizeNorm = 1.0/static_cast(m_levelCount); size_t i; if (m_adjustLevels) // adjust levels @@ -254,7 +254,7 @@ void ScalarMapperRangeBased::majorTickValues( std::vector* domainValues) double prevDomValue = domainValue(0); for (i = 1; i < m_levelCount; ++i) { - double newLevel = domainValue(stepSizeNorm*i); + double newLevel = domainValue(stepSizeNorm*static_cast(i)); if (newLevel != prevDomValue) domainValues->push_back(newLevel); diff --git a/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/CMakeLists.txt b/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/CMakeLists.txt index dc39caff7c..d26bdfd165 100644 --- a/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/CMakeLists.txt +++ b/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/CMakeLists.txt @@ -20,7 +20,7 @@ include_directories(${LibGuiQt_SOURCE_DIR}) include_directories(${LibUtilities_SOURCE_DIR}) include_directories(${SnippetsBasis_SOURCE_DIR}) -set(CEE_LIBS SnippetsBasis freetype LibFreeType LibUtilities LibGuiQt LibViewing LibRender LibGeometry LibIo LibCore opengl32) +set(CEE_LIBS SnippetsBasis freetype LibFreeType LibUtilities LibGuiQt LibViewing LibRender LibGeometry LibIo LibCore) include_directories(${SnippetsModules_SOURCE_DIR}) set(CEE_LIBS LibStructGrid ${CEE_LIBS}) From 9cf0b7cb8600b4be5727f33a7b8f312db1da065d Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Tue, 28 May 2019 13:02:13 +0200 Subject: [PATCH 101/396] #4448 Add -lrt and -lpthread to standalone CEEVIZ build on Linux --- Fwk/VizFwk/TestApps/Qt/QtMinimal/CMakeLists.txt | 7 ++++++- Fwk/VizFwk/TestApps/Qt/QtMultiView/CMakeLists.txt | 8 +++++++- Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/CMakeLists.txt | 7 ++++++- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/Fwk/VizFwk/TestApps/Qt/QtMinimal/CMakeLists.txt b/Fwk/VizFwk/TestApps/Qt/QtMinimal/CMakeLists.txt index dafadcbc16..0e63844ec5 100644 --- a/Fwk/VizFwk/TestApps/Qt/QtMinimal/CMakeLists.txt +++ b/Fwk/VizFwk/TestApps/Qt/QtMinimal/CMakeLists.txt @@ -46,8 +46,13 @@ endif(CEE_USE_QT5) add_definitions(-DCVF_USING_CMAKE) +set(SYSTEM_LIBRARIES) +if (CMAKE_COMPILER_IS_GNUCXX) + set(SYSTEM_LIBRARIES -lrt -lpthread) +endif(CMAKE_COMPILER_IS_GNUCXX) + add_executable(${PROJECT_NAME} ${CEE_SOURCE_FILES} ${MOC_SOURCE_FILES}) -target_link_libraries(${PROJECT_NAME} ${CEE_LIBS} ${OPENGL_LIBRARIES} ${QT_LIBRARIES}) +target_link_libraries(${PROJECT_NAME} ${CEE_LIBS} ${OPENGL_LIBRARIES} ${QT_LIBRARIES} ${SYSTEM_LIBRARIES}) if (CEE_USE_QT5) foreach (qtlib ${QT_LIBRARIES}) diff --git a/Fwk/VizFwk/TestApps/Qt/QtMultiView/CMakeLists.txt b/Fwk/VizFwk/TestApps/Qt/QtMultiView/CMakeLists.txt index 7f2a8dc366..6b01a6c884 100644 --- a/Fwk/VizFwk/TestApps/Qt/QtMultiView/CMakeLists.txt +++ b/Fwk/VizFwk/TestApps/Qt/QtMultiView/CMakeLists.txt @@ -20,6 +20,7 @@ include_directories(${LibGuiQt_SOURCE_DIR}) include_directories(${LibUtilities_SOURCE_DIR}) set(CEE_LIBS LibUtilities LibGuiQt LibViewing LibRender LibGeometry LibIo LibCore) +set(EXTERNAL_LIBS) set(CEE_SOURCE_FILES QMVFactory.cpp @@ -48,8 +49,13 @@ endif(CEE_USE_QT5) # Run MOC on the headers add_definitions(-DCVF_USING_CMAKE) +set(SYSTEM_LIBRARIES) +if (CMAKE_COMPILER_IS_GNUCXX) + set(SYSTEM_LIBRARIES -lrt -lpthread) +endif(CMAKE_COMPILER_IS_GNUCXX) + add_executable(${PROJECT_NAME} ${CEE_SOURCE_FILES} ${MOC_SOURCE_FILES}) -target_link_libraries(${PROJECT_NAME} ${CEE_LIBS} ${OPENGL_LIBRARIES} ${QT_LIBRARIES}) +target_link_libraries(${PROJECT_NAME} ${CEE_LIBS} ${OPENGL_LIBRARIES} ${QT_LIBRARIES} ${SYSTEM_LIBRARIES}) if (CEE_USE_QT5) foreach (qtlib ${QT_LIBRARIES}) diff --git a/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/CMakeLists.txt b/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/CMakeLists.txt index d26bdfd165..edd0a63303 100644 --- a/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/CMakeLists.txt +++ b/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/CMakeLists.txt @@ -58,8 +58,13 @@ endif(CEE_USE_QT5) add_definitions(-DCVF_USING_CMAKE) +set(SYSTEM_LIBRARIES) +if (CMAKE_COMPILER_IS_GNUCXX) + set(SYSTEM_LIBRARIES -lrt -lpthread) +endif(CMAKE_COMPILER_IS_GNUCXX) + add_executable(${PROJECT_NAME} ${CEE_SOURCE_FILES} ${MOC_SOURCE_FILES}) -target_link_libraries(${PROJECT_NAME} ${CEE_LIBS} ${OPENGL_LIBRARIES} ${QT_LIBRARIES}) +target_link_libraries(${PROJECT_NAME} ${CEE_LIBS} ${OPENGL_LIBRARIES} ${QT_LIBRARIES} ${SYSTEM_LIBRARIES}) if (CEE_USE_QT5) From 6691dca4ca7ea0a89210d1976f09da069b69d140 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Tue, 28 May 2019 14:11:08 +0200 Subject: [PATCH 102/396] #4448 Clean up ResInsight Qt5-checks --- ApplicationCode/CMakeLists.txt | 60 +++++++------------ .../WellPathImportSsihub/CMakeLists.txt | 40 ++++--------- CMakeLists.txt | 24 ++------ ThirdParty/Qwt/src/CMakeLists.txt | 23 +++---- ThirdParty/expressionparser/CMakeLists.txt | 10 ++-- ThirdParty/nightcharts/CMakeLists.txt | 11 ++-- 6 files changed, 53 insertions(+), 115 deletions(-) diff --git a/ApplicationCode/CMakeLists.txt b/ApplicationCode/CMakeLists.txt index f76aa79436..551c01a0cd 100644 --- a/ApplicationCode/CMakeLists.txt +++ b/ApplicationCode/CMakeLists.txt @@ -5,19 +5,6 @@ project (ApplicationCode) # Open GL find_package( OpenGL ) -if (RESINSIGHT_BUILD_WITH_QT5) - find_package(Qt5 COMPONENTS Core QUIET) -endif(RESINSIGHT_BUILD_WITH_QT5) - -if (Qt5Core_FOUND) - find_package(Qt5 CONFIG REQUIRED Core Gui OpenGL Network Script Widgets) - set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Network Qt5::OpenGL Qt5::Script Qt5::Widgets) -else() - set (QT_COMPONENTS_REQUIRED QtCore QtGui QtMain QtOpenGl QtNetwork QtScript) - find_package(Qt4 COMPONENTS ${QT_COMPONENTS_REQUIRED} REQUIRED) - include(${QT_USE_FILE}) -endif(Qt5Core_FOUND) - # NB: The generated file is written to Cmake binary folder to avoid source tree pollution # This folder is added to include_directories CONFIGURE_FILE( ${CMAKE_SOURCE_DIR}/ApplicationCode/Adm/RiaVersionInfo.h.cmake @@ -98,6 +85,7 @@ list( APPEND CPP_SOURCES ${UNIT_TEST_FILES} ) +option(RESINSIGHT_ENABLE_GRPC "Enable the gRPC scripting framework" OFF) if (RESINSIGHT_ENABLE_GRPC) list( APPEND REFERENCED_CMAKE_FILES GrpcInterface/CMakeLists.cmake @@ -250,15 +238,6 @@ set ( QT_MOC_HEADERS SocketInterface/RiaSocketServer.h ) -if (Qt5Core_FOUND) - qt5_wrap_cpp(MOC_SOURCE_FILES ${QT_MOC_HEADERS} ) - qt5_wrap_ui( FORM_FILES_CPP ${QT_UI_FILES} ) -else() - qt4_wrap_cpp(MOC_SOURCE_FILES ${QT_MOC_HEADERS} ) - qt4_wrap_ui( FORM_FILES_CPP ${QT_UI_FILES} ) -endif() - - # NOTE! Resources in subfolders must append to QRC_FILES using the following statement # set( QRC_FILES # ${QRC_FILES} @@ -271,18 +250,19 @@ set( QRC_FILES Resources/ResInsight.qrc ) -# Runs RCC on specified files -if ( NOT CMAKE_AUTOMOC) - if (Qt5Core_FOUND) - qt5_add_resources( QRC_FILES_CPP - ${QRC_FILES} - ) - else() - qt4_add_resources( QRC_FILES_CPP - ${QRC_FILES} - ) - endif(Qt5Core_FOUND) -endif(NOT CMAKE_AUTOMOC) +if (RESINSIGHT_BUILD_WITH_QT5) + find_package(Qt5 COMPONENTS REQUIRED Core Gui OpenGL Network Script Widgets) + set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::OpenGL Qt5::Network Qt5::Script Qt5::Widgets) + qt5_wrap_cpp(MOC_SOURCE_FILES ${QT_MOC_HEADERS}) + qt5_wrap_ui(FORM_FILES_CPP ${QT_UI_FILES}) + qt5_add_resources(QRC_FILES_CPP ${QRC_FILES}) +else() + find_package(Qt4 COMPONENTS QtCore QtGui QtMain QtOpenGl QtNetwork QtScript REQUIRED) + include(${QT_USE_FILE}) + qt4_wrap_cpp(MOC_SOURCE_FILES ${QT_MOC_HEADERS}) + qt4_wrap_ui(FORM_FILES_CPP ${QT_UI_FILES}) + qt4_add_resources(QRC_FILES_CPP ${QRC_FILES}) +endif(RESINSIGHT_BUILD_WITH_QT5) # Adding resource (RC) files for Windows if ( MSVC ) @@ -486,7 +466,7 @@ endif() if (MSVC) # Qt DLLs - if (Qt5Core_FOUND) + if (RESINSIGHT_BUILD_WITH_QT5) message(STATUS "Creating post build step for copying Qt DLLs") foreach (qtlib ${QT_LIBRARIES}) add_custom_command(TARGET ResInsight POST_BUILD @@ -494,11 +474,11 @@ if (MSVC) ) endforeach(qtlib) else() - set (QTLIBLIST QtCore4 QtCored4 QtGui4 QtGuid4 QtOpenGl4 QtOpenGld4 QtNetwork4 QtNetworkd4 QtScript4 QtScriptd4 QtScriptTools4 QtScriptToolsd4) - foreach (qtlib ${QTLIBLIST}) - list(APPEND RI_DLL_FILENAMES ${QT_BINARY_DIR}/${qtlib}.dll) + set (QTLIBLIST QtCore QtGui QtGui QtOpenGl QtNetwork QtScript QtScriptTools) + foreach (qtlib ${QTLIBLIST}) + list(APPEND RI_DLL_FILENAMES ${QT_BINARY_DIR}/$,${qtlib}d4.dll,${qtlib}4.dll>) endforeach( qtlib ) - endif() + endif(RESINSIGHT_BUILD_WITH_QT5) # Odb Dlls if (RESINSIGHT_USE_ODB_API) # Find all the dlls @@ -595,7 +575,7 @@ if (RESINSIGHT_PRIVATE_INSTALL) set (RESINSIGHT_FILES ${RI_DLL_FILENAMES}) - if(Qt5_FOUND AND WIN32 AND TARGET Qt5::qmake AND NOT TARGET Qt5::windeployqt) + if(RESINSIGHT_BUILD_WITH_QT5 AND WIN32 AND TARGET Qt5::qmake AND NOT TARGET Qt5::windeployqt) get_target_property(_qt5_qmake_location Qt5::qmake IMPORTED_LOCATION) execute_process( diff --git a/ApplicationCode/WellPathImportSsihub/CMakeLists.txt b/ApplicationCode/WellPathImportSsihub/CMakeLists.txt index 70912c0815..1af067baf2 100644 --- a/ApplicationCode/WellPathImportSsihub/CMakeLists.txt +++ b/ApplicationCode/WellPathImportSsihub/CMakeLists.txt @@ -2,35 +2,20 @@ cmake_minimum_required (VERSION 2.8.12) project (WellPathImportSsihub) -if (RESINSIGHT_BUILD_WITH_QT5) - find_package(Qt5 COMPONENTS Core QUIET) -endif(RESINSIGHT_BUILD_WITH_QT5) - -if (Qt5Core_FOUND) - find_package(Qt5 CONFIG REQUIRED Core Network) -else() - find_package(Qt4 COMPONENTS QtCore QtNetwork REQUIRED) - include(${QT_USE_FILE}) -endif(Qt5Core_FOUND) - # These headers need to go through Qt's MOC compiler -set( QT_MOC_HEADERS +set( MOC_HEADER_FILES RiuWellImportWizard.h ) - -set( QT_UI_FILES -) - -if ( NOT CMAKE_AUTOMOC ) - if (Qt5Core_FOUND) - qt5_wrap_cpp(MOC_SOURCE_FILES ${QT_MOC_HEADERS} ) - qt5_wrap_ui( FORM_FILES_CPP ${QT_UI_FILES} ) - else() - qt4_wrap_cpp(MOC_SOURCE_FILES ${QT_MOC_HEADERS} ) - qt4_wrap_ui( FORM_FILES_CPP ${QT_UI_FILES} ) - endif() -endif() +if (RESINSIGHT_BUILD_WITH_QT5) + find_package(Qt5 COMPONENTS REQUIRED Core Network) + set(QT_LIBRARIES Qt5::Core Qt5::Network) + qt5_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES}) +else() + find_package(Qt4 COMPONENTS QtCore QtNetwork REQUIRED) + include(${QT_USE_FILE}) + qt4_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES}) +endif(RESINSIGHT_BUILD_WITH_QT5) include_directories( ${CMAKE_CURRENT_BINARY_DIR} @@ -38,7 +23,6 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/../FileInterface ) - add_library( ${PROJECT_NAME} RimWellPathImport.h RimWellPathImport.cpp @@ -58,10 +42,6 @@ add_library( ${PROJECT_NAME} ${HEADER_FILES} ) -if (Qt5Core_FOUND) - set(QT_LIBRARIES Qt5::Core Qt5::Network) -endif() - target_link_libraries ( ${PROJECT_NAME} cafUserInterface cafPdmCvf CommonCode ${QT_LIBRARIES} ) diff --git a/CMakeLists.txt b/CMakeLists.txt index 44918e5bca..8f13bd28f3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -253,27 +253,13 @@ list(APPEND THIRD_PARTY_LIBRARIES ################################################################################ # Qt ################################################################################ -option(RESINSIGHT_BUILD_WITH_QT5 "Use Qt5 folder" OFF) -if (RESINSIGHT_BUILD_WITH_QT5) - message(STATUS "Attempting to build with Qt5") - find_package(Qt5 COMPONENTS Core QUIET) -else() - message(STATUS "Attempting to build with Qt4") -endif(RESINSIGHT_BUILD_WITH_QT5) +option(RESINSIGHT_BUILD_WITH_QT5 "Use Qt5" OFF) -if (Qt5Core_FOUND) - message(STATUS "Found Qt5") - find_package (Qt5 CONFIG REQUIRED Core Widgets OpenGL Network Script ScriptTools) +if (RESINSIGHT_BUILD_WITH_QT5) + find_package(Qt5 COMPONENTS REQUIRED Core Gui OpenGL Network Script ScriptTools Widgets) else() - if (RESINSIGHT_BUILD_WITH_QT5) - message(WARNING "Could not find Qt5. Trying with Qt4") - endif(RESINSIGHT_BUILD_WITH_QT5) - find_package(Qt4 COMPONENTS QtCore QtGui QtMain REQUIRED) - if (QT_VERSION_MINOR LESS 6) - message(FATAL_ERROR "Qt 4.6 is required, please specify qmake for variable QT_QMAKE_EXECUTABLE") - endif() - include(${QT_USE_FILE}) -endif(Qt5Core_FOUND) + find_package(Qt4 COMPONENTS QtCore QtGui QtMain QtOpenGl QtNetwork QtScript QtScriptTools REQUIRED) +endif(RESINSIGHT_BUILD_WITH_QT5) # Open GL find_package( OpenGL ) diff --git a/ThirdParty/Qwt/src/CMakeLists.txt b/ThirdParty/Qwt/src/CMakeLists.txt index d27119a9e0..ac87cd9133 100644 --- a/ThirdParty/Qwt/src/CMakeLists.txt +++ b/ThirdParty/Qwt/src/CMakeLists.txt @@ -7,13 +7,6 @@ if (MSVC) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4267") endif() -if (RESINSIGHT_BUILD_WITH_QT5) - find_package(Qt5 COMPONENTS Concurrent Core OpenGL PrintSupport Widgets REQUIRED) -else() - find_package(Qt4 COMPONENTS QtCore QtGui QtOpenGL qtmain REQUIRED) - include(${QT_USE_FILE}) -endif(RESINSIGHT_BUILD_WITH_QT5) - # Adapted from src.pri file in Qwt's source catalog for Qwt 6.1.0 # Compiles static library # Some bits removed (at least SVG) @@ -275,15 +268,15 @@ qwt_thermo.h qwt_wheel.h ) - - -set(MOC_SOURCE_FILES) if (RESINSIGHT_BUILD_WITH_QT5) - qt5_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) + find_package(Qt5 COMPONENTS REQUIRED Concurrent Core Gui OpenGL PrintSupport Widgets) + set(QT_LIBRARIES Qt5::Concurrent Qt5::Core Qt5::Gui Qt5::OpenGL Qt5::PrintSupport Qt5::Widgets) + qt5_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES}) else() - qt4_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) + find_package(Qt4 COMPONENTS QtCore QtGui QtMain QtOpenGl REQUIRED) + include(${QT_USE_FILE}) + qt4_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES}) endif(RESINSIGHT_BUILD_WITH_QT5) - add_library(${PROJECT_NAME} ${HEADER_FILES} ${SOURCE_FILES} ${MOC_SOURCE_FILES}) @@ -292,9 +285,7 @@ target_include_directories(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR} ) -if (RESINSIGHT_BUILD_WITH_QT5) - target_link_libraries(${PROJECT_NAME} Qt5::Concurrent Qt5::Core Qt5::OpenGL Qt5::PrintSupport Qt5::Widgets) -endif(RESINSIGHT_BUILD_WITH_QT5) +target_link_libraries(${PROJECT_NAME} ${QT_LIBRARIES}) if (COMMAND caf_apply_cotire) caf_apply_cotire("${PROJECT_NAME}") diff --git a/ThirdParty/expressionparser/CMakeLists.txt b/ThirdParty/expressionparser/CMakeLists.txt index 80a5ebe01f..b9a92abd87 100644 --- a/ThirdParty/expressionparser/CMakeLists.txt +++ b/ThirdParty/expressionparser/CMakeLists.txt @@ -7,10 +7,12 @@ if(MSVC) message(STATUS "MSVC: Enabled increased number of sections in object files") endif() + if (RESINSIGHT_BUILD_WITH_QT5) - find_package(Qt5 COMPONENTS Core REQUIRED) + find_package(Qt5 COMPONENTS REQUIRED Core) + set(QT_LIBRARIES Qt5::Core) else() - find_package(Qt4 COMPONENTS QtCore REQUIRED) + find_package(Qt4 COMPONENTS QtCore REQUIRED) include(${QT_USE_FILE}) endif(RESINSIGHT_BUILD_WITH_QT5) @@ -35,8 +37,6 @@ if(MSVC) ${CMAKE_CURRENT_SOURCE_DIR} ) -if (RESINSIGHT_BUILD_WITH_QT5) - target_link_libraries(${PROJECT_NAME} Qt5::Core) -endif(RESINSIGHT_BUILD_WITH_QT5) +target_link_libraries(${PROJECT_NAME} ${QT_LIBRARIES}) source_group("" FILES ${PROJECT_FILES}) diff --git a/ThirdParty/nightcharts/CMakeLists.txt b/ThirdParty/nightcharts/CMakeLists.txt index ec5c1773d8..a3f1597974 100644 --- a/ThirdParty/nightcharts/CMakeLists.txt +++ b/ThirdParty/nightcharts/CMakeLists.txt @@ -3,10 +3,13 @@ cmake_minimum_required (VERSION 2.8.12) project (nightcharts) if (RESINSIGHT_BUILD_WITH_QT5) - find_package(Qt5 COMPONENTS Core Widgets REQUIRED) + find_package(Qt5 COMPONENTS REQUIRED Core Widgets) + set(QT_LIBRARIES Qt5::Core Qt5::Widgets) + qt5_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES}) else() - find_package(Qt4 COMPONENTS QtCore QtGui REQUIRED) + find_package(Qt4 COMPONENTS QtCore QtWidgets) include(${QT_USE_FILE}) + qt4_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES}) endif(RESINSIGHT_BUILD_WITH_QT5) list (APPEND MAIN_SOURCE_FILES @@ -26,8 +29,6 @@ target_include_directories(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR} ) -if (RESINSIGHT_BUILD_WITH_QT5) - target_link_libraries(${PROJECT_NAME} Qt5::Core Qt5::Widgets) -endif(RESINSIGHT_BUILD_WITH_QT5) +target_link_libraries(${PROJECT_NAME} ${QT_LIBRARIES}) source_group("" FILES ${PROJECT_FILES}) From a413da41b4f896e5be58319362382295ddf24fc7 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Tue, 28 May 2019 14:11:21 +0200 Subject: [PATCH 103/396] Glew Qt5 Fix for VizFramework --- .../TestApps/Qt/QtSnippetRunner/QSRMain.cpp | 2 ++ .../Qt/QtSnippetRunner/QSRMainWindow.cpp | 11 +++++++++++ .../TestApps/Qt/QtSnippetRunner/QSRMainWindow.h | 2 +- .../Qt/QtSnippetRunner/QSRPropertiesPanel.cpp | 2 ++ .../TestApps/Qt/QtSnippetRunner/QSRRunPanel.cpp | 3 +++ .../Qt/QtSnippetRunner/QSRSnippetWidget.cpp | 2 ++ .../TestApps/Qt/QtSnippetRunner/QSRStdInclude.h | 17 +++++++++-------- .../Qt/QtSnippetRunner/QSRTranslateEvent.cpp | 2 +- 8 files changed, 31 insertions(+), 10 deletions(-) diff --git a/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/QSRMain.cpp b/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/QSRMain.cpp index 17a7fda44e..3a7d2391b2 100644 --- a/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/QSRMain.cpp +++ b/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/QSRMain.cpp @@ -44,6 +44,8 @@ #include "cvfShaderSourceProvider.h" #include "cvfqtUtils.h" +#include +#include //-------------------------------------------------------------------------------------------------- diff --git a/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/QSRMainWindow.cpp b/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/QSRMainWindow.cpp index 09de80fe8b..a815b18be2 100644 --- a/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/QSRMainWindow.cpp +++ b/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/QSRMainWindow.cpp @@ -43,6 +43,17 @@ #include "cvfqtUtils.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + using cvfu::TestSnippet; using cvfu::SnippetInfo; using cvfu::SnippetRegistry; diff --git a/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/QSRMainWindow.h b/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/QSRMainWindow.h index ac5b6e81a1..f5814cd7c5 100644 --- a/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/QSRMainWindow.h +++ b/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/QSRMainWindow.h @@ -52,7 +52,7 @@ #include #endif - +class QAction; class QSRSnippetWidget; class QSRRunPanel; class QSRPropertiesPanel; diff --git a/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/QSRPropertiesPanel.cpp b/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/QSRPropertiesPanel.cpp index 14f04099ed..f4d5e74539 100644 --- a/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/QSRPropertiesPanel.cpp +++ b/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/QSRPropertiesPanel.cpp @@ -43,6 +43,8 @@ #include "cvfqtUtils.h" #if QT_VERSION >= 0x050000 +#include +#include #include #include #include diff --git a/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/QSRRunPanel.cpp b/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/QSRRunPanel.cpp index 293cb67d10..a028fc1a9f 100644 --- a/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/QSRRunPanel.cpp +++ b/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/QSRRunPanel.cpp @@ -44,6 +44,9 @@ #include "cvfqtUtils.h" #if QT_VERSION >= 0x050000 +#include +#include +#include #include #include #include diff --git a/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/QSRSnippetWidget.cpp b/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/QSRSnippetWidget.cpp index acefaaf659..d69b63914d 100644 --- a/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/QSRSnippetWidget.cpp +++ b/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/QSRSnippetWidget.cpp @@ -44,6 +44,8 @@ #include +#include + using cvfu::TestSnippet; diff --git a/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/QSRStdInclude.h b/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/QSRStdInclude.h index c25fd79d5b..43cade5914 100644 --- a/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/QSRStdInclude.h +++ b/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/QSRStdInclude.h @@ -1,23 +1,24 @@ #pragma once -#include -#include -#if QT_VERSION >= 0x050000 -#include -#else -#include -#endif - #include "cvfLibCore.h" #include "cvfLibRender.h" #include "cvfLibGeometry.h" #include "cvfLibViewing.h" +#include "cvfOpenGL.h" #include "cvfuTestSnippet.h" #include "cvfuSnippetFactory.h" #include "cvfuInputEvents.h" +#include +#if QT_VERSION >= 0x050000 +#include +#include +#include +#else +#include +#endif // Introduce name of commonly used classes (that are unlikely to create clashes) from the cvf namespace. // We allow the use of using-declarations in this include file since its sole usage is as a precompiled header file. diff --git a/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/QSRTranslateEvent.cpp b/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/QSRTranslateEvent.cpp index effe9aa068..d69c6a21f0 100644 --- a/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/QSRTranslateEvent.cpp +++ b/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/QSRTranslateEvent.cpp @@ -38,7 +38,7 @@ #include "QSRStdInclude.h" #include "QSRTranslateEvent.h" - +#include //-------------------------------------------------------------------------------------------------- /// From b2b3581e9d61cd2df11794bdd1ee7d5a580b6d19 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Wed, 29 May 2019 08:14:02 +0200 Subject: [PATCH 104/396] Partial revert of ApplicationCode/CMakeLists.txt to fix build issues --- ApplicationCode/CMakeLists.txt | 41 +++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/ApplicationCode/CMakeLists.txt b/ApplicationCode/CMakeLists.txt index 551c01a0cd..aa45bed302 100644 --- a/ApplicationCode/CMakeLists.txt +++ b/ApplicationCode/CMakeLists.txt @@ -5,6 +5,20 @@ project (ApplicationCode) # Open GL find_package( OpenGL ) +option(RESINSIGHT_ENABLE_GRPC "Enable the gRPC scripting framework" OFF) +if (RESINSIGHT_BUILD_WITH_QT5) + find_package(Qt5 COMPONENTS Core QUIET) +endif(RESINSIGHT_BUILD_WITH_QT5) + +if (Qt5Core_FOUND) + find_package(Qt5 CONFIG REQUIRED Core Gui OpenGL Network Script Widgets) + set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Network Qt5::OpenGL Qt5::Script Qt5::Widgets) +else() + set (QT_COMPONENTS_REQUIRED QtCore QtGui QtMain QtOpenGl QtNetwork QtScript) + find_package(Qt4 COMPONENTS ${QT_COMPONENTS_REQUIRED} REQUIRED) + include(${QT_USE_FILE}) +endif(Qt5Core_FOUND) + # NB: The generated file is written to Cmake binary folder to avoid source tree pollution # This folder is added to include_directories CONFIGURE_FILE( ${CMAKE_SOURCE_DIR}/ApplicationCode/Adm/RiaVersionInfo.h.cmake @@ -85,7 +99,6 @@ list( APPEND CPP_SOURCES ${UNIT_TEST_FILES} ) -option(RESINSIGHT_ENABLE_GRPC "Enable the gRPC scripting framework" OFF) if (RESINSIGHT_ENABLE_GRPC) list( APPEND REFERENCED_CMAKE_FILES GrpcInterface/CMakeLists.cmake @@ -238,6 +251,15 @@ set ( QT_MOC_HEADERS SocketInterface/RiaSocketServer.h ) +if (RESINSIGHT_BUILD_WITH_QT5) + qt5_wrap_cpp(MOC_SOURCE_FILES ${QT_MOC_HEADERS} ) + qt5_wrap_ui( FORM_FILES_CPP ${QT_UI_FILES} ) +else() + qt4_wrap_cpp(MOC_SOURCE_FILES ${QT_MOC_HEADERS} ) + qt4_wrap_ui( FORM_FILES_CPP ${QT_UI_FILES} ) +endif(RESINSIGHT_BUILD_WITH_QT5) + + # NOTE! Resources in subfolders must append to QRC_FILES using the following statement # set( QRC_FILES # ${QRC_FILES} @@ -250,18 +272,15 @@ set( QRC_FILES Resources/ResInsight.qrc ) +# Runs RCC on specified files if (RESINSIGHT_BUILD_WITH_QT5) - find_package(Qt5 COMPONENTS REQUIRED Core Gui OpenGL Network Script Widgets) - set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::OpenGL Qt5::Network Qt5::Script Qt5::Widgets) - qt5_wrap_cpp(MOC_SOURCE_FILES ${QT_MOC_HEADERS}) - qt5_wrap_ui(FORM_FILES_CPP ${QT_UI_FILES}) - qt5_add_resources(QRC_FILES_CPP ${QRC_FILES}) + qt5_add_resources( QRC_FILES_CPP + ${QRC_FILES} + ) else() - find_package(Qt4 COMPONENTS QtCore QtGui QtMain QtOpenGl QtNetwork QtScript REQUIRED) - include(${QT_USE_FILE}) - qt4_wrap_cpp(MOC_SOURCE_FILES ${QT_MOC_HEADERS}) - qt4_wrap_ui(FORM_FILES_CPP ${QT_UI_FILES}) - qt4_add_resources(QRC_FILES_CPP ${QRC_FILES}) + qt4_add_resources( QRC_FILES_CPP + ${QRC_FILES} + ) endif(RESINSIGHT_BUILD_WITH_QT5) # Adding resource (RC) files for Windows From 691c26c8faab52c1a211e76b2e9aa089924778ea Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 29 May 2019 10:14:34 +0200 Subject: [PATCH 105/396] Adjustments to install instructions for Windows --- GRPC_install_instructions.txt | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/GRPC_install_instructions.txt b/GRPC_install_instructions.txt index 7deba5e702..2243a31dc2 100644 --- a/GRPC_install_instructions.txt +++ b/GRPC_install_instructions.txt @@ -1,21 +1,22 @@ ########## Windows using vcpkg ################### 1. Clone VCPKG git clone https://github.com/microsoft/vcpkg.git - -4. Install VCPKG from within vcpkg folder: +2. Install VCPKG from within vcpkg folder: .\boostrap-vcpkg.bat -5. Perform integrated install (as admin) within vcpkg folder. Not sure if it is necessary. -.\vcpkg integrate install -5. Install GRPC +3. Install GRPC .\vcpkg install grpc --triplet x64-windows -6. Run cmake with -DCMAKE_TOOLCHAIN_FILE=LOCATION_OF_VCPKG/buildsystems/vcpkg.cmake - This can be set on the configure dialog that comes up when you press configure with a fresh build folder. -7. Enable GRPC by setting RESINSIGHT_ENABLE_GRPC = true -8. Python - - Install Python 3 - - Execute the following using the Python3 - python -m pip install grpcio-tools - - Make sure the python executable is found by setting -DPYTHON_EXECUTABLE=LOCATION_OF_PYTHON.EXE + +4. Python +* Install Python 3 +* Execute the following using Python3 + python -m pip install grpcio-tools +* Make sure the python executable is found by setting -DPYTHON_EXECUTABLE=LOCATION_OF_PYTHON.EXE + +4. Run cmake with the following statements +-DRESINSIGHT_ENABLE_GRPC=true +-DPYTHON_EXECUTABLE=LOCATION_OF_PYTHON.EXE +-DCMAKE_TOOLCHAIN_FILE=LOCATION_OF_VCPKG/scripts/buildsystems/vcpkg.cmake +-A x64 ############ Linux as STANDALONE GPRC (using GRPC_INSTALL_PREFIX=/opt/grpc as an example) ############### 1. Clone grpc From 5b7b9993a044c0ee0e0918321dcbea6370953d7c Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 29 May 2019 11:33:03 +0200 Subject: [PATCH 106/396] Remove duplicate if statement --- ApplicationCode/GrpcInterface/CMakeLists.cmake | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/ApplicationCode/GrpcInterface/CMakeLists.cmake b/ApplicationCode/GrpcInterface/CMakeLists.cmake index ccb0d89738..b361b90186 100644 --- a/ApplicationCode/GrpcInterface/CMakeLists.cmake +++ b/ApplicationCode/GrpcInterface/CMakeLists.cmake @@ -45,12 +45,11 @@ if (MSVC) set(_GRPC_CPP_PLUGIN_EXECUTABLE $) set(GRPC_LIBRARIES ${_GRPC_GRPCPP_UNSECURE} ${_PROTOBUF_LIBPROTOBUF}) - if (MSVC) - set_target_properties(${GRPC_LIBRARIES} PROPERTIES - MAP_IMPORTED_CONFIG_MINSIZEREL RELEASE - MAP_IMPORTED_CONFIG_RELWITHDEBINFO RELEASE + set_target_properties(${GRPC_LIBRARIES} PROPERTIES + MAP_IMPORTED_CONFIG_MINSIZEREL RELEASE + MAP_IMPORTED_CONFIG_RELWITHDEBINFO RELEASE ) - endif(MSVC) + else() if (NOT DEFINED GRPC_INSTALL_PREFIX OR NOT EXISTS ${GRPC_INSTALL_PREFIX}) message(FATAL_ERROR "You need a valid GRPC_INSTALL_PREFIX set to build with GRPC") From 3d109da5b219400382c27bf7769305c92bed79ea Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 29 May 2019 15:12:30 +0200 Subject: [PATCH 107/396] #4425 Python: Add install of gRPC dlls and Python module --- ApplicationCode/CMakeLists.txt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/ApplicationCode/CMakeLists.txt b/ApplicationCode/CMakeLists.txt index aa45bed302..9304e3e7f7 100644 --- a/ApplicationCode/CMakeLists.txt +++ b/ApplicationCode/CMakeLists.txt @@ -644,6 +644,14 @@ if (RESINSIGHT_PRIVATE_INSTALL) ) endif() + # install GRPC-related DLLs + if (RESINSIGHT_ENABLE_GRPC) + set (GRPC_DLL_NAMES libprotobuf cares zlib1) + foreach (dllname ${GRPC_DLL_NAMES}) + list(APPEND RESINSIGHT_FILES "${CMAKE_CURRENT_BINARY_DIR}/$/${dllname}.dll") + endforeach(dllname ${GRPC_DLL_NAMES}) + endif() + # CRT set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_SKIP ON) set(CMAKE_INSTALL_OPENMP_LIBRARIES ON) @@ -652,6 +660,12 @@ if (RESINSIGHT_PRIVATE_INSTALL) endif() + + # install gRPC Python files + if (RESINSIGHT_ENABLE_GRPC) + install(DIRECTORY ${GRPC_PYTHON_SOURCE_PATH} DESTINATION ${RESINSIGHT_INSTALL_FOLDER} FILES_MATCHING PATTERN "*.py") + endif() + set (RESINSIGHT_FILES ${RESINSIGHT_FILES} ${RESINSIGHT_LICENSE_FILES}) From a6cdec08167ddd1907e0d4c4934dd19a3befe77b Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Thu, 30 May 2019 18:52:16 +0200 Subject: [PATCH 108/396] Python: enable storage of new results and improve reliability --- .../GrpcInterface/RiaGrpcCallbacks.h | 2 - .../GrpcInterface/RiaGrpcCallbacks.inl | 2 +- .../GrpcInterface/RiaGrpcGridInfoService.cpp | 5 +-- .../RiaGrpcPropertiesService.cpp | 42 +++++++++++++++++-- .../GrpcInterface/RiaGrpcServer.cpp | 11 ++--- 5 files changed, 45 insertions(+), 17 deletions(-) diff --git a/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.h b/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.h index d830280c39..8367002f60 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.h +++ b/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.h @@ -65,8 +65,6 @@ public: inline CallState callState() const; inline const Status& status() const; - -protected: inline void setNextCallState(CallState state); protected: diff --git a/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.inl b/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.inl index 2cbeb7798e..90f9a11a78 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.inl +++ b/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.inl @@ -272,7 +272,7 @@ template::createNewFromThis() const { return new RiaGrpcClientStreamCallback( - this->m_service, m_methodImpl, m_methodRequest, new StateHandlerT); + this->m_service, m_methodImpl, m_methodRequest, new StateHandlerT(true)); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/GrpcInterface/RiaGrpcGridInfoService.cpp b/ApplicationCode/GrpcInterface/RiaGrpcGridInfoService.cpp index e7be462ad4..3098147970 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcGridInfoService.cpp +++ b/ApplicationCode/GrpcInterface/RiaGrpcGridInfoService.cpp @@ -218,11 +218,10 @@ grpc::Status RiaGrpcGridInfoService::GetGridCount(grpc::ServerContext* context, RimCase* rimCase = findCase(request->id()); RimEclipseCase* eclipseCase = dynamic_cast(rimCase); - size_t gridCount = 0u; if (eclipseCase) { - gridCount = eclipseCase->mainGrid()->gridCount(); - reply->set_count((int)gridCount); + int gridCount = (int) eclipseCase->mainGrid()->gridCount(); + reply->set_count(gridCount); return Status::OK; } return grpc::Status(grpc::NOT_FOUND, "Eclipse Case not found"); diff --git a/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp b/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp index 8b3a4be4c3..dbe8ca6dd2 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp +++ b/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp @@ -26,6 +26,7 @@ #include "RigCaseCellResultsData.h" #include "RigEclipseCaseData.h" #include "RigEclipseResultAddress.h" +#include "RigEclipseResultInfo.h" #include "RigMainGrid.h" #include "RigResultAccessor.h" #include "RigResultAccessorFactory.h" @@ -50,9 +51,10 @@ public: //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- - RiaCellResultsStateHandler() + RiaCellResultsStateHandler(bool clientStreamer = false) : m_request(nullptr) , m_currentCellIdx(0u) + , m_clientStreamer(clientStreamer) { } @@ -82,6 +84,24 @@ public: } return grpc::Status(grpc::NOT_FOUND, "No such time step"); } + else if (m_clientStreamer) + { + resultData->createResultEntry(resAddr, true); + RigEclipseResultAddress addrToMaxTimeStepCountResult; + + size_t timeStepCount = resultData->maxTimeStepCount(&addrToMaxTimeStepCountResult); + const std::vector timeStepInfos = + resultData->timeStepInfos(addrToMaxTimeStepCountResult); + resultData->setTimeStepInfos(resAddr, timeStepInfos); + auto scalarResultFrames = resultData->modifiableCellScalarResultTimesteps(resAddr); + scalarResultFrames.resize(timeStepCount); + if (timeStep < resultData->timeStepCount(resAddr)) + { + initResultAccess(caseData, request->grid_index(), porosityModel, timeStep, resAddr); + return grpc::Status::OK; + } + return grpc::Status(grpc::NOT_FOUND, "No such time step"); + } return grpc::Status(grpc::NOT_FOUND, "No such result"); } return grpc::Status(grpc::NOT_FOUND, "Couldn't find an Eclipse case matching the case Id"); @@ -131,7 +151,7 @@ public: { setCellResult(m_currentCellIdx, values[i]); } - if (m_currentCellIdx == m_cellCount - 1) + if (m_currentCellIdx >= m_cellCount - 1) { return grpc::Status(grpc::OUT_OF_RANGE, "All values have been written"); } @@ -167,10 +187,15 @@ protected: RimEclipseCase* m_eclipseCase; size_t m_currentCellIdx; size_t m_cellCount; + bool m_clientStreamer; }; class RiaActiveCellResultsStateHandler : public RiaCellResultsStateHandler { +public: + RiaActiveCellResultsStateHandler(bool clientStreamer = false) + : RiaCellResultsStateHandler(clientStreamer) + {} protected: void initResultAccess(RigEclipseCaseData* caseData, size_t gridIndex, @@ -180,6 +205,10 @@ protected: { auto activeCellInfo = caseData->activeCellInfo(porosityModel); m_resultValues = &(caseData->results(porosityModel)->modifiableCellScalarResult(resVarAddr, timeStepIndex)); + if (m_resultValues->empty()) + { + m_resultValues->resize(activeCellInfo->reservoirCellResultCount()); + } m_cellCount = activeCellInfo->reservoirActiveCellCount(); } @@ -199,6 +228,11 @@ private: class RiaGridCellResultsStateHandler : public RiaCellResultsStateHandler { +public: + RiaGridCellResultsStateHandler(bool clientStreamer = false) + : RiaCellResultsStateHandler(clientStreamer) + {} + protected: void initResultAccess(RigEclipseCaseData* caseData, size_t gridIndex, @@ -313,9 +347,9 @@ std::vector RiaGrpcPropertiesService::createCallbacks new RiaGrpcServerStreamCallback( this, &Self::GetGridResults, &Self::RequestGetGridResults, new RiaGridCellResultsStateHandler), new RiaGrpcClientStreamCallback( - this, &Self::SetActiveCellResults, &Self::RequestSetActiveCellResults, new RiaActiveCellResultsStateHandler), + this, &Self::SetActiveCellResults, &Self::RequestSetActiveCellResults, new RiaActiveCellResultsStateHandler(true)), new RiaGrpcClientStreamCallback( - this, &Self::SetGridResults, &Self::RequestSetGridResults, new RiaGridCellResultsStateHandler) + this, &Self::SetGridResults, &Self::RequestSetGridResults, new RiaGridCellResultsStateHandler(true)) }; } diff --git a/ApplicationCode/GrpcInterface/RiaGrpcServer.cpp b/ApplicationCode/GrpcInterface/RiaGrpcServer.cpp index 4af25b1eff..9356b3762d 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcServer.cpp +++ b/ApplicationCode/GrpcInterface/RiaGrpcServer.cpp @@ -229,12 +229,13 @@ void RiaGrpcServerImpl::waitForNextRequest() while (m_completionQueue->Next(&tag, &ok)) { + std::lock_guard requestLock(m_requestMutex); RiaGrpcCallbackInterface* method = static_cast(tag); - if (ok) + if (!ok) { - std::lock_guard requestLock(m_requestMutex); - m_unprocessedRequests.push_back(method); + method->setNextCallState(RiaGrpcCallbackInterface::FINISH_REQUEST); } + m_unprocessedRequests.push_back(method); } } @@ -247,17 +248,14 @@ void RiaGrpcServerImpl::process(RiaGrpcCallbackInterface* method) { if (method->callState() == RiaGrpcCallbackInterface::CREATE_HANDLER) { - RiaLogging::debug(QString("Creating request handler for: %1").arg(method->name())); method->createRequestHandler(m_completionQueue.get()); } else if (method->callState() == RiaGrpcCallbackInterface::INIT_REQUEST_STARTED) { method->onInitRequestStarted(); - } else if (method->callState() == RiaGrpcCallbackInterface::INIT_REQUEST_COMPLETED) { - RiaLogging::info(QString("Initialising handling: %1").arg(method->name())); method->onInitRequestCompleted(); } else if (method->callState() == RiaGrpcCallbackInterface::PROCESS_REQUEST) @@ -266,7 +264,6 @@ void RiaGrpcServerImpl::process(RiaGrpcCallbackInterface* method) } else { - RiaLogging::info(QString("Finished handling: %1").arg(method->name())); method->onFinishRequest(); process(method->createNewFromThis()); delete method; From 596f098d43a6d90baeb303984c6c0272d5119e44 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Thu, 30 May 2019 18:52:38 +0200 Subject: [PATCH 109/396] Python: Add more examples and fix async streaming code --- .../GrpcInterface/CMakeLists.cmake | 4 ++ .../GrpcInterface/Python/api/ResInsight.py | 38 +++++++++++++++++-- .../Python/examples/PoroPermXAsync.py | 22 +++++++++++ .../Python/examples/PoroPermXSync.py | 29 ++++++++++++++ .../Python/examples/ResultValues.py | 28 +++++++------- .../Python/examples/SoilPorVAsync.py | 31 +++++++++++++++ .../Python/examples/SoilPorvSync.py | 29 ++++++++++++++ 7 files changed, 163 insertions(+), 18 deletions(-) create mode 100644 ApplicationCode/GrpcInterface/Python/examples/PoroPermXAsync.py create mode 100644 ApplicationCode/GrpcInterface/Python/examples/PoroPermXSync.py create mode 100644 ApplicationCode/GrpcInterface/Python/examples/SoilPorVAsync.py create mode 100644 ApplicationCode/GrpcInterface/Python/examples/SoilPorvSync.py diff --git a/ApplicationCode/GrpcInterface/CMakeLists.cmake b/ApplicationCode/GrpcInterface/CMakeLists.cmake index b361b90186..9d90b288fe 100644 --- a/ApplicationCode/GrpcInterface/CMakeLists.cmake +++ b/ApplicationCode/GrpcInterface/CMakeLists.cmake @@ -146,6 +146,10 @@ if (PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) "api/ResInsight.py" "examples/CommandExample.py" "examples/GridInfoStreamingExample.py" + "examples/PoroPermXSync.py" + "examples/PoroPermXAsync.py" + "examples/SoilPorvAsync.py" + "examples/SoilPorvSync.py" "examples/ResultValues.py" "examples/SelectedCases.py" "examples/AllCases.py" diff --git a/ApplicationCode/GrpcInterface/Python/api/ResInsight.py b/ApplicationCode/GrpcInterface/Python/api/ResInsight.py index 7e8485d093..dc937a9233 100644 --- a/ApplicationCode/GrpcInterface/Python/api/ResInsight.py +++ b/ApplicationCode/GrpcInterface/Python/api/ResInsight.py @@ -120,7 +120,17 @@ class Properties: def __init__(self, channel): self.properties = Properties_pb2_grpc.PropertiesStub(channel) - def generateResultRequestArrays(self, array, parameters): + def generateResultRequestArrayIterator(self, values_iterator, parameters): + chunk = Properties_pb2.ResultRequestChunk() + chunk.params.CopyFrom(parameters) + yield chunk + + for values in values_iterator: + valmsg = Properties_pb2.ResultArray(values = values) + chunk.values.CopyFrom(valmsg) + yield chunk + + def generateResultRequestChunks(self, array, parameters): # Each double is 8 bytes. A good chunk size is 64KiB = 65536B # Meaning ideal number of doubles would be 8192. # However we need overhead space, so if we choose 8160 in chunk size @@ -157,7 +167,9 @@ class Properties: property_name = propertyName, time_step = timeStep, porosity_model = porosityModelEnum) - return self.properties.GetActiveCellResults(request) + for chunk in self.properties.GetActiveCellResults(request): + yield chunk + def gridCellResults(self, caseId, propertyType, propertyName, timeStep, gridIndex = 0, porosityModel = 'MATRIX_MODEL'): propertyTypeEnum = Properties_pb2.PropertyType.Value(propertyType) porosityModelEnum = GridInfo_pb2.PorosityModelType.Value(porosityModel) @@ -168,6 +180,25 @@ class Properties: grid_index = gridIndex, porosity_model = porosityModelEnum) return self.properties.GetGridResults(request) + + def setActiveCellResultsAsync(self, values_iterator, caseId, propertyType, propertyName, timeStep, gridIndex = 0, porosityModel = 'MATRIX_MODEL'): + propertyTypeEnum = Properties_pb2.PropertyType.Value(propertyType) + porosityModelEnum = GridInfo_pb2.PorosityModelType.Value(porosityModel) + request = Properties_pb2.ResultRequest(request_case = CaseInfo_pb2.Case(id=caseId), + property_type = propertyTypeEnum, + property_name = propertyName, + time_step = timeStep, + grid_index = gridIndex, + porosity_model = porosityModelEnum) + try: + reply_iterator = self.generateResultRequestArrayIterator(values_iterator, request) + self.properties.SetActiveCellResults(reply_iterator) + except grpc.RpcError as e: + if e.code() == grpc.StatusCode.NOT_FOUND: + print("Command not found") + else: + print("Other error", e) + def setActiveCellResults(self, values, caseId, propertyType, propertyName, timeStep, gridIndex = 0, porosityModel = 'MATRIX_MODEL'): propertyTypeEnum = Properties_pb2.PropertyType.Value(propertyType) porosityModelEnum = GridInfo_pb2.PorosityModelType.Value(porosityModel) @@ -178,14 +209,13 @@ class Properties: grid_index = gridIndex, porosity_model = porosityModelEnum) try: - request_iterator = self.generateResultRequestArrays(values, request) + request_iterator = self.generateResultRequestChunks(values, request) self.properties.SetActiveCellResults(request_iterator) except grpc.RpcError as e: if e.code() == grpc.StatusCode.NOT_FOUND: print("Command not found") else: print("Other error", e) - def setGridResults(self, values, caseId, propertyType, propertyName, timeStep, gridIndex = 0, porosityModel = 'MATRIX_MODEL'): propertyTypeEnum = Properties_pb2.PropertyType.Value(propertyType) porosityModelEnum = GridInfo_pb2.PorosityModelType.Value(porosityModel) diff --git a/ApplicationCode/GrpcInterface/Python/examples/PoroPermXAsync.py b/ApplicationCode/GrpcInterface/Python/examples/PoroPermXAsync.py new file mode 100644 index 0000000000..859fb3845c --- /dev/null +++ b/ApplicationCode/GrpcInterface/Python/examples/PoroPermXAsync.py @@ -0,0 +1,22 @@ +import sys +import os +sys.path.insert(1, os.path.join(sys.path[0], '../api')) +import ResInsight + +def createResult(poroChunks, permxChunks): + for (poroChunk, permxChunk) in zip(poroChunks, permxChunks): + resultChunk = [] + for (poro, permx) in zip(poroChunk.values, permxChunk.values): + resultChunk.append(poro * permx) + yield resultChunk + + + +resInsight = ResInsight.Instance.find() + +poroChunks = resInsight.properties.activeCellResults(0, 'STATIC_NATIVE', 'PORO', 0) +permxChunks = resInsight.properties.activeCellResults(0, 'STATIC_NATIVE', 'PERMX', 0) + +resInsight.properties.setActiveCellResultsAsync(createResult(poroChunks, permxChunks), 0, 'GENERATED', 'POROPERMXAS', 0) + +print("Transferred all results back") \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/Python/examples/PoroPermXSync.py b/ApplicationCode/GrpcInterface/Python/examples/PoroPermXSync.py new file mode 100644 index 0000000000..d1ca8d111c --- /dev/null +++ b/ApplicationCode/GrpcInterface/Python/examples/PoroPermXSync.py @@ -0,0 +1,29 @@ +import sys +import os +sys.path.insert(1, os.path.join(sys.path[0], '../api')) +import ResInsight + +resInsight = ResInsight.Instance.find() +#gridCount = resInsight.gridInfo.getGridCount(caseId=0) +#gridDimensions = resInsight.gridInfo.getAllGridDimensions(caseId=0) + +for i in range(0, 40): + poroChunks = resInsight.properties.activeCellResults(0, 'STATIC_NATIVE', 'PORO', 0) + poroResults = [] + for poroChunk in poroChunks: + for poro in poroChunk.values: + poroResults.append(poro) + + permxChunks = resInsight.properties.activeCellResults(0, 'STATIC_NATIVE', 'PERMX', 0) + permxResults = [] + for permxChunk in permxChunks: + for permx in permxChunk.values: + permxResults.append(permx) + + results = [] + for (poro, permx) in zip(poroResults, permxResults): + results.append(poro * permx) + + resInsight.properties.setActiveCellResults(results, 0, 'GENERATED', 'POROPERMXSY', 0) + +print("Transferred all results back") \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/Python/examples/ResultValues.py b/ApplicationCode/GrpcInterface/Python/examples/ResultValues.py index dada3b7227..c334d8c52e 100644 --- a/ApplicationCode/GrpcInterface/Python/examples/ResultValues.py +++ b/ApplicationCode/GrpcInterface/Python/examples/ResultValues.py @@ -7,22 +7,22 @@ resInsight = ResInsight.Instance.find() #gridCount = resInsight.gridInfo.getGridCount(caseId=0) #gridDimensions = resInsight.gridInfo.getAllGridDimensions(caseId=0) -resultChunks = resInsight.properties.activeCellResults(0, 'DYNAMIC_NATIVE', 'SOIL', 2) +poroChunks = resInsight.properties.activeCellResults(0, 'STATIC_NATIVE', 'PORO', 0) +poroResults = [] +for poroChunk in poroChunks: + for poro in poroChunk.values: + poroResults.append(poro) + +permxChunks = resInsight.properties.activeCellResults(0, 'STATIC_NATIVE', 'PERMX', 0) +permxResults = [] +for permxChunk in permxChunks: + for permx in permxChunk.values: + permxResults.append(permx) results = [] -for resultChunk in resultChunks: - for value in resultChunk.values: - results.append(value) +for (poro, permx) in zip(poroResults, permxResults): + results.append(poro * permx) + print("Transferred " + str(len(results)) + " cell results") print("30th active cell: ") print(results[29]) - -resultChunks = resInsight.properties.gridCellResults(0, 'DYNAMIC_NATIVE', 'SOIL', 2) - -results = [] -for resultChunk in resultChunks: - for value in resultChunk.values: - results.append(value) -print("Transferred " + str(len(results)) + " cell results") -print("124498th cell: ") -print(results[124498]) diff --git a/ApplicationCode/GrpcInterface/Python/examples/SoilPorVAsync.py b/ApplicationCode/GrpcInterface/Python/examples/SoilPorVAsync.py new file mode 100644 index 0000000000..bc31125d26 --- /dev/null +++ b/ApplicationCode/GrpcInterface/Python/examples/SoilPorVAsync.py @@ -0,0 +1,31 @@ +import sys +import os +sys.path.insert(1, os.path.join(sys.path[0], '../api')) +import ResInsight + +def createResult(soilChunks, porvChunks): + for (soilChunk, porvChunk) in zip(soilChunks, porvChunks): + resultChunk = [] + number = 0 + for (soil, porv) in zip(soilChunk.values, porvChunk.values): + resultChunk.append(soil * porv) + number += 1 + yield resultChunk + + + +resInsight = ResInsight.Instance.find() + +timeStepInfo = resInsight.gridInfo.timeSteps(0) + +porvChunks = resInsight.properties.activeCellResults(0, 'STATIC_NATIVE', 'PORV', 0) +porvArray = [] +for porvChunk in porvChunks: + porvArray.append(porvChunk) + +for i in range (0, len(timeStepInfo.date)): + soilChunks = resInsight.properties.activeCellResults(0, 'DYNAMIC_NATIVE', 'SOIL', i) + input_iterator = createResult(soilChunks, iter(porvArray)) + resInsight.properties.setActiveCellResultsAsync(input_iterator, 0, 'GENERATED', 'SOILPORVAsync', i) + +print("Transferred all results back") \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/Python/examples/SoilPorvSync.py b/ApplicationCode/GrpcInterface/Python/examples/SoilPorvSync.py new file mode 100644 index 0000000000..f17c7e838f --- /dev/null +++ b/ApplicationCode/GrpcInterface/Python/examples/SoilPorvSync.py @@ -0,0 +1,29 @@ +import sys +import os +sys.path.insert(1, os.path.join(sys.path[0], '../api')) +import ResInsight + +resInsight = ResInsight.Instance.find() +#gridCount = resInsight.gridInfo.getGridCount(caseId=0) +#gridDimensions = resInsight.gridInfo.getAllGridDimensions(caseId=0) + +porvChunks = resInsight.properties.activeCellResults(0, 'STATIC_NATIVE', 'PORV', 0) +porvResults = [] +for porvChunk in porvChunks: + for porv in porvChunk.values: + porvResults.append(porv) + +timeStepInfo = resInsight.gridInfo.timeSteps(0) + +for i in range (0, len(timeStepInfo.date)): + soilChunks = resInsight.properties.activeCellResults(0, 'DYNAMIC_NATIVE', 'SOIL', i) + soilResults = [] + for soilChunk in soilChunks: + for soil in soilChunk.values: + soilResults.append(soil) + results = [] + for (soil, porv) in zip(soilResults, porvResults): + results.append(soil * porv) + + resInsight.properties.setActiveCellResults(results, 0, 'GENERATED', 'SOILPORVSync', i) +print("Transferred all results back") \ No newline at end of file From ec5e655617730598a2cafbeb8d09d5454aab805d Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 31 May 2019 10:15:11 +0200 Subject: [PATCH 110/396] Fix casing : temp delete --- .../Python/examples/SoilPorVAsync.py | 31 ------------------- 1 file changed, 31 deletions(-) delete mode 100644 ApplicationCode/GrpcInterface/Python/examples/SoilPorVAsync.py diff --git a/ApplicationCode/GrpcInterface/Python/examples/SoilPorVAsync.py b/ApplicationCode/GrpcInterface/Python/examples/SoilPorVAsync.py deleted file mode 100644 index bc31125d26..0000000000 --- a/ApplicationCode/GrpcInterface/Python/examples/SoilPorVAsync.py +++ /dev/null @@ -1,31 +0,0 @@ -import sys -import os -sys.path.insert(1, os.path.join(sys.path[0], '../api')) -import ResInsight - -def createResult(soilChunks, porvChunks): - for (soilChunk, porvChunk) in zip(soilChunks, porvChunks): - resultChunk = [] - number = 0 - for (soil, porv) in zip(soilChunk.values, porvChunk.values): - resultChunk.append(soil * porv) - number += 1 - yield resultChunk - - - -resInsight = ResInsight.Instance.find() - -timeStepInfo = resInsight.gridInfo.timeSteps(0) - -porvChunks = resInsight.properties.activeCellResults(0, 'STATIC_NATIVE', 'PORV', 0) -porvArray = [] -for porvChunk in porvChunks: - porvArray.append(porvChunk) - -for i in range (0, len(timeStepInfo.date)): - soilChunks = resInsight.properties.activeCellResults(0, 'DYNAMIC_NATIVE', 'SOIL', i) - input_iterator = createResult(soilChunks, iter(porvArray)) - resInsight.properties.setActiveCellResultsAsync(input_iterator, 0, 'GENERATED', 'SOILPORVAsync', i) - -print("Transferred all results back") \ No newline at end of file From db97951a80d3eb7a565c41ea23eace6672232c81 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 31 May 2019 10:17:44 +0200 Subject: [PATCH 111/396] Fix casing : Add file with correct casing --- .../Python/examples/SoilPorvAsync.py | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 ApplicationCode/GrpcInterface/Python/examples/SoilPorvAsync.py diff --git a/ApplicationCode/GrpcInterface/Python/examples/SoilPorvAsync.py b/ApplicationCode/GrpcInterface/Python/examples/SoilPorvAsync.py new file mode 100644 index 0000000000..bc31125d26 --- /dev/null +++ b/ApplicationCode/GrpcInterface/Python/examples/SoilPorvAsync.py @@ -0,0 +1,31 @@ +import sys +import os +sys.path.insert(1, os.path.join(sys.path[0], '../api')) +import ResInsight + +def createResult(soilChunks, porvChunks): + for (soilChunk, porvChunk) in zip(soilChunks, porvChunks): + resultChunk = [] + number = 0 + for (soil, porv) in zip(soilChunk.values, porvChunk.values): + resultChunk.append(soil * porv) + number += 1 + yield resultChunk + + + +resInsight = ResInsight.Instance.find() + +timeStepInfo = resInsight.gridInfo.timeSteps(0) + +porvChunks = resInsight.properties.activeCellResults(0, 'STATIC_NATIVE', 'PORV', 0) +porvArray = [] +for porvChunk in porvChunks: + porvArray.append(porvChunk) + +for i in range (0, len(timeStepInfo.date)): + soilChunks = resInsight.properties.activeCellResults(0, 'DYNAMIC_NATIVE', 'SOIL', i) + input_iterator = createResult(soilChunks, iter(porvArray)) + resInsight.properties.setActiveCellResultsAsync(input_iterator, 0, 'GENERATED', 'SOILPORVAsync', i) + +print("Transferred all results back") \ No newline at end of file From 5365f4dd7df86daa42d8d8576d9bcb63c28d6745 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Fri, 31 May 2019 10:22:30 +0200 Subject: [PATCH 112/396] Caf build fixes for CEE_USE_QT5 --- Fwk/AppFwk/CMakeLists.txt | 4 ++- Fwk/AppFwk/CommonCode/CMakeLists.txt | 2 -- Fwk/AppFwk/cafAnimControl/CMakeLists.txt | 2 -- Fwk/AppFwk/cafCommand/CMakeLists.txt | 2 -- Fwk/AppFwk/cafPdmCvf/CMakeLists.txt | 2 -- Fwk/AppFwk/cafProjectDataModel/CMakeLists.txt | 2 -- .../cafPdmCore/CMakeLists.txt | 2 -- .../cafPdmCore_UnitTests/CMakeLists.txt | 33 ++++++++++--------- .../cafPdmUiCore/CMakeLists.txt | 2 -- .../cafPdmXml/CMakeLists.txt | 2 -- .../cafPdmXml_UnitTests/CMakeLists.txt | 29 ++++++++-------- .../CMakeLists.txt | 15 ++++----- .../cafTestApplication/CMakeLists.txt | 8 ++--- Fwk/AppFwk/cafUserInterface/CMakeLists.txt | 2 -- Fwk/AppFwk/cafViewer/CMakeLists.txt | 2 -- Fwk/AppFwk/cafVizExtensions/CMakeLists.txt | 2 -- Fwk/CMakeLists.txt | 12 ++++--- 17 files changed, 50 insertions(+), 73 deletions(-) diff --git a/Fwk/AppFwk/CMakeLists.txt b/Fwk/AppFwk/CMakeLists.txt index 4b1ccbb5b1..a844191dd5 100644 --- a/Fwk/AppFwk/CMakeLists.txt +++ b/Fwk/AppFwk/CMakeLists.txt @@ -9,7 +9,9 @@ if (MSVC AND (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 19.11)) endif() # Qt -option(CEE_USE_QT5 "Use Qt5" OFF) +if (NOT DEFINED(CEE_USE_QT5)) + option(CEE_USE_QT5 "Use Qt5" OFF) +endif(NOT DEFINED(CEE_USE_QT5)) if (CEE_USE_QT5) find_package(Qt5 COMPONENTS REQUIRED Core Gui OpenGL Widgets) diff --git a/Fwk/AppFwk/CommonCode/CMakeLists.txt b/Fwk/AppFwk/CommonCode/CMakeLists.txt index 6fe78fd8f6..021b52ccc1 100644 --- a/Fwk/AppFwk/CommonCode/CMakeLists.txt +++ b/Fwk/AppFwk/CommonCode/CMakeLists.txt @@ -12,8 +12,6 @@ set( MOC_HEADER_FILES cafMessagePanel.h ) -option(CEE_USE_QT5 "Use Qt5" OFF) - if (CEE_USE_QT5) find_package(Qt5 COMPONENTS REQUIRED Core Gui Widgets OpenGL) set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets Qt5::OpenGL) diff --git a/Fwk/AppFwk/cafAnimControl/CMakeLists.txt b/Fwk/AppFwk/cafAnimControl/CMakeLists.txt index 7c8be9ae6c..9533c572d7 100644 --- a/Fwk/AppFwk/cafAnimControl/CMakeLists.txt +++ b/Fwk/AppFwk/cafAnimControl/CMakeLists.txt @@ -9,8 +9,6 @@ set( MOC_HEADER_FILES cafPopupMenuButton.h ) -option(CEE_USE_QT5 "Use Qt5" OFF) - if (CEE_USE_QT5) find_package(Qt5 COMPONENTS REQUIRED Core Gui Widgets) set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets) diff --git a/Fwk/AppFwk/cafCommand/CMakeLists.txt b/Fwk/AppFwk/cafCommand/CMakeLists.txt index 9ab9f8261e..713a1954b5 100644 --- a/Fwk/AppFwk/cafCommand/CMakeLists.txt +++ b/Fwk/AppFwk/cafCommand/CMakeLists.txt @@ -10,8 +10,6 @@ set (MOC_HEADER_FILES ) # Qt -option(CEE_USE_QT5 "Use Qt5" OFF) - if (CEE_USE_QT5) find_package(Qt5 COMPONENTS REQUIRED Core Gui Widgets) set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets) diff --git a/Fwk/AppFwk/cafPdmCvf/CMakeLists.txt b/Fwk/AppFwk/cafPdmCvf/CMakeLists.txt index 1a0f8d0c35..c591101321 100644 --- a/Fwk/AppFwk/cafPdmCvf/CMakeLists.txt +++ b/Fwk/AppFwk/cafPdmCvf/CMakeLists.txt @@ -3,8 +3,6 @@ cmake_minimum_required (VERSION 2.8.12) project (cafPdmCvf) # Qt -option(CEE_USE_QT5 "Use Qt5" OFF) - if (CEE_USE_QT5) find_package(Qt5 COMPONENTS REQUIRED Core Gui Widgets) set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets) diff --git a/Fwk/AppFwk/cafProjectDataModel/CMakeLists.txt b/Fwk/AppFwk/cafProjectDataModel/CMakeLists.txt index 6f760559b0..90bb67c169 100644 --- a/Fwk/AppFwk/cafProjectDataModel/CMakeLists.txt +++ b/Fwk/AppFwk/cafProjectDataModel/CMakeLists.txt @@ -3,8 +3,6 @@ cmake_minimum_required (VERSION 2.8.12) project (cafProjectDataModel) # Qt -option(CEE_USE_QT5 "Use Qt5" OFF) - if (CEE_USE_QT5) find_package(Qt5 COMPONENTS REQUIRED Core Gui Widgets) set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets) diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/CMakeLists.txt b/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/CMakeLists.txt index f8c2898012..259417b084 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/CMakeLists.txt +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/CMakeLists.txt @@ -2,8 +2,6 @@ cmake_minimum_required (VERSION 2.8.12) project (cafPdmCore) # Qt -option(CEE_USE_QT5 "Use Qt5" OFF) - if (CEE_USE_QT5) find_package(Qt5 COMPONENTS REQUIRED Core) set(QT_LIBRARIES Qt5::Core) diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/cafPdmCore_UnitTests/CMakeLists.txt b/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/cafPdmCore_UnitTests/CMakeLists.txt index f5c9d39c1d..27e369c1ff 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/cafPdmCore_UnitTests/CMakeLists.txt +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/cafPdmCore_UnitTests/CMakeLists.txt @@ -2,13 +2,18 @@ cmake_minimum_required (VERSION 2.8.12) project ( cafPdmCore_UnitTests ) -find_package(Qt5Core CONFIG QUIET) -if (Qt5Core_FOUND) - find_package(Qt5 CONFIG REQUIRED Core Gui Widgets) +# Qt +if (NOT DEFINED(CEE_USE_QT5)) + option(CEE_USE_QT5 "Use Qt5" OFF) +endif(NOT DEFINED(CEE_USE_QT5)) + +if (CEE_USE_QT5) + find_package(Qt5 COMPONENTS REQUIRED Core Gui Widgets) + set(QT_LIBRARIES Qt5::Core Qt5::Widgets Qt5::Gui) else() - find_package(Qt4 COMPONENTS QtCore QtGui REQUIRED) - include(${QT_USE_FILE}) -endif(Qt5Core_FOUND) + find_package(Qt4 COMPONENTS REQUIRED QtCore QtGui) + include(${QT_USE_FILE}) +endif(CEE_USE_QT5) if (MSVC AND (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 19.11)) # VS 2017 : Disable warnings from from gtest code, using deprecated code related to TR1 @@ -57,7 +62,7 @@ target_link_libraries ( ${PROJECT_NAME} ) # Copy Qt Dlls -if (Qt5Core_FOUND) +if (CEE_USE_QT5) foreach (qtlib ${QT_LIBRARIES}) add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different $ $ @@ -65,16 +70,12 @@ if (Qt5Core_FOUND) endforeach(qtlib) # Copy Qt Dlls else() - # Copy Qt Dlls if (MSVC) - set (QTLIBLIST QtCore QtGui ) + set (QTLIBLIST QtCore QtGui) foreach (qtlib ${QTLIBLIST}) - - # Debug - execute_process(COMMAND cmake -E copy_if_different ${QT_BINARY_DIR}/${qtlib}d4.dll ${CMAKE_BINARY_DIR}/Debug/${qtlib}d4.dll) - - # Release - execute_process(COMMAND cmake -E copy_if_different ${QT_BINARY_DIR}/${qtlib}4.dll ${CMAKE_BINARY_DIR}/Release/${qtlib}4.dll) + add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${QT_BINARY_DIR}/$,${qtlib}d4.dll,${qtlib}4.dll> $ + ) endforeach( qtlib ) endif(MSVC) -endif(Qt5Core_FOUND) \ No newline at end of file +endif(CEE_USE_QT5) \ No newline at end of file diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/CMakeLists.txt b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/CMakeLists.txt index 7ad8a54821..30505b80f6 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/CMakeLists.txt +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/CMakeLists.txt @@ -11,8 +11,6 @@ set (MOC_HEADER_FILES ) # Qt -option(CEE_USE_QT5 "Use Qt5" OFF) - if (CEE_USE_QT5) find_package(Qt5 COMPONENTS REQUIRED Core Gui Widgets) set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets) diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmXml/CMakeLists.txt b/Fwk/AppFwk/cafProjectDataModel/cafPdmXml/CMakeLists.txt index 6cf05f2cf2..1bb378b143 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmXml/CMakeLists.txt +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmXml/CMakeLists.txt @@ -3,8 +3,6 @@ cmake_minimum_required (VERSION 2.8.12) project (cafPdmXml) # Qt -option(CEE_USE_QT5 "Use Qt5" OFF) - if (CEE_USE_QT5) find_package(Qt5 COMPONENTS REQUIRED Core Xml) set(QT_LIBRARIES Qt5::Core Qt5::Xml) diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmXml/cafPdmXml_UnitTests/CMakeLists.txt b/Fwk/AppFwk/cafProjectDataModel/cafPdmXml/cafPdmXml_UnitTests/CMakeLists.txt index e39d304012..0e248a7daa 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmXml/cafPdmXml_UnitTests/CMakeLists.txt +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmXml/cafPdmXml_UnitTests/CMakeLists.txt @@ -2,13 +2,17 @@ cmake_minimum_required (VERSION 2.8.12) project ( cafPdmXml_UnitTests ) -find_package(Qt5Core CONFIG QUIET) -if (Qt5Core_FOUND) - find_package(Qt5 CONFIG REQUIRED Core Xml) +if (NOT DEFINED(CEE_USE_QT5)) + option(CEE_USE_QT5 "Use Qt5" OFF) +endif(NOT DEFINED(CEE_USE_QT5)) + +if (CEE_USE_QT5) + find_package(Qt5 COMPONENTS REQUIRED Core Xml) + set(QT_LIBRARIES Qt5::Core Qt5::Xml) else() - find_package(Qt4 COMPONENTS QtCore QtXml REQUIRED) - include(${QT_USE_FILE}) -endif(Qt5Core_FOUND) + find_package(Qt4 COMPONENTS REQUIRED QtCore QtXml) + include(${QT_USE_FILE}) +endif(CEE_USE_QT5) if (MSVC AND (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 19.11)) # VS 2017 : Disable warnings from from gtest code, using deprecated code related to TR1 @@ -49,18 +53,13 @@ if (Qt5Core_FOUND) COMMAND ${CMAKE_COMMAND} -E copy_if_different $ $ ) endforeach(qtlib) - # Copy Qt Dlls else() - # Copy Qt Dlls if (MSVC) - set (QTLIBLIST QtCore) + set (QTLIBLIST QtCore QtXml) foreach (qtlib ${QTLIBLIST}) - - # Debug - execute_process(COMMAND cmake -E copy_if_different ${QT_BINARY_DIR}/${qtlib}d4.dll ${CMAKE_BINARY_DIR}/Debug/${qtlib}d4.dll) - - # Release - execute_process(COMMAND cmake -E copy_if_different ${QT_BINARY_DIR}/${qtlib}4.dll ${CMAKE_BINARY_DIR}/Release/${qtlib}4.dll) + add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${QT_BINARY_DIR}/$,${qtlib}d4.dll,${qtlib}4.dll> $ + ) endforeach( qtlib ) endif(MSVC) endif(Qt5Core_FOUND) \ No newline at end of file diff --git a/Fwk/AppFwk/cafProjectDataModel/cafProjectDataModel_UnitTests/CMakeLists.txt b/Fwk/AppFwk/cafProjectDataModel/cafProjectDataModel_UnitTests/CMakeLists.txt index 673b7861ff..cfddb11b22 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafProjectDataModel_UnitTests/CMakeLists.txt +++ b/Fwk/AppFwk/cafProjectDataModel/cafProjectDataModel_UnitTests/CMakeLists.txt @@ -3,7 +3,9 @@ cmake_minimum_required (VERSION 2.8.12) project ( cafProjectDataModel_UnitTests ) # Qt -option(CEE_USE_QT5 "Use Qt5" OFF) +if (NOT DEFINED(CEE_USE_QT5)) + option(CEE_USE_QT5 "Use Qt5" OFF) +endif(NOT DEFINED(CEE_USE_QT5)) if (CEE_USE_QT5) find_package(Qt5 COMPONENTS REQUIRED Core Xml Gui) @@ -53,18 +55,13 @@ if (CEE_USE_QT5) COMMAND ${CMAKE_COMMAND} -E copy_if_different $ $ ) endforeach(qtlib) - # Copy Qt Dlls else() - # Copy Qt Dlls if (MSVC) set (QTLIBLIST QtCore QtXml) foreach (qtlib ${QTLIBLIST}) - - # Debug - execute_process(COMMAND cmake -E copy_if_different ${QT_BINARY_DIR}/${qtlib}d4.dll ${CMAKE_BINARY_DIR}/Debug/${qtlib}d4.dll) - - # Release - execute_process(COMMAND cmake -E copy_if_different ${QT_BINARY_DIR}/${qtlib}4.dll ${CMAKE_BINARY_DIR}/Release/${qtlib}4.dll) + add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${QT_BINARY_DIR}/$,${qtlib}d4.dll,${qtlib}4.dll> $ + ) endforeach( qtlib ) endif(MSVC) endif(CEE_USE_QT5) \ No newline at end of file diff --git a/Fwk/AppFwk/cafTests/cafTestApplication/CMakeLists.txt b/Fwk/AppFwk/cafTests/cafTestApplication/CMakeLists.txt index ae86aea5b6..cdc1659b78 100644 --- a/Fwk/AppFwk/cafTests/cafTestApplication/CMakeLists.txt +++ b/Fwk/AppFwk/cafTests/cafTestApplication/CMakeLists.txt @@ -20,7 +20,9 @@ set( QRC_FILES textedit.qrc ) -option(CEE_USE_QT5 "Use Qt5" OFF) +if (NOT DEFINED(CEE_USE_QT5)) + option(CEE_USE_QT5 "Use Qt5" OFF) +endif(NOT DEFINED(CEE_USE_QT5)) if (CEE_USE_QT5) find_package(Qt5 COMPONENTS REQUIRED Core Gui Widgets OpenGL) @@ -66,10 +68,6 @@ add_executable ( ${PROJECT_NAME} ${QRC_FILES_CPP} ) -if (Qt5Core_FOUND) - set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::OpenGL Qt5::Widgets) -endif() - set (TAP_LINK_LIBRARIES cafUserInterface ) diff --git a/Fwk/AppFwk/cafUserInterface/CMakeLists.txt b/Fwk/AppFwk/cafUserInterface/CMakeLists.txt index 4c254fcbc4..5f2bf15809 100644 --- a/Fwk/AppFwk/cafUserInterface/CMakeLists.txt +++ b/Fwk/AppFwk/cafUserInterface/CMakeLists.txt @@ -46,8 +46,6 @@ set (MOC_HEADER_FILES cafPdmUiPickableLineEditor.h ) -option(CEE_USE_QT5 "Use Qt5" OFF) - if (CEE_USE_QT5) find_package(Qt5 COMPONENTS REQUIRED Core Gui Widgets) set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets) diff --git a/Fwk/AppFwk/cafViewer/CMakeLists.txt b/Fwk/AppFwk/cafViewer/CMakeLists.txt index 02a7fa0977..02df1adb9b 100644 --- a/Fwk/AppFwk/cafViewer/CMakeLists.txt +++ b/Fwk/AppFwk/cafViewer/CMakeLists.txt @@ -9,8 +9,6 @@ set( MOC_HEADER_FILES cafViewer.h ) -option(CEE_USE_QT5 "Use Qt5" OFF) - if (CEE_USE_QT5) find_package(Qt5 COMPONENTS REQUIRED Core Gui Widgets OpenGL) set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets Qt5::OpenGL) diff --git a/Fwk/AppFwk/cafVizExtensions/CMakeLists.txt b/Fwk/AppFwk/cafVizExtensions/CMakeLists.txt index 2cfb626515..5ac19fdb39 100644 --- a/Fwk/AppFwk/cafVizExtensions/CMakeLists.txt +++ b/Fwk/AppFwk/cafVizExtensions/CMakeLists.txt @@ -6,8 +6,6 @@ project (cafVizExtensions) find_package( OpenGL ) # Qt -option(CEE_USE_QT5 "Use Qt5" OFF) - if (CEE_USE_QT5) find_package(Qt5 COMPONENTS REQUIRED Core Gui Widgets OpenGL) set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets Qt5::OpenGL) diff --git a/Fwk/CMakeLists.txt b/Fwk/CMakeLists.txt index 1de607cd14..4b00e6a77e 100644 --- a/Fwk/CMakeLists.txt +++ b/Fwk/CMakeLists.txt @@ -2,13 +2,15 @@ cmake_minimum_required (VERSION 2.8.12) project (TestCafAndVizFwk) -find_package(Qt5 CONFIG COMPONENTS Core) -if (Qt5Core_FOUND) - find_package(Qt5 CONFIG REQUIRED Core Gui OpenGL Widgets) +option(CEE_USE_QT5 "Use Qt5" OFF) + +if (CEE_USE_QT5) + find_package(Qt5 COMPONENTS REQUIRED Core Gui OpenGL Widgets) + set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::OpenGL Qt5::Widgets) else() - find_package(Qt4 COMPONENTS QtCore QtGui QtMain QtOpenGL REQUIRED) + find_package(Qt4 COMPONENTS QtCore QtGui QtMain QtOpenGl REQUIRED) include(${QT_USE_FILE}) -endif(Qt5Core_FOUND) +endif(CEE_USE_QT5) # Libraries add_subdirectory(AppFwk/cafProjectDataModel/cafPdmCore) From 2c30f846f04a040c0ca295533035e6bedd39d846 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Fri, 31 May 2019 10:24:05 +0200 Subject: [PATCH 113/396] Make MDI Window icon different from main application icon --- ApplicationCode/Resources/ResInsight.qrc | 1 + ApplicationCode/Resources/Window16x16.png | Bin 0 -> 1885 bytes .../UserInterface/RiuMdiSubWindow.cpp | 1 + 3 files changed, 2 insertions(+) create mode 100644 ApplicationCode/Resources/Window16x16.png diff --git a/ApplicationCode/Resources/ResInsight.qrc b/ApplicationCode/Resources/ResInsight.qrc index ceb002417f..fe34b9b7f5 100644 --- a/ApplicationCode/Resources/ResInsight.qrc +++ b/ApplicationCode/Resources/ResInsight.qrc @@ -58,6 +58,7 @@ GeoMechCases48x48.png chain.png TileWindows24x24.png + Window16x16.png LasFile16x16.png WellLogTrack16x16.png WellLogPlot16x16.png diff --git a/ApplicationCode/Resources/Window16x16.png b/ApplicationCode/Resources/Window16x16.png new file mode 100644 index 0000000000000000000000000000000000000000..1c891b5b8a61ed818cd64b1b0db73d3297eeecdc GIT binary patch literal 1885 zcmV-j2cr0iP) zaB^>EX>4U6ba`-PAZ2)IW&i+q+SONCvMj3#{dW|12m&@Z9NUOHgE#!UY%)((?LPMT zd1+K?A_B4iEz|$^?=b)1VYb0IA2p;9EFPC!;*5dX{p9r~>(={x*lX}aH}?dCB2%FDH?M4-_5Vj%|z~VXSOjgx}gURN~TqD|-Dl7c0Xi?m}Ym)@h-@d`Xhg zd%Q*9CX6S=V>V;U zAG&#jbm8`(IfPsD6CDW0r#)Y&&EFVJ$LM=^*#&GloK0O@StIb3>8-UYphf(=)#>cn z5}G0=IK0Nq#l5W}pfIZAZV#}H%Gm|`|6>eOq{sH#bG;v}fJJ|Q2Irj&Aq(hSKN zt1}pKE?lIz;!7y8Xh|hkHdU&tzJ?mB)>L!jCJlMqLW@mXYPnNKD0SC;4?TA6spo-E z8#3JRBaAq7Bs21j+JW^=`vGcnP~(NvWQ;dzpvHKKpjl4*#0-eBBLE&J0wjicVrG?` zKubiaSyXdzo{%@lO?F~cntw*0^lF1-^qu9+KOOCbZnn2>e z^pySPsyHi=ak`})2J_yEUiT7fW09@9x`^X*uY|3EhcqpMzQGz>N?pne$7>%8-Dan>Wv76v1Di$nPH2-I3Q69M zN4?sM6lGB_Eplg3r^cl z{T+(h-Z-@t*}f~)?sw#sQkB~_yMu%M@jkJZ?ZZ$*aA%kug>8K^2$ydr4%bgTY6~`BS5#}Ln(}w_Alj4r6rpo;?Eu{y4b8VN!QO~vqZU-qp zT4_Eg86R00#NSplepqJqx*{jJISmPK_E4@p1o$mp`Bm##7OErDeLFHd^*8bQdANp? z0Ggzm{^h}SzzZz?gimJa@t$vfA4dh(E)FMGal65v*6rv~0{%bztoYkso<;T}LEkXr zwKsq1=(o5Z9Tyg&vC%}GkRNZ({N6k73liMllKBr1Ee#<@yWBVc000JJOGiWipa6gX zXe&6@0{{R332;bRa{vGf6951U69E94oEQKA00(qQO+^Re1s?}A4#h*mKmY&$8FWQh zbVF}#ZDnqB07G(RVRU6=Aa`kWXdp*PO;A^X4i^9b0e(qDK~y-)#gok|1OXVvfAg`% z?5_1W`6flCKzB=1)*kE^=@XDa(q|GQK~@YIhB@<6>oN zM~U*Dp7-!PJx|a3!hesD1BPL^KOsh=Q2{{wtpoY%lDN899-8XbtQU*enu)b--(=KA zZLPXDk7T^8cI9xMgPGY0t-HP#y+SA4*GltfP%C=17&u$@bdV=-bQ>pr9mC34_BpKDG&^`?J4@tzObvmQ~gggYM1AZJk zN%k#+C>JBRB5u}2DQzGdEFm?r$K+z!EumoH2-f93hbL(^4=OQF6D02v*p5vqeUBq4 z1RDF98~0avM%X=W`#@RDjE)Jk)@+~#YjHx)D6WIQvK=@qECA3Fk9^`|eT<{a9su-) zEgbs^pQ_~<7rn^2z2#sLfVdgv Date: Fri, 31 May 2019 14:47:57 +0200 Subject: [PATCH 114/396] #4453 libecl : Add patch for construction of ACTNUM from PORV Assign a value of 3 (two bit masks combined) when creating ACTNUM based on PORV --- patches/libecl_dualporo_actnum.patch | 34 ++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 patches/libecl_dualporo_actnum.patch diff --git a/patches/libecl_dualporo_actnum.patch b/patches/libecl_dualporo_actnum.patch new file mode 100644 index 0000000000..2c9a1e56ff --- /dev/null +++ b/patches/libecl_dualporo_actnum.patch @@ -0,0 +1,34 @@ +From 978139b8cd9361fa1a5884079e66999ee39ea1bd Mon Sep 17 00:00:00 2001 +From: Magne Sjaastad +Date: Fri, 31 May 2019 14:37:50 +0200 +Subject: [PATCH] helper function for libecl dual porosity + +--- + ThirdParty/Ert/lib/ecl/ecl_kw_functions.cpp | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/ThirdParty/Ert/lib/ecl/ecl_kw_functions.cpp b/ThirdParty/Ert/lib/ecl/ecl_kw_functions.cpp +index d10646fd3..e5d980fb1 100644 +--- a/ThirdParty/Ert/lib/ecl/ecl_kw_functions.cpp ++++ b/ThirdParty/Ert/lib/ecl/ecl_kw_functions.cpp +@@ -143,9 +143,16 @@ ecl_kw_type * ecl_kw_alloc_actnum(const ecl_kw_type * porv_kw, float porv_limit) + const float * porv_values = ecl_kw_get_float_ptr(porv_kw); + int * actnum_values = ecl_kw_get_int_ptr( actnum_kw); + ++ // When PORV is used as criteria, make sure all active cells are assigned both ++ // active matrix and active fracture. This will make sure that both single porosity ++ // models and dual porosity models in initialized with the correct bit mask ++ // See documentation in top of ecl_grid.cpp ++ // ++ const int combinedActnumValueForMatrixAndFracture = CELL_ACTIVE_MATRIX + CELL_ACTIVE_FRACTURE; ++ + for (int i=0; i < size; i++) { + if (porv_values[i] > porv_limit) +- actnum_values[i] = 1; ++ actnum_values[i] = combinedActnumValueForMatrixAndFracture; + else + actnum_values[i] = 0; + } +-- +2.21.0.windows.1 + From dcf33d9289893ec0f1739ef15fd6ab27d661636f Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 31 May 2019 14:53:36 +0200 Subject: [PATCH 115/396] #4453 Dual Porosity : Use ACTNUM value 3 when creating values from PORV --- ThirdParty/Ert/lib/ecl/ecl_kw_functions.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/ThirdParty/Ert/lib/ecl/ecl_kw_functions.cpp b/ThirdParty/Ert/lib/ecl/ecl_kw_functions.cpp index d10646fd33..e5d980fb1d 100644 --- a/ThirdParty/Ert/lib/ecl/ecl_kw_functions.cpp +++ b/ThirdParty/Ert/lib/ecl/ecl_kw_functions.cpp @@ -143,9 +143,16 @@ ecl_kw_type * ecl_kw_alloc_actnum(const ecl_kw_type * porv_kw, float porv_limit) const float * porv_values = ecl_kw_get_float_ptr(porv_kw); int * actnum_values = ecl_kw_get_int_ptr( actnum_kw); + // When PORV is used as criteria, make sure all active cells are assigned both + // active matrix and active fracture. This will make sure that both single porosity + // models and dual porosity models in initialized with the correct bit mask + // See documentation in top of ecl_grid.cpp + // + const int combinedActnumValueForMatrixAndFracture = CELL_ACTIVE_MATRIX + CELL_ACTIVE_FRACTURE; + for (int i=0; i < size; i++) { if (porv_values[i] > porv_limit) - actnum_values[i] = 1; + actnum_values[i] = combinedActnumValueForMatrixAndFracture; else actnum_values[i] = 0; } From cf0673d4739b7a70b4614a20f491317e5c85d1d0 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 3 Jun 2019 07:33:14 +0200 Subject: [PATCH 116/396] Upped to 2019.04.0-dev.03 --- ResInsightVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ResInsightVersion.cmake b/ResInsightVersion.cmake index bc584775b5..fd54d6ebf7 100644 --- a/ResInsightVersion.cmake +++ b/ResInsightVersion.cmake @@ -10,7 +10,7 @@ set(RESINSIGHT_VERSION_TEXT "-dev") # 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 ".02") +set(RESINSIGHT_DEV_VERSION ".03") # https://github.com/CRAVA/crava/tree/master/libs/nrlib set(NRLIB_GITHUB_SHA "ba35d4359882f1c6f5e9dc30eb95fe52af50fd6f") From 936fab3e320965d365c7c8d3f00435a05397be87 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 3 Jun 2019 09:11:03 +0200 Subject: [PATCH 117/396] libecl : Improve comment --- ThirdParty/Ert/lib/ecl/ecl_kw_functions.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ThirdParty/Ert/lib/ecl/ecl_kw_functions.cpp b/ThirdParty/Ert/lib/ecl/ecl_kw_functions.cpp index e5d980fb1d..2a3a9fb941 100644 --- a/ThirdParty/Ert/lib/ecl/ecl_kw_functions.cpp +++ b/ThirdParty/Ert/lib/ecl/ecl_kw_functions.cpp @@ -144,9 +144,9 @@ ecl_kw_type * ecl_kw_alloc_actnum(const ecl_kw_type * porv_kw, float porv_limit) int * actnum_values = ecl_kw_get_int_ptr( actnum_kw); // When PORV is used as criteria, make sure all active cells are assigned both - // active matrix and active fracture. This will make sure that both single porosity - // models and dual porosity models in initialized with the correct bit mask - // See documentation in top of ecl_grid.cpp + // active matrix state and active fracture state. This will make sure that + // both single porosity models and dual porosity models are initialized with + // the correct bit mask. See documentation in top of ecl_grid.cpp // const int combinedActnumValueForMatrixAndFracture = CELL_ACTIVE_MATRIX + CELL_ACTIVE_FRACTURE; From a468532d7f9df3412cd2ac640392839fdc184773 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Mon, 3 Jun 2019 14:33:16 +0200 Subject: [PATCH 118/396] #4457 Python: clean up grpc api, Python client API and make installable python package (#4456) * gRPC: Make names more consistent * gRPC: clean up case info and improve Python API for cases * gRPC: much more object oriented Python interface * Python: Make a proper pip-installable package * Update rips Python package to auto generate setup.py with version number * Python: add setup.py to gitignore * Python: Update Python RIPS interface * gRPC: Remove example client from cmake file and unit test * gRPC: Fix up unit test after merge and hide warnings * gRPC: fix up python client code --- ApplicationCode/CMakeLists.txt | 4 +- .../GrpcInterface/CMakeLists.cmake | 46 ++- .../{ResInfo.proto => AppInfo.proto} | 2 +- .../GrpcProtos/{GridInfo.proto => Case.proto} | 56 ++-- .../GrpcInterface/GrpcProtos/CaseInfo.proto | 31 -- .../GrpcInterface/GrpcProtos/Commands.proto | 6 +- .../GrpcInterface/GrpcProtos/Grid.proto | 34 ++ .../GrpcInterface/GrpcProtos/Project.proto | 14 + .../GrpcProtos/ProjectInfo.proto | 16 - .../GrpcInterface/GrpcProtos/Properties.proto | 34 +- .../GrpcInterface/Python/.gitignore | 6 +- ApplicationCode/GrpcInterface/Python/LICENSE | 14 + .../GrpcInterface/Python/README.md | 5 + .../GrpcInterface/Python/api/ResInsight.py | 302 ------------------ .../GrpcInterface/Python/api/__init__.py | 0 .../GrpcInterface/Python/examples/AllCases.py | 16 +- ...Example.py => CaseInfoStreamingExample.py} | 6 +- .../Python/examples/GridInformation.py | 18 ++ .../Python/examples/PoroPermXAsync.py | 8 +- .../Python/examples/PoroPermXSync.py | 33 +- .../Python/examples/ResultValues.py | 28 -- .../Python/examples/SelectedCases.py | 13 +- .../examples/SetActiveCellProperties.py | 19 -- .../Python/examples/SetGridProperties.py | 5 +- .../Python/examples/SoilPorvAsync.py | 14 +- .../Python/examples/SoilPorvSync.py | 15 +- .../GrpcInterface/Python/requirements.txt | 3 + .../GrpcInterface/Python/rips/AppInfo.py | 25 ++ .../GrpcInterface/Python/rips/Case.py | 56 ++++ .../GrpcInterface/Python/rips/Commands.py | 43 +++ .../GrpcInterface/Python/rips/Grid.py | 18 ++ .../GrpcInterface/Python/rips/Instance.py | 78 +++++ .../GrpcInterface/Python/rips/Project.py | 45 +++ .../GrpcInterface/Python/rips/Properties.py | 130 ++++++++ .../GrpcInterface/Python/rips/ResInsight.py | 78 +++++ .../GrpcInterface/Python/rips/__init__.py | 5 + .../GrpcInterface/Python/setup.py.cmake | 21 ++ ...oService.cpp => RiaGrpcAppInfoService.cpp} | 12 +- ...sInfoService.h => RiaGrpcAppInfoService.h} | 4 +- ...InfoService.cpp => RiaGrpcCaseService.cpp} | 82 +++-- ...GridInfoService.h => RiaGrpcCaseService.h} | 12 +- .../GrpcInterface/RiaGrpcGridService.cpp | 75 +++++ .../GrpcInterface/RiaGrpcGridService.h | 30 ++ ...oService.cpp => RiaGrpcProjectService.cpp} | 91 ++---- ...tInfoService.h => RiaGrpcProjectService.h} | 18 +- .../RiaGrpcPropertiesService.cpp | 68 ++-- .../GrpcInterface/RiaGrpcPropertiesService.h | 38 +-- .../GrpcInterface/RiaGrpcServer.cpp | 2 +- .../UnitTests/CMakeLists_files.cmake | 9 + .../UnitTests/RiaGrpcInterface-Test.cpp | 68 ++++ 50 files changed, 1058 insertions(+), 698 deletions(-) rename ApplicationCode/GrpcInterface/GrpcProtos/{ResInfo.proto => AppInfo.proto} (91%) rename ApplicationCode/GrpcInterface/GrpcProtos/{GridInfo.proto => Case.proto} (58%) delete mode 100644 ApplicationCode/GrpcInterface/GrpcProtos/CaseInfo.proto create mode 100644 ApplicationCode/GrpcInterface/GrpcProtos/Grid.proto create mode 100644 ApplicationCode/GrpcInterface/GrpcProtos/Project.proto delete mode 100644 ApplicationCode/GrpcInterface/GrpcProtos/ProjectInfo.proto create mode 100644 ApplicationCode/GrpcInterface/Python/LICENSE create mode 100644 ApplicationCode/GrpcInterface/Python/README.md delete mode 100644 ApplicationCode/GrpcInterface/Python/api/ResInsight.py delete mode 100644 ApplicationCode/GrpcInterface/Python/api/__init__.py rename ApplicationCode/GrpcInterface/Python/examples/{GridInfoStreamingExample.py => CaseInfoStreamingExample.py} (84%) create mode 100644 ApplicationCode/GrpcInterface/Python/examples/GridInformation.py delete mode 100644 ApplicationCode/GrpcInterface/Python/examples/ResultValues.py delete mode 100644 ApplicationCode/GrpcInterface/Python/examples/SetActiveCellProperties.py create mode 100644 ApplicationCode/GrpcInterface/Python/requirements.txt create mode 100644 ApplicationCode/GrpcInterface/Python/rips/AppInfo.py create mode 100644 ApplicationCode/GrpcInterface/Python/rips/Case.py create mode 100644 ApplicationCode/GrpcInterface/Python/rips/Commands.py create mode 100644 ApplicationCode/GrpcInterface/Python/rips/Grid.py create mode 100644 ApplicationCode/GrpcInterface/Python/rips/Instance.py create mode 100644 ApplicationCode/GrpcInterface/Python/rips/Project.py create mode 100644 ApplicationCode/GrpcInterface/Python/rips/Properties.py create mode 100644 ApplicationCode/GrpcInterface/Python/rips/ResInsight.py create mode 100644 ApplicationCode/GrpcInterface/Python/rips/__init__.py create mode 100644 ApplicationCode/GrpcInterface/Python/setup.py.cmake rename ApplicationCode/GrpcInterface/{RiaGrpcResInfoService.cpp => RiaGrpcAppInfoService.cpp} (81%) rename ApplicationCode/GrpcInterface/{RiaGrpcResInfoService.h => RiaGrpcAppInfoService.h} (93%) rename ApplicationCode/GrpcInterface/{RiaGrpcGridInfoService.cpp => RiaGrpcCaseService.cpp} (83%) rename ApplicationCode/GrpcInterface/{RiaGrpcGridInfoService.h => RiaGrpcCaseService.h} (88%) create mode 100644 ApplicationCode/GrpcInterface/RiaGrpcGridService.cpp create mode 100644 ApplicationCode/GrpcInterface/RiaGrpcGridService.h rename ApplicationCode/GrpcInterface/{RiaGrpcProjectInfoService.cpp => RiaGrpcProjectService.cpp} (60%) rename ApplicationCode/GrpcInterface/{RiaGrpcProjectInfoService.h => RiaGrpcProjectService.h} (56%) create mode 100644 ApplicationCode/UnitTests/RiaGrpcInterface-Test.cpp diff --git a/ApplicationCode/CMakeLists.txt b/ApplicationCode/CMakeLists.txt index 9304e3e7f7..66d0eb454b 100644 --- a/ApplicationCode/CMakeLists.txt +++ b/ApplicationCode/CMakeLists.txt @@ -313,12 +313,12 @@ if (MSVC) set( EXE_FILES WIN32) if (RESINSIGHT_ENABLE_GRPC) # GRPC generates a lot of harmless warnings on MSVC - set_source_files_properties(${GRPC_CPP_SOURCES} PROPERTIES COMPILE_FLAGS "/wd4251 /wd4702 /wd4005 /wd4244 /wd4125") + set_source_files_properties(${GRPC_CPP_SOURCES} ${GRPC_UNIT_TEST_SOURCE_FILES} PROPERTIES COMPILE_FLAGS "/wd4251 /wd4702 /wd4005 /wd4244 /wd4125") endif(RESINSIGHT_ENABLE_GRPC) elseif (APPLE) set( EXE_FILES MACOSX_BUNDLE) else() - set_source_files_properties(${GRPC_CPP_SOURCES} PROPERTIES COMPILE_FLAGS "-Wno-overloaded-virtual") + set_source_files_properties(${GRPC_CPP_SOURCES} ${GRPC_UNIT_TESTS_SOURCE_FILES} PROPERTIES COMPILE_FLAGS "-Wno-overloaded-virtual") endif() set( EXE_FILES ${EXE_FILES} diff --git a/ApplicationCode/GrpcInterface/CMakeLists.cmake b/ApplicationCode/GrpcInterface/CMakeLists.cmake index 9d90b288fe..aa2c83701c 100644 --- a/ApplicationCode/GrpcInterface/CMakeLists.cmake +++ b/ApplicationCode/GrpcInterface/CMakeLists.cmake @@ -5,20 +5,22 @@ set ( SOURCE_GROUP_HEADER_FILES ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcCallbacks.h ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcCallbacks.inl ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcServiceInterface.h - ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcGridInfoService.h - ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcProjectInfoService.h + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcCaseService.h + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcGridService.h + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcProjectService.h ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcCommandService.h - ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcResInfoService.h + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcAppInfoService.h ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcPropertiesService.h ) set ( SOURCE_GROUP_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcServer.cpp ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcServiceInterface.cpp - ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcGridInfoService.cpp - ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcProjectInfoService.cpp + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcCaseService.cpp + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcGridService.cpp + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcProjectService.cpp ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcCommandService.cpp - ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcResInfoService.cpp + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcAppInfoService.cpp ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcPropertiesService.cpp ) @@ -70,12 +72,12 @@ endif(PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) # Proto files set(PROTO_FILES "Empty" - "CaseInfo" - "GridInfo" - "ProjectInfo" + "Case" + "Project" "Commands" - "ResInfo" + "AppInfo" "Properties" + "Grid" ) set(GRPC_PYTHON_SOURCE_PATH "${CMAKE_CURRENT_LIST_DIR}/Python") @@ -138,24 +140,33 @@ foreach(proto_file ${PROTO_FILES}) endforeach(proto_file) -if (PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) +if (PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) list(APPEND GRPC_PYTHON_SOURCES ${GRPC_PYTHON_GENERATED_SOURCES} "generated/RiaVersionInfo.py" - "api/__init__.py" - "api/ResInsight.py" + "rips/__init__.py" + "rips/AppInfo.py" + "rips/Case.py" + "rips/Commands.py" + "rips/Grid.py" + "rips/Project.py" + "rips/Properties.py" + "rips/Instance.py" "examples/CommandExample.py" - "examples/GridInfoStreamingExample.py" + "examples/CaseInfoStreamingExample.py" "examples/PoroPermXSync.py" "examples/PoroPermXAsync.py" "examples/SoilPorvAsync.py" "examples/SoilPorvSync.py" - "examples/ResultValues.py" "examples/SelectedCases.py" "examples/AllCases.py" - "examples/SetActiveCellProperties.py" "examples/SetGridProperties.py" + "examples/GridInformation.py" "tests/test_sample.py" + "requirements.txt" + "setup.py.cmake" + "README.md" + "LICENSE" ) foreach(PYTHON_SCRIPT ${GRPC_PYTHON_SOURCES}) @@ -173,6 +184,9 @@ list ( APPEND GRPC_CPP_SOURCES ${SOURCE_GROUP_SOURCE_FILES}) CONFIGURE_FILE( ${CMAKE_SOURCE_DIR}/ApplicationCode/Adm/RiaVersionInfo.py.cmake ${GRPC_PYTHON_SOURCE_PATH}/generated/RiaVersionInfo.py ) +CONFIGURE_FILE( ${GRPC_PYTHON_SOURCE_PATH}/setup.py.cmake + ${GRPC_PYTHON_SOURCE_PATH}/setup.py +) source_group( "GrpcInterface" FILES ${SOURCE_GROUP_HEADER_FILES} ${SOURCE_GROUP_SOURCE_FILES} ${CMAKE_CURRENT_LIST_DIR}/CMakeLists.cmake ) source_group( "GrpcInterface\\GrpcProtos" FILES ${GRPC_PROTO_FILES_FULL_PATH} ) \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/GrpcProtos/ResInfo.proto b/ApplicationCode/GrpcInterface/GrpcProtos/AppInfo.proto similarity index 91% rename from ApplicationCode/GrpcInterface/GrpcProtos/ResInfo.proto rename to ApplicationCode/GrpcInterface/GrpcProtos/AppInfo.proto index f6d711155a..fd5e18e156 100644 --- a/ApplicationCode/GrpcInterface/GrpcProtos/ResInfo.proto +++ b/ApplicationCode/GrpcInterface/GrpcProtos/AppInfo.proto @@ -4,7 +4,7 @@ package rips; import "Empty.proto"; -service ResInfo { +service AppInfo { rpc GetVersion(Empty) returns (Version) {} } diff --git a/ApplicationCode/GrpcInterface/GrpcProtos/GridInfo.proto b/ApplicationCode/GrpcInterface/GrpcProtos/Case.proto similarity index 58% rename from ApplicationCode/GrpcInterface/GrpcProtos/GridInfo.proto rename to ApplicationCode/GrpcInterface/GrpcProtos/Case.proto index add8d75fd1..c4bcb2aace 100644 --- a/ApplicationCode/GrpcInterface/GrpcProtos/GridInfo.proto +++ b/ApplicationCode/GrpcInterface/GrpcProtos/Case.proto @@ -1,19 +1,44 @@ syntax = "proto3"; -import "CaseInfo.proto"; - package rips; -service GridInfo +service Case { - // This function returns a two dimensional matrix: One row for each grid, starting with the main grid. - rpc GetGridCount(Case) returns(GridCount) {} - rpc GetGridDimensions(Case) returns (GridDimensions) {} + rpc GetGridCount(CaseRequest) returns(GridCount) {} rpc GetCellCount(CellInfoRequest) returns (CellCount) {} rpc GetCellInfoForActiveCells(CellInfoRequest) returns (stream CellInfoArray) {} - rpc GetAllCoarseningInfoArray(Case) returns (CoarseningInfoArray) {} - rpc GetTimeSteps(Case) returns (TimeStepDates) {} - rpc GetTimeStepDaysSinceStart(Case) returns (DoubleDates) {} + rpc GetCoarseningInfoArray(CaseRequest) returns (CoarseningInfoArray) {} + rpc GetTimeSteps(CaseRequest) returns (TimeStepDates) {} + rpc GetTimeStepDaysSinceStart(CaseRequest) returns (DoubleDates) {} + rpc GetCaseInfo(CaseRequest) returns (CaseInfo) {} +} + +message CaseRequest { + int32 id = 1; +} + +message CaseInfo +{ + int32 id = 1; + int32 group_id = 2; + string name = 3; + string type = 4; +} + +message CaseInfoArray +{ + repeated CaseInfo data = 1; +} + +message CaseGroup +{ + int32 id = 1; + string name = 2; +} + +message CaseGroups +{ + repeated CaseGroup case_groups = 1; } message GridCount @@ -21,11 +46,6 @@ message GridCount int32 count = 1; } -message GridDimensions -{ - repeated Vec3i dimensions = 1; -} - message Vec3i { int32 i = 1; int32 j = 2; @@ -46,7 +66,7 @@ enum PorosityModelType message CellInfoRequest { - int32 case_id = 1; + CaseRequest case_request = 1; PorosityModelType porosity_model = 2; } @@ -77,7 +97,7 @@ message CoarseningInfo message TimeStepDates { - repeated TimeStepDate date = 1; + repeated TimeStepDate dates = 1; } message TimeStepDate @@ -92,5 +112,5 @@ message TimeStepDate message DoubleDates { - repeated double date_decimal = 1; -} \ No newline at end of file + repeated double date_decimals = 1; +} diff --git a/ApplicationCode/GrpcInterface/GrpcProtos/CaseInfo.proto b/ApplicationCode/GrpcInterface/GrpcProtos/CaseInfo.proto deleted file mode 100644 index e53946ef63..0000000000 --- a/ApplicationCode/GrpcInterface/GrpcProtos/CaseInfo.proto +++ /dev/null @@ -1,31 +0,0 @@ -syntax = "proto3"; - -package rips; - -message Case { - int32 id = 1; -} - -message CaseInfo -{ - int32 id = 1; - int32 group_id = 2; - string name = 3; - string type = 4; -} - -message CaseInfos -{ - repeated CaseInfo case_info = 1; -} - -message CaseGroup -{ - int32 id = 1; - string name = 2; -} - -message CaseGroups -{ - repeated CaseGroup case_group = 1; -} \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto b/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto index 1465550aa2..706f25f39c 100644 --- a/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto +++ b/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto @@ -1,6 +1,6 @@ syntax = "proto3"; -import "CaseInfo.proto"; +import "Case.proto"; import "Empty.proto"; package rips; @@ -272,8 +272,8 @@ message CommandReply { oneof result { - Empty emptyResult = 1; - Case loadCaseResult = 2; + Empty emptyResult = 1; + CaseRequest loadCaseResult = 2; } } diff --git a/ApplicationCode/GrpcInterface/GrpcProtos/Grid.proto b/ApplicationCode/GrpcInterface/GrpcProtos/Grid.proto new file mode 100644 index 0000000000..36409e5bc2 --- /dev/null +++ b/ApplicationCode/GrpcInterface/GrpcProtos/Grid.proto @@ -0,0 +1,34 @@ +syntax = "proto3"; + +package rips; + +import "Case.proto"; + +service Grid +{ + rpc GetCellCenters(GridRequest) returns(CellCenters) {} + rpc GetDimensions(GridRequest) returns (GridDimensions) {} +} + +message GridRequest +{ + CaseRequest case_request = 1; + int32 grid_index = 2; +} + +message Vec3d +{ + double x = 1; + double y = 2; + double z = 3; +} + +message CellCenters +{ + repeated Vec3d centers = 1; +} + +message GridDimensions +{ + Vec3i dimensions = 1; +} diff --git a/ApplicationCode/GrpcInterface/GrpcProtos/Project.proto b/ApplicationCode/GrpcInterface/GrpcProtos/Project.proto new file mode 100644 index 0000000000..1c3c1c4f48 --- /dev/null +++ b/ApplicationCode/GrpcInterface/GrpcProtos/Project.proto @@ -0,0 +1,14 @@ +syntax = "proto3"; + +import "Case.proto"; +import "Empty.proto"; + +package rips; + +service Project { + rpc GetCurrentCase(Empty) returns (CaseRequest) {} + rpc GetSelectedCases(Empty) returns (CaseInfoArray) {} + rpc GetAllCaseGroups(Empty) returns (CaseGroups) {} + rpc GetAllCases(Empty) returns (CaseInfoArray) {} + rpc GetCasesInGroup(CaseGroup) returns (CaseInfoArray) {} +} diff --git a/ApplicationCode/GrpcInterface/GrpcProtos/ProjectInfo.proto b/ApplicationCode/GrpcInterface/GrpcProtos/ProjectInfo.proto deleted file mode 100644 index 33c7a5f765..0000000000 --- a/ApplicationCode/GrpcInterface/GrpcProtos/ProjectInfo.proto +++ /dev/null @@ -1,16 +0,0 @@ -syntax = "proto3"; - -import "CaseInfo.proto"; -import "Empty.proto"; - -package rips; - -service ProjectInfo { - rpc CurrentCase(Empty) returns (Case) {} - rpc CurrentCaseInfo(Empty) returns (CaseInfo) {} - rpc CaseInfoFromCase(Case) returns (CaseInfo) {} - rpc SelectedCases(Empty) returns (CaseInfos) {} - rpc AllCaseGroups(Empty) returns (CaseGroups) {} - rpc AllCases(Empty) returns (CaseInfos) {} - rpc CasesInGroup(CaseGroup) returns (CaseInfos) {} -} diff --git a/ApplicationCode/GrpcInterface/GrpcProtos/Properties.proto b/ApplicationCode/GrpcInterface/GrpcProtos/Properties.proto index ac91299841..3484e32f83 100644 --- a/ApplicationCode/GrpcInterface/GrpcProtos/Properties.proto +++ b/ApplicationCode/GrpcInterface/GrpcProtos/Properties.proto @@ -1,18 +1,17 @@ syntax = "proto3"; import "Empty.proto"; -import "CaseInfo.proto"; -import "GridInfo.proto"; +import "Case.proto"; package rips; service Properties { - rpc GetAvailableProperties(PropertiesRequest) returns (AvailableProperties) {} - rpc GetActiveCellResults(ResultRequest) returns (stream ResultArray) {} - rpc GetGridResults(ResultRequest) returns (stream ResultArray) {} - rpc SetActiveCellResults(stream ResultRequestChunk) returns (Empty) {} - rpc SetGridResults(stream ResultRequestChunk) returns (Empty) {} + rpc GetAvailableProperties(AvailablePropertiesRequest) returns (AvailableProperties) {} + rpc GetActiveCellProperty(PropertyRequest) returns (stream PropertyChunk) {} + rpc GetGridProperty(PropertyRequest) returns (stream PropertyChunk) {} + rpc SetActiveCellProperty(stream PropertyInputChunk) returns (Empty) {} + rpc SetGridProperty(stream PropertyInputChunk) returns (Empty) {} } enum PropertyType @@ -29,9 +28,9 @@ enum PropertyType UNDEFINED = 999; } -message PropertiesRequest +message AvailablePropertiesRequest { - Case request_case = 1; + CaseRequest case_request = 1; PropertyType property_type = 2; PorosityModelType porosity_model = 3; } @@ -41,9 +40,9 @@ message AvailableProperties repeated string property_names = 1; } -message ResultRequest +message PropertyRequest { - Case request_case = 1; + CaseRequest case_request = 1; PropertyType property_type = 2; string property_name = 3; int32 time_step = 4; @@ -56,14 +55,17 @@ message TimeStep int32 index = 1; } -message ResultRequestChunk +message PropertyInputChunk { - // Params needs to be sent in the first message - ResultRequest params = 1; - ResultArray values = 2; + oneof ChunkType + { + // Params needs to be sent in the first message + PropertyRequest params = 1; + PropertyChunk values = 2; + } } -message ResultArray +message PropertyChunk { repeated double values = 1; } diff --git a/ApplicationCode/GrpcInterface/Python/.gitignore b/ApplicationCode/GrpcInterface/Python/.gitignore index 71b76e8465..b95f862edb 100644 --- a/ApplicationCode/GrpcInterface/Python/.gitignore +++ b/ApplicationCode/GrpcInterface/Python/.gitignore @@ -1,3 +1,7 @@ __pycache__ .pytest_cache -generated \ No newline at end of file +generated +dist +build +rips.egg-info +setup.py diff --git a/ApplicationCode/GrpcInterface/Python/LICENSE b/ApplicationCode/GrpcInterface/Python/LICENSE new file mode 100644 index 0000000000..a9ffa5a614 --- /dev/null +++ b/ApplicationCode/GrpcInterface/Python/LICENSE @@ -0,0 +1,14 @@ +Copyright (C) 2019- Equinor ASA + +ResInsight is free software: you can redistribute it andor 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. + diff --git a/ApplicationCode/GrpcInterface/Python/README.md b/ApplicationCode/GrpcInterface/Python/README.md new file mode 100644 index 0000000000..66a09c5118 --- /dev/null +++ b/ApplicationCode/GrpcInterface/Python/README.md @@ -0,0 +1,5 @@ +# ResInsight Processing Server - rips + +A Python interface for the ResInsight visualization and post-processing suite for Reservoir Simulations + +[Learn More](https://www.resinsight.org) diff --git a/ApplicationCode/GrpcInterface/Python/api/ResInsight.py b/ApplicationCode/GrpcInterface/Python/api/ResInsight.py deleted file mode 100644 index dc937a9233..0000000000 --- a/ApplicationCode/GrpcInterface/Python/api/ResInsight.py +++ /dev/null @@ -1,302 +0,0 @@ -from __future__ import print_function - -import grpc -import os -import sys -import socket -import logging - - -sys.path.insert(1, os.path.join(sys.path[0], '../generated')) - -from Empty_pb2 import Empty -import CaseInfo_pb2 -import CaseInfo_pb2_grpc -import Commands_pb2 as Cmd -import Commands_pb2_grpc as CmdRpc -import GridInfo_pb2 -import GridInfo_pb2_grpc -import ProjectInfo_pb2 -import ProjectInfo_pb2_grpc -import ResInfo_pb2 -import ResInfo_pb2_grpc -import Properties_pb2 -import Properties_pb2_grpc -import RiaVersionInfo - -class ResInfo: - def __init__(self, channel): - self.resInfo = ResInfo_pb2_grpc.ResInfoStub(channel) - def versionMessage(self): - return self.resInfo.GetVersion(Empty()) - def majorVersion(self): - return self.versionMessage().major_version - def minorVersion(self): - return self.versionMessage().minor_version - def patchVersion(self): - return self.versionMessage().patch_version - def versionString(self): - return str(self.majorVersion()) + "." + str(self.minorVersion()) + "." + str(self.patchVersion()) - -class CommandExecutor: - def __init__(self, channel): - self.commands = CmdRpc.CommandsStub(channel) - - def execute(self, commandParams): - try: - return self.commands.Execute(commandParams) - except grpc.RpcError as e: - if e.code() == grpc.StatusCode.NOT_FOUND: - print("Command not found") - else: - print("Other error") - - def setTimeStep(self, caseId, timeStep): - return self.execute(Cmd.CommandParams(setTimeStep=Cmd.SetTimeStepParams(caseId=caseId, timeStep=timeStep))) - - def setMainWindowSize(self, width, height): - return self.execute(Cmd.CommandParams(setMainWindowSize=Cmd.SetMainWindowSizeParams(width=width, height=height))) - - def openProject(self, path): - return self.execute(Cmd.CommandParams(openProject=Cmd.FilePathRequest(path=path))) - - def loadCase(self, path): - commandReply = self.execute(Cmd.CommandParams(loadCase=Cmd.FilePathRequest(path=path))) - assert commandReply.HasField("loadCaseResult") - return commandReply.loadCaseResult.id - - def closeProject(self): - return self.execute(Cmd.CommandParams(closeProject=Empty())) - - def exportWellPaths(self, wellPaths=[], mdStepSize=5.0): - if isinstance(wellPaths, str): - wellPathArray = [str] - elif isinstance(wellPaths, list): - wellPathArray = wellPaths - return self.execute(Cmd.CommandParams(exportWellPaths=Cmd.ExportWellPathRequest(wellPathNames=wellPathArray, mdStepSize=mdStepSize))) - -class GridInfo: - def __init__(self, channel): - self.gridInfo = GridInfo_pb2_grpc.GridInfoStub(channel) - - def gridCount(self, caseId=0): - return self.gridInfo.GetGridCount(CaseInfo_pb2.Case(id=caseId)).count - - def gridDimensions(self, caseId=0): - return self.gridInfo.GetGridDimensions(CaseInfo_pb2.Case(id=caseId)).dimensions - - def cellCount(self, caseId=0, porosityModel='MATRIX_MODEL'): - porosityModelEnum = GridInfo_pb2.PorosityModelType.Value(porosityModel) - request = GridInfo_pb2.CellInfoRequest(case_id=caseId, - porosity_model=porosityModel) - return self.gridInfo.GetCellCount(request) - - def cellInfoForActiveCells(self, caseId=0, porosityModel='MATRIX_MODEL'): - porosityModelEnum = GridInfo_pb2.PorosityModelType.Value(porosityModel) - request = GridInfo_pb2.CellInfoRequest(case_id=caseId, - porosity_model=porosityModel) - return self.gridInfo.GetCellInfoForActiveCells(request) - - def timeSteps(self, caseId=0): - return self.gridInfo.GetTimeSteps(CaseInfo_pb2.Case(id=caseId)) - -class ProjectInfo: - def __init__(self, channel): - self.projectInfo = ProjectInfo_pb2_grpc.ProjectInfoStub(channel) - def selectedCases(self): - selected = self.projectInfo.SelectedCases(Empty()) - if selected is not None: - return selected.case_info - else: - return None - def allCases(self): - cases = self.projectInfo.AllCases(Empty()) - if cases is not None: - return cases.case_info - else: - return None - -class Properties: - def __init__(self, channel): - self.properties = Properties_pb2_grpc.PropertiesStub(channel) - - def generateResultRequestArrayIterator(self, values_iterator, parameters): - chunk = Properties_pb2.ResultRequestChunk() - chunk.params.CopyFrom(parameters) - yield chunk - - for values in values_iterator: - valmsg = Properties_pb2.ResultArray(values = values) - chunk.values.CopyFrom(valmsg) - yield chunk - - def generateResultRequestChunks(self, array, parameters): - # Each double is 8 bytes. A good chunk size is 64KiB = 65536B - # Meaning ideal number of doubles would be 8192. - # However we need overhead space, so if we choose 8160 in chunk size - # We have 256B left for overhead which should be plenty - chunkSize = 8000 - index = -1 - while index < len(array): - chunk = Properties_pb2.ResultRequestChunk() - if index is -1: - chunk.params.CopyFrom(parameters) - index += 1; - else: - actualChunkSize = min(len(array) - index + 1, chunkSize) - chunk.values.CopyFrom(Properties_pb2.ResultArray(values = array[index:index+actualChunkSize])) - index += actualChunkSize - - yield chunk - # Final empty message to signal completion - chunk = Properties_pb2.ResultRequestChunk() - yield chunk - - def availableProperties(self, caseId, propertyType, porosityModel = 'MATRIX_MODEL'): - propertyTypeEnum = Properties_pb2.PropertyType.Value(propertyType) - porosityModelEnum = GridInfo_pb2.PorosityModelType.Value(porosityModel) - request = Properties_pb2.PropertiesRequest (request_case = CaseInfo_pb2.Case(id=caseId), - property_type = propertyTypeEnum, - porosity_model = porosityModelEnum) - return self.properties.GetAvailableProperties(request).property_names - def activeCellResults(self, caseId, propertyType, propertyName, timeStep, porosityModel = 'MATRIX_MODEL'): - propertyTypeEnum = Properties_pb2.PropertyType.Value(propertyType) - porosityModelEnum = GridInfo_pb2.PorosityModelType.Value(porosityModel) - request = Properties_pb2.ResultRequest(request_case = CaseInfo_pb2.Case(id=caseId), - property_type = propertyTypeEnum, - property_name = propertyName, - time_step = timeStep, - porosity_model = porosityModelEnum) - for chunk in self.properties.GetActiveCellResults(request): - yield chunk - - def gridCellResults(self, caseId, propertyType, propertyName, timeStep, gridIndex = 0, porosityModel = 'MATRIX_MODEL'): - propertyTypeEnum = Properties_pb2.PropertyType.Value(propertyType) - porosityModelEnum = GridInfo_pb2.PorosityModelType.Value(porosityModel) - request = Properties_pb2.ResultRequest(request_case = CaseInfo_pb2.Case(id=caseId), - property_type = propertyTypeEnum, - property_name = propertyName, - time_step = timeStep, - grid_index = gridIndex, - porosity_model = porosityModelEnum) - return self.properties.GetGridResults(request) - - def setActiveCellResultsAsync(self, values_iterator, caseId, propertyType, propertyName, timeStep, gridIndex = 0, porosityModel = 'MATRIX_MODEL'): - propertyTypeEnum = Properties_pb2.PropertyType.Value(propertyType) - porosityModelEnum = GridInfo_pb2.PorosityModelType.Value(porosityModel) - request = Properties_pb2.ResultRequest(request_case = CaseInfo_pb2.Case(id=caseId), - property_type = propertyTypeEnum, - property_name = propertyName, - time_step = timeStep, - grid_index = gridIndex, - porosity_model = porosityModelEnum) - try: - reply_iterator = self.generateResultRequestArrayIterator(values_iterator, request) - self.properties.SetActiveCellResults(reply_iterator) - except grpc.RpcError as e: - if e.code() == grpc.StatusCode.NOT_FOUND: - print("Command not found") - else: - print("Other error", e) - - def setActiveCellResults(self, values, caseId, propertyType, propertyName, timeStep, gridIndex = 0, porosityModel = 'MATRIX_MODEL'): - propertyTypeEnum = Properties_pb2.PropertyType.Value(propertyType) - porosityModelEnum = GridInfo_pb2.PorosityModelType.Value(porosityModel) - request = Properties_pb2.ResultRequest(request_case = CaseInfo_pb2.Case(id=caseId), - property_type = propertyTypeEnum, - property_name = propertyName, - time_step = timeStep, - grid_index = gridIndex, - porosity_model = porosityModelEnum) - try: - request_iterator = self.generateResultRequestChunks(values, request) - self.properties.SetActiveCellResults(request_iterator) - except grpc.RpcError as e: - if e.code() == grpc.StatusCode.NOT_FOUND: - print("Command not found") - else: - print("Other error", e) - def setGridResults(self, values, caseId, propertyType, propertyName, timeStep, gridIndex = 0, porosityModel = 'MATRIX_MODEL'): - propertyTypeEnum = Properties_pb2.PropertyType.Value(propertyType) - porosityModelEnum = GridInfo_pb2.PorosityModelType.Value(porosityModel) - request = Properties_pb2.ResultRequest(request_case = CaseInfo_pb2.Case(id=caseId), - property_type = propertyTypeEnum, - property_name = propertyName, - time_step = timeStep, - grid_index = gridIndex, - porosity_model = porosityModelEnum) - try: - request_iterator = self.generateResultRequestArrays(values, request) - self.properties.SetGridResults(request_iterator) - except grpc.RpcError as e: - if e.code() == grpc.StatusCode.NOT_FOUND: - print("Command not found") - else: - print("Other error", e) - -class Instance: - @staticmethod - def is_port_in_use(port): - with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: - s.settimeout(0.2) - return s.connect_ex(('localhost', port)) == 0 - - @staticmethod - def launch(): - port = 50051 - portEnv = os.environ.get('RESINSIGHT_GRPC_PORT') - if portEnv: - port = int(portEnv) - - resInsightExecutable = os.environ.get('RESINSIGHT_EXECUTABLE') - if resInsightExecutable is None: - print('Error: Could not launch any ResInsight instances because RESINSIGHT_EXECUTABLE is not set') - return None - - while Instance.is_port_in_use(port): - port += 1 - - print('Port ' + str(port)) - print('Trying to launch', resInsightExecutable) - pid = os.spawnl(os.P_NOWAIT, resInsightExecutable, " --grpcserver " + str(port)) - print(pid) - return Instance(port) - - @staticmethod - def find(startPort = 50051, endPort = 50071): - portEnv = os.environ.get('RESINSIGHT_GRPC_PORT') - if portEnv: - startPort = int(portEnv) - endPort = startPort + 20 - - for tryPort in range(startPort, endPort): - if Instance.is_port_in_use(tryPort): - return Instance(tryPort) - - print('Error: Could not find any ResInsight instances responding between ports ' + str(startPort) + ' and ' + str(endPort)) - return None - - def __init__(self, port = 50051): - logging.basicConfig() - location = "localhost:" + str(port) - self.channel = grpc.insecure_channel(location) - - # Main version check package - self.resInfo = ResInfo(self.channel) - try: - majorVersionOk = self.resInfo.majorVersion() == int(RiaVersionInfo.RESINSIGHT_MAJOR_VERSION) - minorVersionOk = self.resInfo.minorVersion() == int(RiaVersionInfo.RESINSIGHT_MINOR_VERSION) - if not (majorVersionOk and minorVersionOk): - raise Exception('Version of ResInsight does not match version of Python API') - except grpc.RpcError as e: - if e.code() == grpc.StatusCode.UNAVAILABLE: - print('Info: Could not find any instances at port ' + str(port)) - except Exception as e: - print('Error:', e) - - # Service packages - self.commands = CommandExecutor(self.channel) - self.gridInfo = GridInfo(self.channel) - self.projectInfo = ProjectInfo(self.channel) - self.properties = Properties(self.channel) - \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/Python/api/__init__.py b/ApplicationCode/GrpcInterface/Python/api/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ApplicationCode/GrpcInterface/Python/examples/AllCases.py b/ApplicationCode/GrpcInterface/Python/examples/AllCases.py index 3ee8615c8b..f4681de047 100644 --- a/ApplicationCode/GrpcInterface/Python/examples/AllCases.py +++ b/ApplicationCode/GrpcInterface/Python/examples/AllCases.py @@ -1,13 +1,11 @@ import sys import os -sys.path.insert(1, os.path.join(sys.path[0], '../api')) +import rips -import ResInsight - -resInsight = ResInsight.Instance.find() +resInsight = rips.Instance.find() if resInsight is not None: - caseInfos = resInsight.projectInfo.allCases() - - print ("Got " + str(len(caseInfos)) + " cases: ") - for caseInfo in caseInfos: - print(caseInfo.name) + cases = resInsight.project.cases() + + print ("Got " + str(len(cases)) + " cases: ") + for case in cases: + print(case.name) diff --git a/ApplicationCode/GrpcInterface/Python/examples/GridInfoStreamingExample.py b/ApplicationCode/GrpcInterface/Python/examples/CaseInfoStreamingExample.py similarity index 84% rename from ApplicationCode/GrpcInterface/Python/examples/GridInfoStreamingExample.py rename to ApplicationCode/GrpcInterface/Python/examples/CaseInfoStreamingExample.py index 9df2a9fa70..a006128baa 100644 --- a/ApplicationCode/GrpcInterface/Python/examples/GridInfoStreamingExample.py +++ b/ApplicationCode/GrpcInterface/Python/examples/CaseInfoStreamingExample.py @@ -7,10 +7,12 @@ resInsight = ResInsight.Instance.find() #gridCount = resInsight.gridInfo.getGridCount(caseId=0) #gridDimensions = resInsight.gridInfo.getAllGridDimensions(caseId=0) -cellCounts = resInsight.gridInfo.cellCount(caseId=0) +case = resInsight.project.case(id = 0) + +cellCounts = case.cellCount() print("Number of active cells: " + str(cellCounts.active_cell_count)) -activeCellInfoChunks = resInsight.gridInfo.cellInfoForActiveCells(caseId=0) +activeCellInfoChunks = case.cellInfoForActiveCells() #print("Number of grids: " + str(gridCount)) #print(gridDimensions) diff --git a/ApplicationCode/GrpcInterface/Python/examples/GridInformation.py b/ApplicationCode/GrpcInterface/Python/examples/GridInformation.py new file mode 100644 index 0000000000..eff73eb476 --- /dev/null +++ b/ApplicationCode/GrpcInterface/Python/examples/GridInformation.py @@ -0,0 +1,18 @@ +import sys +import os +sys.path.insert(1, os.path.join(sys.path[0], '../api')) + +import ResInsight + +resInsight = ResInsight.Instance.find() +cases = resInsight.project.cases() +print("Number of cases found: ", len(cases)) +for case in cases: + print(case.name) + grids = case.grids() + print("Number of grids: ", len(grids)) + for grid in grids: + print("Grid dimensions: ", grid.dimensions()) + + + diff --git a/ApplicationCode/GrpcInterface/Python/examples/PoroPermXAsync.py b/ApplicationCode/GrpcInterface/Python/examples/PoroPermXAsync.py index 859fb3845c..98c86c5948 100644 --- a/ApplicationCode/GrpcInterface/Python/examples/PoroPermXAsync.py +++ b/ApplicationCode/GrpcInterface/Python/examples/PoroPermXAsync.py @@ -11,12 +11,12 @@ def createResult(poroChunks, permxChunks): yield resultChunk - resInsight = ResInsight.Instance.find() +case = resInsight.project.case(id=0) -poroChunks = resInsight.properties.activeCellResults(0, 'STATIC_NATIVE', 'PORO', 0) -permxChunks = resInsight.properties.activeCellResults(0, 'STATIC_NATIVE', 'PERMX', 0) +poroChunks = case.properties.activeCellProperty('STATIC_NATIVE', 'PORO', 0) +permxChunks = case.properties.activeCellProperty('STATIC_NATIVE', 'PERMX', 0) -resInsight.properties.setActiveCellResultsAsync(createResult(poroChunks, permxChunks), 0, 'GENERATED', 'POROPERMXAS', 0) +case.properties.setActiveCellPropertyAsync(createResult(poroChunks, permxChunks), 'GENERATED', 'POROPERMXAS', 0) print("Transferred all results back") \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/Python/examples/PoroPermXSync.py b/ApplicationCode/GrpcInterface/Python/examples/PoroPermXSync.py index d1ca8d111c..0be8e0017e 100644 --- a/ApplicationCode/GrpcInterface/Python/examples/PoroPermXSync.py +++ b/ApplicationCode/GrpcInterface/Python/examples/PoroPermXSync.py @@ -4,26 +4,25 @@ sys.path.insert(1, os.path.join(sys.path[0], '../api')) import ResInsight resInsight = ResInsight.Instance.find() -#gridCount = resInsight.gridInfo.getGridCount(caseId=0) -#gridDimensions = resInsight.gridInfo.getAllGridDimensions(caseId=0) -for i in range(0, 40): - poroChunks = resInsight.properties.activeCellResults(0, 'STATIC_NATIVE', 'PORO', 0) - poroResults = [] - for poroChunk in poroChunks: - for poro in poroChunk.values: - poroResults.append(poro) +case = resInsight.project.case(id=0) - permxChunks = resInsight.properties.activeCellResults(0, 'STATIC_NATIVE', 'PERMX', 0) - permxResults = [] - for permxChunk in permxChunks: - for permx in permxChunk.values: - permxResults.append(permx) +poroChunks = case.properties.activeCellProperty('STATIC_NATIVE', 'PORO', 0) +poroResults = [] +for poroChunk in poroChunks: + for poro in poroChunk.values: + poroResults.append(poro) - results = [] - for (poro, permx) in zip(poroResults, permxResults): - results.append(poro * permx) +permxChunks = case.properties.activeCellProperty('STATIC_NATIVE', 'PERMX', 0) +permxResults = [] +for permxChunk in permxChunks: + for permx in permxChunk.values: + permxResults.append(permx) - resInsight.properties.setActiveCellResults(results, 0, 'GENERATED', 'POROPERMXSY', 0) +results = [] +for (poro, permx) in zip(poroResults, permxResults): + results.append(poro * permx) + +case.properties.setActiveCellProperty(results, 'GENERATED', 'POROPERMXSY', 0) print("Transferred all results back") \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/Python/examples/ResultValues.py b/ApplicationCode/GrpcInterface/Python/examples/ResultValues.py deleted file mode 100644 index c334d8c52e..0000000000 --- a/ApplicationCode/GrpcInterface/Python/examples/ResultValues.py +++ /dev/null @@ -1,28 +0,0 @@ -import sys -import os -sys.path.insert(1, os.path.join(sys.path[0], '../api')) -import ResInsight - -resInsight = ResInsight.Instance.find() -#gridCount = resInsight.gridInfo.getGridCount(caseId=0) -#gridDimensions = resInsight.gridInfo.getAllGridDimensions(caseId=0) - -poroChunks = resInsight.properties.activeCellResults(0, 'STATIC_NATIVE', 'PORO', 0) -poroResults = [] -for poroChunk in poroChunks: - for poro in poroChunk.values: - poroResults.append(poro) - -permxChunks = resInsight.properties.activeCellResults(0, 'STATIC_NATIVE', 'PERMX', 0) -permxResults = [] -for permxChunk in permxChunks: - for permx in permxChunk.values: - permxResults.append(permx) - -results = [] -for (poro, permx) in zip(poroResults, permxResults): - results.append(poro * permx) - -print("Transferred " + str(len(results)) + " cell results") -print("30th active cell: ") -print(results[29]) diff --git a/ApplicationCode/GrpcInterface/Python/examples/SelectedCases.py b/ApplicationCode/GrpcInterface/Python/examples/SelectedCases.py index 4fc50426ec..830b9f658d 100644 --- a/ApplicationCode/GrpcInterface/Python/examples/SelectedCases.py +++ b/ApplicationCode/GrpcInterface/Python/examples/SelectedCases.py @@ -6,9 +6,12 @@ import ResInsight resInsight = ResInsight.Instance.find() if resInsight is not None: - caseInfos = resInsight.projectInfo.selectedCases() + cases = resInsight.project.selectedCases() + + print ("Got " + str(len(cases)) + " cases: ") + for case in cases: + print(case.name) + for property in case.properties.available('DYNAMIC_NATIVE'): + print(property) + - print ("Got " + str(len(caseInfos)) + " cases: ") - for caseInfo in caseInfos: - print(caseInfo.name) - diff --git a/ApplicationCode/GrpcInterface/Python/examples/SetActiveCellProperties.py b/ApplicationCode/GrpcInterface/Python/examples/SetActiveCellProperties.py deleted file mode 100644 index e9b45668aa..0000000000 --- a/ApplicationCode/GrpcInterface/Python/examples/SetActiveCellProperties.py +++ /dev/null @@ -1,19 +0,0 @@ -import sys -import os -sys.path.insert(1, os.path.join(sys.path[0], '../api')) -import ResInsight - -resInsight = ResInsight.Instance.find() - -activeCellCount = resInsight.gridInfo.cellCount(caseId=0).active_cell_count - -values = [] -for i in range(0, activeCellCount): - values.append(i % 2 * 0.5); - - -timeSteps = resInsight.gridInfo.timeSteps(caseId=0) -for i in range(0, len(timeSteps.date)): - print("Applying values to all time step " + str(i)) - resInsight.properties.setActiveCellResults(values, 0, 'DYNAMIC_NATIVE', 'SOIL', i) - diff --git a/ApplicationCode/GrpcInterface/Python/examples/SetGridProperties.py b/ApplicationCode/GrpcInterface/Python/examples/SetGridProperties.py index bf15573601..70e88e2c82 100644 --- a/ApplicationCode/GrpcInterface/Python/examples/SetGridProperties.py +++ b/ApplicationCode/GrpcInterface/Python/examples/SetGridProperties.py @@ -5,12 +5,13 @@ import ResInsight resInsight = ResInsight.Instance.find() -totalCellCount = resInsight.gridInfo.cellCount(caseId=0).reservoir_cell_count +case = resInsight.project.case(id=0) +totalCellCount = case.cellCount().reservoir_cell_count values = [] for i in range(0, totalCellCount): values.append(i % 2 * 0.75); print("Applying values to full grid") -resInsight.properties.setGridResults(values, 0, 'DYNAMIC_NATIVE', 'SOIL', 0) +case.properties.setGridProperty(values, 'DYNAMIC_NATIVE', 'SOIL', 0) diff --git a/ApplicationCode/GrpcInterface/Python/examples/SoilPorvAsync.py b/ApplicationCode/GrpcInterface/Python/examples/SoilPorvAsync.py index bc31125d26..622b45ebd2 100644 --- a/ApplicationCode/GrpcInterface/Python/examples/SoilPorvAsync.py +++ b/ApplicationCode/GrpcInterface/Python/examples/SoilPorvAsync.py @@ -14,18 +14,18 @@ def createResult(soilChunks, porvChunks): -resInsight = ResInsight.Instance.find() +resInsight = ResInsight.Instance.find() +case = resInsight.project.case(id=0) +timeStepInfo = case.timeSteps() -timeStepInfo = resInsight.gridInfo.timeSteps(0) - -porvChunks = resInsight.properties.activeCellResults(0, 'STATIC_NATIVE', 'PORV', 0) +porvChunks = case.properties.activeCellProperty('STATIC_NATIVE', 'PORV', 0) porvArray = [] for porvChunk in porvChunks: porvArray.append(porvChunk) -for i in range (0, len(timeStepInfo.date)): - soilChunks = resInsight.properties.activeCellResults(0, 'DYNAMIC_NATIVE', 'SOIL', i) +for i in range (0, len(timeStepInfo.dates)): + soilChunks = case.properties.activeCellProperty('DYNAMIC_NATIVE', 'SOIL', i) input_iterator = createResult(soilChunks, iter(porvArray)) - resInsight.properties.setActiveCellResultsAsync(input_iterator, 0, 'GENERATED', 'SOILPORVAsync', i) + case.properties.setActiveCellPropertyAsync(input_iterator, 'GENERATED', 'SOILPORVAsync', i) print("Transferred all results back") \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/Python/examples/SoilPorvSync.py b/ApplicationCode/GrpcInterface/Python/examples/SoilPorvSync.py index f17c7e838f..fe76c8aa92 100644 --- a/ApplicationCode/GrpcInterface/Python/examples/SoilPorvSync.py +++ b/ApplicationCode/GrpcInterface/Python/examples/SoilPorvSync.py @@ -3,20 +3,19 @@ import os sys.path.insert(1, os.path.join(sys.path[0], '../api')) import ResInsight -resInsight = ResInsight.Instance.find() -#gridCount = resInsight.gridInfo.getGridCount(caseId=0) -#gridDimensions = resInsight.gridInfo.getAllGridDimensions(caseId=0) +resInsight = ResInsight.Instance.find() +case = resInsight.case(id=0) -porvChunks = resInsight.properties.activeCellResults(0, 'STATIC_NATIVE', 'PORV', 0) +porvChunks = case.properties.activeCellProperty('STATIC_NATIVE', 'PORV', 0) porvResults = [] for porvChunk in porvChunks: for porv in porvChunk.values: porvResults.append(porv) -timeStepInfo = resInsight.gridInfo.timeSteps(0) +timeStepInfo = case.timeSteps() -for i in range (0, len(timeStepInfo.date)): - soilChunks = resInsight.properties.activeCellResults(0, 'DYNAMIC_NATIVE', 'SOIL', i) +for i in range (0, len(timeStepInfo.dates)): + soilChunks = case.properties.activeCellProperty('DYNAMIC_NATIVE', 'SOIL', i) soilResults = [] for soilChunk in soilChunks: for soil in soilChunk.values: @@ -25,5 +24,5 @@ for i in range (0, len(timeStepInfo.date)): for (soil, porv) in zip(soilResults, porvResults): results.append(soil * porv) - resInsight.properties.setActiveCellResults(results, 0, 'GENERATED', 'SOILPORVSync', i) + case.properties.setActiveCellProperty(results, 'GENERATED', 'SOILPORVSync', i) print("Transferred all results back") \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/Python/requirements.txt b/ApplicationCode/GrpcInterface/Python/requirements.txt new file mode 100644 index 0000000000..be09438dd5 --- /dev/null +++ b/ApplicationCode/GrpcInterface/Python/requirements.txt @@ -0,0 +1,3 @@ +grpcio +grpcio-tools +protobuf \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/Python/rips/AppInfo.py b/ApplicationCode/GrpcInterface/Python/rips/AppInfo.py new file mode 100644 index 0000000000..8ec1fdd80e --- /dev/null +++ b/ApplicationCode/GrpcInterface/Python/rips/AppInfo.py @@ -0,0 +1,25 @@ +import grpc +import os +import sys + +sys.path.insert(1, os.path.join(sys.path[0], '../generated')) + +from Empty_pb2 import Empty + +import AppInfo_pb2 +import AppInfo_pb2_grpc + +class AppInfo: + def __init__(self, channel): + self.appInfo = AppInfo_pb2_grpc.AppInfoStub(channel) + def versionMessage(self): + return self.appInfo.GetVersion(Empty()) + def majorVersion(self): + return self.versionMessage().major_version + def minorVersion(self): + return self.versionMessage().minor_version + def patchVersion(self): + return self.versionMessage().patch_version + def versionString(self): + return str(self.majorVersion()) + "." + str(self.minorVersion()) + "." + str(self.patchVersion()) + diff --git a/ApplicationCode/GrpcInterface/Python/rips/Case.py b/ApplicationCode/GrpcInterface/Python/rips/Case.py new file mode 100644 index 0000000000..8e8419d207 --- /dev/null +++ b/ApplicationCode/GrpcInterface/Python/rips/Case.py @@ -0,0 +1,56 @@ +import grpc +import os +import sys +from .Grid import Grid +from .Properties import Properties + +sys.path.insert(1, os.path.join(sys.path[0], '../generated')) + +import Case_pb2 +import Case_pb2_grpc + +class Case: + def __init__(self, channel, id): + self.channel = channel + self.stub = Case_pb2_grpc.CaseStub(channel) + self.id = id + info = self.stub.GetCaseInfo(Case_pb2.CaseRequest(id=self.id)) + self.name = info.name + self.groupId = info.group_id + self.type = info.type + self.properties = Properties(self) + self.request = Case_pb2.CaseRequest(id=self.id) + + def gridCount(self): + try: + return self.stub.GetGridCount(self.request).count + except grpc.RpcError as e: + if e.code() == grpc.StatusCode.NOT_FOUND: + return 0 + print("ERROR: ", e) + return 0 + + def grid(self, index): + return Grid(index, self) + + def grids(self): + gridList = [] + for i in range(0, self.gridCount()): + gridList.append(Grid(i, self)) + return gridList + + def cellCount(self, porosityModel='MATRIX_MODEL'): + porosityModelEnum = Case_pb2.PorosityModelType.Value(porosityModel) + request = Case_pb2.CellInfoRequest(request_case=self.request, + porosity_model=porosityModel) + return self.stub.GetCellCount(request) + + def cellInfoForActiveCells(self, porosityModel='MATRIX_MODEL'): + porosityModelEnum = Case_pb2.PorosityModelType.Value(porosityModel) + request = Case_pb2.CellInfoRequest(request_case=self.request, + porosity_model=porosityModel) + return self.stub.GetCellInfoForActiveCells(request) + + def timeSteps(self): + return self.stub.GetTimeSteps(self.request) + \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/Python/rips/Commands.py b/ApplicationCode/GrpcInterface/Python/rips/Commands.py new file mode 100644 index 0000000000..725d5c637b --- /dev/null +++ b/ApplicationCode/GrpcInterface/Python/rips/Commands.py @@ -0,0 +1,43 @@ +import grpc +import os +import sys + +import Commands_pb2 as Cmd +import Commands_pb2_grpc as CmdRpc + +class Commands: + def __init__(self, channel): + self.commands = CmdRpc.CommandsStub(channel) + + def execute(self, commandParams): + try: + return self.commands.Execute(commandParams) + except grpc.RpcError as e: + if e.code() == grpc.StatusCode.NOT_FOUND: + print("Command not found") + else: + print("Other error") + + def setTimeStep(self, caseId, timeStep): + return self.execute(Cmd.CommandParams(setTimeStep=Cmd.SetTimeStepParams(caseId=caseId, timeStep=timeStep))) + + def setMainWindowSize(self, width, height): + return self.execute(Cmd.CommandParams(setMainWindowSize=Cmd.SetMainWindowSizeParams(width=width, height=height))) + + def openProject(self, path): + return self.execute(Cmd.CommandParams(openProject=Cmd.FilePathRequest(path=path))) + + def loadCase(self, path): + commandReply = self.execute(Cmd.CommandParams(loadCase=Cmd.FilePathRequest(path=path))) + assert commandReply.HasField("loadCaseResult") + return commandReply.loadCaseResult.id + + def closeProject(self): + return self.execute(Cmd.CommandParams(closeProject=Empty())) + + def exportWellPaths(self, wellPaths=[], mdStepSize=5.0): + if isinstance(wellPaths, str): + wellPathArray = [str] + elif isinstance(wellPaths, list): + wellPathArray = wellPaths + return self.execute(Cmd.CommandParams(exportWellPaths=Cmd.ExportWellPathRequest(wellPathNames=wellPathArray, mdStepSize=mdStepSize))) diff --git a/ApplicationCode/GrpcInterface/Python/rips/Grid.py b/ApplicationCode/GrpcInterface/Python/rips/Grid.py new file mode 100644 index 0000000000..df6fe8c6ef --- /dev/null +++ b/ApplicationCode/GrpcInterface/Python/rips/Grid.py @@ -0,0 +1,18 @@ +import grpc +import os +import sys + +sys.path.insert(1, os.path.join(sys.path[0], '../generated')) + +import Grid_pb2 +import Grid_pb2_grpc + +class Grid: + def __init__(self, index, case): + self.case = case + self.index = index + self.stub = Grid_pb2_grpc.GridStub(self.case.channel) + + def dimensions(self): + return self.stub.GetDimensions(Grid_pb2.GridRequest(case_request = self.case.request, grid_index = self.index)).dimensions + diff --git a/ApplicationCode/GrpcInterface/Python/rips/Instance.py b/ApplicationCode/GrpcInterface/Python/rips/Instance.py new file mode 100644 index 0000000000..d10ea1fdf9 --- /dev/null +++ b/ApplicationCode/GrpcInterface/Python/rips/Instance.py @@ -0,0 +1,78 @@ +import grpc +import os +import sys +import socket +import logging + +sys.path.insert(1, os.path.join(sys.path[0], '../generated')) + +import RiaVersionInfo + +from .AppInfo import AppInfo +from .Commands import Commands +from .Project import Project + +class Instance: + @staticmethod + def is_port_in_use(port): + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: + s.settimeout(0.2) + return s.connect_ex(('localhost', port)) == 0 + + @staticmethod + def launch(): + port = 50051 + portEnv = os.environ.get('RESINSIGHT_GRPC_PORT') + if portEnv: + port = int(portEnv) + + resInsightExecutable = os.environ.get('RESINSIGHT_EXECUTABLE') + if resInsightExecutable is None: + print('Error: Could not launch any ResInsight instances because RESINSIGHT_EXECUTABLE is not set') + return None + + while Instance.is_port_in_use(port): + port += 1 + + print('Port ' + str(port)) + print('Trying to launch', resInsightExecutable) + pid = os.spawnl(os.P_NOWAIT, resInsightExecutable, " --grpcserver " + str(port)) + print(pid) + return Instance(port) + + @staticmethod + def find(startPort = 50051, endPort = 50071): + portEnv = os.environ.get('RESINSIGHT_GRPC_PORT') + if portEnv: + startPort = int(portEnv) + endPort = startPort + 20 + + for tryPort in range(startPort, endPort): + if Instance.is_port_in_use(tryPort): + return Instance(tryPort) + + print('Error: Could not find any ResInsight instances responding between ports ' + str(startPort) + ' and ' + str(endPort)) + return None + + def __init__(self, port = 50051): + logging.basicConfig() + location = "localhost:" + str(port) + self.channel = grpc.insecure_channel(location) + + # Main version check package + self.appInfo = AppInfo(self.channel) + try: + majorVersionOk = self.appInfo.majorVersion() == int(RiaVersionInfo.RESINSIGHT_MAJOR_VERSION) + minorVersionOk = self.appInfo.minorVersion() == int(RiaVersionInfo.RESINSIGHT_MINOR_VERSION) + if not (majorVersionOk and minorVersionOk): + raise Exception('Version of ResInsight does not match version of Python API') + except grpc.RpcError as e: + if e.code() == grpc.StatusCode.UNAVAILABLE: + print('Info: Could not find any instances at port ' + str(port)) + except Exception as e: + print('Error:', e) + + # Service packages + self.commands = Commands(self.channel) + self.project = Project(self.channel) + \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/Python/rips/Project.py b/ApplicationCode/GrpcInterface/Python/rips/Project.py new file mode 100644 index 0000000000..ac143b9186 --- /dev/null +++ b/ApplicationCode/GrpcInterface/Python/rips/Project.py @@ -0,0 +1,45 @@ +import grpc +import os +import sys + +from .Case import Case + +sys.path.insert(1, os.path.join(sys.path[0], '../generated')) + +from Empty_pb2 import Empty +import Project_pb2 +import Project_pb2_grpc + +class Project: + def __init__(self, channel): + self.channel = channel + self.project = Project_pb2_grpc.ProjectStub(channel) + + def selectedCases(self): + caseInfos = self.project.GetSelectedCases(Empty()) + cases = [] + for caseInfo in caseInfos.data: + cases.append(Case(self.channel, caseInfo.id)) + return cases + + def cases(self): + try: + caseInfos = self.project.GetAllCases(Empty()) + + cases = [] + for caseInfo in caseInfos.data: + cases.append(Case(self.channel, caseInfo.id)) + return cases + except grpc.RpcError as e: + if e.code() == grpc.StatusCode.NOT_FOUND: + return [] + else: + print("ERROR: ", e) + return [] + + def case(self, id): + try: + case = Case(self.channel, id) + return case + except grpc.RpcError as e: + return None diff --git a/ApplicationCode/GrpcInterface/Python/rips/Properties.py b/ApplicationCode/GrpcInterface/Python/rips/Properties.py new file mode 100644 index 0000000000..0bf881a88b --- /dev/null +++ b/ApplicationCode/GrpcInterface/Python/rips/Properties.py @@ -0,0 +1,130 @@ +import grpc +import os +import sys + +sys.path.insert(1, os.path.join(sys.path[0], '../generated')) + +import Properties_pb2 +import Properties_pb2_grpc +import Case_pb2 +import Case_pb2_grpc + +class Properties: + def __init__(self, case): + self.case = case + self.propertiesStub = Properties_pb2_grpc.PropertiesStub(self.case.channel) + + def generatePropertyInputIterator(self, values_iterator, parameters): + chunk = Properties_pb2.PropertyInputChunk() + chunk.params.CopyFrom(parameters) + yield chunk + + for values in values_iterator: + valmsg = Properties_pb2.PropertyChunk(values = values) + chunk.values.CopyFrom(valmsg) + yield chunk + + def generatePropertyInputChunks(self, array, parameters): + # Each double is 8 bytes. A good chunk size is 64KiB = 65536B + # Meaning ideal number of doubles would be 8192. + # However we need overhead space, so if we choose 8160 in chunk size + # We have 256B left for overhead which should be plenty + chunkSize = 8000 + index = -1 + while index < len(array): + chunk = Properties_pb2.PropertyInputChunk() + if index is -1: + chunk.params.CopyFrom(parameters) + index += 1; + else: + actualChunkSize = min(len(array) - index + 1, chunkSize) + chunk.values.CopyFrom(Properties_pb2.PropertyChunk(values = array[index:index+actualChunkSize])) + index += actualChunkSize + + yield chunk + # Final empty message to signal completion + chunk = Properties_pb2.PropertyInputChunk() + yield chunk + + def available(self, propertyType, porosityModel = 'MATRIX_MODEL'): + propertyTypeEnum = Properties_pb2.PropertyType.Value(propertyType) + porosityModelEnum = Case_pb2.PorosityModelType.Value(porosityModel) + request = Properties_pb2.AvailablePropertiesRequest (case_request = Case_pb2.CaseRequest(id=self.case.id), + property_type = propertyTypeEnum, + porosity_model = porosityModelEnum) + return self.propertiesStub.GetAvailableProperties(request).property_names + + def activeCellProperty(self, propertyType, propertyName, timeStep, porosityModel = 'MATRIX_MODEL'): + propertyTypeEnum = Properties_pb2.PropertyType.Value(propertyType) + porosityModelEnum = Case_pb2.PorosityModelType.Value(porosityModel) + request = Properties_pb2.PropertyRequest(case_request = Case_pb2.CaseRequest(id=self.case.id), + property_type = propertyTypeEnum, + property_name = propertyName, + time_step = timeStep, + porosity_model = porosityModelEnum) + for chunk in self.propertiesStub.GetActiveCellProperty(request): + yield chunk + + def gridProperty(self, propertyType, propertyName, timeStep, gridIndex = 0, porosityModel = 'MATRIX_MODEL'): + propertyTypeEnum = Properties_pb2.PropertyType.Value(propertyType) + porosityModelEnum = Case_pb2.PorosityModelType.Value(porosityModel) + request = Properties_pb2.PropertyRequest(case_request = self.case.request, + property_type = propertyTypeEnum, + property_name = propertyName, + time_step = timeStep, + grid_index = gridIndex, + porosity_model = porosityModelEnum) + return self.propertiesStub.GetGridProperty(request) + + def setActiveCellPropertyAsync(self, values_iterator, propertyType, propertyName, timeStep, gridIndex = 0, porosityModel = 'MATRIX_MODEL'): + propertyTypeEnum = Properties_pb2.PropertyType.Value(propertyType) + porosityModelEnum = Case_pb2.PorosityModelType.Value(porosityModel) + request = Properties_pb2.PropertyRequest(case_request = self.case.request, + property_type = propertyTypeEnum, + property_name = propertyName, + time_step = timeStep, + grid_index = gridIndex, + porosity_model = porosityModelEnum) + try: + reply_iterator = self.generatePropertyInputIterator(values_iterator, request) + self.propertiesStub.SetActiveCellProperty(reply_iterator) + except grpc.RpcError as e: + if e.code() == grpc.StatusCode.NOT_FOUND: + print("Command not found") + else: + print("Other error", e) + + def setActiveCellProperty(self, values, propertyType, propertyName, timeStep, gridIndex = 0, porosityModel = 'MATRIX_MODEL'): + propertyTypeEnum = Properties_pb2.PropertyType.Value(propertyType) + porosityModelEnum = Case_pb2.PorosityModelType.Value(porosityModel) + request = Properties_pb2.PropertyRequest(case_request = self.case.request, + property_type = propertyTypeEnum, + property_name = propertyName, + time_step = timeStep, + grid_index = gridIndex, + porosity_model = porosityModelEnum) + try: + request_iterator = self.generatePropertyInputChunks(values, request) + self.propertiesStub.SetActiveCellProperty(request_iterator) + except grpc.RpcError as e: + if e.code() == grpc.StatusCode.NOT_FOUND: + print("Command not found") + else: + print("Other error", e) + def setGridProperty(self, values, propertyType, propertyName, timeStep, gridIndex = 0, porosityModel = 'MATRIX_MODEL'): + propertyTypeEnum = Properties_pb2.PropertyType.Value(propertyType) + porosityModelEnum = Case_pb2.PorosityModelType.Value(porosityModel) + request = Properties_pb2.PropertyRequest(case_request = self.case.request, + property_type = propertyTypeEnum, + property_name = propertyName, + time_step = timeStep, + grid_index = gridIndex, + porosity_model = porosityModelEnum) + try: + request_iterator = self.generatePropertyInputChunks(values, request) + self.propertiesStub.SetGridProperty(request_iterator) + except grpc.RpcError as e: + if e.code() == grpc.StatusCode.NOT_FOUND: + print("Command not found") + else: + print("Other error", e) diff --git a/ApplicationCode/GrpcInterface/Python/rips/ResInsight.py b/ApplicationCode/GrpcInterface/Python/rips/ResInsight.py new file mode 100644 index 0000000000..e9bfd24c3f --- /dev/null +++ b/ApplicationCode/GrpcInterface/Python/rips/ResInsight.py @@ -0,0 +1,78 @@ +import grpc +import os +import sys +import socket +import logging + +sys.path.insert(1, os.path.join(sys.path[0], '../generated')) + +import RiaVersionInfo + +from AppInfo import AppInfo +from Commands import Commands +from Project import Project + +class Instance: + @staticmethod + def is_port_in_use(port): + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: + s.settimeout(0.2) + return s.connect_ex(('localhost', port)) == 0 + + @staticmethod + def launch(): + port = 50051 + portEnv = os.environ.get('RESINSIGHT_GRPC_PORT') + if portEnv: + port = int(portEnv) + + resInsightExecutable = os.environ.get('RESINSIGHT_EXECUTABLE') + if resInsightExecutable is None: + print('Error: Could not launch any ResInsight instances because RESINSIGHT_EXECUTABLE is not set') + return None + + while Instance.is_port_in_use(port): + port += 1 + + print('Port ' + str(port)) + print('Trying to launch', resInsightExecutable) + pid = os.spawnl(os.P_NOWAIT, resInsightExecutable, " --grpcserver " + str(port)) + print(pid) + return Instance(port) + + @staticmethod + def find(startPort = 50051, endPort = 50071): + portEnv = os.environ.get('RESINSIGHT_GRPC_PORT') + if portEnv: + startPort = int(portEnv) + endPort = startPort + 20 + + for tryPort in range(startPort, endPort): + if Instance.is_port_in_use(tryPort): + return Instance(tryPort) + + print('Error: Could not find any ResInsight instances responding between ports ' + str(startPort) + ' and ' + str(endPort)) + return None + + def __init__(self, port = 50051): + logging.basicConfig() + location = "localhost:" + str(port) + self.channel = grpc.insecure_channel(location) + + # Main version check package + self.appInfo = AppInfo(self.channel) + try: + majorVersionOk = self.appInfo.majorVersion() == int(RiaVersionInfo.RESINSIGHT_MAJOR_VERSION) + minorVersionOk = self.appInfo.minorVersion() == int(RiaVersionInfo.RESINSIGHT_MINOR_VERSION) + if not (majorVersionOk and minorVersionOk): + raise Exception('Version of ResInsight does not match version of Python API') + except grpc.RpcError as e: + if e.code() == grpc.StatusCode.UNAVAILABLE: + print('Info: Could not find any instances at port ' + str(port)) + except Exception as e: + print('Error:', e) + + # Service packages + self.commands = Commands(self.channel) + self.project = Project(self.channel) + \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/Python/rips/__init__.py b/ApplicationCode/GrpcInterface/Python/rips/__init__.py new file mode 100644 index 0000000000..6d6e54d164 --- /dev/null +++ b/ApplicationCode/GrpcInterface/Python/rips/__init__.py @@ -0,0 +1,5 @@ +name = "rips" +from .Case import Case +from .Grid import Grid +from .Properties import Properties +from .Instance import Instance diff --git a/ApplicationCode/GrpcInterface/Python/setup.py.cmake b/ApplicationCode/GrpcInterface/Python/setup.py.cmake new file mode 100644 index 0000000000..2202937112 --- /dev/null +++ b/ApplicationCode/GrpcInterface/Python/setup.py.cmake @@ -0,0 +1,21 @@ +from setuptools import setup, find_packages + +with open('README.md') as f: + readme = f.read() + +with open('LICENSE') as f: + license = f.read() + +RIPS_DIST_VERSION = '1' + +setup( + name='rips', + version='@RESINSIGHT_MAJOR_VERSION@.@RESINSIGHT_MINOR_VERSION@.@RESINSIGHT_PATCH_VERSION@.' + RIPS_DIST_VERSION, + description='Python Interface for ResInsight', + long_description=readme, + author='Ceetron Solutions', + author_email='info@ceetronsolutions.com', + url='http://www.resinsight.org', + license=license, + packages=find_packages(exclude=('tests', 'docs', '__pycache', 'examples')) +) \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/RiaGrpcResInfoService.cpp b/ApplicationCode/GrpcInterface/RiaGrpcAppInfoService.cpp similarity index 81% rename from ApplicationCode/GrpcInterface/RiaGrpcResInfoService.cpp rename to ApplicationCode/GrpcInterface/RiaGrpcAppInfoService.cpp index c9503b40c7..b0d86041ef 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcResInfoService.cpp +++ b/ApplicationCode/GrpcInterface/RiaGrpcAppInfoService.cpp @@ -15,7 +15,7 @@ // for more details. // ////////////////////////////////////////////////////////////////////////////////// -#include "RiaGrpcResInfoService.h" +#include "RiaGrpcAppInfoService.h" #include "RiaVersionInfo.h" #include "RiaGrpcCallbacks.h" @@ -23,7 +23,7 @@ //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -grpc::Status RiaGrpcResInfoService::GetVersion(grpc::ServerContext* context, const rips::Empty* request, rips::Version* reply) +grpc::Status RiaGrpcAppInfoService::GetVersion(grpc::ServerContext* context, const rips::Empty* request, rips::Version* reply) { reply->set_major_version(RESINSIGHT_MAJOR_VERSION); reply->set_minor_version(RESINSIGHT_MINOR_VERSION); @@ -34,11 +34,11 @@ grpc::Status RiaGrpcResInfoService::GetVersion(grpc::ServerContext* context, con //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::vector RiaGrpcResInfoService::createCallbacks() +std::vector RiaGrpcAppInfoService::createCallbacks() { - typedef RiaGrpcResInfoService Self; + typedef RiaGrpcAppInfoService Self; return { new RiaGrpcUnaryCallback(this, &Self::GetVersion, &Self::RequestGetVersion) }; } -static bool RiaGrpcResInfoService_init = - RiaGrpcServiceFactory::instance()->registerCreator(typeid(RiaGrpcResInfoService).hash_code()); +static bool RiaGrpcAppInfoService_init = + RiaGrpcServiceFactory::instance()->registerCreator(typeid(RiaGrpcAppInfoService).hash_code()); diff --git a/ApplicationCode/GrpcInterface/RiaGrpcResInfoService.h b/ApplicationCode/GrpcInterface/RiaGrpcAppInfoService.h similarity index 93% rename from ApplicationCode/GrpcInterface/RiaGrpcResInfoService.h rename to ApplicationCode/GrpcInterface/RiaGrpcAppInfoService.h index 41b1fbaf20..a81399fd0a 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcResInfoService.h +++ b/ApplicationCode/GrpcInterface/RiaGrpcAppInfoService.h @@ -21,7 +21,7 @@ #include "RiaGrpcServiceInterface.h" -#include "ResInfo.grpc.pb.h" +#include "AppInfo.grpc.pb.h" #include #include @@ -39,7 +39,7 @@ class PdmValueField; class RiaGrpcCallbackInterface; -class RiaGrpcResInfoService : public rips::ResInfo::AsyncService, public RiaGrpcServiceInterface +class RiaGrpcAppInfoService : public rips::AppInfo::AsyncService, public RiaGrpcServiceInterface { public: grpc::Status GetVersion(grpc::ServerContext* context, const rips::Empty* request, rips::Version* reply) override; diff --git a/ApplicationCode/GrpcInterface/RiaGrpcGridInfoService.cpp b/ApplicationCode/GrpcInterface/RiaGrpcCaseService.cpp similarity index 83% rename from ApplicationCode/GrpcInterface/RiaGrpcGridInfoService.cpp rename to ApplicationCode/GrpcInterface/RiaGrpcCaseService.cpp index 3098147970..2e29a47edc 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcGridInfoService.cpp +++ b/ApplicationCode/GrpcInterface/RiaGrpcCaseService.cpp @@ -15,8 +15,9 @@ // for more details. // ////////////////////////////////////////////////////////////////////////////////// -#include "RiaGrpcGridInfoService.h" +#include "RiaGrpcCaseService.h" #include "RiaGrpcCallbacks.h" +#include "RiaSocketTools.h" #include "RigActiveCellInfo.h" #include "RigEclipseCaseData.h" @@ -49,7 +50,7 @@ grpc::Status RiaActiveCellInfoStateHandler::init(const rips::CellInfoRequest* re m_request = request; m_porosityModel = RiaDefines::PorosityModelType(m_request->porosity_model()); - RimCase* rimCase = RiaGrpcServiceInterface::findCase(m_request->case_id()); + RimCase* rimCase = RiaGrpcServiceInterface::findCase(m_request->case_request().id()); m_eclipseCase = dynamic_cast(rimCase); if (!m_eclipseCase) @@ -213,7 +214,7 @@ grpc::Status RiaActiveCellInfoStateHandler::assignReply(rips::CellInfoArray* rep //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -grpc::Status RiaGrpcGridInfoService::GetGridCount(grpc::ServerContext* context, const rips::Case* request, rips::GridCount* reply) +grpc::Status RiaGrpcCaseService::GetGridCount(grpc::ServerContext* context, const rips::CaseRequest* request, rips::GridCount* reply) { RimCase* rimCase = findCase(request->id()); @@ -230,36 +231,9 @@ grpc::Status RiaGrpcGridInfoService::GetGridCount(grpc::ServerContext* context, //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -grpc::Status RiaGrpcGridInfoService::GetGridDimensions(grpc::ServerContext* context, - const rips::Case* request, - rips::GridDimensions* reply) +grpc::Status RiaGrpcCaseService::GetCellCount(grpc::ServerContext* context, const rips::CellInfoRequest* request, rips::CellCount* reply) { - RimCase* rimCase = findCase(request->id()); - - RimEclipseCase* eclipseCase = dynamic_cast(rimCase); - if (eclipseCase) - { - size_t gridCount = eclipseCase->mainGrid()->gridCount(); - for (size_t i = 0; i < gridCount; ++i) - { - const RigGridBase* grid = eclipseCase->mainGrid()->gridByIndex(i); - rips::Vec3i* dimensions = reply->add_dimensions(); - dimensions->set_i((int)grid->cellCountI()); - dimensions->set_j((int)grid->cellCountJ()); - dimensions->set_k((int)grid->cellCountK()); - } - return grpc::Status::OK; - } - - return grpc::Status(grpc::NOT_FOUND, "Eclipse Case not found"); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -grpc::Status RiaGrpcGridInfoService::GetCellCount(grpc::ServerContext* context, const rips::CellInfoRequest* request, rips::CellCount* reply) -{ - RimCase* rimCase = findCase(request->case_id()); + RimCase* rimCase = findCase(request->case_request().id()); RimEclipseCase* eclipseCase = dynamic_cast(rimCase); if (eclipseCase) @@ -278,7 +252,7 @@ grpc::Status RiaGrpcGridInfoService::GetCellCount(grpc::ServerContext* context, /// //-------------------------------------------------------------------------------------------------- grpc::Status -RiaGrpcGridInfoService::GetTimeSteps(grpc::ServerContext* context, const rips::Case* request, rips::TimeStepDates* reply) +RiaGrpcCaseService::GetTimeSteps(grpc::ServerContext* context, const rips::CaseRequest* request, rips::TimeStepDates* reply) { RimCase* rimCase = findCase(request->id()); @@ -288,7 +262,7 @@ RiaGrpcGridInfoService::GetTimeSteps(grpc::ServerContext* context, const rips::C std::vector timeStepDates = eclipseCase->timeStepDates(); for (QDateTime dateTime : timeStepDates) { - rips::TimeStepDate* date = reply->add_date(); + rips::TimeStepDate* date = reply->add_dates(); date->set_year(dateTime.date().year()); date->set_month(dateTime.date().month()); date->set_day(dateTime.date().day()); @@ -301,10 +275,34 @@ RiaGrpcGridInfoService::GetTimeSteps(grpc::ServerContext* context, const rips::C return grpc::Status(grpc::NOT_FOUND, "Eclipse Case not found"); } + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -grpc::Status RiaGrpcGridInfoService::GetCellInfoForActiveCells(grpc::ServerContext* context, +grpc::Status + RiaGrpcCaseService::GetCaseInfo(grpc::ServerContext* context, const rips::CaseRequest* request, rips::CaseInfo* reply) +{ + RimCase* rimCase = findCase(request->id()); + if (rimCase) + { + qint64 caseId = rimCase->caseId(); + qint64 caseGroupId = -1; + QString caseName, caseType; + RiaSocketTools::getCaseInfoFromCase(rimCase, caseId, caseName, caseType, caseGroupId); + + reply->set_id(caseId); + reply->set_group_id(caseGroupId); + reply->set_name(caseName.toStdString()); + reply->set_type(caseType.toStdString()); + return Status::OK; + } + return Status(grpc::NOT_FOUND, "No cases found"); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +grpc::Status RiaGrpcCaseService::GetCellInfoForActiveCells(grpc::ServerContext* context, const rips::CellInfoRequest* request, rips::CellInfoArray* reply, RiaActiveCellInfoStateHandler* stateHandler) @@ -315,17 +313,17 @@ grpc::Status RiaGrpcGridInfoService::GetCellInfoForActiveCells(grpc::ServerConte //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::vector RiaGrpcGridInfoService::createCallbacks() +std::vector RiaGrpcCaseService::createCallbacks() { - typedef RiaGrpcGridInfoService Self; + typedef RiaGrpcCaseService Self; - return {new RiaGrpcUnaryCallback(this, &Self::GetGridCount, &Self::RequestGetGridCount), - new RiaGrpcUnaryCallback(this, &Self::GetGridDimensions, &Self::RequestGetGridDimensions), + return {new RiaGrpcUnaryCallback(this, &Self::GetGridCount, &Self::RequestGetGridCount), new RiaGrpcUnaryCallback(this, &Self::GetCellCount, &Self::RequestGetCellCount), - new RiaGrpcUnaryCallback(this, &Self::GetTimeSteps, &Self::RequestGetTimeSteps), + new RiaGrpcUnaryCallback(this, &Self::GetTimeSteps, &Self::RequestGetTimeSteps), + new RiaGrpcUnaryCallback(this, &Self::GetCaseInfo, &Self::RequestGetCaseInfo), new RiaGrpcServerStreamCallback( this, &Self::GetCellInfoForActiveCells, &Self::RequestGetCellInfoForActiveCells, new RiaActiveCellInfoStateHandler)}; } -static bool RiaGrpcGridInfoService_init = - RiaGrpcServiceFactory::instance()->registerCreator(typeid(RiaGrpcGridInfoService).hash_code()); +static bool RiaGrpcCaseService_init = + RiaGrpcServiceFactory::instance()->registerCreator(typeid(RiaGrpcCaseService).hash_code()); diff --git a/ApplicationCode/GrpcInterface/RiaGrpcGridInfoService.h b/ApplicationCode/GrpcInterface/RiaGrpcCaseService.h similarity index 88% rename from ApplicationCode/GrpcInterface/RiaGrpcGridInfoService.h rename to ApplicationCode/GrpcInterface/RiaGrpcCaseService.h index 104efd439b..5cf51b896e 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcGridInfoService.h +++ b/ApplicationCode/GrpcInterface/RiaGrpcCaseService.h @@ -17,7 +17,7 @@ ////////////////////////////////////////////////////////////////////////////////// #pragma once -#include "GridInfo.grpc.pb.h" +#include "Case.grpc.pb.h" #include "RiaGrpcServiceInterface.h" #include "RiaPorosityModel.h" @@ -26,7 +26,7 @@ namespace rips { -class Case; +class CaseRequest; } class RiaGrpcCallbackInterface; @@ -66,13 +66,13 @@ protected: // gRPC-service answering requests about grid information for a given case // //================================================================================================== -class RiaGrpcGridInfoService final : public rips::GridInfo::AsyncService, public RiaGrpcServiceInterface +class RiaGrpcCaseService final : public rips::Case::AsyncService, public RiaGrpcServiceInterface { public: - grpc::Status GetGridCount(grpc::ServerContext* context, const rips::Case* request, rips::GridCount* reply) override; - grpc::Status GetGridDimensions(grpc::ServerContext* context, const rips::Case* request, rips::GridDimensions* reply) override; + grpc::Status GetGridCount(grpc::ServerContext* context, const rips::CaseRequest* request, rips::GridCount* reply) override; grpc::Status GetCellCount(grpc::ServerContext* context, const rips::CellInfoRequest* request, rips::CellCount* reply) override; - grpc::Status GetTimeSteps(grpc::ServerContext* context, const rips::Case* request, rips::TimeStepDates* reply) override; + grpc::Status GetTimeSteps(grpc::ServerContext* context, const rips::CaseRequest* request, rips::TimeStepDates* reply) override; + grpc::Status GetCaseInfo(grpc::ServerContext* context, const rips::CaseRequest* request, rips::CaseInfo* reply) override; grpc::Status GetCellInfoForActiveCells(grpc::ServerContext* context, const rips::CellInfoRequest* request, diff --git a/ApplicationCode/GrpcInterface/RiaGrpcGridService.cpp b/ApplicationCode/GrpcInterface/RiaGrpcGridService.cpp new file mode 100644 index 0000000000..8bff2e43ee --- /dev/null +++ b/ApplicationCode/GrpcInterface/RiaGrpcGridService.cpp @@ -0,0 +1,75 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 "RiaGrpcGridService.h" + +#include "RiaGrpcCallbacks.h" + +#include "RigEclipseCaseData.h" +#include "RigMainGrid.h" + +#include "RimEclipseCase.h" + +using namespace rips; + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +grpc::Status RiaGrpcGridService::GetDimensions(grpc::ServerContext* context, + const GridRequest* request, + GridDimensions* reply) +{ + RimCase* rimCase = findCase(request->case_request().id()); + + RimEclipseCase* eclipseCase = dynamic_cast(rimCase); + if (eclipseCase) + { + size_t gridIndex = (size_t) request->grid_index(); + if (gridIndex < eclipseCase->mainGrid()->gridCount()) + { + const RigGridBase* grid = eclipseCase->mainGrid()->gridByIndex(gridIndex); + Vec3i* dimensions = new Vec3i; + dimensions->set_i((int)grid->cellCountI()); + dimensions->set_j((int)grid->cellCountJ()); + dimensions->set_k((int)grid->cellCountK()); + + reply->set_allocated_dimensions(dimensions); + return grpc::Status::OK; + } + return grpc::Status(grpc::NOT_FOUND, "Grid not found"); + } + + return grpc::Status(grpc::NOT_FOUND, "Eclipse Case not found"); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RiaGrpcGridService::createCallbacks() +{ + typedef RiaGrpcGridService Self; + + return { + new RiaGrpcUnaryCallback( + this, &Self::GetDimensions, &Self::RequestGetDimensions) + }; +} + + +static bool RiaGrpcGridService_init = + RiaGrpcServiceFactory::instance()->registerCreator(typeid(RiaGrpcGridService).hash_code()); + diff --git a/ApplicationCode/GrpcInterface/RiaGrpcGridService.h b/ApplicationCode/GrpcInterface/RiaGrpcGridService.h new file mode 100644 index 0000000000..707b21c548 --- /dev/null +++ b/ApplicationCode/GrpcInterface/RiaGrpcGridService.h @@ -0,0 +1,30 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 "Grid.grpc.pb.h" + +#include "RiaGrpcServiceInterface.h" + +class RiaGrpcGridService final : public rips::Grid::AsyncService, public RiaGrpcServiceInterface +{ +public: + grpc::Status GetDimensions(grpc::ServerContext* context, const rips::GridRequest* request, rips::GridDimensions* reply) override; + + std::vector createCallbacks() override; +}; diff --git a/ApplicationCode/GrpcInterface/RiaGrpcProjectInfoService.cpp b/ApplicationCode/GrpcInterface/RiaGrpcProjectService.cpp similarity index 60% rename from ApplicationCode/GrpcInterface/RiaGrpcProjectInfoService.cpp rename to ApplicationCode/GrpcInterface/RiaGrpcProjectService.cpp index bd802730f3..364e7cc15a 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcProjectInfoService.cpp +++ b/ApplicationCode/GrpcInterface/RiaGrpcProjectService.cpp @@ -1,4 +1,4 @@ -#include "RiaGrpcProjectInfoService.h" +#include "RiaGrpcProjectService.h" #include "RiaApplication.h" #include "RiaGrpcCallbacks.h" @@ -16,7 +16,7 @@ #include "cafSelectionManager.h" -#include "CaseInfo.grpc.pb.h" +#include "Case.grpc.pb.h" using grpc::ServerCompletionQueue; using grpc::ServerContext; @@ -27,7 +27,7 @@ using namespace rips; //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -Status RiaGrpcProjectInfoService::CurrentCase(ServerContext* context, const rips::Empty* request, rips::Case* reply) +Status RiaGrpcProjectService::GetCurrentCase(ServerContext* context, const rips::Empty* request, rips::CaseRequest* reply) { RimGridView* view = RiaApplication::instance()->activeGridView(); if (view) @@ -45,56 +45,7 @@ Status RiaGrpcProjectInfoService::CurrentCase(ServerContext* context, const rips //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -Status RiaGrpcProjectInfoService::CurrentCaseInfo(ServerContext* context, const rips::Empty* request, rips::CaseInfo* reply) -{ - RimGridView* view = RiaApplication::instance()->activeGridView(); - if (view) - { - RimCase* currentCase = view->ownerCase(); - if (currentCase) - { - qint64 caseId = currentCase->caseId(); - qint64 caseGroupId = -1; - QString caseName, caseType; - RiaSocketTools::getCaseInfoFromCase(currentCase, caseId, caseName, caseType, caseGroupId); - - reply->set_id(caseId); - reply->set_group_id(caseGroupId); - reply->set_name(caseName.toStdString()); - reply->set_type(caseType.toStdString()); - return Status::OK; - } - } - return Status(grpc::NOT_FOUND, "No current case found"); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -grpc::Status - RiaGrpcProjectInfoService::CaseInfoFromCase(grpc::ServerContext* context, const rips::Case* request, rips::CaseInfo* reply) -{ - RimCase* rimCase = findCase(request->id()); - if (rimCase) - { - qint64 caseId = rimCase->caseId(); - qint64 caseGroupId = -1; - QString caseName, caseType; - RiaSocketTools::getCaseInfoFromCase(rimCase, caseId, caseName, caseType, caseGroupId); - - reply->set_id(caseId); - reply->set_group_id(caseGroupId); - reply->set_name(caseName.toStdString()); - reply->set_type(caseType.toStdString()); - return Status::OK; - } - return Status(grpc::NOT_FOUND, "No cases found"); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -Status RiaGrpcProjectInfoService::SelectedCases(ServerContext* context, const rips::Empty* request, rips::CaseInfos* reply) +Status RiaGrpcProjectService::GetSelectedCases(ServerContext* context, const rips::Empty* request, rips::CaseInfoArray* reply) { std::vector cases; caf::SelectionManager::instance()->objectsByType(&cases); @@ -111,7 +62,7 @@ Status RiaGrpcProjectInfoService::SelectedCases(ServerContext* context, const ri QString caseName, caseType; RiaSocketTools::getCaseInfoFromCase(rimCase, caseId, caseName, caseType, caseGroupId); - rips::CaseInfo* caseInfo = reply->add_case_info(); + rips::CaseInfo* caseInfo = reply->add_data(); caseInfo->set_id(caseId); caseInfo->set_group_id(caseGroupId); caseInfo->set_name(caseName.toStdString()); @@ -124,7 +75,7 @@ Status RiaGrpcProjectInfoService::SelectedCases(ServerContext* context, const ri /// //-------------------------------------------------------------------------------------------------- grpc::Status - RiaGrpcProjectInfoService::AllCaseGroups(grpc::ServerContext* context, const rips::Empty* request, rips::CaseGroups* reply) + RiaGrpcProjectService::GetAllCaseGroups(grpc::ServerContext* context, const rips::Empty* request, rips::CaseGroups* reply) { RimProject* proj = RiaApplication::instance()->project(); RimEclipseCaseCollection* analysisModels = @@ -133,7 +84,7 @@ grpc::Status { for (RimIdenticalGridCaseGroup* cg : analysisModels->caseGroups()) { - rips::CaseGroup* caseGroup = reply->add_case_group(); + rips::CaseGroup* caseGroup = reply->add_case_groups(); caseGroup->set_id(cg->groupId()); caseGroup->set_name(cg->name().toStdString()); } @@ -145,7 +96,7 @@ grpc::Status //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -grpc::Status RiaGrpcProjectInfoService::AllCases(grpc::ServerContext* context, const rips::Empty* request, rips::CaseInfos* reply) +grpc::Status RiaGrpcProjectService::GetAllCases(grpc::ServerContext* context, const rips::Empty* request, rips::CaseInfoArray* reply) { std::vector cases; RiaApplication::instance()->project()->allCases(cases); @@ -162,7 +113,7 @@ grpc::Status RiaGrpcProjectInfoService::AllCases(grpc::ServerContext* context, c QString caseName, caseType; RiaSocketTools::getCaseInfoFromCase(rimCase, caseId, caseName, caseType, caseGroupId); - rips::CaseInfo* caseInfo = reply->add_case_info(); + rips::CaseInfo* caseInfo = reply->add_data(); caseInfo->set_id(caseId); caseInfo->set_group_id(caseGroupId); caseInfo->set_name(caseName.toStdString()); @@ -175,7 +126,7 @@ grpc::Status RiaGrpcProjectInfoService::AllCases(grpc::ServerContext* context, c /// //-------------------------------------------------------------------------------------------------- grpc::Status - RiaGrpcProjectInfoService::CasesInGroup(grpc::ServerContext* context, const rips::CaseGroup* request, rips::CaseInfos* reply) + RiaGrpcProjectService::GetCasesInGroup(grpc::ServerContext* context, const rips::CaseGroup* request, rips::CaseInfoArray* reply) { RimProject* proj = RiaApplication::instance()->project(); RimEclipseCaseCollection* analysisModels = @@ -217,7 +168,7 @@ grpc::Status QString caseName, caseType; RiaSocketTools::getCaseInfoFromCase(rimCase, caseId, caseName, caseType, caseGroupId); - rips::CaseInfo* caseInfo = reply->add_case_info(); + rips::CaseInfo* caseInfo = reply->add_data(); caseInfo->set_id(caseId); caseInfo->set_group_id(caseGroupId); caseInfo->set_name(caseName.toStdString()); @@ -231,19 +182,17 @@ grpc::Status //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::vector RiaGrpcProjectInfoService::createCallbacks() +std::vector RiaGrpcProjectService::createCallbacks() { - typedef RiaGrpcProjectInfoService Self; + typedef RiaGrpcProjectService Self; return { - new RiaGrpcUnaryCallback(this, &Self::CurrentCase, &Self::RequestCurrentCase), - new RiaGrpcUnaryCallback(this, &Self::CurrentCaseInfo, &Self::RequestCurrentCaseInfo), - new RiaGrpcUnaryCallback(this, &Self::CaseInfoFromCase, &Self::RequestCaseInfoFromCase), - new RiaGrpcUnaryCallback(this, &Self::SelectedCases, &Self::RequestSelectedCases), - new RiaGrpcUnaryCallback(this, &Self::AllCaseGroups, &Self::RequestAllCaseGroups), - new RiaGrpcUnaryCallback(this, &Self::AllCases, &Self::RequestAllCases), - new RiaGrpcUnaryCallback(this, &Self::CasesInGroup, &Self::RequestCasesInGroup)}; + new RiaGrpcUnaryCallback(this, &Self::GetCurrentCase, &Self::RequestGetCurrentCase), + new RiaGrpcUnaryCallback(this, &Self::GetSelectedCases, &Self::RequestGetSelectedCases), + new RiaGrpcUnaryCallback(this, &Self::GetAllCaseGroups, &Self::RequestGetAllCaseGroups), + new RiaGrpcUnaryCallback(this, &Self::GetAllCases, &Self::RequestGetAllCases), + new RiaGrpcUnaryCallback(this, &Self::GetCasesInGroup, &Self::RequestGetCasesInGroup)}; } -static bool RiaGrpcProjectInfoService_init = - RiaGrpcServiceFactory::instance()->registerCreator(typeid(RiaGrpcProjectInfoService).hash_code()); +static bool RiaGrpcProjectService_init = + RiaGrpcServiceFactory::instance()->registerCreator(typeid(RiaGrpcProjectService).hash_code()); diff --git a/ApplicationCode/GrpcInterface/RiaGrpcProjectInfoService.h b/ApplicationCode/GrpcInterface/RiaGrpcProjectService.h similarity index 56% rename from ApplicationCode/GrpcInterface/RiaGrpcProjectInfoService.h rename to ApplicationCode/GrpcInterface/RiaGrpcProjectService.h index 92ab551cf7..37143c9b8d 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcProjectInfoService.h +++ b/ApplicationCode/GrpcInterface/RiaGrpcProjectService.h @@ -17,7 +17,7 @@ ////////////////////////////////////////////////////////////////////////////////// #pragma once -#include "ProjectInfo.grpc.pb.h" +#include "Project.grpc.pb.h" #include "RiaGrpcServiceInterface.h" #include @@ -25,7 +25,7 @@ namespace rips { class Empty; -class CaseInfo; +class CaseRequest; } // namespace rips class RiaGrpcCallbackInterface; @@ -35,16 +35,14 @@ class RiaGrpcCallbackInterface; // gRPC-service answering requests about project information // //================================================================================================== -class RiaGrpcProjectInfoService final : public rips::ProjectInfo::AsyncService, public RiaGrpcServiceInterface +class RiaGrpcProjectService final : public rips::Project::AsyncService, public RiaGrpcServiceInterface { public: - grpc::Status CurrentCase(grpc::ServerContext* context, const rips::Empty* request, rips::Case* reply) override; - grpc::Status CurrentCaseInfo(grpc::ServerContext* context, const rips::Empty* request, rips::CaseInfo* reply) override; - grpc::Status CaseInfoFromCase(grpc::ServerContext* context, const rips::Case* request, rips::CaseInfo* reply) override; - grpc::Status SelectedCases(grpc::ServerContext* context, const rips::Empty* request, rips::CaseInfos* reply) override; - grpc::Status AllCaseGroups(grpc::ServerContext* context, const rips::Empty* request, rips::CaseGroups* reply) override; - grpc::Status AllCases(grpc::ServerContext* context, const rips::Empty* request, rips::CaseInfos* reply) override; - grpc::Status CasesInGroup(grpc::ServerContext* context, const rips::CaseGroup* request, rips::CaseInfos* reply) override; + grpc::Status GetCurrentCase(grpc::ServerContext* context, const rips::Empty* request, rips::CaseRequest* reply) override; + grpc::Status GetSelectedCases(grpc::ServerContext* context, const rips::Empty* request, rips::CaseInfoArray* reply) override; + grpc::Status GetAllCaseGroups(grpc::ServerContext* context, const rips::Empty* request, rips::CaseGroups* reply) override; + grpc::Status GetAllCases(grpc::ServerContext* context, const rips::Empty* request, rips::CaseInfoArray* reply) override; + grpc::Status GetCasesInGroup(grpc::ServerContext* context, const rips::CaseGroup* request, rips::CaseInfoArray* reply) override; public: std::vector createCallbacks() override; diff --git a/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp b/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp index dbe8ca6dd2..0cf295fefc 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp +++ b/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp @@ -18,7 +18,7 @@ #include "RiaGrpcPropertiesService.h" #include "RiaGrpcCallbacks.h" -#include "RiaGrpcGridInfoService.h" +#include "RiaGrpcCaseService.h" #include "RigActiveCellInfo.h" #include "RigActiveCellsResultAccessor.h" @@ -61,9 +61,9 @@ public: //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- - Status init(const ResultRequest* request) + Status init(const PropertyRequest* request) { - int caseId = request->request_case().id(); + int caseId = request->case_request().id(); m_eclipseCase = dynamic_cast(RiaGrpcServiceInterface::findCase(caseId)); if (m_eclipseCase) @@ -110,21 +110,21 @@ public: //-------------------------------------------------------------------------------------------------- /// Client streamers need to be initialised with the encapsulated parameters //-------------------------------------------------------------------------------------------------- - Status init(const ResultRequestChunk* request) + Status init(const PropertyInputChunk* chunk) { - if (request->has_params()) + if (chunk->has_params()) { - return init(&(request->params())); + return init(&(chunk->params())); } - return grpc::Status(grpc::INVALID_ARGUMENT, "Need to have ResultRequest parameters in first message"); + return grpc::Status(grpc::INVALID_ARGUMENT, "Need to have PropertyRequest parameters in first message"); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- - Status assignStreamReply(ResultArray* reply) + Status assignStreamReply(PropertyChunk* reply) { - const size_t packageSize = RiaGrpcServiceInterface::numberOfMessagesForByteCount(sizeof(rips::ResultArray)); + const size_t packageSize = RiaGrpcServiceInterface::numberOfMessagesForByteCount(sizeof(rips::PropertyChunk)); size_t packageIndex = 0u; reply->mutable_values()->Reserve((int)packageSize); for (; packageIndex < packageSize && m_currentCellIdx < m_cellCount; ++packageIndex, ++m_currentCellIdx) @@ -142,7 +142,7 @@ public: //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- - Status receiveStreamRequest(const ResultRequestChunk* request) + Status receiveStreamRequest(const PropertyInputChunk* request) { if (request->has_values()) { @@ -183,7 +183,7 @@ protected: virtual void setCellResult(size_t currentCellIndex, double value) = 0; protected: - const rips::ResultRequest* m_request; + const rips::PropertyRequest* m_request; RimEclipseCase* m_eclipseCase; size_t m_currentCellIdx; size_t m_cellCount; @@ -263,11 +263,11 @@ private: //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -grpc::Status RiaGrpcPropertiesService::GetAvailableProperties(grpc::ServerContext* context, - const PropertiesRequest* request, - AvailableProperties* reply) +grpc::Status RiaGrpcPropertiesService::GetAvailableProperties(grpc::ServerContext* context, + const AvailablePropertiesRequest* request, + AvailableProperties* reply) { - int caseId = request->request_case().id(); + int caseId = request->case_request().id(); RimEclipseCase* eclipseCase = dynamic_cast(RiaGrpcServiceInterface::findCase(caseId)); if (eclipseCase) { @@ -291,9 +291,9 @@ grpc::Status RiaGrpcPropertiesService::GetAvailableProperties(grpc::ServerContex //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -grpc::Status RiaGrpcPropertiesService::GetActiveCellResults(grpc::ServerContext* context, - const ResultRequest* request, - ResultArray* reply, +grpc::Status RiaGrpcPropertiesService::GetActiveCellProperty(grpc::ServerContext* context, + const PropertyRequest* request, + PropertyChunk* reply, RiaActiveCellResultsStateHandler* stateHandler) { return stateHandler->assignStreamReply(reply); @@ -303,9 +303,9 @@ grpc::Status RiaGrpcPropertiesService::GetActiveCellResults(grpc::ServerContext* //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -grpc::Status RiaGrpcPropertiesService::GetGridResults(grpc::ServerContext* context, - const rips::ResultRequest* request, - rips::ResultArray* reply, +grpc::Status RiaGrpcPropertiesService::GetGridProperty(grpc::ServerContext* context, + const rips::PropertyRequest* request, + rips::PropertyChunk* reply, RiaGridCellResultsStateHandler* stateHandler) { return stateHandler->assignStreamReply(reply); @@ -314,8 +314,8 @@ grpc::Status RiaGrpcPropertiesService::GetGridResults(grpc::ServerContext* //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -grpc::Status RiaGrpcPropertiesService::SetActiveCellResults(grpc::ServerContext* context, - const rips::ResultRequestChunk* request, +grpc::Status RiaGrpcPropertiesService::SetActiveCellProperty(grpc::ServerContext* context, + const rips::PropertyInputChunk* request, rips::Empty* reply, RiaActiveCellResultsStateHandler* stateHandler) { @@ -326,8 +326,8 @@ grpc::Status RiaGrpcPropertiesService::SetActiveCellResults(grpc::ServerContext* //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -grpc::Status RiaGrpcPropertiesService::SetGridResults(grpc::ServerContext* context, - const rips::ResultRequestChunk* request, +grpc::Status RiaGrpcPropertiesService::SetGridProperty(grpc::ServerContext* context, + const rips::PropertyInputChunk* request, rips::Empty* reply, RiaGridCellResultsStateHandler* stateHandler) { @@ -340,16 +340,16 @@ std::vector RiaGrpcPropertiesService::createCallbacks { typedef RiaGrpcPropertiesService Self; - return {new RiaGrpcUnaryCallback( + return {new RiaGrpcUnaryCallback( this, &Self::GetAvailableProperties, &Self::RequestGetAvailableProperties), - new RiaGrpcServerStreamCallback( - this, &Self::GetActiveCellResults, &Self::RequestGetActiveCellResults, new RiaActiveCellResultsStateHandler), - new RiaGrpcServerStreamCallback( - this, &Self::GetGridResults, &Self::RequestGetGridResults, new RiaGridCellResultsStateHandler), - new RiaGrpcClientStreamCallback( - this, &Self::SetActiveCellResults, &Self::RequestSetActiveCellResults, new RiaActiveCellResultsStateHandler(true)), - new RiaGrpcClientStreamCallback( - this, &Self::SetGridResults, &Self::RequestSetGridResults, new RiaGridCellResultsStateHandler(true)) + new RiaGrpcServerStreamCallback( + this, &Self::GetActiveCellProperty, &Self::RequestGetActiveCellProperty, new RiaActiveCellResultsStateHandler), + new RiaGrpcServerStreamCallback( + this, &Self::GetGridProperty, &Self::RequestGetGridProperty, new RiaGridCellResultsStateHandler), + new RiaGrpcClientStreamCallback( + this, &Self::SetActiveCellProperty, &Self::RequestSetActiveCellProperty, new RiaActiveCellResultsStateHandler(true)), + new RiaGrpcClientStreamCallback( + this, &Self::SetGridProperty, &Self::RequestSetGridProperty, new RiaGridCellResultsStateHandler(true)) }; } diff --git a/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.h b/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.h index 827b5a8b66..b918c82400 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.h +++ b/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.h @@ -34,25 +34,25 @@ class RiaGridCellResultsStateHandler; class RiaGrpcPropertiesService final : public rips::Properties::AsyncService, public RiaGrpcServiceInterface { public: - grpc::Status GetAvailableProperties(grpc::ServerContext* context, - const rips::PropertiesRequest* request, - rips::AvailableProperties* reply) override; - grpc::Status GetActiveCellResults(grpc::ServerContext* context, - const rips::ResultRequest* request, - rips::ResultArray* reply, - RiaActiveCellResultsStateHandler* stateHandler); - grpc::Status GetGridResults(grpc::ServerContext* context, - const rips::ResultRequest* request, - rips::ResultArray* reply, - RiaGridCellResultsStateHandler* stateHandler); - grpc::Status SetActiveCellResults(grpc::ServerContext* context, - const rips::ResultRequestChunk* request, - rips::Empty* reply, - RiaActiveCellResultsStateHandler* stateHandler); - grpc::Status SetGridResults(grpc::ServerContext* context, - const rips::ResultRequestChunk* request, - rips::Empty* reply, - RiaGridCellResultsStateHandler* stateHandler); + grpc::Status GetAvailableProperties(grpc::ServerContext* context, + const rips::AvailablePropertiesRequest* request, + rips::AvailableProperties* reply) override; + grpc::Status GetActiveCellProperty(grpc::ServerContext* context, + const rips::PropertyRequest* request, + rips::PropertyChunk* reply, + RiaActiveCellResultsStateHandler* stateHandler); + grpc::Status GetGridProperty(grpc::ServerContext* context, + const rips::PropertyRequest* request, + rips::PropertyChunk* reply, + RiaGridCellResultsStateHandler* stateHandler); + grpc::Status SetActiveCellProperty(grpc::ServerContext* context, + const rips::PropertyInputChunk* chunk, + rips::Empty* reply, + RiaActiveCellResultsStateHandler* stateHandler); + grpc::Status SetGridProperty(grpc::ServerContext* context, + const rips::PropertyInputChunk* chunk, + rips::Empty* reply, + RiaGridCellResultsStateHandler* stateHandler); std::vector createCallbacks() override; }; diff --git a/ApplicationCode/GrpcInterface/RiaGrpcServer.cpp b/ApplicationCode/GrpcInterface/RiaGrpcServer.cpp index 9356b3762d..44c7a0da0c 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcServer.cpp +++ b/ApplicationCode/GrpcInterface/RiaGrpcServer.cpp @@ -23,7 +23,7 @@ #include "RiaGrpcCallbacks.h" #include "RiaGrpcServiceInterface.h" -#include "RiaGrpcGridInfoService.h" +#include "RiaGrpcCaseService.h" #include "RigCaseCellResultsData.h" #include "RigMainGrid.h" diff --git a/ApplicationCode/UnitTests/CMakeLists_files.cmake b/ApplicationCode/UnitTests/CMakeLists_files.cmake index 596414f93a..4cc33352a1 100644 --- a/ApplicationCode/UnitTests/CMakeLists_files.cmake +++ b/ApplicationCode/UnitTests/CMakeLists_files.cmake @@ -57,6 +57,15 @@ ${CMAKE_CURRENT_LIST_DIR}/RimWellPathCompletions-Test.cpp ${CMAKE_CURRENT_LIST_DIR}/RimSummaryCaseCollection-Test.cpp ) +if (RESINSIGHT_ENABLE_GRPC) + list(APPEND GPRC_UNIT_TEST_SOURCE_FILES + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcInterface-Test.cpp + ) + list(APPEND SOURCE_GROUP_SOURCE_FILES + ${GRPC_UNIT_TEST_SOURCE_FILES} + ) +endif(RESINSIGHT_ENABLE_GRPC) + list(APPEND CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES} ) diff --git a/ApplicationCode/UnitTests/RiaGrpcInterface-Test.cpp b/ApplicationCode/UnitTests/RiaGrpcInterface-Test.cpp new file mode 100644 index 0000000000..3e355079e9 --- /dev/null +++ b/ApplicationCode/UnitTests/RiaGrpcInterface-Test.cpp @@ -0,0 +1,68 @@ +#include "gtest/gtest.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "Properties.grpc.pb.h" + +using grpc::Channel; +using grpc::ClientContext; +using grpc::ClientReader; +using grpc::ClientReaderWriter; +using grpc::ClientWriter; +using grpc::Status; + +class PropertiesClient +{ +public: + PropertiesClient(std::shared_ptr channel) + : m_stub(rips::Properties::NewStub(channel)) + { + } + Status GetActiveCellProperty(rips::PropertyType propType, const std::string& propertyName, int timeStep, std::vector* results) const + { + rips::PropertyRequest request; + rips::CaseRequest* requestCase = new rips::CaseRequest; + requestCase->set_id(0); + request.set_allocated_case_request(requestCase); + request.set_grid_index(0); + request.set_porosity_model(rips::PorosityModelType::MATRIX_MODEL); + request.set_property_type(propType); + request.set_property_name(propertyName); + request.set_time_step(timeStep); + rips::PropertyChunk resultArray; + ClientContext context; + + std::unique_ptr> reader = m_stub->GetActiveCellProperty(&context, request); + while (reader->Read(&resultArray)) + { + results->insert(results->end(), resultArray.values().begin(), resultArray.values().end()); + } + return reader->Finish(); + } +private: + std::unique_ptr m_stub; +}; + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +TEST(DISABLED_RiaGrpcInterface, SoilAverage) +{ + PropertiesClient client(grpc::CreateChannel("localhost:50051", grpc::InsecureChannelCredentials())); + + for (size_t i = 0; i < 10; ++i) + { + std::vector results; + Status status = client.GetActiveCellProperty(rips::PropertyType::DYNAMIC_NATIVE, "SOIL", i, &results); + std::cout << "Number of results: " << results.size() << std::endl; + double sum = std::accumulate(results.begin(), results.end(), 0.0); + std::cout << "Avg: " << sum / static_cast(results.size()) << std::endl; + EXPECT_EQ(grpc::OK, status.error_code()); + } +} From 17821ade6c55935dda8dd3de0a81420937badd81 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Mon, 3 Jun 2019 21:10:21 +0200 Subject: [PATCH 119/396] #4461 Fix return values from RicfCommandResponse --- .../CommandFileInterface/Core/RicfCommandResponse.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ApplicationCode/CommandFileInterface/Core/RicfCommandResponse.cpp b/ApplicationCode/CommandFileInterface/Core/RicfCommandResponse.cpp index 95fabe9e42..f46c8c0c56 100644 --- a/ApplicationCode/CommandFileInterface/Core/RicfCommandResponse.cpp +++ b/ApplicationCode/CommandFileInterface/Core/RicfCommandResponse.cpp @@ -22,7 +22,8 @@ //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RicfCommandResponse::RicfCommandResponse(Status status, const QString& message) +RicfCommandResponse::RicfCommandResponse(Status status, const QString& message) + : m_status(COMMAND_OK) { updateStatus(status, message); } From fe2d352f84bd09046092529e289011c0d4c5f84b Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Mon, 3 Jun 2019 21:11:27 +0200 Subject: [PATCH 120/396] #4462 Python Fix examples to run well with either install module or without --- .../GrpcInterface/GrpcProtos/Commands.proto | 1 + .../GrpcInterface/Python/examples/AllCases.py | 2 + .../examples/CaseInfoStreamingExample.py | 8 +- .../Python/examples/CommandExample.py | 15 +++- .../Python/examples/GridInformation.py | 6 +- .../Python/examples/PoroPermXAsync.py | 6 +- .../Python/examples/PoroPermXSync.py | 6 +- .../Python/examples/SelectedCases.py | 6 +- .../Python/examples/SetGridProperties.py | 6 +- .../Python/examples/SoilPorvAsync.py | 6 +- .../Python/examples/SoilPorvSync.py | 8 +- .../GrpcInterface/Python/rips/Case.py | 4 +- .../GrpcInterface/Python/rips/Commands.py | 76 +++++++++++++++---- .../GrpcInterface/Python/rips/Project.py | 1 + 14 files changed, 102 insertions(+), 49 deletions(-) diff --git a/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto b/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto index 706f25f39c..0f8f62a5fb 100644 --- a/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto +++ b/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto @@ -28,6 +28,7 @@ message ReplaceCaseRequest message ReplaceSourceCasesRequest { string gridListFile = 1; + int32 caseGroupId = 2; } message ExportMultiCaseRequest diff --git a/ApplicationCode/GrpcInterface/Python/examples/AllCases.py b/ApplicationCode/GrpcInterface/Python/examples/AllCases.py index f4681de047..5e0acab19a 100644 --- a/ApplicationCode/GrpcInterface/Python/examples/AllCases.py +++ b/ApplicationCode/GrpcInterface/Python/examples/AllCases.py @@ -1,5 +1,7 @@ import sys import os + +sys.path.insert(1, os.path.join(sys.path[0], '..')) import rips resInsight = rips.Instance.find() diff --git a/ApplicationCode/GrpcInterface/Python/examples/CaseInfoStreamingExample.py b/ApplicationCode/GrpcInterface/Python/examples/CaseInfoStreamingExample.py index a006128baa..861e1e8789 100644 --- a/ApplicationCode/GrpcInterface/Python/examples/CaseInfoStreamingExample.py +++ b/ApplicationCode/GrpcInterface/Python/examples/CaseInfoStreamingExample.py @@ -1,11 +1,9 @@ import sys import os -sys.path.insert(1, os.path.join(sys.path[0], '../api')) -import ResInsight +sys.path.insert(1, os.path.join(sys.path[0], '..')) +import rips -resInsight = ResInsight.Instance.find() -#gridCount = resInsight.gridInfo.getGridCount(caseId=0) -#gridDimensions = resInsight.gridInfo.getAllGridDimensions(caseId=0) +resInsight = rips.Instance.find() case = resInsight.project.case(id = 0) diff --git a/ApplicationCode/GrpcInterface/Python/examples/CommandExample.py b/ApplicationCode/GrpcInterface/Python/examples/CommandExample.py index f34fdd8a9d..e45b9776fb 100644 --- a/ApplicationCode/GrpcInterface/Python/examples/CommandExample.py +++ b/ApplicationCode/GrpcInterface/Python/examples/CommandExample.py @@ -1,12 +1,19 @@ import sys import os -sys.path.insert(1, os.path.join(sys.path[0], '../api')) -import ResInsight +import tempfile +sys.path.insert(1, os.path.join(sys.path[0], '..')) +import rips # Load instance -resInsight = ResInsight.Instance.find() +resInsight = rips.Instance.find() # Run a couple of commands resInsight.commands.setTimeStep(caseId=0, timeStep=3) resInsight.commands.setMainWindowSize(width=800, height=500) -resInsight.commands.exportWellPaths() \ No newline at end of file +#resInsight.commands.exportWellPaths() +with tempfile.TemporaryDirectory(prefix="rips") as tmpdirname: + print("Temporary folder: ", tmpdirname) + resInsight.commands.setExportFolder(type='SNAPSHOTS', path=tmpdirname) + resInsight.commands.exportSnapshots() + print(os.listdir(tmpdirname)) + assert(len(os.listdir(tmpdirname)) > 0) \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/Python/examples/GridInformation.py b/ApplicationCode/GrpcInterface/Python/examples/GridInformation.py index eff73eb476..f0f9156816 100644 --- a/ApplicationCode/GrpcInterface/Python/examples/GridInformation.py +++ b/ApplicationCode/GrpcInterface/Python/examples/GridInformation.py @@ -1,10 +1,10 @@ import sys import os -sys.path.insert(1, os.path.join(sys.path[0], '../api')) +sys.path.insert(1, os.path.join(sys.path[0], '..')) -import ResInsight +import rips -resInsight = ResInsight.Instance.find() +resInsight = rips.Instance.find() cases = resInsight.project.cases() print("Number of cases found: ", len(cases)) for case in cases: diff --git a/ApplicationCode/GrpcInterface/Python/examples/PoroPermXAsync.py b/ApplicationCode/GrpcInterface/Python/examples/PoroPermXAsync.py index 98c86c5948..bab115a613 100644 --- a/ApplicationCode/GrpcInterface/Python/examples/PoroPermXAsync.py +++ b/ApplicationCode/GrpcInterface/Python/examples/PoroPermXAsync.py @@ -1,7 +1,7 @@ import sys import os -sys.path.insert(1, os.path.join(sys.path[0], '../api')) -import ResInsight +sys.path.insert(1, os.path.join(sys.path[0], '..')) +import rips def createResult(poroChunks, permxChunks): for (poroChunk, permxChunk) in zip(poroChunks, permxChunks): @@ -11,7 +11,7 @@ def createResult(poroChunks, permxChunks): yield resultChunk -resInsight = ResInsight.Instance.find() +resInsight = rips.Instance.find() case = resInsight.project.case(id=0) poroChunks = case.properties.activeCellProperty('STATIC_NATIVE', 'PORO', 0) diff --git a/ApplicationCode/GrpcInterface/Python/examples/PoroPermXSync.py b/ApplicationCode/GrpcInterface/Python/examples/PoroPermXSync.py index 0be8e0017e..28bdd25640 100644 --- a/ApplicationCode/GrpcInterface/Python/examples/PoroPermXSync.py +++ b/ApplicationCode/GrpcInterface/Python/examples/PoroPermXSync.py @@ -1,9 +1,9 @@ import sys import os -sys.path.insert(1, os.path.join(sys.path[0], '../api')) -import ResInsight +sys.path.insert(1, os.path.join(sys.path[0], '..')) +import rips -resInsight = ResInsight.Instance.find() +resInsight = rips.Instance.find() case = resInsight.project.case(id=0) diff --git a/ApplicationCode/GrpcInterface/Python/examples/SelectedCases.py b/ApplicationCode/GrpcInterface/Python/examples/SelectedCases.py index 830b9f658d..89b35fd4a6 100644 --- a/ApplicationCode/GrpcInterface/Python/examples/SelectedCases.py +++ b/ApplicationCode/GrpcInterface/Python/examples/SelectedCases.py @@ -1,10 +1,10 @@ import sys import os -sys.path.insert(1, os.path.join(sys.path[0], '../api')) +sys.path.insert(1, os.path.join(sys.path[0], '..')) -import ResInsight +import rips -resInsight = ResInsight.Instance.find() +resInsight = rips.Instance.find() if resInsight is not None: cases = resInsight.project.selectedCases() diff --git a/ApplicationCode/GrpcInterface/Python/examples/SetGridProperties.py b/ApplicationCode/GrpcInterface/Python/examples/SetGridProperties.py index 70e88e2c82..7fe0b295e8 100644 --- a/ApplicationCode/GrpcInterface/Python/examples/SetGridProperties.py +++ b/ApplicationCode/GrpcInterface/Python/examples/SetGridProperties.py @@ -1,9 +1,9 @@ import sys import os -sys.path.insert(1, os.path.join(sys.path[0], '../api')) -import ResInsight +sys.path.insert(1, os.path.join(sys.path[0], '..')) +import rips -resInsight = ResInsight.Instance.find() +resInsight = rips.Instance.find() case = resInsight.project.case(id=0) totalCellCount = case.cellCount().reservoir_cell_count diff --git a/ApplicationCode/GrpcInterface/Python/examples/SoilPorvAsync.py b/ApplicationCode/GrpcInterface/Python/examples/SoilPorvAsync.py index 622b45ebd2..1a57db2943 100644 --- a/ApplicationCode/GrpcInterface/Python/examples/SoilPorvAsync.py +++ b/ApplicationCode/GrpcInterface/Python/examples/SoilPorvAsync.py @@ -1,7 +1,7 @@ import sys import os -sys.path.insert(1, os.path.join(sys.path[0], '../api')) -import ResInsight +sys.path.insert(1, os.path.join(sys.path[0], '..')) +import rips def createResult(soilChunks, porvChunks): for (soilChunk, porvChunk) in zip(soilChunks, porvChunks): @@ -14,7 +14,7 @@ def createResult(soilChunks, porvChunks): -resInsight = ResInsight.Instance.find() +resInsight = rips.Instance.find() case = resInsight.project.case(id=0) timeStepInfo = case.timeSteps() diff --git a/ApplicationCode/GrpcInterface/Python/examples/SoilPorvSync.py b/ApplicationCode/GrpcInterface/Python/examples/SoilPorvSync.py index fe76c8aa92..cef107e2e3 100644 --- a/ApplicationCode/GrpcInterface/Python/examples/SoilPorvSync.py +++ b/ApplicationCode/GrpcInterface/Python/examples/SoilPorvSync.py @@ -1,10 +1,10 @@ import sys import os -sys.path.insert(1, os.path.join(sys.path[0], '../api')) -import ResInsight +sys.path.insert(1, os.path.join(sys.path[0], '..')) +import rips -resInsight = ResInsight.Instance.find() -case = resInsight.case(id=0) +resInsight = rips.Instance.find() +case = resInsight.project.case(id=0) porvChunks = case.properties.activeCellProperty('STATIC_NATIVE', 'PORV', 0) porvResults = [] diff --git a/ApplicationCode/GrpcInterface/Python/rips/Case.py b/ApplicationCode/GrpcInterface/Python/rips/Case.py index 8e8419d207..17c2c54078 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Case.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Case.py @@ -41,13 +41,13 @@ class Case: def cellCount(self, porosityModel='MATRIX_MODEL'): porosityModelEnum = Case_pb2.PorosityModelType.Value(porosityModel) - request = Case_pb2.CellInfoRequest(request_case=self.request, + request = Case_pb2.CellInfoRequest(case_request=self.request, porosity_model=porosityModel) return self.stub.GetCellCount(request) def cellInfoForActiveCells(self, porosityModel='MATRIX_MODEL'): porosityModelEnum = Case_pb2.PorosityModelType.Value(porosityModel) - request = Case_pb2.CellInfoRequest(request_case=self.request, + request = Case_pb2.CellInfoRequest(case_request=self.request, porosity_model=porosityModel) return self.stub.GetCellInfoForActiveCells(request) diff --git a/ApplicationCode/GrpcInterface/Python/rips/Commands.py b/ApplicationCode/GrpcInterface/Python/rips/Commands.py index 725d5c637b..8af11a0e11 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Commands.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Commands.py @@ -7,37 +7,81 @@ import Commands_pb2_grpc as CmdRpc class Commands: def __init__(self, channel): + self.channel = channel self.commands = CmdRpc.CommandsStub(channel) - - def execute(self, commandParams): + + def execute(self, **commandParams): try: - return self.commands.Execute(commandParams) + return self.commands.Execute(Cmd.CommandParams(**commandParams)) except grpc.RpcError as e: if e.code() == grpc.StatusCode.NOT_FOUND: - print("Command not found") + print("Command not found", commandParams.keys()) else: - print("Other error") + print("Other error", e) - def setTimeStep(self, caseId, timeStep): - return self.execute(Cmd.CommandParams(setTimeStep=Cmd.SetTimeStepParams(caseId=caseId, timeStep=timeStep))) - - def setMainWindowSize(self, width, height): - return self.execute(Cmd.CommandParams(setMainWindowSize=Cmd.SetMainWindowSizeParams(width=width, height=height))) + ######################## + # Case Control Commands + ######################## def openProject(self, path): - return self.execute(Cmd.CommandParams(openProject=Cmd.FilePathRequest(path=path))) + return self.execute(openProject=Cmd.FilePathRequest(path=path)) + + def closeProject(self): + return self.execute(closeProject=Empty()) + + def setStartDir(self, path): + return self.execute(setStartDir=Cmd.FilePathRequest(path=path)) def loadCase(self, path): - commandReply = self.execute(Cmd.CommandParams(loadCase=Cmd.FilePathRequest(path=path))) + commandReply = self.execute(loadCase=Cmd.FilePathRequest(path=path)) assert commandReply.HasField("loadCaseResult") return commandReply.loadCaseResult.id - - def closeProject(self): - return self.execute(Cmd.CommandParams(closeProject=Empty())) + + def replaceCase(self, path, caseId=0): + return self.execute(replaceCase=Cmd.ReplaceCaseRequest(newGridFile=path, + caseId=caseId)) + + def replaceSourceCases(self, gridListFile, caseGroupId=0): + return self.execute(replaceSourceCases=Cmd.ReplaceSourceCasesRequest(gridListFile=gridListFile, + caseGroupId=caseGroupId)) + ################## + # Export Commands + ################## + + def exportSnapshots(self, type = 'ALL', prefix=''): + return self.execute(exportSnapshots=Cmd.ExportSnapshotsRequest(type=type, + prefix=prefix)) def exportWellPaths(self, wellPaths=[], mdStepSize=5.0): if isinstance(wellPaths, str): wellPathArray = [str] elif isinstance(wellPaths, list): wellPathArray = wellPaths - return self.execute(Cmd.CommandParams(exportWellPaths=Cmd.ExportWellPathRequest(wellPathNames=wellPathArray, mdStepSize=mdStepSize))) + return self.execute(exportWellPaths=Cmd.ExportWellPathRequest(wellPathNames=wellPathArray, mdStepSize=mdStepSize)) + + def exportVisibleCells(self, caseId, viewName, exportKeyword='FLUXNUM', visibleActiveCellsValue=1, hiddenActiveCellsValue=0, inactiveCellsValue=0): + return self.execute(exportVisibleCells=Cmd.ExportVisibleCellsRequest(caseId=caseId, + viewName=viewName, + exportKeyword=exportKeyword, + visibleActiveCellsValue=visibleActiveCellsValue, + hiddenActiveCellsValue=hiddenActiveCellsValue, + inactiveCellsValue=inactiveCellsValue)) + def setExportFolder(self, type, path, createFolder=False): + return self.execute(setExportFolder=Cmd.SetExportFolderRequest(type=type, + path=path, + createFolder=createFolder)) + + def runOctaveScript(self, path, cases): + caseIds = [] + for case in cases: + caseIds.append(case.id) + return self.execute(runOctaveScript=Cmd.RunOctaveScriptRequest(path=path, + caseIds=caseIds)) + + def setMainWindowSize(self, width, height): + return self.execute(setMainWindowSize=Cmd.SetMainWindowSizeParams(width=width, height=height)) + + def setTimeStep(self, caseId, timeStep): + return self.execute(setTimeStep=Cmd.SetTimeStepParams(caseId=caseId, timeStep=timeStep)) + + diff --git a/ApplicationCode/GrpcInterface/Python/rips/Project.py b/ApplicationCode/GrpcInterface/Python/rips/Project.py index ac143b9186..98ce325aa5 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Project.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Project.py @@ -3,6 +3,7 @@ import os import sys from .Case import Case +from .Commands import Commands sys.path.insert(1, os.path.join(sys.path[0], '../generated')) From 35059d1d677b8192115dd83b69ab4d551f0c9eb0 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Mon, 3 Jun 2019 21:22:03 +0200 Subject: [PATCH 121/396] #4428 Implement more commands --- .../GrpcInterface/Python/rips/Commands.py | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/ApplicationCode/GrpcInterface/Python/rips/Commands.py b/ApplicationCode/GrpcInterface/Python/rips/Commands.py index 8af11a0e11..415811d407 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Commands.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Commands.py @@ -48,16 +48,33 @@ class Commands: # Export Commands ################## + def exportMultiCaseSnapshots(self, gridListFile): + return self.execute(exportMultiCaseSnapshot=Cmd.ExportMultiCaseRequest(gridListFile=gridListFile)) + def exportSnapshots(self, type = 'ALL', prefix=''): return self.execute(exportSnapshots=Cmd.ExportSnapshotsRequest(type=type, prefix=prefix)) + def exportProperty(self, caseId, timeStep, property, eclipseKeyword=property, undefinedValue=0.0, exportFile=property): + return self.execute(exportProperty=Cmd.ExportPropertyRequest(caseId=caseId, + timeStep=timeStep, + property=property, + eclipseKeyword=eclipseKeyword, + undefinedValue=undefinedValue, + exportFile=exportFile)) + + def exportPropertyInViews(self, caseId, viewNames, undefinedValue): + if isinstance(viewNames, str): + viewNames = [viewNames] + + return self.execute(exportPropertyInViews=Cmd.ExportPropertyInViewsRequest(caseId=caseId, + viewNames=viewNames, + undefinedValue=undefinedValue)) + def exportWellPaths(self, wellPaths=[], mdStepSize=5.0): if isinstance(wellPaths, str): - wellPathArray = [str] - elif isinstance(wellPaths, list): - wellPathArray = wellPaths - return self.execute(exportWellPaths=Cmd.ExportWellPathRequest(wellPathNames=wellPathArray, mdStepSize=mdStepSize)) + wellPaths = [wellpaths] + return self.execute(exportWellPaths=Cmd.ExportWellPathRequest(wellPathNames=wellPaths, mdStepSize=mdStepSize)) def exportVisibleCells(self, caseId, viewName, exportKeyword='FLUXNUM', visibleActiveCellsValue=1, hiddenActiveCellsValue=0, inactiveCellsValue=0): return self.execute(exportVisibleCells=Cmd.ExportVisibleCellsRequest(caseId=caseId, From 5379e9585712b96c89e20f9098b5a54dc8a5616c Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Tue, 4 Jun 2019 08:43:57 +0200 Subject: [PATCH 122/396] Python: more examples + a comparable Octave Example --- .../Python/examples/InputPropTest.py | 32 +++++++++++++++++++ .../Python/examples/InputPropTestParallel.py | 22 +++++++++++++ .../Python/examples/SoilAverage.py | 29 +++++++++++++++++ .../Python/examples/SoilAverageNoComm.py | 16 ++++++++++ .../GrpcInterface/Python/rips/Case.py | 2 +- .../GrpcInterface/Python/rips/Properties.py | 1 + OctavePlugin/OctaveScripts/SoilAverage.m | 12 +++++++ 7 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 ApplicationCode/GrpcInterface/Python/examples/InputPropTest.py create mode 100644 ApplicationCode/GrpcInterface/Python/examples/InputPropTestParallel.py create mode 100644 ApplicationCode/GrpcInterface/Python/examples/SoilAverage.py create mode 100644 ApplicationCode/GrpcInterface/Python/examples/SoilAverageNoComm.py create mode 100644 OctavePlugin/OctaveScripts/SoilAverage.m diff --git a/ApplicationCode/GrpcInterface/Python/examples/InputPropTest.py b/ApplicationCode/GrpcInterface/Python/examples/InputPropTest.py new file mode 100644 index 0000000000..10be14af1e --- /dev/null +++ b/ApplicationCode/GrpcInterface/Python/examples/InputPropTest.py @@ -0,0 +1,32 @@ +import sys +import os +sys.path.insert(1, os.path.join(sys.path[0], '..')) +import rips +import itertools + +resInsight = rips.Instance.find() +#gridCount = resInsight.gridInfo.getGridCount(caseId=0) +#gridDimensions = resInsight.gridInfo.getAllGridDimensions(caseId=0) + +resultChunks = resInsight.properties.activeCellResults(0, 'STATIC_NATIVE', 'PORO', 0) + +results = [] +for resultChunk in resultChunks: + for value in resultChunk.values: + results.append(value) + +print("Transferred " + str(len(results)) + " poro results") + +resultChunks = resInsight.properties.activeCellResults(0, 'STATIC_NATIVE', 'PERMX', 0) + +permres = [] +for resultChunk in resultChunks: + for value in resultChunk.values: + permres.append(value) + +print("Transferred " + str(len(permres)) + " permx results") +poropermx = [] +for (poro, permx) in zip(results, permres): + poropermx.append(poro * permx) + +resInsight.properties.setActiveCellResults(poropermx, 0, 'GENERATED', 'PORO*PERMX2', 0) diff --git a/ApplicationCode/GrpcInterface/Python/examples/InputPropTestParallel.py b/ApplicationCode/GrpcInterface/Python/examples/InputPropTestParallel.py new file mode 100644 index 0000000000..b4a0963d8b --- /dev/null +++ b/ApplicationCode/GrpcInterface/Python/examples/InputPropTestParallel.py @@ -0,0 +1,22 @@ +import sys +import os +sys.path.insert(1, os.path.join(sys.path[0], '..')) +import rips +import itertools + +resInsight = rips.Instance.find() +#gridCount = resInsight.gridInfo.getGridCount(caseId=0) +#gridDimensions = resInsight.gridInfo.getAllGridDimensions(caseId=0) + +poroChunks = resInsight.properties.activeCellResults(0, 'STATIC_NATIVE', 'PORO', 0) +permxChunks = resInsight.properties.activeCellResults(0, 'STATIC_NATIVE', 'PERMX', 0) + +results = [] +for (poroChunk, permxChunk) in zip(poroChunks, permxChunks): + print("Received chunks") + for (poro, permx) in zip(poroChunk.values, permxChunk.values): + results.append(poro * permx) + +print("Transferred " + str(len(results)) + " poro and permx results") + +resInsight.properties.setActiveCellResults(results, 0, 'GENERATED', 'PORO*PERMX2', 0) diff --git a/ApplicationCode/GrpcInterface/Python/examples/SoilAverage.py b/ApplicationCode/GrpcInterface/Python/examples/SoilAverage.py new file mode 100644 index 0000000000..f28299925c --- /dev/null +++ b/ApplicationCode/GrpcInterface/Python/examples/SoilAverage.py @@ -0,0 +1,29 @@ +import sys +import os +sys.path.insert(1, os.path.join(sys.path[0], '..')) +import rips +import itertools +import time + +start = time.time() + +resInsight = rips.Instance.find() +case = resInsight.project.case(id=0) +grid = case.grid(index = 0) + +timeSteps = case.timeSteps() + +averages = [] +for i in range(0, len(timeSteps)): + resultChunks = case.properties.activeCellProperty('DYNAMIC_NATIVE', 'SOIL', i) + mysum = 0.0 + count = 0 + for chunk in resultChunks: + mysum += sum(chunk.values) + count += len(chunk.values) + + averages.append(mysum/count) + +end = time.time() +print("Time elapsed: ", end - start) +print(averages) \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/Python/examples/SoilAverageNoComm.py b/ApplicationCode/GrpcInterface/Python/examples/SoilAverageNoComm.py new file mode 100644 index 0000000000..06b12c79d0 --- /dev/null +++ b/ApplicationCode/GrpcInterface/Python/examples/SoilAverageNoComm.py @@ -0,0 +1,16 @@ +import sys +import os + +averages = [] +for i in range(0, 10): + values = [] + + sum = 0.0 + count = 0 + for j in range(0, 1199516): + sum += j + count += 1 + + averages.append(sum / count) + +print (averages) diff --git a/ApplicationCode/GrpcInterface/Python/rips/Case.py b/ApplicationCode/GrpcInterface/Python/rips/Case.py index 17c2c54078..baad2cd08a 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Case.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Case.py @@ -52,5 +52,5 @@ class Case: return self.stub.GetCellInfoForActiveCells(request) def timeSteps(self): - return self.stub.GetTimeSteps(self.request) + return self.stub.GetTimeSteps(self.request).dates \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/Python/rips/Properties.py b/ApplicationCode/GrpcInterface/Python/rips/Properties.py index 0bf881a88b..4979412233 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Properties.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Properties.py @@ -111,6 +111,7 @@ class Properties: print("Command not found") else: print("Other error", e) + def setGridProperty(self, values, propertyType, propertyName, timeStep, gridIndex = 0, porosityModel = 'MATRIX_MODEL'): propertyTypeEnum = Properties_pb2.PropertyType.Value(propertyType) porosityModelEnum = Case_pb2.PorosityModelType.Value(porosityModel) diff --git a/OctavePlugin/OctaveScripts/SoilAverage.m b/OctavePlugin/OctaveScripts/SoilAverage.m new file mode 100644 index 0000000000..318a3eca1c --- /dev/null +++ b/OctavePlugin/OctaveScripts/SoilAverage.m @@ -0,0 +1,12 @@ +addpath("C:/cmake_build/ResInsightQt5/OctavePlugin"); + +tic(); + +timeSteps = riGetTimeStepDates(0) +disp("Number of time steps: "), disp(size(timeSteps)) +for i = 1:size(timeSteps) + SOIL = riGetActiveCellProperty(0, "SOIL", i); + avg = mean(SOIL) +endfor +elapsed_time = toc(); +disp("Elapsed time: "), disp(elapsed_time) \ No newline at end of file From b6427d84c318eebf4c617edf8a8e04e02ba4d263 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Tue, 4 Jun 2019 10:33:11 +0200 Subject: [PATCH 123/396] gRPC: enable multiple server->client streams of property data at the same time --- .../RiaGrpcPropertiesService.cpp | 33 ++++++++++++------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp b/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp index 0cf295fefc..9e6dd5eb84 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp +++ b/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp @@ -38,6 +38,8 @@ using namespace rips; +#define NUM_CONCURRENT_SERVER_STREAMS 10 + //-------------------------------------------------------------------------------------------------- /// Abstract handler base class for streaming cell results to client /// @@ -63,6 +65,8 @@ public: //-------------------------------------------------------------------------------------------------- Status init(const PropertyRequest* request) { + m_request = request; + int caseId = request->case_request().id(); m_eclipseCase = dynamic_cast(RiaGrpcServiceInterface::findCase(caseId)); @@ -340,19 +344,24 @@ std::vector RiaGrpcPropertiesService::createCallbacks { typedef RiaGrpcPropertiesService Self; - return {new RiaGrpcUnaryCallback( - this, &Self::GetAvailableProperties, &Self::RequestGetAvailableProperties), - new RiaGrpcServerStreamCallback( - this, &Self::GetActiveCellProperty, &Self::RequestGetActiveCellProperty, new RiaActiveCellResultsStateHandler), - new RiaGrpcServerStreamCallback( - this, &Self::GetGridProperty, &Self::RequestGetGridProperty, new RiaGridCellResultsStateHandler), - new RiaGrpcClientStreamCallback( - this, &Self::SetActiveCellProperty, &Self::RequestSetActiveCellProperty, new RiaActiveCellResultsStateHandler(true)), - new RiaGrpcClientStreamCallback( - this, &Self::SetGridProperty, &Self::RequestSetGridProperty, new RiaGridCellResultsStateHandler(true)) - }; -} + std::vector callbacks; + callbacks = { + new RiaGrpcUnaryCallback( + this, &Self::GetAvailableProperties, &Self::RequestGetAvailableProperties), + new RiaGrpcClientStreamCallback( + this, &Self::SetActiveCellProperty, &Self::RequestSetActiveCellProperty, new RiaActiveCellResultsStateHandler(true)), + new RiaGrpcClientStreamCallback( + this, &Self::SetGridProperty, &Self::RequestSetGridProperty, new RiaGridCellResultsStateHandler(true))}; + for (int i = 0; i < NUM_CONCURRENT_SERVER_STREAMS; ++i) + { + callbacks.push_back(new RiaGrpcServerStreamCallback( + this, &Self::GetActiveCellProperty, &Self::RequestGetActiveCellProperty, new RiaActiveCellResultsStateHandler)); + callbacks.push_back(new RiaGrpcServerStreamCallback( + this, &Self::GetGridProperty, &Self::RequestGetGridProperty, new RiaGridCellResultsStateHandler)); + } + return callbacks; +} static bool RiaGrpcPropertiesService_init = RiaGrpcServiceFactory::instance()->registerCreator(typeid(RiaGrpcPropertiesService).hash_code()); \ No newline at end of file From 930abbf02f076c7446c0df63a90f0e6a5f282afa Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Tue, 4 Jun 2019 10:34:31 +0200 Subject: [PATCH 124/396] Python: added tests and made Octave InputPropTest.m general * removed non-general hard-coded grid sizes and added timing to Octave test * added two Pythonbenchmarks (sync and async) for the same test --- .../GrpcInterface/CMakeLists.cmake | 18 +++++++---- .../Python/examples/InputPropTest.py | 32 ------------------- ...oroPermXAsync.py => InputPropTestAsync.py} | 5 +++ .../Python/examples/InputPropTestParallel.py | 22 ------------- ...{PoroPermXSync.py => InputPropTestSync.py} | 6 +++- .../Python/examples/SoilAverage.py | 6 ++-- .../GrpcInterface/Python/rips/Case.py | 2 +- .../GrpcInterface/Python/rips/Properties.py | 3 +- OctavePlugin/OctaveScripts/InputPropTest.m | 11 ++++--- 9 files changed, 34 insertions(+), 71 deletions(-) delete mode 100644 ApplicationCode/GrpcInterface/Python/examples/InputPropTest.py rename ApplicationCode/GrpcInterface/Python/examples/{PoroPermXAsync.py => InputPropTestAsync.py} (84%) delete mode 100644 ApplicationCode/GrpcInterface/Python/examples/InputPropTestParallel.py rename ApplicationCode/GrpcInterface/Python/examples/{PoroPermXSync.py => InputPropTestSync.py} (85%) diff --git a/ApplicationCode/GrpcInterface/CMakeLists.cmake b/ApplicationCode/GrpcInterface/CMakeLists.cmake index aa2c83701c..8fb4c9a53c 100644 --- a/ApplicationCode/GrpcInterface/CMakeLists.cmake +++ b/ApplicationCode/GrpcInterface/CMakeLists.cmake @@ -31,9 +31,13 @@ if (MSVC) # Find Protobuf installation # Looks for protobuf-config.cmake file installed by Protobuf's cmake installation. - set(protobuf_MODULE_COMPATIBLE ON CACHE BOOL "") - find_package(Protobuf CONFIG 3.0 REQUIRED) - message(STATUS "Using protobuf ${protobuf_VERSION}") + set(protobuf_MODULE_COMPATIBLE ON CACHE DBOOL "") + find_package(Protobuf CONFIG 3.0 QUIET) + if (Protobuf_FOUND) + message(STATUS "Using protobuf ${protobuf_VERSION}") + else() + message(FATAL_ERROR "Protocol Buffers not found. This is required to build with gRPC") + endif() # Find gRPC installation # Looks for gRPCConfig.cmake file installed by gRPC's cmake installation. @@ -54,7 +58,7 @@ if (MSVC) else() if (NOT DEFINED GRPC_INSTALL_PREFIX OR NOT EXISTS ${GRPC_INSTALL_PREFIX}) - message(FATAL_ERROR "You need a valid GRPC_INSTALL_PREFIX set to build with GRPC") + message(FATAL_ERROR "You need a valid GRPC_INSTALL_PREFIX set to build with gRPC") endif() set(ENV{PKG_CONFIG_PATH} "${GRPC_INSTALL_PREFIX}/lib/pkgconfig") find_package(PkgConfig REQUIRED) @@ -154,14 +158,16 @@ if (PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) "rips/Instance.py" "examples/CommandExample.py" "examples/CaseInfoStreamingExample.py" - "examples/PoroPermXSync.py" - "examples/PoroPermXAsync.py" "examples/SoilPorvAsync.py" "examples/SoilPorvSync.py" "examples/SelectedCases.py" "examples/AllCases.py" "examples/SetGridProperties.py" "examples/GridInformation.py" + "examples/InputPropTestSync.py" + "examples/InputPropTestAsync.py" + "examples/SoilAverage.py" + "examples/SoilAverageNoComm.py" "tests/test_sample.py" "requirements.txt" "setup.py.cmake" diff --git a/ApplicationCode/GrpcInterface/Python/examples/InputPropTest.py b/ApplicationCode/GrpcInterface/Python/examples/InputPropTest.py deleted file mode 100644 index 10be14af1e..0000000000 --- a/ApplicationCode/GrpcInterface/Python/examples/InputPropTest.py +++ /dev/null @@ -1,32 +0,0 @@ -import sys -import os -sys.path.insert(1, os.path.join(sys.path[0], '..')) -import rips -import itertools - -resInsight = rips.Instance.find() -#gridCount = resInsight.gridInfo.getGridCount(caseId=0) -#gridDimensions = resInsight.gridInfo.getAllGridDimensions(caseId=0) - -resultChunks = resInsight.properties.activeCellResults(0, 'STATIC_NATIVE', 'PORO', 0) - -results = [] -for resultChunk in resultChunks: - for value in resultChunk.values: - results.append(value) - -print("Transferred " + str(len(results)) + " poro results") - -resultChunks = resInsight.properties.activeCellResults(0, 'STATIC_NATIVE', 'PERMX', 0) - -permres = [] -for resultChunk in resultChunks: - for value in resultChunk.values: - permres.append(value) - -print("Transferred " + str(len(permres)) + " permx results") -poropermx = [] -for (poro, permx) in zip(results, permres): - poropermx.append(poro * permx) - -resInsight.properties.setActiveCellResults(poropermx, 0, 'GENERATED', 'PORO*PERMX2', 0) diff --git a/ApplicationCode/GrpcInterface/Python/examples/PoroPermXAsync.py b/ApplicationCode/GrpcInterface/Python/examples/InputPropTestAsync.py similarity index 84% rename from ApplicationCode/GrpcInterface/Python/examples/PoroPermXAsync.py rename to ApplicationCode/GrpcInterface/Python/examples/InputPropTestAsync.py index bab115a613..dff8f645f9 100644 --- a/ApplicationCode/GrpcInterface/Python/examples/PoroPermXAsync.py +++ b/ApplicationCode/GrpcInterface/Python/examples/InputPropTestAsync.py @@ -2,6 +2,7 @@ import sys import os sys.path.insert(1, os.path.join(sys.path[0], '..')) import rips +import time def createResult(poroChunks, permxChunks): for (poroChunk, permxChunk) in zip(poroChunks, permxChunks): @@ -12,6 +13,7 @@ def createResult(poroChunks, permxChunks): resInsight = rips.Instance.find() +start = time.time() case = resInsight.project.case(id=0) poroChunks = case.properties.activeCellProperty('STATIC_NATIVE', 'PORO', 0) @@ -19,4 +21,7 @@ permxChunks = case.properties.activeCellProperty('STATIC_NATIVE', 'PERMX', 0) case.properties.setActiveCellPropertyAsync(createResult(poroChunks, permxChunks), 'GENERATED', 'POROPERMXAS', 0) +end = time.time() +print("Time elapsed: ", end - start) + print("Transferred all results back") \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/Python/examples/InputPropTestParallel.py b/ApplicationCode/GrpcInterface/Python/examples/InputPropTestParallel.py deleted file mode 100644 index b4a0963d8b..0000000000 --- a/ApplicationCode/GrpcInterface/Python/examples/InputPropTestParallel.py +++ /dev/null @@ -1,22 +0,0 @@ -import sys -import os -sys.path.insert(1, os.path.join(sys.path[0], '..')) -import rips -import itertools - -resInsight = rips.Instance.find() -#gridCount = resInsight.gridInfo.getGridCount(caseId=0) -#gridDimensions = resInsight.gridInfo.getAllGridDimensions(caseId=0) - -poroChunks = resInsight.properties.activeCellResults(0, 'STATIC_NATIVE', 'PORO', 0) -permxChunks = resInsight.properties.activeCellResults(0, 'STATIC_NATIVE', 'PERMX', 0) - -results = [] -for (poroChunk, permxChunk) in zip(poroChunks, permxChunks): - print("Received chunks") - for (poro, permx) in zip(poroChunk.values, permxChunk.values): - results.append(poro * permx) - -print("Transferred " + str(len(results)) + " poro and permx results") - -resInsight.properties.setActiveCellResults(results, 0, 'GENERATED', 'PORO*PERMX2', 0) diff --git a/ApplicationCode/GrpcInterface/Python/examples/PoroPermXSync.py b/ApplicationCode/GrpcInterface/Python/examples/InputPropTestSync.py similarity index 85% rename from ApplicationCode/GrpcInterface/Python/examples/PoroPermXSync.py rename to ApplicationCode/GrpcInterface/Python/examples/InputPropTestSync.py index 28bdd25640..5711e4d5b6 100644 --- a/ApplicationCode/GrpcInterface/Python/examples/PoroPermXSync.py +++ b/ApplicationCode/GrpcInterface/Python/examples/InputPropTestSync.py @@ -2,9 +2,10 @@ import sys import os sys.path.insert(1, os.path.join(sys.path[0], '..')) import rips +import time resInsight = rips.Instance.find() - +start = time.time() case = resInsight.project.case(id=0) poroChunks = case.properties.activeCellProperty('STATIC_NATIVE', 'PORO', 0) @@ -25,4 +26,7 @@ for (poro, permx) in zip(poroResults, permxResults): case.properties.setActiveCellProperty(results, 'GENERATED', 'POROPERMXSY', 0) +end = time.time() +print("Time elapsed: ", end - start) + print("Transferred all results back") \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/Python/examples/SoilAverage.py b/ApplicationCode/GrpcInterface/Python/examples/SoilAverage.py index f28299925c..0fff58b1df 100644 --- a/ApplicationCode/GrpcInterface/Python/examples/SoilAverage.py +++ b/ApplicationCode/GrpcInterface/Python/examples/SoilAverage.py @@ -5,16 +5,16 @@ import rips import itertools import time -start = time.time() - resInsight = rips.Instance.find() + +start = time.time() case = resInsight.project.case(id=0) grid = case.grid(index = 0) timeSteps = case.timeSteps() averages = [] -for i in range(0, len(timeSteps)): +for i in range(0, len(timeSteps.dates)): resultChunks = case.properties.activeCellProperty('DYNAMIC_NATIVE', 'SOIL', i) mysum = 0.0 count = 0 diff --git a/ApplicationCode/GrpcInterface/Python/rips/Case.py b/ApplicationCode/GrpcInterface/Python/rips/Case.py index baad2cd08a..17c2c54078 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Case.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Case.py @@ -52,5 +52,5 @@ class Case: return self.stub.GetCellInfoForActiveCells(request) def timeSteps(self): - return self.stub.GetTimeSteps(self.request).dates + return self.stub.GetTimeSteps(self.request) \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/Python/rips/Properties.py b/ApplicationCode/GrpcInterface/Python/rips/Properties.py index 4979412233..21aec217cd 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Properties.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Properties.py @@ -74,7 +74,8 @@ class Properties: time_step = timeStep, grid_index = gridIndex, porosity_model = porosityModelEnum) - return self.propertiesStub.GetGridProperty(request) + for chunk in self.propertiesStub.GetGridProperty(request): + yield chunk def setActiveCellPropertyAsync(self, values_iterator, propertyType, propertyName, timeStep, gridIndex = 0, porosityModel = 'MATRIX_MODEL'): propertyTypeEnum = Properties_pb2.PropertyType.Value(propertyType) diff --git a/OctavePlugin/OctaveScripts/InputPropTest.m b/OctavePlugin/OctaveScripts/InputPropTest.m index 811528b89d..75c8bcec3f 100644 --- a/OctavePlugin/OctaveScripts/InputPropTest.m +++ b/OctavePlugin/OctaveScripts/InputPropTest.m @@ -1,12 +1,13 @@ addpath("/home/builder/Projects/ResInsightBuildDir/OctavePlugin"); + +tic(); PORO = riGetActiveCellProperty("PORO"); PERMX = riGetActiveCellProperty("PERMX"); IJK = riGetMainGridDimensions(); GENERATED = PORO .* PERMX; -GENERATED(10:IJK(1):IJK(1)*IJK(2)*IJK(3)) = 100; -GENERATED(10*IJK(1):1:11*IJK(1)) = 100; -GENERATED(11*IJK(1):1:12*IJK(1)) = 100; -GENERATED(12*IJK(1):1:13*IJK(1)) = 100; -riSetActiveCellProperty(GENERATED, "PORO*PERMX"); \ No newline at end of file +riSetActiveCellProperty(GENERATED, "PORO*PERMX"); + +elapsed_time = toc(); +disp("Elapsed time: "), disp(elapsed_time) \ No newline at end of file From 3530c8b3de876dba433c45732fc93556f856526b Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Tue, 4 Jun 2019 12:59:06 +0200 Subject: [PATCH 125/396] #4460 #4424 Adding Exit() to the gRPC interface plus implemented test framework --- .../Application/RiaConsoleApplication.cpp | 23 ++++++++- .../Application/RiaConsoleApplication.h | 11 ++++ .../Application/RiaGuiApplication.cpp | 7 ++- .../GrpcInterface/CMakeLists.cmake | 12 +++-- .../GrpcProtos/{AppInfo.proto => App.proto} | 3 +- .../Python/rips/{AppInfo.py => App.py} | 13 ++--- .../GrpcInterface/Python/rips/Case.py | 2 +- .../GrpcInterface/Python/rips/Instance.py | 8 +-- .../GrpcInterface/Python/rips/Project.py | 4 ++ .../GrpcInterface/Python/tests/conftest.py | 16 ++++++ .../GrpcInterface/Python/tests/dataroot.py | 1 + .../GrpcInterface/Python/tests/test_cases.py | 19 +++++++ .../GrpcInterface/Python/tests/test_sample.py | 51 ------------------- ...pInfoService.cpp => RiaGrpcAppService.cpp} | 23 ++++++--- ...pcAppInfoService.h => RiaGrpcAppService.h} | 5 +- .../GrpcInterface/RiaGrpcServer.cpp | 23 +++++++++ ApplicationCode/GrpcInterface/RiaGrpcServer.h | 4 +- 17 files changed, 146 insertions(+), 79 deletions(-) rename ApplicationCode/GrpcInterface/GrpcProtos/{AppInfo.proto => App.proto} (79%) rename ApplicationCode/GrpcInterface/Python/rips/{AppInfo.py => App.py} (76%) create mode 100644 ApplicationCode/GrpcInterface/Python/tests/conftest.py create mode 100644 ApplicationCode/GrpcInterface/Python/tests/dataroot.py create mode 100644 ApplicationCode/GrpcInterface/Python/tests/test_cases.py delete mode 100644 ApplicationCode/GrpcInterface/Python/tests/test_sample.py rename ApplicationCode/GrpcInterface/{RiaGrpcAppInfoService.cpp => RiaGrpcAppService.cpp} (63%) rename ApplicationCode/GrpcInterface/{RiaGrpcAppInfoService.h => RiaGrpcAppService.h} (84%) diff --git a/ApplicationCode/Application/RiaConsoleApplication.cpp b/ApplicationCode/Application/RiaConsoleApplication.cpp index 9a0f316fbd..153ca817b9 100644 --- a/ApplicationCode/Application/RiaConsoleApplication.cpp +++ b/ApplicationCode/Application/RiaConsoleApplication.cpp @@ -345,7 +345,10 @@ void RiaConsoleApplication::showErrorMessage(const QString& errMsg) void RiaConsoleApplication::launchGrpcServer() { #ifdef ENABLE_GRPC - m_grpcServer->run(); + m_grpcServer->runInThread(); + m_idleTimer = new QTimer(this); + connect(m_idleTimer, SIGNAL(timeout()), this, SLOT(runIdleProcessing())); + m_idleTimer->start(0); #endif } @@ -381,3 +384,21 @@ void RiaConsoleApplication::onProjectClosed() processEvents(); } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaConsoleApplication::runIdleProcessing() +{ +#ifdef ENABLE_GRPC + if (RiaGrpcServer::receivedExitRequest()) + { + m_grpcServer->quit(); + QCoreApplication::quit(); + } + else + { + m_grpcServer->processAllQueuedRequests(); + } +#endif +} \ No newline at end of file diff --git a/ApplicationCode/Application/RiaConsoleApplication.h b/ApplicationCode/Application/RiaConsoleApplication.h index 77100d4ab8..a6fb4e939a 100644 --- a/ApplicationCode/Application/RiaConsoleApplication.h +++ b/ApplicationCode/Application/RiaConsoleApplication.h @@ -21,6 +21,9 @@ #include +#include +#include + namespace cvf { class ProgramOptions; @@ -48,5 +51,13 @@ protected: void onProjectOpeningError(const QString& errMsg) override; void onProjectOpened(); void onProjectClosed(); + +private slots: + void runIdleProcessing(); + +private: +#ifdef ENABLE_GRPC + QPointer m_idleTimer; +#endif }; diff --git a/ApplicationCode/Application/RiaGuiApplication.cpp b/ApplicationCode/Application/RiaGuiApplication.cpp index b8e2cdfaa1..42a24b108b 100644 --- a/ApplicationCode/Application/RiaGuiApplication.cpp +++ b/ApplicationCode/Application/RiaGuiApplication.cpp @@ -1687,7 +1687,12 @@ void RiaGuiApplication::slotWorkerProcessFinished(int exitCode, QProcess::ExitSt void RiaGuiApplication::runIdleProcessing() { #ifdef ENABLE_GRPC - if (!caf::ProgressInfoStatic::isRunning()) + if (RiaGrpcServer::receivedExitRequest()) + { + m_grpcServer->quit(); + QCoreApplication::quit(); + } + else if (!caf::ProgressInfoStatic::isRunning()) { m_grpcServer->processAllQueuedRequests(); } diff --git a/ApplicationCode/GrpcInterface/CMakeLists.cmake b/ApplicationCode/GrpcInterface/CMakeLists.cmake index 8fb4c9a53c..a555057fa6 100644 --- a/ApplicationCode/GrpcInterface/CMakeLists.cmake +++ b/ApplicationCode/GrpcInterface/CMakeLists.cmake @@ -9,7 +9,7 @@ set ( SOURCE_GROUP_HEADER_FILES ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcGridService.h ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcProjectService.h ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcCommandService.h - ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcAppInfoService.h + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcAppService.h ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcPropertiesService.h ) @@ -20,7 +20,7 @@ set ( SOURCE_GROUP_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcGridService.cpp ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcProjectService.cpp ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcCommandService.cpp - ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcAppInfoService.cpp + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcAppService.cpp ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcPropertiesService.cpp ) @@ -79,7 +79,7 @@ set(PROTO_FILES "Case" "Project" "Commands" - "AppInfo" + "App" "Properties" "Grid" ) @@ -149,7 +149,7 @@ if (PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) ${GRPC_PYTHON_GENERATED_SOURCES} "generated/RiaVersionInfo.py" "rips/__init__.py" - "rips/AppInfo.py" + "rips/App.py" "rips/Case.py" "rips/Commands.py" "rips/Grid.py" @@ -168,7 +168,9 @@ if (PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) "examples/InputPropTestAsync.py" "examples/SoilAverage.py" "examples/SoilAverageNoComm.py" - "tests/test_sample.py" + "tests/test_cases.py" + "tests/conftest.py" + "tests/dataroot.py" "requirements.txt" "setup.py.cmake" "README.md" diff --git a/ApplicationCode/GrpcInterface/GrpcProtos/AppInfo.proto b/ApplicationCode/GrpcInterface/GrpcProtos/App.proto similarity index 79% rename from ApplicationCode/GrpcInterface/GrpcProtos/AppInfo.proto rename to ApplicationCode/GrpcInterface/GrpcProtos/App.proto index fd5e18e156..e2e7aa7c7c 100644 --- a/ApplicationCode/GrpcInterface/GrpcProtos/AppInfo.proto +++ b/ApplicationCode/GrpcInterface/GrpcProtos/App.proto @@ -4,8 +4,9 @@ package rips; import "Empty.proto"; -service AppInfo { +service App { rpc GetVersion(Empty) returns (Version) {} + rpc Exit(Empty) returns (Empty) {} } message Version { diff --git a/ApplicationCode/GrpcInterface/Python/rips/AppInfo.py b/ApplicationCode/GrpcInterface/Python/rips/App.py similarity index 76% rename from ApplicationCode/GrpcInterface/Python/rips/AppInfo.py rename to ApplicationCode/GrpcInterface/Python/rips/App.py index 8ec1fdd80e..fcf6ec2126 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/AppInfo.py +++ b/ApplicationCode/GrpcInterface/Python/rips/App.py @@ -6,14 +6,14 @@ sys.path.insert(1, os.path.join(sys.path[0], '../generated')) from Empty_pb2 import Empty -import AppInfo_pb2 -import AppInfo_pb2_grpc +import App_pb2 +import App_pb2_grpc -class AppInfo: +class App: def __init__(self, channel): - self.appInfo = AppInfo_pb2_grpc.AppInfoStub(channel) + self.app = App_pb2_grpc.AppStub(channel) def versionMessage(self): - return self.appInfo.GetVersion(Empty()) + return self.app.GetVersion(Empty()) def majorVersion(self): return self.versionMessage().major_version def minorVersion(self): @@ -22,4 +22,5 @@ class AppInfo: return self.versionMessage().patch_version def versionString(self): return str(self.majorVersion()) + "." + str(self.minorVersion()) + "." + str(self.patchVersion()) - + def exit(self): + return self.app.Exit(Empty()) diff --git a/ApplicationCode/GrpcInterface/Python/rips/Case.py b/ApplicationCode/GrpcInterface/Python/rips/Case.py index 17c2c54078..18a1889333 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Case.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Case.py @@ -20,7 +20,7 @@ class Case: self.type = info.type self.properties = Properties(self) self.request = Case_pb2.CaseRequest(id=self.id) - + def gridCount(self): try: return self.stub.GetGridCount(self.request).count diff --git a/ApplicationCode/GrpcInterface/Python/rips/Instance.py b/ApplicationCode/GrpcInterface/Python/rips/Instance.py index d10ea1fdf9..231abed2d9 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Instance.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Instance.py @@ -8,7 +8,7 @@ sys.path.insert(1, os.path.join(sys.path[0], '../generated')) import RiaVersionInfo -from .AppInfo import AppInfo +from .App import App from .Commands import Commands from .Project import Project @@ -60,10 +60,10 @@ class Instance: self.channel = grpc.insecure_channel(location) # Main version check package - self.appInfo = AppInfo(self.channel) + self.app = App(self.channel) try: - majorVersionOk = self.appInfo.majorVersion() == int(RiaVersionInfo.RESINSIGHT_MAJOR_VERSION) - minorVersionOk = self.appInfo.minorVersion() == int(RiaVersionInfo.RESINSIGHT_MINOR_VERSION) + majorVersionOk = self.app.majorVersion() == int(RiaVersionInfo.RESINSIGHT_MAJOR_VERSION) + minorVersionOk = self.app.minorVersion() == int(RiaVersionInfo.RESINSIGHT_MINOR_VERSION) if not (majorVersionOk and minorVersionOk): raise Exception('Version of ResInsight does not match version of Python API') except grpc.RpcError as e: diff --git a/ApplicationCode/GrpcInterface/Python/rips/Project.py b/ApplicationCode/GrpcInterface/Python/rips/Project.py index 98ce325aa5..27cddbfdb3 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Project.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Project.py @@ -44,3 +44,7 @@ class Project: return case except grpc.RpcError as e: return None + + def loadCase(self, path): + return Commands(self.channel).loadCase(path) + diff --git a/ApplicationCode/GrpcInterface/Python/tests/conftest.py b/ApplicationCode/GrpcInterface/Python/tests/conftest.py new file mode 100644 index 0000000000..6ab41cac64 --- /dev/null +++ b/ApplicationCode/GrpcInterface/Python/tests/conftest.py @@ -0,0 +1,16 @@ +import pytest +import sys +import os + +sys.path.insert(1, os.path.join(sys.path[0], '..')) +import rips + +instance = rips.Instance.launch() + +@pytest.fixture +def rips_instance(): + return instance + +def pytest_unconfigure(config): + print("Telling ResInsight to Exit") + instance.app.exit() \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/Python/tests/dataroot.py b/ApplicationCode/GrpcInterface/Python/tests/dataroot.py new file mode 100644 index 0000000000..16c2b32354 --- /dev/null +++ b/ApplicationCode/GrpcInterface/Python/tests/dataroot.py @@ -0,0 +1 @@ +PATH = "../../../TestModels" \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/Python/tests/test_cases.py b/ApplicationCode/GrpcInterface/Python/tests/test_cases.py new file mode 100644 index 0000000000..6f718008f6 --- /dev/null +++ b/ApplicationCode/GrpcInterface/Python/tests/test_cases.py @@ -0,0 +1,19 @@ +import sys +import os + +sys.path.insert(1, os.path.join(sys.path[0], '..')) +import rips + +import dataroot + +def test_Launch(rips_instance): + assert(rips_instance is not None) + +def test_EmptyProject(rips_instance): + cases = rips_instance.project.cases() + assert(len(cases) is 0) + +def test_OneCase(rips_instance): + case = rips_instance.project.loadCase(dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID") + cases = rips_instance.project.cases() + assert(len(cases) is 1) \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/Python/tests/test_sample.py b/ApplicationCode/GrpcInterface/Python/tests/test_sample.py deleted file mode 100644 index 8a0206c83c..0000000000 --- a/ApplicationCode/GrpcInterface/Python/tests/test_sample.py +++ /dev/null @@ -1,51 +0,0 @@ - -import os, sys - -# Add the 'api' path to system path to be able to import modules from the 'api' folder -# python current working directory must be 'tests' -sys.path.insert(1, os.path.join(sys.path[0], '..\\api')) - -import ResInsight - -resInsight = ResInsight.Instance() - - -# content of test_sample.py -def getActiveCellCount(caseId): - activeCellInfoChunks = resInsight.gridInfo.streamActiveCellInfo(caseId) - - receivedActiveCells = [] - for activeCellChunk in activeCellInfoChunks: - for activeCell in activeCellChunk.data: - receivedActiveCells.append(activeCell) - return len(receivedActiveCells) - -def myOpenProject(filepath): - resInsight = ResInsight.Instance() - #resInsight.commands.setMainWindowSize(width=800, height=500) - resInsight.commands.openProject(filepath) - -def test_openProjectAndCountCells(): - testRepositoryRoot = "d:\\gitroot-ceesol\\ResInsight-regression-test" - - #casePath = testRepositoryRoot + "\\ModelData\\TEST10K_FLT_LGR_NNC\\TEST10K_FLT_LGR_NNC.EGRID" - #openEclipseCase(casePath) - -# projectPath = testRepositoryRoot + "\\ProjectFiles\\ProjectFilesSmallTests\\TestCase_10K_Complete\\RegressionTest.rsp" -# projectPath = testRepositoryRoot + "\\ProjectFiles\\ProjectFilesSmallTests\\TestCase_Norne\\RegressionTest.rsp" - projectPath = testRepositoryRoot + "\\ProjectFiles\\ProjectFilesSmallTests\\TestCase_10K_Watertight\\RegressionTest.rsp" - myOpenProject(projectPath) - - assert getActiveCellCount(0) == 11125 - - - -def test_openCaseAndCountCells(): - testRepositoryRoot = "d:\\gitroot-ceesol\\ResInsight-regression-test" - - casePath = testRepositoryRoot + "\\ModelData\\TEST10K_FLT_LGR_NNC\\TEST10K_FLT_LGR_NNC.EGRID" - resInsight.commands.loadCase(casePath) - - assert getActiveCellCount(0) == 11125 - - resInsight.commands.closeProject() diff --git a/ApplicationCode/GrpcInterface/RiaGrpcAppInfoService.cpp b/ApplicationCode/GrpcInterface/RiaGrpcAppService.cpp similarity index 63% rename from ApplicationCode/GrpcInterface/RiaGrpcAppInfoService.cpp rename to ApplicationCode/GrpcInterface/RiaGrpcAppService.cpp index b0d86041ef..bd0f452199 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcAppInfoService.cpp +++ b/ApplicationCode/GrpcInterface/RiaGrpcAppService.cpp @@ -15,15 +15,16 @@ // for more details. // ////////////////////////////////////////////////////////////////////////////////// -#include "RiaGrpcAppInfoService.h" +#include "RiaGrpcAppService.h" #include "RiaVersionInfo.h" #include "RiaGrpcCallbacks.h" +#include "RiaGrpcServer.h" //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -grpc::Status RiaGrpcAppInfoService::GetVersion(grpc::ServerContext* context, const rips::Empty* request, rips::Version* reply) +grpc::Status RiaGrpcAppService::GetVersion(grpc::ServerContext* context, const rips::Empty* request, rips::Version* reply) { reply->set_major_version(RESINSIGHT_MAJOR_VERSION); reply->set_minor_version(RESINSIGHT_MINOR_VERSION); @@ -34,11 +35,21 @@ grpc::Status RiaGrpcAppInfoService::GetVersion(grpc::ServerContext* context, con //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::vector RiaGrpcAppInfoService::createCallbacks() +grpc::Status RiaGrpcAppService::Exit(grpc::ServerContext* context, const rips::Empty* request, rips::Empty* reply) { - typedef RiaGrpcAppInfoService Self; - return { new RiaGrpcUnaryCallback(this, &Self::GetVersion, &Self::RequestGetVersion) }; + RiaGrpcServer::setReceivedExitRequest(); + return grpc::Status::OK; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RiaGrpcAppService::createCallbacks() +{ + typedef RiaGrpcAppService Self; + return { new RiaGrpcUnaryCallback(this, &Self::GetVersion, &Self::RequestGetVersion), + new RiaGrpcUnaryCallback(this, &Self::Exit, &Self::RequestExit) }; } static bool RiaGrpcAppInfoService_init = - RiaGrpcServiceFactory::instance()->registerCreator(typeid(RiaGrpcAppInfoService).hash_code()); + RiaGrpcServiceFactory::instance()->registerCreator(typeid(RiaGrpcAppService).hash_code()); diff --git a/ApplicationCode/GrpcInterface/RiaGrpcAppInfoService.h b/ApplicationCode/GrpcInterface/RiaGrpcAppService.h similarity index 84% rename from ApplicationCode/GrpcInterface/RiaGrpcAppInfoService.h rename to ApplicationCode/GrpcInterface/RiaGrpcAppService.h index a81399fd0a..1882b7664d 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcAppInfoService.h +++ b/ApplicationCode/GrpcInterface/RiaGrpcAppService.h @@ -21,7 +21,7 @@ #include "RiaGrpcServiceInterface.h" -#include "AppInfo.grpc.pb.h" +#include "App.grpc.pb.h" #include #include @@ -39,10 +39,11 @@ class PdmValueField; class RiaGrpcCallbackInterface; -class RiaGrpcAppInfoService : public rips::AppInfo::AsyncService, public RiaGrpcServiceInterface +class RiaGrpcAppService : public rips::App::AsyncService, public RiaGrpcServiceInterface { public: grpc::Status GetVersion(grpc::ServerContext* context, const rips::Empty* request, rips::Version* reply) override; + grpc::Status Exit(grpc::ServerContext* context, const rips::Empty* request, rips::Empty* reply) override; std::vector createCallbacks() override; }; diff --git a/ApplicationCode/GrpcInterface/RiaGrpcServer.cpp b/ApplicationCode/GrpcInterface/RiaGrpcServer.cpp index 44c7a0da0c..ddd1ff9082 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcServer.cpp +++ b/ApplicationCode/GrpcInterface/RiaGrpcServer.cpp @@ -323,6 +323,11 @@ void RiaGrpcServer::runInThread() m_serverImpl->runInThread(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RiaGrpcServer::s_receivedExitRequest = false; + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -373,3 +378,21 @@ int RiaGrpcServer::findAvailablePortNumber(int defaultPortNumber) } return -1; } + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaGrpcServer::setReceivedExitRequest() +{ + RiaLogging::info("Received Exit Request"); + s_receivedExitRequest = true; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RiaGrpcServer::receivedExitRequest() +{ + return s_receivedExitRequest; +} diff --git a/ApplicationCode/GrpcInterface/RiaGrpcServer.h b/ApplicationCode/GrpcInterface/RiaGrpcServer.h index bb74ced170..e6c42e3d7b 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcServer.h +++ b/ApplicationCode/GrpcInterface/RiaGrpcServer.h @@ -44,10 +44,12 @@ public: void processAllQueuedRequests(); void quit(); static int findAvailablePortNumber(int defaultPortNumber); - + static void setReceivedExitRequest(); + static bool receivedExitRequest(); private: void initialize(); private: RiaGrpcServerImpl* m_serverImpl; + static bool s_receivedExitRequest; }; \ No newline at end of file From 8bbbaec9df435fd5747bacece1bcb2ec5be362c6 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Tue, 4 Jun 2019 13:26:30 +0200 Subject: [PATCH 126/396] gRPC: multi-case test --- .../GrpcInterface/Python/tests/test_cases.py | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/ApplicationCode/GrpcInterface/Python/tests/test_cases.py b/ApplicationCode/GrpcInterface/Python/tests/test_cases.py index 6f718008f6..b5c0ed24d7 100644 --- a/ApplicationCode/GrpcInterface/Python/tests/test_cases.py +++ b/ApplicationCode/GrpcInterface/Python/tests/test_cases.py @@ -16,4 +16,28 @@ def test_EmptyProject(rips_instance): def test_OneCase(rips_instance): case = rips_instance.project.loadCase(dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID") cases = rips_instance.project.cases() - assert(len(cases) is 1) \ No newline at end of file + assert(len(cases) is 1) + +def test_MultipleCases(rips_instance): + casePaths = [] + casePaths.append(dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID") + casePaths.append(dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID") + casePaths.append(dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID") + casePaths.append(dataroot.PATH + "/case_with_10_timesteps/Real0/BRUGGE_0000.EGRID") + casePaths.append(dataroot.PATH + "/case_with_10_timesteps/Real10/BRUGGE_0010.EGRID") + casePaths.append(dataroot.PATH + "/case_with_10_timesteps/Real20/BRUGGE_0020.EGRID") + + caseNames = [] + for casePath in casePaths: + caseName = os.path.splitext(os.path.basename(casePath))[0] + caseNames.append(caseName) + rips_instance.project.loadCase(path=casePath) + + print(caseNames) + cases = rips_instance.project.cases() + for case in cases: + print (case.index, case.name) + assert(len(cases) == len(caseNames)) + for i, caseName in enumerate(caseNames): + print(i, caseName) + assert(caseName == cases[i].name) From 196e7df0faa750fdb3367dd4f9c478d7990818f5 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Tue, 4 Jun 2019 20:35:30 +0200 Subject: [PATCH 127/396] #4460 Further gRPC/Python tests --- .../GrpcInterface/Python/rips/Commands.py | 4 +- .../GrpcInterface/Python/rips/Instance.py | 11 ++--- .../GrpcInterface/Python/rips/Project.py | 7 ++++ .../GrpcInterface/Python/tests/conftest.py | 7 ++++ .../GrpcInterface/Python/tests/test_cases.py | 41 +++++++++++++------ .../GrpcInterface/Python/tests/test_grids.py | 17 ++++++++ .../Python/tests/test_properties.py | 23 +++++++++++ 7 files changed, 91 insertions(+), 19 deletions(-) create mode 100644 ApplicationCode/GrpcInterface/Python/tests/test_grids.py create mode 100644 ApplicationCode/GrpcInterface/Python/tests/test_properties.py diff --git a/ApplicationCode/GrpcInterface/Python/rips/Commands.py b/ApplicationCode/GrpcInterface/Python/rips/Commands.py index 415811d407..c0f6939834 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Commands.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Commands.py @@ -2,8 +2,10 @@ import grpc import os import sys +from Empty_pb2 import Empty import Commands_pb2 as Cmd import Commands_pb2_grpc as CmdRpc +from .Case import Case class Commands: def __init__(self, channel): @@ -35,7 +37,7 @@ class Commands: def loadCase(self, path): commandReply = self.execute(loadCase=Cmd.FilePathRequest(path=path)) assert commandReply.HasField("loadCaseResult") - return commandReply.loadCaseResult.id + return Case(self.channel, commandReply.loadCaseResult.id) def replaceCase(self, path, caseId=0): return self.execute(replaceCase=Cmd.ReplaceCaseRequest(newGridFile=path, diff --git a/ApplicationCode/GrpcInterface/Python/rips/Instance.py b/ApplicationCode/GrpcInterface/Python/rips/Instance.py index 231abed2d9..c69d154215 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Instance.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Instance.py @@ -20,16 +20,17 @@ class Instance: return s.connect_ex(('localhost', port)) == 0 @staticmethod - def launch(): + def launch(resInsightExecutable = ''): port = 50051 portEnv = os.environ.get('RESINSIGHT_GRPC_PORT') if portEnv: port = int(portEnv) - resInsightExecutable = os.environ.get('RESINSIGHT_EXECUTABLE') - if resInsightExecutable is None: - print('Error: Could not launch any ResInsight instances because RESINSIGHT_EXECUTABLE is not set') - return None + if not resInsightExecutable: + resInsightExecutable = os.environ.get('RESINSIGHT_EXECUTABLE') + if not resInsightExecutable: + print('Error: Could not launch any ResInsight instances because RESINSIGHT_EXECUTABLE is not set') + return None while Instance.is_port_in_use(port): port += 1 diff --git a/ApplicationCode/GrpcInterface/Python/rips/Project.py b/ApplicationCode/GrpcInterface/Python/rips/Project.py index 27cddbfdb3..797618f582 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Project.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Project.py @@ -15,6 +15,13 @@ class Project: def __init__(self, channel): self.channel = channel self.project = Project_pb2_grpc.ProjectStub(channel) + + def open(self, path): + Commands(self.channel).openProject(path) + return self + + def close(self): + Commands(self.channel).closeProject() def selectedCases(self): caseInfos = self.project.GetSelectedCases(Empty()) diff --git a/ApplicationCode/GrpcInterface/Python/tests/conftest.py b/ApplicationCode/GrpcInterface/Python/tests/conftest.py index 6ab41cac64..7856c359f3 100644 --- a/ApplicationCode/GrpcInterface/Python/tests/conftest.py +++ b/ApplicationCode/GrpcInterface/Python/tests/conftest.py @@ -7,10 +7,17 @@ import rips instance = rips.Instance.launch() +if (not instance): + exit(1) + @pytest.fixture def rips_instance(): return instance +@pytest.fixture +def initializeTest(): + instance.project.close() + def pytest_unconfigure(config): print("Telling ResInsight to Exit") instance.app.exit() \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/Python/tests/test_cases.py b/ApplicationCode/GrpcInterface/Python/tests/test_cases.py index b5c0ed24d7..cabb349cb1 100644 --- a/ApplicationCode/GrpcInterface/Python/tests/test_cases.py +++ b/ApplicationCode/GrpcInterface/Python/tests/test_cases.py @@ -6,26 +6,25 @@ import rips import dataroot -def test_Launch(rips_instance): +def test_Launch(rips_instance, initializeTest): assert(rips_instance is not None) -def test_EmptyProject(rips_instance): +def test_EmptyProject(rips_instance, initializeTest): cases = rips_instance.project.cases() assert(len(cases) is 0) -def test_OneCase(rips_instance): +def test_OneCase(rips_instance, initializeTest): case = rips_instance.project.loadCase(dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID") + assert(case.name == "TEST10K_FLT_LGR_NNC") + assert(case.id == 0) cases = rips_instance.project.cases() assert(len(cases) is 1) -def test_MultipleCases(rips_instance): +def test_MultipleCases(rips_instance, initializeTest): casePaths = [] casePaths.append(dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID") - casePaths.append(dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID") - casePaths.append(dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID") - casePaths.append(dataroot.PATH + "/case_with_10_timesteps/Real0/BRUGGE_0000.EGRID") - casePaths.append(dataroot.PATH + "/case_with_10_timesteps/Real10/BRUGGE_0010.EGRID") - casePaths.append(dataroot.PATH + "/case_with_10_timesteps/Real20/BRUGGE_0020.EGRID") + casePaths.append(dataroot.PATH + "/Case_with_10_timesteps/Real0/BRUGGE_0000.EGRID") + casePaths.append(dataroot.PATH + "/Case_with_10_timesteps/Real30/BRUGGE_0030.EGRID") caseNames = [] for casePath in casePaths: @@ -33,11 +32,27 @@ def test_MultipleCases(rips_instance): caseNames.append(caseName) rips_instance.project.loadCase(path=casePath) - print(caseNames) cases = rips_instance.project.cases() - for case in cases: - print (case.index, case.name) assert(len(cases) == len(caseNames)) for i, caseName in enumerate(caseNames): - print(i, caseName) assert(caseName == cases[i].name) + +def test_10k(rips_instance, initializeTest): + casePath = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID" + case = rips_instance.project.loadCase(path=casePath) + assert(case.gridCount() == 2) + cellCountInfo = case.cellCount() + assert(cellCountInfo.active_cell_count == 11125) + assert(cellCountInfo.reservoir_cell_count == 316224) + timeSteps = case.timeSteps() + assert(len(timeSteps.dates) == 9) + +def test_brugge_0010(rips_instance, initializeTest): + casePath = dataroot.PATH + "/Case_with_10_timesteps/Real10/BRUGGE_0010.EGRID" + case = rips_instance.project.loadCase(path=casePath) + assert(case.gridCount() == 1) + cellCountInfo = case.cellCount() + assert(cellCountInfo.active_cell_count == 43374) + assert(cellCountInfo.reservoir_cell_count == 60048) + timeSteps = case.timeSteps() + assert(len(timeSteps.dates) == 11) \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/Python/tests/test_grids.py b/ApplicationCode/GrpcInterface/Python/tests/test_grids.py new file mode 100644 index 0000000000..cb75df14d4 --- /dev/null +++ b/ApplicationCode/GrpcInterface/Python/tests/test_grids.py @@ -0,0 +1,17 @@ +import sys +import os + +sys.path.insert(1, os.path.join(sys.path[0], '..')) +import rips + +import dataroot + +def test_10k(rips_instance, initializeTest): + casePath = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID" + case = rips_instance.project.loadCase(path=casePath) + assert(case.gridCount() == 2) + grid = case.grid(index=0) + dimensions = grid.dimensions() + assert(dimensions.i == 90) + assert(dimensions.j == 96) + assert(dimensions.k == 36) diff --git a/ApplicationCode/GrpcInterface/Python/tests/test_properties.py b/ApplicationCode/GrpcInterface/Python/tests/test_properties.py new file mode 100644 index 0000000000..e656bd2ee4 --- /dev/null +++ b/ApplicationCode/GrpcInterface/Python/tests/test_properties.py @@ -0,0 +1,23 @@ +import sys +import os +import pytest + +sys.path.insert(1, os.path.join(sys.path[0], '..')) +import rips + +import dataroot + +def test_10k(rips_instance, initializeTest): + casePath = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID" + case = rips_instance.project.loadCase(path=casePath) + + resultChunks = case.properties.activeCellProperty('DYNAMIC_NATIVE', 'SOIL', 1) + mysum = 0.0 + count = 0 + for chunk in resultChunks: + mysum += sum(chunk.values) + count += len(chunk.values) + average = mysum / count + assert(mysum == pytest.approx(621.768, abs=0.001)) + assert(average != pytest.approx(0.0158893, abs=0.0000001)) + assert(average == pytest.approx(0.0558893, abs=0.0000001)) From 5b39860a414e5a6fe2a2b9293fc78f844e7e73db Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Wed, 5 Jun 2019 08:59:30 +0200 Subject: [PATCH 128/396] #4460 Improved error messages for pytest --- ApplicationCode/GrpcInterface/Python/rips/Instance.py | 3 ++- ApplicationCode/GrpcInterface/Python/tests/conftest.py | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ApplicationCode/GrpcInterface/Python/rips/Instance.py b/ApplicationCode/GrpcInterface/Python/rips/Instance.py index c69d154215..81a31ed5c2 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Instance.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Instance.py @@ -29,7 +29,8 @@ class Instance: if not resInsightExecutable: resInsightExecutable = os.environ.get('RESINSIGHT_EXECUTABLE') if not resInsightExecutable: - print('Error: Could not launch any ResInsight instances because RESINSIGHT_EXECUTABLE is not set') + print('ERROR: Could not launch ResInsight because the environment variable' + ' RESINSIGHT_EXECUTABLE is not set') return None while Instance.is_port_in_use(port): diff --git a/ApplicationCode/GrpcInterface/Python/tests/conftest.py b/ApplicationCode/GrpcInterface/Python/tests/conftest.py index 7856c359f3..ac4297201a 100644 --- a/ApplicationCode/GrpcInterface/Python/tests/conftest.py +++ b/ApplicationCode/GrpcInterface/Python/tests/conftest.py @@ -8,6 +8,7 @@ import rips instance = rips.Instance.launch() if (not instance): + print("A ResInsight instance is required for running the tests") exit(1) @pytest.fixture From a0d81a08e8a838524985ff46c4b8cca2a040fe23 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Wed, 5 Jun 2019 11:26:19 +0200 Subject: [PATCH 129/396] #4465 Implement all remaining command file commands and add tests for some commands --- .../GrpcInterface/CMakeLists.cmake | 3 + .../GrpcInterface/GrpcProtos/Commands.proto | 2 +- .../Python/examples/CommandExample.py | 9 ++- .../GrpcInterface/Python/rips/Commands.py | 77 ++++++++++++++++++- .../Python/tests/test_commands.py | 32 ++++++++ 5 files changed, 120 insertions(+), 3 deletions(-) create mode 100644 ApplicationCode/GrpcInterface/Python/tests/test_commands.py diff --git a/ApplicationCode/GrpcInterface/CMakeLists.cmake b/ApplicationCode/GrpcInterface/CMakeLists.cmake index a555057fa6..1e810b7009 100644 --- a/ApplicationCode/GrpcInterface/CMakeLists.cmake +++ b/ApplicationCode/GrpcInterface/CMakeLists.cmake @@ -169,6 +169,9 @@ if (PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) "examples/SoilAverage.py" "examples/SoilAverageNoComm.py" "tests/test_cases.py" + "tests/test_commands.py" + "tests/test_grids.py" + "tests/test_properties.py" "tests/conftest.py" "tests/dataroot.py" "requirements.txt" diff --git a/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto b/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto index 0f8f62a5fb..b44f72918d 100644 --- a/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto +++ b/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto @@ -83,7 +83,7 @@ enum CompdatExportType enum CompdatCombinationMode { INDIVIDUALLY = 0; - COMBINED = 1; + caCOMBINED = 1; } message ExportWellPathCompRequest diff --git a/ApplicationCode/GrpcInterface/Python/examples/CommandExample.py b/ApplicationCode/GrpcInterface/Python/examples/CommandExample.py index e45b9776fb..f9b6376641 100644 --- a/ApplicationCode/GrpcInterface/Python/examples/CommandExample.py +++ b/ApplicationCode/GrpcInterface/Python/examples/CommandExample.py @@ -14,6 +14,13 @@ resInsight.commands.setMainWindowSize(width=800, height=500) with tempfile.TemporaryDirectory(prefix="rips") as tmpdirname: print("Temporary folder: ", tmpdirname) resInsight.commands.setExportFolder(type='SNAPSHOTS', path=tmpdirname) + resInsight.commands.setExportFolder(type='PROPERTIES', path=tmpdirname) resInsight.commands.exportSnapshots() print(os.listdir(tmpdirname)) - assert(len(os.listdir(tmpdirname)) > 0) \ No newline at end of file + assert(len(os.listdir(tmpdirname)) > 0) + case = resInsight.project.case(id=0) + resInsight.commands.exportPropertyInViews(0, "3D View", 0) + expectedFileName = case.name + "-" + str("3D_View") + "-" + "T3" + "-SOIL" + fullPath = tmpdirname + "/" + expectedFileName + assert(os.path.exists(fullPath)) + diff --git a/ApplicationCode/GrpcInterface/Python/rips/Commands.py b/ApplicationCode/GrpcInterface/Python/rips/Commands.py index c0f6939834..e45bc4864b 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Commands.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Commands.py @@ -73,6 +73,35 @@ class Commands: viewNames=viewNames, undefinedValue=undefinedValue)) + def exportWellPathCompletions(self, caseId, timeStep, wellPathNames, fileSplit, + compdatExport, includePerforations, includeFishbones, + excludeMainBoreForFishbones, combinationMode): + if (isinstance(wellPathNames, str)): + wellPathNames = [wellPathNames] + return self.execute(exportWellPathCompletions=Cmd.ExportWellPathCompRequest(caseId=caseId, + timeStep=timeStep, + wellPathNames=wellPathNames, + fileSplit=fileSplit, + compdatExport=compdatExport, + includePerforations=includePerforations, + includeFishbones=includeFishbones, + excludeMainBoreForFishbones=excludeMainBoreForFishbones, + combinationMode=combinationMode)) + + def exportSimWellFractureCompletions(self, caseId, viewName, timeStep, simulationWellNames, fileSplit, compdatExport): + if(isinstance(simulationWellNames, str)): + simulationWellNames = [simulationWellNames] + return self.execute(exportSimWellFractureCompletions=Cmd.ExportSimWellPathFraqRequest(caseId=caseId, + viewName=viewName, + timeStep=timeStep, + simulationWellNames=simulationWellNames, + fileSplit=fileSplit, + compdatExport=compdatExport)) + + def exportMsw(self, caseId, wellPath): + return self.execute(exportMsw=Cmd.ExportMswRequest(caseId=caseId, + wellPath=wellPath)) + def exportWellPaths(self, wellPaths=[], mdStepSize=5.0): if isinstance(wellPaths, str): wellPaths = [wellpaths] @@ -100,7 +129,53 @@ class Commands: def setMainWindowSize(self, width, height): return self.execute(setMainWindowSize=Cmd.SetMainWindowSizeParams(width=width, height=height)) + def computeCaseGroupStatistics(self, caseIds): + if isinstance(caseIds, int): + caseIds = [caseIds] + return self.execute(computeCaseGroupStatistics=Cmd.ComputeCaseGroupStatRequest(caseIds=caseIds)) + def setTimeStep(self, caseId, timeStep): return self.execute(setTimeStep=Cmd.SetTimeStepParams(caseId=caseId, timeStep=timeStep)) - + + def scaleFractureTemplate(self, id, halfLength, height, dFactor, conductivity): + return self.execute(scaleFractureTemplate=Cmd.ScaleFractureTemplateRequest(id=id, + halfLength=halfLength, + height=height, + dFactor=dFactor, + conductivity=conductivity)) + + def setFractureContainment(self, id, topLayer, baseLayer): + return self.execute(setFractureContainment=Cmd.SetFracContainmentRequest(id=id, + topLayer=topLayer, + baseLayer=baseLayer)) + + def createMultipleFractures(self, caseId, templateId, wellPathNames, minDistFromWellTd, + maxFracturesPerWell, topLayer, baseLayer, spacing, action): + if isinstance(wellPathNames, str): + wellPathNames = [wellPathNames] + return self.execute(createMultipleFractures=Cmd.MultipleFracAction(caseId=caseId, + templateId=templateId, + wellPathNames=wellPathNames, + minDistFromWellTd=minDistFromWellTd, + maxFracturesPerWell=maxFracturesPerWell, + topLayer=topLayer, + baseLayer=baseLayer, + spacing=spacing, + action=action)) + + def createLgrForCompletions(self, caseId, timeStep, wellPathNames, refinementI, refinementJ, refinementK, splitType): + if isinstance(wellPathNames, str): + wellPathNames = [wellPathNames] + return self.execute(createLgrForCompletions=Cmd.CreateLgrForCompRequest(caseId=caseId, + timeStep=timeStep, + wellPathNames=wellPathNames, + refinementI=refinementI, + refinementJ=refinementJ, + refinementK=refinementK, + splitType=splitType)) + + def createSaturationPressurePlots(self, caseIds): + if isinstance(caseIds, int): + caseIds = [caseIds] + return self.execute(createSaturationPressurePlots=Cmd.CreateSatPressPlotRequest(caseIds=caseIds)) diff --git a/ApplicationCode/GrpcInterface/Python/tests/test_commands.py b/ApplicationCode/GrpcInterface/Python/tests/test_commands.py new file mode 100644 index 0000000000..ef65e34baf --- /dev/null +++ b/ApplicationCode/GrpcInterface/Python/tests/test_commands.py @@ -0,0 +1,32 @@ +import sys +import os +import tempfile + +sys.path.insert(1, os.path.join(sys.path[0], '..')) +import rips + +import dataroot + +def test_exportSnapshots(rips_instance, initializeTest): + casePath = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID" + rips_instance.project.loadCase(casePath) + with tempfile.TemporaryDirectory(prefix="rips") as tmpdirname: + print("Temporary folder: ", tmpdirname) + rips_instance.commands.setExportFolder(type='SNAPSHOTS', path=tmpdirname) + rips_instance.commands.exportSnapshots() + print(os.listdir(tmpdirname)) + assert(len(os.listdir(tmpdirname)) > 0) + for fileName in os.listdir(tmpdirname): + assert(os.path.splitext(fileName)[1] == '.png') + +def test_exportPropertyInView(rips_instance, initializeTest): + casePath = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID" + rips_instance.project.loadCase(casePath) + with tempfile.TemporaryDirectory(prefix="rips") as tmpdirname: + print("Temporary folder: ", tmpdirname) + rips_instance.commands.setExportFolder(type='PROPERTIES', path=tmpdirname) + case = rips_instance.project.case(id=0) + rips_instance.commands.exportPropertyInViews(0, "3D View", 0) + expectedFileName = case.name + "-" + str("3D_View") + "-" + "T0" + "-SOIL" + fullPath = tmpdirname + "/" + expectedFileName + assert(os.path.exists(fullPath)) \ No newline at end of file From 7444007219fbb8c072eae60baea9f6c78d607033 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Wed, 5 Jun 2019 14:28:48 +0200 Subject: [PATCH 130/396] #4470 Fix crashes when launching headless --- .../Application/Tools/RiaImportEclipseCaseTools.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/ApplicationCode/Application/Tools/RiaImportEclipseCaseTools.cpp b/ApplicationCode/Application/Tools/RiaImportEclipseCaseTools.cpp index a51ad88209..f9b273d652 100644 --- a/ApplicationCode/Application/Tools/RiaImportEclipseCaseTools.cpp +++ b/ApplicationCode/Application/Tools/RiaImportEclipseCaseTools.cpp @@ -179,7 +179,10 @@ bool RiaImportEclipseCaseTools::openEclipseCasesFromFile(const QStringList& file project->activeOilField()->completionTemplateCollection()->setDefaultUnitSystemBasedOnLoadedCases(); - RiuPlotMainWindowTools::refreshToolbars(); + if (RiaGuiApplication::isRunning()) + { + RiuPlotMainWindowTools::refreshToolbars(); + } if (openedFilesOut) { @@ -312,8 +315,10 @@ int RiaImportEclipseCaseTools::openEclipseCaseShowTimeStepFilterImpl(const QStri analysisModels->updateConnectedEditors(); - RiuMainWindow::instance()->selectAsCurrentItem(riv->cellResult()); - + if (RiaGuiApplication::isRunning()) + { + RiuMainWindow::instance()->selectAsCurrentItem(riv->cellResult()); + } return rimResultReservoir->caseId(); } From eec5569eca3bbed932450531ef091accf4ce8fb3 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Wed, 5 Jun 2019 14:30:10 +0200 Subject: [PATCH 131/396] #4428 Fix load case with relative paths --- .../CommandFileInterface/RicfLoadCase.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/ApplicationCode/CommandFileInterface/RicfLoadCase.cpp b/ApplicationCode/CommandFileInterface/RicfLoadCase.cpp index f2d4fe8a1a..5c1513c5ff 100644 --- a/ApplicationCode/CommandFileInterface/RicfLoadCase.cpp +++ b/ApplicationCode/CommandFileInterface/RicfLoadCase.cpp @@ -18,10 +18,12 @@ #include "RicfLoadCase.h" +#include "RiaApplication.h" #include "RiaImportEclipseCaseTools.h" - #include "RiaLogging.h" +#include +#include #include CAF_PDM_SOURCE_INIT(RicfLoadCaseResult, "loadCaseResult"); @@ -50,11 +52,19 @@ RicfLoadCase::RicfLoadCase() //-------------------------------------------------------------------------------------------------- RicfCommandResponse RicfLoadCase::execute() { + QString absolutePath = m_path; + QFileInfo projectPathInfo(absolutePath); + if (!projectPathInfo.exists()) + { + QDir startDir(RiaApplication::instance()->startDir()); + absolutePath = startDir.absoluteFilePath(m_path); + } + RiaImportEclipseCaseTools::FileCaseIdMap fileCaseIdMap; - bool ok = RiaImportEclipseCaseTools::openEclipseCasesFromFile(QStringList({m_path()}), &fileCaseIdMap, true); + bool ok = RiaImportEclipseCaseTools::openEclipseCasesFromFile(QStringList({absolutePath}), &fileCaseIdMap, true); if (!ok) { - QString error = QString("loadCase: Unable to load case from %1").arg(m_path()); + QString error = QString("loadCase: Unable to load case from %1").arg(absolutePath); RiaLogging::error(error); return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, error); } From 1a337ea0f810120e4646774c5cfcae887d5c213a Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Wed, 5 Jun 2019 15:45:22 +0200 Subject: [PATCH 132/396] #4474 Add command for getting runtime info (i.e. console/gui) * Also fixed up some tests when running in console --- .../GrpcInterface/GrpcProtos/App.proto | 12 ++++++++++ .../GrpcInterface/Python/rips/App.py | 7 ++++++ .../GrpcInterface/Python/rips/Instance.py | 23 +++++++++++++----- .../GrpcInterface/Python/tests/conftest.py | 24 +++++++++++-------- .../Python/tests/test_commands.py | 4 ++++ .../GrpcInterface/RiaGrpcAppService.cpp | 23 ++++++++++++++++-- .../GrpcInterface/RiaGrpcAppService.h | 1 + .../GrpcInterface/RiaGrpcCommandService.cpp | 5 ---- 8 files changed, 76 insertions(+), 23 deletions(-) diff --git a/ApplicationCode/GrpcInterface/GrpcProtos/App.proto b/ApplicationCode/GrpcInterface/GrpcProtos/App.proto index e2e7aa7c7c..6ab1ce3b68 100644 --- a/ApplicationCode/GrpcInterface/GrpcProtos/App.proto +++ b/ApplicationCode/GrpcInterface/GrpcProtos/App.proto @@ -7,10 +7,22 @@ import "Empty.proto"; service App { rpc GetVersion(Empty) returns (Version) {} rpc Exit(Empty) returns (Empty) {} + rpc GetRuntimeInfo(Empty) returns (RuntimeInfo) {} } message Version { int32 major_version = 1; int32 minor_version = 2; int32 patch_version = 3; +} + +enum ApplicationTypeEnum +{ + GUI_APPLICATION = 0; + CONSOLE_APPLICATION = 1; +} + +message RuntimeInfo +{ + ApplicationTypeEnum app_type = 1; } \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/Python/rips/App.py b/ApplicationCode/GrpcInterface/Python/rips/App.py index fcf6ec2126..3e41c576df 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/App.py +++ b/ApplicationCode/GrpcInterface/Python/rips/App.py @@ -23,4 +23,11 @@ class App: def versionString(self): return str(self.majorVersion()) + "." + str(self.minorVersion()) + "." + str(self.patchVersion()) def exit(self): + print("Telling ResInsight to Exit") return self.app.Exit(Empty()) + def isConsole(self): + print("RunTimeInfo stuff: ", self.app.GetRuntimeInfo(Empty()).app_type) + return self.app.GetRuntimeInfo(Empty()).app_type == App_pb2.ApplicationTypeEnum.Value('CONSOLE_APPLICATION') + def isGui(self): + print("RunTimeInfo stuff: ", self.app.GetRuntimeInfo(Empty()).app_type) + return self.app.GetRuntimeInfo(Empty()).app_type == App_pb2.ApplicationTypeEnum.Value('GUI_APPLICATION') diff --git a/ApplicationCode/GrpcInterface/Python/rips/Instance.py b/ApplicationCode/GrpcInterface/Python/rips/Instance.py index 81a31ed5c2..40a3861ee6 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Instance.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Instance.py @@ -13,6 +13,8 @@ from .Commands import Commands from .Project import Project class Instance: + launched = False + @staticmethod def is_port_in_use(port): with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: @@ -20,7 +22,7 @@ class Instance: return s.connect_ex(('localhost', port)) == 0 @staticmethod - def launch(resInsightExecutable = ''): + def launch(resInsightExecutable = '', console = False): port = 50051 portEnv = os.environ.get('RESINSIGHT_GRPC_PORT') if portEnv: @@ -38,9 +40,11 @@ class Instance: print('Port ' + str(port)) print('Trying to launch', resInsightExecutable) - pid = os.spawnl(os.P_NOWAIT, resInsightExecutable, " --grpcserver " + str(port)) - print(pid) - return Instance(port) + parameters = " --grpcserver " + str(port) + if console: + parameters += " --console" + pid = os.spawnl(os.P_NOWAIT, resInsightExecutable, parameters) + return Instance(port=port, launched=True) @staticmethod def find(startPort = 50051, endPort = 50071): @@ -56,10 +60,11 @@ class Instance: print('Error: Could not find any ResInsight instances responding between ports ' + str(startPort) + ' and ' + str(endPort)) return None - def __init__(self, port = 50051): + def __init__(self, port = 50051, launched = False): logging.basicConfig() location = "localhost:" + str(port) self.channel = grpc.insecure_channel(location) + self.launched = launched # Main version check package self.app = App(self.channel) @@ -77,4 +82,10 @@ class Instance: # Service packages self.commands = Commands(self.channel) self.project = Project(self.channel) - \ No newline at end of file + + path = os.getcwd() + self.commands.setStartDir(path=path) + + def __del__(self): + if self.launched: + self.app.exit() \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/Python/tests/conftest.py b/ApplicationCode/GrpcInterface/Python/tests/conftest.py index ac4297201a..36ee4024f4 100644 --- a/ApplicationCode/GrpcInterface/Python/tests/conftest.py +++ b/ApplicationCode/GrpcInterface/Python/tests/conftest.py @@ -1,24 +1,28 @@ import pytest import sys import os +import getopt sys.path.insert(1, os.path.join(sys.path[0], '..')) import rips -instance = rips.Instance.launch() - -if (not instance): - print("A ResInsight instance is required for running the tests") - exit(1) +_rips_instance = None @pytest.fixture def rips_instance(): - return instance + return _rips_instance @pytest.fixture def initializeTest(): - instance.project.close() + _rips_instance.project.close() -def pytest_unconfigure(config): - print("Telling ResInsight to Exit") - instance.app.exit() \ No newline at end of file +def pytest_addoption(parser): + parser.addoption("--console", action="store_true", default=False, help="Run as console application") + +def pytest_configure(config): + global _rips_instance + console = False + if config.getoption('--console'): + print("Should run as console app") + console = True + _rips_instance = rips.Instance.launch(console=console) diff --git a/ApplicationCode/GrpcInterface/Python/tests/test_commands.py b/ApplicationCode/GrpcInterface/Python/tests/test_commands.py index ef65e34baf..ec99c0aa6a 100644 --- a/ApplicationCode/GrpcInterface/Python/tests/test_commands.py +++ b/ApplicationCode/GrpcInterface/Python/tests/test_commands.py @@ -1,6 +1,7 @@ import sys import os import tempfile +import pytest sys.path.insert(1, os.path.join(sys.path[0], '..')) import rips @@ -8,6 +9,9 @@ import rips import dataroot def test_exportSnapshots(rips_instance, initializeTest): + if not rips_instance.app.isGui(): + pytest.skip("Cannot run test without a GUI") + casePath = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID" rips_instance.project.loadCase(casePath) with tempfile.TemporaryDirectory(prefix="rips") as tmpdirname: diff --git a/ApplicationCode/GrpcInterface/RiaGrpcAppService.cpp b/ApplicationCode/GrpcInterface/RiaGrpcAppService.cpp index bd0f452199..8224ce9e62 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcAppService.cpp +++ b/ApplicationCode/GrpcInterface/RiaGrpcAppService.cpp @@ -17,6 +17,7 @@ ////////////////////////////////////////////////////////////////////////////////// #include "RiaGrpcAppService.h" +#include "RiaGuiApplication.h" #include "RiaVersionInfo.h" #include "RiaGrpcCallbacks.h" #include "RiaGrpcServer.h" @@ -41,14 +42,32 @@ grpc::Status RiaGrpcAppService::Exit(grpc::ServerContext* context, const rips::E return grpc::Status::OK; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +grpc::Status RiaGrpcAppService::GetRuntimeInfo(grpc::ServerContext* context, const rips::Empty* request, rips::RuntimeInfo* reply) +{ + rips::ApplicationTypeEnum appType = rips::CONSOLE_APPLICATION; + if (RiaGuiApplication::isRunning()) + { + appType = rips::GUI_APPLICATION; + } + reply->set_app_type(appType); + + return grpc::Status::OK; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector RiaGrpcAppService::createCallbacks() { typedef RiaGrpcAppService Self; - return { new RiaGrpcUnaryCallback(this, &Self::GetVersion, &Self::RequestGetVersion), - new RiaGrpcUnaryCallback(this, &Self::Exit, &Self::RequestExit) }; + return { + new RiaGrpcUnaryCallback(this, &Self::GetVersion, &Self::RequestGetVersion), + new RiaGrpcUnaryCallback(this, &Self::Exit, &Self::RequestExit), + new RiaGrpcUnaryCallback(this, &Self::GetRuntimeInfo, &Self::RequestGetRuntimeInfo) + }; } static bool RiaGrpcAppInfoService_init = diff --git a/ApplicationCode/GrpcInterface/RiaGrpcAppService.h b/ApplicationCode/GrpcInterface/RiaGrpcAppService.h index 1882b7664d..cdf1c28457 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcAppService.h +++ b/ApplicationCode/GrpcInterface/RiaGrpcAppService.h @@ -44,6 +44,7 @@ class RiaGrpcAppService : public rips::App::AsyncService, public RiaGrpcServiceI public: grpc::Status GetVersion(grpc::ServerContext* context, const rips::Empty* request, rips::Version* reply) override; grpc::Status Exit(grpc::ServerContext* context, const rips::Empty* request, rips::Empty* reply) override; + grpc::Status GetRuntimeInfo(grpc::ServerContext* context, const rips::Empty* request, rips::RuntimeInfo* reply) override; std::vector createCallbacks() override; }; diff --git a/ApplicationCode/GrpcInterface/RiaGrpcCommandService.cpp b/ApplicationCode/GrpcInterface/RiaGrpcCommandService.cpp index cf65a5d44e..3570a13e59 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcCommandService.cpp +++ b/ApplicationCode/GrpcInterface/RiaGrpcCommandService.cpp @@ -17,8 +17,6 @@ ////////////////////////////////////////////////////////////////////////////////// #include "RiaGrpcCommandService.h" -#include "RiaLogging.h" - #include "RiaGrpcCallbacks.h" #include "RicfSetTimeStep.h" @@ -45,7 +43,6 @@ using namespace google::protobuf; grpc::Status RiaGrpcCommandService::Execute(grpc::ServerContext* context, const CommandParams* request, CommandReply* reply) { auto requestDescriptor = request->GetDescriptor(); - RiaLogging::info(QString::fromStdString(requestDescriptor->name())); CommandParams::ParamsCase paramsCase = request->params_case(); if (paramsCase != CommandParams::PARAMS_NOT_SET) @@ -55,7 +52,6 @@ grpc::Status RiaGrpcCommandService::Execute(grpc::ServerContext* context, const const Message& params = request->GetReflection()->GetMessage(*request, grpcOneOfMessage); QString grpcOneOfMessageName = QString::fromStdString(grpcOneOfMessage->name()); - RiaLogging::info(QString("Found Command: %1").arg(grpcOneOfMessageName)); auto pdmObjectHandle = caf::PdmDefaultObjectFactory::instance()->create(grpcOneOfMessageName); auto commandHandle = dynamic_cast(pdmObjectHandle); if (commandHandle) @@ -71,7 +67,6 @@ grpc::Status RiaGrpcCommandService::Execute(grpc::ServerContext* context, const auto pdmValueFieldHandle = dynamic_cast(pdmObjectHandle->findField(parameterName)); if (pdmValueFieldHandle) { - RiaLogging::info(QString("Found Matching Parameter: %1").arg(parameterName)); assignPdmFieldValue(pdmValueFieldHandle, params, parameter); } } From 4c54ec85222d5529f630953a9411141d48ae68e0 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 5 Jun 2019 21:59:05 +0200 Subject: [PATCH 133/396] #4464 LAS files : Reintroduce wellPathCollection->addWellLogs(wellLogFilePaths) This function was removed unintentionally as part of the splitting of GUI/console application. --- ApplicationCode/Application/RiaApplication.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ApplicationCode/Application/RiaApplication.cpp b/ApplicationCode/Application/RiaApplication.cpp index 4621e587bd..98385e1bad 100644 --- a/ApplicationCode/Application/RiaApplication.cpp +++ b/ApplicationCode/Application/RiaApplication.cpp @@ -835,6 +835,8 @@ void RiaApplication::addWellLogsToModel(const QList& wellLogFilePaths) m_project->updateConnectedEditors(); } + oilField->wellPathCollection->addWellLogs(wellLogFilePaths); + oilField->wellPathCollection->updateConnectedEditors(); } From 7de2358a0de60945c619e05f6310ff4029b46ee6 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 5 Jun 2019 22:27:40 +0200 Subject: [PATCH 134/396] #4442 Completion Export : Set export of MSW data on as default --- .../RicExportCompletionDataSettingsUi.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ApplicationCode/Commands/CompletionExportCommands/RicExportCompletionDataSettingsUi.cpp b/ApplicationCode/Commands/CompletionExportCommands/RicExportCompletionDataSettingsUi.cpp index d047c5f332..3e9fbccd09 100644 --- a/ApplicationCode/Commands/CompletionExportCommands/RicExportCompletionDataSettingsUi.cpp +++ b/ApplicationCode/Commands/CompletionExportCommands/RicExportCompletionDataSettingsUi.cpp @@ -82,7 +82,7 @@ RicExportCompletionDataSettingsUi::RicExportCompletionDataSettingsUi() CAF_PDM_InitField(&timeStep, "TimeStepIndex", 0, " Time Step", "", "", ""); - CAF_PDM_InitField(&includeMsw, "IncludeMSW", false, "Include Multi Segment Well Model", "", "", ""); + CAF_PDM_InitField(&includeMsw, "IncludeMSW", true, "Include Multi Segment Well Model", "", "", ""); CAF_PDM_InitField(&useLateralNTG, "UseLateralNTG", false, "Use NTG Horizontally", "", "", ""); From 8301827516001a30d2151adca9844f0147ec48d2 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 5 Jun 2019 22:47:00 +0200 Subject: [PATCH 135/396] cppcheck :Fix missing initialization --- .../GrpcInterface/RiaGrpcPropertiesService.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp b/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp index 9e6dd5eb84..0389c8cefe 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp +++ b/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp @@ -55,7 +55,9 @@ public: //-------------------------------------------------------------------------------------------------- RiaCellResultsStateHandler(bool clientStreamer = false) : m_request(nullptr) + , m_eclipseCase(nullptr) , m_currentCellIdx(0u) + , m_cellCount(0u) , m_clientStreamer(clientStreamer) { } @@ -199,7 +201,10 @@ class RiaActiveCellResultsStateHandler : public RiaCellResultsStateHandler public: RiaActiveCellResultsStateHandler(bool clientStreamer = false) : RiaCellResultsStateHandler(clientStreamer) - {} + , m_resultValues(nullptr) + { + } + protected: void initResultAccess(RigEclipseCaseData* caseData, size_t gridIndex, @@ -364,4 +369,4 @@ std::vector RiaGrpcPropertiesService::createCallbacks } static bool RiaGrpcPropertiesService_init = - RiaGrpcServiceFactory::instance()->registerCreator(typeid(RiaGrpcPropertiesService).hash_code()); \ No newline at end of file + RiaGrpcServiceFactory::instance()->registerCreator(typeid(RiaGrpcPropertiesService).hash_code()); From fdc1f6b645512b3bd8eb634ce7263c8bd0acaac7 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 6 Jun 2019 07:20:17 +0200 Subject: [PATCH 136/396] #4411 Grid Cross Plot : Fix inverted category legend in plot --- .../ProjectDataModel/GridCrossPlots/RimGridCrossPlotDataSet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ApplicationCode/ProjectDataModel/GridCrossPlots/RimGridCrossPlotDataSet.cpp b/ApplicationCode/ProjectDataModel/GridCrossPlots/RimGridCrossPlotDataSet.cpp index f9a800902b..53ca83b74b 100644 --- a/ApplicationCode/ProjectDataModel/GridCrossPlots/RimGridCrossPlotDataSet.cpp +++ b/ApplicationCode/ProjectDataModel/GridCrossPlots/RimGridCrossPlotDataSet.cpp @@ -979,7 +979,7 @@ void RimGridCrossPlotDataSet::updateLegendRange() const std::vector& categoryNames = formationNames->formationNames(); if (!categoryNames.empty()) { - legendConfig()->setNamedCategories(categoryNames); + legendConfig()->setNamedCategoriesInverse(categoryNames); legendConfig()->setAutomaticRanges(0, categoryNames.size() - 1, 0, categoryNames.size() - 1); } } From 2cbfecd2e6584dbfda05fe59de160648c770cb81 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 6 Jun 2019 12:35:56 +0200 Subject: [PATCH 137/396] #4475 Dock Windows : Always restore window visibility in plot window --- ApplicationCode/Application/RiaGuiApplication.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ApplicationCode/Application/RiaGuiApplication.cpp b/ApplicationCode/Application/RiaGuiApplication.cpp index 42a24b108b..f6971f190b 100644 --- a/ApplicationCode/Application/RiaGuiApplication.cpp +++ b/ApplicationCode/Application/RiaGuiApplication.cpp @@ -1310,6 +1310,8 @@ void RiaGuiApplication::onProjectOpened() m_mainPlotWindow->show(); m_mainPlotWindow->raise(); } + + m_mainPlotWindow->restoreDockWidgetVisibilities(); } else if (mainPlotWindow()) { From 05451aa904388fc2df174527db4a978fabf2cad3 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Thu, 6 Jun 2019 08:27:39 +0200 Subject: [PATCH 138/396] Python: tidied up tests --- ApplicationCode/GrpcInterface/Python/rips/App.py | 2 -- ApplicationCode/GrpcInterface/Python/tests/conftest.py | 5 +++++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/ApplicationCode/GrpcInterface/Python/rips/App.py b/ApplicationCode/GrpcInterface/Python/rips/App.py index 3e41c576df..f80e31e69c 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/App.py +++ b/ApplicationCode/GrpcInterface/Python/rips/App.py @@ -26,8 +26,6 @@ class App: print("Telling ResInsight to Exit") return self.app.Exit(Empty()) def isConsole(self): - print("RunTimeInfo stuff: ", self.app.GetRuntimeInfo(Empty()).app_type) return self.app.GetRuntimeInfo(Empty()).app_type == App_pb2.ApplicationTypeEnum.Value('CONSOLE_APPLICATION') def isGui(self): - print("RunTimeInfo stuff: ", self.app.GetRuntimeInfo(Empty()).app_type) return self.app.GetRuntimeInfo(Empty()).app_type == App_pb2.ApplicationTypeEnum.Value('GUI_APPLICATION') diff --git a/ApplicationCode/GrpcInterface/Python/tests/conftest.py b/ApplicationCode/GrpcInterface/Python/tests/conftest.py index 36ee4024f4..998aaa1ea3 100644 --- a/ApplicationCode/GrpcInterface/Python/tests/conftest.py +++ b/ApplicationCode/GrpcInterface/Python/tests/conftest.py @@ -8,6 +8,10 @@ import rips _rips_instance = None +if not os.environ.get("RESINSIGHT_EXECUTABLE"): + print("ERROR: Need to have the environment variable RESINSIGHT_EXECUTABLE set to a valid ResInsight executable") + exit(1) + @pytest.fixture def rips_instance(): return _rips_instance @@ -26,3 +30,4 @@ def pytest_configure(config): print("Should run as console app") console = True _rips_instance = rips.Instance.launch(console=console) + assert(_rips_instance is not None) From 4701ea5134022c0cf658feea3099e9c10246fc90 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Thu, 6 Jun 2019 09:12:44 +0200 Subject: [PATCH 139/396] #4430 Implement GetDaysSinceStart and add way of connecting to existing ResInsight in pytest --- .../GrpcInterface/GrpcProtos/Case.proto | 6 ++-- .../GrpcInterface/Python/tests/conftest.py | 16 +++++---- .../GrpcInterface/RiaGrpcCaseService.cpp | 36 +++++++++++++++++++ .../GrpcInterface/RiaGrpcCaseService.h | 1 + 4 files changed, 49 insertions(+), 10 deletions(-) diff --git a/ApplicationCode/GrpcInterface/GrpcProtos/Case.proto b/ApplicationCode/GrpcInterface/GrpcProtos/Case.proto index c4bcb2aace..2752c86016 100644 --- a/ApplicationCode/GrpcInterface/GrpcProtos/Case.proto +++ b/ApplicationCode/GrpcInterface/GrpcProtos/Case.proto @@ -9,7 +9,7 @@ service Case rpc GetCellInfoForActiveCells(CellInfoRequest) returns (stream CellInfoArray) {} rpc GetCoarseningInfoArray(CaseRequest) returns (CoarseningInfoArray) {} rpc GetTimeSteps(CaseRequest) returns (TimeStepDates) {} - rpc GetTimeStepDaysSinceStart(CaseRequest) returns (DoubleDates) {} + rpc GetDaysSinceStart(CaseRequest) returns (DaysSinceStart) {} rpc GetCaseInfo(CaseRequest) returns (CaseInfo) {} } @@ -110,7 +110,7 @@ message TimeStepDate int32 second = 6; } -message DoubleDates +message DaysSinceStart { - repeated double date_decimals = 1; + repeated double day_decimals = 1; } diff --git a/ApplicationCode/GrpcInterface/Python/tests/conftest.py b/ApplicationCode/GrpcInterface/Python/tests/conftest.py index 998aaa1ea3..1a79cffe61 100644 --- a/ApplicationCode/GrpcInterface/Python/tests/conftest.py +++ b/ApplicationCode/GrpcInterface/Python/tests/conftest.py @@ -8,10 +8,6 @@ import rips _rips_instance = None -if not os.environ.get("RESINSIGHT_EXECUTABLE"): - print("ERROR: Need to have the environment variable RESINSIGHT_EXECUTABLE set to a valid ResInsight executable") - exit(1) - @pytest.fixture def rips_instance(): return _rips_instance @@ -22,12 +18,18 @@ def initializeTest(): def pytest_addoption(parser): parser.addoption("--console", action="store_true", default=False, help="Run as console application") + parser.addoption("--existing", action="store_true", default=False, help="Look for existing ResInsight") def pytest_configure(config): global _rips_instance console = False - if config.getoption('--console'): + if config.getoption('--existing'): + print("Looking for existing ResInsight") + _rips_instance = rips.Instance.find() + elif config.getoption('--console'): print("Should run as console app") console = True - _rips_instance = rips.Instance.launch(console=console) - assert(_rips_instance is not None) + _rips_instance = rips.Instance.launch(console=console) + if not _rips_instance: + print("Need a valid ResInsight executable to launch tests") + exit(0) diff --git a/ApplicationCode/GrpcInterface/RiaGrpcCaseService.cpp b/ApplicationCode/GrpcInterface/RiaGrpcCaseService.cpp index 2e29a47edc..09be0fa52f 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcCaseService.cpp +++ b/ApplicationCode/GrpcInterface/RiaGrpcCaseService.cpp @@ -20,7 +20,9 @@ #include "RiaSocketTools.h" #include "RigActiveCellInfo.h" +#include "RigCaseCellResultsData.h" #include "RigEclipseCaseData.h" +#include "RigEclipseResultAddress.h" #include "RigMainGrid.h" #include "RimEclipseCase.h" @@ -275,6 +277,39 @@ RiaGrpcCaseService::GetTimeSteps(grpc::ServerContext* context, const rips::CaseR return grpc::Status(grpc::NOT_FOUND, "Eclipse Case not found"); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +grpc::Status RiaGrpcCaseService::GetDaysSinceStart(grpc::ServerContext* context, + const rips::CaseRequest* request, + rips::DaysSinceStart* reply) +{ + RimCase* rimCase = findCase(request->id()); + + RimEclipseCase* eclipseCase = dynamic_cast(rimCase); + if (eclipseCase) + { + RigEclipseResultAddress addrToMaxTimeStepCountResult; + if (eclipseCase && eclipseCase->eclipseCaseData()) + { + eclipseCase->eclipseCaseData()->results(RiaDefines::MATRIX_MODEL)->maxTimeStepCount(&addrToMaxTimeStepCountResult); + if (!addrToMaxTimeStepCountResult.isValid()) + { + return grpc::Status(grpc::NOT_FOUND, "Invalid result. No time steps found."); + } + } + + std::vector daysSinceSimulationStart = + eclipseCase->eclipseCaseData()->results(RiaDefines::MATRIX_MODEL)->daysSinceSimulationStart(addrToMaxTimeStepCountResult); + + for (auto days : daysSinceSimulationStart) + { + reply->add_day_decimals(days); + } + return grpc::Status::OK; + } + return grpc::Status(grpc::NOT_FOUND, "Eclipse Case not found"); +} //-------------------------------------------------------------------------------------------------- /// @@ -320,6 +355,7 @@ std::vector RiaGrpcCaseService::createCallbacks() return {new RiaGrpcUnaryCallback(this, &Self::GetGridCount, &Self::RequestGetGridCount), new RiaGrpcUnaryCallback(this, &Self::GetCellCount, &Self::RequestGetCellCount), new RiaGrpcUnaryCallback(this, &Self::GetTimeSteps, &Self::RequestGetTimeSteps), + new RiaGrpcUnaryCallback(this, &Self::GetDaysSinceStart, &Self::RequestGetDaysSinceStart), new RiaGrpcUnaryCallback(this, &Self::GetCaseInfo, &Self::RequestGetCaseInfo), new RiaGrpcServerStreamCallback( this, &Self::GetCellInfoForActiveCells, &Self::RequestGetCellInfoForActiveCells, new RiaActiveCellInfoStateHandler)}; diff --git a/ApplicationCode/GrpcInterface/RiaGrpcCaseService.h b/ApplicationCode/GrpcInterface/RiaGrpcCaseService.h index 5cf51b896e..621d3c3795 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcCaseService.h +++ b/ApplicationCode/GrpcInterface/RiaGrpcCaseService.h @@ -72,6 +72,7 @@ public: grpc::Status GetGridCount(grpc::ServerContext* context, const rips::CaseRequest* request, rips::GridCount* reply) override; grpc::Status GetCellCount(grpc::ServerContext* context, const rips::CellInfoRequest* request, rips::CellCount* reply) override; grpc::Status GetTimeSteps(grpc::ServerContext* context, const rips::CaseRequest* request, rips::TimeStepDates* reply) override; + grpc::Status GetDaysSinceStart(grpc::ServerContext* context, const rips::CaseRequest* request, rips::DaysSinceStart* reply) override; grpc::Status GetCaseInfo(grpc::ServerContext* context, const rips::CaseRequest* request, rips::CaseInfo* reply) override; grpc::Status GetCellInfoForActiveCells(grpc::ServerContext* context, From 57e282eb7e98fe61d3ecf0a30ba1b6849a2b66e3 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Thu, 6 Jun 2019 09:13:23 +0200 Subject: [PATCH 140/396] Python: return time step arrays directly rather than struct containing time step arrays --- .../GrpcInterface/Python/examples/SoilAverage.py | 2 +- .../GrpcInterface/Python/examples/SoilPorvAsync.py | 2 +- .../GrpcInterface/Python/examples/SoilPorvSync.py | 2 +- ApplicationCode/GrpcInterface/Python/rips/Case.py | 8 +++++++- ApplicationCode/GrpcInterface/Python/tests/conftest.py | 7 ++++--- ApplicationCode/GrpcInterface/Python/tests/test_cases.py | 8 ++++++-- 6 files changed, 20 insertions(+), 9 deletions(-) diff --git a/ApplicationCode/GrpcInterface/Python/examples/SoilAverage.py b/ApplicationCode/GrpcInterface/Python/examples/SoilAverage.py index 0fff58b1df..56270e7ffc 100644 --- a/ApplicationCode/GrpcInterface/Python/examples/SoilAverage.py +++ b/ApplicationCode/GrpcInterface/Python/examples/SoilAverage.py @@ -14,7 +14,7 @@ grid = case.grid(index = 0) timeSteps = case.timeSteps() averages = [] -for i in range(0, len(timeSteps.dates)): +for i in range(0, len(timeSteps)): resultChunks = case.properties.activeCellProperty('DYNAMIC_NATIVE', 'SOIL', i) mysum = 0.0 count = 0 diff --git a/ApplicationCode/GrpcInterface/Python/examples/SoilPorvAsync.py b/ApplicationCode/GrpcInterface/Python/examples/SoilPorvAsync.py index 1a57db2943..0015eb14b9 100644 --- a/ApplicationCode/GrpcInterface/Python/examples/SoilPorvAsync.py +++ b/ApplicationCode/GrpcInterface/Python/examples/SoilPorvAsync.py @@ -23,7 +23,7 @@ porvArray = [] for porvChunk in porvChunks: porvArray.append(porvChunk) -for i in range (0, len(timeStepInfo.dates)): +for i in range (0, len(timeStepInfo)): soilChunks = case.properties.activeCellProperty('DYNAMIC_NATIVE', 'SOIL', i) input_iterator = createResult(soilChunks, iter(porvArray)) case.properties.setActiveCellPropertyAsync(input_iterator, 'GENERATED', 'SOILPORVAsync', i) diff --git a/ApplicationCode/GrpcInterface/Python/examples/SoilPorvSync.py b/ApplicationCode/GrpcInterface/Python/examples/SoilPorvSync.py index cef107e2e3..81bf8cbb7c 100644 --- a/ApplicationCode/GrpcInterface/Python/examples/SoilPorvSync.py +++ b/ApplicationCode/GrpcInterface/Python/examples/SoilPorvSync.py @@ -14,7 +14,7 @@ for porvChunk in porvChunks: timeStepInfo = case.timeSteps() -for i in range (0, len(timeStepInfo.dates)): +for i in range (0, len(timeStepInfo)): soilChunks = case.properties.activeCellProperty('DYNAMIC_NATIVE', 'SOIL', i) soilResults = [] for soilChunk in soilChunks: diff --git a/ApplicationCode/GrpcInterface/Python/rips/Case.py b/ApplicationCode/GrpcInterface/Python/rips/Case.py index 18a1889333..fad475bb61 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Case.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Case.py @@ -21,6 +21,7 @@ class Case: self.properties = Properties(self) self.request = Case_pb2.CaseRequest(id=self.id) + # Get number of grids in the case def gridCount(self): try: return self.stub.GetGridCount(self.request).count @@ -30,9 +31,11 @@ class Case: print("ERROR: ", e) return 0 + # Get Grid of a given index. Returns a rips Grid object def grid(self, index): return Grid(index, self) + # Get a list of all rips Grid objects in the case def grids(self): gridList = [] for i in range(0, self.gridCount()): @@ -52,5 +55,8 @@ class Case: return self.stub.GetCellInfoForActiveCells(request) def timeSteps(self): - return self.stub.GetTimeSteps(self.request) + return self.stub.GetTimeSteps(self.request).dates + + def daysSinceStart(self): + return self.stub.GetDaysSinceStart(self.request).day_decimals \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/Python/tests/conftest.py b/ApplicationCode/GrpcInterface/Python/tests/conftest.py index 1a79cffe61..0e75f1a8dc 100644 --- a/ApplicationCode/GrpcInterface/Python/tests/conftest.py +++ b/ApplicationCode/GrpcInterface/Python/tests/conftest.py @@ -26,9 +26,10 @@ def pytest_configure(config): if config.getoption('--existing'): print("Looking for existing ResInsight") _rips_instance = rips.Instance.find() - elif config.getoption('--console'): - print("Should run as console app") - console = True + else: + if config.getoption('--console'): + print("Should run as console app") + console = True _rips_instance = rips.Instance.launch(console=console) if not _rips_instance: print("Need a valid ResInsight executable to launch tests") diff --git a/ApplicationCode/GrpcInterface/Python/tests/test_cases.py b/ApplicationCode/GrpcInterface/Python/tests/test_cases.py index cabb349cb1..562e74fe25 100644 --- a/ApplicationCode/GrpcInterface/Python/tests/test_cases.py +++ b/ApplicationCode/GrpcInterface/Python/tests/test_cases.py @@ -45,7 +45,9 @@ def test_10k(rips_instance, initializeTest): assert(cellCountInfo.active_cell_count == 11125) assert(cellCountInfo.reservoir_cell_count == 316224) timeSteps = case.timeSteps() - assert(len(timeSteps.dates) == 9) + assert(len(timeSteps) == 9) + daysSinceStart = case.daysSinceStart() + assert(len(daysSinceStart) == 9) def test_brugge_0010(rips_instance, initializeTest): casePath = dataroot.PATH + "/Case_with_10_timesteps/Real10/BRUGGE_0010.EGRID" @@ -55,4 +57,6 @@ def test_brugge_0010(rips_instance, initializeTest): assert(cellCountInfo.active_cell_count == 43374) assert(cellCountInfo.reservoir_cell_count == 60048) timeSteps = case.timeSteps() - assert(len(timeSteps.dates) == 11) \ No newline at end of file + assert(len(timeSteps) == 11) + daysSinceStart = case.daysSinceStart() + assert(len(daysSinceStart) == 11) From c075f7b352e59e580840de4c44dc02846a4f0492 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Thu, 6 Jun 2019 09:32:44 +0200 Subject: [PATCH 141/396] Python: wait for ResInsight to start --- .../GrpcInterface/Python/rips/Instance.py | 44 ++++++++++++++----- 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/ApplicationCode/GrpcInterface/Python/rips/Instance.py b/ApplicationCode/GrpcInterface/Python/rips/Instance.py index 40a3861ee6..11de80a7fb 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Instance.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Instance.py @@ -3,6 +3,7 @@ import os import sys import socket import logging +import time sys.path.insert(1, os.path.join(sys.path[0], '../generated')) @@ -44,7 +45,9 @@ class Instance: if console: parameters += " --console" pid = os.spawnl(os.P_NOWAIT, resInsightExecutable, parameters) - return Instance(port=port, launched=True) + if pid: + return Instance(port=port, launched=True) + return None @staticmethod def find(startPort = 50051, endPort = 50071): @@ -60,25 +63,42 @@ class Instance: print('Error: Could not find any ResInsight instances responding between ports ' + str(startPort) + ' and ' + str(endPort)) return None + def checkVersion(self): + try: + majorVersionOk = self.app.majorVersion() == int(RiaVersionInfo.RESINSIGHT_MAJOR_VERSION) + minorVersionOk = self.app.minorVersion() == int(RiaVersionInfo.RESINSIGHT_MINOR_VERSION) + return True, majorVersionOk and minorVersionOk + except grpc.RpcError as e: + return False, False + def __init__(self, port = 50051, launched = False): logging.basicConfig() location = "localhost:" + str(port) + self.channel = grpc.insecure_channel(location) self.launched = launched # Main version check package self.app = App(self.channel) - try: - majorVersionOk = self.app.majorVersion() == int(RiaVersionInfo.RESINSIGHT_MAJOR_VERSION) - minorVersionOk = self.app.minorVersion() == int(RiaVersionInfo.RESINSIGHT_MINOR_VERSION) - if not (majorVersionOk and minorVersionOk): - raise Exception('Version of ResInsight does not match version of Python API') - except grpc.RpcError as e: - if e.code() == grpc.StatusCode.UNAVAILABLE: - print('Info: Could not find any instances at port ' + str(port)) - except Exception as e: - print('Error:', e) - + + connectionOk = False + versionOk = False + + if launched: + for i in range(0, 5): + connectionOk, versionOk = self.checkVersion() + if connectionOk: + break + time.sleep(0.5) + else: + connectionOk, versionOk = self.checkVersion() + + if not connectionOk: + raise Exception('Error: Could not connect to resinsight at ', location) + exit(1) + if not versionOk: + raise Exception('Error: Wrong Version of ResInsight at ', location) + # Service packages self.commands = Commands(self.channel) self.project = Project(self.channel) From df2fe42c4aadd2655425b3fc3b5626f22a2dc9ab Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Thu, 6 Jun 2019 10:57:07 +0200 Subject: [PATCH 142/396] Python: gRPC timeout --- .../Application/RiaGuiApplication.cpp | 22 +++++++++++++++++-- .../GrpcInterface/RiaGrpcServer.cpp | 11 ++++++---- ApplicationCode/GrpcInterface/RiaGrpcServer.h | 2 +- 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/ApplicationCode/Application/RiaGuiApplication.cpp b/ApplicationCode/Application/RiaGuiApplication.cpp index f6971f190b..b2180ef5cf 100644 --- a/ApplicationCode/Application/RiaGuiApplication.cpp +++ b/ApplicationCode/Application/RiaGuiApplication.cpp @@ -112,6 +112,7 @@ #include "cvfProgramOptions.h" #include "cvfqtUtils.h" +#include #include #include #include @@ -1238,7 +1239,7 @@ void RiaGuiApplication::launchGrpcServer() m_grpcServer->runInThread(); m_idleTimer = new QTimer(this); connect(m_idleTimer, SIGNAL(timeout()), this, SLOT(runIdleProcessing())); - m_idleTimer->start(0); + m_idleTimer->start(5); #endif } @@ -1696,7 +1697,24 @@ void RiaGuiApplication::runIdleProcessing() } else if (!caf::ProgressInfoStatic::isRunning()) { - m_grpcServer->processAllQueuedRequests(); + static int idleIterationCount = 0; + int iterationInterval = 0; + if (m_grpcServer->processAllQueuedRequests() > 0) + { + idleIterationCount = 0; + } + else + { + idleIterationCount = std::min(++idleIterationCount, 500); + if (idleIterationCount == 500) + { + iterationInterval = 5; + } + } + if (iterationInterval != m_idleTimer->interval()) + { + m_idleTimer->setInterval(iterationInterval); + } } #endif } diff --git a/ApplicationCode/GrpcInterface/RiaGrpcServer.cpp b/ApplicationCode/GrpcInterface/RiaGrpcServer.cpp index ddd1ff9082..6a98af95b3 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcServer.cpp +++ b/ApplicationCode/GrpcInterface/RiaGrpcServer.cpp @@ -61,7 +61,7 @@ public: void run(); void runInThread(); void initialize(); - void processAllQueuedRequests(); + size_t processAllQueuedRequests(); void quit(); private: @@ -168,7 +168,7 @@ void RiaGrpcServerImpl::initialize() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RiaGrpcServerImpl::processAllQueuedRequests() +size_t RiaGrpcServerImpl::processAllQueuedRequests() { std::list waitingRequests; { @@ -176,6 +176,8 @@ void RiaGrpcServerImpl::processAllQueuedRequests() std::lock_guard requestLock(m_requestMutex); waitingRequests.swap(m_unprocessedRequests); } + size_t count = waitingRequests.size(); + // Now free to receive new requests from client while processing the current ones. while (!waitingRequests.empty()) { @@ -183,6 +185,7 @@ void RiaGrpcServerImpl::processAllQueuedRequests() waitingRequests.pop_front(); process(method); } + return count; } //-------------------------------------------------------------------------------------------------- @@ -339,9 +342,9 @@ void RiaGrpcServer::initialize() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RiaGrpcServer::processAllQueuedRequests() +size_t RiaGrpcServer::processAllQueuedRequests() { - m_serverImpl->processAllQueuedRequests(); + return m_serverImpl->processAllQueuedRequests(); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/GrpcInterface/RiaGrpcServer.h b/ApplicationCode/GrpcInterface/RiaGrpcServer.h index e6c42e3d7b..769bfd348e 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcServer.h +++ b/ApplicationCode/GrpcInterface/RiaGrpcServer.h @@ -41,7 +41,7 @@ public: bool isRunning() const; void run(); void runInThread(); - void processAllQueuedRequests(); + size_t processAllQueuedRequests(); void quit(); static int findAvailablePortNumber(int defaultPortNumber); static void setReceivedExitRequest(); From 464f3b9d834705edef827a08baf1e43a8526cbce Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 6 Jun 2019 13:35:25 +0200 Subject: [PATCH 143/396] #4441 Advanced snapshot export : Remember output path between multiple sessions --- .../RicAdvancedSnapshotExportFeature.cpp | 9 ++++++++ .../RiuAdvancedSnapshotExportWidget.cpp | 21 +++++++++++++++---- .../RiuAdvancedSnapshotExportWidget.h | 2 ++ 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/ApplicationCode/Commands/ExportCommands/RicAdvancedSnapshotExportFeature.cpp b/ApplicationCode/Commands/ExportCommands/RicAdvancedSnapshotExportFeature.cpp index 358432e5f4..bf07f46e0c 100644 --- a/ApplicationCode/Commands/ExportCommands/RicAdvancedSnapshotExportFeature.cpp +++ b/ApplicationCode/Commands/ExportCommands/RicAdvancedSnapshotExportFeature.cpp @@ -87,7 +87,16 @@ void RicAdvancedSnapshotExportFeature::onActionTriggered(bool isChecked) dlg.addEmptySnapshotItems(4); } + { + QString fallbackFolderName = RiaApplication::instance()->createAbsolutePathFromProjectRelativePath("snapshots"); + QString folderName = + RiaApplication::instance()->lastUsedDialogDirectoryWithFallback("ADVANCED_SNAPSHOT_EXPORT", fallbackFolderName); + dlg.setExportFolder(folderName); + } + dlg.exec(); + + RiaApplication::instance()->setLastUsedDialogDirectory("ADVANCED_SNAPSHOT_EXPORT", dlg.exportFolder()); } } diff --git a/ApplicationCode/UserInterface/RiuAdvancedSnapshotExportWidget.cpp b/ApplicationCode/UserInterface/RiuAdvancedSnapshotExportWidget.cpp index 5c522a572d..74e1cb96a1 100644 --- a/ApplicationCode/UserInterface/RiuAdvancedSnapshotExportWidget.cpp +++ b/ApplicationCode/UserInterface/RiuAdvancedSnapshotExportWidget.cpp @@ -93,10 +93,7 @@ RiuAdvancedSnapshotExportWidget::RiuAdvancedSnapshotExportWidget(QWidget* parent layout->addWidget(new QLabel("Export folder")); - // Save images in snapshot catalog relative to project directory - QString snapshotFolderName = RiaApplication::instance()->createAbsolutePathFromProjectRelativePath("snapshots"); - - m_exportFolderLineEdit = new QLineEdit(snapshotFolderName); + m_exportFolderLineEdit = new QLineEdit; QToolButton* button = new QToolButton; button->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred)); @@ -187,6 +184,22 @@ void RiuAdvancedSnapshotExportWidget::addEmptySnapshotItems(size_t itemCount) m_rimProject->multiSnapshotDefinitions.uiCapability()->updateConnectedEditors(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuAdvancedSnapshotExportWidget::setExportFolder(const QString& folder) +{ + m_exportFolderLineEdit->setText(folder); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RiuAdvancedSnapshotExportWidget::exportFolder() const +{ + return m_exportFolderLineEdit->text(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/UserInterface/RiuAdvancedSnapshotExportWidget.h b/ApplicationCode/UserInterface/RiuAdvancedSnapshotExportWidget.h index 6f4a43b72c..8dd566ab8d 100644 --- a/ApplicationCode/UserInterface/RiuAdvancedSnapshotExportWidget.h +++ b/ApplicationCode/UserInterface/RiuAdvancedSnapshotExportWidget.h @@ -38,6 +38,8 @@ public: void addSnapshotItemFromActiveView(); void addEmptySnapshotItems(size_t itemCount); + void setExportFolder(const QString& folder); + QString exportFolder() const; private slots: void customMenuRequested(QPoint pos); From 91bbbdbe74e6b7a37e74a99619eb00e589df021c Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Thu, 6 Jun 2019 13:29:47 +0200 Subject: [PATCH 144/396] Python: add poropermx test --- .../Python/tests/test_properties.py | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/ApplicationCode/GrpcInterface/Python/tests/test_properties.py b/ApplicationCode/GrpcInterface/Python/tests/test_properties.py index e656bd2ee4..9ef3561a7b 100644 --- a/ApplicationCode/GrpcInterface/Python/tests/test_properties.py +++ b/ApplicationCode/GrpcInterface/Python/tests/test_properties.py @@ -21,3 +21,35 @@ def test_10k(rips_instance, initializeTest): assert(mysum == pytest.approx(621.768, abs=0.001)) assert(average != pytest.approx(0.0158893, abs=0.0000001)) assert(average == pytest.approx(0.0558893, abs=0.0000001)) + + +def createResult(poroChunks, permxChunks): + for (poroChunk, permxChunk) in zip(poroChunks, permxChunks): + resultChunk = [] + for (poro, permx) in zip(poroChunk.values, permxChunk.values): + resultChunk.append(poro * permx) + yield resultChunk + +def checkResults(poroChunks, permxChunks, poroPermXChunks): + for (poroChunk, permxChunk, poroPermXChunk) in zip(poroChunks, permxChunks, poroPermXChunks): + for (poro, permx, poropermx) in zip(poroChunk.values, permxChunk.values, poroPermXChunk.values): + recalc = poro * permx + assert(recalc == pytest.approx(poropermx, rel=1.0e-10)) + +def test_10k_PoroPermX(rips_instance, initializeTest): + casePath = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID" + case = rips_instance.project.loadCase(path=casePath) + + poroChunks = case.properties.activeCellProperty('STATIC_NATIVE', 'PORO', 0) + permxChunks = case.properties.activeCellProperty('STATIC_NATIVE', 'PERMX', 0) + + case.properties.setActiveCellPropertyAsync(createResult(poroChunks, permxChunks), 'GENERATED', 'POROPERMXAS', 0) + + poroChunks = case.properties.activeCellProperty('STATIC_NATIVE', 'PORO', 0) + permxChunks = case.properties.activeCellProperty('STATIC_NATIVE', 'PERMX', 0) + poroPermXChunks = case.properties.activeCellProperty('GENERATED', 'POROPERMXAS', 0) + + checkResults(poroChunks, permxChunks, poroPermXChunks) + + + \ No newline at end of file From ea45d07b856b1b6e4ba43dfeac26b5a2e48f16a2 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Thu, 6 Jun 2019 13:34:10 +0200 Subject: [PATCH 145/396] Python: fix console flags for test --- ApplicationCode/GrpcInterface/Python/rips/Instance.py | 7 ++++--- ApplicationCode/GrpcInterface/Python/tests/conftest.py | 1 - 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ApplicationCode/GrpcInterface/Python/rips/Instance.py b/ApplicationCode/GrpcInterface/Python/rips/Instance.py index 11de80a7fb..17da837e88 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Instance.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Instance.py @@ -41,10 +41,11 @@ class Instance: print('Port ' + str(port)) print('Trying to launch', resInsightExecutable) - parameters = " --grpcserver " + str(port) + parameters = ["ResInsight", "--grpcserver", str(port)] if console: - parameters += " --console" - pid = os.spawnl(os.P_NOWAIT, resInsightExecutable, parameters) + print("Launching as console app") + parameters.append("--console") + pid = os.spawnv(os.P_NOWAIT, resInsightExecutable, parameters) if pid: return Instance(port=port, launched=True) return None diff --git a/ApplicationCode/GrpcInterface/Python/tests/conftest.py b/ApplicationCode/GrpcInterface/Python/tests/conftest.py index 0e75f1a8dc..38ad8111c8 100644 --- a/ApplicationCode/GrpcInterface/Python/tests/conftest.py +++ b/ApplicationCode/GrpcInterface/Python/tests/conftest.py @@ -28,7 +28,6 @@ def pytest_configure(config): _rips_instance = rips.Instance.find() else: if config.getoption('--console'): - print("Should run as console app") console = True _rips_instance = rips.Instance.launch(console=console) if not _rips_instance: From 6dbe5964a197eb0ca5026e6ac0bac23bcc0c17d9 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Thu, 6 Jun 2019 13:48:59 +0200 Subject: [PATCH 146/396] Python: avoid cleanip in destructor of Instance. It doesn't work right on Linux. --- ApplicationCode/GrpcInterface/Python/rips/Instance.py | 4 ---- ApplicationCode/GrpcInterface/Python/tests/conftest.py | 3 +++ 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/ApplicationCode/GrpcInterface/Python/rips/Instance.py b/ApplicationCode/GrpcInterface/Python/rips/Instance.py index 17da837e88..a1904352ef 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Instance.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Instance.py @@ -106,7 +106,3 @@ class Instance: path = os.getcwd() self.commands.setStartDir(path=path) - - def __del__(self): - if self.launched: - self.app.exit() \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/Python/tests/conftest.py b/ApplicationCode/GrpcInterface/Python/tests/conftest.py index 38ad8111c8..a862d65c69 100644 --- a/ApplicationCode/GrpcInterface/Python/tests/conftest.py +++ b/ApplicationCode/GrpcInterface/Python/tests/conftest.py @@ -33,3 +33,6 @@ def pytest_configure(config): if not _rips_instance: print("Need a valid ResInsight executable to launch tests") exit(0) + +def pytest_unconfigure(): + _rips_instance.app.exit() \ No newline at end of file From a0334fc48270dfaffcbc889901f55bafc637754a Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Thu, 6 Jun 2019 14:00:47 +0200 Subject: [PATCH 147/396] Python: disable brugge tests --- ApplicationCode/GrpcInterface/Python/tests/test_cases.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/ApplicationCode/GrpcInterface/Python/tests/test_cases.py b/ApplicationCode/GrpcInterface/Python/tests/test_cases.py index 562e74fe25..e0c61b6a31 100644 --- a/ApplicationCode/GrpcInterface/Python/tests/test_cases.py +++ b/ApplicationCode/GrpcInterface/Python/tests/test_cases.py @@ -1,5 +1,6 @@ import sys import os +import pytest sys.path.insert(1, os.path.join(sys.path[0], '..')) import rips @@ -23,9 +24,9 @@ def test_OneCase(rips_instance, initializeTest): def test_MultipleCases(rips_instance, initializeTest): casePaths = [] casePaths.append(dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID") - casePaths.append(dataroot.PATH + "/Case_with_10_timesteps/Real0/BRUGGE_0000.EGRID") - casePaths.append(dataroot.PATH + "/Case_with_10_timesteps/Real30/BRUGGE_0030.EGRID") - + casePaths.append(dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID") + casePaths.append(dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID") + caseNames = [] for casePath in casePaths: caseName = os.path.splitext(os.path.basename(casePath))[0] @@ -49,6 +50,7 @@ def test_10k(rips_instance, initializeTest): daysSinceStart = case.daysSinceStart() assert(len(daysSinceStart) == 9) +@pytest.mark.skipif(sys.platform.startswith('linux'), reason="Brugge is currently exceptionally slow on Linux") def test_brugge_0010(rips_instance, initializeTest): casePath = dataroot.PATH + "/Case_with_10_timesteps/Real10/BRUGGE_0010.EGRID" case = rips_instance.project.loadCase(path=casePath) From 58765ffdd4560e41e22fba12bc16e2e850c155ec Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Thu, 6 Jun 2019 14:17:08 +0200 Subject: [PATCH 148/396] Python: close project before QCoreApplication::quit when told to exit by gRPC call --- ApplicationCode/Application/RiaGuiApplication.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/ApplicationCode/Application/RiaGuiApplication.cpp b/ApplicationCode/Application/RiaGuiApplication.cpp index b2180ef5cf..9ea84ad600 100644 --- a/ApplicationCode/Application/RiaGuiApplication.cpp +++ b/ApplicationCode/Application/RiaGuiApplication.cpp @@ -1692,6 +1692,7 @@ void RiaGuiApplication::runIdleProcessing() #ifdef ENABLE_GRPC if (RiaGrpcServer::receivedExitRequest()) { + closeProject(); m_grpcServer->quit(); QCoreApplication::quit(); } From eaf795112fc57311a2ae9b849ebfc9c0f8727977 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Thu, 6 Jun 2019 14:23:18 +0200 Subject: [PATCH 149/396] Python: increase the amount of times we try to connect to ResInsight --- ApplicationCode/GrpcInterface/Python/rips/Instance.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ApplicationCode/GrpcInterface/Python/rips/Instance.py b/ApplicationCode/GrpcInterface/Python/rips/Instance.py index a1904352ef..b7610a5892 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Instance.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Instance.py @@ -86,7 +86,7 @@ class Instance: versionOk = False if launched: - for i in range(0, 5): + for i in range(0, 10): connectionOk, versionOk = self.checkVersion() if connectionOk: break From 8ca8d5d2d837e8475583d00e4728e0ed76a39020 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Thu, 6 Jun 2019 14:37:57 +0200 Subject: [PATCH 150/396] Python: increase timeout for looking and more informative error message if it fails --- ApplicationCode/GrpcInterface/Python/rips/Instance.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ApplicationCode/GrpcInterface/Python/rips/Instance.py b/ApplicationCode/GrpcInterface/Python/rips/Instance.py index b7610a5892..47b41ed13f 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Instance.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Instance.py @@ -90,12 +90,15 @@ class Instance: connectionOk, versionOk = self.checkVersion() if connectionOk: break - time.sleep(0.5) + time.sleep(1.0) else: connectionOk, versionOk = self.checkVersion() if not connectionOk: - raise Exception('Error: Could not connect to resinsight at ', location) + if launched: + raise Exception('Error: Could not connect to resinsight at ', location, ' after trying 10 times with 1 second apart') + else: + raise Exception('Error: Could not connect to resinsight at ', location) exit(1) if not versionOk: raise Exception('Error: Wrong Version of ResInsight at ', location) From 3e9ef51c6bef46229b091c7468bfa16d2cf88c79 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Thu, 6 Jun 2019 14:41:40 +0200 Subject: [PATCH 151/396] Python: fix paths to work even if you launch a script from a different folder --- ApplicationCode/GrpcInterface/Python/rips/App.py | 2 +- ApplicationCode/GrpcInterface/Python/rips/Case.py | 2 +- ApplicationCode/GrpcInterface/Python/rips/Commands.py | 2 ++ ApplicationCode/GrpcInterface/Python/rips/Grid.py | 2 +- ApplicationCode/GrpcInterface/Python/rips/Instance.py | 2 +- ApplicationCode/GrpcInterface/Python/rips/Project.py | 2 +- ApplicationCode/GrpcInterface/Python/rips/Properties.py | 2 +- 7 files changed, 8 insertions(+), 6 deletions(-) diff --git a/ApplicationCode/GrpcInterface/Python/rips/App.py b/ApplicationCode/GrpcInterface/Python/rips/App.py index f80e31e69c..96213c0f89 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/App.py +++ b/ApplicationCode/GrpcInterface/Python/rips/App.py @@ -2,7 +2,7 @@ import grpc import os import sys -sys.path.insert(1, os.path.join(sys.path[0], '../generated')) +sys.path.insert(0, os.path.join(os.path.dirname(__file__), '../generated')) from Empty_pb2 import Empty diff --git a/ApplicationCode/GrpcInterface/Python/rips/Case.py b/ApplicationCode/GrpcInterface/Python/rips/Case.py index fad475bb61..85309e5ba3 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Case.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Case.py @@ -4,7 +4,7 @@ import sys from .Grid import Grid from .Properties import Properties -sys.path.insert(1, os.path.join(sys.path[0], '../generated')) +sys.path.insert(0, os.path.join(os.path.dirname(__file__), '../generated')) import Case_pb2 import Case_pb2_grpc diff --git a/ApplicationCode/GrpcInterface/Python/rips/Commands.py b/ApplicationCode/GrpcInterface/Python/rips/Commands.py index e45bc4864b..59270d7d46 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Commands.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Commands.py @@ -2,6 +2,8 @@ import grpc import os import sys +sys.path.insert(0, os.path.join(os.path.dirname(__file__), '../generated')) + from Empty_pb2 import Empty import Commands_pb2 as Cmd import Commands_pb2_grpc as CmdRpc diff --git a/ApplicationCode/GrpcInterface/Python/rips/Grid.py b/ApplicationCode/GrpcInterface/Python/rips/Grid.py index df6fe8c6ef..0a4b8261cc 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Grid.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Grid.py @@ -2,7 +2,7 @@ import grpc import os import sys -sys.path.insert(1, os.path.join(sys.path[0], '../generated')) +sys.path.insert(0, os.path.join(os.path.dirname(__file__), '../generated')) import Grid_pb2 import Grid_pb2_grpc diff --git a/ApplicationCode/GrpcInterface/Python/rips/Instance.py b/ApplicationCode/GrpcInterface/Python/rips/Instance.py index 47b41ed13f..a9f8c75dd3 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Instance.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Instance.py @@ -5,7 +5,7 @@ import socket import logging import time -sys.path.insert(1, os.path.join(sys.path[0], '../generated')) +sys.path.insert(0, os.path.join(os.path.dirname(__file__), '../generated')) import RiaVersionInfo diff --git a/ApplicationCode/GrpcInterface/Python/rips/Project.py b/ApplicationCode/GrpcInterface/Python/rips/Project.py index 797618f582..d17ebc83c4 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Project.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Project.py @@ -5,7 +5,7 @@ import sys from .Case import Case from .Commands import Commands -sys.path.insert(1, os.path.join(sys.path[0], '../generated')) +sys.path.insert(0, os.path.join(os.path.dirname(__file__), '../generated')) from Empty_pb2 import Empty import Project_pb2 diff --git a/ApplicationCode/GrpcInterface/Python/rips/Properties.py b/ApplicationCode/GrpcInterface/Python/rips/Properties.py index 21aec217cd..d7883ab03d 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Properties.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Properties.py @@ -2,7 +2,7 @@ import grpc import os import sys -sys.path.insert(1, os.path.join(sys.path[0], '../generated')) +sys.path.insert(0, os.path.join(os.path.dirname(__file__), '../generated')) import Properties_pb2 import Properties_pb2_grpc From 74718c38fc669c1e3e292498c0519d5107bda8f2 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 7 Jun 2019 12:32:22 +0200 Subject: [PATCH 152/396] #4473 Qt5 : Set Qt5 as default Qt version Still possible to use Qt4 by RESINSIGHT_BUILD_WITH_QT5=OFF --- .appveyor.yml | 2 +- CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 376070813d..79895b564b 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -15,6 +15,6 @@ build_script: if exist "%QT5%" set Path=%QT5%\bin;%Path% - cmake -G "Visual Studio 15 2017 Win64" -DCMAKE_BUILD_TYPE=Release -DRESINSIGHT_BUILD_WITH_QT5=true -DRESINSIGHT_ENABLE_COTIRE=on "-DCMAKE_PREFIX_PATH=%QT5%" .. + cmake -G "Visual Studio 15 2017 Win64" -DCMAKE_BUILD_TYPE=Release -DRESINSIGHT_ENABLE_COTIRE=on "-DCMAKE_PREFIX_PATH=%QT5%" .. cmake --build . --target ResInsight_unity --config Release \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 8f13bd28f3..273dc9432b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -253,7 +253,7 @@ list(APPEND THIRD_PARTY_LIBRARIES ################################################################################ # Qt ################################################################################ -option(RESINSIGHT_BUILD_WITH_QT5 "Use Qt5" OFF) +option(RESINSIGHT_BUILD_WITH_QT5 "Use Qt5" ON) if (RESINSIGHT_BUILD_WITH_QT5) find_package(Qt5 COMPONENTS REQUIRED Core Gui OpenGL Network Script ScriptTools Widgets) From 8ce19c742e8bfd1b316e3f72208b9f59d217b45d Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 7 Jun 2019 14:41:55 +0200 Subject: [PATCH 153/396] #4404 Derived Ensemble: Fix stepping based on data source --- .../RifDerivedEnsembleReader.cpp | 31 ++++--- .../FileInterface/RifDerivedEnsembleReader.h | 2 +- .../RifSummaryReaderInterface.cpp | 23 +++-- .../FileInterface/RifSummaryReaderInterface.h | 3 + .../Summary/RimDerivedEnsembleCase.cpp | 92 +++++++++++-------- .../RimDerivedEnsembleCaseCollection.cpp | 2 +- 6 files changed, 92 insertions(+), 61 deletions(-) diff --git a/ApplicationCode/FileInterface/RifDerivedEnsembleReader.cpp b/ApplicationCode/FileInterface/RifDerivedEnsembleReader.cpp index 839bfa1f92..29ce9daca4 100644 --- a/ApplicationCode/FileInterface/RifDerivedEnsembleReader.cpp +++ b/ApplicationCode/FileInterface/RifDerivedEnsembleReader.cpp @@ -1,17 +1,17 @@ ///////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2017- Statoil ASA -// +// // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// +// // ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. -// -// See the GNU General Public License at +// +// See the GNU General Public License at // for more details. // ///////////////////////////////////////////////////////////////////////////////// @@ -21,22 +21,30 @@ #include "RimDerivedEnsembleCase.h" //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- const std::vector RifDerivedEnsembleReader::EMPTY_TIME_STEPS_VECTOR; //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- -RifDerivedEnsembleReader::RifDerivedEnsembleReader(RimDerivedEnsembleCase* derivedCase) +RifDerivedEnsembleReader::RifDerivedEnsembleReader(RimDerivedEnsembleCase* derivedCase, + RifSummaryReaderInterface* sourceSummaryReader1) { CVF_ASSERT(derivedCase); m_derivedCase = derivedCase; + + if (sourceSummaryReader1) + { + // TODO: This is assuming that the addresses of both reader interfaces are equal + m_allResultAddresses = sourceSummaryReader1->allResultAddresses(); + m_allErrorAddresses = sourceSummaryReader1->allErrorAddresses(); + } } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- const std::vector& RifDerivedEnsembleReader::timeSteps(const RifEclipseSummaryAddress& resultAddress) const { @@ -49,7 +57,7 @@ const std::vector& RifDerivedEnsembleReader::timeSteps(const RifEclipseS } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- bool RifDerivedEnsembleReader::values(const RifEclipseSummaryAddress& resultAddress, std::vector* values) const { @@ -62,12 +70,13 @@ bool RifDerivedEnsembleReader::values(const RifEclipseSummaryAddress& resultAddr auto dataValues = m_derivedCase->values(resultAddress); values->clear(); values->reserve(dataValues.size()); - for (auto val : dataValues) values->push_back(val); + for (auto val : dataValues) + values->push_back(val); return true; } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- std::string RifDerivedEnsembleReader::unitName(const RifEclipseSummaryAddress& resultAddress) const { diff --git a/ApplicationCode/FileInterface/RifDerivedEnsembleReader.h b/ApplicationCode/FileInterface/RifDerivedEnsembleReader.h index e54c88c40f..f5f5efb1e1 100644 --- a/ApplicationCode/FileInterface/RifDerivedEnsembleReader.h +++ b/ApplicationCode/FileInterface/RifDerivedEnsembleReader.h @@ -33,7 +33,7 @@ class RifDerivedEnsembleReader : public RifSummaryReaderInterface static const std::vector EMPTY_TIME_STEPS_VECTOR; public: - RifDerivedEnsembleReader(RimDerivedEnsembleCase* derivedCase); + RifDerivedEnsembleReader(RimDerivedEnsembleCase* derivedCase, RifSummaryReaderInterface* sourceSummaryReader1); const std::vector& timeSteps(const RifEclipseSummaryAddress& resultAddress) const override; bool values(const RifEclipseSummaryAddress& resultAddress, std::vector* values) const override; diff --git a/ApplicationCode/FileInterface/RifSummaryReaderInterface.cpp b/ApplicationCode/FileInterface/RifSummaryReaderInterface.cpp index 4beb891517..0a05128476 100644 --- a/ApplicationCode/FileInterface/RifSummaryReaderInterface.cpp +++ b/ApplicationCode/FileInterface/RifSummaryReaderInterface.cpp @@ -1,17 +1,17 @@ ///////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2017- Statoil ASA -// +// // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// +// // ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. -// -// See the GNU General Public License at +// +// See the GNU General Public License at // for more details. // ///////////////////////////////////////////////////////////////////////////////// @@ -22,9 +22,8 @@ #include - //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- const std::set& RifSummaryReaderInterface::allResultAddresses() const { @@ -32,7 +31,15 @@ const std::set& RifSummaryReaderInterface::allResultAd } //-------------------------------------------------------------------------------------------------- -/// +/// +//-------------------------------------------------------------------------------------------------- +const std::set& RifSummaryReaderInterface::allErrorAddresses() const +{ + return m_allErrorAddresses; +} + +//-------------------------------------------------------------------------------------------------- +/// //-------------------------------------------------------------------------------------------------- RifEclipseSummaryAddress RifSummaryReaderInterface::errorAddress(const RifEclipseSummaryAddress& resultAddress) const { @@ -43,7 +50,7 @@ RifEclipseSummaryAddress RifSummaryReaderInterface::errorAddress(const RifEclips } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- bool RifSummaryReaderInterface::hasAddress(const RifEclipseSummaryAddress& resultAddress) const { diff --git a/ApplicationCode/FileInterface/RifSummaryReaderInterface.h b/ApplicationCode/FileInterface/RifSummaryReaderInterface.h index 732abdc9d0..6cd47c3eec 100644 --- a/ApplicationCode/FileInterface/RifSummaryReaderInterface.h +++ b/ApplicationCode/FileInterface/RifSummaryReaderInterface.h @@ -38,7 +38,10 @@ class RifSummaryReaderInterface : public cvf::Object { public: bool hasAddress(const RifEclipseSummaryAddress& resultAddress) const; + const std::set& allResultAddresses() const; + const std::set& allErrorAddresses() const; + RifEclipseSummaryAddress errorAddress(const RifEclipseSummaryAddress& resultAddress) const; virtual const std::vector& timeSteps(const RifEclipseSummaryAddress& resultAddress) const = 0; diff --git a/ApplicationCode/ProjectDataModel/Summary/RimDerivedEnsembleCase.cpp b/ApplicationCode/ProjectDataModel/Summary/RimDerivedEnsembleCase.cpp index 7d6538b846..83878b8c74 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimDerivedEnsembleCase.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimDerivedEnsembleCase.cpp @@ -1,17 +1,17 @@ ///////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2016- Statoil ASA -// +// // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// +// // ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. -// -// See the GNU General Public License at +// +// See the GNU General Public License at // for more details. // ///////////////////////////////////////////////////////////////////////////////// @@ -28,9 +28,9 @@ #include "RimMainPlotCollection.h" #include "RimOilField.h" #include "RimProject.h" +#include "RimSummaryCaseCollection.h" #include "RimSummaryCaseMainCollection.h" #include "RimSummaryPlotCollection.h" -#include "RimSummaryCaseCollection.h" #include "cvfAssert.h" @@ -39,17 +39,19 @@ CAF_PDM_ABSTRACT_SOURCE_INIT(RimDerivedEnsembleCase, "RimDerivedEnsembleCase"); //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- const std::vector RimDerivedEnsembleCase::EMPTY_TIME_STEPS_VECTOR; const std::vector RimDerivedEnsembleCase::EMPTY_VALUES_VECTOR; //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- -RimDerivedEnsembleCase::RimDerivedEnsembleCase() : m_summaryCase1(nullptr), m_summaryCase2(nullptr) +RimDerivedEnsembleCase::RimDerivedEnsembleCase() + : m_summaryCase1(nullptr) + , m_summaryCase2(nullptr) { - CAF_PDM_InitObject("Summary Case",":/SummaryCase16x16.png","",""); + CAF_PDM_InitObject("Summary Case", ":/SummaryCase16x16.png", "", ""); CAF_PDM_InitFieldNoDefault(&m_summaryCase1, "SummaryCase1", "SummaryCase1", "", "", ""); CAF_PDM_InitFieldNoDefault(&m_summaryCase2, "SummaryCase2", "SummaryCase2", "", "", ""); @@ -57,15 +59,12 @@ RimDerivedEnsembleCase::RimDerivedEnsembleCase() : m_summaryCase1(nullptr), m_su } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- -RimDerivedEnsembleCase::~RimDerivedEnsembleCase() -{ - -} +RimDerivedEnsembleCase::~RimDerivedEnsembleCase() {} //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- void RimDerivedEnsembleCase::setInUse(bool inUse) { @@ -80,7 +79,7 @@ void RimDerivedEnsembleCase::setInUse(bool inUse) } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- bool RimDerivedEnsembleCase::isInUse() const { @@ -88,7 +87,7 @@ bool RimDerivedEnsembleCase::isInUse() const } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- void RimDerivedEnsembleCase::setSummaryCases(RimSummaryCase* sumCase1, RimSummaryCase* sumCase2) { @@ -98,7 +97,7 @@ void RimDerivedEnsembleCase::setSummaryCases(RimSummaryCase* sumCase1, RimSummar } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- bool RimDerivedEnsembleCase::needsCalculation(const RifEclipseSummaryAddress& address) const { @@ -106,7 +105,7 @@ bool RimDerivedEnsembleCase::needsCalculation(const RifEclipseSummaryAddress& ad } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- const std::vector& RimDerivedEnsembleCase::timeSteps(const RifEclipseSummaryAddress& address) const { @@ -115,7 +114,7 @@ const std::vector& RimDerivedEnsembleCase::timeSteps(const RifEclipseSum } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- const std::vector& RimDerivedEnsembleCase::values(const RifEclipseSummaryAddress& address) const { @@ -124,14 +123,14 @@ const std::vector& RimDerivedEnsembleCase::values(const RifEclipseSummar } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- void RimDerivedEnsembleCase::calculate(const RifEclipseSummaryAddress& address) { clearData(address); - RifSummaryReaderInterface* reader1 = m_summaryCase1 ? m_summaryCase1->summaryReader() : nullptr; - RifSummaryReaderInterface* reader2 = m_summaryCase2 ? m_summaryCase2->summaryReader() : nullptr; + RifSummaryReaderInterface* reader1 = m_summaryCase1 ? m_summaryCase1->summaryReader() : nullptr; + RifSummaryReaderInterface* reader2 = m_summaryCase2 ? m_summaryCase2->summaryReader() : nullptr; if (!reader1 || !reader2 || !parentEnsemble()) return; if (!reader1->hasAddress(address) || !reader2->hasAddress(address)) @@ -144,10 +143,10 @@ void RimDerivedEnsembleCase::calculate(const RifEclipseSummaryAddress& address) return; } - RiaTimeHistoryCurveMerger merger; - std::vector values1; - std::vector values2; - DerivedEnsembleOperator op = parentEnsemble()->op(); + RiaTimeHistoryCurveMerger merger; + std::vector values1; + std::vector values2; + DerivedEnsembleOperator op = parentEnsemble()->op(); reader1->values(address, &values1); reader2->values(address, &values2); @@ -159,7 +158,7 @@ void RimDerivedEnsembleCase::calculate(const RifEclipseSummaryAddress& address) std::vector& allValues1 = merger.interpolatedCurveValuesForAllTimeSteps(0); std::vector& allValues2 = merger.interpolatedCurveValuesForAllTimeSteps(1); - size_t sampleCount = merger.allTimeSteps().size(); + size_t sampleCount = merger.allTimeSteps().size(); std::vector calculatedValues; calculatedValues.reserve(sampleCount); for (size_t i = 0; i < sampleCount; i++) @@ -174,33 +173,46 @@ void RimDerivedEnsembleCase::calculate(const RifEclipseSummaryAddress& address) } } - auto& dataItem = m_data[address]; - dataItem.first = merger.allTimeSteps(); + auto& dataItem = m_data[address]; + dataItem.first = merger.allTimeSteps(); dataItem.second = calculatedValues; } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- QString RimDerivedEnsembleCase::caseName() const { auto case1Name = m_summaryCase1->caseName(); auto case2Name = m_summaryCase2->caseName(); - if (case1Name == case2Name) return case1Name; - else return QString("%1/%2").arg(case1Name).arg(case2Name); + if (case1Name == case2Name) + return case1Name; + else + return QString("%1/%2").arg(case1Name).arg(case2Name); } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- void RimDerivedEnsembleCase::createSummaryReaderInterface() { - m_reader.reset(new RifDerivedEnsembleReader(this)); + RifSummaryReaderInterface* summaryCase1Reader = nullptr; + if (m_summaryCase1) + { + if (!m_summaryCase1->summaryReader()) + { + m_summaryCase1->createSummaryReaderInterface(); + } + + summaryCase1Reader = m_summaryCase1->summaryReader(); + } + + m_reader.reset(new RifDerivedEnsembleReader(this, summaryCase1Reader)); } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- RifSummaryReaderInterface* RimDerivedEnsembleCase::summaryReader() { @@ -208,7 +220,7 @@ RifSummaryReaderInterface* RimDerivedEnsembleCase::summaryReader() } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- void RimDerivedEnsembleCase::updateFilePathsFromProjectPath(const QString& newProjectPath, const QString& oldProjectPath) { @@ -216,9 +228,9 @@ void RimDerivedEnsembleCase::updateFilePathsFromProjectPath(const QString& newPr } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- -RimDerivedEnsembleCaseCollection * RimDerivedEnsembleCase::parentEnsemble() const +RimDerivedEnsembleCaseCollection* RimDerivedEnsembleCase::parentEnsemble() const { RimDerivedEnsembleCaseCollection* ensemble; firstAncestorOrThisOfType(ensemble); @@ -226,7 +238,7 @@ RimDerivedEnsembleCaseCollection * RimDerivedEnsembleCase::parentEnsemble() cons } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- void RimDerivedEnsembleCase::clearData(const RifEclipseSummaryAddress& address) { diff --git a/ApplicationCode/ProjectDataModel/Summary/RimDerivedEnsembleCaseCollection.cpp b/ApplicationCode/ProjectDataModel/Summary/RimDerivedEnsembleCaseCollection.cpp index 805bd86ac4..882d84cfb1 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimDerivedEnsembleCaseCollection.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimDerivedEnsembleCaseCollection.cpp @@ -152,8 +152,8 @@ void RimDerivedEnsembleCaseCollection::updateDerivedEnsembleCases() if (!sumCase2) continue; auto derivedCase = firstCaseNotInUse(); - derivedCase->createSummaryReaderInterface(); derivedCase->setSummaryCases(sumCase1, sumCase2); + derivedCase->createSummaryReaderInterface(); derivedCase->setCaseRealizationParameters(crp); derivedCase->setInUse(true); } From e2686b28e6c63499533304e7e2ee36aebbd78070 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 7 Jun 2019 15:19:31 +0200 Subject: [PATCH 154/396] #4385 Well Allocation: Fix missing x-axis units --- ApplicationCode/UserInterface/RiuWellLogTrack.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ApplicationCode/UserInterface/RiuWellLogTrack.cpp b/ApplicationCode/UserInterface/RiuWellLogTrack.cpp index d12ecd2845..6388b9200d 100644 --- a/ApplicationCode/UserInterface/RiuWellLogTrack.cpp +++ b/ApplicationCode/UserInterface/RiuWellLogTrack.cpp @@ -130,9 +130,9 @@ void RiuWellLogTrack::setDepthTitle(const QString& title) void RiuWellLogTrack::setXTitle(const QString& title) { QwtText axisTitleX = axisTitle(QwtPlot::xTop); - axisTitleX.setText(title); if (title != axisTitleX.text()) { + axisTitleX.setText(title); setAxisTitle(QwtPlot::xTop, axisTitleX); } } From 92f2e085b09356f66a300621328f39f5039c4621 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Fri, 7 Jun 2019 09:38:54 -0400 Subject: [PATCH 155/396] Add a build script for GRPC on Linux GrpcInstall/ --- build_grpc_linux.sh | 53 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100755 build_grpc_linux.sh diff --git a/build_grpc_linux.sh b/build_grpc_linux.sh new file mode 100755 index 0000000000..749c236d30 --- /dev/null +++ b/build_grpc_linux.sh @@ -0,0 +1,53 @@ +#!/bin/bash + +if [ $# -lt 2 ]; then + echo "You need to provide two arguments:" + echo " 1. The folder in which to clone and build grpc" + echo " 2. The folder in which to install grpc" + echo "Both folders need to be user writeable but will be created if they do not exist" + echo "Example: " + echo " build_grpc.sh /tmp/grpc `pwd`/GrpcInstall" + exit 1 +fi + +parentdir="$(dirname $1)" +if [ -d $1 ]; then + if ! [ -w $1 ]; then + echo "$1 exists and you don't have the permissions to write to it" + exit 1 + fi +elif [ -d ${parentdir} ]; then + if ! [ -w ${parentdir} ]; then + echo "You don't have the permissions to write to ${parentdir}" + exit 1 + fi +else + echo "${parentdir} does not exist" + exit 1 +fi + +if [ -d "$2" ]; then + if ! [ -w "$2" ]; then + echo "You don't have the permissions to write to $2" + exit 1 + fi +else + mkdir -p "$2" || { echo "Failed to create $2. Make sure you have write permissions." ; exit 1; } +fi + + +echo "Cloning GRPC repository to: $1" +echo "Installing to: $2" + +git clone https://github.com/grpc/grpc.git $1 +cd $1 +git checkout v1.21.1 +git submodule init +git submodule update +export PROTOBUF_CONFIG_OPTS="--prefix=$2" +make prefix=$2 +echo "Installing GRPC to $2" +make install prefix=$2 +cd third_party/protobuf +make install + From 6fae8f9c9487d75d8510e64a507a4e3230909b99 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 7 Jun 2019 15:54:07 +0200 Subject: [PATCH 156/396] Summary Import : Limit size of error message to be displayed --- .../Summary/RimSummaryCaseCollection.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCaseCollection.cpp b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCaseCollection.cpp index 8ece76742b..95396885f6 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCaseCollection.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCaseCollection.cpp @@ -497,14 +497,16 @@ bool RimSummaryCaseCollection::validateEnsembleCases(const std::vector Date: Sun, 9 Jun 2019 11:28:30 +0200 Subject: [PATCH 157/396] Updated GRPC install instructions --- GRPC_install_instructions.txt | 57 +++++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 20 deletions(-) diff --git a/GRPC_install_instructions.txt b/GRPC_install_instructions.txt index 2243a31dc2..30c634c8ac 100644 --- a/GRPC_install_instructions.txt +++ b/GRPC_install_instructions.txt @@ -18,24 +18,41 @@ git clone https://github.com/microsoft/vcpkg.git -DCMAKE_TOOLCHAIN_FILE=LOCATION_OF_VCPKG/scripts/buildsystems/vcpkg.cmake -A x64 -############ Linux as STANDALONE GPRC (using GRPC_INSTALL_PREFIX=/opt/grpc as an example) ############### -1. Clone grpc -git clone https://github.com/grpc/grpc.git -2. From within grpc folder, check out stable version of grpc and initialise repo: -git checkout v1.20.1 -git submodule init -git submodule update -3. Make sure you're building with devtools-3, since you'll be using that for ResInsight too -scl enable devtoolset-3 bash -export PROTOBUF_CONFIG_OPTS="--prefix=/opt/grpc" -make prefix=/opt/grpc -sudo make prefix=/opt/grpc install -4. Install protobuf (still within grpc folder) -cd third_party/protobuf -sudo make install -5. Make sure you have a Python 3 version available in your paths. -I.e.: "sudo yum install rh-python35" and then "scl enable rh-python35 bash" -6. Install grpcio-tools for Python (this may have to be done as root user): -pip install grpcio-tools -7. Run cmake making sure GRPC_INSTALL_PREFIX is set to /opt/grpc, PYTHON_EXECUTABLE set to a good python 3 and RESINSIGHT_ENABLE_GRPC = true +############ Linux as STANDALONE GPRC ############### + +######################################################################################################### +# 1. install autotools, autoconf and libtool with your distributions package manager. +# +# On Centos 6 you will need a newer Python and newer version of GCC than the standard version +# ResInsight AND gRPC will build with devtoolset-3+ but apparently devtoolset-3 is now gone +# So you will need to install devtoolset-6, devtoolset-7 or devtoolset-8. +# It makes sense to install devtoolset-6* (with asterix) to get all the necessary devtoolset packages +# You will also need a version of Python 3.5 +# +########################################################################################################## + +################################################################### +# 2. Enable compiler and Python on Centos 6 (on other distributions, this may be different) +################################################################### +sudo yum install devtoolset-6* rh-python35 autotools autoconf libtool yum +scl enable devtoolset-6 rh-python35 bash + +################################################################################################################ +# 3. Run grpc install script and install to a user-writable directory. I.e, from within the ResInsight folder: +# Most of this runs fine without root. But unfortunately grpc currently fails to install the C++ library without root. +# So the script is required to be run as root even if the provided folders are writeable by the user +# WARNING: As of grpc 1.21.1 a long install directory (/opt/grpc in the example below) may get you into trouble +# with this bug: https://github.com/grpc/grpc/issues/14844 +# A patch is available in the issue, but the easiest thing to do is to ensure a short install path +################################################################################################################ + +sudo ./build-grpc-centos.sh /tmp/grpc /opt/grpc + +############################################################################## +# 4. Install grpcio-tools for Python (this may have to be done as root user): +############################################################################## +sudo pip install grpcio-tools + +################################################################################# +# 5. Run cmake making sure GRPC_INSTALL_PREFIX is set to the Grpc install folder, PYTHON_EXECUTABLE set to a good python 3 and RESINSIGHT_ENABLE_GRPC = true From ea4f310bc40d37a85521f44d17f7e938ec10873f Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Sun, 9 Jun 2019 11:35:49 +0200 Subject: [PATCH 158/396] More improvements to install instructions --- GRPC_install_instructions.txt | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/GRPC_install_instructions.txt b/GRPC_install_instructions.txt index 30c634c8ac..a9f842f916 100644 --- a/GRPC_install_instructions.txt +++ b/GRPC_install_instructions.txt @@ -31,10 +31,12 @@ git clone https://github.com/microsoft/vcpkg.git # ########################################################################################################## +sudo yum install autotools autoconf libtool devtoolset-6* rh-python35 + ################################################################### # 2. Enable compiler and Python on Centos 6 (on other distributions, this may be different) ################################################################### -sudo yum install devtoolset-6* rh-python35 autotools autoconf libtool yum + scl enable devtoolset-6 rh-python35 bash ################################################################################################################ @@ -49,10 +51,30 @@ scl enable devtoolset-6 rh-python35 bash sudo ./build-grpc-centos.sh /tmp/grpc /opt/grpc ############################################################################## -# 4. Install grpcio-tools for Python (this may have to be done as root user): +# Python GRPC module, OPTION 1 +# 5a. Install grpcio-tools for Python as root user. If you cannot install python packages as root user, see 4b. +# NOTE: IF THIS FAILS WITH AN ERROR MESSAGE FROM PIP ABOUT +# "YOU SHOULD CONSIDER UPGRADING VIA 'python -m pip install --upgrade pip'" +# Then performing this should fix the problem. ############################################################################## -sudo pip install grpcio-tools + +sudo python -m pip install grpcio-tools + +############################################################################## +# Python GRPC module, OPTION 2 +# 5b. Install grpcio-tools for Python as regular user. +# NOTE: IF THIS FAILS WITH AN ERROR MESSAGE FROM PIP ABOUT +# "YOU SHOULD CONSIDER UPGRADING VIA 'python -m pip install --upgrade pip'" +# Then performing this should fix the problem. +############################################################################## + +python -m pip install --user grpcio-tools + ################################################################################# -# 5. Run cmake making sure GRPC_INSTALL_PREFIX is set to the Grpc install folder, PYTHON_EXECUTABLE set to a good python 3 and RESINSIGHT_ENABLE_GRPC = true - +# 6. Run cmake making sure of the following: +# * GRPC_INSTALL_PREFIX is set to the Grpc install folder, +# * PYTHON_EXECUTABLE set to a good python 3 +# * RESINSIGHT_ENABLE_GRPC = true +################################ +See regular build instructions for the rest \ No newline at end of file From 8283d1ac8663b1e8975bf873e51745a26c19406a Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Tue, 11 Jun 2019 09:53:21 +0200 Subject: [PATCH 159/396] Python: test for opening project --- ApplicationCode/GrpcInterface/CMakeLists.cmake | 1 + .../GrpcInterface/Python/tests/test_project.py | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 ApplicationCode/GrpcInterface/Python/tests/test_project.py diff --git a/ApplicationCode/GrpcInterface/CMakeLists.cmake b/ApplicationCode/GrpcInterface/CMakeLists.cmake index 1e810b7009..b3337d5973 100644 --- a/ApplicationCode/GrpcInterface/CMakeLists.cmake +++ b/ApplicationCode/GrpcInterface/CMakeLists.cmake @@ -172,6 +172,7 @@ if (PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) "tests/test_commands.py" "tests/test_grids.py" "tests/test_properties.py" + "tests/test_project.py" "tests/conftest.py" "tests/dataroot.py" "requirements.txt" diff --git a/ApplicationCode/GrpcInterface/Python/tests/test_project.py b/ApplicationCode/GrpcInterface/Python/tests/test_project.py new file mode 100644 index 0000000000..3786b918ff --- /dev/null +++ b/ApplicationCode/GrpcInterface/Python/tests/test_project.py @@ -0,0 +1,17 @@ +import sys +import os +import pytest + +sys.path.insert(1, os.path.join(sys.path[0], '..')) +import rips + +import dataroot + +def test_loadProject(rips_instance, initializeTest): + project = rips_instance.project.open(dataroot.PATH + "/TEST10K_FLT_LGR_NNC/10KWithWellLog.rsp") + case = project.case(id=0) + assert(case is not None) + assert(case.name == "TEST10K_FLT_LGR_NNC") + assert(case.id == 0) + cases = rips_instance.project.cases() + assert(len(cases) is 1) \ No newline at end of file From 979a109f80e8f74d639d9225329a0409bc49387e Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Tue, 11 Jun 2019 09:54:16 +0200 Subject: [PATCH 160/396] #4476 Fix reload of group by formation when a 3d Filter View is enabled * Need to ensure the display model has been created by the time the cross plot is created. --- ApplicationCode/Application/RiaApplication.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ApplicationCode/Application/RiaApplication.cpp b/ApplicationCode/Application/RiaApplication.cpp index 98385e1bad..8f000f6b83 100644 --- a/ApplicationCode/Application/RiaApplication.cpp +++ b/ApplicationCode/Application/RiaApplication.cpp @@ -28,6 +28,7 @@ #include "RiaProjectModifier.h" #include "RiaSocketServer.h" #include "RiaVersionInfo.h" +#include "RiaViewRedrawScheduler.h" #include "ExportCommands/RicSnapshotAllViewsToFileFeature.h" #include "HoloLensCommands/RicHoloLensSessionManager.h" @@ -590,6 +591,10 @@ bool RiaApplication::loadProject(const QString& projectFileName, oilField->annotationCollection()->loadDataAndUpdate(); } + // Some procedures in onProjectOpened() may rely on the display model having been created + // So we need to force the completion of the display model here. + RiaViewRedrawScheduler::instance()->updateAndRedrawScheduledViews(); + // NB! This function must be called before executing command objects, // because the tree view state is restored from project file and sets // current active view ( see restoreTreeViewState() ) From 99e581fabdf1aa04c2e42dd6c06aa264843622a1 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Tue, 11 Jun 2019 11:11:02 +0200 Subject: [PATCH 161/396] gRPC: Fix mistake in installation instructions --- GRPC_install_instructions.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GRPC_install_instructions.txt b/GRPC_install_instructions.txt index a9f842f916..e2e8cc49ef 100644 --- a/GRPC_install_instructions.txt +++ b/GRPC_install_instructions.txt @@ -48,7 +48,7 @@ scl enable devtoolset-6 rh-python35 bash # A patch is available in the issue, but the easiest thing to do is to ensure a short install path ################################################################################################################ -sudo ./build-grpc-centos.sh /tmp/grpc /opt/grpc +sudo ./build-grpc-linux.sh /tmp/grpc /opt/grpc ############################################################################## # Python GRPC module, OPTION 1 From 79058049c6f80afc38f4b549c1830936807cc6f4 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Tue, 11 Jun 2019 11:13:56 +0200 Subject: [PATCH 162/396] gRPC: Add more comments to install instructions --- GRPC_install_instructions.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/GRPC_install_instructions.txt b/GRPC_install_instructions.txt index e2e8cc49ef..440d581849 100644 --- a/GRPC_install_instructions.txt +++ b/GRPC_install_instructions.txt @@ -46,6 +46,10 @@ scl enable devtoolset-6 rh-python35 bash # WARNING: As of grpc 1.21.1 a long install directory (/opt/grpc in the example below) may get you into trouble # with this bug: https://github.com/grpc/grpc/issues/14844 # A patch is available in the issue, but the easiest thing to do is to ensure a short install path +# +# NOTE: The shell running build-grpc-linux.sh will need the scl enables listed in the previous step. +# This means that if you run the script as root by first doing su and then running without sudo +# ... then root will need to run the scl enable commands ################################################################################################################ sudo ./build-grpc-linux.sh /tmp/grpc /opt/grpc From 0507c5d7754c7af1f849af0c42bbebc36193b70c Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Tue, 11 Jun 2019 11:25:00 +0200 Subject: [PATCH 163/396] gRPC: Cleanup of install instructions --- GRPC_install_instructions.txt | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/GRPC_install_instructions.txt b/GRPC_install_instructions.txt index 440d581849..50ecc6cac0 100644 --- a/GRPC_install_instructions.txt +++ b/GRPC_install_instructions.txt @@ -1,4 +1,9 @@ -########## Windows using vcpkg ################### +########## Windows using vcpkg ############################################################################# +# gRPC should be built once and only updated when there is a specific requirement to do so +# So Step 1-4 are rarely done. +# While Step 5 is instructions for configuring the nightly-build of ResInsight +# Step 5 is not fully described and assumes knowledge of how to build ResInsight normally. See README.md +############################################################################################################ 1. Clone VCPKG git clone https://github.com/microsoft/vcpkg.git 2. Install VCPKG from within vcpkg folder: @@ -12,13 +17,18 @@ git clone https://github.com/microsoft/vcpkg.git python -m pip install grpcio-tools * Make sure the python executable is found by setting -DPYTHON_EXECUTABLE=LOCATION_OF_PYTHON.EXE -4. Run cmake with the following statements +5. Run cmake with the following statements -DRESINSIGHT_ENABLE_GRPC=true -DPYTHON_EXECUTABLE=LOCATION_OF_PYTHON.EXE -DCMAKE_TOOLCHAIN_FILE=LOCATION_OF_VCPKG/scripts/buildsystems/vcpkg.cmake -A x64 -############ Linux as STANDALONE GPRC ############### +############ Linux as STANDALONE GPRC #################################################################### +# gRPC should be built once and only updated when there is a specific requirement to do so +# So Step 1-5 are rarely done. +# While Step 6 is instructions for configuring the nightly-build of ResInsight +# Step 6 is not fully described and assumes knowledge of how to build ResInsight normally. See README.md +########################################################################################################## ######################################################################################################### # 1. install autotools, autoconf and libtool with your distributions package manager. @@ -46,13 +56,9 @@ scl enable devtoolset-6 rh-python35 bash # WARNING: As of grpc 1.21.1 a long install directory (/opt/grpc in the example below) may get you into trouble # with this bug: https://github.com/grpc/grpc/issues/14844 # A patch is available in the issue, but the easiest thing to do is to ensure a short install path -# -# NOTE: The shell running build-grpc-linux.sh will need the scl enables listed in the previous step. -# This means that if you run the script as root by first doing su and then running without sudo -# ... then root will need to run the scl enable commands ################################################################################################################ -sudo ./build-grpc-linux.sh /tmp/grpc /opt/grpc +sudo ./build-grpc-centos.sh /tmp/grpc /opt/grpc ############################################################################## # Python GRPC module, OPTION 1 @@ -74,11 +80,11 @@ sudo python -m pip install grpcio-tools python -m pip install --user grpcio-tools - ################################################################################# -# 6. Run cmake making sure of the following: +# 6. Building ResInsight with GRPC enabled: +# Run cmake making sure of the following: # * GRPC_INSTALL_PREFIX is set to the Grpc install folder, # * PYTHON_EXECUTABLE set to a good python 3 -# * RESINSIGHT_ENABLE_GRPC = true +# * RESINSIGHT_ENABLE_GRPC = true ################################ See regular build instructions for the rest \ No newline at end of file From c2bad4a6863816acd2f988964a0502a6a20b4596 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Sun, 9 Jun 2019 15:35:31 +0200 Subject: [PATCH 164/396] #4421 Python: Add GRPC status to About dialog * If the finish comes because the server is shut down, there is no m_eclipseCase --- ApplicationCode/Application/RiaApplication.h | 5 + .../Application/RiaConsoleApplication.cpp | 10 + .../Application/RiaConsoleApplication.h | 4 + .../Application/RiaGuiApplication.cpp | 10 + .../Application/RiaGuiApplication.h | 3 + .../ApplicationCommands/RicHelpFeatures.cpp | 14 ++ .../GrpcInterface/CMakeLists.cmake.orig | 206 ++++++++++++++++++ .../RiaGrpcPropertiesService.cpp | 9 +- ApplicationCode/GrpcInterface/RiaGrpcServer.h | 2 +- 9 files changed, 259 insertions(+), 4 deletions(-) create mode 100644 ApplicationCode/GrpcInterface/CMakeLists.cmake.orig diff --git a/ApplicationCode/Application/RiaApplication.h b/ApplicationCode/Application/RiaApplication.h index 81660a925a..09f0f7326a 100644 --- a/ApplicationCode/Application/RiaApplication.h +++ b/ApplicationCode/Application/RiaApplication.h @@ -183,7 +183,12 @@ public: virtual void addToRecentFiles(const QString& fileName) {} virtual void showInformationMessage(const QString& infoText) = 0; virtual void showErrorMessage(const QString& errMsg) = 0; + virtual void launchGrpcServer() = 0; + +#ifdef ENABLE_GRPC + virtual RiaGrpcServer* grpcServer() const = 0; +#endif protected: // Protected implementation specific overrides virtual void invokeProcessEvents(QEventLoop::ProcessEventsFlags flags = QEventLoop::AllEvents) = 0; diff --git a/ApplicationCode/Application/RiaConsoleApplication.cpp b/ApplicationCode/Application/RiaConsoleApplication.cpp index 153ca817b9..5c4e6cf53d 100644 --- a/ApplicationCode/Application/RiaConsoleApplication.cpp +++ b/ApplicationCode/Application/RiaConsoleApplication.cpp @@ -352,6 +352,16 @@ void RiaConsoleApplication::launchGrpcServer() #endif } +#ifdef ENABLE_GRPC +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiaGrpcServer* RiaConsoleApplication::grpcServer() const +{ + return m_grpcServer.get(); +} +#endif + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/Application/RiaConsoleApplication.h b/ApplicationCode/Application/RiaConsoleApplication.h index a6fb4e939a..7506a1125e 100644 --- a/ApplicationCode/Application/RiaConsoleApplication.h +++ b/ApplicationCode/Application/RiaConsoleApplication.h @@ -45,6 +45,10 @@ public: void showInformationMessage(const QString& text) override; void showErrorMessage(const QString& errMsg) override; void launchGrpcServer() override; +#ifdef ENABLE_GRPC + RiaGrpcServer* grpcServer() const override; +#endif + protected: // Protected implementation specific overrides void invokeProcessEvents(QEventLoop::ProcessEventsFlags flags = QEventLoop::AllEvents) override; diff --git a/ApplicationCode/Application/RiaGuiApplication.cpp b/ApplicationCode/Application/RiaGuiApplication.cpp index 9ea84ad600..78783583c0 100644 --- a/ApplicationCode/Application/RiaGuiApplication.cpp +++ b/ApplicationCode/Application/RiaGuiApplication.cpp @@ -1243,6 +1243,16 @@ void RiaGuiApplication::launchGrpcServer() #endif } +#ifdef ENABLE_GRPC +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiaGrpcServer* RiaGuiApplication::grpcServer() const +{ + return m_grpcServer.get(); +} +#endif + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/Application/RiaGuiApplication.h b/ApplicationCode/Application/RiaGuiApplication.h index 725d3f3db8..6ff68c02f1 100644 --- a/ApplicationCode/Application/RiaGuiApplication.h +++ b/ApplicationCode/Application/RiaGuiApplication.h @@ -133,6 +133,9 @@ public: void showInformationMessage(const QString& text) override; void showErrorMessage(const QString& errMsg) override; void launchGrpcServer() override; +#ifdef ENABLE_GRPC + RiaGrpcServer* grpcServer() const override; +#endif protected: // Protected RiaApplication overrides void invokeProcessEvents(QEventLoop::ProcessEventsFlags flags = QEventLoop::AllEvents) override; diff --git a/ApplicationCode/Commands/ApplicationCommands/RicHelpFeatures.cpp b/ApplicationCode/Commands/ApplicationCommands/RicHelpFeatures.cpp index 7adff9751a..d77a880452 100644 --- a/ApplicationCode/Commands/ApplicationCommands/RicHelpFeatures.cpp +++ b/ApplicationCode/Commands/ApplicationCommands/RicHelpFeatures.cpp @@ -121,6 +121,20 @@ void RicHelpAboutFeature::onActionTriggered(bool isChecked) dlg.addVersionEntry(" ", txt); } +#ifdef ENABLE_GRPC + RiaGrpcServer* grpcServer = RiaApplication::instance()->grpcServer(); + if (grpcServer && grpcServer->isRunning()) + { + dlg.addVersionEntry(" ", QString(" gRPC available and running at port %1").arg(grpcServer->portNumber())); + } + else + { + dlg.addVersionEntry(" ", QString(" gRPC available but currently disabled in preferences")); + } +#else + dlg.addVersionEntry(" ", " gRPC disabled"); +#endif + if (RiaApplication::enableDevelopmentFeatures()) { QString vendor("Unknown"); diff --git a/ApplicationCode/GrpcInterface/CMakeLists.cmake.orig b/ApplicationCode/GrpcInterface/CMakeLists.cmake.orig new file mode 100644 index 0000000000..3a3f4c43df --- /dev/null +++ b/ApplicationCode/GrpcInterface/CMakeLists.cmake.orig @@ -0,0 +1,206 @@ +cmake_minimum_required (VERSION 2.8.12) + +set ( SOURCE_GROUP_HEADER_FILES + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcServer.h + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcCallbacks.h + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcCallbacks.inl + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcServiceInterface.h + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcCaseService.h + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcGridService.h + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcProjectService.h + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcCommandService.h + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcAppService.h + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcPropertiesService.h +) + +set ( SOURCE_GROUP_SOURCE_FILES + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcServer.cpp + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcServiceInterface.cpp + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcCaseService.cpp + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcGridService.cpp + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcProjectService.cpp + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcCommandService.cpp + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcAppService.cpp + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcPropertiesService.cpp +) + +add_definitions(-DENABLE_GRPC) + +if (MSVC) + add_definitions(-D_WIN32_WINNT=0x600) + + # Find Protobuf installation + # Looks for protobuf-config.cmake file installed by Protobuf's cmake installation. + set(protobuf_MODULE_COMPATIBLE ON CACHE DBOOL "") + find_package(Protobuf CONFIG 3.0 QUIET) + if (Protobuf_FOUND) + message(STATUS "Using protobuf ${protobuf_VERSION}") + else() + message(FATAL_ERROR "Protocol Buffers not found. This is required to build with gRPC") + endif() + + # Find gRPC installation + # Looks for gRPCConfig.cmake file installed by gRPC's cmake installation. + find_package(gRPC CONFIG REQUIRED NO_MODULE) + message(STATUS "Using gRPC ${gRPC_VERSION}") + + set(_PROTOBUF_LIBPROTOBUF protobuf::libprotobuf) + set(_PROTOBUF_PROTOC $) + + set(_GRPC_GRPCPP_UNSECURE gRPC::grpc++_unsecure gRPC::grpc_unsecure gRPC::gpr) + set(_GRPC_CPP_PLUGIN_EXECUTABLE $) + set(GRPC_LIBRARIES ${_GRPC_GRPCPP_UNSECURE} ${_PROTOBUF_LIBPROTOBUF}) + + set_target_properties(${GRPC_LIBRARIES} PROPERTIES + MAP_IMPORTED_CONFIG_MINSIZEREL RELEASE + MAP_IMPORTED_CONFIG_RELWITHDEBINFO RELEASE + ) + +else() + if (NOT DEFINED GRPC_INSTALL_PREFIX OR NOT EXISTS ${GRPC_INSTALL_PREFIX}) + message(FATAL_ERROR "You need a valid GRPC_INSTALL_PREFIX set to build with gRPC") + endif() + set(ENV{PKG_CONFIG_PATH} "${GRPC_INSTALL_PREFIX}/lib/pkgconfig") + find_package(PkgConfig REQUIRED) + pkg_check_modules(GRPC REQUIRED grpc++_unsecure>=1.20 grpc_unsecure gpr protobuf) + set(_PROTOBUF_PROTOC "${GRPC_INSTALL_PREFIX}/bin/protoc") + set(_GRPC_CPP_PLUGIN_EXECUTABLE "${GRPC_INSTALL_PREFIX}/bin/grpc_cpp_plugin") + include_directories(AFTER ${GRPC_INCLUDE_DIRS}) +endif() + +# Cannot use the nice new FindPackage modules for python since that is CMake 3.12+ +if(PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) + message(STATUS "Using Python ${PYTHON_EXECUTABLE}") +endif(PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) + +# Proto files +set(PROTO_FILES + "Empty" + "Case" + "Project" + "Commands" + "App" + "Properties" + "Grid" +) + +set(GRPC_PYTHON_SOURCE_PATH "${CMAKE_CURRENT_LIST_DIR}/Python") +set(GRPC_PYTHON_DEST_PATH "${CMAKE_BINARY_DIR}/Python") + +foreach(proto_file ${PROTO_FILES}) + get_filename_component(rips_proto "${CMAKE_CURRENT_LIST_DIR}/GrpcProtos/${proto_file}.proto" ABSOLUTE) + get_filename_component(rips_proto_path "${rips_proto}" PATH) + + list(APPEND GRPC_PROTO_FILES_FULL_PATH ${rips_proto}) + + set(rips_proto_srcs "${CMAKE_BINARY_DIR}/Generated/${proto_file}.pb.cc") + set(rips_proto_hdrs "${CMAKE_BINARY_DIR}/Generated/${proto_file}.pb.h") + set(rips_grpc_srcs "${CMAKE_BINARY_DIR}/Generated/${proto_file}.grpc.pb.cc") + set(rips_grpc_hdrs "${CMAKE_BINARY_DIR}/Generated/${proto_file}.grpc.pb.h") + + add_custom_command( + OUTPUT "${rips_proto_srcs}" "${rips_proto_hdrs}" "${rips_grpc_srcs}" "${rips_grpc_hdrs}" + COMMAND ${_PROTOBUF_PROTOC} + ARGS --grpc_out "${CMAKE_BINARY_DIR}/Generated" + --cpp_out "${CMAKE_BINARY_DIR}/Generated" + -I "${rips_proto_path}" + --plugin=protoc-gen-grpc="${_GRPC_CPP_PLUGIN_EXECUTABLE}" + "${rips_proto}" + DEPENDS "${rips_proto}" + ) + + if (PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) + set(rips_proto_python "generated/${proto_file}_pb2.py") + set(rips_grpc_python "generated/${proto_file}_pb2_grpc.py") + + add_custom_command( + OUTPUT "${GRPC_PYTHON_SOURCE_PATH}/${rips_proto_python}" "${GRPC_PYTHON_SOURCE_PATH}/${rips_grpc_python}" + COMMAND ${PYTHON_EXECUTABLE} + ARGS -m grpc_tools.protoc + -I "${rips_proto_path}" + --python_out "${GRPC_PYTHON_SOURCE_PATH}/generated" + --grpc_python_out "${GRPC_PYTHON_SOURCE_PATH}/generated" + "${rips_proto}" + DEPENDS "${rips_proto}" + COMMENT "Generating ${rips_proto_python} and ${rips_grpc_python}" + VERBATIM + ) + list (APPEND GRPC_PYTHON_GENERATED_SOURCES + ${rips_proto_python} + ${rips_grpc_python} + ) + + endif(PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) + + list( APPEND GRPC_HEADER_FILES + ${rips_proto_hdrs} + ${rips_grpc_hdrs} + ) + + list( APPEND GRPC_CPP_SOURCES + ${rips_proto_srcs} + ${rips_grpc_srcs} + ) + +endforeach(proto_file) + +if (PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) + list(APPEND GRPC_PYTHON_SOURCES + ${GRPC_PYTHON_GENERATED_SOURCES} + "generated/RiaVersionInfo.py" + "rips/__init__.py" + "rips/App.py" + "rips/Case.py" + "rips/Commands.py" + "rips/Grid.py" + "rips/Project.py" + "rips/Properties.py" + "rips/Instance.py" + "examples/CommandExample.py" + "examples/CaseInfoStreamingExample.py" + "examples/SoilPorvAsync.py" + "examples/SoilPorvSync.py" + "examples/SelectedCases.py" + "examples/AllCases.py" + "examples/SetGridProperties.py" + "examples/GridInformation.py" + "examples/InputPropTestSync.py" + "examples/InputPropTestAsync.py" + "examples/SoilAverage.py" + "examples/SoilAverageNoComm.py" + "tests/test_cases.py" +<<<<<<< Updated upstream + "tests/test_commands.py" +======= +>>>>>>> Stashed changes + "tests/test_grids.py" + "tests/test_properties.py" + "tests/conftest.py" + "tests/dataroot.py" + "requirements.txt" + "setup.py.cmake" + "README.md" + "LICENSE" + ) + + foreach(PYTHON_SCRIPT ${GRPC_PYTHON_SOURCES}) + list(APPEND GRPC_PYTHON_SOURCES_FULL_PATH "${GRPC_PYTHON_SOURCE_PATH}/${PYTHON_SCRIPT}") + endforeach() +if (MSVC) + source_group(TREE ${GRPC_PYTHON_SOURCE_PATH} FILES ${GRPC_PYTHON_SOURCES_FULL_PATH} PREFIX "GrpcInterface\\Python") +endif(MSVC) + +endif(PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) + +list ( APPEND GRPC_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES}) +list ( APPEND GRPC_CPP_SOURCES ${SOURCE_GROUP_SOURCE_FILES}) + +CONFIGURE_FILE( ${CMAKE_SOURCE_DIR}/ApplicationCode/Adm/RiaVersionInfo.py.cmake + ${GRPC_PYTHON_SOURCE_PATH}/generated/RiaVersionInfo.py +) +CONFIGURE_FILE( ${GRPC_PYTHON_SOURCE_PATH}/setup.py.cmake + ${GRPC_PYTHON_SOURCE_PATH}/setup.py +) + +source_group( "GrpcInterface" FILES ${SOURCE_GROUP_HEADER_FILES} ${SOURCE_GROUP_SOURCE_FILES} ${CMAKE_CURRENT_LIST_DIR}/CMakeLists.cmake ) +source_group( "GrpcInterface\\GrpcProtos" FILES ${GRPC_PROTO_FILES_FULL_PATH} ) \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp b/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp index 0389c8cefe..18d3767f08 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp +++ b/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp @@ -172,10 +172,13 @@ public: //-------------------------------------------------------------------------------------------------- void finish() { - for (Rim3dView* view : m_eclipseCase->views()) + if (m_eclipseCase) { - view->setCurrentTimeStepAndUpdate(view->currentTimeStep()); - view->createDisplayModelAndRedraw(); + for (Rim3dView* view : m_eclipseCase->views()) + { + view->setCurrentTimeStepAndUpdate(view->currentTimeStep()); + view->createDisplayModelAndRedraw(); + } } } diff --git a/ApplicationCode/GrpcInterface/RiaGrpcServer.h b/ApplicationCode/GrpcInterface/RiaGrpcServer.h index 769bfd348e..c5402b3ec3 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcServer.h +++ b/ApplicationCode/GrpcInterface/RiaGrpcServer.h @@ -45,7 +45,7 @@ public: void quit(); static int findAvailablePortNumber(int defaultPortNumber); static void setReceivedExitRequest(); - static bool receivedExitRequest(); + static bool receivedExitRequest(); private: void initialize(); From 8f6858932b9c4ecdbb10dbdbb8cc3e4634da8e0f Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Tue, 11 Jun 2019 13:05:01 +0200 Subject: [PATCH 165/396] gRPC: Upgrade install instructions with pip user upgrade --- GRPC_install_instructions.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/GRPC_install_instructions.txt b/GRPC_install_instructions.txt index 50ecc6cac0..51ef9e81b9 100644 --- a/GRPC_install_instructions.txt +++ b/GRPC_install_instructions.txt @@ -58,7 +58,7 @@ scl enable devtoolset-6 rh-python35 bash # A patch is available in the issue, but the easiest thing to do is to ensure a short install path ################################################################################################################ -sudo ./build-grpc-centos.sh /tmp/grpc /opt/grpc +sudo ./build-grpc-linux.sh /tmp/grpc /opt/grpc ############################################################################## # Python GRPC module, OPTION 1 @@ -66,6 +66,7 @@ sudo ./build-grpc-centos.sh /tmp/grpc /opt/grpc # NOTE: IF THIS FAILS WITH AN ERROR MESSAGE FROM PIP ABOUT # "YOU SHOULD CONSIDER UPGRADING VIA 'python -m pip install --upgrade pip'" # Then performing this should fix the problem. +# It IS possible to upgrade pip as a regular user: python -m pip install --user --upgrade pip ############################################################################## sudo python -m pip install grpcio-tools From fe268cd25f9511d48ed675a4b3849b9ec846812e Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Tue, 11 Jun 2019 15:15:26 +0200 Subject: [PATCH 166/396] Python: create PyDoc type docs, fix some inconsistencies in code and update rips module version --- .../GrpcInterface/Python/rips/App.py | 19 +++- .../GrpcInterface/Python/rips/Case.py | 44 ++++++++- .../GrpcInterface/Python/rips/Commands.py | 61 +++++++------ .../GrpcInterface/Python/rips/Grid.py | 9 ++ .../GrpcInterface/Python/rips/Instance.py | 63 ++++++++++--- .../GrpcInterface/Python/rips/Project.py | 35 +++++++ .../GrpcInterface/Python/rips/Properties.py | 91 +++++++++++++++++-- .../GrpcInterface/Python/setup.py.cmake | 2 +- 8 files changed, 268 insertions(+), 56 deletions(-) diff --git a/ApplicationCode/GrpcInterface/Python/rips/App.py b/ApplicationCode/GrpcInterface/Python/rips/App.py index 96213c0f89..05ec7857c5 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/App.py +++ b/ApplicationCode/GrpcInterface/Python/rips/App.py @@ -10,22 +10,33 @@ import App_pb2 import App_pb2_grpc class App: + """ResInsight application information and control. + Allows retrieving of information and controlling the running instance + Not meant to be constructed manually, but exists as part of the Instance method + """ def __init__(self, channel): self.app = App_pb2_grpc.AppStub(channel) - def versionMessage(self): + def __versionMessage(self): return self.app.GetVersion(Empty()) def majorVersion(self): - return self.versionMessage().major_version + """Get an integer with the major version number""" + return self.__versionMessage().major_version def minorVersion(self): - return self.versionMessage().minor_version + """Get an integer with the minor version number""" + return self.__versionMessage().minor_version def patchVersion(self): - return self.versionMessage().patch_version + """Get an integer with the patch version number""" + return self.__versionMessage().patch_version def versionString(self): + """Get a full version string, i.e. 2019.04.01""" return str(self.majorVersion()) + "." + str(self.minorVersion()) + "." + str(self.patchVersion()) def exit(self): + """Tell ResInsight instance to quit""" print("Telling ResInsight to Exit") return self.app.Exit(Empty()) def isConsole(self): + """Returns true if the connected ResInsight instance is a console app""" return self.app.GetRuntimeInfo(Empty()).app_type == App_pb2.ApplicationTypeEnum.Value('CONSOLE_APPLICATION') def isGui(self): + """Returns true if the connected ResInsight instance is a GUI app""" return self.app.GetRuntimeInfo(Empty()).app_type == App_pb2.ApplicationTypeEnum.Value('GUI_APPLICATION') diff --git a/ApplicationCode/GrpcInterface/Python/rips/Case.py b/ApplicationCode/GrpcInterface/Python/rips/Case.py index 85309e5ba3..bc31487ed4 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Case.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Case.py @@ -10,6 +10,17 @@ import Case_pb2 import Case_pb2_grpc class Case: + """ResInsight case class + + Operate on a ResInsight case specified by a Case Id integer. + Not meant to be constructed separately but created by one of the following + methods in Project: loadCase, case, allCases, selectedCases + + Attributes: + id(int): Case Id corresponding to case Id in ResInsight project. + name(string): Case name + groupId(int): Case Group id + """ def __init__(self, channel, id): self.channel = channel self.stub = Case_pb2_grpc.CaseStub(channel) @@ -21,8 +32,8 @@ class Case: self.properties = Properties(self) self.request = Case_pb2.CaseRequest(id=self.id) - # Get number of grids in the case def gridCount(self): + """Get number of grids in the case""" try: return self.stub.GetGridCount(self.request).count except grpc.RpcError as e: @@ -31,32 +42,57 @@ class Case: print("ERROR: ", e) return 0 - # Get Grid of a given index. Returns a rips Grid object def grid(self, index): + """Get Grid of a given index. Returns a rips Grid object""" return Grid(index, self) - - # Get a list of all rips Grid objects in the case + def grids(self): + """Get a list of all rips Grid objects in the case""" gridList = [] for i in range(0, self.gridCount()): gridList.append(Grid(i, self)) return gridList def cellCount(self, porosityModel='MATRIX_MODEL'): + """Get a cell count object containing number of active cells and + total number of cells + + Arguments: + porosityModel(string): String representing an enum. + must be 'MATRIX_MODEL' or 'FRACTURE_MODEL'. + Returns: + Cell Count object with the following integer attributes: + active_cell_count: number of active cells + reservoir_cell_count: total number of reservoir cells + """ porosityModelEnum = Case_pb2.PorosityModelType.Value(porosityModel) request = Case_pb2.CellInfoRequest(case_request=self.request, porosity_model=porosityModel) return self.stub.GetCellCount(request) def cellInfoForActiveCells(self, porosityModel='MATRIX_MODEL'): + """Get Stream of cell info objects for current case + Arguments: + porosityModel(string): String representing an enum. + must be 'MATRIX_MODEL' or 'FRACTURE_MODEL'. + Returns: + Stream of cell info objects with the following attributes: + grid_index(int): grid the cell belongs to + parent_grid_index(int): parent of the grid the cell belongs to + coarsening_box_index(int): the coarsening box index + local_ijk(Vec3i: i(int), j(int), k(int)): local cell index in i, j, k directions. + parent_ijk(Vec3i: i(int), j(int), k(int)): cell index in parent grid in i, j, k. + """ porosityModelEnum = Case_pb2.PorosityModelType.Value(porosityModel) request = Case_pb2.CellInfoRequest(case_request=self.request, porosity_model=porosityModel) return self.stub.GetCellInfoForActiveCells(request) def timeSteps(self): + """Get a list containing time step strings for all time steps""" return self.stub.GetTimeSteps(self.request).dates def daysSinceStart(self): + """Get a list of decimal values representing days since the start of the simulation""" return self.stub.GetDaysSinceStart(self.request).day_decimals \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/Python/rips/Commands.py b/ApplicationCode/GrpcInterface/Python/rips/Commands.py index 59270d7d46..18ebcff88c 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Commands.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Commands.py @@ -10,11 +10,20 @@ import Commands_pb2_grpc as CmdRpc from .Case import Case class Commands: + """Command executor which can run ResInsight Command File commands nearly verbatim + + Documentation Command File Interface: + https://resinsight.org/docs/commandfile/ + + The differences are: + 1. Enum values have to be provided as strings. I.e. "ALL" instead of ALL. + 2. Booleans have to be specified as correct Python. True instead of true. + """ def __init__(self, channel): self.channel = channel self.commands = CmdRpc.CommandsStub(channel) - def execute(self, **commandParams): + def __execute(self, **commandParams): try: return self.commands.Execute(Cmd.CommandParams(**commandParams)) except grpc.RpcError as e: @@ -28,39 +37,39 @@ class Commands: ######################## def openProject(self, path): - return self.execute(openProject=Cmd.FilePathRequest(path=path)) + return self.__execute(openProject=Cmd.FilePathRequest(path=path)) def closeProject(self): - return self.execute(closeProject=Empty()) + return self.__execute(closeProject=Empty()) def setStartDir(self, path): - return self.execute(setStartDir=Cmd.FilePathRequest(path=path)) + return self.__execute(setStartDir=Cmd.FilePathRequest(path=path)) def loadCase(self, path): - commandReply = self.execute(loadCase=Cmd.FilePathRequest(path=path)) + commandReply = self.__execute(loadCase=Cmd.FilePathRequest(path=path)) assert commandReply.HasField("loadCaseResult") return Case(self.channel, commandReply.loadCaseResult.id) def replaceCase(self, path, caseId=0): - return self.execute(replaceCase=Cmd.ReplaceCaseRequest(newGridFile=path, + return self.__execute(replaceCase=Cmd.ReplaceCaseRequest(newGridFile=path, caseId=caseId)) def replaceSourceCases(self, gridListFile, caseGroupId=0): - return self.execute(replaceSourceCases=Cmd.ReplaceSourceCasesRequest(gridListFile=gridListFile, + return self.__execute(replaceSourceCases=Cmd.ReplaceSourceCasesRequest(gridListFile=gridListFile, caseGroupId=caseGroupId)) ################## # Export Commands ################## def exportMultiCaseSnapshots(self, gridListFile): - return self.execute(exportMultiCaseSnapshot=Cmd.ExportMultiCaseRequest(gridListFile=gridListFile)) + return self.__execute(exportMultiCaseSnapshot=Cmd.ExportMultiCaseRequest(gridListFile=gridListFile)) def exportSnapshots(self, type = 'ALL', prefix=''): - return self.execute(exportSnapshots=Cmd.ExportSnapshotsRequest(type=type, + return self.__execute(exportSnapshots=Cmd.ExportSnapshotsRequest(type=type, prefix=prefix)) def exportProperty(self, caseId, timeStep, property, eclipseKeyword=property, undefinedValue=0.0, exportFile=property): - return self.execute(exportProperty=Cmd.ExportPropertyRequest(caseId=caseId, + return self.__execute(exportProperty=Cmd.ExportPropertyRequest(caseId=caseId, timeStep=timeStep, property=property, eclipseKeyword=eclipseKeyword, @@ -71,7 +80,7 @@ class Commands: if isinstance(viewNames, str): viewNames = [viewNames] - return self.execute(exportPropertyInViews=Cmd.ExportPropertyInViewsRequest(caseId=caseId, + return self.__execute(exportPropertyInViews=Cmd.ExportPropertyInViewsRequest(caseId=caseId, viewNames=viewNames, undefinedValue=undefinedValue)) @@ -80,7 +89,7 @@ class Commands: excludeMainBoreForFishbones, combinationMode): if (isinstance(wellPathNames, str)): wellPathNames = [wellPathNames] - return self.execute(exportWellPathCompletions=Cmd.ExportWellPathCompRequest(caseId=caseId, + return self.__execute(exportWellPathCompletions=Cmd.ExportWellPathCompRequest(caseId=caseId, timeStep=timeStep, wellPathNames=wellPathNames, fileSplit=fileSplit, @@ -93,7 +102,7 @@ class Commands: def exportSimWellFractureCompletions(self, caseId, viewName, timeStep, simulationWellNames, fileSplit, compdatExport): if(isinstance(simulationWellNames, str)): simulationWellNames = [simulationWellNames] - return self.execute(exportSimWellFractureCompletions=Cmd.ExportSimWellPathFraqRequest(caseId=caseId, + return self.__execute(exportSimWellFractureCompletions=Cmd.ExportSimWellPathFraqRequest(caseId=caseId, viewName=viewName, timeStep=timeStep, simulationWellNames=simulationWellNames, @@ -101,23 +110,23 @@ class Commands: compdatExport=compdatExport)) def exportMsw(self, caseId, wellPath): - return self.execute(exportMsw=Cmd.ExportMswRequest(caseId=caseId, + return self.__execute(exportMsw=Cmd.ExportMswRequest(caseId=caseId, wellPath=wellPath)) def exportWellPaths(self, wellPaths=[], mdStepSize=5.0): if isinstance(wellPaths, str): wellPaths = [wellpaths] - return self.execute(exportWellPaths=Cmd.ExportWellPathRequest(wellPathNames=wellPaths, mdStepSize=mdStepSize)) + return self.__execute(exportWellPaths=Cmd.ExportWellPathRequest(wellPathNames=wellPaths, mdStepSize=mdStepSize)) def exportVisibleCells(self, caseId, viewName, exportKeyword='FLUXNUM', visibleActiveCellsValue=1, hiddenActiveCellsValue=0, inactiveCellsValue=0): - return self.execute(exportVisibleCells=Cmd.ExportVisibleCellsRequest(caseId=caseId, + return self.__execute(exportVisibleCells=Cmd.ExportVisibleCellsRequest(caseId=caseId, viewName=viewName, exportKeyword=exportKeyword, visibleActiveCellsValue=visibleActiveCellsValue, hiddenActiveCellsValue=hiddenActiveCellsValue, inactiveCellsValue=inactiveCellsValue)) def setExportFolder(self, type, path, createFolder=False): - return self.execute(setExportFolder=Cmd.SetExportFolderRequest(type=type, + return self.__execute(setExportFolder=Cmd.SetExportFolderRequest(type=type, path=path, createFolder=createFolder)) @@ -125,29 +134,29 @@ class Commands: caseIds = [] for case in cases: caseIds.append(case.id) - return self.execute(runOctaveScript=Cmd.RunOctaveScriptRequest(path=path, + return self.__execute(runOctaveScript=Cmd.RunOctaveScriptRequest(path=path, caseIds=caseIds)) def setMainWindowSize(self, width, height): - return self.execute(setMainWindowSize=Cmd.SetMainWindowSizeParams(width=width, height=height)) + return self.__execute(setMainWindowSize=Cmd.SetMainWindowSizeParams(width=width, height=height)) def computeCaseGroupStatistics(self, caseIds): if isinstance(caseIds, int): caseIds = [caseIds] - return self.execute(computeCaseGroupStatistics=Cmd.ComputeCaseGroupStatRequest(caseIds=caseIds)) + return self.__execute(computeCaseGroupStatistics=Cmd.ComputeCaseGroupStatRequest(caseIds=caseIds)) def setTimeStep(self, caseId, timeStep): - return self.execute(setTimeStep=Cmd.SetTimeStepParams(caseId=caseId, timeStep=timeStep)) + return self.__execute(setTimeStep=Cmd.SetTimeStepParams(caseId=caseId, timeStep=timeStep)) def scaleFractureTemplate(self, id, halfLength, height, dFactor, conductivity): - return self.execute(scaleFractureTemplate=Cmd.ScaleFractureTemplateRequest(id=id, + return self.__execute(scaleFractureTemplate=Cmd.ScaleFractureTemplateRequest(id=id, halfLength=halfLength, height=height, dFactor=dFactor, conductivity=conductivity)) def setFractureContainment(self, id, topLayer, baseLayer): - return self.execute(setFractureContainment=Cmd.SetFracContainmentRequest(id=id, + return self.__execute(setFractureContainment=Cmd.SetFracContainmentRequest(id=id, topLayer=topLayer, baseLayer=baseLayer)) @@ -155,7 +164,7 @@ class Commands: maxFracturesPerWell, topLayer, baseLayer, spacing, action): if isinstance(wellPathNames, str): wellPathNames = [wellPathNames] - return self.execute(createMultipleFractures=Cmd.MultipleFracAction(caseId=caseId, + return self.__execute(createMultipleFractures=Cmd.MultipleFracAction(caseId=caseId, templateId=templateId, wellPathNames=wellPathNames, minDistFromWellTd=minDistFromWellTd, @@ -168,7 +177,7 @@ class Commands: def createLgrForCompletions(self, caseId, timeStep, wellPathNames, refinementI, refinementJ, refinementK, splitType): if isinstance(wellPathNames, str): wellPathNames = [wellPathNames] - return self.execute(createLgrForCompletions=Cmd.CreateLgrForCompRequest(caseId=caseId, + return self.__execute(createLgrForCompletions=Cmd.CreateLgrForCompRequest(caseId=caseId, timeStep=timeStep, wellPathNames=wellPathNames, refinementI=refinementI, @@ -179,5 +188,5 @@ class Commands: def createSaturationPressurePlots(self, caseIds): if isinstance(caseIds, int): caseIds = [caseIds] - return self.execute(createSaturationPressurePlots=Cmd.CreateSatPressPlotRequest(caseIds=caseIds)) + return self.__execute(createSaturationPressurePlots=Cmd.CreateSatPressPlotRequest(caseIds=caseIds)) diff --git a/ApplicationCode/GrpcInterface/Python/rips/Grid.py b/ApplicationCode/GrpcInterface/Python/rips/Grid.py index 0a4b8261cc..9f83359ee3 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Grid.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Grid.py @@ -8,11 +8,20 @@ import Grid_pb2 import Grid_pb2_grpc class Grid: + """Grid Information. Not meant to be constructed separately + + Create Grid objects using mathods on Case: Grid() and Grids() + """ def __init__(self, index, case): self.case = case self.index = index self.stub = Grid_pb2_grpc.GridStub(self.case.channel) def dimensions(self): + """The dimensions in i, j, k direction + + Returns: + Vec3i: class with integer attributes i, j, k representing the extent in all three dimensions. + """ return self.stub.GetDimensions(Grid_pb2.GridRequest(case_request = self.case.request, grid_index = self.index)).dimensions diff --git a/ApplicationCode/GrpcInterface/Python/rips/Instance.py b/ApplicationCode/GrpcInterface/Python/rips/Instance.py index a9f8c75dd3..88966d423a 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Instance.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Instance.py @@ -14,16 +14,38 @@ from .Commands import Commands from .Project import Project class Instance: - launched = False + """The ResInsight Instance class. Use to launch or find existing ResInsight instances + + Attributes: + launched(bool): Tells us whether the application was launched as a new process. + If the application was launched we may need to close it when exiting the script. + app(App): Application information object. Set when creating an instance. + commands(Commands): Command executor. Set when creating an instance. + project(Project): Current project in ResInsight. + Set when creating an instance and updated when opening/closing projects. + """ @staticmethod - def is_port_in_use(port): + def __is_port_in_use(port): with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.settimeout(0.2) return s.connect_ex(('localhost', port)) == 0 @staticmethod - def launch(resInsightExecutable = '', console = False): + def launch(resInsightExecutable = '', console = False): + """ Launch a new Instance of ResInsight. This requires the environment variable + RESINSIGHT_EXECUTABLE to be set or the parameter resInsightExecutable to be provided. + The RESINSIGHT_GRPC_PORT environment variable can be set to an alternative port number. + + Args: + resInsightExecutable (str): Path to a valid ResInsight executable. If set + will take precedence over what is provided in the RESINSIGHT_EXECUTABLE + environment variable. + console (bool): If True, launch as console application, without GUI. + Returns: + Instance: an instance object if it worked. None if not. + """ + port = 50051 portEnv = os.environ.get('RESINSIGHT_GRPC_PORT') if portEnv: @@ -36,7 +58,7 @@ class Instance: ' RESINSIGHT_EXECUTABLE is not set') return None - while Instance.is_port_in_use(port): + while Instance.__is_port_in_use(port): port += 1 print('Port ' + str(port)) @@ -47,24 +69,36 @@ class Instance: parameters.append("--console") pid = os.spawnv(os.P_NOWAIT, resInsightExecutable, parameters) if pid: - return Instance(port=port, launched=True) + instance = Instance(port=port) + instance.launched = True + return instance return None @staticmethod def find(startPort = 50051, endPort = 50071): + """ Search for an existing Instance of ResInsight by testing ports. + + By default we search from port 50051 to 50071 or if the environment + variable RESINSIGHT_GRPC_PORT is set we search + RESINSIGHT_GRPC_PORT to RESINSIGHT_GRPC_PORT+20 + + Args: + startPort(int): start searching from this port + endPort(int): search up to but not including this port + """ portEnv = os.environ.get('RESINSIGHT_GRPC_PORT') if portEnv: startPort = int(portEnv) endPort = startPort + 20 for tryPort in range(startPort, endPort): - if Instance.is_port_in_use(tryPort): + if Instance.__is_port_in_use(tryPort): return Instance(tryPort) print('Error: Could not find any ResInsight instances responding between ports ' + str(startPort) + ' and ' + str(endPort)) return None - def checkVersion(self): + def __checkVersion(self): try: majorVersionOk = self.app.majorVersion() == int(RiaVersionInfo.RESINSIGHT_MAJOR_VERSION) minorVersionOk = self.app.minorVersion() == int(RiaVersionInfo.RESINSIGHT_MINOR_VERSION) @@ -72,12 +106,17 @@ class Instance: except grpc.RpcError as e: return False, False - def __init__(self, port = 50051, launched = False): + def __init__(self, port = 50051): + """ Attempts to connect to ResInsight at aa specific port on localhost + + Args: + port(int): port number + """ logging.basicConfig() location = "localhost:" + str(port) self.channel = grpc.insecure_channel(location) - self.launched = launched + self.launched = False # Main version check package self.app = App(self.channel) @@ -85,14 +124,14 @@ class Instance: connectionOk = False versionOk = False - if launched: + if self.launched: for i in range(0, 10): - connectionOk, versionOk = self.checkVersion() + connectionOk, versionOk = self.__checkVersion() if connectionOk: break time.sleep(1.0) else: - connectionOk, versionOk = self.checkVersion() + connectionOk, versionOk = self.__checkVersion() if not connectionOk: if launched: diff --git a/ApplicationCode/GrpcInterface/Python/rips/Project.py b/ApplicationCode/GrpcInterface/Python/rips/Project.py index d17ebc83c4..60b61f9874 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Project.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Project.py @@ -12,18 +12,34 @@ import Project_pb2 import Project_pb2_grpc class Project: + """ResInsight project. Not intended to be created separately. + + Automatically created and assigned to Instance. + """ def __init__(self, channel): self.channel = channel self.project = Project_pb2_grpc.ProjectStub(channel) def open(self, path): + """Open a new project from the given path + + Argument: + path(string): path to project file + + """ Commands(self.channel).openProject(path) return self def close(self): + """Close the current project (and open new blank project)""" Commands(self.channel).closeProject() def selectedCases(self): + """Get a list of all cases selected in the project tree + + Returns: + A list of rips Case objects + """ caseInfos = self.project.GetSelectedCases(Empty()) cases = [] for caseInfo in caseInfos.data: @@ -31,6 +47,11 @@ class Project: return cases def cases(self): + """Get a list of all cases in the project + + Returns: + A list of rips Case objects + """ try: caseInfos = self.project.GetAllCases(Empty()) @@ -46,6 +67,13 @@ class Project: return [] def case(self, id): + """Get a specific case from the provided case Id + + Arguments: + id(int): case id + Returns: + A rips Case object + """ try: case = Case(self.channel, id) return case @@ -53,5 +81,12 @@ class Project: return None def loadCase(self, path): + """Load a new case from the given file path + + Arguments: + path(string): file path to case + Returns: + A rips Case object + """ return Commands(self.channel).loadCase(path) diff --git a/ApplicationCode/GrpcInterface/Python/rips/Properties.py b/ApplicationCode/GrpcInterface/Python/rips/Properties.py index d7883ab03d..96142d9987 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Properties.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Properties.py @@ -10,11 +10,17 @@ import Case_pb2 import Case_pb2_grpc class Properties: + """ Class for streaming properties to and from ResInsight + """ def __init__(self, case): + """ + Arguments: + case(Case): A rips case to handle properties for + """ self.case = case self.propertiesStub = Properties_pb2_grpc.PropertiesStub(self.case.channel) - def generatePropertyInputIterator(self, values_iterator, parameters): + def __generatePropertyInputIterator(self, values_iterator, parameters): chunk = Properties_pb2.PropertyInputChunk() chunk.params.CopyFrom(parameters) yield chunk @@ -24,7 +30,7 @@ class Properties: chunk.values.CopyFrom(valmsg) yield chunk - def generatePropertyInputChunks(self, array, parameters): + def __generatePropertyInputChunks(self, array, parameters): # Each double is 8 bytes. A good chunk size is 64KiB = 65536B # Meaning ideal number of doubles would be 8192. # However we need overhead space, so if we choose 8160 in chunk size @@ -47,6 +53,22 @@ class Properties: yield chunk def available(self, propertyType, porosityModel = 'MATRIX_MODEL'): + """Get a list of available properties + + Arguments: + propertyType(string): string corresponding to propertyType enum + Can be one of the following: + 'DYNAMIC_NATIVE' + 'STATIC_NATIVE' + 'SOURSIMRL' + 'GENERATED' + 'INPUT_PROPERTY' + 'FORMATION_NAMES' + 'FLOW_DIAGNOSTICS' + 'INJECTION_FLOODING' + porosityModel(string): 'MATRIX_MODEL' or 'FRACTURE_MODEL'. + """ + propertyTypeEnum = Properties_pb2.PropertyType.Value(propertyType) porosityModelEnum = Case_pb2.PorosityModelType.Value(porosityModel) request = Properties_pb2.AvailablePropertiesRequest (case_request = Case_pb2.CaseRequest(id=self.case.id), @@ -55,6 +77,18 @@ class Properties: return self.propertiesStub.GetAvailableProperties(request).property_names def activeCellProperty(self, propertyType, propertyName, timeStep, porosityModel = 'MATRIX_MODEL'): + """Get a cell property for all active cells. Async, so returns an iterator + + Arguments: + propertyType(string): string enum. See available() + propertyName(string): name of an Eclipse property + timeStep(int): the time step for which to get the property for + porosityModel(string): string enum. See available() + + Returns: + An iterator to a chunk object containing an array of double values + You first loop through the chunks and then the values within the chunk to get all values. + """ propertyTypeEnum = Properties_pb2.PropertyType.Value(propertyType) porosityModelEnum = Case_pb2.PorosityModelType.Value(porosityModel) request = Properties_pb2.PropertyRequest(case_request = Case_pb2.CaseRequest(id=self.case.id), @@ -66,6 +100,19 @@ class Properties: yield chunk def gridProperty(self, propertyType, propertyName, timeStep, gridIndex = 0, porosityModel = 'MATRIX_MODEL'): + """Get a cell property for all grid cells. Async, so returns an iterator + + Arguments: + propertyType(string): string enum. See available() + propertyName(string): name of an Eclipse property + timeStep(int): the time step for which to get the property for + gridIndex(int): index to the grid we're getting values for + porosityModel(string): string enum. See available() + + Returns: + An iterator to a chunk object containing an array of double values + You first loop through the chunks and then the values within the chunk to get all values. + """ propertyTypeEnum = Properties_pb2.PropertyType.Value(propertyType) porosityModelEnum = Case_pb2.PorosityModelType.Value(porosityModel) request = Properties_pb2.PropertyRequest(case_request = self.case.request, @@ -77,17 +124,25 @@ class Properties: for chunk in self.propertiesStub.GetGridProperty(request): yield chunk - def setActiveCellPropertyAsync(self, values_iterator, propertyType, propertyName, timeStep, gridIndex = 0, porosityModel = 'MATRIX_MODEL'): + def setActiveCellPropertyAsync(self, values_iterator, propertyType, propertyName, timeStep, porosityModel = 'MATRIX_MODEL'): + """Set a cell property for all active cells. Async, and so takes an iterator to the input values + + Arguments: + values_iterator(iterator): an iterator to the properties to be set + propertyType(string): string enum. See available() + propertyName(string): name of an Eclipse property + timeStep(int): the time step for which to get the property for + porosityModel(string): string enum. See available() + """ propertyTypeEnum = Properties_pb2.PropertyType.Value(propertyType) porosityModelEnum = Case_pb2.PorosityModelType.Value(porosityModel) request = Properties_pb2.PropertyRequest(case_request = self.case.request, property_type = propertyTypeEnum, property_name = propertyName, time_step = timeStep, - grid_index = gridIndex, porosity_model = porosityModelEnum) try: - reply_iterator = self.generatePropertyInputIterator(values_iterator, request) + reply_iterator = self.__generatePropertyInputIterator(values_iterator, request) self.propertiesStub.SetActiveCellProperty(reply_iterator) except grpc.RpcError as e: if e.code() == grpc.StatusCode.NOT_FOUND: @@ -95,17 +150,25 @@ class Properties: else: print("Other error", e) - def setActiveCellProperty(self, values, propertyType, propertyName, timeStep, gridIndex = 0, porosityModel = 'MATRIX_MODEL'): + def setActiveCellProperty(self, values, propertyType, propertyName, timeStep, porosityModel = 'MATRIX_MODEL'): + """Set a cell property for all active cells. + + Arguments: + values(list): a list of double precision floating point numbers + propertyType(string): string enum. See available() + propertyName(string): name of an Eclipse property + timeStep(int): the time step for which to get the property for + porosityModel(string): string enum. See available() + """ propertyTypeEnum = Properties_pb2.PropertyType.Value(propertyType) porosityModelEnum = Case_pb2.PorosityModelType.Value(porosityModel) request = Properties_pb2.PropertyRequest(case_request = self.case.request, property_type = propertyTypeEnum, property_name = propertyName, time_step = timeStep, - grid_index = gridIndex, porosity_model = porosityModelEnum) try: - request_iterator = self.generatePropertyInputChunks(values, request) + request_iterator = self.__generatePropertyInputChunks(values, request) self.propertiesStub.SetActiveCellProperty(request_iterator) except grpc.RpcError as e: if e.code() == grpc.StatusCode.NOT_FOUND: @@ -114,6 +177,16 @@ class Properties: print("Other error", e) def setGridProperty(self, values, propertyType, propertyName, timeStep, gridIndex = 0, porosityModel = 'MATRIX_MODEL'): + """Set a cell property for all grid cells. + + Arguments: + values(list): a list of double precision floating point numbers + propertyType(string): string enum. See available() + propertyName(string): name of an Eclipse property + timeStep(int): the time step for which to get the property for + gridIndex(int): index to the grid we're setting values for + porosityModel(string): string enum. See available() + """ propertyTypeEnum = Properties_pb2.PropertyType.Value(propertyType) porosityModelEnum = Case_pb2.PorosityModelType.Value(porosityModel) request = Properties_pb2.PropertyRequest(case_request = self.case.request, @@ -123,7 +196,7 @@ class Properties: grid_index = gridIndex, porosity_model = porosityModelEnum) try: - request_iterator = self.generatePropertyInputChunks(values, request) + request_iterator = self.__generatePropertyInputChunks(values, request) self.propertiesStub.SetGridProperty(request_iterator) except grpc.RpcError as e: if e.code() == grpc.StatusCode.NOT_FOUND: diff --git a/ApplicationCode/GrpcInterface/Python/setup.py.cmake b/ApplicationCode/GrpcInterface/Python/setup.py.cmake index 2202937112..6e447b1644 100644 --- a/ApplicationCode/GrpcInterface/Python/setup.py.cmake +++ b/ApplicationCode/GrpcInterface/Python/setup.py.cmake @@ -6,7 +6,7 @@ with open('README.md') as f: with open('LICENSE') as f: license = f.read() -RIPS_DIST_VERSION = '1' +RIPS_DIST_VERSION = '2' setup( name='rips', From 1d8a417e33a359398a7f4338c8e44d2edcc8c4e1 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Wed, 12 Jun 2019 08:29:41 +0200 Subject: [PATCH 167/396] Python: move examples, tests and generated inside rips folder so they are packaged in rips pip-package --- .../GrpcInterface/CMakeLists.cmake | 50 ++++++------ .../GrpcInterface/Python/rips/App.py | 2 +- .../GrpcInterface/Python/rips/Case.py | 2 +- .../GrpcInterface/Python/rips/Commands.py | 2 +- .../GrpcInterface/Python/rips/Grid.py | 2 +- .../GrpcInterface/Python/rips/Instance.py | 2 +- .../GrpcInterface/Python/rips/Project.py | 2 +- .../GrpcInterface/Python/rips/Properties.py | 2 +- .../GrpcInterface/Python/rips/ResInsight.py | 78 ------------------- .../Python/{ => rips}/examples/AllCases.py | 2 +- .../examples/CaseInfoStreamingExample.py | 2 +- .../{ => rips}/examples/CommandExample.py | 2 +- .../{ => rips}/examples/GridInformation.py | 2 +- .../{ => rips}/examples/InputPropTestAsync.py | 2 +- .../{ => rips}/examples/InputPropTestSync.py | 2 +- .../{ => rips}/examples/SelectedCases.py | 2 +- .../{ => rips}/examples/SetGridProperties.py | 2 +- .../Python/{ => rips}/examples/SoilAverage.py | 2 +- .../{ => rips}/examples/SoilAverageNoComm.py | 0 .../{ => rips}/examples/SoilPorvAsync.py | 2 +- .../{ => rips}/examples/SoilPorvSync.py | 2 +- .../Python/{ => rips}/tests/conftest.py | 2 +- .../Python/rips/tests/dataroot.py | 1 + .../Python/{ => rips}/tests/test_cases.py | 2 +- .../Python/{ => rips}/tests/test_commands.py | 2 +- .../Python/{ => rips}/tests/test_grids.py | 2 +- .../Python/{ => rips}/tests/test_project.py | 2 +- .../{ => rips}/tests/test_properties.py | 2 +- .../GrpcInterface/Python/setup.py.cmake | 4 +- .../GrpcInterface/Python/tests/dataroot.py | 1 - 30 files changed, 52 insertions(+), 130 deletions(-) delete mode 100644 ApplicationCode/GrpcInterface/Python/rips/ResInsight.py rename ApplicationCode/GrpcInterface/Python/{ => rips}/examples/AllCases.py (80%) rename ApplicationCode/GrpcInterface/Python/{ => rips}/examples/CaseInfoStreamingExample.py (91%) rename ApplicationCode/GrpcInterface/Python/{ => rips}/examples/CommandExample.py (94%) rename ApplicationCode/GrpcInterface/Python/{ => rips}/examples/GridInformation.py (85%) rename ApplicationCode/GrpcInterface/Python/{ => rips}/examples/InputPropTestAsync.py (88%) rename ApplicationCode/GrpcInterface/Python/{ => rips}/examples/InputPropTestSync.py (89%) rename ApplicationCode/GrpcInterface/Python/{ => rips}/examples/SelectedCases.py (85%) rename ApplicationCode/GrpcInterface/Python/{ => rips}/examples/SetGridProperties.py (86%) rename ApplicationCode/GrpcInterface/Python/{ => rips}/examples/SoilAverage.py (89%) rename ApplicationCode/GrpcInterface/Python/{ => rips}/examples/SoilAverageNoComm.py (100%) rename ApplicationCode/GrpcInterface/Python/{ => rips}/examples/SoilPorvAsync.py (90%) rename ApplicationCode/GrpcInterface/Python/{ => rips}/examples/SoilPorvSync.py (89%) rename ApplicationCode/GrpcInterface/Python/{ => rips}/tests/conftest.py (91%) create mode 100644 ApplicationCode/GrpcInterface/Python/rips/tests/dataroot.py rename ApplicationCode/GrpcInterface/Python/{ => rips}/tests/test_cases.py (97%) rename ApplicationCode/GrpcInterface/Python/{ => rips}/tests/test_commands.py (93%) rename ApplicationCode/GrpcInterface/Python/{ => rips}/tests/test_grids.py (88%) rename ApplicationCode/GrpcInterface/Python/{ => rips}/tests/test_project.py (82%) rename ApplicationCode/GrpcInterface/Python/{ => rips}/tests/test_properties.py (97%) delete mode 100644 ApplicationCode/GrpcInterface/Python/tests/dataroot.py diff --git a/ApplicationCode/GrpcInterface/CMakeLists.cmake b/ApplicationCode/GrpcInterface/CMakeLists.cmake index b3337d5973..79d2117361 100644 --- a/ApplicationCode/GrpcInterface/CMakeLists.cmake +++ b/ApplicationCode/GrpcInterface/CMakeLists.cmake @@ -110,16 +110,16 @@ foreach(proto_file ${PROTO_FILES}) ) if (PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) - set(rips_proto_python "generated/${proto_file}_pb2.py") - set(rips_grpc_python "generated/${proto_file}_pb2_grpc.py") + set(rips_proto_python "rips/generated/${proto_file}_pb2.py") + set(rips_grpc_python "rips/generated/${proto_file}_pb2_grpc.py") add_custom_command( OUTPUT "${GRPC_PYTHON_SOURCE_PATH}/${rips_proto_python}" "${GRPC_PYTHON_SOURCE_PATH}/${rips_grpc_python}" COMMAND ${PYTHON_EXECUTABLE} ARGS -m grpc_tools.protoc -I "${rips_proto_path}" - --python_out "${GRPC_PYTHON_SOURCE_PATH}/generated" - --grpc_python_out "${GRPC_PYTHON_SOURCE_PATH}/generated" + --python_out "${GRPC_PYTHON_SOURCE_PATH}/rips/generated" + --grpc_python_out "${GRPC_PYTHON_SOURCE_PATH}/rips/generated" "${rips_proto}" DEPENDS "${rips_proto}" COMMENT "Generating ${rips_proto_python} and ${rips_grpc_python}" @@ -147,7 +147,7 @@ endforeach(proto_file) if (PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) list(APPEND GRPC_PYTHON_SOURCES ${GRPC_PYTHON_GENERATED_SOURCES} - "generated/RiaVersionInfo.py" + "rips/generated/RiaVersionInfo.py" "rips/__init__.py" "rips/App.py" "rips/Case.py" @@ -156,25 +156,25 @@ if (PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) "rips/Project.py" "rips/Properties.py" "rips/Instance.py" - "examples/CommandExample.py" - "examples/CaseInfoStreamingExample.py" - "examples/SoilPorvAsync.py" - "examples/SoilPorvSync.py" - "examples/SelectedCases.py" - "examples/AllCases.py" - "examples/SetGridProperties.py" - "examples/GridInformation.py" - "examples/InputPropTestSync.py" - "examples/InputPropTestAsync.py" - "examples/SoilAverage.py" - "examples/SoilAverageNoComm.py" - "tests/test_cases.py" - "tests/test_commands.py" - "tests/test_grids.py" - "tests/test_properties.py" - "tests/test_project.py" - "tests/conftest.py" - "tests/dataroot.py" + "rips/examples/CommandExample.py" + "rips/examples/CaseInfoStreamingExample.py" + "rips/examples/SoilPorvAsync.py" + "rips/examples/SoilPorvSync.py" + "rips/examples/SelectedCases.py" + "rips/examples/AllCases.py" + "rips/examples/SetGridProperties.py" + "rips/examples/GridInformation.py" + "rips/examples/InputPropTestSync.py" + "rips/examples/InputPropTestAsync.py" + "rips/examples/SoilAverage.py" + "rips/examples/SoilAverageNoComm.py" + "rips/tests/test_cases.py" + "rips/tests/test_commands.py" + "rips/tests/test_grids.py" + "rips/tests/test_properties.py" + "rips/tests/test_project.py" + "rips/tests/conftest.py" + "rips/tests/dataroot.py" "requirements.txt" "setup.py.cmake" "README.md" @@ -194,7 +194,7 @@ list ( APPEND GRPC_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES}) list ( APPEND GRPC_CPP_SOURCES ${SOURCE_GROUP_SOURCE_FILES}) CONFIGURE_FILE( ${CMAKE_SOURCE_DIR}/ApplicationCode/Adm/RiaVersionInfo.py.cmake - ${GRPC_PYTHON_SOURCE_PATH}/generated/RiaVersionInfo.py + ${GRPC_PYTHON_SOURCE_PATH}/rips/generated/RiaVersionInfo.py ) CONFIGURE_FILE( ${GRPC_PYTHON_SOURCE_PATH}/setup.py.cmake ${GRPC_PYTHON_SOURCE_PATH}/setup.py diff --git a/ApplicationCode/GrpcInterface/Python/rips/App.py b/ApplicationCode/GrpcInterface/Python/rips/App.py index 05ec7857c5..2eed6c8abb 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/App.py +++ b/ApplicationCode/GrpcInterface/Python/rips/App.py @@ -2,7 +2,7 @@ import grpc import os import sys -sys.path.insert(0, os.path.join(os.path.dirname(__file__), '../generated')) +sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'generated')) from Empty_pb2 import Empty diff --git a/ApplicationCode/GrpcInterface/Python/rips/Case.py b/ApplicationCode/GrpcInterface/Python/rips/Case.py index bc31487ed4..000843a563 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Case.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Case.py @@ -4,7 +4,7 @@ import sys from .Grid import Grid from .Properties import Properties -sys.path.insert(0, os.path.join(os.path.dirname(__file__), '../generated')) +sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'generated')) import Case_pb2 import Case_pb2_grpc diff --git a/ApplicationCode/GrpcInterface/Python/rips/Commands.py b/ApplicationCode/GrpcInterface/Python/rips/Commands.py index 18ebcff88c..687e3b5c58 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Commands.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Commands.py @@ -2,7 +2,7 @@ import grpc import os import sys -sys.path.insert(0, os.path.join(os.path.dirname(__file__), '../generated')) +sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'generated')) from Empty_pb2 import Empty import Commands_pb2 as Cmd diff --git a/ApplicationCode/GrpcInterface/Python/rips/Grid.py b/ApplicationCode/GrpcInterface/Python/rips/Grid.py index 9f83359ee3..3a8ab8d77f 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Grid.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Grid.py @@ -2,7 +2,7 @@ import grpc import os import sys -sys.path.insert(0, os.path.join(os.path.dirname(__file__), '../generated')) +sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'generated')) import Grid_pb2 import Grid_pb2_grpc diff --git a/ApplicationCode/GrpcInterface/Python/rips/Instance.py b/ApplicationCode/GrpcInterface/Python/rips/Instance.py index 88966d423a..9ae3db2850 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Instance.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Instance.py @@ -5,7 +5,7 @@ import socket import logging import time -sys.path.insert(0, os.path.join(os.path.dirname(__file__), '../generated')) +sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'generated')) import RiaVersionInfo diff --git a/ApplicationCode/GrpcInterface/Python/rips/Project.py b/ApplicationCode/GrpcInterface/Python/rips/Project.py index 60b61f9874..4d3b720fe9 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Project.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Project.py @@ -5,7 +5,7 @@ import sys from .Case import Case from .Commands import Commands -sys.path.insert(0, os.path.join(os.path.dirname(__file__), '../generated')) +sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'generated')) from Empty_pb2 import Empty import Project_pb2 diff --git a/ApplicationCode/GrpcInterface/Python/rips/Properties.py b/ApplicationCode/GrpcInterface/Python/rips/Properties.py index 96142d9987..a95b6bdd1f 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Properties.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Properties.py @@ -2,7 +2,7 @@ import grpc import os import sys -sys.path.insert(0, os.path.join(os.path.dirname(__file__), '../generated')) +sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'generated')) import Properties_pb2 import Properties_pb2_grpc diff --git a/ApplicationCode/GrpcInterface/Python/rips/ResInsight.py b/ApplicationCode/GrpcInterface/Python/rips/ResInsight.py deleted file mode 100644 index e9bfd24c3f..0000000000 --- a/ApplicationCode/GrpcInterface/Python/rips/ResInsight.py +++ /dev/null @@ -1,78 +0,0 @@ -import grpc -import os -import sys -import socket -import logging - -sys.path.insert(1, os.path.join(sys.path[0], '../generated')) - -import RiaVersionInfo - -from AppInfo import AppInfo -from Commands import Commands -from Project import Project - -class Instance: - @staticmethod - def is_port_in_use(port): - with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: - s.settimeout(0.2) - return s.connect_ex(('localhost', port)) == 0 - - @staticmethod - def launch(): - port = 50051 - portEnv = os.environ.get('RESINSIGHT_GRPC_PORT') - if portEnv: - port = int(portEnv) - - resInsightExecutable = os.environ.get('RESINSIGHT_EXECUTABLE') - if resInsightExecutable is None: - print('Error: Could not launch any ResInsight instances because RESINSIGHT_EXECUTABLE is not set') - return None - - while Instance.is_port_in_use(port): - port += 1 - - print('Port ' + str(port)) - print('Trying to launch', resInsightExecutable) - pid = os.spawnl(os.P_NOWAIT, resInsightExecutable, " --grpcserver " + str(port)) - print(pid) - return Instance(port) - - @staticmethod - def find(startPort = 50051, endPort = 50071): - portEnv = os.environ.get('RESINSIGHT_GRPC_PORT') - if portEnv: - startPort = int(portEnv) - endPort = startPort + 20 - - for tryPort in range(startPort, endPort): - if Instance.is_port_in_use(tryPort): - return Instance(tryPort) - - print('Error: Could not find any ResInsight instances responding between ports ' + str(startPort) + ' and ' + str(endPort)) - return None - - def __init__(self, port = 50051): - logging.basicConfig() - location = "localhost:" + str(port) - self.channel = grpc.insecure_channel(location) - - # Main version check package - self.appInfo = AppInfo(self.channel) - try: - majorVersionOk = self.appInfo.majorVersion() == int(RiaVersionInfo.RESINSIGHT_MAJOR_VERSION) - minorVersionOk = self.appInfo.minorVersion() == int(RiaVersionInfo.RESINSIGHT_MINOR_VERSION) - if not (majorVersionOk and minorVersionOk): - raise Exception('Version of ResInsight does not match version of Python API') - except grpc.RpcError as e: - if e.code() == grpc.StatusCode.UNAVAILABLE: - print('Info: Could not find any instances at port ' + str(port)) - except Exception as e: - print('Error:', e) - - # Service packages - self.commands = Commands(self.channel) - self.project = Project(self.channel) - \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/Python/examples/AllCases.py b/ApplicationCode/GrpcInterface/Python/rips/examples/AllCases.py similarity index 80% rename from ApplicationCode/GrpcInterface/Python/examples/AllCases.py rename to ApplicationCode/GrpcInterface/Python/rips/examples/AllCases.py index 5e0acab19a..3c0a742389 100644 --- a/ApplicationCode/GrpcInterface/Python/examples/AllCases.py +++ b/ApplicationCode/GrpcInterface/Python/rips/examples/AllCases.py @@ -1,7 +1,7 @@ import sys import os -sys.path.insert(1, os.path.join(sys.path[0], '..')) +sys.path.insert(1, os.path.join(sys.path[0], '../../')) import rips resInsight = rips.Instance.find() diff --git a/ApplicationCode/GrpcInterface/Python/examples/CaseInfoStreamingExample.py b/ApplicationCode/GrpcInterface/Python/rips/examples/CaseInfoStreamingExample.py similarity index 91% rename from ApplicationCode/GrpcInterface/Python/examples/CaseInfoStreamingExample.py rename to ApplicationCode/GrpcInterface/Python/rips/examples/CaseInfoStreamingExample.py index 861e1e8789..409a75f9ac 100644 --- a/ApplicationCode/GrpcInterface/Python/examples/CaseInfoStreamingExample.py +++ b/ApplicationCode/GrpcInterface/Python/rips/examples/CaseInfoStreamingExample.py @@ -1,6 +1,6 @@ import sys import os -sys.path.insert(1, os.path.join(sys.path[0], '..')) +sys.path.insert(1, os.path.join(sys.path[0], '../../')) import rips resInsight = rips.Instance.find() diff --git a/ApplicationCode/GrpcInterface/Python/examples/CommandExample.py b/ApplicationCode/GrpcInterface/Python/rips/examples/CommandExample.py similarity index 94% rename from ApplicationCode/GrpcInterface/Python/examples/CommandExample.py rename to ApplicationCode/GrpcInterface/Python/rips/examples/CommandExample.py index f9b6376641..3fa9d48890 100644 --- a/ApplicationCode/GrpcInterface/Python/examples/CommandExample.py +++ b/ApplicationCode/GrpcInterface/Python/rips/examples/CommandExample.py @@ -1,7 +1,7 @@ import sys import os import tempfile -sys.path.insert(1, os.path.join(sys.path[0], '..')) +sys.path.insert(1, os.path.join(sys.path[0], '../../')) import rips # Load instance diff --git a/ApplicationCode/GrpcInterface/Python/examples/GridInformation.py b/ApplicationCode/GrpcInterface/Python/rips/examples/GridInformation.py similarity index 85% rename from ApplicationCode/GrpcInterface/Python/examples/GridInformation.py rename to ApplicationCode/GrpcInterface/Python/rips/examples/GridInformation.py index f0f9156816..66e0bcbcd9 100644 --- a/ApplicationCode/GrpcInterface/Python/examples/GridInformation.py +++ b/ApplicationCode/GrpcInterface/Python/rips/examples/GridInformation.py @@ -1,6 +1,6 @@ import sys import os -sys.path.insert(1, os.path.join(sys.path[0], '..')) +sys.path.insert(1, os.path.join(sys.path[0], '../../')) import rips diff --git a/ApplicationCode/GrpcInterface/Python/examples/InputPropTestAsync.py b/ApplicationCode/GrpcInterface/Python/rips/examples/InputPropTestAsync.py similarity index 88% rename from ApplicationCode/GrpcInterface/Python/examples/InputPropTestAsync.py rename to ApplicationCode/GrpcInterface/Python/rips/examples/InputPropTestAsync.py index dff8f645f9..237164e78d 100644 --- a/ApplicationCode/GrpcInterface/Python/examples/InputPropTestAsync.py +++ b/ApplicationCode/GrpcInterface/Python/rips/examples/InputPropTestAsync.py @@ -1,6 +1,6 @@ import sys import os -sys.path.insert(1, os.path.join(sys.path[0], '..')) +sys.path.insert(1, os.path.join(sys.path[0], '../../')) import rips import time diff --git a/ApplicationCode/GrpcInterface/Python/examples/InputPropTestSync.py b/ApplicationCode/GrpcInterface/Python/rips/examples/InputPropTestSync.py similarity index 89% rename from ApplicationCode/GrpcInterface/Python/examples/InputPropTestSync.py rename to ApplicationCode/GrpcInterface/Python/rips/examples/InputPropTestSync.py index 5711e4d5b6..4618fa5556 100644 --- a/ApplicationCode/GrpcInterface/Python/examples/InputPropTestSync.py +++ b/ApplicationCode/GrpcInterface/Python/rips/examples/InputPropTestSync.py @@ -1,6 +1,6 @@ import sys import os -sys.path.insert(1, os.path.join(sys.path[0], '..')) +sys.path.insert(1, os.path.join(sys.path[0], '../../')) import rips import time diff --git a/ApplicationCode/GrpcInterface/Python/examples/SelectedCases.py b/ApplicationCode/GrpcInterface/Python/rips/examples/SelectedCases.py similarity index 85% rename from ApplicationCode/GrpcInterface/Python/examples/SelectedCases.py rename to ApplicationCode/GrpcInterface/Python/rips/examples/SelectedCases.py index 89b35fd4a6..de17ac08fb 100644 --- a/ApplicationCode/GrpcInterface/Python/examples/SelectedCases.py +++ b/ApplicationCode/GrpcInterface/Python/rips/examples/SelectedCases.py @@ -1,6 +1,6 @@ import sys import os -sys.path.insert(1, os.path.join(sys.path[0], '..')) +sys.path.insert(1, os.path.join(sys.path[0], '../../')) import rips diff --git a/ApplicationCode/GrpcInterface/Python/examples/SetGridProperties.py b/ApplicationCode/GrpcInterface/Python/rips/examples/SetGridProperties.py similarity index 86% rename from ApplicationCode/GrpcInterface/Python/examples/SetGridProperties.py rename to ApplicationCode/GrpcInterface/Python/rips/examples/SetGridProperties.py index 7fe0b295e8..23a51f5fa4 100644 --- a/ApplicationCode/GrpcInterface/Python/examples/SetGridProperties.py +++ b/ApplicationCode/GrpcInterface/Python/rips/examples/SetGridProperties.py @@ -1,6 +1,6 @@ import sys import os -sys.path.insert(1, os.path.join(sys.path[0], '..')) +sys.path.insert(1, os.path.join(sys.path[0], '../../')) import rips resInsight = rips.Instance.find() diff --git a/ApplicationCode/GrpcInterface/Python/examples/SoilAverage.py b/ApplicationCode/GrpcInterface/Python/rips/examples/SoilAverage.py similarity index 89% rename from ApplicationCode/GrpcInterface/Python/examples/SoilAverage.py rename to ApplicationCode/GrpcInterface/Python/rips/examples/SoilAverage.py index 56270e7ffc..6b89ce95a7 100644 --- a/ApplicationCode/GrpcInterface/Python/examples/SoilAverage.py +++ b/ApplicationCode/GrpcInterface/Python/rips/examples/SoilAverage.py @@ -1,6 +1,6 @@ import sys import os -sys.path.insert(1, os.path.join(sys.path[0], '..')) +sys.path.insert(1, os.path.join(sys.path[0], '../../')) import rips import itertools import time diff --git a/ApplicationCode/GrpcInterface/Python/examples/SoilAverageNoComm.py b/ApplicationCode/GrpcInterface/Python/rips/examples/SoilAverageNoComm.py similarity index 100% rename from ApplicationCode/GrpcInterface/Python/examples/SoilAverageNoComm.py rename to ApplicationCode/GrpcInterface/Python/rips/examples/SoilAverageNoComm.py diff --git a/ApplicationCode/GrpcInterface/Python/examples/SoilPorvAsync.py b/ApplicationCode/GrpcInterface/Python/rips/examples/SoilPorvAsync.py similarity index 90% rename from ApplicationCode/GrpcInterface/Python/examples/SoilPorvAsync.py rename to ApplicationCode/GrpcInterface/Python/rips/examples/SoilPorvAsync.py index 0015eb14b9..640468beda 100644 --- a/ApplicationCode/GrpcInterface/Python/examples/SoilPorvAsync.py +++ b/ApplicationCode/GrpcInterface/Python/rips/examples/SoilPorvAsync.py @@ -1,6 +1,6 @@ import sys import os -sys.path.insert(1, os.path.join(sys.path[0], '..')) +sys.path.insert(1, os.path.join(sys.path[0], '../../')) import rips def createResult(soilChunks, porvChunks): diff --git a/ApplicationCode/GrpcInterface/Python/examples/SoilPorvSync.py b/ApplicationCode/GrpcInterface/Python/rips/examples/SoilPorvSync.py similarity index 89% rename from ApplicationCode/GrpcInterface/Python/examples/SoilPorvSync.py rename to ApplicationCode/GrpcInterface/Python/rips/examples/SoilPorvSync.py index 81bf8cbb7c..4c8b44537c 100644 --- a/ApplicationCode/GrpcInterface/Python/examples/SoilPorvSync.py +++ b/ApplicationCode/GrpcInterface/Python/rips/examples/SoilPorvSync.py @@ -1,6 +1,6 @@ import sys import os -sys.path.insert(1, os.path.join(sys.path[0], '..')) +sys.path.insert(1, os.path.join(sys.path[0], '../../')) import rips resInsight = rips.Instance.find() diff --git a/ApplicationCode/GrpcInterface/Python/tests/conftest.py b/ApplicationCode/GrpcInterface/Python/rips/tests/conftest.py similarity index 91% rename from ApplicationCode/GrpcInterface/Python/tests/conftest.py rename to ApplicationCode/GrpcInterface/Python/rips/tests/conftest.py index a862d65c69..996ea6688e 100644 --- a/ApplicationCode/GrpcInterface/Python/tests/conftest.py +++ b/ApplicationCode/GrpcInterface/Python/rips/tests/conftest.py @@ -3,7 +3,7 @@ import sys import os import getopt -sys.path.insert(1, os.path.join(sys.path[0], '..')) +sys.path.insert(1, os.path.join(sys.path[0], '../../')) import rips _rips_instance = None diff --git a/ApplicationCode/GrpcInterface/Python/rips/tests/dataroot.py b/ApplicationCode/GrpcInterface/Python/rips/tests/dataroot.py new file mode 100644 index 0000000000..63ac446863 --- /dev/null +++ b/ApplicationCode/GrpcInterface/Python/rips/tests/dataroot.py @@ -0,0 +1 @@ +PATH = "../../../../TestModels" \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/Python/tests/test_cases.py b/ApplicationCode/GrpcInterface/Python/rips/tests/test_cases.py similarity index 97% rename from ApplicationCode/GrpcInterface/Python/tests/test_cases.py rename to ApplicationCode/GrpcInterface/Python/rips/tests/test_cases.py index e0c61b6a31..ab1579c5e8 100644 --- a/ApplicationCode/GrpcInterface/Python/tests/test_cases.py +++ b/ApplicationCode/GrpcInterface/Python/rips/tests/test_cases.py @@ -2,7 +2,7 @@ import sys import os import pytest -sys.path.insert(1, os.path.join(sys.path[0], '..')) +sys.path.insert(1, os.path.join(sys.path[0], '../../')) import rips import dataroot diff --git a/ApplicationCode/GrpcInterface/Python/tests/test_commands.py b/ApplicationCode/GrpcInterface/Python/rips/tests/test_commands.py similarity index 93% rename from ApplicationCode/GrpcInterface/Python/tests/test_commands.py rename to ApplicationCode/GrpcInterface/Python/rips/tests/test_commands.py index ec99c0aa6a..906a2902e2 100644 --- a/ApplicationCode/GrpcInterface/Python/tests/test_commands.py +++ b/ApplicationCode/GrpcInterface/Python/rips/tests/test_commands.py @@ -3,7 +3,7 @@ import os import tempfile import pytest -sys.path.insert(1, os.path.join(sys.path[0], '..')) +sys.path.insert(1, os.path.join(sys.path[0], '../../')) import rips import dataroot diff --git a/ApplicationCode/GrpcInterface/Python/tests/test_grids.py b/ApplicationCode/GrpcInterface/Python/rips/tests/test_grids.py similarity index 88% rename from ApplicationCode/GrpcInterface/Python/tests/test_grids.py rename to ApplicationCode/GrpcInterface/Python/rips/tests/test_grids.py index cb75df14d4..52556d94da 100644 --- a/ApplicationCode/GrpcInterface/Python/tests/test_grids.py +++ b/ApplicationCode/GrpcInterface/Python/rips/tests/test_grids.py @@ -1,7 +1,7 @@ import sys import os -sys.path.insert(1, os.path.join(sys.path[0], '..')) +sys.path.insert(1, os.path.join(sys.path[0], '../../')) import rips import dataroot diff --git a/ApplicationCode/GrpcInterface/Python/tests/test_project.py b/ApplicationCode/GrpcInterface/Python/rips/tests/test_project.py similarity index 82% rename from ApplicationCode/GrpcInterface/Python/tests/test_project.py rename to ApplicationCode/GrpcInterface/Python/rips/tests/test_project.py index 3786b918ff..9595923d4b 100644 --- a/ApplicationCode/GrpcInterface/Python/tests/test_project.py +++ b/ApplicationCode/GrpcInterface/Python/rips/tests/test_project.py @@ -2,7 +2,7 @@ import sys import os import pytest -sys.path.insert(1, os.path.join(sys.path[0], '..')) +sys.path.insert(1, os.path.join(sys.path[0], '../../')) import rips import dataroot diff --git a/ApplicationCode/GrpcInterface/Python/tests/test_properties.py b/ApplicationCode/GrpcInterface/Python/rips/tests/test_properties.py similarity index 97% rename from ApplicationCode/GrpcInterface/Python/tests/test_properties.py rename to ApplicationCode/GrpcInterface/Python/rips/tests/test_properties.py index 9ef3561a7b..0966df800c 100644 --- a/ApplicationCode/GrpcInterface/Python/tests/test_properties.py +++ b/ApplicationCode/GrpcInterface/Python/rips/tests/test_properties.py @@ -2,7 +2,7 @@ import sys import os import pytest -sys.path.insert(1, os.path.join(sys.path[0], '..')) +sys.path.insert(1, os.path.join(sys.path[0], '../../')) import rips import dataroot diff --git a/ApplicationCode/GrpcInterface/Python/setup.py.cmake b/ApplicationCode/GrpcInterface/Python/setup.py.cmake index 6e447b1644..e067cd1567 100644 --- a/ApplicationCode/GrpcInterface/Python/setup.py.cmake +++ b/ApplicationCode/GrpcInterface/Python/setup.py.cmake @@ -6,7 +6,7 @@ with open('README.md') as f: with open('LICENSE') as f: license = f.read() -RIPS_DIST_VERSION = '2' +RIPS_DIST_VERSION = '3' setup( name='rips', @@ -17,5 +17,5 @@ setup( author_email='info@ceetronsolutions.com', url='http://www.resinsight.org', license=license, - packages=find_packages(exclude=('tests', 'docs', '__pycache', 'examples')) + packages=find_packages(exclude=('docs', '__pycache__')) ) \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/Python/tests/dataroot.py b/ApplicationCode/GrpcInterface/Python/tests/dataroot.py deleted file mode 100644 index 16c2b32354..0000000000 --- a/ApplicationCode/GrpcInterface/Python/tests/dataroot.py +++ /dev/null @@ -1 +0,0 @@ -PATH = "../../../TestModels" \ No newline at end of file From 6a2d1def1dd2e26d6b69572aff78b4feca457df6 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Wed, 12 Jun 2019 08:48:08 +0200 Subject: [PATCH 168/396] gRPC install updates --- GRPC_install_instructions.txt | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/GRPC_install_instructions.txt b/GRPC_install_instructions.txt index 51ef9e81b9..9800a105a4 100644 --- a/GRPC_install_instructions.txt +++ b/GRPC_install_instructions.txt @@ -53,9 +53,12 @@ scl enable devtoolset-6 rh-python35 bash # 3. Run grpc install script and install to a user-writable directory. I.e, from within the ResInsight folder: # Most of this runs fine without root. But unfortunately grpc currently fails to install the C++ library without root. # So the script is required to be run as root even if the provided folders are writeable by the user -# WARNING: As of grpc 1.21.1 a long install directory (/opt/grpc in the example below) may get you into trouble -# with this bug: https://github.com/grpc/grpc/issues/14844 -# A patch is available in the issue, but the easiest thing to do is to ensure a short install path +# +# WARNING: As of grpc 1.21.1 a long install directory may cause you to trigger a gRPC bug. +# The installation directory is the second argument (/opt/grpc in the example, which isn't too long). +# +# Bug: https://github.com/grpc/grpc/issues/14844 +# A workaround patch is available in the issue, but the easiest thing to do is to ensure a short install path ################################################################################################################ sudo ./build-grpc-linux.sh /tmp/grpc /opt/grpc From 4b8b4ea47ae4f0a235da853176972484ddfa6a45 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 12 Jun 2019 15:26:37 +0200 Subject: [PATCH 169/396] #4405 Derived Ensemble: Fix missing mean value for part of summary plot --- .../ProjectDataModel/Summary/RimEnsembleStatisticsCase.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/Summary/RimEnsembleStatisticsCase.cpp b/ApplicationCode/ProjectDataModel/Summary/RimEnsembleStatisticsCase.cpp index 7165de359d..0531db1112 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimEnsembleStatisticsCase.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimEnsembleStatisticsCase.cpp @@ -256,8 +256,11 @@ void RimEnsembleStatisticsCase::calculateStatistics(const std::vector& v std::multiset vSet(values.begin(), values.end()); for (double v : vSet) { - sortedValues.push_back(v); - valueSum += v; + if (RiaStatisticsTools::isValidNumber(v)) + { + sortedValues.push_back(v); + valueSum += v; + } } } From a6210cfcc1c986259a003bbc9c1e7a452d23f38c Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 13 Jun 2019 17:32:47 +0200 Subject: [PATCH 170/396] Whitespace --- .../Application/RiaSummaryCurveDefinition.cpp | 49 +++++++++---------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/ApplicationCode/Application/RiaSummaryCurveDefinition.cpp b/ApplicationCode/Application/RiaSummaryCurveDefinition.cpp index 599603f0a7..bc014a5986 100644 --- a/ApplicationCode/Application/RiaSummaryCurveDefinition.cpp +++ b/ApplicationCode/Application/RiaSummaryCurveDefinition.cpp @@ -1,17 +1,17 @@ ///////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2017 Statoil ASA -// +// // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// +// // ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. -// -// See the GNU General Public License at +// +// See the GNU General Public License at // for more details. // ///////////////////////////////////////////////////////////////////////////////// @@ -26,27 +26,26 @@ /// //-------------------------------------------------------------------------------------------------- RiaSummaryCurveDefinition::RiaSummaryCurveDefinition() -: m_summaryCase(nullptr) -, m_ensemble(nullptr) + : m_summaryCase(nullptr) + , m_ensemble(nullptr) { } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- -RiaSummaryCurveDefinition::RiaSummaryCurveDefinition(RimSummaryCase* summaryCase, +RiaSummaryCurveDefinition::RiaSummaryCurveDefinition(RimSummaryCase* summaryCase, const RifEclipseSummaryAddress& summaryAddress, - RimSummaryCaseCollection* ensemble) + RimSummaryCaseCollection* ensemble) : m_summaryCase(summaryCase) , m_ensemble(ensemble) , m_summaryAddress(summaryAddress) { - } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- RimSummaryCase* RiaSummaryCurveDefinition::summaryCase() const { @@ -54,7 +53,7 @@ RimSummaryCase* RiaSummaryCurveDefinition::summaryCase() const } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- RimSummaryCaseCollection* RiaSummaryCurveDefinition::ensemble() const { @@ -62,7 +61,7 @@ RimSummaryCaseCollection* RiaSummaryCurveDefinition::ensemble() const } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- const RifEclipseSummaryAddress& RiaSummaryCurveDefinition::summaryAddress() const { @@ -70,16 +69,15 @@ const RifEclipseSummaryAddress& RiaSummaryCurveDefinition::summaryAddress() cons } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- bool RiaSummaryCurveDefinition::isEnsembleCurve() const { return m_ensemble != nullptr; } - //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- void RiaSummaryCurveDefinition::resultValues(const RiaSummaryCurveDefinition& curveDefinition, std::vector* values) { @@ -87,7 +85,7 @@ void RiaSummaryCurveDefinition::resultValues(const RiaSummaryCurveDefinition& cu if (!curveDefinition.summaryAddress().isValid()) return; if (!curveDefinition.summaryCase()) return; - + RifSummaryReaderInterface* reader = curveDefinition.summaryCase()->summaryReader(); if (!reader) return; @@ -95,7 +93,7 @@ void RiaSummaryCurveDefinition::resultValues(const RiaSummaryCurveDefinition& cu } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- const std::vector& RiaSummaryCurveDefinition::timeSteps(const RiaSummaryCurveDefinition& curveDefinition) { @@ -111,19 +109,21 @@ const std::vector& RiaSummaryCurveDefinition::timeSteps(const RiaSummary } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- QString RiaSummaryCurveDefinition::curveDefinitionText() const { QString caseName; - if (summaryCase() ) caseName = summaryCase()->caseName(); - else if (ensemble()) caseName = ensemble()->name(); - + if (summaryCase()) + caseName = summaryCase()->caseName(); + else if (ensemble()) + caseName = ensemble()->name(); + return RiaSummaryCurveDefinition::curveDefinitionText(caseName, summaryAddress()); } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- QString RiaSummaryCurveDefinition::curveDefinitionText(const QString& caseName, const RifEclipseSummaryAddress& summaryAddress) { @@ -138,7 +138,7 @@ QString RiaSummaryCurveDefinition::curveDefinitionText(const QString& caseName, } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- bool RiaSummaryCurveDefinition::operator<(const RiaSummaryCurveDefinition& other) const { @@ -183,4 +183,3 @@ bool RiaSummaryCurveDefinition::operator<(const RiaSummaryCurveDefinition& other return (m_summaryAddress < other.summaryAddress()); } - From a5670cdb0e403263d912bd4a23b3f3116c680758 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 13 Jun 2019 17:34:25 +0200 Subject: [PATCH 171/396] #4482 Summary Plot: Missing curve if same case name, but different folders --- .../Application/RiaSummaryCurveDefinition.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/ApplicationCode/Application/RiaSummaryCurveDefinition.cpp b/ApplicationCode/Application/RiaSummaryCurveDefinition.cpp index bc014a5986..79285ac184 100644 --- a/ApplicationCode/Application/RiaSummaryCurveDefinition.cpp +++ b/ApplicationCode/Application/RiaSummaryCurveDefinition.cpp @@ -142,6 +142,7 @@ QString RiaSummaryCurveDefinition::curveDefinitionText(const QString& caseName, //-------------------------------------------------------------------------------------------------- bool RiaSummaryCurveDefinition::operator<(const RiaSummaryCurveDefinition& other) const { + if (m_ensemble != other.ensemble()) { QString ensembleName; QString otherEnsembleName; @@ -156,12 +157,17 @@ bool RiaSummaryCurveDefinition::operator<(const RiaSummaryCurveDefinition& other otherEnsembleName = other.ensemble()->name(); } + // First check if names are different to ensure stable alphabetic sort if (ensembleName != otherEnsembleName) { return ensembleName < otherEnsembleName; } + + // Use pointer address, sorting will be be unstable + return m_ensemble < other.ensemble(); } + if (m_summaryCase != other.summaryCase()) { QString summaryCaseName; QString otherSummaryCaseName; @@ -175,10 +181,14 @@ bool RiaSummaryCurveDefinition::operator<(const RiaSummaryCurveDefinition& other otherSummaryCaseName = other.summaryCase()->caseName(); } + // First check if names are different to ensure stable alphabetic sort if (summaryCaseName != otherSummaryCaseName) { return summaryCaseName < otherSummaryCaseName; } + + // Use pointer address, sorting will be be unstable + return m_summaryCase < other.summaryCase(); } return (m_summaryAddress < other.summaryAddress()); From 3611d32e9ed2b8cfa53d6ea6b1020c6d36937a66 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Wed, 12 Jun 2019 11:27:54 +0200 Subject: [PATCH 172/396] Python: make rips packages complete --- ApplicationCode/GrpcInterface/Python/MANIFEST.in | 4 ++++ ApplicationCode/GrpcInterface/Python/rips/Instance.py | 2 +- ApplicationCode/GrpcInterface/Python/setup.py.cmake | 5 +++-- 3 files changed, 8 insertions(+), 3 deletions(-) create mode 100644 ApplicationCode/GrpcInterface/Python/MANIFEST.in diff --git a/ApplicationCode/GrpcInterface/Python/MANIFEST.in b/ApplicationCode/GrpcInterface/Python/MANIFEST.in new file mode 100644 index 0000000000..113b7ecdf3 --- /dev/null +++ b/ApplicationCode/GrpcInterface/Python/MANIFEST.in @@ -0,0 +1,4 @@ +include *.txt +include *.md +include LICENSE +recursive-include rips *.py diff --git a/ApplicationCode/GrpcInterface/Python/rips/Instance.py b/ApplicationCode/GrpcInterface/Python/rips/Instance.py index 9ae3db2850..d8b626c5a2 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Instance.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Instance.py @@ -134,7 +134,7 @@ class Instance: connectionOk, versionOk = self.__checkVersion() if not connectionOk: - if launched: + if self.launched: raise Exception('Error: Could not connect to resinsight at ', location, ' after trying 10 times with 1 second apart') else: raise Exception('Error: Could not connect to resinsight at ', location) diff --git a/ApplicationCode/GrpcInterface/Python/setup.py.cmake b/ApplicationCode/GrpcInterface/Python/setup.py.cmake index e067cd1567..17dbffd5fc 100644 --- a/ApplicationCode/GrpcInterface/Python/setup.py.cmake +++ b/ApplicationCode/GrpcInterface/Python/setup.py.cmake @@ -6,7 +6,7 @@ with open('README.md') as f: with open('LICENSE') as f: license = f.read() -RIPS_DIST_VERSION = '3' +RIPS_DIST_VERSION = '8' setup( name='rips', @@ -17,5 +17,6 @@ setup( author_email='info@ceetronsolutions.com', url='http://www.resinsight.org', license=license, - packages=find_packages(exclude=('docs', '__pycache__')) + include_package_data=True, + packages=['rips', 'rips.generated', 'rips.examples', 'rips.tests'] ) \ No newline at end of file From b7865aea95475f41ba3fdc58ad1a98314a048e43 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 14 Jun 2019 10:45:24 +0200 Subject: [PATCH 173/396] #2023 SSI-hub: Create ResInsight project at well path download --- .../RicWellPathsImportSsihubFeature.cpp | 39 +++++++++++++------ 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/ApplicationCode/Commands/WellPathCommands/RicWellPathsImportSsihubFeature.cpp b/ApplicationCode/Commands/WellPathCommands/RicWellPathsImportSsihubFeature.cpp index aa11da2c5d..f407acd445 100644 --- a/ApplicationCode/Commands/WellPathCommands/RicWellPathsImportSsihubFeature.cpp +++ b/ApplicationCode/Commands/WellPathCommands/RicWellPathsImportSsihubFeature.cpp @@ -32,6 +32,7 @@ #include #include #include +#include CAF_CMD_SOURCE_INIT(RicWellPathsImportSsihubFeature, "RicWellPathsImportSsihubFeature"); @@ -41,17 +42,6 @@ CAF_CMD_SOURCE_INIT(RicWellPathsImportSsihubFeature, "RicWellPathsImportSsihubFe //-------------------------------------------------------------------------------------------------- bool RicWellPathsImportSsihubFeature::isCommandEnabled() { - RiaApplication* app = RiaApplication::instance(); - if (!app->project()) - { - return false; - } - - if (!caf::Utils::fileExists(app->project()->fileName())) - { - return false; - } - return true; } @@ -63,8 +53,33 @@ void RicWellPathsImportSsihubFeature::onActionTriggered(bool isChecked) RiaApplication* app = RiaApplication::instance(); if (!app->project()) return; - if (!caf::Utils::fileExists(app->project()->fileName())) return; + if (!caf::Utils::fileExists(app->project()->fileName())) + { + RiaGuiApplication* guiApp = RiaGuiApplication::instance(); + if (guiApp) + { + QMessageBox msgBox(guiApp->mainWindow()); + msgBox.setIcon(QMessageBox::Question); + QString questionText = QString("Import of well paths will be stored as a part of a ResInsight project file. Please " + "save the project to file before importing well paths."); + + msgBox.setText(questionText); + msgBox.setInformativeText("Do you want to save the project?"); + msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + + int ret = msgBox.exec(); + if (ret == QMessageBox::Yes) + { + guiApp->saveProject(); + } + } + + if (!caf::Utils::fileExists(app->project()->fileName())) + { + return; + } + } // Update the UTM bounding box from the reservoir app->project()->computeUtmAreaOfInterest(); From 6701e136647a204f8ee443754e8f3221df3e9c2b Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 14 Jun 2019 10:45:47 +0200 Subject: [PATCH 174/396] Whitespace --- .../RicWellPathsImportSsihubFeature.cpp | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/ApplicationCode/Commands/WellPathCommands/RicWellPathsImportSsihubFeature.cpp b/ApplicationCode/Commands/WellPathCommands/RicWellPathsImportSsihubFeature.cpp index f407acd445..0b9d0e3514 100644 --- a/ApplicationCode/Commands/WellPathCommands/RicWellPathsImportSsihubFeature.cpp +++ b/ApplicationCode/Commands/WellPathCommands/RicWellPathsImportSsihubFeature.cpp @@ -2,17 +2,17 @@ // // Copyright (C) 2015- Statoil ASA // Copyright (C) 2015- Ceetron Solutions AS -// +// // 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 +// +// See the GNU General Public License at // for more details. // ///////////////////////////////////////////////////////////////////////////////// @@ -36,9 +36,8 @@ CAF_CMD_SOURCE_INIT(RicWellPathsImportSsihubFeature, "RicWellPathsImportSsihubFeature"); - //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- bool RicWellPathsImportSsihubFeature::isCommandEnabled() { @@ -46,7 +45,7 @@ bool RicWellPathsImportSsihubFeature::isCommandEnabled() } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- void RicWellPathsImportSsihubFeature::onActionTriggered(bool isChecked) { @@ -94,12 +93,13 @@ void RicWellPathsImportSsihubFeature::onActionTriggered(bool isChecked) QString copyOfOriginalObject = app->project()->wellPathImport()->writeObjectToXmlString(); if (!app->preferences()) return; - RiuWellImportWizard wellImportwizard(app->preferences()->ssihubAddress, wellPathsFolderPath, app->project()->wellPathImport(), RiuMainWindow::instance()); + RiuWellImportWizard wellImportwizard( + app->preferences()->ssihubAddress, wellPathsFolderPath, app->project()->wellPathImport(), RiuMainWindow::instance()); // Get password/username from application cache { #ifdef _DEBUG - // Valid credentials for ssihubfake received in mail from Håkon + // Valid credentials for ssihubfake received in mail from Håkon QString ssihubUsername = "admin"; QString ssihubPassword = "resinsight"; #else @@ -127,7 +127,7 @@ void RicWellPathsImportSsihubFeature::onActionTriggered(bool isChecked) } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- void RicWellPathsImportSsihubFeature::setupActionLook(QAction* actionToSetup) { From 055cb732db4e065071a02870ed2755f2c147428b Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Fri, 14 Jun 2019 16:07:09 +0200 Subject: [PATCH 175/396] Python: fix up some examples --- .../GrpcInterface/CMakeLists.cmake | 2 + .../GrpcInterface/Python/rips/Case.py | 21 ++++-- .../GrpcInterface/Python/rips/Commands.py | 69 +++++++++++++++++-- .../GrpcInterface/Python/rips/Instance.py | 12 ++-- .../GrpcInterface/Python/rips/Project.py | 6 +- .../GrpcInterface/Python/rips/Properties.py | 56 +++++++-------- .../GrpcInterface/Python/rips/__init__.py | 3 + .../Python/rips/examples/AppInfo.py | 10 +++ .../rips/examples/InputPropTestAsync.py | 5 +- .../Python/rips/examples/InputPropTestSync.py | 1 + .../Python/rips/examples/InstanceExample.py | 10 +++ .../GrpcInterface/Python/setup.py.cmake | 2 +- 12 files changed, 148 insertions(+), 49 deletions(-) create mode 100644 ApplicationCode/GrpcInterface/Python/rips/examples/AppInfo.py create mode 100644 ApplicationCode/GrpcInterface/Python/rips/examples/InstanceExample.py diff --git a/ApplicationCode/GrpcInterface/CMakeLists.cmake b/ApplicationCode/GrpcInterface/CMakeLists.cmake index 79d2117361..6096786078 100644 --- a/ApplicationCode/GrpcInterface/CMakeLists.cmake +++ b/ApplicationCode/GrpcInterface/CMakeLists.cmake @@ -156,6 +156,8 @@ if (PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) "rips/Project.py" "rips/Properties.py" "rips/Instance.py" + "rips/examples/AppInfo.py" + "rips/examples/InstanceExample.py" "rips/examples/CommandExample.py" "rips/examples/CaseInfoStreamingExample.py" "rips/examples/SoilPorvAsync.py" diff --git a/ApplicationCode/GrpcInterface/Python/rips/Case.py b/ApplicationCode/GrpcInterface/Python/rips/Case.py index 000843a563..202fb3fd24 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Case.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Case.py @@ -17,9 +17,9 @@ class Case: methods in Project: loadCase, case, allCases, selectedCases Attributes: - id(int): Case Id corresponding to case Id in ResInsight project. - name(string): Case name - groupId(int): Case Group id + id (int): Case Id corresponding to case Id in ResInsight project. + name (str): Case name + groupId (int): Case Group id """ def __init__(self, channel, id): self.channel = channel @@ -43,7 +43,13 @@ class Case: return 0 def grid(self, index): - """Get Grid of a given index. Returns a rips Grid object""" + """Get Grid of a given index. Returns a rips Grid object + + Arguments: + index (int): The grid index + + Returns: Grid object + """ return Grid(index, self) def grids(self): @@ -58,7 +64,7 @@ class Case: total number of cells Arguments: - porosityModel(string): String representing an enum. + porosityModel (str): String representing an enum. must be 'MATRIX_MODEL' or 'FRACTURE_MODEL'. Returns: Cell Count object with the following integer attributes: @@ -72,9 +78,11 @@ class Case: def cellInfoForActiveCells(self, porosityModel='MATRIX_MODEL'): """Get Stream of cell info objects for current case + Arguments: - porosityModel(string): String representing an enum. + porosityModel(str): String representing an enum. must be 'MATRIX_MODEL' or 'FRACTURE_MODEL'. + Returns: Stream of cell info objects with the following attributes: grid_index(int): grid the cell belongs to @@ -82,6 +90,7 @@ class Case: coarsening_box_index(int): the coarsening box index local_ijk(Vec3i: i(int), j(int), k(int)): local cell index in i, j, k directions. parent_ijk(Vec3i: i(int), j(int), k(int)): cell index in parent grid in i, j, k. + """ porosityModelEnum = Case_pb2.PorosityModelType.Value(porosityModel) request = Case_pb2.CellInfoRequest(case_request=self.request, diff --git a/ApplicationCode/GrpcInterface/Python/rips/Commands.py b/ApplicationCode/GrpcInterface/Python/rips/Commands.py index 687e3b5c58..87517aa3a5 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Commands.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Commands.py @@ -16,8 +16,9 @@ class Commands: https://resinsight.org/docs/commandfile/ The differences are: - 1. Enum values have to be provided as strings. I.e. "ALL" instead of ALL. - 2. Booleans have to be specified as correct Python. True instead of true. + * Enum values have to be provided as strings. I.e. "ALL" instead of ALL. + * Booleans have to be specified as correct Python. True instead of true. + """ def __init__(self, channel): self.channel = channel @@ -37,24 +38,61 @@ class Commands: ######################## def openProject(self, path): + """Open a project + + Arguments: + path (str): path to project file + + + """ return self.__execute(openProject=Cmd.FilePathRequest(path=path)) def closeProject(self): + """Close the current project (and reopen empty one)""" return self.__execute(closeProject=Empty()) def setStartDir(self, path): + """Set current start directory + + Arguments: + path (str): path to directory + + """ return self.__execute(setStartDir=Cmd.FilePathRequest(path=path)) def loadCase(self, path): + """Load a case + + Arguments: + path (str): path to EGRID file + + Returns: + A Case object + + """ commandReply = self.__execute(loadCase=Cmd.FilePathRequest(path=path)) assert commandReply.HasField("loadCaseResult") return Case(self.channel, commandReply.loadCaseResult.id) - def replaceCase(self, path, caseId=0): - return self.__execute(replaceCase=Cmd.ReplaceCaseRequest(newGridFile=path, + def replaceCase(self, newGridFile, caseId=0): + """Replace the given case with a new case loaded from file + + Arguments: + newGridFile (str): path to EGRID file + caseId (int): case Id to replace + + """ + return self.__execute(replaceCase=Cmd.ReplaceCaseRequest(newGridFile=newGridFile, caseId=caseId)) def replaceSourceCases(self, gridListFile, caseGroupId=0): + """Replace all source cases within a case group + + Arguments: + gridListFile (str): path to file containing a list of cases + caseGroupId (int): id of the case group to replace + + """ return self.__execute(replaceSourceCases=Cmd.ReplaceSourceCasesRequest(gridListFile=gridListFile, caseGroupId=caseGroupId)) ################## @@ -62,13 +100,36 @@ class Commands: ################## def exportMultiCaseSnapshots(self, gridListFile): + """Export snapshots for a set of cases + + Arguments: + gridListFile (str): Path to a file containing a list of grids to export snapshot for + + """ return self.__execute(exportMultiCaseSnapshot=Cmd.ExportMultiCaseRequest(gridListFile=gridListFile)) def exportSnapshots(self, type = 'ALL', prefix=''): + """ Export snapshots of a given type + + Arguments: + type (str): Enum string ('ALL', 'VIEWS' or 'PLOTS') + prefix (str): Exported file name prefix + + """ return self.__execute(exportSnapshots=Cmd.ExportSnapshotsRequest(type=type, prefix=prefix)) def exportProperty(self, caseId, timeStep, property, eclipseKeyword=property, undefinedValue=0.0, exportFile=property): + """ Export an Eclipse property + + Arguments: + caseId (int): case id + timeStep (int): time step index + property (str): property to export + eclipseKeyword (str): Eclipse keyword used as text in export header. Defaults to the value of property parameter. + undefinedValue (double): Value to use for undefined values. Defaults to 0.0 + exportFile (str): Filename for export. Defaults to the value of property parameter + """ return self.__execute(exportProperty=Cmd.ExportPropertyRequest(caseId=caseId, timeStep=timeStep, property=property, diff --git a/ApplicationCode/GrpcInterface/Python/rips/Instance.py b/ApplicationCode/GrpcInterface/Python/rips/Instance.py index d8b626c5a2..33a254bc82 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Instance.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Instance.py @@ -17,11 +17,11 @@ class Instance: """The ResInsight Instance class. Use to launch or find existing ResInsight instances Attributes: - launched(bool): Tells us whether the application was launched as a new process. + launched (bool): Tells us whether the application was launched as a new process. If the application was launched we may need to close it when exiting the script. - app(App): Application information object. Set when creating an instance. - commands(Commands): Command executor. Set when creating an instance. - project(Project): Current project in ResInsight. + app (App): Application information object. Set when creating an instance. + commands (Commands): Command executor. Set when creating an instance. + project (Project): Current project in ResInsight. Set when creating an instance and updated when opening/closing projects. """ @@ -83,8 +83,8 @@ class Instance: RESINSIGHT_GRPC_PORT to RESINSIGHT_GRPC_PORT+20 Args: - startPort(int): start searching from this port - endPort(int): search up to but not including this port + startPort (int): start searching from this port + endPort (int): search up to but not including this port """ portEnv = os.environ.get('RESINSIGHT_GRPC_PORT') if portEnv: diff --git a/ApplicationCode/GrpcInterface/Python/rips/Project.py b/ApplicationCode/GrpcInterface/Python/rips/Project.py index 4d3b720fe9..d97aae4504 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Project.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Project.py @@ -23,8 +23,8 @@ class Project: def open(self, path): """Open a new project from the given path - Argument: - path(string): path to project file + Arguments: + path(str): path to project file """ Commands(self.channel).openProject(path) @@ -84,7 +84,7 @@ class Project: """Load a new case from the given file path Arguments: - path(string): file path to case + path(str): file path to case Returns: A rips Case object """ diff --git a/ApplicationCode/GrpcInterface/Python/rips/Properties.py b/ApplicationCode/GrpcInterface/Python/rips/Properties.py index a95b6bdd1f..9bd5a3dc7b 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Properties.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Properties.py @@ -55,18 +55,20 @@ class Properties: def available(self, propertyType, porosityModel = 'MATRIX_MODEL'): """Get a list of available properties - Arguments: - propertyType(string): string corresponding to propertyType enum - Can be one of the following: - 'DYNAMIC_NATIVE' - 'STATIC_NATIVE' - 'SOURSIMRL' - 'GENERATED' - 'INPUT_PROPERTY' - 'FORMATION_NAMES' - 'FLOW_DIAGNOSTICS' - 'INJECTION_FLOODING' - porosityModel(string): 'MATRIX_MODEL' or 'FRACTURE_MODEL'. + Arguments: + propertyType (str): string corresponding to propertyType enum. + + Can be one of the following: + + 'DYNAMIC_NATIVE' + 'STATIC_NATIVE' + 'SOURSIMRL' + 'GENERATED' + 'INPUT_PROPERTY' + 'FORMATION_NAMES' + 'FLOW_DIAGNOSTICS' + 'INJECTION_FLOODING' + porosityModel(str): 'MATRIX_MODEL' or 'FRACTURE_MODEL'. """ propertyTypeEnum = Properties_pb2.PropertyType.Value(propertyType) @@ -80,10 +82,10 @@ class Properties: """Get a cell property for all active cells. Async, so returns an iterator Arguments: - propertyType(string): string enum. See available() - propertyName(string): name of an Eclipse property + propertyType(str): string enum. See available() + propertyName(str): name of an Eclipse property timeStep(int): the time step for which to get the property for - porosityModel(string): string enum. See available() + porosityModel(str): string enum. See available() Returns: An iterator to a chunk object containing an array of double values @@ -103,11 +105,11 @@ class Properties: """Get a cell property for all grid cells. Async, so returns an iterator Arguments: - propertyType(string): string enum. See available() - propertyName(string): name of an Eclipse property + propertyType(str): string enum. See available() + propertyName(str): name of an Eclipse property timeStep(int): the time step for which to get the property for gridIndex(int): index to the grid we're getting values for - porosityModel(string): string enum. See available() + porosityModel(str): string enum. See available() Returns: An iterator to a chunk object containing an array of double values @@ -129,10 +131,10 @@ class Properties: Arguments: values_iterator(iterator): an iterator to the properties to be set - propertyType(string): string enum. See available() - propertyName(string): name of an Eclipse property + propertyType(str): string enum. See available() + propertyName(str): name of an Eclipse property timeStep(int): the time step for which to get the property for - porosityModel(string): string enum. See available() + porosityModel(str): string enum. See available() """ propertyTypeEnum = Properties_pb2.PropertyType.Value(propertyType) porosityModelEnum = Case_pb2.PorosityModelType.Value(porosityModel) @@ -155,10 +157,10 @@ class Properties: Arguments: values(list): a list of double precision floating point numbers - propertyType(string): string enum. See available() - propertyName(string): name of an Eclipse property + propertyType(str): string enum. See available() + propertyName(str): name of an Eclipse property timeStep(int): the time step for which to get the property for - porosityModel(string): string enum. See available() + porosityModel(str): string enum. See available() """ propertyTypeEnum = Properties_pb2.PropertyType.Value(propertyType) porosityModelEnum = Case_pb2.PorosityModelType.Value(porosityModel) @@ -181,11 +183,11 @@ class Properties: Arguments: values(list): a list of double precision floating point numbers - propertyType(string): string enum. See available() - propertyName(string): name of an Eclipse property + propertyType(str): string enum. See available() + propertyName(str): name of an Eclipse property timeStep(int): the time step for which to get the property for gridIndex(int): index to the grid we're setting values for - porosityModel(string): string enum. See available() + porosityModel(str): string enum. See available() """ propertyTypeEnum = Properties_pb2.PropertyType.Value(propertyType) porosityModelEnum = Case_pb2.PorosityModelType.Value(porosityModel) diff --git a/ApplicationCode/GrpcInterface/Python/rips/__init__.py b/ApplicationCode/GrpcInterface/Python/rips/__init__.py index 6d6e54d164..1522a01bcc 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/__init__.py +++ b/ApplicationCode/GrpcInterface/Python/rips/__init__.py @@ -3,3 +3,6 @@ from .Case import Case from .Grid import Grid from .Properties import Properties from .Instance import Instance +from .App import App +from .Commands import Commands +from .Project import Project \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/AppInfo.py b/ApplicationCode/GrpcInterface/Python/rips/examples/AppInfo.py new file mode 100644 index 0000000000..d8d71d340e --- /dev/null +++ b/ApplicationCode/GrpcInterface/Python/rips/examples/AppInfo.py @@ -0,0 +1,10 @@ +import sys +import os + +sys.path.insert(1, os.path.join(sys.path[0], '../../')) +import rips + +resInsight = rips.Instance.find() +if resInsight is not None: + print(resInsight.app.versionString()) + print("Is this a console run?", resInsight.app.isConsole()) diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/InputPropTestAsync.py b/ApplicationCode/GrpcInterface/Python/rips/examples/InputPropTestAsync.py index 237164e78d..b4bfdc133c 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/examples/InputPropTestAsync.py +++ b/ApplicationCode/GrpcInterface/Python/rips/examples/InputPropTestAsync.py @@ -1,6 +1,7 @@ import sys import os sys.path.insert(1, os.path.join(sys.path[0], '../../')) + import rips import time @@ -11,7 +12,6 @@ def createResult(poroChunks, permxChunks): resultChunk.append(poro * permx) yield resultChunk - resInsight = rips.Instance.find() start = time.time() case = resInsight.project.case(id=0) @@ -19,7 +19,8 @@ case = resInsight.project.case(id=0) poroChunks = case.properties.activeCellProperty('STATIC_NATIVE', 'PORO', 0) permxChunks = case.properties.activeCellProperty('STATIC_NATIVE', 'PERMX', 0) -case.properties.setActiveCellPropertyAsync(createResult(poroChunks, permxChunks), 'GENERATED', 'POROPERMXAS', 0) +case.properties.setActiveCellPropertyAsync(createResult(poroChunks, permxChunks), + 'GENERATED', 'POROPERMXAS', 0) end = time.time() print("Time elapsed: ", end - start) diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/InputPropTestSync.py b/ApplicationCode/GrpcInterface/Python/rips/examples/InputPropTestSync.py index 4618fa5556..62b09804a2 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/examples/InputPropTestSync.py +++ b/ApplicationCode/GrpcInterface/Python/rips/examples/InputPropTestSync.py @@ -1,6 +1,7 @@ import sys import os sys.path.insert(1, os.path.join(sys.path[0], '../../')) + import rips import time diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/InstanceExample.py b/ApplicationCode/GrpcInterface/Python/rips/examples/InstanceExample.py new file mode 100644 index 0000000000..2b08f90d6c --- /dev/null +++ b/ApplicationCode/GrpcInterface/Python/rips/examples/InstanceExample.py @@ -0,0 +1,10 @@ +import sys +import os + +sys.path.insert(1, os.path.join(sys.path[0], '../../')) +import rips + +resInsight = rips.Instance.find() + +if resInsight is None: + print('ERROR: could not find ResInsight') \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/Python/setup.py.cmake b/ApplicationCode/GrpcInterface/Python/setup.py.cmake index 17dbffd5fc..a91a6f682c 100644 --- a/ApplicationCode/GrpcInterface/Python/setup.py.cmake +++ b/ApplicationCode/GrpcInterface/Python/setup.py.cmake @@ -6,7 +6,7 @@ with open('README.md') as f: with open('LICENSE') as f: license = f.read() -RIPS_DIST_VERSION = '8' +RIPS_DIST_VERSION = '9' setup( name='rips', From f59a13cd1801d587c1ba252bc00757f16b028b78 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Fri, 14 Jun 2019 16:07:56 +0200 Subject: [PATCH 176/396] Python: add system for generating markdown docs --- .../Python/doc/README_DOCUMENTATION.txt | 4 + .../GrpcInterface/Python/doc/make.bat | 35 ++++++ .../Python/doc/source/PythonRips.rst | 2 + .../GrpcInterface/Python/doc/source/conf.py | 67 +++++++++++ .../Python/doc/source/header.rst | 20 ++++ .../GrpcInterface/Python/doc/source/rips.rst | 105 ++++++++++++++++++ 6 files changed, 233 insertions(+) create mode 100644 ApplicationCode/GrpcInterface/Python/doc/README_DOCUMENTATION.txt create mode 100644 ApplicationCode/GrpcInterface/Python/doc/make.bat create mode 100644 ApplicationCode/GrpcInterface/Python/doc/source/PythonRips.rst create mode 100644 ApplicationCode/GrpcInterface/Python/doc/source/conf.py create mode 100644 ApplicationCode/GrpcInterface/Python/doc/source/header.rst create mode 100644 ApplicationCode/GrpcInterface/Python/doc/source/rips.rst diff --git a/ApplicationCode/GrpcInterface/Python/doc/README_DOCUMENTATION.txt b/ApplicationCode/GrpcInterface/Python/doc/README_DOCUMENTATION.txt new file mode 100644 index 0000000000..51fff95b6b --- /dev/null +++ b/ApplicationCode/GrpcInterface/Python/doc/README_DOCUMENTATION.txt @@ -0,0 +1,4 @@ +You need sphinx (pip install sphinx) to update the documentation. + +To update run "make html" to update to reflect changes to the python code. + diff --git a/ApplicationCode/GrpcInterface/Python/doc/make.bat b/ApplicationCode/GrpcInterface/Python/doc/make.bat new file mode 100644 index 0000000000..9534b01813 --- /dev/null +++ b/ApplicationCode/GrpcInterface/Python/doc/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=source +set BUILDDIR=build + +if "%1" == "" goto help + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/ApplicationCode/GrpcInterface/Python/doc/source/PythonRips.rst b/ApplicationCode/GrpcInterface/Python/doc/source/PythonRips.rst new file mode 100644 index 0000000000..2b480dc465 --- /dev/null +++ b/ApplicationCode/GrpcInterface/Python/doc/source/PythonRips.rst @@ -0,0 +1,2 @@ +.. include:: header.rst +.. include:: rips.rst \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/Python/doc/source/conf.py b/ApplicationCode/GrpcInterface/Python/doc/source/conf.py new file mode 100644 index 0000000000..847e7561d0 --- /dev/null +++ b/ApplicationCode/GrpcInterface/Python/doc/source/conf.py @@ -0,0 +1,67 @@ +# Configuration file for the Sphinx documentation builder. +# +# This file only contains a selection of the most common options. For a full +# list see the documentation: +# http://www.sphinx-doc.org/en/master/config + +# -- Path setup -------------------------------------------------------------- + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +import os +import sys +sys.path.insert(0, os.path.abspath('../../')) + + +# -- Project information ----------------------------------------------------- + +project = 'rips' +copyright = '2019, Ceetron Solutions AS' +author = 'Ceetron Solutions AS' + +# The full version, including alpha/beta/rc tags +release = '2019.04.01' + + +# -- General configuration --------------------------------------------------- + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'sphinx.ext.autodoc', + 'sphinx.ext.napoleon', + 'sphinx_markdown_builder' +] + +master_doc = 'PythonRips' + +napoleon_google_docstring = True + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path. +exclude_patterns = ['build/*', 'rips.rst'] + + +# -- Options for HTML output ------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = 'alabaster' + +smartquotes=False + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + + +# -- Extension configuration ------------------------------------------------- diff --git a/ApplicationCode/GrpcInterface/Python/doc/source/header.rst b/ApplicationCode/GrpcInterface/Python/doc/source/header.rst new file mode 100644 index 0000000000..e2c497489b --- /dev/null +++ b/ApplicationCode/GrpcInterface/Python/doc/source/header.rst @@ -0,0 +1,20 @@ +--- +layout: docs +title: rips - gRPC Python API +permalink: /docs/python/ +published: true +--- + +ResInsight has a `gRPC Remote Procedure Call `_ interface with a Python Client interface. This interface allows you to interact with a running ResInsight instance from a Python script. + +The Python client package is available for install via the Python PIP package system with ``pip install rips`` as admin user, or ``pip install --user rips`` as a regular user. + +On some systems the ``pip`` command may have to be replaced by ``python -m pip``. + +In order for gRPC to be available, ResInsight needs to be built with the ``RESINSIGHT_ENABLE_GRPC`` option set. A valid gRPC build will show a message in the About dialog confirming gRPC is available: + +.. image:: ../images/AboutGrpc.png + +Furthermore, gRPC needs to be enabled in the Scripting tab of the Preference dialog: + +.. image:: ../images/PrefGrpc.png diff --git a/ApplicationCode/GrpcInterface/Python/doc/source/rips.rst b/ApplicationCode/GrpcInterface/Python/doc/source/rips.rst new file mode 100644 index 0000000000..c03c530f93 --- /dev/null +++ b/ApplicationCode/GrpcInterface/Python/doc/source/rips.rst @@ -0,0 +1,105 @@ +Instance Module +================ + +.. autoclass:: rips.Instance + :members: + +Example +-------- + +.. literalinclude:: ../../rips/examples/InstanceExample.py + :language: python + :lines: 5- + :emphasize-lines: 3 + +App Module +=========== + +.. autoclass:: rips.App + :members: + +Example +-------- + +.. literalinclude:: ../../rips/examples/AppInfo.py + :language: python + :lines: 5- + :emphasize-lines: 5 + +Case Module +============ +.. autoclass:: rips.Case + :members: + +Example +------- + +.. literalinclude:: ../../rips/examples/AllCases.py + :language: python + :lines: 5- + :emphasize-lines: 5 + +Commands Module +=============== + +.. autoclass:: rips.Commands + :members: + :undoc-members: + +Example +-------- +.. literalinclude:: ../../rips/examples/CommandExample.py + :language: python + :lines: 5- + +Grid Module +=========== + +.. autoclass:: rips.Grid + :members: + +Example +------- +.. code-block:: python + + case = rips_instance.project.loadCase(path=casePath) + print (case.gridCount()) + if case.gridCount() > 0: + grid = case.grid(index=0) + dimensions = grid.dimensions() + print(dimensions.i) + print(dimensions.j) + print(dimensions.k) + +Project Module +============== + +.. autoclass:: rips.Project + :members: + +Properties Module +================= + +.. autoclass:: rips.Properties + :members: + +Synchronous Example +-------------------- +Read two properties, multiply them together and push the results back to ResInsight in a naïve way, by reading PORO into a list, then reading PERMX into a list, then multiplying them both in a resulting list and finally transferring back the list. + +This is slow and inefficient, but works. + +.. literalinclude:: ../../rips/examples/InputPropTestSync.py + :language: python + :lines: 5- + +Asynchronous Example +-------------------- +Read two properties at the same time chunk by chunk, multiply each chunk together and start transferring the result back to ResInsight as soon as the chunk is finished. + +This is far more efficient. + +.. literalinclude:: ../../rips/examples/InputPropTestAsync.py + :language: python + :lines: 5- + From 41235a2f005dfcc7c8fba54a805264febe362e01 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 17 Jun 2019 09:02:26 +0200 Subject: [PATCH 177/396] #4490 Command Features : Add support for setting application state to be used in features --- .../Application/CMakeLists_files.cmake | 2 + .../Application/RiaFeatureCommandContext.cpp | 70 +++++++++++++++++++ .../Application/RiaFeatureCommandContext.h | 54 ++++++++++++++ .../WellPathImportSsihubTestApp/TestTools.h | 28 -------- 4 files changed, 126 insertions(+), 28 deletions(-) create mode 100644 ApplicationCode/Application/RiaFeatureCommandContext.cpp create mode 100644 ApplicationCode/Application/RiaFeatureCommandContext.h delete mode 100644 ApplicationCode/WellPathImportSsihubTestApp/TestTools.h diff --git a/ApplicationCode/Application/CMakeLists_files.cmake b/ApplicationCode/Application/CMakeLists_files.cmake index c575b75c48..dd3a8ddcbc 100644 --- a/ApplicationCode/Application/CMakeLists_files.cmake +++ b/ApplicationCode/Application/CMakeLists_files.cmake @@ -15,6 +15,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RiaViewRedrawScheduler.h ${CMAKE_CURRENT_LIST_DIR}/RiaMemoryCleanup.h ${CMAKE_CURRENT_LIST_DIR}/RiaFontCache.h ${CMAKE_CURRENT_LIST_DIR}/RiaEclipseFileNameTools.h +${CMAKE_CURRENT_LIST_DIR}/RiaFeatureCommandContext.h ) set (SOURCE_GROUP_SOURCE_FILES @@ -34,6 +35,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RiaViewRedrawScheduler.cpp ${CMAKE_CURRENT_LIST_DIR}/RiaMemoryCleanup.cpp ${CMAKE_CURRENT_LIST_DIR}/RiaFontCache.cpp ${CMAKE_CURRENT_LIST_DIR}/RiaEclipseFileNameTools.cpp +${CMAKE_CURRENT_LIST_DIR}/RiaFeatureCommandContext.cpp ) list(APPEND CODE_HEADER_FILES diff --git a/ApplicationCode/Application/RiaFeatureCommandContext.cpp b/ApplicationCode/Application/RiaFeatureCommandContext.cpp new file mode 100644 index 0000000000..d671195dca --- /dev/null +++ b/ApplicationCode/Application/RiaFeatureCommandContext.cpp @@ -0,0 +1,70 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 "RiaFeatureCommandContext.h" + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiaFeatureCommandContext::RiaFeatureCommandContext() {} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiaFeatureCommandContext::~RiaFeatureCommandContext() {} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaFeatureCommandContext::setObject(QObject* object) +{ + m_pointerToQObject = object; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QObject* RiaFeatureCommandContext::object() const +{ + return m_pointerToQObject; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiaFeatureCommandContext* RiaFeatureCommandContext::instance() +{ + static RiaFeatureCommandContext* commandFileExecutorInstance = new RiaFeatureCommandContext(); + return commandFileExecutorInstance; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiaFeatureCommandContextHelper::RiaFeatureCommandContextHelper(QObject* object) +{ + RiaFeatureCommandContext::instance()->setObject(object); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiaFeatureCommandContextHelper::~RiaFeatureCommandContextHelper() +{ + RiaFeatureCommandContext::instance()->setObject(nullptr); +} diff --git a/ApplicationCode/Application/RiaFeatureCommandContext.h b/ApplicationCode/Application/RiaFeatureCommandContext.h new file mode 100644 index 0000000000..9ac89ddb4d --- /dev/null +++ b/ApplicationCode/Application/RiaFeatureCommandContext.h @@ -0,0 +1,54 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +class RiaFeatureCommandContext +{ + friend class RiaFeatureCommandContextHelper; + +public: + QObject* object() const; + + static RiaFeatureCommandContext* instance(); + +private: + RiaFeatureCommandContext(); + ~RiaFeatureCommandContext(); + + void setObject(QObject* object); + +private: + QPointer m_pointerToQObject; +}; + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +class RiaFeatureCommandContextHelper +{ +public: + RiaFeatureCommandContextHelper(QObject* object); + ~RiaFeatureCommandContextHelper(); +}; diff --git a/ApplicationCode/WellPathImportSsihubTestApp/TestTools.h b/ApplicationCode/WellPathImportSsihubTestApp/TestTools.h deleted file mode 100644 index 805d012b43..0000000000 --- a/ApplicationCode/WellPathImportSsihubTestApp/TestTools.h +++ /dev/null @@ -1,28 +0,0 @@ -///////////////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS -// -// 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 - -class RimWellPathImport; - -class TestTools -{ -public: - static RimWellPathImport* createMockObject(); -}; - From bdcc7c53f7194d0c984d9df9d4bfdee377fa77e8 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 17 Jun 2019 09:03:22 +0200 Subject: [PATCH 178/396] #4490 Command Features : Use app state for toggle features --- .../RicToggleItemsFeatureImpl.cpp | 55 +++++++++++++++---- .../RicToggleItemsFeatureImpl.h | 2 + 2 files changed, 46 insertions(+), 11 deletions(-) diff --git a/ApplicationCode/Commands/ToggleCommands/RicToggleItemsFeatureImpl.cpp b/ApplicationCode/Commands/ToggleCommands/RicToggleItemsFeatureImpl.cpp index f6fe0062b9..b378f2a7cb 100644 --- a/ApplicationCode/Commands/ToggleCommands/RicToggleItemsFeatureImpl.cpp +++ b/ApplicationCode/Commands/ToggleCommands/RicToggleItemsFeatureImpl.cpp @@ -19,9 +19,10 @@ #include "RicToggleItemsFeatureImpl.h" +#include "RiaFeatureCommandContext.h" +#include "RiaGuiApplication.h" #include "RiuMainWindow.h" #include "RiuPlotMainWindow.h" -#include "RiaGuiApplication.h" #include "cafPdmUiFieldHandle.h" #include "cafPdmUiItem.h" @@ -153,22 +154,54 @@ void RicToggleItemsFeatureImpl::setObjectToggleStateForSelection(SelectionToggle } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +caf::PdmUiTreeView* RicToggleItemsFeatureImpl::findTreeView(const caf::PdmUiItem* uiItem) +{ + { + RiaFeatureCommandContext* context = RiaFeatureCommandContext::instance(); + + caf::PdmUiTreeView* customActiveTreeView = dynamic_cast(context->object()); + if (customActiveTreeView) + { + return customActiveTreeView; + } + } + + { + QModelIndex modIndex = RiuMainWindow::instance()->projectTreeView()->findModelIndex(uiItem); + if (modIndex.isValid()) + { + return RiuMainWindow::instance()->projectTreeView(); + } + } + + RiuPlotMainWindow* mainPlotWindow = RiaGuiApplication::instance()->mainPlotWindow(); + if (mainPlotWindow) + { + QModelIndex modIndex = mainPlotWindow->projectTreeView()->findModelIndex(uiItem); + if (modIndex.isValid()) + { + return mainPlotWindow->projectTreeView(); + } + } + + return nullptr; +} + //-------------------------------------------------------------------------------------------------- /// Finds the tree item in either the 3D main window or plot main window project tree view //-------------------------------------------------------------------------------------------------- caf::PdmUiTreeOrdering* RicToggleItemsFeatureImpl::findTreeItemFromSelectedUiItem(const caf::PdmUiItem* uiItem) { - QModelIndex modIndex = RiuMainWindow::instance()->projectTreeView()->findModelIndex(uiItem); - if(!modIndex.isValid()) + caf::PdmUiTreeView* pdmUiTreeView = findTreeView(uiItem); + + if (pdmUiTreeView) { - RiuPlotMainWindow* mainPlotWindow = RiaGuiApplication::instance()->mainPlotWindow(); - if(mainPlotWindow) - { - modIndex = mainPlotWindow->projectTreeView()->findModelIndex(uiItem); - } + QModelIndex modIndex = pdmUiTreeView->findModelIndex(uiItem); + return static_cast(modIndex.internalPointer()); } - caf::PdmUiTreeOrdering* treeItem = static_cast(modIndex.internalPointer()); - - return treeItem; + return nullptr; } diff --git a/ApplicationCode/Commands/ToggleCommands/RicToggleItemsFeatureImpl.h b/ApplicationCode/Commands/ToggleCommands/RicToggleItemsFeatureImpl.h index 9190368529..0f99b47b8a 100644 --- a/ApplicationCode/Commands/ToggleCommands/RicToggleItemsFeatureImpl.h +++ b/ApplicationCode/Commands/ToggleCommands/RicToggleItemsFeatureImpl.h @@ -23,6 +23,7 @@ namespace caf { class PdmUiItem; class PdmUiTreeOrdering; + class PdmUiTreeView; }; //================================================================================================== @@ -45,6 +46,7 @@ public: static void setObjectToggleStateForSelection(SelectionToggleType state); private: + static caf::PdmUiTreeView* findTreeView(const caf::PdmUiItem* uiItem); static caf::PdmUiTreeOrdering* findTreeItemFromSelectedUiItem(const caf::PdmUiItem* uiItem); }; From 03c1311d5880d9a1a53593ba109900aaa4a469cd Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 17 Jun 2019 09:11:38 +0200 Subject: [PATCH 179/396] #692 SSIhub: add Sub Items On/Off/Toggle to well list --- ApplicationCode/CMakeLists.txt | 4 +- .../CMakeLists_files.cmake | 32 ++++++ .../RicWellPathsImportSsihubFeature.cpp | 0 .../RicWellPathsImportSsihubFeature.h | 0 .../RimOilFieldEntry.cpp | 4 +- .../SsiHubImportCommands}/RimOilFieldEntry.h | 0 .../RimOilRegionEntry.cpp | 0 .../SsiHubImportCommands}/RimOilRegionEntry.h | 0 .../RimWellPathImport.cpp | 2 +- .../SsiHubImportCommands}/RimWellPathImport.h | 0 .../SsiHubImportCommands}/RimWellsEntry.cpp | 0 .../SsiHubImportCommands}/RimWellsEntry.h | 0 .../RiuWellImportWizard.cpp | 48 ++++++++ .../RiuWellImportWizard.h | 30 ++++- .../WellPathCommands/CMakeLists_files.cmake | 2 - .../ProjectDataModel/RimProject.cpp | 2 +- .../UserInterface/RiuMainWindow.cpp | 6 - .../WellPathImportSsihub/CMakeLists.txt | 49 -------- .../CMakeLists.txt | 106 ------------------ .../WellPathImportSsihubTestApp/TestTools.cpp | 52 --------- .../WellPathImportSsihubTestApp/main.cpp | 82 -------------- 21 files changed, 112 insertions(+), 307 deletions(-) create mode 100644 ApplicationCode/Commands/SsiHubImportCommands/CMakeLists_files.cmake rename ApplicationCode/Commands/{WellPathCommands => SsiHubImportCommands}/RicWellPathsImportSsihubFeature.cpp (100%) rename ApplicationCode/Commands/{WellPathCommands => SsiHubImportCommands}/RicWellPathsImportSsihubFeature.h (100%) rename ApplicationCode/{WellPathImportSsihub => Commands/SsiHubImportCommands}/RimOilFieldEntry.cpp (95%) rename ApplicationCode/{WellPathImportSsihub => Commands/SsiHubImportCommands}/RimOilFieldEntry.h (100%) rename ApplicationCode/{WellPathImportSsihub => Commands/SsiHubImportCommands}/RimOilRegionEntry.cpp (100%) rename ApplicationCode/{WellPathImportSsihub => Commands/SsiHubImportCommands}/RimOilRegionEntry.h (100%) rename ApplicationCode/{WellPathImportSsihub => Commands/SsiHubImportCommands}/RimWellPathImport.cpp (99%) rename ApplicationCode/{WellPathImportSsihub => Commands/SsiHubImportCommands}/RimWellPathImport.h (100%) rename ApplicationCode/{WellPathImportSsihub => Commands/SsiHubImportCommands}/RimWellsEntry.cpp (100%) rename ApplicationCode/{WellPathImportSsihub => Commands/SsiHubImportCommands}/RimWellsEntry.h (100%) rename ApplicationCode/{WellPathImportSsihub => Commands/SsiHubImportCommands}/RiuWellImportWizard.cpp (96%) rename ApplicationCode/{WellPathImportSsihub => Commands/SsiHubImportCommands}/RiuWellImportWizard.h (92%) delete mode 100644 ApplicationCode/WellPathImportSsihub/CMakeLists.txt delete mode 100644 ApplicationCode/WellPathImportSsihubTestApp/CMakeLists.txt delete mode 100644 ApplicationCode/WellPathImportSsihubTestApp/TestTools.cpp delete mode 100644 ApplicationCode/WellPathImportSsihubTestApp/main.cpp diff --git a/ApplicationCode/CMakeLists.txt b/ApplicationCode/CMakeLists.txt index 66d0eb454b..b43668d54b 100644 --- a/ApplicationCode/CMakeLists.txt +++ b/ApplicationCode/CMakeLists.txt @@ -66,7 +66,6 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/ResultStatisticsCache ${CMAKE_CURRENT_SOURCE_DIR}/ReservoirDataModel ${CMAKE_CURRENT_SOURCE_DIR}/ReservoirDataModel/Completions - ${CMAKE_CURRENT_SOURCE_DIR}/WellPathImportSsihub ${CMAKE_CURRENT_SOURCE_DIR}/GeoMech/OdbReader ${CMAKE_CURRENT_SOURCE_DIR}/GeoMech/GeoMechDataModel ${CMAKE_CURRENT_SOURCE_DIR}/GeoMech/GeoMechVisualization @@ -151,6 +150,7 @@ list( APPEND REFERENCED_CMAKE_FILES Commands/OctaveScriptCommands/CMakeLists_files.cmake Commands/OperationsUsingObjReferences/CMakeLists_files.cmake Commands/SummaryPlotCommands/CMakeLists_files.cmake + Commands/SsiHubImportCommands/CMakeLists_files.cmake Commands/ToggleCommands/CMakeLists_files.cmake Commands/ViewLink/CMakeLists_files.cmake Commands/WellLogCommands/CMakeLists_files.cmake @@ -189,11 +189,9 @@ list( APPEND CPP_SOURCES # Sub-directory projects ############################################################################# -add_subdirectory(WellPathImportSsihub) add_subdirectory(ResultStatisticsCache) set( RI_LIBRARIES - WellPathImportSsihub ResultStatisticsCache ) diff --git a/ApplicationCode/Commands/SsiHubImportCommands/CMakeLists_files.cmake b/ApplicationCode/Commands/SsiHubImportCommands/CMakeLists_files.cmake new file mode 100644 index 0000000000..952ed159b6 --- /dev/null +++ b/ApplicationCode/Commands/SsiHubImportCommands/CMakeLists_files.cmake @@ -0,0 +1,32 @@ + +set (SOURCE_GROUP_HEADER_FILES +${CMAKE_CURRENT_LIST_DIR}/RicWellPathsImportSsihubFeature.h +${CMAKE_CURRENT_LIST_DIR}/RimOilFieldEntry.h +${CMAKE_CURRENT_LIST_DIR}/RimOilRegionEntry.h +${CMAKE_CURRENT_LIST_DIR}/RimWellPathImport.h +${CMAKE_CURRENT_LIST_DIR}/RimWellsEntry.h +${CMAKE_CURRENT_LIST_DIR}/RiuWellImportWizard.h +) + +set (SOURCE_GROUP_SOURCE_FILES +${CMAKE_CURRENT_LIST_DIR}/RicWellPathsImportSsihubFeature.cpp +${CMAKE_CURRENT_LIST_DIR}/RimOilFieldEntry.cpp +${CMAKE_CURRENT_LIST_DIR}/RimOilRegionEntry.cpp +${CMAKE_CURRENT_LIST_DIR}/RimWellPathImport.cpp +${CMAKE_CURRENT_LIST_DIR}/RimWellsEntry.cpp +${CMAKE_CURRENT_LIST_DIR}/RiuWellImportWizard.cpp +) + +list(APPEND CODE_HEADER_FILES +${SOURCE_GROUP_HEADER_FILES} +) + +list(APPEND CODE_SOURCE_FILES +${SOURCE_GROUP_SOURCE_FILES} +) + +list(APPEND QT_MOC_HEADERS +${CMAKE_CURRENT_LIST_DIR}/RiuWellImportWizard.h +) + +source_group( "CommandFeature\\SsiHub" FILES ${SOURCE_GROUP_HEADER_FILES} ${SOURCE_GROUP_SOURCE_FILES} ${CMAKE_CURRENT_LIST_DIR}/CMakeLists_files.cmake ) diff --git a/ApplicationCode/Commands/WellPathCommands/RicWellPathsImportSsihubFeature.cpp b/ApplicationCode/Commands/SsiHubImportCommands/RicWellPathsImportSsihubFeature.cpp similarity index 100% rename from ApplicationCode/Commands/WellPathCommands/RicWellPathsImportSsihubFeature.cpp rename to ApplicationCode/Commands/SsiHubImportCommands/RicWellPathsImportSsihubFeature.cpp diff --git a/ApplicationCode/Commands/WellPathCommands/RicWellPathsImportSsihubFeature.h b/ApplicationCode/Commands/SsiHubImportCommands/RicWellPathsImportSsihubFeature.h similarity index 100% rename from ApplicationCode/Commands/WellPathCommands/RicWellPathsImportSsihubFeature.h rename to ApplicationCode/Commands/SsiHubImportCommands/RicWellPathsImportSsihubFeature.h diff --git a/ApplicationCode/WellPathImportSsihub/RimOilFieldEntry.cpp b/ApplicationCode/Commands/SsiHubImportCommands/RimOilFieldEntry.cpp similarity index 95% rename from ApplicationCode/WellPathImportSsihub/RimOilFieldEntry.cpp rename to ApplicationCode/Commands/SsiHubImportCommands/RimOilFieldEntry.cpp index dae33da0c2..e4a37572e6 100644 --- a/ApplicationCode/WellPathImportSsihub/RimOilFieldEntry.cpp +++ b/ApplicationCode/Commands/SsiHubImportCommands/RimOilFieldEntry.cpp @@ -117,12 +117,12 @@ void RimOilFieldEntry::updateEnabledState() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RimWellPathEntry* RimOilFieldEntry::find(const QString& name, RimWellPathEntry::WellTypeEnum wellPathType) +RimWellPathEntry* RimOilFieldEntry::find(const QString& entryName, RimWellPathEntry::WellTypeEnum wellPathType) { for (size_t i = 0; i < wells.size(); i++) { RimWellPathEntry* wellPathEntry = wells[i]; - if (wellPathEntry->name == name && wellPathEntry->wellPathType == wellPathType) + if (wellPathEntry->name == entryName && wellPathEntry->wellPathType == wellPathType) { return wellPathEntry; } diff --git a/ApplicationCode/WellPathImportSsihub/RimOilFieldEntry.h b/ApplicationCode/Commands/SsiHubImportCommands/RimOilFieldEntry.h similarity index 100% rename from ApplicationCode/WellPathImportSsihub/RimOilFieldEntry.h rename to ApplicationCode/Commands/SsiHubImportCommands/RimOilFieldEntry.h diff --git a/ApplicationCode/WellPathImportSsihub/RimOilRegionEntry.cpp b/ApplicationCode/Commands/SsiHubImportCommands/RimOilRegionEntry.cpp similarity index 100% rename from ApplicationCode/WellPathImportSsihub/RimOilRegionEntry.cpp rename to ApplicationCode/Commands/SsiHubImportCommands/RimOilRegionEntry.cpp diff --git a/ApplicationCode/WellPathImportSsihub/RimOilRegionEntry.h b/ApplicationCode/Commands/SsiHubImportCommands/RimOilRegionEntry.h similarity index 100% rename from ApplicationCode/WellPathImportSsihub/RimOilRegionEntry.h rename to ApplicationCode/Commands/SsiHubImportCommands/RimOilRegionEntry.h diff --git a/ApplicationCode/WellPathImportSsihub/RimWellPathImport.cpp b/ApplicationCode/Commands/SsiHubImportCommands/RimWellPathImport.cpp similarity index 99% rename from ApplicationCode/WellPathImportSsihub/RimWellPathImport.cpp rename to ApplicationCode/Commands/SsiHubImportCommands/RimWellPathImport.cpp index 19b00c39ae..10bdb178e0 100644 --- a/ApplicationCode/WellPathImportSsihub/RimWellPathImport.cpp +++ b/ApplicationCode/Commands/SsiHubImportCommands/RimWellPathImport.cpp @@ -146,7 +146,7 @@ void RimWellPathImport::updateRegions(const QStringList& regionStrings, const QS if (!oilFieldEntry) { - RimOilFieldEntry* oilFieldEntry = new RimOilFieldEntry; + oilFieldEntry = new RimOilFieldEntry; oilFieldEntry->name = fieldStrings[i]; oilFieldEntry->edmId = edmIds[i]; diff --git a/ApplicationCode/WellPathImportSsihub/RimWellPathImport.h b/ApplicationCode/Commands/SsiHubImportCommands/RimWellPathImport.h similarity index 100% rename from ApplicationCode/WellPathImportSsihub/RimWellPathImport.h rename to ApplicationCode/Commands/SsiHubImportCommands/RimWellPathImport.h diff --git a/ApplicationCode/WellPathImportSsihub/RimWellsEntry.cpp b/ApplicationCode/Commands/SsiHubImportCommands/RimWellsEntry.cpp similarity index 100% rename from ApplicationCode/WellPathImportSsihub/RimWellsEntry.cpp rename to ApplicationCode/Commands/SsiHubImportCommands/RimWellsEntry.cpp diff --git a/ApplicationCode/WellPathImportSsihub/RimWellsEntry.h b/ApplicationCode/Commands/SsiHubImportCommands/RimWellsEntry.h similarity index 100% rename from ApplicationCode/WellPathImportSsihub/RimWellsEntry.h rename to ApplicationCode/Commands/SsiHubImportCommands/RimWellsEntry.h diff --git a/ApplicationCode/WellPathImportSsihub/RiuWellImportWizard.cpp b/ApplicationCode/Commands/SsiHubImportCommands/RiuWellImportWizard.cpp similarity index 96% rename from ApplicationCode/WellPathImportSsihub/RiuWellImportWizard.cpp rename to ApplicationCode/Commands/SsiHubImportCommands/RiuWellImportWizard.cpp index a7d9093b93..2cae131221 100644 --- a/ApplicationCode/WellPathImportSsihub/RiuWellImportWizard.cpp +++ b/ApplicationCode/Commands/SsiHubImportCommands/RiuWellImportWizard.cpp @@ -18,12 +18,15 @@ #include "RiuWellImportWizard.h" +#include "RiaFeatureCommandContext.h" + #include "RifJsonEncodeDecode.h" #include "RimOilFieldEntry.h" #include "RimOilRegionEntry.h" #include "RimWellPathImport.h" +#include "cafCmdFeatureMenuBuilder.h" #include "cafPdmDocument.h" #include "cafPdmObject.h" #include "cafPdmObjectGroup.h" @@ -36,6 +39,8 @@ #include #include #include +#include + #if QT_VERSION >= 0x050000 #include #else @@ -45,6 +50,8 @@ #include +CAF_PDM_XML_ABSTRACT_SOURCE_INIT(ObjectGroupWithHeaders, "ObjectGroupWithHeaders"); // Do not use. Abstract class + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -859,6 +866,15 @@ WellSelectionPage::WellSelectionPage(RimWellPathImport* wellPathImport, QWidget* layout->addWidget(label); m_wellSelectionTreeView = new caf::PdmUiTreeView(this); + m_wellSelectionTreeView->treeView()->setContextMenuPolicy(Qt::CustomContextMenu); + m_wellSelectionTreeView->enableSelectionManagerUpdating(true); + m_wellSelectionTreeView->treeView()->setSelectionMode(QAbstractItemView::ExtendedSelection); + + connect(m_wellSelectionTreeView->treeView(), + SIGNAL(customContextMenuRequested(const QPoint&)), + SLOT(customMenuRequested(const QPoint&))); + + layout->addWidget(m_wellSelectionTreeView); m_wellPathImportObject = wellPathImport; @@ -1009,6 +1025,38 @@ void WellSelectionPage::selectedWellPathEntries(std::vector& dow } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void WellSelectionPage::customMenuRequested(const QPoint& pos) +{ + QMenu menu; + + RiaFeatureCommandContextHelper helper(m_wellSelectionTreeView); + + caf::CmdFeatureMenuBuilder menuBuilder; + + + menuBuilder << "RicToggleItemsOnFeature"; + menuBuilder << "RicToggleItemsOffFeature"; + menuBuilder << "RicToggleItemsFeature"; + menuBuilder << "RicToggleItemsOnOthersOffFeature"; + + menuBuilder.appendToMenu(&menu); + + + // Qt doc: QAbstractScrollArea and its subclasses that map the context menu event to coordinates of the viewport(). + // Since we might get this signal from different treeViews, we need to map the position accordingly. + QObject* senderObj = this->sender(); + QTreeView* treeView = dynamic_cast(senderObj); + if (treeView) + { + QPoint globalPos = treeView->viewport()->mapToGlobal(pos); + menu.exec(globalPos); + } +} + + //-------------------------------------------------------------------------------------------------- /// diff --git a/ApplicationCode/WellPathImportSsihub/RiuWellImportWizard.h b/ApplicationCode/Commands/SsiHubImportCommands/RiuWellImportWizard.h similarity index 92% rename from ApplicationCode/WellPathImportSsihub/RiuWellImportWizard.h rename to ApplicationCode/Commands/SsiHubImportCommands/RiuWellImportWizard.h index 9981bdf504..12137224c4 100644 --- a/ApplicationCode/WellPathImportSsihub/RiuWellImportWizard.h +++ b/ApplicationCode/Commands/SsiHubImportCommands/RiuWellImportWizard.h @@ -21,7 +21,6 @@ #include "cafPdmChildArrayField.h" #include "cafPdmField.h" #include "cafPdmObject.h" -#include "cafPdmObjectGroup.h" #include #include @@ -85,12 +84,34 @@ private: //-------------------------------------------------------------------------------------------------- /// Container class used to define column headers //-------------------------------------------------------------------------------------------------- -class ObjectGroupWithHeaders : public caf::PdmObjectCollection +class ObjectGroupWithHeaders : public caf::PdmObject { + CAF_PDM_HEADER_INIT; + public: - ObjectGroupWithHeaders() {}; + ObjectGroupWithHeaders() + { + CAF_PDM_InitFieldNoDefault(&objects, "PdmObjects", "", "", "", ""); + + CAF_PDM_InitField(&m_isChecked, "IsChecked", true, "Active", "", "", ""); + m_isChecked.uiCapability()->setUiHidden(true); + }; void defineObjectEditorAttribute(QString uiConfigName, caf::PdmUiEditorAttribute * attribute) override; + +public: + caf::PdmChildArrayField objects; + +protected: + + caf::PdmFieldHandle* objectToggleField() override + { + return &m_isChecked; + } + +protected: + caf::PdmField m_isChecked; + }; //-------------------------------------------------------------------------------------------------- @@ -137,6 +158,9 @@ public: private: void sortObjectsByDescription(caf::PdmObjectCollection* objects); +private slots: + void customMenuRequested(const QPoint& pos); + private: ObjectGroupWithHeaders* m_regionsWithVisibleWells; RimWellPathImport* m_wellPathImportObject; diff --git a/ApplicationCode/Commands/WellPathCommands/CMakeLists_files.cmake b/ApplicationCode/Commands/WellPathCommands/CMakeLists_files.cmake index 316f3f892e..4032ae68a8 100644 --- a/ApplicationCode/Commands/WellPathCommands/CMakeLists_files.cmake +++ b/ApplicationCode/Commands/WellPathCommands/CMakeLists_files.cmake @@ -2,7 +2,6 @@ set (SOURCE_GROUP_HEADER_FILES ${CMAKE_CURRENT_LIST_DIR}/RicWellPathDeleteFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicWellPathsImportFileFeature.h -${CMAKE_CURRENT_LIST_DIR}/RicWellPathsImportSsihubFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicNewEditableWellPathFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicShowWellPlanFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicNewWellPathListTargetFeature.h @@ -29,7 +28,6 @@ ${CMAKE_CURRENT_LIST_DIR}/PointTangentManipulator/RicPolylineTarget3dEditor.h set (SOURCE_GROUP_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/RicWellPathDeleteFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicWellPathsImportFileFeature.cpp -${CMAKE_CURRENT_LIST_DIR}/RicWellPathsImportSsihubFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicNewEditableWellPathFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicShowWellPlanFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicNewWellPathListTargetFeature.cpp diff --git a/ApplicationCode/ProjectDataModel/RimProject.cpp b/ApplicationCode/ProjectDataModel/RimProject.cpp index 1696eb0d56..ee92d123a2 100644 --- a/ApplicationCode/ProjectDataModel/RimProject.cpp +++ b/ApplicationCode/ProjectDataModel/RimProject.cpp @@ -76,7 +76,7 @@ #include "RimWellLogPlotCollection.h" #include "RimWellPath.h" #include "RimWellPathCollection.h" -#include "RimWellPathImport.h" +#include "SsiHubImportCommands/RimWellPathImport.h" #include "RiuPlotMainWindow.h" #include "RiuMainWindow.h" diff --git a/ApplicationCode/UserInterface/RiuMainWindow.cpp b/ApplicationCode/UserInterface/RiuMainWindow.cpp index dc2ba5afcb..b397ab9004 100644 --- a/ApplicationCode/UserInterface/RiuMainWindow.cpp +++ b/ApplicationCode/UserInterface/RiuMainWindow.cpp @@ -843,14 +843,9 @@ void RiuMainWindow::refreshViewActions() //-------------------------------------------------------------------------------------------------- void RiuMainWindow::slotRefreshFileActions() { - RiaApplication* app = RiaApplication::instance(); - - bool projectFileExists = caf::Utils::fileExists(app->project()->fileName()); - caf::CmdFeatureManager* cmdFeatureMgr = caf::CmdFeatureManager::instance(); CVF_ASSERT(cmdFeatureMgr); - cmdFeatureMgr->action("RicWellPathsImportSsihubFeature")->setEnabled(projectFileExists); QStringList commandIdList; commandIdList << "RicExportEclipseInputGridFeature"; commandIdList << "RicSaveEclipseInputVisibleCellsFeature"; @@ -858,7 +853,6 @@ void RiuMainWindow::slotRefreshFileActions() commandIdList << "RicExportCompletionsForVisibleWellPathsFeature"; commandIdList << "RicExportVisibleWellPathsFeature"; cmdFeatureMgr->refreshStates(commandIdList); - } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/WellPathImportSsihub/CMakeLists.txt b/ApplicationCode/WellPathImportSsihub/CMakeLists.txt deleted file mode 100644 index 1af067baf2..0000000000 --- a/ApplicationCode/WellPathImportSsihub/CMakeLists.txt +++ /dev/null @@ -1,49 +0,0 @@ -cmake_minimum_required (VERSION 2.8.12) - -project (WellPathImportSsihub) - -# These headers need to go through Qt's MOC compiler -set( MOC_HEADER_FILES - RiuWellImportWizard.h -) - -if (RESINSIGHT_BUILD_WITH_QT5) - find_package(Qt5 COMPONENTS REQUIRED Core Network) - set(QT_LIBRARIES Qt5::Core Qt5::Network) - qt5_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES}) -else() - find_package(Qt4 COMPONENTS QtCore QtNetwork REQUIRED) - include(${QT_USE_FILE}) - qt4_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES}) -endif(RESINSIGHT_BUILD_WITH_QT5) - -include_directories( - ${CMAKE_CURRENT_BINARY_DIR} - - ${CMAKE_CURRENT_SOURCE_DIR}/../FileInterface -) - -add_library( ${PROJECT_NAME} - RimWellPathImport.h - RimWellPathImport.cpp - RimOilRegionEntry.h - RimOilRegionEntry.cpp - RimOilFieldEntry.h - RimOilFieldEntry.cpp - RimWellsEntry.h - RimWellsEntry.cpp - RiuWellImportWizard.h - RiuWellImportWizard.cpp - - ${CMAKE_CURRENT_SOURCE_DIR}/../FileInterface/RifJsonEncodeDecode.cpp - - ${MOC_SOURCE_FILES} - ${FORM_FILES_CPP} - ${HEADER_FILES} -) - -target_link_libraries ( ${PROJECT_NAME} - cafUserInterface cafPdmCvf CommonCode ${QT_LIBRARIES} -) - -source_group("" FILES ${PROJECT_FILES}) diff --git a/ApplicationCode/WellPathImportSsihubTestApp/CMakeLists.txt b/ApplicationCode/WellPathImportSsihubTestApp/CMakeLists.txt deleted file mode 100644 index e7727c021e..0000000000 --- a/ApplicationCode/WellPathImportSsihubTestApp/CMakeLists.txt +++ /dev/null @@ -1,106 +0,0 @@ -cmake_minimum_required (VERSION 2.8) - -project ( WellPathImportSsihubTestApp ) - - -find_package(Qt5 CONFIG COMPONENTS Core) -if (Qt5Core_FOUND) - message(STATUS "Found Qt5") - find_package(Qt5 CONFIG REQUIRED Core Gui OpenGl Network Script ScriptTools Widgets) -else() - set (QT_COMPONENTS_REQUIRED QtCore QtGui QtMain QtOpenGl QtNetwork QtScript QtScriptTools) - find_package(Qt4 COMPONENTS ${QT_COMPONENTS_REQUIRED} REQUIRED) - include(${QT_USE_FILE}) - if (QT4_FOUND) - message(STATUS "Found Qt4") - endif(QT4_FOUND) -endif(Qt5Core_FOUND) - - -# Open GL -find_package( OpenGL ) - - - -add_subdirectory(../WellPathImportSsihub "${CMAKE_CURRENT_BINARY_DIR}/WellPathImportSsihub") -add_subdirectory(../../Fwk/AppFwk/cafProjectDataModel "${CMAKE_CURRENT_BINARY_DIR}/cafProjectDataModel") -add_subdirectory(../../Fwk/AppFwk/cafUserInterface "${CMAKE_CURRENT_BINARY_DIR}/cafUserInterface") - -#add_subdirectory(../../cafTests/cafTestApplication "${CMAKE_CURRENT_BINARY_DIR}/cafTestApplication") - -include_directories( - ${WellPathImportSsihub_SOURCE_DIR} - ${WellPathImportSsihub_SOURCE_DIR}/../../Fwk/AppFwk/cafProjectDataModel - ${WellPathImportSsihub_SOURCE_DIR}/../../Fwk/AppFwk/cafUserInterface -) - - -# Qt MOC -set ( QT_MOC_HEADERS -) - -if (Qt5Core_FOUND) - qt5_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) -else() - qt4_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) -endif() - -# Resource file -set( QRC_FILES -) - -# Runs RCC on specified files -if (Qt5Core_FOUND) - qt5_add_resources( QRC_FILES_CPP - ${QRC_FILES} - ) -else() - qt4_add_resources( QRC_FILES_CPP - ${QRC_FILES} - ) -endif() - - -# add the executable -add_executable ( ${PROJECT_NAME} - main.cpp - TestTools.cpp - TestTools.h - ${MOC_SOURCE_FILES} - ${QRC_FILES_CPP} -) - -if (Qt5Core_FOUND) - set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::OpenGl Qt5::Network Qt5::Script Qt5::ScriptTools Qt5::Widgets) -endif() - -target_link_libraries ( ${PROJECT_NAME} - - cafProjectDataModel - cafUserInterface - - WellPathImportSsihub - ${QT_LIBRARIES} -) - -# Copy Qt Dlls -if (Qt5Core_FOUND) - foreach (qtlib ${QT_LIBRARIES}) - add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_if_different $ $ - ) - endforeach(qtlib) - # Copy Qt Dlls -else() - # Copy Qt Dlls - if (MSVC) - foreach (qtlib ${QT_COMPONENTS_REQUIRED}) - - # Debug - execute_process(COMMAND cmake -E copy_if_different ${QT_BINARY_DIR}/${qtlib}d4.dll ${CMAKE_BINARY_DIR}/Debug/${qtlib}d4.dll) - - # Release - execute_process(COMMAND cmake -E copy_if_different ${QT_BINARY_DIR}/${qtlib}4.dll ${CMAKE_BINARY_DIR}/Release/${qtlib}4.dll) - endforeach( qtlib ) - endif(MSVC) -endif(Qt5Core_FOUND) diff --git a/ApplicationCode/WellPathImportSsihubTestApp/TestTools.cpp b/ApplicationCode/WellPathImportSsihubTestApp/TestTools.cpp deleted file mode 100644 index 299538ac2f..0000000000 --- a/ApplicationCode/WellPathImportSsihubTestApp/TestTools.cpp +++ /dev/null @@ -1,52 +0,0 @@ -///////////////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS -// -// 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 "TestTools.h" -#include "RimWellPathImport.h" - - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -RimWellPathImport* TestTools::createMockObject() -{ - RimWellPathImport* wellPathImport = new RimWellPathImport; - - RimOilRegionEntry* regionA = new RimOilRegionEntry; - regionA->name = "Region A"; - - RimOilFieldEntry* fieldA = new RimOilFieldEntry; - fieldA->name = "test a"; - fieldA->edmId = "edm1"; - - RimOilFieldEntry* fieldB = new RimOilFieldEntry; - fieldB->name = "test b"; - fieldB->edmId = "edm b"; - - regionA->fields.push_back(fieldA); - - wellPathImport->regions.push_back(regionA); - - RimOilRegionEntry* regionB = new RimOilRegionEntry; - regionB->name = "Region B"; - - wellPathImport->regions.push_back(regionB); - - wellPathImport->utmFilterMode = RimWellPathImport::UTM_FILTER_PROJECT; - return wellPathImport; -} diff --git a/ApplicationCode/WellPathImportSsihubTestApp/main.cpp b/ApplicationCode/WellPathImportSsihubTestApp/main.cpp deleted file mode 100644 index ee34c11206..0000000000 --- a/ApplicationCode/WellPathImportSsihubTestApp/main.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor -** the names of its contributors may be used to endorse or promote -** products derived from this software without specific prior written -** permission. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include -#include - -#include "TestTools.h" -#include "RiuWellImportWizard.h" -#include "RimWellPathImport.h" - - - - - -int main(int argc, char *argv[]) -{ - QApplication app(argc, argv); - - - QString destinationFolder("c:/tmp/resinsight_ws"); - QString wsAddress("http://127.0.0.1:5000"); - - - int north = 7500000; - int south = 7000000; - int east = 401000; - int west = 400000; - - RimWellPathImport* wellPathImportObject = TestTools::createMockObject(); - wellPathImportObject->north = north; - wellPathImportObject->south = south; - wellPathImportObject->east = east; - wellPathImportObject->west = west; - - QString username("admin"); - QString password("resinsight"); - - - RiuWellImportWizard wizard(wsAddress, destinationFolder, wellPathImportObject); - wizard.setCredentials(username, password); - wizard.show(); - - - return app.exec(); -} From b17749ccbd5949eebefba13c73bc39e983b70c9d Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 17 Jun 2019 10:21:23 +0200 Subject: [PATCH 180/396] #692 SSIhub: Set wells default toggled on --- .../Commands/SsiHubImportCommands/RiuWellImportWizard.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/ApplicationCode/Commands/SsiHubImportCommands/RiuWellImportWizard.cpp b/ApplicationCode/Commands/SsiHubImportCommands/RiuWellImportWizard.cpp index 2cae131221..fac0abd4d4 100644 --- a/ApplicationCode/Commands/SsiHubImportCommands/RiuWellImportWizard.cpp +++ b/ApplicationCode/Commands/SsiHubImportCommands/RiuWellImportWizard.cpp @@ -955,6 +955,7 @@ void WellSelectionPage::buildWellTreeView() RimWellPathEntry* wellPathCopy = new RimWellPathEntry; wellPathCopy->readObjectFromXmlString(objStr, caf::PdmDefaultObjectFactory::instance()); + wellPathCopy->selected = true; fieldGroup->objects.push_back(wellPathCopy); } From 99ce43ccdb9071ba27d75cb483440d59a57403cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A5rd=20Skaflestad?= Date: Mon, 17 Jun 2019 19:31:48 +0200 Subject: [PATCH 181/396] Support Creating ECLGraph from "ecl_grid_type*" This commit introduces a new static function ECLGraph::load(const ecl_grid_type*, const ECLInitFileData&) This is in order to simplify constructing the backing graph from ResInsight's .EGRID input--especially to have consistent view of a model's active cells irrespective of which simulator created the result set. --- .../opm/utility/ECLGraph.cpp | 47 ++++++++++--------- .../opm/utility/ECLGraph.hpp | 9 ++++ 2 files changed, 35 insertions(+), 21 deletions(-) diff --git a/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLGraph.cpp b/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLGraph.cpp index 528d977441..08e97ab983 100644 --- a/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLGraph.cpp +++ b/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLGraph.cpp @@ -1261,8 +1261,8 @@ public: /// If available in the INIT file, the constructor will /// also leverage the transmissibility data when /// constructing the active cell neighbourship table. - Impl(const boost::filesystem::path& grid, - const ECLInitFileData& init); + Impl(const ecl_grid_type* grid, + const ECLInitFileData& init); /// Retrieve number of grids. /// @@ -1909,21 +1909,17 @@ isViable(const std::vector& grids, // ====================================================================== -Opm::ECLGraph::Impl::Impl(const boost::filesystem::path& grid, - const ECLInitFileData& init) +Opm::ECLGraph::Impl::Impl(const ecl_grid_type* grid, + const ECLInitFileData& init) { - const auto G = ECL::loadCase(grid); - - const auto numGrids = ECL::numGrids(G.get()); + const auto numGrids = ECL::numGrids(grid); this->grid_.reserve(numGrids); this->activeOffset_.reserve(numGrids + 1); this->activeOffset_.push_back(0); - for (auto gridID = 0*numGrids; gridID < numGrids; ++gridID) - { - this->grid_.emplace_back(ECL::getGrid(G.get(), gridID), - init, gridID); + for (auto gridID = 0*numGrids; gridID < numGrids; ++gridID) { + this->grid_.emplace_back(ECL::getGrid(grid, gridID), init, gridID); this->activeOffset_.push_back(this->activeOffset_.back() + this->grid_.back().numCells()); @@ -1933,34 +1929,34 @@ Opm::ECLGraph::Impl::Impl(const boost::filesystem::path& grid, this->gridID_[this->activeGrids_.back()] = gridID; } - this->defineNNCs(G.get(), init); + this->defineNNCs(grid, init); this->defineActivePhases(init); // Extract geometry of main grid. { // Size { - this->geomGrid_.size[0] = ecl_grid_get_nx(G.get()); - this->geomGrid_.size[1] = ecl_grid_get_ny(G.get()); - this->geomGrid_.size[2] = ecl_grid_get_nz(G.get()); + this->geomGrid_.size[0] = ecl_grid_get_nx(grid); + this->geomGrid_.size[1] = ecl_grid_get_ny(grid); + this->geomGrid_.size[2] = ecl_grid_get_nz(grid); } // COORD { const auto ncoord = - static_cast(ecl_grid_get_coord_size(G.get())); + static_cast(ecl_grid_get_coord_size(grid)); this->geomGrid_.coord.resize(ncoord, 0.0); - ecl_grid_init_coord_data_double(G.get(), this->geomGrid_.coord.data()); + ecl_grid_init_coord_data_double(grid, this->geomGrid_.coord.data()); } // ZCORN { const auto nzcorn = - static_cast(ecl_grid_get_zcorn_size(G.get())); + static_cast(ecl_grid_get_zcorn_size(grid)); this->geomGrid_.zcorn.resize(nzcorn, 0.0); - ecl_grid_init_zcorn_data_double(G.get(), this->geomGrid_.zcorn.data()); + ecl_grid_init_zcorn_data_double(grid, this->geomGrid_.zcorn.data()); } // ACTNUM @@ -1972,7 +1968,7 @@ Opm::ECLGraph::Impl::Impl(const boost::filesystem::path& grid, this->geomGrid_.actnum.assign(nglob, 1); - ecl_grid_init_actnum_data(G.get(), this->geomGrid_.actnum.data()); + ecl_grid_init_actnum_data(grid, this->geomGrid_.actnum.data()); } } } @@ -2431,7 +2427,16 @@ Opm::ECLGraph Opm::ECLGraph::load(const boost::filesystem::path& grid, const ECLInitFileData& init) { - auto pImpl = ImplPtr{new Impl(grid, init)}; + auto G = ECL::loadCase(grid); + + return ECLGraph::load(G.get(), init); +} + +Opm::ECLGraph +Opm::ECLGraph::load(const ecl_grid_type* grid, + const ECLInitFileData& init) +{ + auto pImpl = ImplPtr{ new Impl(grid, init) }; return { std::move(pImpl) }; } diff --git a/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLGraph.hpp b/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLGraph.hpp index bd12218ea3..20891bad08 100644 --- a/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLGraph.hpp +++ b/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLGraph.hpp @@ -38,6 +38,11 @@ /// on-disk ECLIPSE output, featuring on-demand property loading from /// backing object (e.g., restart vectors at various time points). +extern "C" { + struct ecl_grid_struct; + typedef ecl_grid_struct ecl_grid_type; +} // extern "C" + namespace Opm { /// Package an ECLIPSE result set (represented as GRID, INIT, and @@ -92,6 +97,10 @@ namespace Opm { load(const boost::filesystem::path& gridFile, const ECLInitFileData& init); + static ECLGraph + load(const ecl_grid_type* grid, + const ECLInitFileData& init); + /// Retrieve number of grids in model. /// /// \return The number of LGR grids plus one (the main grid). From ff16156c2a5b616eba78dcfaa0efe7244c30cfbd Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 18 Jun 2019 10:58:07 +0200 Subject: [PATCH 182/396] #4434 Flow Diag adjustments : Use active cells from PORV in Flow Diag --- .../FileInterface/RifReaderEclipseOutput.h | 9 ++++++-- .../RigCaseCellResultsData.cpp | 8 +++++++ .../RigCaseCellResultsData.h | 1 + .../RigFlowDiagSolverInterface.cpp | 23 +++++++++++++++---- 4 files changed, 35 insertions(+), 6 deletions(-) diff --git a/ApplicationCode/FileInterface/RifReaderEclipseOutput.h b/ApplicationCode/FileInterface/RifReaderEclipseOutput.h index 8efcb14c05..ec1cb02421 100644 --- a/ApplicationCode/FileInterface/RifReaderEclipseOutput.h +++ b/ApplicationCode/FileInterface/RifReaderEclipseOutput.h @@ -83,6 +83,13 @@ public: std::set availablePhases() const override; + // Load main, it is up to the consumer to release the memory using + // + // ecl_grid_type* myGrid = loadMainGrid(); + // free(myGrid); + // + ecl_grid_type* loadMainGrid() const; + private: bool readActiveCellInfo(); void buildMetaData(ecl_grid_type* grid); @@ -108,8 +115,6 @@ private: static bool isEclipseAndSoursimTimeStepsEqual(const QDateTime& eclipseDateTime, const QDateTime& sourSimDateTime); - ecl_grid_type* loadMainGrid() const; - private: QString m_fileName; // Name of file used to start accessing Eclipse output files QStringList m_filesWithSameBaseName; // Set of files in filename's path with same base name as filename diff --git a/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp b/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp index 948cdc0059..90606db90a 100644 --- a/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp @@ -2639,6 +2639,14 @@ void RigCaseCellResultsData::setReaderInterface(RifReaderInterface* readerInterf m_readerInterface = readerInterface; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +const RifReaderInterface* RigCaseCellResultsData::readerInterface() const +{ + return m_readerInterface.p(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.h b/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.h index cac97fc235..f8c5bd0952 100644 --- a/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.h +++ b/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.h @@ -57,6 +57,7 @@ public: // Initialization void setReaderInterface(RifReaderInterface* readerInterface); + const RifReaderInterface* readerInterface() const; void setHdf5Filename(const QString& hdf5SourSimFilename ); void setActiveFormationNames(RigFormationNames* activeFormationNames); RigFormationNames* activeFormationNames(); diff --git a/ApplicationCode/ReservoirDataModel/RigFlowDiagSolverInterface.cpp b/ApplicationCode/ReservoirDataModel/RigFlowDiagSolverInterface.cpp index 1ed3c85107..6875a82e9e 100644 --- a/ApplicationCode/ReservoirDataModel/RigFlowDiagSolverInterface.cpp +++ b/ApplicationCode/ReservoirDataModel/RigFlowDiagSolverInterface.cpp @@ -21,6 +21,7 @@ #include "RiaLogging.h" #include "RifEclipseOutputFileTools.h" +#include "RifReaderEclipseOutput.h" #include "RifReaderInterface.h" #include "RigActiveCellInfo.h" @@ -121,11 +122,11 @@ void RigFlowDiagTimeStepResult::addResult(const RigFlowDiagResultAddress& resAdd class RigOpmFlowDiagStaticData : public cvf::Object { public: - RigOpmFlowDiagStaticData(const std::string& grid, const std::string& init, RiaEclipseUnitTools::UnitSystem caseUnitSystem) + RigOpmFlowDiagStaticData(const ecl_grid_type* mainGrid, const std::string& init, RiaEclipseUnitTools::UnitSystem caseUnitSystem) { Opm::ECLInitFileData initData(init); - m_eclGraph.reset(new Opm::ECLGraph(Opm::ECLGraph::load(grid, initData))); + m_eclGraph.reset(new Opm::ECLGraph(Opm::ECLGraph::load(mainGrid, initData))); m_hasUnifiedRestartFile = false; m_poreVolume = m_eclGraph->poreVolume(); @@ -518,8 +519,22 @@ bool RigFlowDiagSolverInterface::ensureStaticDataObjectInstanceCreated() return false; } - RiaEclipseUnitTools::UnitSystem caseUnitSystem = eclipseCaseData->unitsType(); - m_opmFlowDiagStaticData = new RigOpmFlowDiagStaticData(gridFileName.toStdString(), initFileName, caseUnitSystem); + //ecl_grid_type* mainGrid = eclipseCaseData->results(RiaDefines::MATRIX_MODEL)->readerInterface(); + auto fileReader = eclipseCaseData->results(RiaDefines::MATRIX_MODEL)->readerInterface(); + auto eclOutput = dynamic_cast(fileReader); + if (eclOutput) + { + ecl_grid_type* mainGrid = eclOutput->loadMainGrid(); + if (!mainGrid) + { + return false; + } + + RiaEclipseUnitTools::UnitSystem caseUnitSystem = eclipseCaseData->unitsType(); + m_opmFlowDiagStaticData = new RigOpmFlowDiagStaticData(mainGrid, initFileName, caseUnitSystem); + + free(mainGrid); + } } } From c1b9738298db21b91ae5204cfc49f6f7575b5084 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 18 Jun 2019 12:27:29 +0200 Subject: [PATCH 183/396] #4434 Flow Diag adjustments : Use ecl_grid_free --- .../ReservoirDataModel/RigFlowDiagSolverInterface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ApplicationCode/ReservoirDataModel/RigFlowDiagSolverInterface.cpp b/ApplicationCode/ReservoirDataModel/RigFlowDiagSolverInterface.cpp index 6875a82e9e..84c286582f 100644 --- a/ApplicationCode/ReservoirDataModel/RigFlowDiagSolverInterface.cpp +++ b/ApplicationCode/ReservoirDataModel/RigFlowDiagSolverInterface.cpp @@ -533,7 +533,7 @@ bool RigFlowDiagSolverInterface::ensureStaticDataObjectInstanceCreated() RiaEclipseUnitTools::UnitSystem caseUnitSystem = eclipseCaseData->unitsType(); m_opmFlowDiagStaticData = new RigOpmFlowDiagStaticData(mainGrid, initFileName, caseUnitSystem); - free(mainGrid); + ecl_grid_free(mainGrid); } } } From cf00cb48094037f4e32c8247d258439c3c5ef7c5 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 20 Jun 2019 12:01:00 +0200 Subject: [PATCH 184/396] #4497 Fishbones : Set default fishbones to use spacing --- .../ProjectDataModel/Completions/RimFishbonesMultipleSubs.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ApplicationCode/ProjectDataModel/Completions/RimFishbonesMultipleSubs.cpp b/ApplicationCode/ProjectDataModel/Completions/RimFishbonesMultipleSubs.cpp index ec34468ef1..b1e04b61e1 100644 --- a/ApplicationCode/ProjectDataModel/Completions/RimFishbonesMultipleSubs.cpp +++ b/ApplicationCode/ProjectDataModel/Completions/RimFishbonesMultipleSubs.cpp @@ -152,7 +152,7 @@ QString RimFishbonesMultipleSubs::generatedName() const void RimFishbonesMultipleSubs::setMeasuredDepthAndCount(double startMD, double spacing, int subCount) { double endMD = startMD + spacing * subCount; - m_valveLocations->initFields(RimMultipleValveLocations::VALVE_COUNT, startMD, endMD, spacing, subCount, {}); + m_valveLocations->initFields(RimMultipleValveLocations::VALVE_SPACING, startMD, endMD, spacing, subCount, {}); computeRangesAndLocations(); computeRotationAngles(); From 3b8348ddba18519ddf8eeedf8190a8f8fc1c1a41 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 19 Jun 2019 13:10:51 +0200 Subject: [PATCH 185/396] #4495 Active Cells : Add const to methods --- .../FileInterface/RifEclipseOutputFileTools.cpp | 14 +++++++------- .../FileInterface/RifEclipseOutputFileTools.h | 14 +++++++------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/ApplicationCode/FileInterface/RifEclipseOutputFileTools.cpp b/ApplicationCode/FileInterface/RifEclipseOutputFileTools.cpp index 8d05154f7b..764736e624 100644 --- a/ApplicationCode/FileInterface/RifEclipseOutputFileTools.cpp +++ b/ApplicationCode/FileInterface/RifEclipseOutputFileTools.cpp @@ -123,7 +123,7 @@ void getDayMonthYear(const ecl_kw_type* intehead_kw, int* day, int* month, int* //-------------------------------------------------------------------------------------------------- /// Get list of time step texts (dates) //-------------------------------------------------------------------------------------------------- -void RifEclipseOutputFileTools::timeSteps(ecl_file_type* ecl_file, std::vector* timeSteps, std::vector* daysSinceSimulationStart) +void RifEclipseOutputFileTools::timeSteps(const ecl_file_type* ecl_file, std::vector* timeSteps, std::vector* daysSinceSimulationStart) { if (!ecl_file) return; @@ -183,7 +183,7 @@ void RifEclipseOutputFileTools::timeSteps(ecl_file_type* ecl_file, std::vector* values) +bool RifEclipseOutputFileTools::keywordData(const ecl_file_type* ecl_file, const QString& keyword, size_t fileKeywordOccurrence, std::vector* values) { bool result = false; @@ -210,7 +210,7 @@ bool RifEclipseOutputFileTools::keywordData(ecl_file_type* ecl_file, const QStri //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool RifEclipseOutputFileTools::keywordData(ecl_file_type* ecl_file, const QString& keyword, size_t fileKeywordOccurrence, std::vector* values) +bool RifEclipseOutputFileTools::keywordData(const ecl_file_type* ecl_file, const QString& keyword, size_t fileKeywordOccurrence, std::vector* values) { bool result = false; @@ -365,7 +365,7 @@ void RifEclipseOutputFileTools::readGridDimensions(const QString& gridFileName, /// 3 : LAB /// -1 : No INTEHEAD keyword found //-------------------------------------------------------------------------------------------------- -int RifEclipseOutputFileTools::readUnitsType(ecl_file_type* ecl_file) +int RifEclipseOutputFileTools::readUnitsType(const ecl_file_type* ecl_file) { int unitsType = -1; @@ -427,7 +427,7 @@ QString RifEclipseOutputFileTools::createIndexFileName(const QString& resultFile //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::set RifEclipseOutputFileTools::findAvailablePhases(ecl_file_type* ecl_file) +std::set RifEclipseOutputFileTools::findAvailablePhases(const ecl_file_type* ecl_file) { std::set phaseTypes; @@ -462,7 +462,7 @@ std::set RifEclipseOutputFileTools::findAvailablePhases(e /// //-------------------------------------------------------------------------------------------------- void RifEclipseOutputFileTools::transferNncFluxData(const ecl_grid_type* grid, - ecl_file_view_type* summaryView, + const ecl_file_view_type* summaryView, std::vector* waterFlux, std::vector* oilFlux, std::vector* gasFlux) @@ -501,7 +501,7 @@ void RifEclipseOutputFileTools::transferNncFluxData(const ecl_grid_type* grid, //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool RifEclipseOutputFileTools::isExportedFromIntersect(ecl_file_type* ecl_file) +bool RifEclipseOutputFileTools::isExportedFromIntersect(const ecl_file_type* ecl_file) { // This code is taken from ecl_file_get_ecl_version() in ecl_file.cpp diff --git a/ApplicationCode/FileInterface/RifEclipseOutputFileTools.h b/ApplicationCode/FileInterface/RifEclipseOutputFileTools.h index 0486cfd337..88e509ef07 100644 --- a/ApplicationCode/FileInterface/RifEclipseOutputFileTools.h +++ b/ApplicationCode/FileInterface/RifEclipseOutputFileTools.h @@ -51,10 +51,10 @@ public: static void findKeywordsAndItemCount(std::vector ecl_files, QStringList* resultNames, std::vector* resultDataItemCounts); - static bool keywordData(ecl_file_type* ecl_file, const QString& keyword, size_t fileKeywordOccurrence, std::vector* values); - static bool keywordData(ecl_file_type* ecl_file, const QString& keyword, size_t fileKeywordOccurrence, std::vector* values); + static bool keywordData(const ecl_file_type* ecl_file, const QString& keyword, size_t fileKeywordOccurrence, std::vector* values); + static bool keywordData(const ecl_file_type* ecl_file, const QString& keyword, size_t fileKeywordOccurrence, std::vector* values); - static void timeSteps(ecl_file_type* ecl_file, std::vector* timeSteps, std::vector* daysSinceSimulationStart); + static void timeSteps(const ecl_file_type* ecl_file, std::vector* timeSteps, std::vector* daysSinceSimulationStart); static bool isValidEclipseFileName(const QString& fileName); static QByteArray md5sum(const QString& fileName); @@ -65,18 +65,18 @@ public: static void readGridDimensions(const QString& gridFileName, std::vector< std::vector >& gridDimensions); - static int readUnitsType(ecl_file_type* ecl_file); + static int readUnitsType(const ecl_file_type* ecl_file); static cvf::ref createDynamicResultAccess(const QString& fileName); static QString createIndexFileName(const QString& resultFileName); - static std::set findAvailablePhases(ecl_file_type* ecl_file); + static std::set findAvailablePhases(const ecl_file_type* ecl_file); - static void transferNncFluxData(const ecl_grid_type* grid, ecl_file_view_type* summaryView, + static void transferNncFluxData(const ecl_grid_type* grid, const ecl_file_view_type* summaryView, std::vector* waterFlux, std::vector* oilFlux, std::vector* gasFlux); - static bool isExportedFromIntersect(ecl_file_type* ecl_file); + static bool isExportedFromIntersect(const ecl_file_type* ecl_file); static ecl_kw_type* createActnumFromPorv(ecl_file_type* ecl_file); From df69bc2d8d8accc0091f179b59ca801ff999c2ae Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 19 Jun 2019 13:41:42 +0200 Subject: [PATCH 186/396] Whitespace --- .../FileInterface/RifReaderEclipseOutput.cpp | 845 ++++++++++-------- 1 file changed, 465 insertions(+), 380 deletions(-) diff --git a/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp b/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp index c93d7fbfd7..654d8b82c0 100644 --- a/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp +++ b/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp @@ -3,17 +3,17 @@ // Copyright (C) 2011- Statoil ASA // Copyright (C) 2013- Ceetron Solutions AS // Copyright (C) 2011-2012 Ceetron AS -// +// // 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 +// +// See the GNU General Public License at // for more details. // ///////////////////////////////////////////////////////////////////////////////// @@ -25,11 +25,11 @@ #include "RiaLogging.h" #include "RiaPreferences.h" +#include "RiaStringEncodingTools.h" #include "RifEclipseInputFileTools.h" #include "RifEclipseOutputFileTools.h" #include "RifHdf5ReaderInterface.h" #include "RifReaderSettings.h" -#include "RiaStringEncodingTools.h" #ifdef USE_HDF5 #include "RifHdf5Reader.h" @@ -48,9 +48,9 @@ #include "cvfTrace.h" #include "ert/ecl/ecl_kw_magic.h" +#include "ert/ecl/ecl_nnc_data.h" #include "ert/ecl/ecl_nnc_export.h" #include "ert/ecl/ecl_nnc_geometry.h" -#include "ert/ecl/ecl_nnc_data.h" #include #include @@ -59,7 +59,6 @@ #include #include - //-------------------------------------------------------------------------------------------------- /// ECLIPSE cell numbering layout: /// Lower layer: Upper layer @@ -76,12 +75,12 @@ // The indexing conventions for vertices in ECLIPSE // -// 2-------------3 -// /| /| -// / | / | /j -// / | / | / -// 0-------------1 | *---i -// | | | | | +// 2-------------3 +// /| /| +// / | / | /j +// / | / | / +// 0-------------1 | *---i +// | | | | | // | 6---------|---7 | // | / | / |k // | / | / @@ -91,10 +90,10 @@ // // The indexing conventions for vertices in ResInsight // -// 7-------------6 |k -// /| /| | /j -// / | / | |/ -// / | / | *---i +// 7-------------6 |k +// /| /| | /j +// / | / | |/ +// / | / | *---i // 4-------------5 | // | | | | // | 3---------|---2 @@ -105,18 +104,23 @@ // vertex indices // -static const size_t cellMappingECLRi[8] = { 0, 1, 3, 2, 4, 5, 7, 6 }; - +static const size_t cellMappingECLRi[8] = {0, 1, 3, 2, 4, 5, 7, 6}; //************************************************************************************************** // Static functions //************************************************************************************************** -bool transferGridCellData(RigMainGrid* mainGrid, RigActiveCellInfo* activeCellInfo, RigActiveCellInfo* fractureActiveCellInfo, RigGridBase* localGrid, const ecl_grid_type* localEclGrid, size_t matrixActiveStartIndex, size_t fractureActiveStartIndex) +bool transferGridCellData(RigMainGrid* mainGrid, + RigActiveCellInfo* activeCellInfo, + RigActiveCellInfo* fractureActiveCellInfo, + RigGridBase* localGrid, + const ecl_grid_type* localEclGrid, + size_t matrixActiveStartIndex, + size_t fractureActiveStartIndex) { CVF_ASSERT(activeCellInfo && fractureActiveCellInfo); - int cellCount = ecl_grid_get_global_size(localEclGrid); + int cellCount = ecl_grid_get_global_size(localEclGrid); size_t cellStartIndex = mainGrid->globalCellArray().size(); size_t nodeStartIndex = mainGrid->nodes().size(); @@ -124,10 +128,10 @@ bool transferGridCellData(RigMainGrid* mainGrid, RigActiveCellInfo* activeCellIn defaultCell.setHostGrid(localGrid); mainGrid->globalCellArray().resize(cellStartIndex + cellCount, defaultCell); - mainGrid->nodes().resize(nodeStartIndex + cellCount*8, cvf::Vec3d(0,0,0)); + mainGrid->nodes().resize(nodeStartIndex + cellCount * 8, cvf::Vec3d(0, 0, 0)); - int progTicks = 100; - int cellsPrProgressTick = std::max(1, cellCount/progTicks); + int progTicks = 100; + int cellsPrProgressTick = std::max(1, cellCount / progTicks); caf::ProgressInfo progInfo(progTicks, ""); size_t computedCellCount = 0; @@ -151,7 +155,8 @@ bool transferGridCellData(RigMainGrid* mainGrid, RigActiveCellInfo* activeCellIn int fractureActiveIndex = ecl_grid_get_active_fracture_index1(localEclGrid, gridLocalCellIndex); if (fractureActiveIndex != -1) { - fractureActiveCellInfo->setCellResultIndex(cellStartIndex + gridLocalCellIndex, fractureActiveStartIndex + fractureActiveIndex); + fractureActiveCellInfo->setCellResultIndex(cellStartIndex + gridLocalCellIndex, + fractureActiveStartIndex + fractureActiveIndex); } // Parent cell index @@ -165,15 +170,15 @@ bool transferGridCellData(RigMainGrid* mainGrid, RigActiveCellInfo* activeCellIn { cell.setParentCellIndex(parentCellIndex); } - + // Corner coordinates int cIdx; for (cIdx = 0; cIdx < 8; ++cIdx) { - double * point = mainGrid->nodes()[nodeStartIndex + gridLocalCellIndex * 8 + cellMappingECLRi[cIdx]].ptr(); + double* point = mainGrid->nodes()[nodeStartIndex + gridLocalCellIndex * 8 + cellMappingECLRi[cIdx]].ptr(); ecl_grid_get_cell_corner_xyz1(localEclGrid, gridLocalCellIndex, cIdx, &(point[0]), &(point[1]), &(point[2])); - point[2] = -point[2]; // Flipping Z making depth become negative z values - cell.cornerIndices()[cIdx] = nodeStartIndex + gridLocalCellIndex*8 + cIdx; + point[2] = -point[2]; // Flipping Z making depth become negative z values + cell.cornerIndices()[cIdx] = nodeStartIndex + gridLocalCellIndex * 8 + cIdx; } // Sub grid in cell @@ -187,7 +192,7 @@ bool transferGridCellData(RigMainGrid* mainGrid, RigActiveCellInfo* activeCellIn // Mark inactive long pyramid looking cells as invalid // Forslag - //if (!invalid && (cell.isInCoarseCell() || (!cell.isActiveInMatrixModel() && !cell.isActiveInFractureModel()) ) ) + // if (!invalid && (cell.isInCoarseCell() || (!cell.isActiveInMatrixModel() && !cell.isActiveInFractureModel()) ) ) cell.setInvalid(cell.isLongPyramidCell()); #pragma omp critical @@ -215,7 +220,7 @@ RifReaderEclipseOutput::RifReaderEclipseOutput() m_eclipseCase = nullptr; - m_ecl_init_file = nullptr; + m_ecl_init_file = nullptr; m_dynamicResultsAccess = nullptr; } @@ -234,7 +239,6 @@ RifReaderEclipseOutput::~RifReaderEclipseOutput() { m_dynamicResultsAccess->close(); } - } //-------------------------------------------------------------------------------------------------- @@ -250,7 +254,7 @@ bool RifReaderEclipseOutput::transferGeometry(const ecl_grid_type* mainEclGrid, return false; } - RigActiveCellInfo* activeCellInfo = eclipseCase->activeCellInfo(RiaDefines::MATRIX_MODEL); + RigActiveCellInfo* activeCellInfo = eclipseCase->activeCellInfo(RiaDefines::MATRIX_MODEL); RigActiveCellInfo* fractureActiveCellInfo = eclipseCase->activeCellInfo(RiaDefines::FRACTURE_MODEL); CVF_ASSERT(activeCellInfo && fractureActiveCellInfo); @@ -258,7 +262,7 @@ bool RifReaderEclipseOutput::transferGeometry(const ecl_grid_type* mainEclGrid, RigMainGrid* mainGrid = eclipseCase->mainGrid(); CVF_ASSERT(mainGrid); { - cvf::Vec3st gridPointDim(0,0,0); + cvf::Vec3st gridPointDim(0, 0, 0); gridPointDim.x() = ecl_grid_get_nx(mainEclGrid) + 1; gridPointDim.y() = ecl_grid_get_ny(mainEclGrid) + 1; gridPointDim.z() = ecl_grid_get_nz(mainEclGrid) + 1; @@ -280,9 +284,9 @@ bool RifReaderEclipseOutput::transferGeometry(const ecl_grid_type* mainEclGrid, ecl_grid_type* localEclGrid = ecl_grid_iget_lgr(mainEclGrid, lgrIdx); std::string lgrName = ecl_grid_get_name(localEclGrid); - int lgrId = ecl_grid_get_lgr_nr(localEclGrid); + int lgrId = ecl_grid_get_lgr_nr(localEclGrid); - cvf::Vec3st gridPointDim(0,0,0); + cvf::Vec3st gridPointDim(0, 0, 0); gridPointDim.x() = ecl_grid_get_nx(localEclGrid) + 1; gridPointDim.y() = ecl_grid_get_ny(localEclGrid) + 1; gridPointDim.z() = ecl_grid_get_nz(localEclGrid) + 1; @@ -297,14 +301,14 @@ bool RifReaderEclipseOutput::transferGeometry(const ecl_grid_type* mainEclGrid, totalCellCount += ecl_grid_get_global_size(localEclGrid); } - + activeCellInfo->setReservoirCellCount(totalCellCount); fractureActiveCellInfo->setReservoirCellCount(totalCellCount); // Reserve room for the cells and nodes and fill them with data mainGrid->globalCellArray().reserve(totalCellCount); - mainGrid->nodes().reserve(8*totalCellCount); + mainGrid->nodes().reserve(8 * totalCellCount); caf::ProgressInfo progInfo(3 + numLGRs, ""); @@ -313,7 +317,7 @@ bool RifReaderEclipseOutput::transferGeometry(const ecl_grid_type* mainEclGrid, transferGridCellData(mainGrid, activeCellInfo, fractureActiveCellInfo, mainGrid, mainEclGrid, 0, 0); } - size_t globalMatrixActiveSize = ecl_grid_get_nactive(mainEclGrid); + size_t globalMatrixActiveSize = ecl_grid_get_nactive(mainEclGrid); size_t globalFractureActiveSize = ecl_grid_get_nactive_fracture(mainEclGrid); activeCellInfo->setGridCount(1 + numLGRs); @@ -324,15 +328,20 @@ bool RifReaderEclipseOutput::transferGeometry(const ecl_grid_type* mainEclGrid, transferCoarseningInfo(mainEclGrid, mainGrid); - for (lgrIdx = 0; lgrIdx < numLGRs; ++lgrIdx) { - auto task = progInfo.task("LGR number " + QString::number(lgrIdx + 1), 1); + auto task = progInfo.task("LGR number " + QString::number(lgrIdx + 1), 1); ecl_grid_type* localEclGrid = ecl_grid_iget_lgr(mainEclGrid, lgrIdx); - RigLocalGrid* localGrid = static_cast(mainGrid->gridByIndex(lgrIdx+1)); + RigLocalGrid* localGrid = static_cast(mainGrid->gridByIndex(lgrIdx + 1)); - transferGridCellData(mainGrid, activeCellInfo, fractureActiveCellInfo, localGrid, localEclGrid, globalMatrixActiveSize, globalFractureActiveSize); + transferGridCellData(mainGrid, + activeCellInfo, + fractureActiveCellInfo, + localGrid, + localEclGrid, + globalMatrixActiveSize, + globalFractureActiveSize); int matrixActiveCellCount = ecl_grid_get_nactive(localEclGrid); globalMatrixActiveSize += matrixActiveCellCount; @@ -359,12 +368,13 @@ bool RifReaderEclipseOutput::transferGeometry(const ecl_grid_type* mainEclGrid, bool RifReaderEclipseOutput::open(const QString& fileName, RigEclipseCaseData* eclipseCase) { CVF_ASSERT(eclipseCase); - caf::ProgressInfo progress(100, "Reading Grid"); + caf::ProgressInfo progress(100, "Reading Grid"); if (!RifEclipseOutputFileTools::isValidEclipseFileName(fileName)) { - QString errorMessage = QFileInfo(fileName).fileName() + QString(" is not a valid Eclipse file name.\n" - "Please make sure the file does not contain a mix of upper and lower case letters."); + QString errorMessage = QFileInfo(fileName).fileName() + + QString(" is not a valid Eclipse file name.\n" + "Please make sure the file does not contain a mix of upper and lower case letters."); RiaLogging::error(errorMessage); return false; } @@ -372,12 +382,12 @@ bool RifReaderEclipseOutput::open(const QString& fileName, RigEclipseCaseData* e QStringList fileSet; { auto task = progress.task("Get set of files"); - + if (!RifEclipseOutputFileTools::findSiblingFilesWithSameBaseName(fileName, &fileSet)) return false; m_fileName = fileName; } - + ecl_grid_type* mainEclGrid = nullptr; { auto task = progress.task("Open Init File and Load Main Grid", 19); @@ -429,7 +439,7 @@ bool RifReaderEclipseOutput::open(const QString& fileName, RigEclipseCaseData* e if (isNNCsEnabled()) { caf::ProgressInfo nncProgress(10, ""); - + { auto subNncTask = nncProgress.task("Reading static NNC data"); transferStaticNNCData(mainEclGrid, m_ecl_init_file, eclipseCase->mainGrid()); @@ -441,14 +451,14 @@ bool RifReaderEclipseOutput::open(const QString& fileName, RigEclipseCaseData* e auto subNncTask = nncProgress.task("Reading dynamic NNC data"); transferDynamicNNCData(mainEclGrid, eclipseCase->mainGrid()); } - + { auto subNncTask = nncProgress.task("Processing connections", 8); eclipseCase->mainGrid()->nncData()->processConnections(*(eclipseCase->mainGrid())); } } } - + { auto task = progress.task("Handling well information", 10); if (!RiaApplication::instance()->preferences()->readerSettings()->skipWellData()) @@ -470,7 +480,7 @@ bool RifReaderEclipseOutput::open(const QString& fileName, RigEclipseCaseData* e } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- void RifReaderEclipseOutput::setHdf5FileName(const QString& fileName) { @@ -511,12 +521,14 @@ void RifReaderEclipseOutput::setHdf5FileName(const QString& fileName) return; } - + if (timeStepInfos.size() > 0) { if (allTimeSteps().size() != sourSimTimeSteps.size()) { - RiaLogging::error(QString("HDF: Time step count mismatch, Eclipse : %1 ; HDF : %2 ").arg(allTimeSteps().size()).arg(sourSimTimeSteps.size())); + RiaLogging::error(QString("HDF: Time step count mismatch, Eclipse : %1 ; HDF : %2 ") + .arg(allTimeSteps().size()) + .arg(sourSimTimeSteps.size())); return; } @@ -534,7 +546,9 @@ void RifReaderEclipseOutput::setHdf5FileName(const QString& fileName) } else { - RiaLogging::error(QString("HDF: Time step count mismatch, Eclipse : %1 ; HDF : %2 ").arg(timeStepInfos.size()).arg(sourSimTimeSteps.size())); + RiaLogging::error(QString("HDF: Time step count mismatch, Eclipse : %1 ; HDF : %2 ") + .arg(timeStepInfos.size()) + .arg(sourSimTimeSteps.size())); // We have less soursim time steps than eclipse time steps isTimeStampsEqual = false; @@ -548,7 +562,7 @@ void RifReaderEclipseOutput::setHdf5FileName(const QString& fileName) // Use time steps from HDF to define the time steps QDateTime firstDate = sourSimTimeSteps[0]; - std::vector daysSinceSimulationStart; + std::vector daysSinceSimulationStart; for (auto d : sourSimTimeSteps) { @@ -584,7 +598,7 @@ void RifReaderEclipseOutput::setHdf5FileName(const QString& fileName) } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- void RifReaderEclipseOutput::setFileDataAccess(RifEclipseRestartDataAccess* restartDataAccess) { @@ -600,7 +614,7 @@ const size_t* RifReaderEclipseOutput::eclipseCellIndexMapping() } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- void RifReaderEclipseOutput::importFaults(const QStringList& fileSet, cvf::Collection* faults) { @@ -615,12 +629,13 @@ void RifReaderEclipseOutput::importFaults(const QStringList& fileSet, cvf::Colle } else { - foreach(QString fname, fileSet) + foreach (QString fname, fileSet) { if (fname.endsWith(".DATA")) { std::vector filenamesWithFaults; - RifEclipseInputFileTools::readFaultsInGridSection(fname, faults, &filenamesWithFaults, faultIncludeFileAbsolutePathPrefix()); + RifEclipseInputFileTools::readFaultsInGridSection( + fname, faults, &filenamesWithFaults, faultIncludeFileAbsolutePathPrefix()); std::sort(filenamesWithFaults.begin(), filenamesWithFaults.end()); std::vector::iterator last = std::unique(filenamesWithFaults.begin(), filenamesWithFaults.end()); @@ -633,7 +648,7 @@ void RifReaderEclipseOutput::importFaults(const QStringList& fileSet, cvf::Colle } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- void RifReaderEclipseOutput::importEquilData(const QString& deckFileName, const QString& includeStatementAbsolutePathPrefix, @@ -651,14 +666,14 @@ void RifReaderEclipseOutput::importEquilData(const QString& deckFileName, bool isStopParsingKeywordDetected = false; RifEclipseInputFileTools::readKeywordAndParseIncludeStatementsRecursively(keyword, - keywordToStopParsing, - data, - startPositionInFile, - pathAliasDefinitions, - &keywordContent, - &fileNamesContainingKeyword, - &isStopParsingKeywordDetected, - includeStatementAbsolutePathPrefix); + keywordToStopParsing, + data, + startPositionInFile, + pathAliasDefinitions, + &keywordContent, + &fileNamesContainingKeyword, + &isStopParsingKeywordDetected, + includeStatementAbsolutePathPrefix); std::vector equilItems; for (const auto& s : keywordContent) { @@ -672,11 +687,13 @@ void RifReaderEclipseOutput::importEquilData(const QString& deckFileName, } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- -void RifReaderEclipseOutput::transferStaticNNCData(const ecl_grid_type* mainEclGrid , ecl_file_type* init_file, RigMainGrid* mainGrid) +void RifReaderEclipseOutput::transferStaticNNCData(const ecl_grid_type* mainEclGrid, + ecl_file_type* init_file, + RigMainGrid* mainGrid) { - if (!m_ecl_init_file ) return; + if (!m_ecl_init_file) return; CVF_ASSERT(mainEclGrid && mainGrid); @@ -687,7 +704,7 @@ void RifReaderEclipseOutput::transferStaticNNCData(const ecl_grid_type* mainEclG ecl_nnc_data_type* tran_data = ecl_nnc_data_alloc_tran(mainEclGrid, nnc_geo, ecl_file_get_global_view(init_file)); if (tran_data) { - int numNNC = ecl_nnc_data_get_size(tran_data); + int numNNC = ecl_nnc_data_get_size(tran_data); int geometrySize = ecl_nnc_geometry_size(nnc_geo); CVF_ASSERT(numNNC == geometrySize); @@ -696,16 +713,19 @@ void RifReaderEclipseOutput::transferStaticNNCData(const ecl_grid_type* mainEclG // Transform to our own data structures mainGrid->nncData()->connections().resize(numNNC); - std::vector& transmissibilityValues = mainGrid->nncData()->makeStaticConnectionScalarResult(RigNNCData::propertyNameCombTrans()); + std::vector& transmissibilityValues = + mainGrid->nncData()->makeStaticConnectionScalarResult(RigNNCData::propertyNameCombTrans()); const double* transValues = ecl_nnc_data_get_values(tran_data); for (int nIdx = 0; nIdx < numNNC; ++nIdx) { const ecl_nnc_pair_type* geometry_pair = ecl_nnc_geometry_iget(nnc_geo, nIdx); - RigGridBase* grid1 = mainGrid->gridByIndex(geometry_pair->grid_nr1); - mainGrid->nncData()->connections()[nIdx].m_c1GlobIdx = grid1->reservoirCellIndex(geometry_pair->global_index1); - RigGridBase* grid2 = mainGrid->gridByIndex(geometry_pair->grid_nr2); - mainGrid->nncData()->connections()[nIdx].m_c2GlobIdx = grid2->reservoirCellIndex(geometry_pair->global_index2); + RigGridBase* grid1 = mainGrid->gridByIndex(geometry_pair->grid_nr1); + mainGrid->nncData()->connections()[nIdx].m_c1GlobIdx = + grid1->reservoirCellIndex(geometry_pair->global_index1); + RigGridBase* grid2 = mainGrid->gridByIndex(geometry_pair->grid_nr2); + mainGrid->nncData()->connections()[nIdx].m_c2GlobIdx = + grid2->reservoirCellIndex(geometry_pair->global_index2); transmissibilityValues[nIdx] = transValues[nIdx]; } @@ -719,7 +739,7 @@ void RifReaderEclipseOutput::transferStaticNNCData(const ecl_grid_type* mainEclG } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- void RifReaderEclipseOutput::transferDynamicNNCData(const ecl_grid_type* mainEclGrid, RigMainGrid* mainGrid) { @@ -729,21 +749,26 @@ void RifReaderEclipseOutput::transferDynamicNNCData(const ecl_grid_type* mainEcl size_t timeStepCount = m_dynamicResultsAccess->timeStepCount(); - std::vector< std::vector >& waterFluxData = mainGrid->nncData()->makeDynamicConnectionScalarResult(RigNNCData::propertyNameFluxWat(), timeStepCount); - std::vector< std::vector >& oilFluxData = mainGrid->nncData()->makeDynamicConnectionScalarResult(RigNNCData::propertyNameFluxOil(), timeStepCount); - std::vector< std::vector >& gasFluxData = mainGrid->nncData()->makeDynamicConnectionScalarResult(RigNNCData::propertyNameFluxGas(), timeStepCount); + std::vector>& waterFluxData = + mainGrid->nncData()->makeDynamicConnectionScalarResult(RigNNCData::propertyNameFluxWat(), timeStepCount); + std::vector>& oilFluxData = + mainGrid->nncData()->makeDynamicConnectionScalarResult(RigNNCData::propertyNameFluxOil(), timeStepCount); + std::vector>& gasFluxData = + mainGrid->nncData()->makeDynamicConnectionScalarResult(RigNNCData::propertyNameFluxGas(), timeStepCount); for (size_t timeStep = 0; timeStep < timeStepCount; ++timeStep) { - m_dynamicResultsAccess->dynamicNNCResults(mainEclGrid, timeStep, &waterFluxData[timeStep], &oilFluxData[timeStep], &gasFluxData[timeStep]); + m_dynamicResultsAccess->dynamicNNCResults( + mainEclGrid, timeStep, &waterFluxData[timeStep], &oilFluxData[timeStep], &gasFluxData[timeStep]); } } - //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- -bool RifReaderEclipseOutput::openAndReadActiveCellData(const QString& fileName, const std::vector& mainCaseTimeSteps, RigEclipseCaseData* eclipseCase) +bool RifReaderEclipseOutput::openAndReadActiveCellData(const QString& fileName, + const std::vector& mainCaseTimeSteps, + RigEclipseCaseData* eclipseCase) { CVF_ASSERT(eclipseCase); @@ -759,14 +784,14 @@ bool RifReaderEclipseOutput::openAndReadActiveCellData(const QString& fileName, // Keep the set of files of interest m_filesWithSameBaseName = fileSet; - m_eclipseCase = eclipseCase; - m_fileName = fileName; + m_eclipseCase = eclipseCase; + m_fileName = fileName; if (!readActiveCellInfo()) { return false; } - + ensureDynamicResultAccessIsPresent(); if (m_dynamicResultsAccess.notNull()) { @@ -776,9 +801,8 @@ bool RifReaderEclipseOutput::openAndReadActiveCellData(const QString& fileName, return true; } - //-------------------------------------------------------------------------------------------------- -/// +/// /// See also RigStatistics::computeActiveCellUnion() //-------------------------------------------------------------------------------------------------- bool RifReaderEclipseOutput::readActiveCellInfo() @@ -789,13 +813,14 @@ bool RifReaderEclipseOutput::readActiveCellInfo() QString egridFileName = RifEclipseOutputFileTools::firstFileNameOfType(m_filesWithSameBaseName, ECL_EGRID_FILE); if (egridFileName.size() > 0) { - ecl_file_type* ecl_file = ecl_file_open(RiaStringEncodingTools::toNativeEncoded(egridFileName).data(), ECL_FILE_CLOSE_STREAM); + ecl_file_type* ecl_file = + ecl_file_open(RiaStringEncodingTools::toNativeEncoded(egridFileName).data(), ECL_FILE_CLOSE_STREAM); if (!ecl_file) return false; int actnumKeywordCount = ecl_file_get_num_named_kw(ecl_file, ACTNUM_KW); if (actnumKeywordCount > 0) { - std::vector > actnumValuesPerGrid; + std::vector> actnumValuesPerGrid; actnumValuesPerGrid.resize(actnumKeywordCount); size_t reservoirCellCount = 0; @@ -812,7 +837,7 @@ bool RifReaderEclipseOutput::readActiveCellInfo() return false; } - RigActiveCellInfo* activeCellInfo = m_eclipseCase->activeCellInfo(RiaDefines::MATRIX_MODEL); + RigActiveCellInfo* activeCellInfo = m_eclipseCase->activeCellInfo(RiaDefines::MATRIX_MODEL); RigActiveCellInfo* fractureActiveCellInfo = m_eclipseCase->activeCellInfo(RiaDefines::FRACTURE_MODEL); activeCellInfo->setReservoirCellCount(reservoirCellCount); @@ -820,12 +845,12 @@ bool RifReaderEclipseOutput::readActiveCellInfo() activeCellInfo->setGridCount(actnumKeywordCount); fractureActiveCellInfo->setGridCount(actnumKeywordCount); - size_t cellIdx = 0; - size_t globalActiveMatrixIndex = 0; + size_t cellIdx = 0; + size_t globalActiveMatrixIndex = 0; size_t globalActiveFractureIndex = 0; for (size_t gridIdx = 0; gridIdx < static_cast(actnumKeywordCount); gridIdx++) { - size_t activeMatrixIndex = 0; + size_t activeMatrixIndex = 0; size_t activeFractureIndex = 0; std::vector& actnumValues = actnumValuesPerGrid[gridIdx]; @@ -863,7 +888,6 @@ bool RifReaderEclipseOutput::readActiveCellInfo() return false; } - //-------------------------------------------------------------------------------------------------- /// Build meta data - get states and results info //-------------------------------------------------------------------------------------------------- @@ -872,11 +896,11 @@ void RifReaderEclipseOutput::buildMetaData(ecl_grid_type* grid) CVF_ASSERT(m_eclipseCase); CVF_ASSERT(m_filesWithSameBaseName.size() > 0); - caf::ProgressInfo progInfo(m_filesWithSameBaseName.size() + 3,""); + caf::ProgressInfo progInfo(m_filesWithSameBaseName.size() + 3, ""); progInfo.setNextProgressIncrement(m_filesWithSameBaseName.size()); - RigCaseCellResultsData* matrixModelResults = m_eclipseCase->results(RiaDefines::MATRIX_MODEL); + RigCaseCellResultsData* matrixModelResults = m_eclipseCase->results(RiaDefines::MATRIX_MODEL); RigCaseCellResultsData* fractureModelResults = m_eclipseCase->results(RiaDefines::FRACTURE_MODEL); std::vector timeStepInfos; @@ -891,15 +915,18 @@ void RifReaderEclipseOutput::buildMetaData(ecl_grid_type* grid) timeStepInfos = createFilteredTimeStepInfos(); - QStringList resultNames; + QStringList resultNames; std::vector resultNamesDataItemCounts; m_dynamicResultsAccess->resultNames(&resultNames, &resultNamesDataItemCounts); { - QStringList matrixResultNames = validKeywordsForPorosityModel(resultNames, resultNamesDataItemCounts, - m_eclipseCase->activeCellInfo(RiaDefines::MATRIX_MODEL), - m_eclipseCase->activeCellInfo(RiaDefines::FRACTURE_MODEL), - RiaDefines::MATRIX_MODEL, m_dynamicResultsAccess->timeStepCount()); + QStringList matrixResultNames = + validKeywordsForPorosityModel(resultNames, + resultNamesDataItemCounts, + m_eclipseCase->activeCellInfo(RiaDefines::MATRIX_MODEL), + m_eclipseCase->activeCellInfo(RiaDefines::FRACTURE_MODEL), + RiaDefines::MATRIX_MODEL, + m_dynamicResultsAccess->timeStepCount()); for (int i = 0; i < matrixResultNames.size(); ++i) { @@ -910,10 +937,13 @@ void RifReaderEclipseOutput::buildMetaData(ecl_grid_type* grid) } { - QStringList fractureResultNames = validKeywordsForPorosityModel(resultNames, resultNamesDataItemCounts, - m_eclipseCase->activeCellInfo(RiaDefines::MATRIX_MODEL), - m_eclipseCase->activeCellInfo(RiaDefines::FRACTURE_MODEL), - RiaDefines::FRACTURE_MODEL, m_dynamicResultsAccess->timeStepCount()); + QStringList fractureResultNames = + validKeywordsForPorosityModel(resultNames, + resultNamesDataItemCounts, + m_eclipseCase->activeCellInfo(RiaDefines::MATRIX_MODEL), + m_eclipseCase->activeCellInfo(RiaDefines::FRACTURE_MODEL), + RiaDefines::FRACTURE_MODEL, + m_dynamicResultsAccess->timeStepCount()); for (int i = 0; i < fractureResultNames.size(); ++i) { @@ -932,7 +962,7 @@ void RifReaderEclipseOutput::buildMetaData(ecl_grid_type* grid) { // Default units type is METRIC RiaEclipseUnitTools::UnitSystem unitsType = RiaEclipseUnitTools::UNITS_METRIC; - int unitsTypeValue; + int unitsTypeValue; if (m_dynamicResultsAccess.notNull()) { @@ -965,12 +995,13 @@ void RifReaderEclipseOutput::buildMetaData(ecl_grid_type* grid) if (m_ecl_init_file) { - QStringList resultNames; - std::vector resultNamesDataItemCounts; - std::vector< ecl_file_type* > filesUsedToFindAvailableKeywords; + QStringList resultNames; + std::vector resultNamesDataItemCounts; + std::vector filesUsedToFindAvailableKeywords; filesUsedToFindAvailableKeywords.push_back(m_ecl_init_file); - RifEclipseOutputFileTools::findKeywordsAndItemCount(filesUsedToFindAvailableKeywords, &resultNames, &resultNamesDataItemCounts); + RifEclipseOutputFileTools::findKeywordsAndItemCount( + filesUsedToFindAvailableKeywords, &resultNames, &resultNamesDataItemCounts); std::vector staticTimeStepInfo; if (!timeStepInfos.empty()) @@ -979,11 +1010,14 @@ void RifReaderEclipseOutput::buildMetaData(ecl_grid_type* grid) } { - QStringList matrixResultNames = validKeywordsForPorosityModel(resultNames, resultNamesDataItemCounts, - m_eclipseCase->activeCellInfo(RiaDefines::MATRIX_MODEL), - m_eclipseCase->activeCellInfo(RiaDefines::FRACTURE_MODEL), - RiaDefines::MATRIX_MODEL, 1); - + QStringList matrixResultNames = + validKeywordsForPorosityModel(resultNames, + resultNamesDataItemCounts, + m_eclipseCase->activeCellInfo(RiaDefines::MATRIX_MODEL), + m_eclipseCase->activeCellInfo(RiaDefines::FRACTURE_MODEL), + RiaDefines::MATRIX_MODEL, + 1); + // Add ACTNUM matrixResultNames += "ACTNUM"; @@ -996,10 +1030,13 @@ void RifReaderEclipseOutput::buildMetaData(ecl_grid_type* grid) } { - QStringList fractureResultNames = validKeywordsForPorosityModel(resultNames, resultNamesDataItemCounts, - m_eclipseCase->activeCellInfo(RiaDefines::MATRIX_MODEL), - m_eclipseCase->activeCellInfo(RiaDefines::FRACTURE_MODEL), - RiaDefines::FRACTURE_MODEL, 1); + QStringList fractureResultNames = + validKeywordsForPorosityModel(resultNames, + resultNamesDataItemCounts, + m_eclipseCase->activeCellInfo(RiaDefines::MATRIX_MODEL), + m_eclipseCase->activeCellInfo(RiaDefines::FRACTURE_MODEL), + RiaDefines::FRACTURE_MODEL, + 1); // Add ACTNUM fractureResultNames += "ACTNUM"; @@ -1027,7 +1064,9 @@ void RifReaderEclipseOutput::ensureDynamicResultAccessIsPresent() //-------------------------------------------------------------------------------------------------- /// Get all values of a given static result as doubles //-------------------------------------------------------------------------------------------------- -bool RifReaderEclipseOutput::staticResult(const QString& result, RiaDefines::PorosityModelType matrixOrFracture, std::vector* values) +bool RifReaderEclipseOutput::staticResult(const QString& result, + RiaDefines::PorosityModelType matrixOrFracture, + std::vector* values) { CVF_ASSERT(values); @@ -1041,7 +1080,7 @@ bool RifReaderEclipseOutput::staticResult(const QString& result, RiaDefines::Por openInitFile(); - if(m_ecl_init_file) + if (m_ecl_init_file) { std::vector fileValues; @@ -1061,19 +1100,19 @@ bool RifReaderEclipseOutput::staticResult(const QString& result, RiaDefines::Por } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- void RifReaderEclipseOutput::sourSimRlResult(const QString& result, size_t stepIndex, std::vector* values) { values->clear(); - if ( !m_hdfReaderInterface ) return; + if (!m_hdfReaderInterface) return; - if ( m_eclipseCase->mainGrid()->gridCount() == 0 ) + if (m_eclipseCase->mainGrid()->gridCount() == 0) { RiaLogging::error("No grids available"); - return ; + return; } size_t activeCellCount = cvf::UNDEFINED_SIZE_T; @@ -1095,7 +1134,7 @@ void RifReaderEclipseOutput::sourSimRlResult(const QString& result, size_t stepI } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- std::vector RifReaderEclipseOutput::allTimeSteps() const { @@ -1112,7 +1151,10 @@ std::vector RifReaderEclipseOutput::allTimeSteps() const //-------------------------------------------------------------------------------------------------- /// Get dynamic result at given step index. Will concatenate values for the main grid and all sub grids. //-------------------------------------------------------------------------------------------------- -bool RifReaderEclipseOutput::dynamicResult(const QString& result, RiaDefines::PorosityModelType matrixOrFracture, size_t stepIndex, std::vector* values) +bool RifReaderEclipseOutput::dynamicResult(const QString& result, + RiaDefines::PorosityModelType matrixOrFracture, + size_t stepIndex, + std::vector* values) { ensureDynamicResultAccessIsPresent(); @@ -1132,46 +1174,48 @@ bool RifReaderEclipseOutput::dynamicResult(const QString& result, RiaDefines::Po return true; } - //-------------------------------------------------------------------------------------------------- -/// Helper struct to store info on how a well-to-grid connection contributes to the position of +/// Helper struct to store info on how a well-to-grid connection contributes to the position of /// well segments without any connections. //-------------------------------------------------------------------------------------------------- struct SegmentPositionContribution { - SegmentPositionContribution( int connectionSegmentId, - cvf::Vec3d connectionPosition, - double lengthFromConnection, - bool isInsolating, - int segmentIdUnder, - int segmentIdAbove, - bool isFromAbove) - : m_connectionSegmentId(connectionSegmentId), - m_lengthFromConnection(lengthFromConnection), - m_isInsolating(isInsolating), - m_connectionPosition(connectionPosition), - m_segmentIdUnder(segmentIdUnder), - m_segmentIdAbove(segmentIdAbove), - m_isFromAbove(isFromAbove) - {} + SegmentPositionContribution(int connectionSegmentId, + cvf::Vec3d connectionPosition, + double lengthFromConnection, + bool isInsolating, + int segmentIdUnder, + int segmentIdAbove, + bool isFromAbove) + : m_connectionSegmentId(connectionSegmentId) + , m_lengthFromConnection(lengthFromConnection) + , m_isInsolating(isInsolating) + , m_connectionPosition(connectionPosition) + , m_segmentIdUnder(segmentIdUnder) + , m_segmentIdAbove(segmentIdAbove) + , m_isFromAbove(isFromAbove) + { + } - int m_connectionSegmentId; - double m_lengthFromConnection; - bool m_isInsolating; - cvf::Vec3d m_connectionPosition; - int m_segmentIdUnder; - int m_segmentIdAbove; - bool m_isFromAbove; + int m_connectionSegmentId; + double m_lengthFromConnection; + bool m_isInsolating; + cvf::Vec3d m_connectionPosition; + int m_segmentIdUnder; + int m_segmentIdAbove; + bool m_isFromAbove; }; -size_t localGridCellIndexFromErtConnection(const RigGridBase* grid, const well_conn_type* ert_connection, const char* wellNameForErrorMsgs ) +size_t localGridCellIndexFromErtConnection(const RigGridBase* grid, + const well_conn_type* ert_connection, + const char* wellNameForErrorMsgs) { CVF_ASSERT(ert_connection); CVF_ASSERT(grid); - int cellI = well_conn_get_i( ert_connection ); - int cellJ = well_conn_get_j( ert_connection ); - int cellK = well_conn_get_k( ert_connection ); + int cellI = well_conn_get_i(ert_connection); + int cellJ = well_conn_get_j(ert_connection); + int cellK = well_conn_get_k(ert_connection); // If a well is defined in fracture region, the K-value is from (cellCountK - 1) -> cellCountK*2 - 1 // Adjust K so index is always in valid grid region @@ -1196,12 +1240,13 @@ size_t localGridCellIndexFromErtConnection(const RigGridBase* grid, const well_c Undefined items in this array may be set to zero. */ - // The K value might also be -1. It is not yet known why, or what it is supposed to mean, + // The K value might also be -1. It is not yet known why, or what it is supposed to mean, // but for now we will interpret as 0. // TODO: Ask Joakim Haave regarding this. if (cellK < 0) { - //cvf::Trace::show("Well Connection for grid " + cvf::String(grid->gridName()) + "\n - Detected negative K value (K=" + cvf::String(cellK) + ") for well : " + cvf::String(wellName) + " K clamped to 0"); + // cvf::Trace::show("Well Connection for grid " + cvf::String(grid->gridName()) + "\n - Detected negative K value (K=" + + // cvf::String(cellK) + ") for well : " + cvf::String(wellName) + " K clamped to 0"); cellK = 0; } @@ -1212,48 +1257,54 @@ size_t localGridCellIndexFromErtConnection(const RigGridBase* grid, const well_c int maxCellK = static_cast(grid->cellCountK()); if (wellNameForErrorMsgs) { - cvf::Trace::show("Well Connection for grid " + cvf::String(grid->gridName()) + "\n - Ignored connection with invalid K value (K=" + cvf::String(cellK) + ", max K = " + cvf::String(maxCellK) + ") for well : " + cvf::String(wellNameForErrorMsgs)); + cvf::Trace::show("Well Connection for grid " + cvf::String(grid->gridName()) + + "\n - Ignored connection with invalid K value (K=" + cvf::String(cellK) + + ", max K = " + cvf::String(maxCellK) + ") for well : " + cvf::String(wellNameForErrorMsgs)); } return cvf::UNDEFINED_SIZE_T; } return grid->cellIndexFromIJK(cellI, cellJ, cellK); - } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- -RigWellResultPoint RifReaderEclipseOutput::createWellResultPoint(const RigGridBase* grid, const well_conn_type* ert_connection, int ertBranchId, int ertSegmentId, const char* wellName) +RigWellResultPoint RifReaderEclipseOutput::createWellResultPoint(const RigGridBase* grid, + const well_conn_type* ert_connection, + int ertBranchId, + int ertSegmentId, + const char* wellName) { CVF_ASSERT(ert_connection); CVF_ASSERT(grid); size_t gridCellIndex = localGridCellIndexFromErtConnection(grid, ert_connection, wellName); - bool isCellOpen = well_conn_open( ert_connection ); - double volumeRate = well_conn_get_volume_rate( ert_connection); - double oilRate = well_conn_get_oil_rate(ert_connection) ; - double gasRate = well_conn_get_gas_rate(ert_connection); - double waterRate = well_conn_get_water_rate(ert_connection); + bool isCellOpen = well_conn_open(ert_connection); + double volumeRate = well_conn_get_volume_rate(ert_connection); + double oilRate = well_conn_get_oil_rate(ert_connection); + double gasRate = well_conn_get_gas_rate(ert_connection); + double waterRate = well_conn_get_water_rate(ert_connection); double connectionFactor = well_conn_get_connection_factor(ert_connection); - + RigWellResultPoint resultPoint; if (gridCellIndex != cvf::UNDEFINED_SIZE_T) { - resultPoint.m_gridIndex = grid->gridIndex(); + resultPoint.m_gridIndex = grid->gridIndex(); resultPoint.m_gridCellIndex = gridCellIndex; resultPoint.m_isOpen = isCellOpen; - resultPoint.m_ertBranchId = ertBranchId; + resultPoint.m_ertBranchId = ertBranchId; resultPoint.m_ertSegmentId = ertSegmentId; - resultPoint.m_flowRate = volumeRate; - resultPoint.m_oilRate = oilRate; - resultPoint.m_waterRate = waterRate; - - resultPoint.m_gasRate = RiaEclipseUnitTools::convertSurfaceGasFlowRateToOilEquivalents(m_eclipseCase->unitsType(), gasRate); + resultPoint.m_flowRate = volumeRate; + resultPoint.m_oilRate = oilRate; + resultPoint.m_waterRate = waterRate; + + resultPoint.m_gasRate = + RiaEclipseUnitTools::convertSurfaceGasFlowRateToOilEquivalents(m_eclipseCase->unitsType(), gasRate); resultPoint.m_connectionFactor = connectionFactor; } @@ -1261,9 +1312,8 @@ RigWellResultPoint RifReaderEclipseOutput::createWellResultPoint(const RigGridBa return resultPoint; } - //-------------------------------------------------------------------------------------------------- -/// Inverse distance interpolation of the supplied points and distance weights for +/// Inverse distance interpolation of the supplied points and distance weights for /// the contributing points which are closest above, and closest below //-------------------------------------------------------------------------------------------------- cvf::Vec3d interpolate3DPosition(const std::vector& positions) @@ -1271,31 +1321,33 @@ cvf::Vec3d interpolate3DPosition(const std::vector& std::vector filteredPositions; filteredPositions.reserve(positions.size()); - double minDistFromContribAbove = HUGE_VAL; - double minDistFromContribBelow = HUGE_VAL; + double minDistFromContribAbove = HUGE_VAL; + double minDistFromContribBelow = HUGE_VAL; std::vector contrFromAbove; std::vector contrFromBelow; - for (size_t i = 0; i < positions.size(); i++) { if (positions[i].m_connectionPosition != cvf::Vec3d::UNDEFINED) { if (positions[i].m_isFromAbove && positions[i].m_lengthFromConnection < minDistFromContribAbove) { - if (contrFromAbove.size()) contrFromAbove[0] = positions[i]; - else contrFromAbove.push_back(positions[i]); + if (contrFromAbove.size()) + contrFromAbove[0] = positions[i]; + else + contrFromAbove.push_back(positions[i]); minDistFromContribAbove = positions[i].m_lengthFromConnection; } - if (! positions[i].m_isFromAbove && positions[i].m_lengthFromConnection < minDistFromContribBelow) + if (!positions[i].m_isFromAbove && positions[i].m_lengthFromConnection < minDistFromContribBelow) { - if (contrFromBelow.size()) contrFromBelow[0] = positions[i]; - else contrFromBelow.push_back(positions[i]); + if (contrFromBelow.size()) + contrFromBelow[0] = positions[i]; + else + contrFromBelow.push_back(positions[i]); minDistFromContribBelow = positions[i].m_lengthFromConnection; - } } } @@ -1305,7 +1357,7 @@ cvf::Vec3d interpolate3DPosition(const std::vector& std::vector nominators(filteredPositions.size(), 0.0); - double denominator = 0.0; + double denominator = 0.0; cvf::Vec3d interpolatedValue = cvf::Vec3d::ZERO; for (size_t i = 0; i < filteredPositions.size(); i++) @@ -1321,13 +1373,12 @@ cvf::Vec3d interpolate3DPosition(const std::vector& } else if (distance < 1.0) { - //distance = 1.0; + // distance = 1.0; } - - distance = 1.0 / distance; + distance = 1.0 / distance; nominators[i] = distance; - denominator += distance; + denominator += distance; #endif } @@ -1336,46 +1387,44 @@ cvf::Vec3d interpolate3DPosition(const std::vector& #endif for (size_t i = 0; i < filteredPositions.size(); i++) { - interpolatedValue += (nominators[i]/denominator) * filteredPositions[i].m_connectionPosition; + interpolatedValue += (nominators[i] / denominator) * filteredPositions[i].m_connectionPosition; } return interpolatedValue; } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- -void propagatePosContribDownwards(std::map > & segmentIdToPositionContrib, - const well_segment_collection_type * allErtSegments, - int ertSegmentId, - std::vector posContrib) +void propagatePosContribDownwards(std::map>& segmentIdToPositionContrib, + const well_segment_collection_type* allErtSegments, + int ertSegmentId, + std::vector posContrib) { - - std::map >::iterator posContribIt; + std::map>::iterator posContribIt; posContribIt = segmentIdToPositionContrib.find(ertSegmentId); - - if ( posContribIt != segmentIdToPositionContrib.end()) + if (posContribIt != segmentIdToPositionContrib.end()) { // Create a set of the segments below this, that has to be followed. std::set segmentIdsBelow; - for (size_t i = 0 ; i < posContribIt->second.size(); ++i) + for (size_t i = 0; i < posContribIt->second.size(); ++i) { segmentIdsBelow.insert(posContribIt->second[i].m_segmentIdUnder); } // Get the segment length to add to the contributions - well_segment_type *segment = well_segment_collection_get( allErtSegments , posContribIt->first); - double sementLength = well_segment_get_length(segment); + well_segment_type* segment = well_segment_collection_get(allErtSegments, posContribIt->first); + double sementLength = well_segment_get_length(segment); // If we do not have the contribution represented, add it, and accumulate the length // If it is already present, do not touch for (size_t i = 0; i < posContrib.size(); ++i) { bool foundContribution = false; - for (size_t j = 0 ; j < posContribIt->second.size(); ++j) + for (size_t j = 0; j < posContribIt->second.size(); ++j) { if (posContribIt->second[j].m_connectionSegmentId == posContrib[i].m_connectionSegmentId) { @@ -1384,7 +1433,7 @@ void propagatePosContribDownwards(std::map(m_mainGrid->gridCountOnFile()) - 1; - for ( int gridNr = lastGridNr; gridNr >= 0; --gridNr ) + for (int gridNr = lastGridNr; gridNr >= 0; --gridNr) { const well_conn_type* ert_wellhead = well_state_iget_wellhead(ert_well_state, static_cast(gridNr)); - if ( ert_wellhead ) + if (ert_wellhead) { - size_t localGridCellidx = localGridCellIndexFromErtConnection( m_mainGrid->gridByIndex(gridNr), ert_wellhead, nullptr); + size_t localGridCellidx = + localGridCellIndexFromErtConnection(m_mainGrid->gridByIndex(gridNr), ert_wellhead, nullptr); this->insertTheParentCells(gridNr, localGridCellidx); } - std::string gridname = gridNr == 0 ? ECL_GRID_GLOBAL_GRID: m_mainGrid->gridByIndex(gridNr)->gridName(); + std::string gridname = gridNr == 0 ? ECL_GRID_GLOBAL_GRID : m_mainGrid->gridByIndex(gridNr)->gridName(); const well_conn_collection_type* connections = well_state_get_grid_connections(ert_well_state, gridname.data()); - if ( connections ) + if (connections) { int connectionCount = well_conn_collection_get_size(connections); - if ( connectionCount ) + if (connectionCount) { - for ( int connIdx = 0; connIdx < connectionCount; connIdx++ ) + for (int connIdx = 0; connIdx < connectionCount; connIdx++) { well_conn_type* ert_connection = well_conn_collection_iget(connections, connIdx); - - size_t localGridCellidx = localGridCellIndexFromErtConnection( m_mainGrid->gridByIndex(gridNr), ert_connection, nullptr); + + size_t localGridCellidx = + localGridCellIndexFromErtConnection(m_mainGrid->gridByIndex(gridNr), ert_connection, nullptr); this->insertTheParentCells(gridNr, localGridCellidx); } } @@ -1445,12 +1497,12 @@ public: { if (!wellResultPoint.isCell()) return false; - size_t gridIndex = wellResultPoint.m_gridIndex; + size_t gridIndex = wellResultPoint.m_gridIndex; size_t gridCellIndex = wellResultPoint.m_gridCellIndex; - size_t reservoirCellIdx = m_mainGrid->reservoirCellIndexByGridAndGridLocalCellIndex(gridIndex, gridCellIndex); + size_t reservoirCellIdx = m_mainGrid->reservoirCellIndexByGridAndGridLocalCellIndex(gridIndex, gridCellIndex); - if ( m_gridCellsWithSubCellWellConnections.count(reservoirCellIdx) ) + if (m_gridCellsWithSubCellWellConnections.count(reservoirCellIdx)) { return true; } @@ -1461,28 +1513,27 @@ public: } private: - - void insertTheParentCells( size_t gridIndex, size_t gridCellIndex ) + void insertTheParentCells(size_t gridIndex, size_t gridCellIndex) { if (gridCellIndex == cvf::UNDEFINED_SIZE_T) return; // Traverse parent gridcells, and add them to the map - while ( gridIndex > 0 ) // is lgr + while (gridIndex > 0) // is lgr { const RigCell& connectionCell = m_mainGrid->cellByGridAndGridLocalCellIdx(gridIndex, gridCellIndex); - RigGridBase* hostGrid = connectionCell.hostGrid(); + RigGridBase* hostGrid = connectionCell.hostGrid(); - RigLocalGrid* lgrHost = static_cast (hostGrid); - gridIndex = lgrHost->parentGrid()->gridIndex(); - gridCellIndex = connectionCell.parentCellIndex(); + RigLocalGrid* lgrHost = static_cast(hostGrid); + gridIndex = lgrHost->parentGrid()->gridIndex(); + gridCellIndex = connectionCell.parentCellIndex(); - size_t parentReservoirCellIdx = m_mainGrid->reservoirCellIndexByGridAndGridLocalCellIndex(gridIndex, gridCellIndex); + size_t parentReservoirCellIdx = m_mainGrid->reservoirCellIndexByGridAndGridLocalCellIndex(gridIndex, gridCellIndex); m_gridCellsWithSubCellWellConnections.insert(parentReservoirCellIdx); } } - std::set m_gridCellsWithSubCellWellConnections; + std::set m_gridCellsWithSubCellWellConnections; const RigMainGrid* m_mainGrid; }; //-------------------------------------------------------------------------------------------------- @@ -1499,7 +1550,7 @@ void RifReaderEclipseOutput::readWellCells(const ecl_grid_type* mainEclGrid, boo m_dynamicResultsAccess->readWellData(ert_well_info, importCompleteMswData); - std::vector daysSinceSimulationStart; + std::vector daysSinceSimulationStart; std::vector timeSteps; m_dynamicResultsAccess->timeSteps(&timeSteps, &daysSinceSimulationStart); std::vector reportNumbers = m_dynamicResultsAccess->reportNumbers(); @@ -1514,7 +1565,7 @@ void RifReaderEclipseOutput::readWellCells(const ecl_grid_type* mainEclGrid, boo m_eclipseCase->allGrids(&grids); cvf::Collection wells; - caf::ProgressInfo progress(well_info_get_num_wells(ert_well_info), ""); + caf::ProgressInfo progress(well_info_get_num_wells(ert_well_info), ""); int wellIdx; for (wellIdx = 0; wellIdx < well_info_get_num_wells(ert_well_info); wellIdx++) @@ -1523,10 +1574,10 @@ void RifReaderEclipseOutput::readWellCells(const ecl_grid_type* mainEclGrid, boo CVF_ASSERT(wellName); cvf::ref simWellData = new RigSimWellData; - simWellData->m_wellName = wellName; + simWellData->m_wellName = wellName; - well_ts_type* ert_well_time_series = well_info_get_ts(ert_well_info , wellName); - int timeStepCount = well_ts_get_size(ert_well_time_series); + well_ts_type* ert_well_time_series = well_info_get_ts(ert_well_info, wellName); + int timeStepCount = well_ts_get_size(ert_well_time_series); simWellData->m_wellCellsTimeSteps.resize(timeStepCount); @@ -1539,7 +1590,7 @@ void RifReaderEclipseOutput::readWellCells(const ecl_grid_type* mainEclGrid, boo // Build timestamp for well bool haveFoundTimeStamp = false; - + if (sameCount) { int reportNr = well_state_get_report_nr(ert_well_state); @@ -1549,7 +1600,7 @@ void RifReaderEclipseOutput::readWellCells(const ecl_grid_type* mainEclGrid, boo if (reportNumbers[i] == reportNr) { wellResFrame.m_timestamp = timeSteps[i]; - haveFoundTimeStamp = true; + haveFoundTimeStamp = true; } } } @@ -1559,7 +1610,7 @@ void RifReaderEclipseOutput::readWellCells(const ecl_grid_type* mainEclGrid, boo // This fallback will not work for timesteps before 1970. // Also see RifEclipseOutputFileAccess::timeStepsText for accessing time_t structures - time_t stepTime = well_state_get_sim_time(ert_well_state); + time_t stepTime = well_state_get_sim_time(ert_well_state); wellResFrame.m_timestamp = QDateTime::fromTime_t(stepTime); } @@ -1586,16 +1637,15 @@ void RifReaderEclipseOutput::readWellCells(const ecl_grid_type* mainEclGrid, boo wellResFrame.m_productionType = RigWellResultFrame::UNDEFINED_PRODUCTION_TYPE; } - wellResFrame.m_isOpen = well_state_is_open( ert_well_state ); - + wellResFrame.m_isOpen = well_state_is_open(ert_well_state); if (importCompleteMswData && well_state_is_MSW(ert_well_state)) { simWellData->setMultiSegmentWell(true); - // how do we handle LGR-s ? + // how do we handle LGR-s ? // 1. Create separate visual branches for each Grid, with its own wellhead - // 2. Always use the connections to the grid with the highest number (innermost LGR). + // 2. Always use the connections to the grid with the highest number (innermost LGR). // 3. Handle both and switch between them according to visual settings of grid visualization // Will there ever exist connections to different grids for the same segment ? // We have currently selected 2. @@ -1605,7 +1655,7 @@ void RifReaderEclipseOutput::readWellCells(const ecl_grid_type* mainEclGrid, boo int lastGridNr = static_cast(grids.size()) - 1; for (int gridNr = lastGridNr; gridNr >= 0; --gridNr) { - // If several grids have a wellhead definition for this well, we use the last one. + // If several grids have a wellhead definition for this well, we use the last one. // (Possibly the innermost LGR) const well_conn_type* ert_wellhead = well_state_iget_wellhead(ert_well_state, static_cast(gridNr)); @@ -1613,42 +1663,41 @@ void RifReaderEclipseOutput::readWellCells(const ecl_grid_type* mainEclGrid, boo { wellResFrame.m_wellHead = createWellResultPoint(grids[gridNr], ert_wellhead, -1, -1, wellName); - // HACK: Ert returns open as "this is equally wrong as closed for well heads". + // HACK: Ert returns open as "this is equally wrong as closed for well heads". // Well heads are not open jfr mail communication with HHGS and JH Statoil 07.01.2016 - wellResFrame.m_wellHead.m_isOpen = false; + wellResFrame.m_wellHead.m_isOpen = false; break; } } - well_branch_collection_type* branches = well_state_get_branches(ert_well_state); - int branchCount = well_branch_collection_get_size(branches); - wellResFrame.m_wellResultBranches.resize( branchCount); - std::map > segmentIdToPositionContrib; - std::vector upperSegmentIdsOfUnpositionedSegementGroup; + well_branch_collection_type* branches = well_state_get_branches(ert_well_state); + int branchCount = well_branch_collection_get_size(branches); + wellResFrame.m_wellResultBranches.resize(branchCount); + std::map> segmentIdToPositionContrib; + std::vector upperSegmentIdsOfUnpositionedSegementGroup; // For each branch, go from bottom segment upwards and transfer their connections to WellResultpoints. - // If they have no connections, create a resultpoint representing their bottom position, which will + // If they have no connections, create a resultpoint representing their bottom position, which will // receive an actual position at a later stage. // I addition, distribute contributions for calculating segment bottom positions from bottom and up. - for (int bIdx = 0; bIdx < well_branch_collection_get_size(branches); bIdx++) { - RigWellResultBranch& wellResultBranch = wellResFrame.m_wellResultBranches[ bIdx]; + RigWellResultBranch& wellResultBranch = wellResFrame.m_wellResultBranches[bIdx]; const well_segment_type* segment = well_branch_collection_iget_start_segment(branches, bIdx); - int branchId = well_segment_get_branch_id(segment); + int branchId = well_segment_get_branch_id(segment); wellResultBranch.m_ertBranchId = branchId; // Data for segment position calculation - int lastConnectionSegmentId = -1; - cvf::Vec3d lastConnectionPos = cvf::Vec3d::UNDEFINED; - cvf::Vec3d lastConnectionCellCorner= cvf::Vec3d::UNDEFINED; - double lastConnectionCellSize = 0; - double accLengthFromLastConnection = 0; - int segmentIdBelow = -1; - bool segmentBelowHasConnections = false; + int lastConnectionSegmentId = -1; + cvf::Vec3d lastConnectionPos = cvf::Vec3d::UNDEFINED; + cvf::Vec3d lastConnectionCellCorner = cvf::Vec3d::UNDEFINED; + double lastConnectionCellSize = 0; + double accLengthFromLastConnection = 0; + int segmentIdBelow = -1; + bool segmentBelowHasConnections = false; while (segment && branchId == well_segment_get_branch_id(segment)) { @@ -1663,45 +1712,48 @@ void RifReaderEclipseOutput::readWellCells(const ecl_grid_type* mainEclGrid, boo if (well_segment_has_grid_connections(segment, gridName.data())) { - const well_conn_collection_type* connections = well_segment_get_connections(segment, gridName.data()); + const well_conn_collection_type* connections = + well_segment_get_connections(segment, gridName.data()); int connectionCount = well_conn_collection_get_size(connections); - // Loop backwards to put the deepest connections first in the array. (The segments are also traversed deep to shallow) - for (int connIdx = connectionCount-1; connIdx >= 0; connIdx--) + // Loop backwards to put the deepest connections first in the array. (The segments are also + // traversed deep to shallow) + for (int connIdx = connectionCount - 1; connIdx >= 0; connIdx--) { well_conn_type* ert_connection = well_conn_collection_iget(connections, connIdx); - wellResultBranch.m_branchResultPoints.push_back( - createWellResultPoint(grids[gridNr], ert_connection, branchId, well_segment_get_id(segment), wellName)); + wellResultBranch.m_branchResultPoints.push_back(createWellResultPoint( + grids[gridNr], ert_connection, branchId, well_segment_get_id(segment), wellName)); } segmentHasConnections = true; // Prepare data for segment position calculation - well_conn_type* ert_connection = well_conn_collection_iget(connections, 0); - RigWellResultPoint point = createWellResultPoint(grids[gridNr], ert_connection, branchId, well_segment_get_id(segment), wellName); - lastConnectionPos = grids[gridNr]->cell(point.m_gridCellIndex).center(); + well_conn_type* ert_connection = well_conn_collection_iget(connections, 0); + RigWellResultPoint point = createWellResultPoint( + grids[gridNr], ert_connection, branchId, well_segment_get_id(segment), wellName); + lastConnectionPos = grids[gridNr]->cell(point.m_gridCellIndex).center(); cvf::Vec3d cellVxes[8]; grids[gridNr]->cellCornerVertices(point.m_gridCellIndex, cellVxes); - lastConnectionCellCorner = cellVxes[0]; - lastConnectionCellSize = (lastConnectionPos - cellVxes[0]).length(); + lastConnectionCellCorner = cellVxes[0]; + lastConnectionCellSize = (lastConnectionPos - cellVxes[0]).length(); - - lastConnectionSegmentId = well_segment_get_id(segment); - accLengthFromLastConnection = well_segment_get_length(segment)/(connectionCount+1); - if ( ! segmentBelowHasConnections) upperSegmentIdsOfUnpositionedSegementGroup.push_back(segmentIdBelow); + lastConnectionSegmentId = well_segment_get_id(segment); + accLengthFromLastConnection = well_segment_get_length(segment) / (connectionCount + 1); + if (!segmentBelowHasConnections) + upperSegmentIdsOfUnpositionedSegementGroup.push_back(segmentIdBelow); break; // Stop looping over grids } } - - // If the segment did not have connections at all, we need to create a resultpoint representing the bottom of the segment - // and store it as an unpositioned segment + + // If the segment did not have connections at all, we need to create a resultpoint representing the bottom + // of the segment and store it as an unpositioned segment if (!segmentHasConnections) { RigWellResultPoint data; - data.m_ertBranchId = branchId; + data.m_ertBranchId = branchId; data.m_ertSegmentId = well_segment_get_id(segment); wellResultBranch.m_branchResultPoints.push_back(data); @@ -1709,14 +1761,18 @@ void RifReaderEclipseOutput::readWellCells(const ecl_grid_type* mainEclGrid, boo // Store data for segment position calculation bool isAnInsolationContribution = accLengthFromLastConnection < lastConnectionCellSize; - - segmentIdToPositionContrib[well_segment_get_id(segment)].push_back( - SegmentPositionContribution(lastConnectionSegmentId, lastConnectionPos, accLengthFromLastConnection, isAnInsolationContribution, segmentIdBelow, -1, false)); + segmentIdToPositionContrib[well_segment_get_id(segment)].push_back( + SegmentPositionContribution(lastConnectionSegmentId, + lastConnectionPos, + accLengthFromLastConnection, + isAnInsolationContribution, + segmentIdBelow, + -1, + false)); accLengthFromLastConnection += well_segment_get_length(segment); - } - segmentIdBelow = well_segment_get_id(segment); + segmentIdBelow = well_segment_get_id(segment); segmentBelowHasConnections = segmentHasConnections; if (well_segment_get_outlet_id(segment) == -1) @@ -1745,13 +1801,14 @@ void RifReaderEclipseOutput::readWellCells(const ecl_grid_type* mainEclGrid, boo if (well_segment_has_grid_connections(outletSegment, gridName.data())) { - const well_conn_collection_type* connections = well_segment_get_connections(outletSegment, gridName.data()); + const well_conn_collection_type* connections = + well_segment_get_connections(outletSegment, gridName.data()); int connectionCount = well_conn_collection_get_size(connections); - // Select the deepest connection - well_conn_type* ert_connection = well_conn_collection_iget(connections, connectionCount-1); - wellResultBranch.m_branchResultPoints.push_back( - createWellResultPoint(grids[gridNr], ert_connection, branchId, well_segment_get_id(outletSegment), wellName)); + // Select the deepest connection + well_conn_type* ert_connection = well_conn_collection_iget(connections, connectionCount - 1); + wellResultBranch.m_branchResultPoints.push_back(createWellResultPoint( + grids[gridNr], ert_connection, branchId, well_segment_get_id(outletSegment), wellName)); outletSegmentHasConnections = true; break; // Stop looping over grids @@ -1763,20 +1820,27 @@ void RifReaderEclipseOutput::readWellCells(const ecl_grid_type* mainEclGrid, boo // Store the result point RigWellResultPoint data; - data.m_ertBranchId = well_segment_get_branch_id(outletSegment); + data.m_ertBranchId = well_segment_get_branch_id(outletSegment); data.m_ertSegmentId = well_segment_get_id(outletSegment); wellResultBranch.m_branchResultPoints.push_back(data); - // Store data for segment position calculation, + // Store data for segment position calculation, // and propagate it upwards until we meet a segment with connections bool isAnInsolationContribution = accLengthFromLastConnection < lastConnectionCellSize; cvf::Vec3d lastConnectionPosWOffset = lastConnectionPos; - if (isAnInsolationContribution) lastConnectionPosWOffset += 0.4*(lastConnectionCellCorner-lastConnectionPos); + if (isAnInsolationContribution) + lastConnectionPosWOffset += 0.4 * (lastConnectionCellCorner - lastConnectionPos); - segmentIdToPositionContrib[well_segment_get_id(outletSegment)].push_back( - SegmentPositionContribution(lastConnectionSegmentId, lastConnectionPosWOffset, accLengthFromLastConnection, isAnInsolationContribution, segmentIdBelow, -1, false)); + segmentIdToPositionContrib[well_segment_get_id(outletSegment)].push_back( + SegmentPositionContribution(lastConnectionSegmentId, + lastConnectionPosWOffset, + accLengthFromLastConnection, + isAnInsolationContribution, + segmentIdBelow, + -1, + false)); /// Loop further to add this position contribution until a segment with connections is found @@ -1794,7 +1858,7 @@ void RifReaderEclipseOutput::readWellCells(const ecl_grid_type* mainEclGrid, boo aboveOutletSegment = well_segment_get_outlet(outletSegment); } - while (aboveOutletSegment ) + while (aboveOutletSegment) { // Loop backwards, just because we do that the other places bool segmentHasConnections = false; @@ -1814,13 +1878,20 @@ void RifReaderEclipseOutput::readWellCells(const ecl_grid_type* mainEclGrid, boo if (!segmentHasConnections) { - segmentIdToPositionContrib[well_segment_get_id(aboveOutletSegment)].push_back( - SegmentPositionContribution(lastConnectionSegmentId, lastConnectionPos, accLengthFromLastConnection, isAnInsolationContribution, segmentIdBelow, -1, false)); + segmentIdToPositionContrib[well_segment_get_id(aboveOutletSegment)].push_back( + SegmentPositionContribution(lastConnectionSegmentId, + lastConnectionPos, + accLengthFromLastConnection, + isAnInsolationContribution, + segmentIdBelow, + -1, + false)); accLengthFromLastConnection += well_segment_get_length(aboveOutletSegment); } else { - break; // We have found a segment with connections. We do not need to propagate position contributions further + break; // We have found a segment with connections. We do not need to propagate position + // contributions further } segmentIdBelow = well_segment_get_id(aboveOutletSegment); @@ -1834,13 +1905,11 @@ void RifReaderEclipseOutput::readWellCells(const ecl_grid_type* mainEclGrid, boo aboveOutletSegment = well_segment_get_outlet(aboveOutletSegment); } } - - } } else { - // Add wellhead as result point Nope. Not Yet, but it is a good idea. + // Add wellhead as result point Nope. Not Yet, but it is a good idea. // The centerline calculations would be a bit simpler, I think. } @@ -1849,16 +1918,15 @@ void RifReaderEclipseOutput::readWellCells(const ecl_grid_type* mainEclGrid, boo std::reverse(wellResultBranch.m_branchResultPoints.begin(), wellResultBranch.m_branchResultPoints.end()); } // End of the branch loop - // Propagate position contributions from connections above unpositioned segments downwards - well_segment_collection_type * allErtSegments = well_state_get_segments( ert_well_state ); + well_segment_collection_type* allErtSegments = well_state_get_segments(ert_well_state); - for (size_t bIdx = 0; bIdx < wellResFrame.m_wellResultBranches.size(); ++bIdx) + for (size_t bIdx = 0; bIdx < wellResFrame.m_wellResultBranches.size(); ++bIdx) { - RigWellResultBranch& wellResultBranch = wellResFrame.m_wellResultBranches[ bIdx]; - bool previousResultPointWasCell = false; - if (bIdx == 0) previousResultPointWasCell = true; // Wellhead + RigWellResultBranch& wellResultBranch = wellResFrame.m_wellResultBranches[bIdx]; + bool previousResultPointWasCell = false; + if (bIdx == 0) previousResultPointWasCell = true; // Wellhead // Go downwards until we find a none-cell resultpoint just after a cell-resultpoint // When we do, start propagating @@ -1866,7 +1934,7 @@ void RifReaderEclipseOutput::readWellCells(const ecl_grid_type* mainEclGrid, boo for (size_t rpIdx = 0; rpIdx < wellResultBranch.m_branchResultPoints.size(); ++rpIdx) { RigWellResultPoint resPoint = wellResultBranch.m_branchResultPoints[rpIdx]; - if ( resPoint.isCell() ) + if (resPoint.isCell()) { previousResultPointWasCell = true; } @@ -1877,31 +1945,39 @@ void RifReaderEclipseOutput::readWellCells(const ecl_grid_type* mainEclGrid, boo RigWellResultPoint prevResPoint; if (bIdx == 0 && rpIdx == 0) { - prevResPoint = wellResFrame.m_wellHead; + prevResPoint = wellResFrame.m_wellHead; } else { - prevResPoint = wellResultBranch.m_branchResultPoints[rpIdx - 1 ]; + prevResPoint = wellResultBranch.m_branchResultPoints[rpIdx - 1]; } - cvf::Vec3d lastConnectionPos = grids[prevResPoint.m_gridIndex]->cell(prevResPoint.m_gridCellIndex).center(); + cvf::Vec3d lastConnectionPos = + grids[prevResPoint.m_gridIndex]->cell(prevResPoint.m_gridCellIndex).center(); - SegmentPositionContribution posContrib(prevResPoint.m_ertSegmentId, lastConnectionPos, 0.0, false, -1, prevResPoint.m_ertSegmentId, true); + SegmentPositionContribution posContrib(prevResPoint.m_ertSegmentId, + lastConnectionPos, + 0.0, + false, + -1, + prevResPoint.m_ertSegmentId, + true); int ertSegmentId = resPoint.m_ertSegmentId; - std::map >::iterator posContribIt; + std::map>::iterator posContribIt; posContribIt = segmentIdToPositionContrib.find(ertSegmentId); CVF_ASSERT(posContribIt != segmentIdToPositionContrib.end()); - std::vector posContributions = posContribIt->second; + std::vector posContributions = posContribIt->second; for (size_t i = 0; i < posContributions.size(); ++i) { posContributions[i].m_segmentIdAbove = prevResPoint.m_ertSegmentId; } posContributions.push_back(posContrib); - propagatePosContribDownwards(segmentIdToPositionContrib, allErtSegments, ertSegmentId, posContributions); + propagatePosContribDownwards( + segmentIdToPositionContrib, allErtSegments, ertSegmentId, posContributions); } previousResultPointWasCell = false; @@ -1912,7 +1988,8 @@ void RifReaderEclipseOutput::readWellCells(const ecl_grid_type* mainEclGrid, boo // Calculate the bottom position of all the unpositioned segments // Then do the calculation based on the refined contributions - std::map >::iterator posContribIt = segmentIdToPositionContrib.begin(); + std::map>::iterator posContribIt = + segmentIdToPositionContrib.begin(); std::map bottomPositions; while (posContribIt != segmentIdToPositionContrib.end()) { @@ -1922,13 +1999,13 @@ void RifReaderEclipseOutput::readWellCells(const ecl_grid_type* mainEclGrid, boo // Distribute the positions to the resultpoints stored in the wellResultBranch.m_branchResultPoints - for (size_t bIdx = 0; bIdx < wellResFrame.m_wellResultBranches.size(); ++bIdx) + for (size_t bIdx = 0; bIdx < wellResFrame.m_wellResultBranches.size(); ++bIdx) { - RigWellResultBranch& wellResultBranch = wellResFrame.m_wellResultBranches[ bIdx]; + RigWellResultBranch& wellResultBranch = wellResFrame.m_wellResultBranches[bIdx]; for (size_t rpIdx = 0; rpIdx < wellResultBranch.m_branchResultPoints.size(); ++rpIdx) { - RigWellResultPoint & resPoint = wellResultBranch.m_branchResultPoints[rpIdx]; - if ( ! resPoint.isCell() ) + RigWellResultPoint& resPoint = wellResultBranch.m_branchResultPoints[rpIdx]; + if (!resPoint.isCell()) { resPoint.m_bottomPosition = bottomPositions[resPoint.m_ertSegmentId]; } @@ -1941,27 +2018,28 @@ void RifReaderEclipseOutput::readWellCells(const ecl_grid_type* mainEclGrid, boo // Code handling None-MSW Wells ... Normal wells that is. WellResultPointHasSubCellConnectionCalculator subCellConnCalc(m_eclipseCase->mainGrid(), ert_well_state); - int lastGridNr = static_cast(grids.size()) - 1; - for ( int gridNr = 0; gridNr <= lastGridNr; ++gridNr ) + int lastGridNr = static_cast(grids.size()) - 1; + for (int gridNr = 0; gridNr <= lastGridNr; ++gridNr) { const well_conn_type* ert_wellhead = well_state_iget_wellhead(ert_well_state, static_cast(gridNr)); - if ( ert_wellhead ) + if (ert_wellhead) { RigWellResultPoint wellHeadRp = createWellResultPoint(grids[gridNr], ert_wellhead, -1, -1, wellName); - // HACK: Ert returns open as "this is equally wrong as closed for well heads". + // HACK: Ert returns open as "this is equally wrong as closed for well heads". // Well heads are not open jfr mail communication with HHGS and JH Statoil 07.01.2016 wellHeadRp.m_isOpen = false; - if (!subCellConnCalc.hasSubCellConnection(wellHeadRp)) wellResFrame.m_wellHead = wellHeadRp; + if (!subCellConnCalc.hasSubCellConnection(wellHeadRp)) wellResFrame.m_wellHead = wellHeadRp; } - const well_conn_collection_type* connections = well_state_get_grid_connections(ert_well_state, this->ertGridName(gridNr).data()); + const well_conn_collection_type* connections = + well_state_get_grid_connections(ert_well_state, this->ertGridName(gridNr).data()); // Import all well result cells for all connections - if ( connections ) + if (connections) { int connectionCount = well_conn_collection_get_size(connections); - if ( connectionCount ) + if (connectionCount) { wellResFrame.m_wellResultBranches.push_back(RigWellResultBranch()); RigWellResultBranch& wellResultBranch = wellResFrame.m_wellResultBranches.back(); @@ -1971,13 +2049,15 @@ void RifReaderEclipseOutput::readWellCells(const ecl_grid_type* mainEclGrid, boo size_t existingCellCount = wellResultBranch.m_branchResultPoints.size(); wellResultBranch.m_branchResultPoints.resize(existingCellCount + connectionCount); - for ( int connIdx = 0; connIdx < connectionCount; connIdx++ ) + for (int connIdx = 0; connIdx < connectionCount; connIdx++) { - well_conn_type* ert_connection = well_conn_collection_iget(connections, connIdx); - RigWellResultPoint wellRp = createWellResultPoint(grids[gridNr], ert_connection, -1, -1, wellName); + well_conn_type* ert_connection = well_conn_collection_iget(connections, connIdx); + RigWellResultPoint wellRp = + createWellResultPoint(grids[gridNr], ert_connection, -1, -1, wellName); - if (!subCellConnCalc.hasSubCellConnection(wellRp)){ - wellResultBranch.m_branchResultPoints[existingCellCount + connIdx] = wellRp; + if (!subCellConnCalc.hasSubCellConnection(wellRp)) + { + wellResultBranch.m_branchResultPoints[existingCellCount + connIdx] = wellRp; } } } @@ -1986,7 +2066,6 @@ void RifReaderEclipseOutput::readWellCells(const ecl_grid_type* mainEclGrid, boo } } - std::vector filteredTimeSteps; { std::vector filteredTimeStepInfos = createFilteredTimeStepInfos(); @@ -2008,16 +2087,15 @@ void RifReaderEclipseOutput::readWellCells(const ecl_grid_type* mainEclGrid, boo m_eclipseCase->setSimWellData(wells); } - //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- -QStringList RifReaderEclipseOutput::validKeywordsForPorosityModel(const QStringList& keywords, - const std::vector& keywordDataItemCounts, - const RigActiveCellInfo* matrixActiveCellInfo, - const RigActiveCellInfo* fractureActiveCellInfo, - RiaDefines::PorosityModelType porosityModel, - size_t timeStepCount) const +QStringList RifReaderEclipseOutput::validKeywordsForPorosityModel(const QStringList& keywords, + const std::vector& keywordDataItemCounts, + const RigActiveCellInfo* matrixActiveCellInfo, + const RigActiveCellInfo* fractureActiveCellInfo, + RiaDefines::PorosityModelType porosityModel, + size_t timeStepCount) const { CVF_ASSERT(matrixActiveCellInfo); @@ -2035,11 +2113,11 @@ QStringList RifReaderEclipseOutput::validKeywordsForPorosityModel(const QStringL } QStringList keywordsWithCorrectNumberOfDataItems; - + for (int i = 0; i < keywords.size(); i++) { - QString keyword = keywords[i]; - size_t keywordDataItemCount = keywordDataItemCounts[i]; + QString keyword = keywords[i]; + size_t keywordDataItemCount = keywordDataItemCounts[i]; bool validKeyword = false; @@ -2049,7 +2127,7 @@ QStringList RifReaderEclipseOutput::validKeywordsForPorosityModel(const QStringL // Found result for all cells for N time steps, usually a static dataset for one time step validKeyword = true; } - else + else { size_t timeStepsMatrixRest = keywordDataItemCount % matrixActiveCellInfo->reservoirActiveCellCount(); @@ -2059,19 +2137,23 @@ QStringList RifReaderEclipseOutput::validKeywordsForPorosityModel(const QStringL timeStepsFractureRest = keywordDataItemCount % fractureActiveCellInfo->reservoirActiveCellCount(); } - size_t sumFractureMatrixActiveCellCount = matrixActiveCellInfo->reservoirActiveCellCount() + fractureActiveCellInfo->reservoirActiveCellCount(); + size_t sumFractureMatrixActiveCellCount = + matrixActiveCellInfo->reservoirActiveCellCount() + fractureActiveCellInfo->reservoirActiveCellCount(); size_t timeStepsMatrixAndFractureRest = keywordDataItemCount % sumFractureMatrixActiveCellCount; if (porosityModel == RiaDefines::MATRIX_MODEL && timeStepsMatrixRest == 0) { - if (keywordDataItemCount <= timeStepCount * std::max(matrixActiveCellInfo->reservoirActiveCellCount(), sumFractureMatrixActiveCellCount)) + if (keywordDataItemCount <= + timeStepCount * std::max(matrixActiveCellInfo->reservoirActiveCellCount(), sumFractureMatrixActiveCellCount)) { validKeyword = true; } } - else if (porosityModel == RiaDefines::FRACTURE_MODEL && fractureActiveCellInfo->reservoirActiveCellCount() > 0 && timeStepsFractureRest == 0) + else if (porosityModel == RiaDefines::FRACTURE_MODEL && fractureActiveCellInfo->reservoirActiveCellCount() > 0 && + timeStepsFractureRest == 0) { - if (keywordDataItemCount <= timeStepCount * std::max(fractureActiveCellInfo->reservoirActiveCellCount(), sumFractureMatrixActiveCellCount)) + if (keywordDataItemCount <= timeStepCount * std::max(fractureActiveCellInfo->reservoirActiveCellCount(), + sumFractureMatrixActiveCellCount)) { validKeyword = true; } @@ -2090,12 +2172,14 @@ QStringList RifReaderEclipseOutput::validKeywordsForPorosityModel(const QStringL { if (timeStepCount == 1) { - size_t mainGridMatrixActiveCellCount; matrixActiveCellInfo->gridActiveCellCounts(0, mainGridMatrixActiveCellCount); - size_t mainGridFractureActiveCellCount; fractureActiveCellInfo->gridActiveCellCounts(0, mainGridFractureActiveCellCount); + size_t mainGridMatrixActiveCellCount; + matrixActiveCellInfo->gridActiveCellCounts(0, mainGridMatrixActiveCellCount); + size_t mainGridFractureActiveCellCount; + fractureActiveCellInfo->gridActiveCellCounts(0, mainGridFractureActiveCellCount); - if ( keywordDataItemCount == mainGridMatrixActiveCellCount - || keywordDataItemCount == mainGridFractureActiveCellCount - || keywordDataItemCount == mainGridMatrixActiveCellCount + mainGridFractureActiveCellCount ) + if (keywordDataItemCount == mainGridMatrixActiveCellCount || + keywordDataItemCount == mainGridFractureActiveCellCount || + keywordDataItemCount == mainGridMatrixActiveCellCount + mainGridFractureActiveCellCount) { validKeyword = true; } @@ -2111,9 +2195,8 @@ QStringList RifReaderEclipseOutput::validKeywordsForPorosityModel(const QStringL return keywordsWithCorrectNumberOfDataItems; } - //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- std::vector RifReaderEclipseOutput::createFilteredTimeStepInfos() { @@ -2122,8 +2205,8 @@ std::vector RifReaderEclipseOutput::createFilteredTimeSt if (m_dynamicResultsAccess.notNull()) { std::vector timeStepsOnFile; - std::vector daysSinceSimulationStartOnFile; - std::vector reportNumbersOnFile; + std::vector daysSinceSimulationStartOnFile; + std::vector reportNumbersOnFile; m_dynamicResultsAccess->timeSteps(&timeStepsOnFile, &daysSinceSimulationStartOnFile); reportNumbersOnFile = m_dynamicResultsAccess->reportNumbers(); @@ -2135,7 +2218,8 @@ std::vector RifReaderEclipseOutput::createFilteredTimeSt { if (this->isTimeStepIncludedByFilter(i)) { - timeStepInfos.push_back(RigEclipseTimeStepInfo(timeStepsOnFile[i], reportNumbersOnFile[i], daysSinceSimulationStartOnFile[i])); + timeStepInfos.push_back( + RigEclipseTimeStepInfo(timeStepsOnFile[i], reportNumbersOnFile[i], daysSinceSimulationStartOnFile[i])); } } } @@ -2144,14 +2228,14 @@ std::vector RifReaderEclipseOutput::createFilteredTimeSt } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- bool RifReaderEclipseOutput::isEclipseAndSoursimTimeStepsEqual(const QDateTime& eclipseDateTime, const QDateTime& sourSimDateTime) { // Compare date down to and including seconds // Compare of complete date time objects will often result in differences - const int secondsThreshold = 4; + const int secondsThreshold = 4; const QString dateStr("yyyy.MMM.dd hh:mm:ss:zzz"); int secondsDiff = eclipseDateTime.secsTo(sourSimDateTime); @@ -2176,7 +2260,7 @@ bool RifReaderEclipseOutput::isEclipseAndSoursimTimeStepsEqual(const QDateTime& } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- ecl_grid_type* RifReaderEclipseOutput::loadMainGrid() const { @@ -2191,7 +2275,8 @@ ecl_grid_type* RifReaderEclipseOutput::loadMainGrid() const int* actnum_values = ecl_kw_get_int_ptr(actnumFromPorv); if (actnum_values) { - mainEclGrid = ecl_grid_alloc_ext_actnum(RiaStringEncodingTools::toNativeEncoded(m_fileName).data(), actnum_values); + mainEclGrid = + ecl_grid_alloc_ext_actnum(RiaStringEncodingTools::toNativeEncoded(m_fileName).data(), actnum_values); } ecl_kw_free(actnumFromPorv); @@ -2208,13 +2293,15 @@ ecl_grid_type* RifReaderEclipseOutput::loadMainGrid() const } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- -void RifReaderEclipseOutput::extractResultValuesBasedOnPorosityModel(RiaDefines::PorosityModelType matrixOrFracture, std::vector* destinationResultValues, const std::vector& sourceResultValues) +void RifReaderEclipseOutput::extractResultValuesBasedOnPorosityModel(RiaDefines::PorosityModelType matrixOrFracture, + std::vector* destinationResultValues, + const std::vector& sourceResultValues) { if (sourceResultValues.size() == 0) return; - RigActiveCellInfo* fracActCellInfo = m_eclipseCase->activeCellInfo(RiaDefines::FRACTURE_MODEL); + RigActiveCellInfo* fracActCellInfo = m_eclipseCase->activeCellInfo(RiaDefines::FRACTURE_MODEL); if (matrixOrFracture == RiaDefines::MATRIX_MODEL && fracActCellInfo->reservoirActiveCellCount() == 0) { @@ -2222,25 +2309,24 @@ void RifReaderEclipseOutput::extractResultValuesBasedOnPorosityModel(RiaDefines: } else { - RigActiveCellInfo* actCellInfo = m_eclipseCase->activeCellInfo(RiaDefines::MATRIX_MODEL); + RigActiveCellInfo* actCellInfo = m_eclipseCase->activeCellInfo(RiaDefines::MATRIX_MODEL); size_t sourceStartPosition = 0; for (size_t i = 0; i < m_eclipseCase->mainGrid()->gridCount(); i++) { - if(m_eclipseCase->mainGrid()->gridByIndex(i)->isTempGrid()) continue; + if (m_eclipseCase->mainGrid()->gridByIndex(i)->isTempGrid()) continue; - size_t matrixActiveCellCount = 0; + size_t matrixActiveCellCount = 0; size_t fractureActiveCellCount = 0; - + actCellInfo->gridActiveCellCounts(i, matrixActiveCellCount); fracActCellInfo->gridActiveCellCounts(i, fractureActiveCellCount); - if (matrixOrFracture == RiaDefines::MATRIX_MODEL) { - destinationResultValues->insert(destinationResultValues->end(), - sourceResultValues.begin() + sourceStartPosition, + destinationResultValues->insert(destinationResultValues->end(), + sourceResultValues.begin() + sourceStartPosition, sourceResultValues.begin() + sourceStartPosition + matrixActiveCellCount); } else @@ -2263,7 +2349,7 @@ void RifReaderEclipseOutput::extractResultValuesBasedOnPorosityModel(RiaDefines: } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- void RifReaderEclipseOutput::openInitFile() { @@ -2280,7 +2366,7 @@ void RifReaderEclipseOutput::openInitFile() } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- void RifReaderEclipseOutput::transferCoarseningInfo(const ecl_grid_type* eclGrid, RigGridBase* grid) { @@ -2302,7 +2388,7 @@ void RifReaderEclipseOutput::transferCoarseningInfo(const ecl_grid_type* eclGrid } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- std::set RifReaderEclipseOutput::availablePhases() const { @@ -2315,7 +2401,7 @@ std::set RifReaderEclipseOutput::availablePhases() const } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- std::string RifReaderEclipseOutput::ertGridName(size_t gridNr) { @@ -2333,4 +2419,3 @@ std::string RifReaderEclipseOutput::ertGridName(size_t gridNr) return gridName; } - From ada2fb1480ca825febe96e4cc5b55f2703808216 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 19 Jun 2019 13:36:33 +0200 Subject: [PATCH 187/396] #4495 Active Cells : Add helper class to import active cells --- .../FileInterface/CMakeLists_files.cmake | 3 + .../FileInterface/RifActiveCellsReader.cpp | 93 ++++++++++++++ .../FileInterface/RifActiveCellsReader.h | 38 ++++++ .../UnitTests/CMakeLists_files.cmake | 1 + .../UnitTests/RifActiveCellsReader-Test.cpp | 119 ++++++++++++++++++ 5 files changed, 254 insertions(+) create mode 100644 ApplicationCode/FileInterface/RifActiveCellsReader.cpp create mode 100644 ApplicationCode/FileInterface/RifActiveCellsReader.h create mode 100644 ApplicationCode/UnitTests/RifActiveCellsReader-Test.cpp diff --git a/ApplicationCode/FileInterface/CMakeLists_files.cmake b/ApplicationCode/FileInterface/CMakeLists_files.cmake index c2a01d4dce..b8ea98a084 100644 --- a/ApplicationCode/FileInterface/CMakeLists_files.cmake +++ b/ApplicationCode/FileInterface/CMakeLists_files.cmake @@ -43,6 +43,8 @@ ${CMAKE_CURRENT_LIST_DIR}/RifCaseRealizationParametersReader.h ${CMAKE_CURRENT_LIST_DIR}/RifFileParseTools.h ${CMAKE_CURRENT_LIST_DIR}/RifEnsembleStatisticsReader.h ${CMAKE_CURRENT_LIST_DIR}/RifDerivedEnsembleReader.h +${CMAKE_CURRENT_LIST_DIR}/RifActiveCellsReader.h + # HDF5 file reader is directly included in ResInsight main CmakeList.txt #${CMAKE_CURRENT_LIST_DIR}/RifHdf5Reader.h @@ -90,6 +92,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RifCaseRealizationParametersReader.cpp ${CMAKE_CURRENT_LIST_DIR}/RifFileParseTools.cpp ${CMAKE_CURRENT_LIST_DIR}/RifEnsembleStatisticsReader.cpp ${CMAKE_CURRENT_LIST_DIR}/RifDerivedEnsembleReader.cpp +${CMAKE_CURRENT_LIST_DIR}/RifActiveCellsReader.cpp # HDF5 file reader is directly included in ResInsight main CmakeList.txt #${CMAKE_CURRENT_LIST_DIR}/RifHdf5Reader.cpp diff --git a/ApplicationCode/FileInterface/RifActiveCellsReader.cpp b/ApplicationCode/FileInterface/RifActiveCellsReader.cpp new file mode 100644 index 0000000000..0364dadbe1 --- /dev/null +++ b/ApplicationCode/FileInterface/RifActiveCellsReader.cpp @@ -0,0 +1,93 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 "RifActiveCellsReader.h" + +#include "ert/ecl/ecl_file.hpp" +#include "ert/ecl/ecl_grid.hpp" +#include "ert/ecl/ecl_kw_magic.hpp" + +#include "cafAssert.h" + +#include "RiaStringEncodingTools.h" + +#include "RifEclipseOutputFileTools.h" + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector> RifActiveCellsReader::activeCellsFromActnumKeyword(const ecl_grid_type* mainEclGrid, + const ecl_file_type* ecl_file) +{ + std::vector> activeCellsAllGrids; + + int actnumKeywordCount = ecl_file_get_num_named_kw(ecl_file, ACTNUM_KW); + for (size_t gridIdx = 0; gridIdx < static_cast(actnumKeywordCount); gridIdx++) + { + std::vector nativeActnumvValues; + RifEclipseOutputFileTools::keywordData(ecl_file, ACTNUM_KW, gridIdx, &nativeActnumvValues); + + activeCellsAllGrids.push_back(nativeActnumvValues); + } + + return activeCellsAllGrids; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector> RifActiveCellsReader::activeCellsFromPorvKeyword(const ecl_grid_type* mainEclGrid, + const ecl_file_type* ecl_file) +{ + CAF_ASSERT(mainEclGrid && ecl_file); + + std::vector> activeCellsAllGrids; + + // When PORV is used as criteria, make sure all active cells are assigned both + // active matrix state and active fracture state. This will make sure that + // both single porosity models and dual porosity models are initialized with + // the correct bit mask. See documentation in top of ecl_grid.cpp + // + const int combinedActnumValueForMatrixAndFracture = CELL_ACTIVE_MATRIX + CELL_ACTIVE_FRACTURE; + + int porvKeywordCount = ecl_file_get_num_named_kw(ecl_file, PORV_KW); + for (size_t gridIdx = 0; gridIdx < static_cast(porvKeywordCount); gridIdx++) + { + std::vector porvValues; + RifEclipseOutputFileTools::keywordData(ecl_file, PORV_KW, gridIdx, &porvValues); + + std::vector activeCellsOneGrid; + activeCellsOneGrid.resize(porvValues.size()); + + for (size_t i = 0; i < porvValues.size(); i++) + { + if (porvValues[i] > 0.0) + { + activeCellsOneGrid[i] = combinedActnumValueForMatrixAndFracture; + } + else + { + activeCellsOneGrid[i] = 0; + } + } + + activeCellsAllGrids.push_back(activeCellsOneGrid); + } + + return activeCellsAllGrids; +} diff --git a/ApplicationCode/FileInterface/RifActiveCellsReader.h b/ApplicationCode/FileInterface/RifActiveCellsReader.h new file mode 100644 index 0000000000..b6212b4895 --- /dev/null +++ b/ApplicationCode/FileInterface/RifActiveCellsReader.h @@ -0,0 +1,38 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 + +typedef struct ecl_grid_struct ecl_grid_type; +typedef struct ecl_file_struct ecl_file_type; + +//================================================================================================== +// +// +//================================================================================================== +class RifActiveCellsReader +{ +public: + static std::vector> activeCellsFromActnumKeyword(const ecl_grid_type* mainEclGrid, + const ecl_file_type* ecl_file); + + static std::vector> activeCellsFromPorvKeyword(const ecl_grid_type* mainEclGrid, + const ecl_file_type* ecl_file); +}; diff --git a/ApplicationCode/UnitTests/CMakeLists_files.cmake b/ApplicationCode/UnitTests/CMakeLists_files.cmake index 4cc33352a1..0d16177430 100644 --- a/ApplicationCode/UnitTests/CMakeLists_files.cmake +++ b/ApplicationCode/UnitTests/CMakeLists_files.cmake @@ -55,6 +55,7 @@ ${CMAKE_CURRENT_LIST_DIR}/Intersect-Test.cpp ${CMAKE_CURRENT_LIST_DIR}/RifPerforationIntervalReader-Test.cpp ${CMAKE_CURRENT_LIST_DIR}/RimWellPathCompletions-Test.cpp ${CMAKE_CURRENT_LIST_DIR}/RimSummaryCaseCollection-Test.cpp +${CMAKE_CURRENT_LIST_DIR}/RifActiveCellsReader-Test.cpp ) if (RESINSIGHT_ENABLE_GRPC) diff --git a/ApplicationCode/UnitTests/RifActiveCellsReader-Test.cpp b/ApplicationCode/UnitTests/RifActiveCellsReader-Test.cpp new file mode 100644 index 0000000000..ecfbbbe8c5 --- /dev/null +++ b/ApplicationCode/UnitTests/RifActiveCellsReader-Test.cpp @@ -0,0 +1,119 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 "gtest/gtest.h" + +#include "RiaStringEncodingTools.h" +#include "RiaTestDataDirectory.h" +#include "RifActiveCellsReader.h" + +#include "ert/ecl/ecl_grid.hpp" +#include "ert/ecl/ecl_file.hpp" + +#include + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +TEST(RifActiveCellsReaderTest, BasicTest10k) +{ + QDir baseFolder(TEST_MODEL_DIR); + bool subFolderExists = baseFolder.cd("TEST10K_FLT_LGR_NNC"); + EXPECT_TRUE(subFolderExists); + + ecl_grid_type* mainEclGrid = nullptr; + + { + QString filename("TEST10K_FLT_LGR_NNC.EGRID"); + QString filePath = baseFolder.absoluteFilePath(filename); + + mainEclGrid = ecl_grid_alloc(RiaStringEncodingTools::toNativeEncoded(filePath).data()); + } + + std::vector> activeCellsFromActnum; + std::vector> activeCellsFromPorv; + { + QString filename("TEST10K_FLT_LGR_NNC.EGRID"); + QString filePath = baseFolder.absoluteFilePath(filename); + + ecl_file_type* gridFile = ecl_file_open(RiaStringEncodingTools::toNativeEncoded(filePath).data(), ECL_FILE_CLOSE_STREAM); + activeCellsFromActnum = RifActiveCellsReader::activeCellsFromActnumKeyword(mainEclGrid, gridFile); + EXPECT_EQ(2, activeCellsFromActnum.size()); + ecl_file_close(gridFile); + } + + { + QString filename("TEST10K_FLT_LGR_NNC.INIT"); + QString filePath = baseFolder.absoluteFilePath(filename); + + ecl_file_type* initFile = ecl_file_open(RiaStringEncodingTools::toNativeEncoded(filePath).data(), ECL_FILE_CLOSE_STREAM); + + activeCellsFromPorv = RifActiveCellsReader::activeCellsFromPorvKeyword(mainEclGrid, initFile); + EXPECT_EQ(2, activeCellsFromPorv.size()); + + ecl_file_close(initFile); + } + + for (size_t gridIndex = 0; gridIndex < activeCellsFromActnum.size(); gridIndex++) + { + for (size_t valueIndex = 0; valueIndex < activeCellsFromActnum[gridIndex].size(); valueIndex++) + { + auto actnumValue = activeCellsFromActnum[gridIndex][valueIndex]; + auto porvValue = activeCellsFromPorv[gridIndex][valueIndex]; + if (actnumValue > 0) + { + EXPECT_TRUE(porvValue > 0); + } + else + { + EXPECT_EQ(0, porvValue); + } + } + } + + std::vector expectedActiveCellCountPerGrid; + expectedActiveCellCountPerGrid.push_back(8517); + expectedActiveCellCountPerGrid.push_back(2608); + + for (int gridIndex = 0; gridIndex < static_cast(activeCellsFromActnum.size()); gridIndex++) + { + ecl_grid_type* currentGrid = nullptr; + if (gridIndex == 0) + { + currentGrid = mainEclGrid; + } + else + { + currentGrid = ecl_grid_iget_lgr(mainEclGrid, gridIndex - 1); + } + + auto activeCellsForGrid = activeCellsFromActnum[gridIndex]; + if (ecl_grid_get_global_size(currentGrid) == static_cast(activeCellsForGrid.size())) + { + int expectedCellCount = expectedActiveCellCountPerGrid[gridIndex]; + EXPECT_EQ(expectedCellCount, ecl_grid_get_nactive(currentGrid)); + + int* actnum_values = activeCellsForGrid.data(); + + ecl_grid_reset_actnum(currentGrid, actnum_values); + EXPECT_EQ(expectedCellCount, ecl_grid_get_nactive(currentGrid)); + } + } + + ecl_grid_free(mainEclGrid); +} From 085c4f371471c39ed8a21893ad2f7e56586bd1c0 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 19 Jun 2019 15:02:10 +0200 Subject: [PATCH 188/396] #4495 Active Cells : Add dual porosity flag to RigMainGrid --- .../ReservoirDataModel/RigMainGrid.cpp | 17 +++++++++++++++++ .../ReservoirDataModel/RigMainGrid.h | 5 +++++ 2 files changed, 22 insertions(+) diff --git a/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp b/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp index e9223343e8..38988e112e 100644 --- a/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp +++ b/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp @@ -42,6 +42,7 @@ RigMainGrid::RigMainGrid() m_useMapAxes = false; m_mapAxes = defaultMapAxes(); + m_dualPorosity = false; } RigMainGrid::~RigMainGrid() {} @@ -829,6 +830,22 @@ cvf::Mat4d RigMainGrid::mapAxisTransform() const return mapAxisTrans; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RigMainGrid::isDualPorosity() const +{ + return m_dualPorosity; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigMainGrid::setDualPorosity(bool enable) +{ + m_dualPorosity = enable; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ReservoirDataModel/RigMainGrid.h b/ApplicationCode/ReservoirDataModel/RigMainGrid.h index c0d64da439..125a86a40e 100644 --- a/ApplicationCode/ReservoirDataModel/RigMainGrid.h +++ b/ApplicationCode/ReservoirDataModel/RigMainGrid.h @@ -100,6 +100,9 @@ public: std::array mapAxesF() const; cvf::Mat4d mapAxisTransform() const; + + bool isDualPorosity() const; + void setDualPorosity(bool enable); private: void initAllSubCellsMainGridCellIndex(); void buildCellSearchTree(); @@ -126,5 +129,7 @@ private: bool m_useMapAxes; std::array m_mapAxes; + + bool m_dualPorosity; }; From 515b2a42372148bc5dfdf1daf2d1d17e0201ae5f Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 19 Jun 2019 15:05:54 +0200 Subject: [PATCH 189/396] #4495 Active Cells : Use PORV or ACTNUM from statistics computations --- .../FileInterface/RifActiveCellsReader.cpp | 20 +- .../FileInterface/RifActiveCellsReader.h | 6 +- .../FileInterface/RifReaderEclipseOutput.cpp | 171 ++++++++++-------- .../FileInterface/RifReaderEclipseOutput.h | 2 +- .../UnitTests/RifActiveCellsReader-Test.cpp | 4 +- 5 files changed, 112 insertions(+), 91 deletions(-) diff --git a/ApplicationCode/FileInterface/RifActiveCellsReader.cpp b/ApplicationCode/FileInterface/RifActiveCellsReader.cpp index 0364dadbe1..44ae8acd3c 100644 --- a/ApplicationCode/FileInterface/RifActiveCellsReader.cpp +++ b/ApplicationCode/FileInterface/RifActiveCellsReader.cpp @@ -31,9 +31,10 @@ //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::vector> RifActiveCellsReader::activeCellsFromActnumKeyword(const ecl_grid_type* mainEclGrid, - const ecl_file_type* ecl_file) +std::vector> RifActiveCellsReader::activeCellsFromActnumKeyword(const ecl_file_type* ecl_file) { + CAF_ASSERT(ecl_file); + std::vector> activeCellsAllGrids; int actnumKeywordCount = ecl_file_get_num_named_kw(ecl_file, ACTNUM_KW); @@ -51,10 +52,9 @@ std::vector> RifActiveCellsReader::activeCellsFromActnumKeyword //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::vector> RifActiveCellsReader::activeCellsFromPorvKeyword(const ecl_grid_type* mainEclGrid, - const ecl_file_type* ecl_file) +std::vector> RifActiveCellsReader::activeCellsFromPorvKeyword(const ecl_file_type* ecl_file, bool dualPorosity) { - CAF_ASSERT(mainEclGrid && ecl_file); + CAF_ASSERT(ecl_file); std::vector> activeCellsAllGrids; @@ -63,7 +63,6 @@ std::vector> RifActiveCellsReader::activeCellsFromPorvKeyword(c // both single porosity models and dual porosity models are initialized with // the correct bit mask. See documentation in top of ecl_grid.cpp // - const int combinedActnumValueForMatrixAndFracture = CELL_ACTIVE_MATRIX + CELL_ACTIVE_FRACTURE; int porvKeywordCount = ecl_file_get_num_named_kw(ecl_file, PORV_KW); for (size_t gridIdx = 0; gridIdx < static_cast(porvKeywordCount); gridIdx++) @@ -78,7 +77,14 @@ std::vector> RifActiveCellsReader::activeCellsFromPorvKeyword(c { if (porvValues[i] > 0.0) { - activeCellsOneGrid[i] = combinedActnumValueForMatrixAndFracture; + if (!dualPorosity || i < porvValues.size() / 2) + { + activeCellsOneGrid[i] = CELL_ACTIVE_MATRIX; + } + else + { + activeCellsOneGrid[i] = CELL_ACTIVE_FRACTURE; + } } else { diff --git a/ApplicationCode/FileInterface/RifActiveCellsReader.h b/ApplicationCode/FileInterface/RifActiveCellsReader.h index b6212b4895..1690fea5ce 100644 --- a/ApplicationCode/FileInterface/RifActiveCellsReader.h +++ b/ApplicationCode/FileInterface/RifActiveCellsReader.h @@ -30,9 +30,7 @@ typedef struct ecl_file_struct ecl_file_type; class RifActiveCellsReader { public: - static std::vector> activeCellsFromActnumKeyword(const ecl_grid_type* mainEclGrid, - const ecl_file_type* ecl_file); + static std::vector> activeCellsFromActnumKeyword(const ecl_file_type* ecl_file); - static std::vector> activeCellsFromPorvKeyword(const ecl_grid_type* mainEclGrid, - const ecl_file_type* ecl_file); + static std::vector> activeCellsFromPorvKeyword(const ecl_file_type* ecl_file, bool dualPorosity); }; diff --git a/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp b/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp index 654d8b82c0..16fb62f3a1 100644 --- a/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp +++ b/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp @@ -26,6 +26,7 @@ #include "RiaPreferences.h" #include "RiaStringEncodingTools.h" +#include "RifActiveCellsReader.h" #include "RifEclipseInputFileTools.h" #include "RifEclipseOutputFileTools.h" #include "RifHdf5ReaderInterface.h" @@ -273,6 +274,8 @@ bool RifReaderEclipseOutput::transferGeometry(const ecl_grid_type* mainEclGrid, // ERT returns file path to grid file as name for main grid mainGrid->setGridName("Main grid"); + mainGrid->setDualPorosity(ecl_grid_dual_grid(mainEclGrid)); + // Get and set grid and lgr metadata size_t totalCellCount = static_cast(ecl_grid_get_global_size(mainEclGrid)); @@ -810,82 +813,96 @@ bool RifReaderEclipseOutput::readActiveCellInfo() CVF_ASSERT(m_eclipseCase); CVF_ASSERT(m_eclipseCase->mainGrid()); - QString egridFileName = RifEclipseOutputFileTools::firstFileNameOfType(m_filesWithSameBaseName, ECL_EGRID_FILE); - if (egridFileName.size() > 0) + std::vector> actnumValuesPerGrid; + { - ecl_file_type* ecl_file = - ecl_file_open(RiaStringEncodingTools::toNativeEncoded(egridFileName).data(), ECL_FILE_CLOSE_STREAM); - if (!ecl_file) return false; - - int actnumKeywordCount = ecl_file_get_num_named_kw(ecl_file, ACTNUM_KW); - if (actnumKeywordCount > 0) + // If INIT file is present and PORV is found, use PORV as basis for active cells + QString initFileName = RifEclipseOutputFileTools::firstFileNameOfType(m_filesWithSameBaseName, ECL_INIT_FILE); + if (initFileName.size() > 0) { - std::vector> actnumValuesPerGrid; - actnumValuesPerGrid.resize(actnumKeywordCount); - - size_t reservoirCellCount = 0; - for (size_t gridIdx = 0; gridIdx < static_cast(actnumKeywordCount); gridIdx++) + ecl_file_type* ecl_file = + ecl_file_open(RiaStringEncodingTools::toNativeEncoded(initFileName).data(), ECL_FILE_CLOSE_STREAM); + if (ecl_file) { - RifEclipseOutputFileTools::keywordData(ecl_file, ACTNUM_KW, gridIdx, &actnumValuesPerGrid[gridIdx]); - - reservoirCellCount += actnumValuesPerGrid[gridIdx].size(); + bool isDualPorosity = m_eclipseCase->mainGrid()->isDualPorosity(); + actnumValuesPerGrid = RifActiveCellsReader::activeCellsFromPorvKeyword(ecl_file, isDualPorosity); + ecl_file_close(ecl_file); } - - // Check if number of cells is matching - if (m_eclipseCase->mainGrid()->globalCellArray().size() != reservoirCellCount) - { - return false; - } - - RigActiveCellInfo* activeCellInfo = m_eclipseCase->activeCellInfo(RiaDefines::MATRIX_MODEL); - RigActiveCellInfo* fractureActiveCellInfo = m_eclipseCase->activeCellInfo(RiaDefines::FRACTURE_MODEL); - - activeCellInfo->setReservoirCellCount(reservoirCellCount); - fractureActiveCellInfo->setReservoirCellCount(reservoirCellCount); - activeCellInfo->setGridCount(actnumKeywordCount); - fractureActiveCellInfo->setGridCount(actnumKeywordCount); - - size_t cellIdx = 0; - size_t globalActiveMatrixIndex = 0; - size_t globalActiveFractureIndex = 0; - for (size_t gridIdx = 0; gridIdx < static_cast(actnumKeywordCount); gridIdx++) - { - size_t activeMatrixIndex = 0; - size_t activeFractureIndex = 0; - - std::vector& actnumValues = actnumValuesPerGrid[gridIdx]; - - for (size_t i = 0; i < actnumValues.size(); i++) - { - if (actnumValues[i] == 1 || actnumValues[i] == 3) - { - activeCellInfo->setCellResultIndex(cellIdx, globalActiveMatrixIndex++); - activeMatrixIndex++; - } - - if (actnumValues[i] == 2 || actnumValues[i] == 3) - { - fractureActiveCellInfo->setCellResultIndex(cellIdx, globalActiveFractureIndex++); - activeFractureIndex++; - } - - cellIdx++; - } - - activeCellInfo->setGridActiveCellCounts(gridIdx, activeMatrixIndex); - fractureActiveCellInfo->setGridActiveCellCounts(gridIdx, activeFractureIndex); - } - - activeCellInfo->computeDerivedData(); - fractureActiveCellInfo->computeDerivedData(); } - - ecl_file_close(ecl_file); - - return true; } - return false; + if (actnumValuesPerGrid.empty()) + { + // Try ACTNUM from grid file as basis for active cells + QString egridFileName = RifEclipseOutputFileTools::firstFileNameOfType(m_filesWithSameBaseName, ECL_EGRID_FILE); + if (egridFileName.size() > 0) + { + ecl_file_type* ecl_file = + ecl_file_open(RiaStringEncodingTools::toNativeEncoded(egridFileName).data(), ECL_FILE_CLOSE_STREAM); + if (ecl_file) + { + actnumValuesPerGrid = RifActiveCellsReader::activeCellsFromActnumKeyword(ecl_file); + ecl_file_close(ecl_file); + } + } + } + + size_t reservoirCellCount = 0; + for (const auto& actnumValues : actnumValuesPerGrid) + { + reservoirCellCount += actnumValues.size(); + } + + // Check if number of cells is matching + if (m_eclipseCase->mainGrid()->globalCellArray().size() != reservoirCellCount) + { + return false; + } + + RigActiveCellInfo* activeCellInfo = m_eclipseCase->activeCellInfo(RiaDefines::MATRIX_MODEL); + RigActiveCellInfo* fractureActiveCellInfo = m_eclipseCase->activeCellInfo(RiaDefines::FRACTURE_MODEL); + + activeCellInfo->setReservoirCellCount(reservoirCellCount); + fractureActiveCellInfo->setReservoirCellCount(reservoirCellCount); + activeCellInfo->setGridCount(actnumValuesPerGrid.size()); + fractureActiveCellInfo->setGridCount(actnumValuesPerGrid.size()); + + size_t cellIdx = 0; + size_t globalActiveMatrixIndex = 0; + size_t globalActiveFractureIndex = 0; + + for (size_t gridIndex = 0; gridIndex < actnumValuesPerGrid.size(); gridIndex++) + { + size_t activeMatrixIndex = 0; + size_t activeFractureIndex = 0; + + std::vector& actnumValues = actnumValuesPerGrid[gridIndex]; + + for (int actnumValue : actnumValues) + { + if (actnumValue == 1 || actnumValue == 3) + { + activeCellInfo->setCellResultIndex(cellIdx, globalActiveMatrixIndex++); + activeMatrixIndex++; + } + + if (actnumValue == 2 || actnumValue == 3) + { + fractureActiveCellInfo->setCellResultIndex(cellIdx, globalActiveFractureIndex++); + activeFractureIndex++; + } + + cellIdx++; + } + + activeCellInfo->setGridActiveCellCounts(gridIndex, activeMatrixIndex); + fractureActiveCellInfo->setGridActiveCellCounts(gridIndex, activeFractureIndex); + } + + activeCellInfo->computeDerivedData(); + fractureActiveCellInfo->computeDerivedData(); + + return true; } //-------------------------------------------------------------------------------------------------- @@ -1245,8 +1262,8 @@ size_t localGridCellIndexFromErtConnection(const RigGridBase* grid, // TODO: Ask Joakim Haave regarding this. if (cellK < 0) { - // cvf::Trace::show("Well Connection for grid " + cvf::String(grid->gridName()) + "\n - Detected negative K value (K=" + - // cvf::String(cellK) + ") for well : " + cvf::String(wellName) + " K clamped to 0"); + // cvf::Trace::show("Well Connection for grid " + cvf::String(grid->gridName()) + "\n - Detected negative K value + // (K=" + cvf::String(cellK) + ") for well : " + cvf::String(wellName) + " K clamped to 0"); cellK = 0; } @@ -1716,8 +1733,8 @@ void RifReaderEclipseOutput::readWellCells(const ecl_grid_type* mainEclGrid, boo well_segment_get_connections(segment, gridName.data()); int connectionCount = well_conn_collection_get_size(connections); - // Loop backwards to put the deepest connections first in the array. (The segments are also - // traversed deep to shallow) + // Loop backwards to put the deepest connections first in the array. (The segments are + // also traversed deep to shallow) for (int connIdx = connectionCount - 1; connIdx >= 0; connIdx--) { well_conn_type* ert_connection = well_conn_collection_iget(connections, connIdx); @@ -1747,8 +1764,8 @@ void RifReaderEclipseOutput::readWellCells(const ecl_grid_type* mainEclGrid, boo } } - // If the segment did not have connections at all, we need to create a resultpoint representing the bottom - // of the segment and store it as an unpositioned segment + // If the segment did not have connections at all, we need to create a resultpoint representing + // the bottom of the segment and store it as an unpositioned segment if (!segmentHasConnections) { @@ -1890,8 +1907,8 @@ void RifReaderEclipseOutput::readWellCells(const ecl_grid_type* mainEclGrid, boo } else { - break; // We have found a segment with connections. We do not need to propagate position - // contributions further + break; // We have found a segment with connections. We do not need to propagate + // position contributions further } segmentIdBelow = well_segment_get_id(aboveOutletSegment); diff --git a/ApplicationCode/FileInterface/RifReaderEclipseOutput.h b/ApplicationCode/FileInterface/RifReaderEclipseOutput.h index ec1cb02421..61c68c4b84 100644 --- a/ApplicationCode/FileInterface/RifReaderEclipseOutput.h +++ b/ApplicationCode/FileInterface/RifReaderEclipseOutput.h @@ -60,7 +60,7 @@ public: static const size_t* eclipseCellIndexMapping(); - virtual bool openAndReadActiveCellData(const QString& fileName, const std::vector& mainCaseTimeSteps, RigEclipseCaseData* eclipseCase); + bool openAndReadActiveCellData(const QString& fileName, const std::vector& mainCaseTimeSteps, RigEclipseCaseData* eclipseCase); bool staticResult(const QString& result, RiaDefines::PorosityModelType matrixOrFracture, std::vector* values) override; bool dynamicResult(const QString& result, RiaDefines::PorosityModelType matrixOrFracture, size_t stepIndex, std::vector* values) override; diff --git a/ApplicationCode/UnitTests/RifActiveCellsReader-Test.cpp b/ApplicationCode/UnitTests/RifActiveCellsReader-Test.cpp index ecfbbbe8c5..22c8a96da3 100644 --- a/ApplicationCode/UnitTests/RifActiveCellsReader-Test.cpp +++ b/ApplicationCode/UnitTests/RifActiveCellsReader-Test.cpp @@ -52,7 +52,7 @@ TEST(RifActiveCellsReaderTest, BasicTest10k) QString filePath = baseFolder.absoluteFilePath(filename); ecl_file_type* gridFile = ecl_file_open(RiaStringEncodingTools::toNativeEncoded(filePath).data(), ECL_FILE_CLOSE_STREAM); - activeCellsFromActnum = RifActiveCellsReader::activeCellsFromActnumKeyword(mainEclGrid, gridFile); + activeCellsFromActnum = RifActiveCellsReader::activeCellsFromActnumKeyword(gridFile); EXPECT_EQ(2, activeCellsFromActnum.size()); ecl_file_close(gridFile); } @@ -63,7 +63,7 @@ TEST(RifActiveCellsReaderTest, BasicTest10k) ecl_file_type* initFile = ecl_file_open(RiaStringEncodingTools::toNativeEncoded(filePath).data(), ECL_FILE_CLOSE_STREAM); - activeCellsFromPorv = RifActiveCellsReader::activeCellsFromPorvKeyword(mainEclGrid, initFile); + activeCellsFromPorv = RifActiveCellsReader::activeCellsFromPorvKeyword(initFile, false); EXPECT_EQ(2, activeCellsFromPorv.size()); ecl_file_close(initFile); From 7c054c47f2d54d7d23f676a2b8516be6d50ae66a Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 20 Jun 2019 15:00:01 +0200 Subject: [PATCH 190/396] #4495 Active Cells : Handle active cells for dual porosity models based on PORV --- .../FileInterface/RifActiveCellsReader.cpp | 58 +++++++++++++++---- .../FileInterface/RifActiveCellsReader.h | 3 + .../FileInterface/RifReaderEclipseOutput.cpp | 29 ++++------ .../FileInterface/RifReaderEclipseOutput.h | 2 +- .../RigFlowDiagSolverInterface.cpp | 2 +- 5 files changed, 62 insertions(+), 32 deletions(-) diff --git a/ApplicationCode/FileInterface/RifActiveCellsReader.cpp b/ApplicationCode/FileInterface/RifActiveCellsReader.cpp index 44ae8acd3c..7bb7c209e0 100644 --- a/ApplicationCode/FileInterface/RifActiveCellsReader.cpp +++ b/ApplicationCode/FileInterface/RifActiveCellsReader.cpp @@ -58,11 +58,10 @@ std::vector> RifActiveCellsReader::activeCellsFromPorvKeyword(c std::vector> activeCellsAllGrids; - // When PORV is used as criteria, make sure all active cells are assigned both - // active matrix state and active fracture state. This will make sure that - // both single porosity models and dual porosity models are initialized with - // the correct bit mask. See documentation in top of ecl_grid.cpp + // Active cell count is always the same size as the number of cells in the grid + // If we have dual porosity, we have to divide by 2 // + // See documentation of active cells in top of ecl_grid.cpp int porvKeywordCount = ecl_file_get_num_named_kw(ecl_file, PORV_KW); for (size_t gridIdx = 0; gridIdx < static_cast(porvKeywordCount); gridIdx++) @@ -71,24 +70,36 @@ std::vector> RifActiveCellsReader::activeCellsFromPorvKeyword(c RifEclipseOutputFileTools::keywordData(ecl_file, PORV_KW, gridIdx, &porvValues); std::vector activeCellsOneGrid; - activeCellsOneGrid.resize(porvValues.size()); - for (size_t i = 0; i < porvValues.size(); i++) + size_t activeCellCount = porvValues.size(); + if (dualPorosity) { - if (porvValues[i] > 0.0) + activeCellCount /= 2; + } + activeCellsOneGrid.resize(activeCellCount, 0); + + for (size_t poreValueIndex = 0; poreValueIndex < porvValues.size(); poreValueIndex++) + { + size_t indexToCell = poreValueIndex; + if (indexToCell >= activeCellCount) { - if (!dualPorosity || i < porvValues.size() / 2) + indexToCell = poreValueIndex - activeCellCount; + } + + if (porvValues[poreValueIndex] > 0.0) + { + if (!dualPorosity || poreValueIndex < porvValues.size() / 2) { - activeCellsOneGrid[i] = CELL_ACTIVE_MATRIX; + activeCellsOneGrid[indexToCell] = CELL_ACTIVE_MATRIX; } else { - activeCellsOneGrid[i] = CELL_ACTIVE_FRACTURE; + activeCellsOneGrid[indexToCell] += CELL_ACTIVE_FRACTURE; } } else { - activeCellsOneGrid[i] = 0; + activeCellsOneGrid[indexToCell] = 0; } } @@ -97,3 +108,28 @@ std::vector> RifActiveCellsReader::activeCellsFromPorvKeyword(c return activeCellsAllGrids; } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RifActiveCellsReader::applyActiveCellsToAllGrids(ecl_grid_type* ecl_main_grid, + const std::vector>& activeCellsForAllGrids) +{ + CAF_ASSERT(ecl_main_grid); + + for (int gridIndex = 0; gridIndex < static_cast(activeCellsForAllGrids.size()); gridIndex++) + { + ecl_grid_type* currentGrid = ecl_main_grid; + if (gridIndex > 0) + { + currentGrid = ecl_grid_iget_lgr(ecl_main_grid, gridIndex - 1); + } + + auto activeCellsForGrid = activeCellsForAllGrids[gridIndex]; + CAF_ASSERT(ecl_grid_get_global_size(currentGrid) == static_cast(activeCellsForGrid.size())); + + int* actnum_values = activeCellsForGrid.data(); + + ecl_grid_reset_actnum(currentGrid, actnum_values); + } +} diff --git a/ApplicationCode/FileInterface/RifActiveCellsReader.h b/ApplicationCode/FileInterface/RifActiveCellsReader.h index 1690fea5ce..e807ebd425 100644 --- a/ApplicationCode/FileInterface/RifActiveCellsReader.h +++ b/ApplicationCode/FileInterface/RifActiveCellsReader.h @@ -33,4 +33,7 @@ public: static std::vector> activeCellsFromActnumKeyword(const ecl_file_type* ecl_file); static std::vector> activeCellsFromPorvKeyword(const ecl_file_type* ecl_file, bool dualPorosity); + + static void applyActiveCellsToAllGrids(ecl_grid_type* ecl_main_grid, + const std::vector>& activeCellsForAllGrids); }; diff --git a/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp b/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp index 16fb62f3a1..9df5ae294a 100644 --- a/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp +++ b/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp @@ -401,7 +401,7 @@ bool RifReaderEclipseOutput::open(const QString& fileName, RigEclipseCaseData* e // Read geometry // Todo: Needs to check existence of file before calling ert, else it will abort - mainEclGrid = loadMainGrid(); + mainEclGrid = loadAllGrids(); if (!mainEclGrid) { QString errorMessage = QString(" Failed to create a main grid from file\n%1").arg(m_fileName); @@ -2279,30 +2279,21 @@ bool RifReaderEclipseOutput::isEclipseAndSoursimTimeStepsEqual(const QDateTime& //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -ecl_grid_type* RifReaderEclipseOutput::loadMainGrid() const +ecl_grid_type* RifReaderEclipseOutput::loadAllGrids() const { - ecl_grid_type* mainEclGrid = nullptr; + ecl_grid_type* mainEclGrid = ecl_grid_alloc(RiaStringEncodingTools::toNativeEncoded(m_fileName).data()); + if (m_ecl_init_file) { - if (m_ecl_init_file) - { - ecl_kw_type* actnumFromPorv = RifEclipseOutputFileTools::createActnumFromPorv(m_ecl_init_file); - if (actnumFromPorv) - { - int* actnum_values = ecl_kw_get_int_ptr(actnumFromPorv); - if (actnum_values) - { - mainEclGrid = - ecl_grid_alloc_ext_actnum(RiaStringEncodingTools::toNativeEncoded(m_fileName).data(), actnum_values); - } + // TODO : ecl_grid_alloc() will automatically read ACTNUM from EGRID file, and reading of active cell information can be + // skipped if PORV is available - ecl_kw_free(actnumFromPorv); - } - } + bool isDualPorosity = ecl_grid_dual_grid(mainEclGrid); + auto activeCells = RifActiveCellsReader::activeCellsFromPorvKeyword(m_ecl_init_file, isDualPorosity); - if (!mainEclGrid) + if (!activeCells.empty()) { - mainEclGrid = ecl_grid_alloc(RiaStringEncodingTools::toNativeEncoded(m_fileName).data()); + RifActiveCellsReader::applyActiveCellsToAllGrids(mainEclGrid, activeCells); } } diff --git a/ApplicationCode/FileInterface/RifReaderEclipseOutput.h b/ApplicationCode/FileInterface/RifReaderEclipseOutput.h index 61c68c4b84..d2f93f2614 100644 --- a/ApplicationCode/FileInterface/RifReaderEclipseOutput.h +++ b/ApplicationCode/FileInterface/RifReaderEclipseOutput.h @@ -88,7 +88,7 @@ public: // ecl_grid_type* myGrid = loadMainGrid(); // free(myGrid); // - ecl_grid_type* loadMainGrid() const; + ecl_grid_type* loadAllGrids() const; private: bool readActiveCellInfo(); diff --git a/ApplicationCode/ReservoirDataModel/RigFlowDiagSolverInterface.cpp b/ApplicationCode/ReservoirDataModel/RigFlowDiagSolverInterface.cpp index 84c286582f..a962e592ee 100644 --- a/ApplicationCode/ReservoirDataModel/RigFlowDiagSolverInterface.cpp +++ b/ApplicationCode/ReservoirDataModel/RigFlowDiagSolverInterface.cpp @@ -524,7 +524,7 @@ bool RigFlowDiagSolverInterface::ensureStaticDataObjectInstanceCreated() auto eclOutput = dynamic_cast(fileReader); if (eclOutput) { - ecl_grid_type* mainGrid = eclOutput->loadMainGrid(); + ecl_grid_type* mainGrid = eclOutput->loadAllGrids(); if (!mainGrid) { return false; From 8997ec00e0258ab951706932b2625ee22ecdbae6 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 21 Jun 2019 07:07:37 +0200 Subject: [PATCH 191/396] #4493 Fracture : Hide Fractures in tree view if no fractures in model --- .../RicNewSimWellFractureAtPosFeature.cpp | 7 +++---- .../RicNewSimWellFractureFeature.cpp | 7 +++---- .../RicNewWellPathFractureFeature.cpp | 6 +++--- .../ProjectDataModel/RimEclipseView.cpp | 17 +++++++++++------ 4 files changed, 20 insertions(+), 17 deletions(-) diff --git a/ApplicationCode/Commands/FractureCommands/RicNewSimWellFractureAtPosFeature.cpp b/ApplicationCode/Commands/FractureCommands/RicNewSimWellFractureAtPosFeature.cpp index 4e2c2eec18..e813fe78c5 100644 --- a/ApplicationCode/Commands/FractureCommands/RicNewSimWellFractureAtPosFeature.cpp +++ b/ApplicationCode/Commands/FractureCommands/RicNewSimWellFractureAtPosFeature.cpp @@ -109,7 +109,6 @@ void RicNewSimWellFractureAtPosFeature::onActionTriggered(bool isChecked) fracture->setFractureTemplate(fracDef); simWell->updateConnectedEditors(); - Riu3DMainWindowTools::selectAsCurrentItem(fracture); activeView->scheduleCreateDisplayModelAndRedraw(); @@ -117,10 +116,10 @@ void RicNewSimWellFractureAtPosFeature::onActionTriggered(bool isChecked) simWell->firstAncestorOrThisOfType(eclipseCase); if (eclipseCase) { - RimProject* project; - eclipseCase->firstAncestorOrThisOfTypeAsserted(project); - project->reloadCompletionTypeResultsForEclipseCase(eclipseCase); + proj->reloadCompletionTypeResultsForEclipseCase(eclipseCase); + proj->updateConnectedEditors(); } + Riu3DMainWindowTools::selectAsCurrentItem(fracture); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/Commands/FractureCommands/RicNewSimWellFractureFeature.cpp b/ApplicationCode/Commands/FractureCommands/RicNewSimWellFractureFeature.cpp index 950011c593..3da5674761 100644 --- a/ApplicationCode/Commands/FractureCommands/RicNewSimWellFractureFeature.cpp +++ b/ApplicationCode/Commands/FractureCommands/RicNewSimWellFractureFeature.cpp @@ -98,16 +98,15 @@ void RicNewSimWellFractureFeature::onActionTriggered(bool isChecked) fracture->updateFracturePositionFromLocation(); eclipseWell->updateConnectedEditors(); - Riu3DMainWindowTools::selectAsCurrentItem(fracture); RimEclipseCase* eclipseCase = nullptr; objHandle->firstAncestorOrThisOfType(eclipseCase); if (eclipseCase) { - RimProject* project; - objHandle->firstAncestorOrThisOfTypeAsserted(project); - project->reloadCompletionTypeResultsForEclipseCase(eclipseCase); + proj->reloadCompletionTypeResultsForEclipseCase(eclipseCase); + proj->updateConnectedEditors(); } + Riu3DMainWindowTools::selectAsCurrentItem(fracture); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/Commands/FractureCommands/RicNewWellPathFractureFeature.cpp b/ApplicationCode/Commands/FractureCommands/RicNewWellPathFractureFeature.cpp index 33c1799a5d..986f195d92 100644 --- a/ApplicationCode/Commands/FractureCommands/RicNewWellPathFractureFeature.cpp +++ b/ApplicationCode/Commands/FractureCommands/RicNewWellPathFractureFeature.cpp @@ -96,15 +96,15 @@ void RicNewWellPathFractureFeature::addFracture(RimWellPath* wellPath, double me fracture->setFractureTemplate(fracDef); } - wellPath->updateConnectedEditors(); - Riu3DMainWindowTools::selectAsCurrentItem(fracture); - RimProject* project = nullptr; fractureCollection->firstAncestorOrThisOfType(project); if (project) { project->reloadCompletionTypeResultsInAllViews(); + project->updateAllRequiredEditors(); } + + Riu3DMainWindowTools::selectAsCurrentItem(fracture); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimEclipseView.cpp b/ApplicationCode/ProjectDataModel/RimEclipseView.cpp index f595da6449..aad32675ab 100644 --- a/ApplicationCode/ProjectDataModel/RimEclipseView.cpp +++ b/ApplicationCode/ProjectDataModel/RimEclipseView.cpp @@ -1645,13 +1645,18 @@ void RimEclipseView::defineUiTreeOrdering(caf::PdmUiTreeOrdering& uiTreeOrdering uiTreeOrdering.add(faultResultSettings()); uiTreeOrdering.add(wellCollection()); - RimProject* project = RiaApplication::instance()->project(); - CVF_ASSERT(project); - RimOilField* oilfield = project->activeOilField(); - - if (oilfield && oilfield->fractureDefinitionCollection()) { - if (!oilfield->fractureDefinitionCollection()->fractureTemplates().empty()) + bool showFractureColors = false; + + std::vector fractures; + m_wellCollection->descendantsIncludingThisOfType(fractures); + wellPathCollection()->descendantsIncludingThisOfType(fractures); + if (!fractures.empty()) + { + showFractureColors = true; + } + + if (showFractureColors) { uiTreeOrdering.add(fractureColors()); } From a3d521e272408900e601042222b60c7af1e470d2 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 21 Jun 2019 09:11:10 +0200 Subject: [PATCH 192/396] #4402 Ensembles: Remove Preference import option 'Separate Case' for Origin ensembles --- .../Application/RiaPreferences.cpp | 29 ++++++++++-- ApplicationCode/Application/RiaPreferences.h | 1 + .../RifSummaryCaseRestartSelector.cpp | 44 ++++++++++++++----- .../RifSummaryCaseRestartSelector.h | 2 - 4 files changed, 60 insertions(+), 16 deletions(-) diff --git a/ApplicationCode/Application/RiaPreferences.cpp b/ApplicationCode/Application/RiaPreferences.cpp index ef2d39b419..f81d7f0a88 100644 --- a/ApplicationCode/Application/RiaPreferences.cpp +++ b/ApplicationCode/Application/RiaPreferences.cpp @@ -116,6 +116,7 @@ RiaPreferences::RiaPreferences(void) CAF_PDM_InitFieldNoDefault(&summaryRestartFilesShowImportDialog, "summaryRestartFilesShowImportDialog", "Show Import Dialog", "", "", ""); CAF_PDM_InitField(&summaryImportMode, "summaryImportMode", SummaryRestartFilesImportModeType(RiaPreferences::IMPORT), "Default Summary Import Option", "", "", ""); CAF_PDM_InitField(&gridImportMode, "gridImportMode", SummaryRestartFilesImportModeType(RiaPreferences::NOT_IMPORT), "Default Grid Import Option", "", "", ""); + CAF_PDM_InitField(&summaryEnsembleImportMode, "summaryEnsembleImportMode", SummaryRestartFilesImportModeType(RiaPreferences::IMPORT), "Default Ensemble Summary Import Option", "", "", ""); CAF_PDM_InitFieldNoDefault(&m_holoLensExportFolder, "holoLensExportFolder", "HoloLens Export Folder", "", "", ""); m_holoLensExportFolder.uiCapability()->setUiLabelPosition(caf::PdmUiItemInfo::TOP); @@ -241,10 +242,21 @@ void RiaPreferences::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& caf::PdmUiGroup* restartBehaviourGroup = uiOrdering.addNewGroup("Origin Files"); restartBehaviourGroup->add(&summaryRestartFilesShowImportDialog); - caf::PdmUiGroup* summaryImportOptionGroup = restartBehaviourGroup->addNewGroup("Origin Summary Files"); - summaryImportOptionGroup->add(&summaryImportMode); - caf::PdmUiGroup* gridImportOptionGroup = restartBehaviourGroup->addNewGroup("Origin Grid Files"); - gridImportOptionGroup->add(&gridImportMode); + + { + caf::PdmUiGroup* group = restartBehaviourGroup->addNewGroup("Origin Summary Files"); + group->add(&summaryImportMode); + } + + { + caf::PdmUiGroup* group = restartBehaviourGroup->addNewGroup("Origin Grid Files"); + group->add(&gridImportMode); + } + + { + caf::PdmUiGroup* group = restartBehaviourGroup->addNewGroup("Origin Ensemble Summary Files"); + group->add(&summaryEnsembleImportMode); + } } else if (uiConfigName == m_tabNames[2]) { @@ -294,6 +306,15 @@ QList RiaPreferences::calculateValueOptions(const caf::P options.push_back(caf::PdmOptionItemInfo(skip.uiText(), RiaPreferences::NOT_IMPORT)); options.push_back(caf::PdmOptionItemInfo(separate.uiText(), RiaPreferences::SEPARATE_CASES)); } + else if (fieldNeedingOptions == &summaryEnsembleImportMode) + { + // Manual option handling in order to one only a subset of the enum values + SummaryRestartFilesImportModeType skip(RiaPreferences::NOT_IMPORT); + SummaryRestartFilesImportModeType allowImport(RiaPreferences::IMPORT); + + options.push_back(caf::PdmOptionItemInfo(skip.uiText(), RiaPreferences::NOT_IMPORT)); + options.push_back(caf::PdmOptionItemInfo(allowImport.uiText(), RiaPreferences::IMPORT)); + } return options; } diff --git a/ApplicationCode/Application/RiaPreferences.h b/ApplicationCode/Application/RiaPreferences.h index bbbab6108f..26bdc5fc33 100644 --- a/ApplicationCode/Application/RiaPreferences.h +++ b/ApplicationCode/Application/RiaPreferences.h @@ -106,6 +106,7 @@ public: // Pdm Fields caf::PdmField summaryRestartFilesShowImportDialog; caf::PdmField summaryImportMode; caf::PdmField gridImportMode; + caf::PdmField summaryEnsembleImportMode; caf::PdmField holoLensDisableCertificateVerification; diff --git a/ApplicationCode/FileInterface/RifSummaryCaseRestartSelector.cpp b/ApplicationCode/FileInterface/RifSummaryCaseRestartSelector.cpp index 42beb40b76..d4ff5fe7f4 100644 --- a/ApplicationCode/FileInterface/RifSummaryCaseRestartSelector.cpp +++ b/ApplicationCode/FileInterface/RifSummaryCaseRestartSelector.cpp @@ -70,11 +70,8 @@ RifSummaryCaseRestartSelector::RifSummaryCaseRestartSelector() { RiaPreferences* prefs = RiaApplication::instance()->preferences(); m_showDialog = prefs->summaryRestartFilesShowImportDialog(); - m_defaultSummaryImportMode = mapReadOption(prefs->summaryImportMode()); - m_defaultGridImportMode = mapReadOption(prefs->gridImportMode()); m_ensembleOrGroupMode = false; - //m_buildGridFileList = false; m_gridFiles.clear(); } @@ -176,7 +173,21 @@ void RifSummaryCaseRestartSelector::determineFilesToImportByAskingUser(const std m_summaryFileInfos.clear(); m_gridFiles.clear(); m_summaryFileErrors.clear(); - + + RiaPreferences* prefs = RiaApplication::instance()->preferences(); + + RicSummaryCaseRestartDialog::ImportOptions defaultSummaryImportMode; + if (m_ensembleOrGroupMode) + { + defaultSummaryImportMode = mapReadOption(prefs->summaryEnsembleImportMode()); + } + else + { + defaultSummaryImportMode = mapReadOption(prefs->summaryImportMode()); + } + + RicSummaryCaseRestartDialog::ImportOptions defaultGridImportMode = mapReadOption(prefs->gridImportMode()); + caf::ProgressInfo progress(initialFiles.size(), QString("Importing files")); for (const RifSummaryCaseFileImportInfo& initialFile : initialFiles) { @@ -185,8 +196,8 @@ void RifSummaryCaseRestartSelector::determineFilesToImportByAskingUser(const std initialFile.failOnSummaryFileError(), enableApplyToAllField, m_ensembleOrGroupMode, - m_defaultSummaryImportMode, - m_defaultGridImportMode, + defaultSummaryImportMode, + defaultGridImportMode, &lastResult); if (result.status == RicSummaryCaseRestartDialogResult::SUMMARY_CANCELLED) @@ -241,6 +252,18 @@ void RifSummaryCaseRestartSelector::determineFilesToImportUsingPrefs(const std:: m_gridFiles.clear(); m_summaryFileErrors.clear(); + RiaPreferences* prefs = RiaApplication::instance()->preferences(); + + RicSummaryCaseRestartDialog::ImportOptions defaultSummaryImportMode; + if (m_ensembleOrGroupMode) + { + defaultSummaryImportMode = mapReadOption(prefs->summaryEnsembleImportMode()); + } + else + { + defaultSummaryImportMode = mapReadOption(prefs->summaryImportMode()); + } + caf::ProgressInfo progress(initialFiles.size(), QString("Importing files")); for (const RifSummaryCaseFileImportInfo& initialFile : initialFiles) { @@ -251,15 +274,15 @@ void RifSummaryCaseRestartSelector::determineFilesToImportUsingPrefs(const std:: if (handleSummaryFile) { - if (m_defaultSummaryImportMode == RicSummaryCaseRestartDialog::IMPORT_ALL) + if (defaultSummaryImportMode == RicSummaryCaseRestartDialog::IMPORT_ALL) { m_summaryFileInfos.push_back(RifSummaryCaseFileResultInfo(initialSummaryFile, true)); } - else if (m_defaultSummaryImportMode == RicSummaryCaseRestartDialog::NOT_IMPORT) + else if (defaultSummaryImportMode == RicSummaryCaseRestartDialog::NOT_IMPORT) { m_summaryFileInfos.push_back(RifSummaryCaseFileResultInfo(initialSummaryFile, false)); } - else if (m_defaultSummaryImportMode == RicSummaryCaseRestartDialog::SEPARATE_CASES) + else if (defaultSummaryImportMode == RicSummaryCaseRestartDialog::SEPARATE_CASES) { m_summaryFileInfos.push_back(RifSummaryCaseFileResultInfo(initialSummaryFile, false)); bool hasWarnings = false; @@ -280,7 +303,8 @@ void RifSummaryCaseRestartSelector::determineFilesToImportUsingPrefs(const std:: { m_gridFiles.push_back(initialGridFile); - if (m_defaultGridImportMode == RicSummaryCaseRestartDialog::SEPARATE_CASES) + RicSummaryCaseRestartDialog::ImportOptions defaultGridImportMode = mapReadOption(prefs->gridImportMode()); + if (defaultGridImportMode == RicSummaryCaseRestartDialog::SEPARATE_CASES) { RifReaderEclipseSummary reader; bool hasWarnings = false; diff --git a/ApplicationCode/FileInterface/RifSummaryCaseRestartSelector.h b/ApplicationCode/FileInterface/RifSummaryCaseRestartSelector.h index 7885d5d437..afeaacd226 100644 --- a/ApplicationCode/FileInterface/RifSummaryCaseRestartSelector.h +++ b/ApplicationCode/FileInterface/RifSummaryCaseRestartSelector.h @@ -59,8 +59,6 @@ private: bool m_showDialog; bool m_ensembleOrGroupMode; - RicSummaryCaseRestartDialog::ImportOptions m_defaultSummaryImportMode; - RicSummaryCaseRestartDialog::ImportOptions m_defaultGridImportMode; std::vector m_summaryFileInfos; QStringList m_gridFiles; From 188e81d3d2bb14b17cb9a096e9b77ea40e751afb Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 21 Jun 2019 12:16:09 +0200 Subject: [PATCH 193/396] #4494 Grid Statistics : Update and compute data when visible cell changes from toggling LGR grids --- ApplicationCode/ProjectDataModel/RimEclipseView.cpp | 13 +++++++++---- ApplicationCode/ProjectDataModel/RimGeoMechView.cpp | 2 +- ApplicationCode/ProjectDataModel/RimGridView.cpp | 8 ++++++++ ApplicationCode/ProjectDataModel/RimGridView.h | 6 +++--- 4 files changed, 21 insertions(+), 8 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimEclipseView.cpp b/ApplicationCode/ProjectDataModel/RimEclipseView.cpp index aad32675ab..3a3f6807e4 100644 --- a/ApplicationCode/ProjectDataModel/RimEclipseView.cpp +++ b/ApplicationCode/ProjectDataModel/RimEclipseView.cpp @@ -346,6 +346,8 @@ void RimEclipseView::updateScaleTransform() //-------------------------------------------------------------------------------------------------- void RimEclipseView::createDisplayModel() { + clearReservoirCellVisibilities(); + if (m_viewer.isNull()) return; #if 0 // Debug info @@ -581,6 +583,8 @@ void RimEclipseView::createDisplayModel() //-------------------------------------------------------------------------------------------------- void RimEclipseView::updateCurrentTimeStep() { + clearReservoirCellVisibilities(); + m_propertyFilterCollection()->updateFromCurrentTimeStep(); updateLegends(); // To make sure the scalar mappers are set up correctly @@ -1095,7 +1099,7 @@ void RimEclipseView::scheduleGeometryRegen(RivCellSetEnum geometryType) } } - m_currentReservoirCellVisibility = nullptr; + clearReservoirCellVisibilities(); } //-------------------------------------------------------------------------------------------------- @@ -1104,7 +1108,7 @@ void RimEclipseView::scheduleGeometryRegen(RivCellSetEnum geometryType) void RimEclipseView::scheduleReservoirGridGeometryRegen() { m_reservoirGridPartManager->clearGeometryCache(); - m_currentReservoirCellVisibility = nullptr; + clearReservoirCellVisibilities(); } //-------------------------------------------------------------------------------------------------- @@ -1888,13 +1892,14 @@ void RimEclipseView::setOverridePropertyFilterCollection(RimEclipsePropertyFilte //-------------------------------------------------------------------------------------------------- void RimEclipseView::calculateCurrentTotalCellVisibility(cvf::UByteArray* totalVisibility, int timeStep) { - size_t gridCount = this->eclipseCase()->eclipseCaseData()->gridCount(); size_t cellCount = this->mainGrid()->globalCellArray().size(); totalVisibility->resize(cellCount); totalVisibility->setAll(false); - for (size_t gridIdx = 0; gridIdx < gridCount; ++gridIdx) + std::vector gridIndices = this->indicesToVisibleGrids(); + + for (auto gridIdx : gridIndices) { RigGridBase* grid = this->eclipseCase()->eclipseCaseData()->grid(gridIdx); int gridCellCount = static_cast(grid->cellCount()); diff --git a/ApplicationCode/ProjectDataModel/RimGeoMechView.cpp b/ApplicationCode/ProjectDataModel/RimGeoMechView.cpp index abccbc2345..a8efcb14f8 100644 --- a/ApplicationCode/ProjectDataModel/RimGeoMechView.cpp +++ b/ApplicationCode/ProjectDataModel/RimGeoMechView.cpp @@ -764,7 +764,7 @@ void RimGeoMechView::scheduleGeometryRegen(RivCellSetEnum geometryType) viewLinker->scheduleGeometryRegenForDepViews(geometryType); } } - m_currentReservoirCellVisibility = nullptr; + clearReservoirCellVisibilities(); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimGridView.cpp b/ApplicationCode/ProjectDataModel/RimGridView.cpp index 39b930891c..ef87be8137 100644 --- a/ApplicationCode/ProjectDataModel/RimGridView.cpp +++ b/ApplicationCode/ProjectDataModel/RimGridView.cpp @@ -427,6 +427,14 @@ RimGridCollection* RimGridView::gridCollection() const return m_gridCollection(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimGridView::clearReservoirCellVisibilities() +{ + m_currentReservoirCellVisibility = nullptr; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimGridView.h b/ApplicationCode/ProjectDataModel/RimGridView.h index 3da53aef10..d4d23c37fe 100644 --- a/ApplicationCode/ProjectDataModel/RimGridView.h +++ b/ApplicationCode/ProjectDataModel/RimGridView.h @@ -79,6 +79,8 @@ protected: RimGridCollection* gridCollection() const; + void clearReservoirCellVisibilities(); + protected: // Fields caf::PdmChildField m_crossSectionCollection; caf::PdmChildField m_overlayInfoConfig; @@ -87,10 +89,8 @@ protected: // Fields caf::PdmChildField m_gridCollection; caf::PdmChildField m_annotationCollection; -protected: - cvf::ref m_currentReservoirCellVisibility; - private: + cvf::ref m_currentReservoirCellVisibility; RimViewLinker* viewLinkerIfMasterView() const; bool m_previousGridModeMeshLinesWasFaults; }; From 512ecfdf74a9673d74e43edc41507dcc16ba6fc5 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 21 Jun 2019 22:19:55 +0200 Subject: [PATCH 194/396] #4502 Flow Characteristics Plot : Add legend titles --- .../RiuFlowCharacteristicsPlot.cpp | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.cpp b/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.cpp index 28dbb6bcc8..80bff9f85b 100644 --- a/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.cpp +++ b/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.cpp @@ -18,7 +18,10 @@ #include "RiuFlowCharacteristicsPlot.h" +#include "RiaApplication.h" #include "RiaColorTables.h" +#include "RiaFontCache.h" +#include "RiaPreferences.h" #include "RimFlowCharacteristicsPlot.h" @@ -84,10 +87,46 @@ RiuFlowCharacteristicsPlot::RiuFlowCharacteristicsPlot(RimFlowCharacteristicsPlo addWindowZoom(m_sweepEffPlot); m_sweepEffPlot->setTitle("Sweep Efficiency"); + int legendFontSize = RiaFontCache::pointSizeFromFontSizeEnum(RiaApplication::instance()->preferences()->defaultPlotFontSize()); + + { + QwtText axisTitle = m_sweepEffPlot->axisTitle(QwtPlot::xBottom); + auto font = axisTitle.font(); + font.setPointSize(legendFontSize); + axisTitle.setFont(font); + axisTitle.setText("Dimensionless Time"); + m_sweepEffPlot->setAxisTitle(QwtPlot::xBottom, axisTitle); + } + { + QwtText axisTitle = m_sweepEffPlot->axisTitle(QwtPlot::yLeft); + auto font = axisTitle.font(); + font.setPointSize(legendFontSize); + axisTitle.setFont(font); + axisTitle.setText("Sweep Efficiency"); + m_sweepEffPlot->setAxisTitle(QwtPlot::yLeft, axisTitle); + } + RiuQwtPlotTools::setCommonPlotBehaviour(m_flowCapVsStorageCapPlot); new RiuQwtPlotWheelZoomer(m_flowCapVsStorageCapPlot); addWindowZoom(m_flowCapVsStorageCapPlot); m_flowCapVsStorageCapPlot->setTitle("Flow Capacity vs Storage Capacity"); + + { + QwtText axisTitle = m_flowCapVsStorageCapPlot->axisTitle(QwtPlot::xBottom); + auto font = axisTitle.font(); + font.setPointSize(legendFontSize); + axisTitle.setFont(font); + axisTitle.setText("Storage Capacity [C]"); + m_flowCapVsStorageCapPlot->setAxisTitle(QwtPlot::xBottom, axisTitle); + } + { + QwtText axisTitle = m_flowCapVsStorageCapPlot->axisTitle(QwtPlot::yLeft); + auto font = axisTitle.font(); + font.setPointSize(legendFontSize); + axisTitle.setFont(font); + axisTitle.setText("Flow Capacity [F]"); + m_flowCapVsStorageCapPlot->setAxisTitle(QwtPlot::yLeft, axisTitle); + } } //-------------------------------------------------------------------------------------------------- From 5067c6ce9c5dc25be54cf9e7e822487bdb9d41e9 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Sun, 23 Jun 2019 15:02:45 +0200 Subject: [PATCH 195/396] #4503 Framework : Add support for passing text data to command features --- .../Application/RiaFeatureCommandContext.cpp | 77 ++++++++++++++++++- .../Application/RiaFeatureCommandContext.h | 28 +++++-- 2 files changed, 98 insertions(+), 7 deletions(-) diff --git a/ApplicationCode/Application/RiaFeatureCommandContext.cpp b/ApplicationCode/Application/RiaFeatureCommandContext.cpp index d671195dca..7337bbaad9 100644 --- a/ApplicationCode/Application/RiaFeatureCommandContext.cpp +++ b/ApplicationCode/Application/RiaFeatureCommandContext.cpp @@ -18,6 +18,8 @@ #include "RiaFeatureCommandContext.h" +#include + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -44,6 +46,52 @@ QObject* RiaFeatureCommandContext::object() const return m_pointerToQObject; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RiaFeatureCommandContext::titleString() const +{ + if (m_pointerToQObject) + { + QVariant variant = m_pointerToQObject->property(titleStringIdentifier().data()); + + return variant.toString(); + } + + return QString(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RiaFeatureCommandContext::contentString() const +{ + if (m_pointerToQObject) + { + QVariant variant = m_pointerToQObject->property(contentStringIdentifier().data()); + + return variant.toString(); + } + + return QString(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::string RiaFeatureCommandContext::titleStringIdentifier() +{ + return "titleStringIdentifier"; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::string RiaFeatureCommandContext::contentStringIdentifier() +{ + return "contentStringIdentifier"; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -56,9 +104,9 @@ RiaFeatureCommandContext* RiaFeatureCommandContext::instance() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RiaFeatureCommandContextHelper::RiaFeatureCommandContextHelper(QObject* object) +RiaFeatureCommandContextHelper::RiaFeatureCommandContextHelper(QObject* externalObject) { - RiaFeatureCommandContext::instance()->setObject(object); + RiaFeatureCommandContext::instance()->setObject(externalObject); } //-------------------------------------------------------------------------------------------------- @@ -68,3 +116,28 @@ RiaFeatureCommandContextHelper::~RiaFeatureCommandContextHelper() { RiaFeatureCommandContext::instance()->setObject(nullptr); } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiaFeatureCommandContextTextHelper::RiaFeatureCommandContextTextHelper(const QString& title, const QString& text) +{ + m_object = new QObject; + + m_object->setProperty(RiaFeatureCommandContext::titleStringIdentifier().data(), title); + m_object->setProperty(RiaFeatureCommandContext::contentStringIdentifier().data(), text); + + RiaFeatureCommandContext::instance()->setObject(m_object); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiaFeatureCommandContextTextHelper::~RiaFeatureCommandContextTextHelper() +{ + if (m_object) + { + m_object->deleteLater(); + m_object = nullptr; + } +} diff --git a/ApplicationCode/Application/RiaFeatureCommandContext.h b/ApplicationCode/Application/RiaFeatureCommandContext.h index 9ac89ddb4d..3c31ebd4be 100644 --- a/ApplicationCode/Application/RiaFeatureCommandContext.h +++ b/ApplicationCode/Application/RiaFeatureCommandContext.h @@ -29,16 +29,21 @@ class RiaFeatureCommandContext friend class RiaFeatureCommandContextHelper; public: - QObject* object() const; - static RiaFeatureCommandContext* instance(); + QObject* object() const; + void setObject(QObject* object); + + QString titleString() const; + QString contentString() const; + + static std::string titleStringIdentifier(); + static std::string contentStringIdentifier(); + private: RiaFeatureCommandContext(); ~RiaFeatureCommandContext(); - void setObject(QObject* object); - private: QPointer m_pointerToQObject; }; @@ -49,6 +54,19 @@ private: class RiaFeatureCommandContextHelper { public: - RiaFeatureCommandContextHelper(QObject* object); + RiaFeatureCommandContextHelper(QObject* externalObject); ~RiaFeatureCommandContextHelper(); }; + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +class RiaFeatureCommandContextTextHelper +{ +public: + RiaFeatureCommandContextTextHelper(const QString& title, const QString& text); + ~RiaFeatureCommandContextTextHelper(); + +private: + QObject* m_object; +}; From 79df075fe4ffabc748540373628d2fb79f84d115 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Sun, 23 Jun 2019 15:12:33 +0200 Subject: [PATCH 196/396] #4136 Export of Flow Characteristics : Rename --- .../ProjectDataModel/Flow/RimFlowCharacteristicsPlot.cpp | 8 ++++---- .../ReservoirDataModel/RigFlowDiagSolverInterface.cpp | 4 ++-- .../ReservoirDataModel/RigFlowDiagSolverInterface.h | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/Flow/RimFlowCharacteristicsPlot.cpp b/ApplicationCode/ProjectDataModel/Flow/RimFlowCharacteristicsPlot.cpp index 2d0cb446e4..f1229faefb 100644 --- a/ApplicationCode/ProjectDataModel/Flow/RimFlowCharacteristicsPlot.cpp +++ b/ApplicationCode/ProjectDataModel/Flow/RimFlowCharacteristicsPlot.cpp @@ -629,11 +629,11 @@ void RimFlowCharacteristicsPlot::onLoadDataAndUpdate() const auto& flowCharResults = timeStepToFlowResultMap[timeStepIdx]; m_flowCharPlotWidget->addFlowCapStorageCapCurve(timeStepDates[timeStepIdx], - flowCharResults.m_flowCapStorageCapCurve.first, - flowCharResults.m_flowCapStorageCapCurve.second); + flowCharResults.m_storageCapFlowCapCurve.first, + flowCharResults.m_storageCapFlowCapCurve.second); m_flowCharPlotWidget->addSweepEfficiencyCurve(timeStepDates[timeStepIdx], - flowCharResults.m_sweepEfficiencyCurve.first, - flowCharResults.m_sweepEfficiencyCurve.second); + flowCharResults.m_dimensionlessTimeSweepEfficiencyCurve.first, + flowCharResults.m_dimensionlessTimeSweepEfficiencyCurve.second); } m_flowCharPlotWidget->showLegend(m_showLegend()); diff --git a/ApplicationCode/ReservoirDataModel/RigFlowDiagSolverInterface.cpp b/ApplicationCode/ReservoirDataModel/RigFlowDiagSolverInterface.cpp index a962e592ee..3340bb2488 100644 --- a/ApplicationCode/ReservoirDataModel/RigFlowDiagSolverInterface.cpp +++ b/ApplicationCode/ReservoirDataModel/RigFlowDiagSolverInterface.cpp @@ -638,9 +638,9 @@ RigFlowDiagSolverInterface::FlowCharacteristicsResultFrame RigFlowDiagSolverInte poreVolume, max_pv_fraction); - result.m_flowCapStorageCapCurve = flowCapStorCapCurve; + result.m_storageCapFlowCapCurve = flowCapStorCapCurve; result.m_lorenzCoefficient = lorenzCoefficient(flowCapStorCapCurve); - result.m_sweepEfficiencyCurve = sweepEfficiency(flowCapStorCapCurve); + result.m_dimensionlessTimeSweepEfficiencyCurve = sweepEfficiency(flowCapStorCapCurve); } catch (const std::exception& e) { diff --git a/ApplicationCode/ReservoirDataModel/RigFlowDiagSolverInterface.h b/ApplicationCode/ReservoirDataModel/RigFlowDiagSolverInterface.h index 81b4a7ab3a..10fdecd728 100644 --- a/ApplicationCode/ReservoirDataModel/RigFlowDiagSolverInterface.h +++ b/ApplicationCode/ReservoirDataModel/RigFlowDiagSolverInterface.h @@ -70,8 +70,8 @@ public: using Curve = std::pair< std::vector, std::vector >; - Curve m_flowCapStorageCapCurve; - Curve m_sweepEfficiencyCurve; + Curve m_storageCapFlowCapCurve; + Curve m_dimensionlessTimeSweepEfficiencyCurve; double m_lorenzCoefficient; }; From 7879fe186d9a93814d08f1ed38e675748ac8145e Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Sun, 23 Jun 2019 15:18:17 +0200 Subject: [PATCH 197/396] #4136 Export of Flow Characteristics : Create text for export and add context menu --- .../RicShowPlotDataFeature.cpp | 46 ++++-- .../Flow/RimFlowCharacteristicsPlot.cpp | 145 ++++++++++++++++-- .../Flow/RimFlowCharacteristicsPlot.h | 3 + .../RiuFlowCharacteristicsPlot.cpp | 31 +++- .../RiuFlowCharacteristicsPlot.h | 1 + 5 files changed, 200 insertions(+), 26 deletions(-) diff --git a/ApplicationCode/Commands/ApplicationCommands/RicShowPlotDataFeature.cpp b/ApplicationCode/Commands/ApplicationCommands/RicShowPlotDataFeature.cpp index eafbaca629..3da8d88955 100644 --- a/ApplicationCode/Commands/ApplicationCommands/RicShowPlotDataFeature.cpp +++ b/ApplicationCode/Commands/ApplicationCommands/RicShowPlotDataFeature.cpp @@ -1,23 +1,24 @@ ///////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2017 Statoil ASA -// +// // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// +// // ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. -// -// See the GNU General Public License at +// +// See the GNU General Public License at // for more details. // ///////////////////////////////////////////////////////////////////////////////// #include "RicShowPlotDataFeature.h" +#include "RiaFeatureCommandContext.h" #include "RiaGuiApplication.h" #include "RimGridCrossPlot.h" @@ -36,7 +37,6 @@ #include - CAF_CMD_SOURCE_INIT(RicShowPlotDataFeature, "RicShowPlotDataFeature"); //-------------------------------------------------------------------------------------------------- @@ -166,11 +166,17 @@ private: /// /// /// RicShowPlotDataFeature -/// -/// +/// +/// //-------------------------------------------------------------------------------------------------- bool RicShowPlotDataFeature::isCommandEnabled() { + QString content = RiaFeatureCommandContext::instance()->contentString(); + if (!content.isEmpty()) + { + return true; + } + auto selectedSummaryPlots = caf::selectedObjectsByType(); if (selectedSummaryPlots.size() > 0) { @@ -195,15 +201,29 @@ bool RicShowPlotDataFeature::isCommandEnabled() } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- void RicShowPlotDataFeature::onActionTriggered(bool isChecked) { + QString content = RiaFeatureCommandContext::instance()->contentString(); + if (!content.isEmpty()) + { + QString title = "Data Content"; + { + QString titleCandidate = RiaFeatureCommandContext::instance()->titleString(); + if (!titleCandidate.isEmpty()) titleCandidate = titleCandidate; + } + + RicShowPlotDataFeature::showTextWindow(title, content); + + return; + } + this->disableModelChangeContribution(); std::vector selectedSummaryPlots = caf::selectedObjectsByType(); - std::vector wellLogPlots = caf::selectedObjectsByType(); - std::vector crossPlots = caf::selectedObjectsByType(); + std::vector wellLogPlots = caf::selectedObjectsByType(); + std::vector crossPlots = caf::selectedObjectsByType(); if (selectedSummaryPlots.size() == 0 && wellLogPlots.size() == 0 && crossPlots.size() == 0) { CVF_ASSERT(false); @@ -223,7 +243,7 @@ void RicShowPlotDataFeature::onActionTriggered(bool isChecked) for (RimWellLogPlot* wellLogPlot : wellLogPlots) { QString title = wellLogPlot->description(); - QString text = wellLogPlot->asciiDataForPlotExport(); + QString text = wellLogPlot->asciiDataForPlotExport(); RicShowPlotDataFeature::showTextWindow(title, text); } @@ -235,7 +255,7 @@ void RicShowPlotDataFeature::onActionTriggered(bool isChecked) } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- void RicShowPlotDataFeature::setupActionLook(QAction* actionToSetup) { @@ -244,7 +264,7 @@ void RicShowPlotDataFeature::setupActionLook(QAction* actionToSetup) } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- void RicShowPlotDataFeature::showTabbedTextWindow(RiuTabbedTextProvider* textProvider) { diff --git a/ApplicationCode/ProjectDataModel/Flow/RimFlowCharacteristicsPlot.cpp b/ApplicationCode/ProjectDataModel/Flow/RimFlowCharacteristicsPlot.cpp index f1229faefb..7d005f00b6 100644 --- a/ApplicationCode/ProjectDataModel/Flow/RimFlowCharacteristicsPlot.cpp +++ b/ApplicationCode/ProjectDataModel/Flow/RimFlowCharacteristicsPlot.cpp @@ -18,6 +18,8 @@ #include "RimFlowCharacteristicsPlot.h" +#include "RifEclipseDataTableFormatter.h" + #include "RigActiveCellInfo.h" #include "RigEclipseCaseData.h" #include "RigFlowDiagResults.h" @@ -555,19 +557,22 @@ void RimFlowCharacteristicsPlot::onLoadDataAndUpdate() if (m_flowDiagSolution && m_flowCharPlotWidget) { - RigFlowDiagResults* flowResult = m_flowDiagSolution->flowDiagResults(); - std::vector calculatedTimesteps = flowResult->calculatedTimeSteps(RigFlowDiagResultAddress::PHASE_ALL); + RigFlowDiagResults* flowResult = m_flowDiagSolution->flowDiagResults(); - if (m_timeStepSelectionType == SELECTED) { - for (int tsIdx : m_selectedTimeSteps()) - { - m_flowDiagSolution()->flowDiagResults()->maxAbsPairFlux(tsIdx); - } - calculatedTimesteps = m_selectedTimeSteps(); - } + std::vector calculatedTimesteps = flowResult->calculatedTimeSteps(RigFlowDiagResultAddress::PHASE_ALL); - m_currentlyPlottedTimeSteps = calculatedTimesteps; + if (m_timeStepSelectionType == SELECTED) + { + for (int tsIdx : m_selectedTimeSteps()) + { + m_flowDiagSolution()->flowDiagResults()->maxAbsPairFlux(tsIdx); + } + calculatedTimesteps = m_selectedTimeSteps(); + } + + m_currentlyPlottedTimeSteps = calculatedTimesteps; + } std::vector timeStepDates = m_case->timeStepDates(); QStringList timeStepStrings = m_case->timeStepStrings(); @@ -586,7 +591,7 @@ void RimFlowCharacteristicsPlot::onLoadDataAndUpdate() std::map timeStepToFlowResultMap; - for (int timeStepIdx : calculatedTimesteps) + for (int timeStepIdx : m_currentlyPlottedTimeSteps) { if (m_cellFilter() == RigFlowDiagResults::CELLS_VISIBLE) { @@ -622,9 +627,11 @@ void RimFlowCharacteristicsPlot::onLoadDataAndUpdate() lorenzVals[timeStepIdx] = timeStepToFlowResultMap[timeStepIdx].m_lorenzCoefficient; } + m_timeStepToFlowResultMap = timeStepToFlowResultMap; + m_flowCharPlotWidget->setLorenzCurve(timeStepStrings, timeStepDates, lorenzVals); - for (int timeStepIdx : calculatedTimesteps) + for (int timeStepIdx : m_currentlyPlottedTimeSteps) { const auto& flowCharResults = timeStepToFlowResultMap[timeStepIdx]; @@ -652,6 +659,120 @@ void RimFlowCharacteristicsPlot::viewGeometryUpdated() } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double interpolate(std::vector& xData, std::vector& yData, double x, bool extrapolate) +{ + size_t itemCount = xData.size(); + + size_t index = 0; + if (x >= xData[itemCount - 2]) + { + index = itemCount - 2; + } + else + { + while (x > xData[index + 1]) + index++; + } + double xLeft = xData[index]; + double yLeft = yData[index]; + double xRight = xData[index + 1]; + double yRight = yData[index + 1]; + + if (!extrapolate) + { + if (x < xLeft) yRight = yLeft; + if (x > xRight) yLeft = yRight; + } + + double dydx = (yRight - yLeft) / (xRight - xLeft); + + return yLeft + dydx * (x - xLeft); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RimFlowCharacteristicsPlot::curveDataAsText() const +{ + QString tableText; + + QTextStream stream(&tableText); + RifEclipseDataTableFormatter formatter(stream); + + std::vector header = { + RifEclipseOutputTableColumn("Date"), + RifEclipseOutputTableColumn("Storage Capacity"), + RifEclipseOutputTableColumn("Flow Capacity"), + RifEclipseOutputTableColumn("Sweep Efficiency"), + RifEclipseOutputTableColumn("Dimensionless Time"), + RifEclipseOutputTableColumn("Lorentz Coefficient"), + }; + + formatter.header(header); + + std::vector timeStepDates = m_case->timeStepDates(); + + std::vector storageCapacitySamplingValues = {0.08, 0.1, 0.2, 0.3, 0.4}; + size_t sampleCount = storageCapacitySamplingValues.size(); + + for (const auto& timeIndex : m_currentlyPlottedTimeSteps) + { + QString dateString = timeStepDates[timeIndex].toString("yyyy-MM-DD"); + + auto a = m_timeStepToFlowResultMap.find(timeIndex); + if (a != m_timeStepToFlowResultMap.end()) + { + auto storageCapacityValues = a->second.m_storageCapFlowCapCurve.first; + auto flowCapacityValues = a->second.m_storageCapFlowCapCurve.second; + + bool extrapolate = false; + std::vector flowCapacitySamplingValues; + for (const auto storageCapacity : storageCapacitySamplingValues) + { + { + double flowCapacity = interpolate(storageCapacityValues, flowCapacityValues, storageCapacity, extrapolate); + flowCapacitySamplingValues.push_back(flowCapacity); + } + } + + auto dimensionLessTimeValues = a->second.m_dimensionlessTimeSweepEfficiencyCurve.first; + auto sweepEffValues = a->second.m_dimensionlessTimeSweepEfficiencyCurve.second; + + std::vector dimensionLessTimeSamplingValues; + std::vector sweepEffSamplingValues; + double range = dimensionLessTimeValues.back() - dimensionLessTimeValues[0]; + double step = range / sampleCount; + for (size_t i = 0; i < sampleCount; i++) + { + double dimensionLessTimeValue = i * step; + dimensionLessTimeSamplingValues.push_back(dimensionLessTimeValue); + double sweepEffValue = interpolate(dimensionLessTimeValues, sweepEffValues, dimensionLessTimeValue, extrapolate); + sweepEffSamplingValues.push_back(sweepEffValue); + } + + auto lorentz = a->second.m_lorenzCoefficient; + + for (size_t i = 0; i < sampleCount; i++) + { + formatter.add(dateString); + formatter.add(storageCapacitySamplingValues[i]); + formatter.add(flowCapacitySamplingValues[i]); + formatter.add(sweepEffSamplingValues[i]); + formatter.add(dimensionLessTimeSamplingValues[i]); + formatter.add(lorentz); + formatter.rowCompleted(); + } + } + } + + formatter.tableCompleted(); + + return tableText; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/Flow/RimFlowCharacteristicsPlot.h b/ApplicationCode/ProjectDataModel/Flow/RimFlowCharacteristicsPlot.h index e5a1df6dcd..78fc196a87 100644 --- a/ApplicationCode/ProjectDataModel/Flow/RimFlowCharacteristicsPlot.h +++ b/ApplicationCode/ProjectDataModel/Flow/RimFlowCharacteristicsPlot.h @@ -67,6 +67,8 @@ public: void deleteViewWidget() override; void viewGeometryUpdated(); + QString curveDataAsText() const; + enum TimeSelectionType { ALL_AVAILABLE, @@ -107,6 +109,7 @@ private: caf::PdmField m_maxTof; std::vector m_currentlyPlottedTimeSteps; + std::map m_timeStepToFlowResultMap; QPointer m_flowCharPlotWidget; }; diff --git a/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.cpp b/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.cpp index 80bff9f85b..e47ea231b8 100644 --- a/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.cpp +++ b/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.cpp @@ -20,6 +20,7 @@ #include "RiaApplication.h" #include "RiaColorTables.h" +#include "RiaFeatureCommandContext.h" #include "RiaFontCache.h" #include "RiaPreferences.h" @@ -34,6 +35,8 @@ #include "cvfBase.h" #include "cvfColor3.h" +#include "cafCmdFeatureMenuBuilder.h" + #include "qwt_date.h" #include "qwt_legend.h" #include "qwt_plot.h" @@ -316,7 +319,33 @@ QSize RiuFlowCharacteristicsPlot::minimumSizeHint() const } //-------------------------------------------------------------------------------------------------- -/// +/// +//-------------------------------------------------------------------------------------------------- +void RiuFlowCharacteristicsPlot::contextMenuEvent(QContextMenuEvent* event) +{ + if (m_plotDefinition) + { + QString curveDataAsText = m_plotDefinition->curveDataAsText(); + + QString dialogTitle = "Flow Characteristics"; + + RiaFeatureCommandContextTextHelper helper(dialogTitle, curveDataAsText); + + caf::CmdFeatureMenuBuilder menuBuilder; + menuBuilder << "RicShowPlotDataFeature"; + + QMenu menu; + menuBuilder.appendToMenu(&menu); + + if (menu.actions().size() > 0) + { + menu.exec(event->globalPos()); + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// //-------------------------------------------------------------------------------------------------- QSize RiuFlowCharacteristicsPlot::sizeHint() const { diff --git a/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.h b/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.h index 13d2b05bce..3b3aa8e62a 100644 --- a/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.h +++ b/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.h @@ -68,6 +68,7 @@ public: protected: QSize sizeHint() const override; QSize minimumSizeHint() const override; + void contextMenuEvent(QContextMenuEvent* event) override; private: void setDefaults(); From 5dc4e08a03ce2aafb1a77c0ef8c02590e68795cd Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Sun, 23 Jun 2019 18:05:51 +0200 Subject: [PATCH 198/396] #4504 Framework : Add CSV text formatter --- .../FileInterface/CMakeLists_files.cmake | 2 + .../RifCsvDataTableFormatter.cpp | 138 ++++++++++++++++++ .../FileInterface/RifCsvDataTableFormatter.h | 50 +++++++ .../RifEclipseDataTableFormatter.h | 10 +- .../UnitTests/CMakeLists_files.cmake | 1 + .../RifCsvDataTableFormatter-Test.cpp | 48 ++++++ 6 files changed, 245 insertions(+), 4 deletions(-) create mode 100644 ApplicationCode/FileInterface/RifCsvDataTableFormatter.cpp create mode 100644 ApplicationCode/FileInterface/RifCsvDataTableFormatter.h create mode 100644 ApplicationCode/UnitTests/RifCsvDataTableFormatter-Test.cpp diff --git a/ApplicationCode/FileInterface/CMakeLists_files.cmake b/ApplicationCode/FileInterface/CMakeLists_files.cmake index b8ea98a084..c9e00fdb07 100644 --- a/ApplicationCode/FileInterface/CMakeLists_files.cmake +++ b/ApplicationCode/FileInterface/CMakeLists_files.cmake @@ -44,6 +44,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RifFileParseTools.h ${CMAKE_CURRENT_LIST_DIR}/RifEnsembleStatisticsReader.h ${CMAKE_CURRENT_LIST_DIR}/RifDerivedEnsembleReader.h ${CMAKE_CURRENT_LIST_DIR}/RifActiveCellsReader.h +${CMAKE_CURRENT_LIST_DIR}/RifCsvDataTableFormatter.h # HDF5 file reader is directly included in ResInsight main CmakeList.txt @@ -93,6 +94,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RifFileParseTools.cpp ${CMAKE_CURRENT_LIST_DIR}/RifEnsembleStatisticsReader.cpp ${CMAKE_CURRENT_LIST_DIR}/RifDerivedEnsembleReader.cpp ${CMAKE_CURRENT_LIST_DIR}/RifActiveCellsReader.cpp +${CMAKE_CURRENT_LIST_DIR}/RifCsvDataTableFormatter.cpp # HDF5 file reader is directly included in ResInsight main CmakeList.txt #${CMAKE_CURRENT_LIST_DIR}/RifHdf5Reader.cpp diff --git a/ApplicationCode/FileInterface/RifCsvDataTableFormatter.cpp b/ApplicationCode/FileInterface/RifCsvDataTableFormatter.cpp new file mode 100644 index 0000000000..ca502be7f3 --- /dev/null +++ b/ApplicationCode/FileInterface/RifCsvDataTableFormatter.cpp @@ -0,0 +1,138 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 "RifCsvDataTableFormatter.h" + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RifCsvDataTableFormatter::RifCsvDataTableFormatter(QTextStream& out, const QString fieldSeparator) + : m_out(out) + , m_fieldSeparator(fieldSeparator) +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RifCsvDataTableFormatter& RifCsvDataTableFormatter::header(const std::vector& tableHeader) +{ + outputBuffer(); + m_columnHeaders = tableHeader; + + return *this; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RifCsvDataTableFormatter& RifCsvDataTableFormatter::add(const QString& str) +{ + QString quotedString = "\"" + str + "\""; + m_lineBuffer.push_back(quotedString); + return *this; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RifCsvDataTableFormatter& RifCsvDataTableFormatter::add(double num) +{ + size_t column = m_lineBuffer.size(); + m_lineBuffer.push_back(RifEclipseDataTableFormatter::format(num, m_columnHeaders[column].doubleFormat)); + return *this; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RifCsvDataTableFormatter& RifCsvDataTableFormatter::add(int num) +{ + m_lineBuffer.push_back(RifEclipseDataTableFormatter::format(num)); + return *this; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RifCsvDataTableFormatter& RifCsvDataTableFormatter::add(size_t num) +{ + m_lineBuffer.push_back(RifEclipseDataTableFormatter::format(num)); + return *this; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RifCsvDataTableFormatter::rowCompleted() +{ + RifEclipseOutputTableLine line; + line.data = m_lineBuffer; + line.lineType = CONTENTS; + line.appendTextSet = false; + m_buffer.push_back(line); + m_lineBuffer.clear(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RifCsvDataTableFormatter::tableCompleted() +{ + outputBuffer(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RifCsvDataTableFormatter::outputBuffer() +{ + if (!m_columnHeaders.empty()) + { + for (size_t i = 0; i < m_columnHeaders.size(); i++) + { + m_out << m_columnHeaders[i].title; + + if (i < m_columnHeaders.size() - 1) + { + m_out << m_fieldSeparator; + } + } + m_out << "\n"; + } + + for (const auto& line : m_buffer) + { + if (line.lineType == CONTENTS) + { + QString lineText; + for (size_t i = 0; i < line.data.size(); i++) + { + lineText += line.data[i]; + if (i < line.data.size() - 1) + { + lineText += m_fieldSeparator; + } + } + + m_out << lineText << "\n"; + } + } + m_columnHeaders.clear(); + m_buffer.clear(); +} diff --git a/ApplicationCode/FileInterface/RifCsvDataTableFormatter.h b/ApplicationCode/FileInterface/RifCsvDataTableFormatter.h new file mode 100644 index 0000000000..882f3d11dd --- /dev/null +++ b/ApplicationCode/FileInterface/RifCsvDataTableFormatter.h @@ -0,0 +1,50 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 "RifEclipseDataTableFormatter.h" + +//================================================================================================== +// +// CSV text formatter using the same pattern as RifEclipseDataTableFormatter so it will be easy to switch formatters +// +//================================================================================================== +class RifCsvDataTableFormatter +{ +public: + RifCsvDataTableFormatter(QTextStream& out, const QString fieldSeparator = ","); + + RifCsvDataTableFormatter& header(const std::vector& tableHeader); + RifCsvDataTableFormatter& add(const QString& str); + RifCsvDataTableFormatter& add(double num); + RifCsvDataTableFormatter& add(int num); + RifCsvDataTableFormatter& add(size_t num); + void rowCompleted(); + void tableCompleted(); + +private: + void outputBuffer(); + +private: + QTextStream& m_out; + std::vector m_columnHeaders; + std::vector m_buffer; + std::vector m_lineBuffer; + QString m_fieldSeparator; +}; diff --git a/ApplicationCode/FileInterface/RifEclipseDataTableFormatter.h b/ApplicationCode/FileInterface/RifEclipseDataTableFormatter.h index 385dbe3636..6c55888a3c 100644 --- a/ApplicationCode/FileInterface/RifEclipseDataTableFormatter.h +++ b/ApplicationCode/FileInterface/RifEclipseDataTableFormatter.h @@ -139,15 +139,17 @@ public: int tableWidth() const; -private: +protected: + friend class RifCsvDataTableFormatter; + int measure(const QString str); int measure(double num, RifEclipseOutputTableDoubleFormatting doubleFormat); int measure(int num); int measure(size_t num); - QString format(double num, RifEclipseOutputTableDoubleFormatting doubleFormat); - QString format(int num); - QString format(size_t num); + static QString format(double num, RifEclipseOutputTableDoubleFormatting doubleFormat); + static QString format(int num); + static QString format(size_t num); QString formatColumn(const QString str, size_t columnIndex) const; void outputBuffer(); diff --git a/ApplicationCode/UnitTests/CMakeLists_files.cmake b/ApplicationCode/UnitTests/CMakeLists_files.cmake index 0d16177430..160b3fda66 100644 --- a/ApplicationCode/UnitTests/CMakeLists_files.cmake +++ b/ApplicationCode/UnitTests/CMakeLists_files.cmake @@ -56,6 +56,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RifPerforationIntervalReader-Test.cpp ${CMAKE_CURRENT_LIST_DIR}/RimWellPathCompletions-Test.cpp ${CMAKE_CURRENT_LIST_DIR}/RimSummaryCaseCollection-Test.cpp ${CMAKE_CURRENT_LIST_DIR}/RifActiveCellsReader-Test.cpp +${CMAKE_CURRENT_LIST_DIR}/RifCsvDataTableFormatter-Test.cpp ) if (RESINSIGHT_ENABLE_GRPC) diff --git a/ApplicationCode/UnitTests/RifCsvDataTableFormatter-Test.cpp b/ApplicationCode/UnitTests/RifCsvDataTableFormatter-Test.cpp new file mode 100644 index 0000000000..2c95bc6f8b --- /dev/null +++ b/ApplicationCode/UnitTests/RifCsvDataTableFormatter-Test.cpp @@ -0,0 +1,48 @@ +#include "gtest/gtest.h" + +#include "RifCsvDataTableFormatter.h" + +#include +#include + +TEST(RifCsvDataTableFormatter, BasicUsage) +{ + QString tableText; + QTextStream stream(&tableText); + RifCsvDataTableFormatter formatter(stream, ";"); + + std::vector header = { + RifEclipseOutputTableColumn("Well"), + RifEclipseOutputTableColumn("Integer Number"), + RifEclipseOutputTableColumn("sci", RifEclipseOutputTableDoubleFormat::RIF_SCIENTIFIC), + RifEclipseOutputTableColumn("float", RifEclipseOutputTableDoubleFormat::RIF_FLOAT), + RifEclipseOutputTableColumn("consise", RifEclipseOutputTableDoubleFormat::RIF_CONSISE), + }; + + formatter.header(header); + + formatter.add("well a"); + formatter.add(1); + formatter.add(2.123456789); + formatter.add(2.123456789); + formatter.add(2.123456789); + formatter.rowCompleted(); + + formatter.add("well B"); + formatter.add(12); + formatter.add(0.3e-12); + formatter.add(0.3e-12); + formatter.add(0.3e-12); + formatter.rowCompleted(); + + formatter.add("well c"); + formatter.add(123); + formatter.add(0.3e+12); + formatter.add(0.3e+12); + formatter.add(0.3e+12); + formatter.rowCompleted(); + + formatter.tableCompleted(); + + std::cout << tableText.toStdString(); +} From 3c644629dfc73572fe37a4ecd071f297fa983bef Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Sun, 23 Jun 2019 18:32:05 +0200 Subject: [PATCH 199/396] #4136 Export of Flow Characteristics : Use CSV text export --- ApplicationCode/Application/RiaPreferences.cpp | 9 ++++++++- ApplicationCode/Application/RiaPreferences.h | 1 + .../ApplicationCommands/RicShowPlotDataFeature.cpp | 2 +- .../Flow/RimFlowCharacteristicsPlot.cpp | 12 ++++++++---- 4 files changed, 18 insertions(+), 6 deletions(-) diff --git a/ApplicationCode/Application/RiaPreferences.cpp b/ApplicationCode/Application/RiaPreferences.cpp index f81d7f0a88..382478c581 100644 --- a/ApplicationCode/Application/RiaPreferences.cpp +++ b/ApplicationCode/Application/RiaPreferences.cpp @@ -125,6 +125,8 @@ RiaPreferences::RiaPreferences(void) CAF_PDM_InitField(&holoLensDisableCertificateVerification, "holoLensDisableCertificateVerification", false, "Disable SSL Certificate Verification (HoloLens)", "", "", ""); holoLensDisableCertificateVerification.uiCapability()->setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN); + CAF_PDM_InitField(&csvTextExportFieldSeparator, "csvTextExportFieldSeparator", QString(","), "CSV Text Export Field Separator", "", "", ""); + CAF_PDM_InitField(&m_showProjectChangedDialog, "showProjectChangedDialog", true, "Show 'Project has changed' dialog", "", "", ""); m_showProjectChangedDialog.uiCapability()->setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN); @@ -134,6 +136,7 @@ RiaPreferences::RiaPreferences(void) m_tabNames << "General"; m_tabNames << "Eclipse"; m_tabNames << "Scripting"; + m_tabNames << "Export"; if (RiaApplication::enableDevelopmentFeatures()) { m_tabNames << "System"; @@ -274,7 +277,11 @@ void RiaPreferences::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& scriptGroup->add(&scriptDirectories); scriptGroup->add(&scriptEditorExecutable); } - else if (RiaApplication::enableDevelopmentFeatures() && uiConfigName == m_tabNames[3]) + else if (uiConfigName == m_tabNames[3]) + { + uiOrdering.add(&csvTextExportFieldSeparator); + } + else if (RiaApplication::enableDevelopmentFeatures() && uiConfigName == m_tabNames[4]) { uiOrdering.add(&m_appendClassNameToUiText); uiOrdering.add(&m_appendFieldKeywordToToolTipText); diff --git a/ApplicationCode/Application/RiaPreferences.h b/ApplicationCode/Application/RiaPreferences.h index 26bdc5fc33..ebace447ab 100644 --- a/ApplicationCode/Application/RiaPreferences.h +++ b/ApplicationCode/Application/RiaPreferences.h @@ -109,6 +109,7 @@ public: // Pdm Fields caf::PdmField summaryEnsembleImportMode; caf::PdmField holoLensDisableCertificateVerification; + caf::PdmField csvTextExportFieldSeparator; protected: void defineEditorAttribute(const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute) override; diff --git a/ApplicationCode/Commands/ApplicationCommands/RicShowPlotDataFeature.cpp b/ApplicationCode/Commands/ApplicationCommands/RicShowPlotDataFeature.cpp index 3da8d88955..8c7963b3f8 100644 --- a/ApplicationCode/Commands/ApplicationCommands/RicShowPlotDataFeature.cpp +++ b/ApplicationCode/Commands/ApplicationCommands/RicShowPlotDataFeature.cpp @@ -211,7 +211,7 @@ void RicShowPlotDataFeature::onActionTriggered(bool isChecked) QString title = "Data Content"; { QString titleCandidate = RiaFeatureCommandContext::instance()->titleString(); - if (!titleCandidate.isEmpty()) titleCandidate = titleCandidate; + if (!titleCandidate.isEmpty()) title = titleCandidate; } RicShowPlotDataFeature::showTextWindow(title, content); diff --git a/ApplicationCode/ProjectDataModel/Flow/RimFlowCharacteristicsPlot.cpp b/ApplicationCode/ProjectDataModel/Flow/RimFlowCharacteristicsPlot.cpp index 7d005f00b6..eb11b10c0f 100644 --- a/ApplicationCode/ProjectDataModel/Flow/RimFlowCharacteristicsPlot.cpp +++ b/ApplicationCode/ProjectDataModel/Flow/RimFlowCharacteristicsPlot.cpp @@ -18,7 +18,10 @@ #include "RimFlowCharacteristicsPlot.h" -#include "RifEclipseDataTableFormatter.h" +#include "RiaApplication.h" +#include "RiaPreferences.h" + +#include "RifCsvDataTableFormatter.h" #include "RigActiveCellInfo.h" #include "RigEclipseCaseData.h" @@ -697,10 +700,11 @@ double interpolate(std::vector& xData, std::vector& yData, doubl //-------------------------------------------------------------------------------------------------- QString RimFlowCharacteristicsPlot::curveDataAsText() const { + QString fieldSeparator = RiaApplication::instance()->preferences()->csvTextExportFieldSeparator; QString tableText; - QTextStream stream(&tableText); - RifEclipseDataTableFormatter formatter(stream); + QTextStream stream(&tableText); + RifCsvDataTableFormatter formatter(stream, fieldSeparator); std::vector header = { RifEclipseOutputTableColumn("Date"), @@ -720,7 +724,7 @@ QString RimFlowCharacteristicsPlot::curveDataAsText() const for (const auto& timeIndex : m_currentlyPlottedTimeSteps) { - QString dateString = timeStepDates[timeIndex].toString("yyyy-MM-DD"); + QString dateString = timeStepDates[timeIndex].toString("yyyy-MM-dd"); auto a = m_timeStepToFlowResultMap.find(timeIndex); if (a != m_timeStepToFlowResultMap.end()) From c802ba1f9880de5c6f907c76a33c114bd307a15c Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Sun, 23 Jun 2019 18:39:04 +0200 Subject: [PATCH 200/396] #4495 Active Cells : Remove unused function --- .../RifEclipseOutputFileTools.cpp | 27 ------------------- .../FileInterface/RifEclipseOutputFileTools.h | 2 -- 2 files changed, 29 deletions(-) diff --git a/ApplicationCode/FileInterface/RifEclipseOutputFileTools.cpp b/ApplicationCode/FileInterface/RifEclipseOutputFileTools.cpp index 764736e624..0d8771893b 100644 --- a/ApplicationCode/FileInterface/RifEclipseOutputFileTools.cpp +++ b/ApplicationCode/FileInterface/RifEclipseOutputFileTools.cpp @@ -517,33 +517,6 @@ bool RifEclipseOutputFileTools::isExportedFromIntersect(const ecl_file_type* ecl return false; } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -ecl_kw_type* RifEclipseOutputFileTools::createActnumFromPorv(ecl_file_type* ecl_file) -{ - std::string porv_kw("PORV"); - - if (ecl_file_has_kw(ecl_file, porv_kw.data())) - { - ecl_file_view_type* fileView = ecl_file_get_global_view(ecl_file); - - int keywordCount = ecl_file_get_num_named_kw(ecl_file, porv_kw.data()); - for (int index = 0; index < keywordCount; index++) - { - ecl_kw_type* fileKeyword = ecl_file_view_iget_named_kw(fileView, porv_kw.data(), index); - if (fileKeyword) - { - float porvLimit = 0.0f; - - return ecl_kw_alloc_actnum(fileKeyword, porvLimit); - } - } - } - - return nullptr; -} - //-------------------------------------------------------------------------------------------------- /// Convenience method to hide C fopen calls in #pragma declarations to avoid warnings on Windows //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/FileInterface/RifEclipseOutputFileTools.h b/ApplicationCode/FileInterface/RifEclipseOutputFileTools.h index 88e509ef07..5cd65f8e0b 100644 --- a/ApplicationCode/FileInterface/RifEclipseOutputFileTools.h +++ b/ApplicationCode/FileInterface/RifEclipseOutputFileTools.h @@ -78,8 +78,6 @@ public: static bool isExportedFromIntersect(const ecl_file_type* ecl_file); - static ecl_kw_type* createActnumFromPorv(ecl_file_type* ecl_file); - static FILE* fopen(const QString& filePath, const QString& mode); private: From 56a53fedff3902512e2a48755880472118be2835 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Sun, 23 Jun 2019 19:00:14 +0200 Subject: [PATCH 201/396] Flow Characteristics : Load data in default plot when project is loaded --- .../ProjectDataModel/Flow/RimFlowPlotCollection.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ApplicationCode/ProjectDataModel/Flow/RimFlowPlotCollection.cpp b/ApplicationCode/ProjectDataModel/Flow/RimFlowPlotCollection.cpp index f4cb53f4a3..d06cf60635 100644 --- a/ApplicationCode/ProjectDataModel/Flow/RimFlowPlotCollection.cpp +++ b/ApplicationCode/ProjectDataModel/Flow/RimFlowPlotCollection.cpp @@ -92,6 +92,11 @@ void RimFlowPlotCollection::loadDataAndUpdate() p->loadDataAndUpdate(); plotProgress.incrementProgress(); } + + if (m_flowCharacteristicsPlot) + { + m_flowCharacteristicsPlot->loadDataAndUpdate(); + } } //-------------------------------------------------------------------------------------------------- From 055c1489b1b4b667843b339dd99950ba4091a173 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 24 Jun 2019 19:56:00 +0200 Subject: [PATCH 202/396] #4426 Linux : Avoid copy of libecl sym links Rename the libecl so file to match the file name ResInsight is depending on --- CMakeLists.txt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 273dc9432b..78b7106948 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -454,14 +454,14 @@ if (RESINSIGHT_PRIVATE_INSTALL) ################################################################################ if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") - set(ERT_SHARED_LIB_FILES - ${CMAKE_BINARY_DIR}/ThirdParty/Ert/${CMAKE_INSTALL_LIBDIR}/libecl.so - ${CMAKE_BINARY_DIR}/ThirdParty/Ert/${CMAKE_INSTALL_LIBDIR}/libecl.so.2 - ${CMAKE_BINARY_DIR}/ThirdParty/Ert/${CMAKE_INSTALL_LIBDIR}/libecl.so.2.4 - ) + get_filename_component(ERT_SHARED_LIB_FILES ${CMAKE_BINARY_DIR}/ThirdParty/Ert/${CMAKE_INSTALL_LIBDIR}/libecl.so.2 REALPATH) + + get_filename_component(FILE_NAME_WE ${ERT_SHARED_LIB_FILES} NAME_WE) + set(FILE_NAME_FOR_INSTALL "${FILE_NAME_WE}.so.2") + message (STATUS "libecl FILE_NAME_FOR_INSTALL - ${FILE_NAME_FOR_INSTALL}") - install(FILES ${ERT_SHARED_LIB_FILES} DESTINATION ${RESINSIGHT_INSTALL_FOLDER} ) - endif() + install(FILES ${ERT_SHARED_LIB_FILES} DESTINATION ${RESINSIGHT_INSTALL_FOLDER} RENAME ${FILE_NAME_FOR_INSTALL} ) + endif(${CMAKE_SYSTEM_NAME} MATCHES "Linux") endif (RESINSIGHT_PRIVATE_INSTALL) From 40c89489e81a80c7bef9803bd61f8b04acd23812 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 24 Jun 2019 19:59:16 +0200 Subject: [PATCH 203/396] #4426 Linux : Add flag to allow bundle of Qt5 libraries --- ApplicationCode/CMakeLists.txt | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/ApplicationCode/CMakeLists.txt b/ApplicationCode/CMakeLists.txt index b43668d54b..2062f17bd4 100644 --- a/ApplicationCode/CMakeLists.txt +++ b/ApplicationCode/CMakeLists.txt @@ -584,6 +584,23 @@ if (RESINSIGHT_PRIVATE_INSTALL) set_target_properties (ResInsight PROPERTIES INSTALL_RPATH "${RESINSIGHT_INSTALL_RPATH}") + # bundle Qt5 libraries + option (RESINSIGHT_QT5_BUNDLE_LIBRARIES "Bundle Qt5 libraries" OFF) + mark_as_advanced(FORCE RESINSIGHT_QT5_BUNDLE_LIBRARIES) + if (RESINSIGHT_QT5_BUNDLE_LIBRARIES) + message( STATUS "Bundling of Qt5 libraries is enabled" ) + + foreach (qtlib ${QT_LIBRARIES}) + get_target_property(FILE_NAME_FULL_PATH ${qtlib} LOCATION) + message (STATUS "${qtlib} location on disk - ${FILE_NAME_FULL_PATH}") + get_filename_component(FILE_NAME_WE ${FILE_NAME_FULL_PATH} NAME_WE) + set(FILE_NAME_FOR_INSTALL "${FILE_NAME_WE}.so.5") + message (STATUS "${qtlib} filename for install - ${FILE_NAME_FOR_INSTALL}") + + install(FILES ${FILE_NAME_FULL_PATH} DESTINATION ${RESINSIGHT_INSTALL_FOLDER} RENAME ${FILE_NAME_FOR_INSTALL} ) + endforeach() + endif(RESINSIGHT_QT5_BUNDLE_LIBRARIES) + endif() if (${CMAKE_SYSTEM_NAME} MATCHES "Windows") From 4de0799b2ef5185025f3f172e7cfb8b2abe39981 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 25 Jun 2019 13:06:28 +0200 Subject: [PATCH 204/396] #4426 Linux : Write out full path to source library file --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 78b7106948..e755e83117 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -455,6 +455,7 @@ if (RESINSIGHT_PRIVATE_INSTALL) if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") get_filename_component(ERT_SHARED_LIB_FILES ${CMAKE_BINARY_DIR}/ThirdParty/Ert/${CMAKE_INSTALL_LIBDIR}/libecl.so.2 REALPATH) + message (STATUS "libecl real path - ${ERT_SHARED_LIB_FILES}") get_filename_component(FILE_NAME_WE ${ERT_SHARED_LIB_FILES} NAME_WE) set(FILE_NAME_FOR_INSTALL "${FILE_NAME_WE}.so.2") From a4973dbb62ae563141ccefc0d091d988ddac89e3 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 25 Jun 2019 14:31:59 +0200 Subject: [PATCH 205/396] Revert "#4426 Linux : Avoid copy of libecl sym links" This reverts commit 055c1489b1b4b667843b339dd99950ba4091a173. --- CMakeLists.txt | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e755e83117..273dc9432b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -454,15 +454,14 @@ if (RESINSIGHT_PRIVATE_INSTALL) ################################################################################ if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") - get_filename_component(ERT_SHARED_LIB_FILES ${CMAKE_BINARY_DIR}/ThirdParty/Ert/${CMAKE_INSTALL_LIBDIR}/libecl.so.2 REALPATH) - message (STATUS "libecl real path - ${ERT_SHARED_LIB_FILES}") - - get_filename_component(FILE_NAME_WE ${ERT_SHARED_LIB_FILES} NAME_WE) - set(FILE_NAME_FOR_INSTALL "${FILE_NAME_WE}.so.2") - message (STATUS "libecl FILE_NAME_FOR_INSTALL - ${FILE_NAME_FOR_INSTALL}") + set(ERT_SHARED_LIB_FILES + ${CMAKE_BINARY_DIR}/ThirdParty/Ert/${CMAKE_INSTALL_LIBDIR}/libecl.so + ${CMAKE_BINARY_DIR}/ThirdParty/Ert/${CMAKE_INSTALL_LIBDIR}/libecl.so.2 + ${CMAKE_BINARY_DIR}/ThirdParty/Ert/${CMAKE_INSTALL_LIBDIR}/libecl.so.2.4 + ) - install(FILES ${ERT_SHARED_LIB_FILES} DESTINATION ${RESINSIGHT_INSTALL_FOLDER} RENAME ${FILE_NAME_FOR_INSTALL} ) - endif(${CMAKE_SYSTEM_NAME} MATCHES "Linux") + install(FILES ${ERT_SHARED_LIB_FILES} DESTINATION ${RESINSIGHT_INSTALL_FOLDER} ) + endif() endif (RESINSIGHT_PRIVATE_INSTALL) From eb258ee7425012c06d504656b86e1039be9fe4d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Tue, 25 Jun 2019 16:41:22 +0200 Subject: [PATCH 206/396] AppFwk: Added missign guard against nullptr --- Fwk/AppFwk/cafUserInterface/cafPdmUiTreeViewQModel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeViewQModel.cpp b/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeViewQModel.cpp index f87092a278..44c8b1727c 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeViewQModel.cpp +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeViewQModel.cpp @@ -69,7 +69,7 @@ PdmUiTreeViewQModel::PdmUiTreeViewQModel(PdmUiTreeViewEditor* treeViewEditor) void PdmUiTreeViewQModel::setPdmItemRoot(PdmUiItem* rootItem) { // Check if we are already watching this root - if (m_treeOrderingRoot && m_treeOrderingRoot->activeItem() == rootItem) + if (rootItem && m_treeOrderingRoot && m_treeOrderingRoot->activeItem() == rootItem) { this->updateSubTree(rootItem); return; From 72d4c0b51ab6c8f218fc737f16d5248566c934cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Tue, 25 Jun 2019 16:42:38 +0200 Subject: [PATCH 207/396] AppFwk: Added pdm field of cvf::Mat3d --- Fwk/AppFwk/cafPdmCvf/CMakeLists.txt | 10 +++ .../cafPdmCvf/cafPdmMat3d/cafPdmCoreMat3d.h | 82 ++++++++++++++++++ .../cafPdmMat3d/cafPdmFieldCvfMat3d.h | 41 +++++++++ .../cafPdmCvf/cafPdmMat3d/cafPdmUiCoreMat3d.h | 85 +++++++++++++++++++ .../cafPdmCvf/cafPdmMat3d/cafPdmXmlMat3d.cpp | 70 +++++++++++++++ .../cafPdmCvf/cafPdmMat3d/cafPdmXmlMat3d.h | 45 ++++++++++ 6 files changed, 333 insertions(+) create mode 100644 Fwk/AppFwk/cafPdmCvf/cafPdmMat3d/cafPdmCoreMat3d.h create mode 100644 Fwk/AppFwk/cafPdmCvf/cafPdmMat3d/cafPdmFieldCvfMat3d.h create mode 100644 Fwk/AppFwk/cafPdmCvf/cafPdmMat3d/cafPdmUiCoreMat3d.h create mode 100644 Fwk/AppFwk/cafPdmCvf/cafPdmMat3d/cafPdmXmlMat3d.cpp create mode 100644 Fwk/AppFwk/cafPdmCvf/cafPdmMat3d/cafPdmXmlMat3d.h diff --git a/Fwk/AppFwk/cafPdmCvf/CMakeLists.txt b/Fwk/AppFwk/cafPdmCvf/CMakeLists.txt index c591101321..04379861f7 100644 --- a/Fwk/AppFwk/cafPdmCvf/CMakeLists.txt +++ b/Fwk/AppFwk/cafPdmCvf/CMakeLists.txt @@ -36,11 +36,21 @@ add_library( ${PROJECT_NAME} cafPdmXmlMat4d.cpp cafPdmXmlMat4d.h cafPdmFieldCvfMat4d.h + + cafPdmMat3d/cafPdmCoreMat3d.h + cafPdmMat3d/cafPdmUiCoreMat3d.h + cafPdmMat3d/cafPdmXmlMat3d.cpp + cafPdmMat3d/cafPdmXmlMat3d.h + cafPdmMat3d/cafPdmFieldCvfMat3d.h + + ${MOC_HEADER_FILES} + ${MOC_SOURCE_FILES} ) target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/cafPdmMat3d ) target_link_libraries ( ${PROJECT_NAME} diff --git a/Fwk/AppFwk/cafPdmCvf/cafPdmMat3d/cafPdmCoreMat3d.h b/Fwk/AppFwk/cafPdmCvf/cafPdmMat3d/cafPdmCoreMat3d.h new file mode 100644 index 0000000000..031756f2a8 --- /dev/null +++ b/Fwk/AppFwk/cafPdmCvf/cafPdmMat3d/cafPdmCoreMat3d.h @@ -0,0 +1,82 @@ +//################################################################################################## +// +// Custom Visualization Core library +// Copyright (C) Ceetron Solutions AS +// +// This library may be used under the terms of either the GNU General Public License or +// the GNU Lesser General Public License as follows: +// +// GNU General Public License Usage +// This library 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. +// +// This library 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. +// +// GNU Lesser General Public License Usage +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This library 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 Lesser General Public License at <> +// for more details. +// +//################################################################################################## + +#pragma once + +#include "cvfBase.h" +#include "cvfMatrix3.h" + +#include "cafInternalPdmValueFieldSpecializations.h" + +#include "cafPdmXmlMat3d.h" + + +namespace caf +{ + +template <> +class PdmValueFieldSpecialization < cvf::Mat3d > +{ +public: + /// Convert the field value into a QVariant + static QVariant convert(const cvf::Mat3d& value) + { + QString str; + + QTextStream textStream(&str); + textStream << value; + + return QVariant(str); + } + + /// Set the field value from a QVariant + static void setFromVariant(const QVariant& variantValue, cvf::Mat3d& value) + { + QString str = variantValue.toString(); + + QTextStream textStream(&str); + + textStream >> value; + } + + static bool isEqual(const QVariant& variantValue, const QVariant& variantValue2) + { + return variantValue == variantValue2; + } +}; + + +} // end namespace caf diff --git a/Fwk/AppFwk/cafPdmCvf/cafPdmMat3d/cafPdmFieldCvfMat3d.h b/Fwk/AppFwk/cafPdmCvf/cafPdmMat3d/cafPdmFieldCvfMat3d.h new file mode 100644 index 0000000000..f4b2f21e8d --- /dev/null +++ b/Fwk/AppFwk/cafPdmCvf/cafPdmMat3d/cafPdmFieldCvfMat3d.h @@ -0,0 +1,41 @@ +//################################################################################################## +// +// Custom Visualization Core library +// Copyright (C) Ceetron Solutions AS +// +// This library may be used under the terms of either the GNU General Public License or +// the GNU Lesser General Public License as follows: +// +// GNU General Public License Usage +// This library 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. +// +// This library 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. +// +// GNU Lesser General Public License Usage +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This library 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 Lesser General Public License at <> +// for more details. +// +//################################################################################################## + +#pragma once + +#include "cafPdmCoreMat3d.h" +#include "cafPdmXmlMat3d.h" +#include "cafPdmUiCoreMat3d.h" diff --git a/Fwk/AppFwk/cafPdmCvf/cafPdmMat3d/cafPdmUiCoreMat3d.h b/Fwk/AppFwk/cafPdmCvf/cafPdmMat3d/cafPdmUiCoreMat3d.h new file mode 100644 index 0000000000..a2bfe89828 --- /dev/null +++ b/Fwk/AppFwk/cafPdmCvf/cafPdmMat3d/cafPdmUiCoreMat3d.h @@ -0,0 +1,85 @@ +//################################################################################################## +// +// Custom Visualization Core library +// Copyright (C) Ceetron Solutions AS +// +// This library may be used under the terms of either the GNU General Public License or +// the GNU Lesser General Public License as follows: +// +// GNU General Public License Usage +// This library 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. +// +// This library 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. +// +// GNU Lesser General Public License Usage +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This library 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 Lesser General Public License at <> +// for more details. +// +//################################################################################################## + +#pragma once + +#include "cafPdmCoreMat3d.h" + +#include "cafInternalPdmValueFieldSpecializations.h" +#include "cafPdmUiFieldSpecialization.h" +#include "cafPdmUiItem.h" + +#include "cvfBase.h" +#include "cvfMatrix3.h" + +namespace caf +{ + +template <> +class PdmUiFieldSpecialization < cvf::Mat3d > +{ +public: + /// Convert the field value into a QVariant + static QVariant convert(const cvf::Mat3d& value) + { + return PdmValueFieldSpecialization< cvf::Mat3d >::convert(value); + } + + /// Set the field value from a QVariant + static void setFromVariant(const QVariant& variantValue, cvf::Mat3d& value) + { + PdmValueFieldSpecialization< cvf::Mat3d >::setFromVariant(variantValue, value); + } + + static bool isDataElementEqual(const QVariant& variantValue, const QVariant& variantValue2) + { + return PdmValueFieldSpecialization< cvf::Mat3d >::isEqual(variantValue, variantValue2); + } + + /// Methods to get a list of options for a field, specialized for AppEnum + static QList valueOptions(bool* useOptionsOnly, const cvf::Mat3d&) + { + return QList(); + } + + /// Methods to retrieve the possible PdmObject pointed to by a field + static void childObjects(const PdmDataValueField< cvf::Mat3d >&, std::vector*) + { } + +}; + +} // end namespace caf + diff --git a/Fwk/AppFwk/cafPdmCvf/cafPdmMat3d/cafPdmXmlMat3d.cpp b/Fwk/AppFwk/cafPdmCvf/cafPdmMat3d/cafPdmXmlMat3d.cpp new file mode 100644 index 0000000000..8c97f26de9 --- /dev/null +++ b/Fwk/AppFwk/cafPdmCvf/cafPdmMat3d/cafPdmXmlMat3d.cpp @@ -0,0 +1,70 @@ +//################################################################################################## +// +// Custom Visualization Core library +// Copyright (C) Ceetron Solutions AS +// +// This library may be used under the terms of either the GNU General Public License or +// the GNU Lesser General Public License as follows: +// +// GNU General Public License Usage +// This library 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. +// +// This library 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. +// +// GNU Lesser General Public License Usage +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This library 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 Lesser General Public License at <> +// for more details. +// +//################################################################################################## + +#include "cafPdmXmlMat3d.h" + +#include + +QTextStream& operator >> (QTextStream& str, cvf::Mat3d& value) +{ + for (int r = 0; r < 3; ++r) + { + for (int c = 0; c < 3; ++c) + { + str >> value(r, c); + } + } + + return str; +} + +QTextStream& operator << (QTextStream& str, const cvf::Mat3d& value) +{ + for (int r = 0; r < 3; ++r) + { + for (int c = 0; c < 3; ++c) + { + str << value(r, c); + + if (r * c < 9) + { + str << " "; + } + } + } + + return str; +} diff --git a/Fwk/AppFwk/cafPdmCvf/cafPdmMat3d/cafPdmXmlMat3d.h b/Fwk/AppFwk/cafPdmCvf/cafPdmMat3d/cafPdmXmlMat3d.h new file mode 100644 index 0000000000..d84859f0ca --- /dev/null +++ b/Fwk/AppFwk/cafPdmCvf/cafPdmMat3d/cafPdmXmlMat3d.h @@ -0,0 +1,45 @@ +//################################################################################################## +// +// Custom Visualization Core library +// Copyright (C) Ceetron Solutions AS +// +// This library may be used under the terms of either the GNU General Public License or +// the GNU Lesser General Public License as follows: +// +// GNU General Public License Usage +// This library 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. +// +// This library 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. +// +// GNU Lesser General Public License Usage +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This library 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 Lesser General Public License at <> +// for more details. +// +//################################################################################################## + +#pragma once + +#include "cvfBase.h" +#include "cvfMatrix3.h" + +class QTextStream; + +QTextStream& operator >> (QTextStream& str, cvf::Mat3d& value); +QTextStream& operator << (QTextStream& str, const cvf::Mat3d& value); From f1dfab043384f697040308b7b6ea83eb2c3b8dac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Tue, 25 Jun 2019 16:46:29 +0200 Subject: [PATCH 208/396] AppFwk: Make push button editor fill the column if Label position is HIDDEN --- Fwk/AppFwk/cafUserInterface/cafPdmUiPushButtonEditor.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiPushButtonEditor.cpp b/Fwk/AppFwk/cafUserInterface/cafPdmUiPushButtonEditor.cpp index d525e7f170..83c0f441be 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiPushButtonEditor.cpp +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiPushButtonEditor.cpp @@ -103,9 +103,12 @@ void PdmUiPushButtonEditor::configureAndUpdateUi(const QString& uiConfigName) } } - QSize defaultSize = m_pushButton->sizeHint(); - m_pushButton->setMinimumWidth(10*std::round(0.1*(defaultSize.width() + 10))); - m_buttonLayout->setAlignment(m_pushButton, Qt::AlignRight); + if ( uiField()->uiLabelPosition(uiConfigName) != PdmUiItemInfo::HIDDEN ) + { + QSize defaultSize = m_pushButton->sizeHint(); + m_pushButton->setMinimumWidth(10*std::round(0.1*(defaultSize.width() + 10))); + m_buttonLayout->setAlignment(m_pushButton, Qt::AlignRight); + } if (variantFieldValue.type() == QVariant::Bool) { From 183988befd8c956ceaf3cde598af226feb1ac5fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Tue, 25 Jun 2019 16:47:22 +0200 Subject: [PATCH 209/396] AppFwk: Filepath Editor: Made browse button inactive when field is read only. --- Fwk/AppFwk/cafUserInterface/cafPdmUiFilePathEditor.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiFilePathEditor.cpp b/Fwk/AppFwk/cafUserInterface/cafPdmUiFilePathEditor.cpp index 84cea13657..bc83858b0d 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiFilePathEditor.cpp +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiFilePathEditor.cpp @@ -70,6 +70,7 @@ void PdmUiFilePathEditor::configureAndUpdateUi(const QString& uiConfigName) m_lineEdit->setEnabled(!uiField()->isUiReadOnly(uiConfigName)); m_lineEdit->setToolTip(uiField()->uiToolTip(uiConfigName)); + m_button->setEnabled(!uiField()->isUiReadOnly(uiConfigName)); caf::PdmUiObjectHandle* uiObject = uiObj(uiField()->fieldHandle()->ownerObject()); if (uiObject) From ce91cc3cc247745d981c9099f65fdf719b8068f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Tue, 25 Jun 2019 16:50:03 +0200 Subject: [PATCH 210/396] AppFwk: PdmSettings: Added methods that reads and writes (only) valuefields of an object properly --- .../cafPdmXml/cafPdmSettings.cpp | 84 ++++++++++++++++++- .../cafPdmXml/cafPdmSettings.h | 3 + 2 files changed, 86 insertions(+), 1 deletion(-) diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmXml/cafPdmSettings.cpp b/Fwk/AppFwk/cafProjectDataModel/cafPdmXml/cafPdmSettings.cpp index faa6888b35..7e0c7dd049 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmXml/cafPdmSettings.cpp +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmXml/cafPdmSettings.cpp @@ -41,7 +41,6 @@ #include "cafPdmXmlObjectHandle.h" - namespace caf { @@ -138,5 +137,88 @@ void PdmSettings::writeFieldsToApplicationStore(const caf::PdmObjectHandle* obje } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void PdmSettings::readValueFieldsFromApplicationStore(caf::PdmObjectHandle* object, const QString folderName /*= ""*/) +{ + // Qt doc : + // + // Constructs a QSettings object for accessing settings of the application and organization + // set previously with a call to QCoreApplication::setOrganizationName(), + // QCoreApplication::setOrganizationDomain(), and QCoreApplication::setApplicationName(). + QSettings settings; + + if ( folderName != "" ) + { + settings.beginGroup(folderName); + } + + std::vector fields; + + object->fields(fields); + size_t i; + for (i = 0; i < fields.size(); i++) + { + caf::PdmFieldHandle* fieldHandle = fields[i]; + caf::PdmValueField* valueField = dynamic_cast(fieldHandle); + + if (valueField) + { + QString key = fieldHandle->keyword(); + if ( settings.contains(key) ) + { + QVariant val = settings.value(key); + + QString fieldText = "" + val.toString() + ""; + QXmlStreamReader reader(fieldText); + + // Make stream point to the text data for the field + reader.readNext(); // StartDocument + reader.readNext(); // StartElement + reader.readNext(); // Characters + fieldHandle->xmlCapability()->readFieldData(reader, nullptr); + } + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void PdmSettings::writeValueFieldsToApplicationStore(const caf::PdmObjectHandle* object, const QString folderName /*= ""*/) +{ + CAF_ASSERT(object); + + // Qt doc : + // + // Constructs a QSettings object for accessing settings of the application and organization + // set previously with a call to QCoreApplication::setOrganizationName(), + // QCoreApplication::setOrganizationDomain(), and QCoreApplication::setApplicationName(). + QSettings settings; + + if ( folderName != "" ) + { + settings.beginGroup(folderName); + } + + std::vector fields; + object->fields(fields); + + size_t i; + for (i = 0; i < fields.size(); i++) + { + caf::PdmFieldHandle* fieldHandle = fields[i]; + caf::PdmValueField* valueField = dynamic_cast(fieldHandle); + if (valueField) + { + QString fieldText; + QXmlStreamWriter writer(&fieldText); + + fieldHandle->xmlCapability()->writeFieldData(writer); + settings.setValue(fieldHandle->keyword(), fieldText); + } + } +} } // namespace caf diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmXml/cafPdmSettings.h b/Fwk/AppFwk/cafProjectDataModel/cafPdmXml/cafPdmSettings.h index 8de5adc6ea..4962fbb211 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmXml/cafPdmSettings.h +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmXml/cafPdmSettings.h @@ -49,6 +49,9 @@ class PdmSettings public: static void readFieldsFromApplicationStore(caf::PdmObjectHandle* object, const QString context = ""); static void writeFieldsToApplicationStore(const caf::PdmObjectHandle* object, const QString context = ""); + + static void readValueFieldsFromApplicationStore(caf::PdmObjectHandle* object, const QString folderName = ""); + static void writeValueFieldsToApplicationStore(const caf::PdmObjectHandle* object, const QString folderName = ""); }; From cc2b19cb57e4b2153a5a5d3e0ef19110be583d3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Tue, 25 Jun 2019 16:50:46 +0200 Subject: [PATCH 211/396] AppFwk: Added a tabbed property view dialog as convenience until we have a "tab" option in the uiOrdering system --- Fwk/AppFwk/cafUserInterface/CMakeLists.txt | 2 + .../cafPdmUiTabbedPropertyViewDialog.cpp | 117 ++++++++++++++++++ .../cafPdmUiTabbedPropertyViewDialog.h | 39 ++++++ 3 files changed, 158 insertions(+) create mode 100644 Fwk/AppFwk/cafUserInterface/cafPdmUiTabbedPropertyViewDialog.cpp create mode 100644 Fwk/AppFwk/cafUserInterface/cafPdmUiTabbedPropertyViewDialog.h diff --git a/Fwk/AppFwk/cafUserInterface/CMakeLists.txt b/Fwk/AppFwk/cafUserInterface/CMakeLists.txt index 5f2bf15809..247e12db1d 100644 --- a/Fwk/AppFwk/cafUserInterface/CMakeLists.txt +++ b/Fwk/AppFwk/cafUserInterface/CMakeLists.txt @@ -155,6 +155,8 @@ set( PROJECT_FILES cafPdmUiPickableLineEditor.cpp cafStyleSheetTools.h cafStyleSheetTools.cpp + cafPdmUiTabbedPropertyViewDialog.h + cafPdmUiTabbedPropertyViewDialog.cpp ) add_library( ${PROJECT_NAME} diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiTabbedPropertyViewDialog.cpp b/Fwk/AppFwk/cafUserInterface/cafPdmUiTabbedPropertyViewDialog.cpp new file mode 100644 index 0000000000..6076f4f364 --- /dev/null +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiTabbedPropertyViewDialog.cpp @@ -0,0 +1,117 @@ + +#include "cafPdmUiTabbedPropertyViewDialog.h" + +#include "cafPdmObject.h" +#include "cafPdmUiPropertyView.h" + +#include +#include +#include +#include +#include +#include + +namespace caf +{ + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +PdmUiTabbedPropertyViewDialog::PdmUiTabbedPropertyViewDialog(caf::PdmObject* object, + const QStringList& uiConfigNameForTabs, + const QString& windowTitle, + QWidget* parent) + : QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint) +{ + this->setWindowTitle(windowTitle); + + QTabWidget* tabWidget = new QTabWidget; + + for (int i = 0; i < uiConfigNameForTabs.size(); i++) + { + QHBoxLayout* widgetLayout = new QHBoxLayout; + widgetLayout->setContentsMargins(0, 0, 0, 0); + + QWidget* containerWidget = new QWidget; + containerWidget->setLayout(widgetLayout); + + caf::PdmUiPropertyView* pdmUiPropertyView = new caf::PdmUiPropertyView(); + pdmUiPropertyView->setUiConfigurationName(uiConfigNameForTabs[i]); + + widgetLayout->addWidget(pdmUiPropertyView); + + tabWidget->addTab(containerWidget, uiConfigNameForTabs[i]); + pdmUiPropertyView->showProperties(object); + + m_propertyViewTabs.push_back(pdmUiPropertyView); + } + + QVBoxLayout* dialogLayout = new QVBoxLayout; + setLayout(dialogLayout); + + dialogLayout->addWidget(tabWidget); + + + m_dialogButtonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + connect(m_dialogButtonBox, SIGNAL(accepted()), this, SLOT(accept())); + connect(m_dialogButtonBox, SIGNAL(rejected()), this, SLOT(reject())); + + dialogLayout->addWidget(m_dialogButtonBox); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +PdmUiTabbedPropertyViewDialog::~PdmUiTabbedPropertyViewDialog() +{ + for (auto propView : m_propertyViewTabs) + { + propView->showProperties(nullptr); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QSize PdmUiTabbedPropertyViewDialog::minimumSizeHint() const +{ + QSize minSizeHint(0, 0); + + for (auto propView : m_propertyViewTabs) + { + QSize pageSize = propView->minimumSizeHint(); + pageSize += QSize(0, 100); + + minSizeHint = minSizeHint.expandedTo(pageSize); + } + + return minSizeHint; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QSize PdmUiTabbedPropertyViewDialog::sizeHint() const +{ + QSize maxSizeHint(0, 0); + + for (auto w : m_propertyViewTabs) + { + QSize pageSize = w->sizeHint(); + pageSize += QSize(0, 100); + + maxSizeHint = maxSizeHint.expandedTo(pageSize); + } + + return maxSizeHint; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QDialogButtonBox* PdmUiTabbedPropertyViewDialog::dialogButtonBox() +{ + return m_dialogButtonBox; +} + +} \ No newline at end of file diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiTabbedPropertyViewDialog.h b/Fwk/AppFwk/cafUserInterface/cafPdmUiTabbedPropertyViewDialog.h new file mode 100644 index 0000000000..01b6c610e6 --- /dev/null +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiTabbedPropertyViewDialog.h @@ -0,0 +1,39 @@ +#pragma once + + +#include + +namespace caf { + class PdmObject; + class PdmUiPropertyView; +} + +class QDialogButtonBox; +class QWidget; +class QString; +class QStringList; + +namespace caf +{ + +class PdmUiTabbedPropertyViewDialog : public QDialog +{ +public: + PdmUiTabbedPropertyViewDialog(caf::PdmObject* object, + const QStringList& uiConfigNameForTabs, + const QString& windowTitle, + QWidget* parent); + ~PdmUiTabbedPropertyViewDialog() override; + + QDialogButtonBox* dialogButtonBox(); + +protected: + QSize minimumSizeHint() const override; + QSize sizeHint() const override; + +private: + std::vector m_propertyViewTabs; + QDialogButtonBox* m_dialogButtonBox; +}; + +} \ No newline at end of file From b802937657460d6718e20d6b4fefeb366ec381e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Tue, 25 Jun 2019 16:51:45 +0200 Subject: [PATCH 212/396] Fwk: Added the variable CEE_USE_QT5 as an option in pdmCore and LibGuiQt, to make it visible in the Cmake Gui. --- Fwk/AppFwk/cafProjectDataModel/cafPdmCore/CMakeLists.txt | 2 ++ Fwk/VizFwk/LibGuiQt/CMakeLists.txt | 2 ++ 2 files changed, 4 insertions(+) diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/CMakeLists.txt b/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/CMakeLists.txt index 259417b084..3be790e3d2 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/CMakeLists.txt +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/CMakeLists.txt @@ -2,6 +2,8 @@ cmake_minimum_required (VERSION 2.8.12) project (cafPdmCore) # Qt +option(CEE_USE_QT5 "Use Qt 5 instead of Qt 4" true) + if (CEE_USE_QT5) find_package(Qt5 COMPONENTS REQUIRED Core) set(QT_LIBRARIES Qt5::Core) diff --git a/Fwk/VizFwk/LibGuiQt/CMakeLists.txt b/Fwk/VizFwk/LibGuiQt/CMakeLists.txt index 6a9bab1c42..50f4aa9fd4 100644 --- a/Fwk/VizFwk/LibGuiQt/CMakeLists.txt +++ b/Fwk/VizFwk/LibGuiQt/CMakeLists.txt @@ -12,6 +12,8 @@ endif() find_package(OpenGL) # Qt +option(CEE_USE_QT5 "Use Qt 5 instead of Qt 4" true) + if (CEE_USE_QT5) find_package(Qt5 COMPONENTS REQUIRED Core Gui Widgets OpenGL) set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets Qt5::OpenGL) From b0e73b7422ec58f4be0c7f42b4f3a270818ff594 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Tue, 25 Jun 2019 16:53:01 +0200 Subject: [PATCH 213/396] VizFwk: Fixed scaling bug in paralell projection for FixedSizeTransform. Was always 1 pixel high --- Fwk/VizFwk/LibViewing/cvfFixedSizeTransform.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Fwk/VizFwk/LibViewing/cvfFixedSizeTransform.cpp b/Fwk/VizFwk/LibViewing/cvfFixedSizeTransform.cpp index fed21720d3..66ef9df101 100644 --- a/Fwk/VizFwk/LibViewing/cvfFixedSizeTransform.cpp +++ b/Fwk/VizFwk/LibViewing/cvfFixedSizeTransform.cpp @@ -86,7 +86,7 @@ void FixedSizeTransform::updateWorldTransform(const cvf::Camera* camera) } else { - scaleFactor = camera->frontPlanePixelHeight(); + scaleFactor = fixedPixelSizeModelUnits()*camera->frontPlanePixelHeight(); } Mat4d scaleMatrix = Mat4d::fromScaling(Vec3d(scaleFactor, scaleFactor, scaleFactor)); From 78a705f05cb78b8c0b3664aef43ec4840c1dd9fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Tue, 25 Jun 2019 16:55:03 +0200 Subject: [PATCH 214/396] AppFwk: Qt5: Avoid use of an obsolete class --- Fwk/AppFwk/cafUserInterface/cafPdmUiCheckBoxDelegate.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiCheckBoxDelegate.cpp b/Fwk/AppFwk/cafUserInterface/cafPdmUiCheckBoxDelegate.cpp index ef26af9228..ac5f53b681 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiCheckBoxDelegate.cpp +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiCheckBoxDelegate.cpp @@ -82,7 +82,7 @@ QRect adjustedPaintRect(const QStyleOptionViewItem &option) //-------------------------------------------------------------------------------------------------- void PdmUiCheckBoxDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { - QStyleOptionViewItemV4 viewItemOption(option); + QStyleOptionViewItem viewItemOption(option); viewItemOption.rect = adjustedPaintRect(option); From 87d673b67292a168c5aa12ad773c446038d9d401 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Tue, 25 Jun 2019 16:56:43 +0200 Subject: [PATCH 215/396] VizFwk: Added method to set the ManipulatorTrackball sensitivity --- Fwk/VizFwk/LibViewing/cvfManipulatorTrackball.cpp | 8 ++++++++ Fwk/VizFwk/LibViewing/cvfManipulatorTrackball.h | 1 + 2 files changed, 9 insertions(+) diff --git a/Fwk/VizFwk/LibViewing/cvfManipulatorTrackball.cpp b/Fwk/VizFwk/LibViewing/cvfManipulatorTrackball.cpp index a165ce59ea..6bed8910b4 100644 --- a/Fwk/VizFwk/LibViewing/cvfManipulatorTrackball.cpp +++ b/Fwk/VizFwk/LibViewing/cvfManipulatorTrackball.cpp @@ -163,6 +163,14 @@ void ManipulatorTrackball::endNavigation() } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void ManipulatorTrackball::setRotationSensitivity(double scaleFactor) +{ + m_rotateSensitivity = scaleFactor; +} + //-------------------------------------------------------------------------------------------------- /// Pan the camera up/down and left/right /// diff --git a/Fwk/VizFwk/LibViewing/cvfManipulatorTrackball.h b/Fwk/VizFwk/LibViewing/cvfManipulatorTrackball.h index 6da737324e..f9c465279c 100644 --- a/Fwk/VizFwk/LibViewing/cvfManipulatorTrackball.h +++ b/Fwk/VizFwk/LibViewing/cvfManipulatorTrackball.h @@ -75,6 +75,7 @@ public: void startNavigation(NavigationType navigationType, int x, int y); bool updateNavigation(int x, int y); void endNavigation(); + void setRotationSensitivity(double scaleFactor); private: bool pan(int posX, int posY); From 936d2e122d2c8bed921126c994091792630e1aa3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Tue, 25 Jun 2019 16:59:53 +0200 Subject: [PATCH 216/396] AppFwk: Added optional adaptive rotation sensitivity to CAD and Ceetron Plus navigation policies --- Fwk/AppFwk/cafViewer/cafCadNavigation.cpp | 5 ++ .../cafViewer/cafCeetronPlusNavigation.cpp | 6 ++ .../cafViewer/cafTrackBallBasedNavigation.cpp | 63 +++++++++++++++++++ .../cafViewer/cafTrackBallBasedNavigation.h | 32 ++++++++++ 4 files changed, 106 insertions(+) diff --git a/Fwk/AppFwk/cafViewer/cafCadNavigation.cpp b/Fwk/AppFwk/cafViewer/cafCadNavigation.cpp index 13b4c39e02..1a5a44f5ac 100644 --- a/Fwk/AppFwk/cafViewer/cafCadNavigation.cpp +++ b/Fwk/AppFwk/cafViewer/cafCadNavigation.cpp @@ -93,6 +93,8 @@ bool caf::CadNavigation::handleInputEvent(QInputEvent* inputEvent) } m_trackball->startNavigation(cvf::ManipulatorTrackball::ROTATE, translatedMousePosX, translatedMousePosY); + m_roationSensitivityCalculator.init(me); + m_isNavigating = true; m_hasMovedMouseDuringNavigation = false; isEventHandled = true; @@ -137,6 +139,9 @@ bool caf::CadNavigation::handleInputEvent(QInputEvent* inputEvent) if (m_isNavigating) { + double sensitivity = m_roationSensitivityCalculator.calculateSensitivity(me); + + m_trackball->setRotationSensitivity(sensitivity); bool needRedraw = m_trackball->updateNavigation(translatedMousePosX, translatedMousePosY); if(needRedraw) { diff --git a/Fwk/AppFwk/cafViewer/cafCeetronPlusNavigation.cpp b/Fwk/AppFwk/cafViewer/cafCeetronPlusNavigation.cpp index a5b205f421..5fa26f6f24 100644 --- a/Fwk/AppFwk/cafViewer/cafCeetronPlusNavigation.cpp +++ b/Fwk/AppFwk/cafViewer/cafCeetronPlusNavigation.cpp @@ -95,6 +95,8 @@ bool caf::CeetronPlusNavigation::handleInputEvent(QInputEvent* inputEvent) } m_trackball->startNavigation(cvf::ManipulatorTrackball::ROTATE, translatedMousePosX, translatedMousePosY); + m_roationSensitivityCalculator.init(me); + m_isNavigating = true; m_hasMovedMouseDuringNavigation = false; isEventHandled = true; @@ -174,7 +176,11 @@ bool caf::CeetronPlusNavigation::handleInputEvent(QInputEvent* inputEvent) } else { + double sensitivity = m_roationSensitivityCalculator.calculateSensitivity(me); + + m_trackball->setRotationSensitivity(sensitivity); bool needRedraw = m_trackball->updateNavigation(translatedMousePosX, translatedMousePosY); + if (needRedraw) { m_viewer->navigationPolicyUpdate(); diff --git a/Fwk/AppFwk/cafViewer/cafTrackBallBasedNavigation.cpp b/Fwk/AppFwk/cafViewer/cafTrackBallBasedNavigation.cpp index b1fc7a0db0..6121a5df91 100644 --- a/Fwk/AppFwk/cafViewer/cafTrackBallBasedNavigation.cpp +++ b/Fwk/AppFwk/cafViewer/cafTrackBallBasedNavigation.cpp @@ -297,3 +297,66 @@ bool caf::TrackBallBasedNavigation::shouldRaytraceForNewPoiDuringWheelZoom(int z } return false; } + +#include + +//#include +// +//#pragma warning(disable:4996) +//void openDebugWindow() +//{ +// AllocConsole(); +// freopen("conin$", "r", stdin); +// freopen("conout$", "w", stdout); +// freopen("conout$", "w", stderr); +//} +// +//#include + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void caf::RotationSensitivityCalculator::init(QMouseEvent* eventAtRotationStart) +{ + m_lastPosX = eventAtRotationStart->x(); + m_lastPosY = eventAtRotationStart->y(); + m_lastTime = eventAtRotationStart->timestamp(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double caf::RotationSensitivityCalculator::calculateSensitivity(QMouseEvent* eventWhenRotating ) +{ + double sensitivity = 1.0; + + if ( m_isEnabled ) + { + auto presentTime = eventWhenRotating->timestamp(); + unsigned long timeSinceLast = presentTime - m_lastTime; + if ( timeSinceLast == 0 ) timeSinceLast = 1; // one millisecond + + int deltaX = eventWhenRotating->x() - m_lastPosX; + int deltaY = eventWhenRotating->y() - m_lastPosY; + + cvf::Vec2d mouseVelocity(deltaX, deltaY); + mouseVelocity /= 1.0e-3*timeSinceLast; + + double mouseVelocityLength = mouseVelocity.length(); + double mouseVelocityLengthCorr = 0.3*mouseVelocityLength + 0.7*m_lastMouseVelocityLenght; + + double slowLimit = 170.0; + + if ( mouseVelocityLengthCorr < slowLimit ) sensitivity = mouseVelocityLengthCorr*mouseVelocityLengthCorr/(slowLimit*slowLimit); + + m_lastPosX = eventWhenRotating->x(); + m_lastPosY = eventWhenRotating->y(); + m_lastTime = eventWhenRotating->timestamp(); + m_lastMouseVelocityLenght = 0.8*mouseVelocityLength + 0.2*m_lastMouseVelocityLenght; + + //openDebugWindow(); + //std::cout << sensitivity << " Speed: " << mouseVelocity.length() << " " << mouseVelocityLengthCorr << " \tDelta " << deltaX << ", " << deltaY << " "<< timeSinceLast << std::endl; + } + + return sensitivity; +} diff --git a/Fwk/AppFwk/cafViewer/cafTrackBallBasedNavigation.h b/Fwk/AppFwk/cafViewer/cafTrackBallBasedNavigation.h index eb2af4a81e..34a27658bc 100644 --- a/Fwk/AppFwk/cafViewer/cafTrackBallBasedNavigation.h +++ b/Fwk/AppFwk/cafViewer/cafTrackBallBasedNavigation.h @@ -44,6 +44,36 @@ namespace cvf { class Ray; } +class QMouseEvent; + +namespace caf +{ +class RotationSensitivityCalculator +{ +public: + RotationSensitivityCalculator() + : m_lastPosX(0) + , m_lastPosY(0) + , m_lastMouseVelocityLenght(200) + , m_isEnabled(false) + {} + + void enable(bool enable) { m_isEnabled = enable; } + void init(QMouseEvent* eventAtRotationStart); + + double calculateSensitivity(QMouseEvent* eventWhenRotating); + +private: + bool m_isEnabled; + int m_lastPosX; /// Previous mouse position + int m_lastPosY; + unsigned long m_lastTime; + double m_lastMouseVelocityLenght; +}; + +} // End namespace caf + + namespace caf { //-------------------------------------------------------------------------------------------------- @@ -62,6 +92,7 @@ public: ~TrackBallBasedNavigation() override; void enableEventEating(bool enable) { m_consumeEvents = enable; } void enableRotation(bool enable) { m_isRotationEnabled = enable; } + void enableAdaptiveRotationSensitivity(bool enable) { m_roationSensitivityCalculator.enable(enable); } protected: // General navigation policy overrides @@ -78,6 +109,7 @@ protected: cvf::ref m_trackball; bool m_isRotCenterInitialized; cvf::Vec3d m_pointOfInterest; + RotationSensitivityCalculator m_roationSensitivityCalculator; bool m_isNavigating; bool m_hasMovedMouseDuringNavigation; From 2930d4152185d7cec93523ece17a35ef5cbbe886 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Tue, 25 Jun 2019 17:01:38 +0200 Subject: [PATCH 217/396] AppFwk: Fix of Qt5 OpenGL related problems: Offset + Context deletion. Added option to control the direction of the parallel projection headlight Added optional visualization of point of interest to caf::Viewer --- Fwk/AppFwk/cafViewer/CMakeLists.txt | 1 + .../cafViewer/cafPointOfInterestVisualizer.h | 62 ++++++++++++++++ Fwk/AppFwk/cafViewer/cafViewer.cpp | 73 +++++++++++++++++-- Fwk/AppFwk/cafViewer/cafViewer.h | 7 ++ 4 files changed, 136 insertions(+), 7 deletions(-) create mode 100644 Fwk/AppFwk/cafViewer/cafPointOfInterestVisualizer.h diff --git a/Fwk/AppFwk/cafViewer/CMakeLists.txt b/Fwk/AppFwk/cafViewer/CMakeLists.txt index 02df1adb9b..4de3993271 100644 --- a/Fwk/AppFwk/cafViewer/CMakeLists.txt +++ b/Fwk/AppFwk/cafViewer/CMakeLists.txt @@ -30,6 +30,7 @@ add_library( ${PROJECT_NAME} cafTrackBallBasedNavigation.h cafNavigationPolicy.cpp cafNavigationPolicy.h + cafPointOfInterestVisualizer.h cafOpenGLWidget.cpp cafOpenGLWidget.h cafViewer.cpp diff --git a/Fwk/AppFwk/cafViewer/cafPointOfInterestVisualizer.h b/Fwk/AppFwk/cafViewer/cafPointOfInterestVisualizer.h new file mode 100644 index 0000000000..d46a2f338c --- /dev/null +++ b/Fwk/AppFwk/cafViewer/cafPointOfInterestVisualizer.h @@ -0,0 +1,62 @@ +//################################################################################################## +// +// Custom Visualization Core library +// Copyright (C) CeetronSolutions AS +// +// This library may be used under the terms of either the GNU General Public License or +// the GNU Lesser General Public License as follows: +// +// GNU General Public License Usage +// This library 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. +// +// This library 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. +// +// GNU Lesser General Public License Usage +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This library 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 Lesser General Public License at <> +// for more details. +// +//################################################################################################## +#pragma once + +#include "cvfBase.h" +#include "cvfObject.h" +#include "cvfVector3.h" + +namespace cvf +{ + class Model; +} + +namespace caf +{ + +class PointOfInterestVisualizer : public cvf::Object +{ +public: + /// Returns the model containing the visualization of the PointOfInterest + /// Must always return the same model. + virtual cvf::Model* model() = 0; + + /// Update the model to show a different point of interest position + virtual void update(cvf::Vec3d pointOfInterest) = 0; +}; + +} + diff --git a/Fwk/AppFwk/cafViewer/cafViewer.cpp b/Fwk/AppFwk/cafViewer/cafViewer.cpp index 431d5f8641..016a7d3134 100644 --- a/Fwk/AppFwk/cafViewer/cafViewer.cpp +++ b/Fwk/AppFwk/cafViewer/cafViewer.cpp @@ -34,12 +34,12 @@ // //################################################################################################## - #include "cafViewer.h" #include "cafCadNavigation.h" #include "cafFrameAnimationControl.h" #include "cafNavigationPolicy.h" +#include "cafPointOfInterestVisualizer.h" #include "cvfCamera.h" #include "cvfDebugTimer.h" @@ -112,7 +112,11 @@ cvf::ref caf::Viewer::sm_openGLContextGroup; /// //-------------------------------------------------------------------------------------------------- caf::Viewer::Viewer(const QGLFormat& format, QWidget* parent) + #if QT_VERSION >= 0x050000 + : caf::OpenGLWidget(contextGroup(), format, nullptr, sharedWidget()), + #else : caf::OpenGLWidget(contextGroup(), format, new QWidget(parent), sharedWidget()), + #endif m_navigationPolicy(nullptr), m_navigationPolicyEnabled(true), m_defaultPerspectiveNearPlaneDistance(0.05), @@ -122,10 +126,15 @@ caf::Viewer::Viewer(const QGLFormat& format, QWidget* parent) m_releaseOGLResourcesEachFrame(false), m_isOverlayPaintingEnabled(true), m_offscreenViewportWidth(0), - m_offscreenViewportHeight(0) + m_offscreenViewportHeight(0), + m_parallelProjectionLightDirection(0, 0, -1) // Light directly from behind { + #if QT_VERSION >= 0x050000 + m_layoutWidget = new QWidget(parent); + #else m_layoutWidget = parentWidget(); - + #endif + QHBoxLayout* layout = new QHBoxLayout(m_layoutWidget); layout->addWidget(this); @@ -165,6 +174,7 @@ caf::Viewer::Viewer(const QGLFormat& format, QWidget* parent) sm_viewers.push_back(this); } + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -419,6 +429,22 @@ void caf::Viewer::optimizeClippingPlanes() //-------------------------------------------------------------------------------------------------- bool caf::Viewer::event(QEvent* e) { + #if QT_VERSION >= 0x050000 + // The most reliable way we have found of detecting when an OpenGL context is about to be destroyed is + // hooking into the QEvent::PlatformSurface event and checking for the SurfaceAboutToBeDestroyed event type. + // From the Qt doc: + // The underlying native surface will be destroyed immediately after this event. + // The SurfaceAboutToBeDestroyed event type is useful as a means of stopping rendering to a platform window before it is destroyed. + if ( e->type() == QEvent::PlatformSurface ) + { + QPlatformSurfaceEvent* platformSurfaceEvent = static_cast(e); + if ( platformSurfaceEvent->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed ) + { + cvfShutdownOpenGLContext(); + } + } + #endif + if (e && m_navigationPolicy.notNull() && m_navigationPolicyEnabled) { switch (e->type()) @@ -618,10 +644,21 @@ void caf::Viewer::paintEvent(QPaintEvent* event) optimizeClippingPlanes(); + if ( m_poiVisualizationManager.notNull() ) + { + m_poiVisualizationManager->update(m_navigationPolicy->pointOfInterest()); + m_mainRendering->scene()->addModel(m_poiVisualizationManager->model()); + } + // Do normal drawing m_renderingSequence->render(myOglContext.p()); CVF_CHECK_OGL(cvfOpenGLContext()); + if ( m_poiVisualizationManager.notNull() ) + { + m_mainRendering->scene()->removeModel(m_poiVisualizationManager->model()); + } + if (isShadersSupported()) { cvfqt::OpenGLContext::restoreOpenGLState(myOglContext.p()); @@ -1146,10 +1183,10 @@ void caf::Viewer::enableParallelProjection(bool enableOrtho) m_mainCamera->setProjectionAsOrtho(1.0, m_mainCamera->nearPlane(), m_mainCamera->farPlane()); this->updateParallelProjectionHeightFromMoveZoom(pointOfInterest); - // Set the light position behind us, far away from the scene + // Set a fake directional light by putting the point far away from the scene float sceneDepth = m_mainCamera->farPlane() - m_mainCamera->nearPlane(); - this->m_renderingSequence->setDefaultFFLightPositional(cvf::Vec3f(0,0, 2 * sceneDepth)); - m_globalUniformSet->setHeadLightPosition(cvf::Vec3f(0,0, 2 * sceneDepth)); + this->m_renderingSequence->setDefaultFFLightPositional(-m_parallelProjectionLightDirection* 10*sceneDepth); + m_globalUniformSet->setHeadLightPosition(-m_parallelProjectionLightDirection* 10*sceneDepth); this->update(); } @@ -1159,7 +1196,7 @@ void caf::Viewer::enableParallelProjection(bool enableOrtho) // so we do not need to update the camera position based on orthoHeight and fieldOfView. // We assume the camera is in a sensible position. - // Set dummy near and far plane. These wll be updated by the optimize clipping planes + // Set dummy near and far plane. These will be updated by the optimize clipping planes m_mainCamera->setProjectionAsPerspective(m_cameraFieldOfViewYDeg, 0.1, 1.0); this->m_renderingSequence->setDefaultFFLightPositional(cvf::Vec3f(0.5, 5.0, 7.0)); @@ -1169,6 +1206,28 @@ void caf::Viewer::enableParallelProjection(bool enableOrtho) } } +//-------------------------------------------------------------------------------------------------- +/// Direction in camera coordinates default is (0, 0, -1) directly from behind +//-------------------------------------------------------------------------------------------------- +void caf::Viewer::setParallelProjectionHeadLightDirection(const cvf::Vec3f& direction) +{ + m_parallelProjectionLightDirection = direction; + + float sceneDepth = m_mainCamera->farPlane() - m_mainCamera->nearPlane(); + this->m_renderingSequence->setDefaultFFLightPositional(-m_parallelProjectionLightDirection* 10*sceneDepth); + m_globalUniformSet->setHeadLightPosition(-m_parallelProjectionLightDirection* 10*sceneDepth); + + this->update(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void caf::Viewer::setPointOfInterestVisualizer(PointOfInterestVisualizer* poiVisualizer) +{ + m_poiVisualizationManager = poiVisualizer; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/Fwk/AppFwk/cafViewer/cafViewer.h b/Fwk/AppFwk/cafViewer/cafViewer.h index 2f8401bf84..5cead98591 100644 --- a/Fwk/AppFwk/cafViewer/cafViewer.h +++ b/Fwk/AppFwk/cafViewer/cafViewer.h @@ -65,6 +65,7 @@ namespace caf { class FrameAnimationControl; class NavigationPolicy; class Viewer; + class PointOfInterestVisualizer; } class QInputEvent; @@ -121,6 +122,8 @@ public: void setView( const cvf::Vec3d& alongDirection, const cvf::Vec3d& upDirection ); void zoomAll(); void enableParallelProjection(bool enable); + void setParallelProjectionHeadLightDirection(const cvf::Vec3f& direction); + void setPointOfInterestVisualizer(PointOfInterestVisualizer* poiVisualizer); // Interface for navigation policies void updateParallelProjectionHeightFromMoveZoom(const cvf::Vec3d& pointOfInterest); @@ -224,9 +227,13 @@ private: cvf::Collection m_frameScenes; cvf::Collection m_staticModels; + // Poi visualization + cvf::ref m_poiVisualizationManager; + // Parallel projection light modification cvf::ref m_globalUniformSet; + cvf::Vec3f m_parallelProjectionLightDirection; // Offscreen render objects cvf::ref m_offscreenFbo; From b2857676c8f4349840dcb540575a61546aee739b Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 25 Jun 2019 17:49:38 +0200 Subject: [PATCH 218/396] #4136 Command File : Export of flow characteristics --- .../CMakeLists_files.cmake | 2 + .../RicfExportFlowCharacteristics.cpp | 116 ++++++++++++++++++ .../RicfExportFlowCharacteristics.h | 51 ++++++++ .../Flow/RimFlowCharacteristicsPlot.cpp | 53 ++++++++ .../Flow/RimFlowCharacteristicsPlot.h | 5 + 5 files changed, 227 insertions(+) create mode 100644 ApplicationCode/CommandFileInterface/RicfExportFlowCharacteristics.cpp create mode 100644 ApplicationCode/CommandFileInterface/RicfExportFlowCharacteristics.h diff --git a/ApplicationCode/CommandFileInterface/CMakeLists_files.cmake b/ApplicationCode/CommandFileInterface/CMakeLists_files.cmake index 91b91819de..8fd95c86d6 100644 --- a/ApplicationCode/CommandFileInterface/CMakeLists_files.cmake +++ b/ApplicationCode/CommandFileInterface/CMakeLists_files.cmake @@ -28,6 +28,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RicfExportLgrForCompletions.h ${CMAKE_CURRENT_LIST_DIR}/RicfCreateLgrForCompletions.h ${CMAKE_CURRENT_LIST_DIR}/RicfApplicationTools.h ${CMAKE_CURRENT_LIST_DIR}/RicfCreateSaturationPressurePlots.h +${CMAKE_CURRENT_LIST_DIR}/RicfExportFlowCharacteristics.h ) set (SOURCE_GROUP_SOURCE_FILES @@ -59,6 +60,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RicfExportLgrForCompletions.cpp ${CMAKE_CURRENT_LIST_DIR}/RicfCreateLgrForCompletions.cpp ${CMAKE_CURRENT_LIST_DIR}/RicfApplicationTools.cpp ${CMAKE_CURRENT_LIST_DIR}/RicfCreateSaturationPressurePlots.cpp +${CMAKE_CURRENT_LIST_DIR}/RicfExportFlowCharacteristics.cpp ) list(APPEND CODE_HEADER_FILES diff --git a/ApplicationCode/CommandFileInterface/RicfExportFlowCharacteristics.cpp b/ApplicationCode/CommandFileInterface/RicfExportFlowCharacteristics.cpp new file mode 100644 index 0000000000..602d5f0417 --- /dev/null +++ b/ApplicationCode/CommandFileInterface/RicfExportFlowCharacteristics.cpp @@ -0,0 +1,116 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2017 Statoil ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RicfExportFlowCharacteristics.h" + +#include "RiaApplication.h" +#include "RiaLogging.h" + +#include "RicfApplicationTools.h" + +#include "RimEclipseResultCase.h" +#include "RimFlowCharacteristicsPlot.h" +#include "RimFlowPlotCollection.h" +#include "RimMainPlotCollection.h" +#include "RimProject.h" + +#include +#include +#include + +CAF_PDM_SOURCE_INIT(RicfExportFlowCharacteristics, "exportFlowCharacteristics"); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RicfExportFlowCharacteristics::RicfExportFlowCharacteristics() +{ + RICF_InitField(&m_caseId, "caseId", -1, "Case ID", "", "", ""); + RICF_InitField(&m_selectedTimeSteps, "timeSteps", std::vector(), "Selected Time Steps", "", "", ""); + RICF_InitField(&m_injectors, "injectors", std::vector(), "Injectors", "", "", ""); + RICF_InitField(&m_producers, "producers", std::vector(), "Producers", "", "", ""); + RICF_InitField(&m_fileName, "fileName", QString(), "Export File Name", "", "", ""); + RICF_InitField(&m_minCommunication, "minimumCommunication", 0.0, "Minimum Communication", "", "", ""); + RICF_InitField(&m_maxPvFraction, "aquiferCellThreshold", 0.1, "Aquifer Cell Threshold", "", "", ""); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RicfCommandResponse RicfExportFlowCharacteristics::execute() +{ + using TOOLS = RicfApplicationTools; + + auto eclipseCase = dynamic_cast(TOOLS::caseFromId(m_caseId())); + if (!eclipseCase) + { + QString error = QString("exportFlowCharacteristics: Could not find case with ID %1.").arg(m_caseId()); + RiaLogging::error(error); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, error); + } + + { + QString exportFileName = m_fileName(); + if (exportFileName.isEmpty()) + { + QString exportFolder = RiaApplication::instance()->createAbsolutePathFromProjectRelativePath("flow_characteristics"); + + QDir exportDir(exportFolder); + if (!exportDir.exists()) + { + if (!exportDir.mkpath(".")) + { + QString msg = QString("Failed to create folder - %1").arg(exportFolder); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, msg); + } + } + + exportFileName = exportFolder + QString("/flow_characteristics_data.txt"); + } + + RimFlowPlotCollection* flowPlotColl = RiaApplication::instance()->project()->mainPlotCollection->flowPlotCollection(); + if (flowPlotColl) + { + RimFlowCharacteristicsPlot* plot = flowPlotColl->defaultFlowCharacteristicsPlot(); + plot->setFromFlowSolution(eclipseCase->defaultFlowDiagSolution()); + plot->setTimeSteps(m_selectedTimeSteps); + plot->setInjectorsAndProducers(m_injectors, m_producers); + plot->setAquiferCellThreshold(m_maxPvFraction); + plot->setMinimumCommunication(m_minCommunication); + + plot->loadDataAndUpdate(); + + { + QString content = plot->curveDataAsText(); + + QFile file(exportFileName); + if (file.open(QIODevice::WriteOnly | QIODevice::Text)) + { + QTextStream textstream(&file); + textstream << content; + } + else + { + QString msg = QString("Failed to export file - %1").arg(exportFileName); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, msg); + } + } + } + } + return RicfCommandResponse(); +} diff --git a/ApplicationCode/CommandFileInterface/RicfExportFlowCharacteristics.h b/ApplicationCode/CommandFileInterface/RicfExportFlowCharacteristics.h new file mode 100644 index 0000000000..37a510d0e2 --- /dev/null +++ b/ApplicationCode/CommandFileInterface/RicfExportFlowCharacteristics.h @@ -0,0 +1,51 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2017 Statoil ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "RiaDefines.h" + +#include "RicfCommandObject.h" + +#include + +#include "cafPdmField.h" + +//================================================================================================== +// +// +// +//================================================================================================== +class RicfExportFlowCharacteristics : public RicfCommandObject +{ + CAF_PDM_HEADER_INIT; + +public: + RicfExportFlowCharacteristics(); + + RicfCommandResponse execute() override; + +private: + caf::PdmField m_caseId; + caf::PdmField> m_selectedTimeSteps; + caf::PdmField> m_injectors; + caf::PdmField> m_producers; + caf::PdmField m_fileName; + caf::PdmField m_minCommunication; + caf::PdmField m_maxPvFraction; +}; diff --git a/ApplicationCode/ProjectDataModel/Flow/RimFlowCharacteristicsPlot.cpp b/ApplicationCode/ProjectDataModel/Flow/RimFlowCharacteristicsPlot.cpp index eb11b10c0f..97d6772b33 100644 --- a/ApplicationCode/ProjectDataModel/Flow/RimFlowCharacteristicsPlot.cpp +++ b/ApplicationCode/ProjectDataModel/Flow/RimFlowCharacteristicsPlot.cpp @@ -141,6 +141,8 @@ void RimFlowCharacteristicsPlot::setFromFlowSolution(RimFlowDiagSolution* flowSo m_flowDiagSolution = flowSolution; m_showWindow = true; + m_timeStepToFlowResultMap.clear(); + m_currentlyPlottedTimeSteps.clear(); onLoadDataAndUpdate(); } @@ -173,6 +175,57 @@ void RimFlowCharacteristicsPlot::updateCurrentTimeStep() this->onLoadDataAndUpdate(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFlowCharacteristicsPlot::setTimeSteps(const std::vector& timeSteps) +{ + m_selectedTimeSteps = timeSteps; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFlowCharacteristicsPlot::setInjectorsAndProducers(const std::vector& injectors, + const std::vector& producers) +{ + std::vector allTracers; + + allTracers = producers; + allTracers.insert(allTracers.end(), injectors.begin(), injectors.end()); + + if (producers.empty() && !injectors.empty()) + { + m_cellFilter = RigFlowDiagResults::CELLS_FLOODED; + } + else if (!producers.empty() && injectors.empty()) + { + m_cellFilter = RigFlowDiagResults::CELLS_DRAINED; + } + else if (!producers.empty() && !injectors.empty()) + { + m_cellFilter = RigFlowDiagResults::CELLS_COMMUNICATION; + } + + m_selectedTracerNames = allTracers; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFlowCharacteristicsPlot::setMinimumCommunication(double minimumCommunication) +{ + m_minCommunication = minimumCommunication; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFlowCharacteristicsPlot::setAquiferCellThreshold(double aquiferCellThreshold) +{ + m_maxPvFraction = aquiferCellThreshold; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/Flow/RimFlowCharacteristicsPlot.h b/ApplicationCode/ProjectDataModel/Flow/RimFlowCharacteristicsPlot.h index 78fc196a87..831bb2bcbc 100644 --- a/ApplicationCode/ProjectDataModel/Flow/RimFlowCharacteristicsPlot.h +++ b/ApplicationCode/ProjectDataModel/Flow/RimFlowCharacteristicsPlot.h @@ -74,6 +74,11 @@ public: ALL_AVAILABLE, SELECTED, }; + + void setTimeSteps(const std::vector& timeSteps); + void setInjectorsAndProducers(const std::vector& injectors, const std::vector& producers); + void setMinimumCommunication(double minimumCommunication); + void setAquiferCellThreshold(double aquiferCellThreshold); protected: // RimViewWindow overrides From d108e1f3548c4f63521b2ee065fa10461b464321 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 25 Jun 2019 18:02:47 +0200 Subject: [PATCH 219/396] AppFwk : Guard use of timestamp() function introduced in Qt5 --- Fwk/AppFwk/cafViewer/cafTrackBallBasedNavigation.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Fwk/AppFwk/cafViewer/cafTrackBallBasedNavigation.cpp b/Fwk/AppFwk/cafViewer/cafTrackBallBasedNavigation.cpp index 6121a5df91..9267547722 100644 --- a/Fwk/AppFwk/cafViewer/cafTrackBallBasedNavigation.cpp +++ b/Fwk/AppFwk/cafViewer/cafTrackBallBasedNavigation.cpp @@ -320,7 +320,10 @@ void caf::RotationSensitivityCalculator::init(QMouseEvent* eventAtRotationStart) { m_lastPosX = eventAtRotationStart->x(); m_lastPosY = eventAtRotationStart->y(); + +#if QT_VERSION >= 0x050000 m_lastTime = eventAtRotationStart->timestamp(); +#endif } //-------------------------------------------------------------------------------------------------- @@ -332,6 +335,7 @@ double caf::RotationSensitivityCalculator::calculateSensitivity(QMouseEvent* eve if ( m_isEnabled ) { +#if QT_VERSION >= 0x050000 auto presentTime = eventWhenRotating->timestamp(); unsigned long timeSinceLast = presentTime - m_lastTime; if ( timeSinceLast == 0 ) timeSinceLast = 1; // one millisecond @@ -356,6 +360,7 @@ double caf::RotationSensitivityCalculator::calculateSensitivity(QMouseEvent* eve //openDebugWindow(); //std::cout << sensitivity << " Speed: " << mouseVelocity.length() << " " << mouseVelocityLengthCorr << " \tDelta " << deltaX << ", " << deltaY << " "<< timeSinceLast << std::endl; +#endif } return sensitivity; From 0f0e440185909905af50523bcb3b1a858dd42e19 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 25 Jun 2019 18:18:47 +0200 Subject: [PATCH 220/396] #4136 Flow Characteristics : Avoid space in CSV column header --- .../Flow/RimFlowCharacteristicsPlot.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/Flow/RimFlowCharacteristicsPlot.cpp b/ApplicationCode/ProjectDataModel/Flow/RimFlowCharacteristicsPlot.cpp index 97d6772b33..f6bb1de503 100644 --- a/ApplicationCode/ProjectDataModel/Flow/RimFlowCharacteristicsPlot.cpp +++ b/ApplicationCode/ProjectDataModel/Flow/RimFlowCharacteristicsPlot.cpp @@ -761,11 +761,11 @@ QString RimFlowCharacteristicsPlot::curveDataAsText() const std::vector header = { RifEclipseOutputTableColumn("Date"), - RifEclipseOutputTableColumn("Storage Capacity"), - RifEclipseOutputTableColumn("Flow Capacity"), - RifEclipseOutputTableColumn("Sweep Efficiency"), - RifEclipseOutputTableColumn("Dimensionless Time"), - RifEclipseOutputTableColumn("Lorentz Coefficient"), + RifEclipseOutputTableColumn("StorageCapacity"), + RifEclipseOutputTableColumn("FlowCapacity"), + RifEclipseOutputTableColumn("SweepEfficiency"), + RifEclipseOutputTableColumn("DimensionlessTime"), + RifEclipseOutputTableColumn("LorentzCoefficient"), }; formatter.header(header); From 7213ae7e9839e7d2ee9e3a2c896ac547dbb1944f Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 26 Jun 2019 07:50:42 +0200 Subject: [PATCH 221/396] #4136 Flow Characteristics : Support relative export paths --- .../RicfExportFlowCharacteristics.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/ApplicationCode/CommandFileInterface/RicfExportFlowCharacteristics.cpp b/ApplicationCode/CommandFileInterface/RicfExportFlowCharacteristics.cpp index 602d5f0417..d512081dc5 100644 --- a/ApplicationCode/CommandFileInterface/RicfExportFlowCharacteristics.cpp +++ b/ApplicationCode/CommandFileInterface/RicfExportFlowCharacteristics.cpp @@ -66,9 +66,12 @@ RicfCommandResponse RicfExportFlowCharacteristics::execute() { QString exportFileName = m_fileName(); - if (exportFileName.isEmpty()) + QFileInfo fi(exportFileName); + if (!fi.isAbsolute()) { - QString exportFolder = RiaApplication::instance()->createAbsolutePathFromProjectRelativePath("flow_characteristics"); + QString relativePath = fi.path(); + + QString exportFolder = RiaApplication::instance()->createAbsolutePathFromProjectRelativePath(relativePath); QDir exportDir(exportFolder); if (!exportDir.exists()) @@ -80,7 +83,7 @@ RicfCommandResponse RicfExportFlowCharacteristics::execute() } } - exportFileName = exportFolder + QString("/flow_characteristics_data.txt"); + exportFileName = exportFolder + "/" + fi.fileName(); } RimFlowPlotCollection* flowPlotColl = RiaApplication::instance()->project()->mainPlotCollection->flowPlotCollection(); From a6e10987164977e8e0edfd2eb419be396fce6a9b Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 26 Jun 2019 08:00:42 +0200 Subject: [PATCH 222/396] CMake : Propagate Qt4/Qt5 flag to AppFwk and VizFwk --- CMakeLists.txt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 273dc9432b..a02489bbda 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -322,9 +322,7 @@ set_property(TARGET ################################################################################ # App and Viz Framework Qt5 setting ################################################################################ -if (RESINSIGHT_BUILD_WITH_QT5) - set(CEE_USE_QT5 ON) -endif(RESINSIGHT_BUILD_WITH_QT5) +set(CEE_USE_QT5 RESINSIGHT_BUILD_WITH_QT5) ################################################################################ From 546c5aef821c7a1d15f23018b24f90f3b2dcb4f6 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 26 Jun 2019 08:14:54 +0200 Subject: [PATCH 223/396] CMake : Propagate Qt4/Qt5 flag to AppFwk and VizFwk, add to cache --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a02489bbda..57fe664b39 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -320,9 +320,9 @@ set_property(TARGET ################################################################################ -# App and Viz Framework Qt5 setting +# App and Viz Framework Qt5 setting, propagate settings in RESINSIGHT_BUILD_WITH_QT5 ################################################################################ -set(CEE_USE_QT5 RESINSIGHT_BUILD_WITH_QT5) +set(CEE_USE_QT5 RESINSIGHT_BUILD_WITH_QT5 CACHE BOOL "Flag used to enable Qt5 in AppFwk and VizFwk") ################################################################################ From a521748eda7a7feb0777583a4ac9d86c0aeab684 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 26 Jun 2019 09:19:36 +0200 Subject: [PATCH 224/396] CMake : Propagate Qt4/Qt5 flag to AppFwk and VizFwk, use FORCE --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 57fe664b39..1fde6e8c82 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -322,7 +322,7 @@ set_property(TARGET ################################################################################ # App and Viz Framework Qt5 setting, propagate settings in RESINSIGHT_BUILD_WITH_QT5 ################################################################################ -set(CEE_USE_QT5 RESINSIGHT_BUILD_WITH_QT5 CACHE BOOL "Flag used to enable Qt5 in AppFwk and VizFwk") +set(CEE_USE_QT5 ${RESINSIGHT_BUILD_WITH_QT5} CACHE BOOL "Flag used to enable Qt5 in AppFwk and VizFwk" FORCE) ################################################################################ From 3ac518da4cdb3dff7578df4a92702e200acb7e5b Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 26 Jun 2019 12:09:02 +0200 Subject: [PATCH 225/396] Dock State : Make sure dock state is stored when exit is triggered --- .../RicExitApplicationFeature.cpp | 25 +++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/ApplicationCode/Commands/ApplicationCommands/RicExitApplicationFeature.cpp b/ApplicationCode/Commands/ApplicationCommands/RicExitApplicationFeature.cpp index 09bc949b34..b2e17bb7b1 100644 --- a/ApplicationCode/Commands/ApplicationCommands/RicExitApplicationFeature.cpp +++ b/ApplicationCode/Commands/ApplicationCommands/RicExitApplicationFeature.cpp @@ -1,17 +1,17 @@ ///////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2016 Statoil ASA -// +// // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// +// // ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. -// -// See the GNU General Public License at +// +// See the GNU General Public License at // for more details. // ///////////////////////////////////////////////////////////////////////////////// @@ -20,6 +20,7 @@ #include "RiaGuiApplication.h" #include "RiuMainWindow.h" +#include "RiuPlotMainWindow.h" #include #include @@ -27,7 +28,7 @@ CAF_CMD_SOURCE_INIT(RicExitApplicationFeature, "RicExitApplicationFeature"); //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- bool RicExitApplicationFeature::isCommandEnabled() { @@ -35,7 +36,7 @@ bool RicExitApplicationFeature::isCommandEnabled() } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- void RicExitApplicationFeature::onActionTriggered(bool isChecked) { @@ -44,6 +45,16 @@ void RicExitApplicationFeature::onActionTriggered(bool isChecked) RiaGuiApplication* app = RiaGuiApplication::instance(); if (!app->askUserToSaveModifiedProject()) return; + if (app->mainPlotWindow()) + { + app->mainPlotWindow()->saveWinGeoAndDockToolBarLayout(); + } + + if (app->mainWindow()) + { + app->mainWindow()->saveWinGeoAndDockToolBarLayout(); + } + // Hide all windows first to make sure they get closed properly for (QWidget* topLevelWidget : app->topLevelWidgets()) { @@ -54,7 +65,7 @@ void RicExitApplicationFeature::onActionTriggered(bool isChecked) } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- void RicExitApplicationFeature::setupActionLook(QAction* actionToSetup) { From 1e748d09f6efea9f997b10f21127adaba06765ca Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 27 Jun 2019 09:44:59 +0200 Subject: [PATCH 226/396] Deployment : Add SSL binaries to installation on Windows Use cmake macro to find ssl library, and manipulate include path to find path of DLLs --- ApplicationCode/CMakeLists.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/ApplicationCode/CMakeLists.txt b/ApplicationCode/CMakeLists.txt index 2062f17bd4..3b29e56c00 100644 --- a/ApplicationCode/CMakeLists.txt +++ b/ApplicationCode/CMakeLists.txt @@ -667,6 +667,18 @@ if (RESINSIGHT_PRIVATE_INSTALL) endforeach(dllname ${GRPC_DLL_NAMES}) endif() + # OpenSSL + find_package(OpenSSL) + if (OPENSSL_FOUND) + message("OpenSSL include dir: ${OPENSSL_INCLUDE_DIR}") + SET(OPENSSL_BIN_DIR ${OPENSSL_INCLUDE_DIR}) + string(REPLACE "include" "bin" OPENSSL_BIN_DIR ${OPENSSL_BIN_DIR}) + message("OpenSSL binary dir: ${OPENSSL_BIN_DIR}") + + install(FILES ${OPENSSL_BIN_DIR}/libeay32.dll DESTINATION ${RESINSIGHT_INSTALL_FOLDER}) + install(FILES ${OPENSSL_BIN_DIR}/ssleay32.dll DESTINATION ${RESINSIGHT_INSTALL_FOLDER}) + endif(OPENSSL_FOUND) + # CRT set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_SKIP ON) set(CMAKE_INSTALL_OPENMP_LIBRARIES ON) From 37043b36af356117bf2e98678637b65684db2b28 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 27 Jun 2019 11:31:36 +0200 Subject: [PATCH 227/396] #4506 Deployment : Add option to control bundling of OpenSSL Added RESINSIGHT_BUNDLE_OPENSSL --- ApplicationCode/CMakeLists.txt | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/ApplicationCode/CMakeLists.txt b/ApplicationCode/CMakeLists.txt index 3b29e56c00..50af82455e 100644 --- a/ApplicationCode/CMakeLists.txt +++ b/ApplicationCode/CMakeLists.txt @@ -668,16 +668,19 @@ if (RESINSIGHT_PRIVATE_INSTALL) endif() # OpenSSL - find_package(OpenSSL) - if (OPENSSL_FOUND) - message("OpenSSL include dir: ${OPENSSL_INCLUDE_DIR}") - SET(OPENSSL_BIN_DIR ${OPENSSL_INCLUDE_DIR}) - string(REPLACE "include" "bin" OPENSSL_BIN_DIR ${OPENSSL_BIN_DIR}) - message("OpenSSL binary dir: ${OPENSSL_BIN_DIR}") + option(RESINSIGHT_BUNDLE_OPENSSL "Bundle the OpenSSL binary DLLs" OFF) + if (RESINSIGHT_BUNDLE_OPENSSL) + find_package(OpenSSL) + if (OPENSSL_FOUND) + message("OpenSSL include dir: ${OPENSSL_INCLUDE_DIR}") + SET(OPENSSL_BIN_DIR ${OPENSSL_INCLUDE_DIR}) + string(REPLACE "include" "bin" OPENSSL_BIN_DIR ${OPENSSL_BIN_DIR}) + message("OpenSSL binary dir: ${OPENSSL_BIN_DIR}") - install(FILES ${OPENSSL_BIN_DIR}/libeay32.dll DESTINATION ${RESINSIGHT_INSTALL_FOLDER}) - install(FILES ${OPENSSL_BIN_DIR}/ssleay32.dll DESTINATION ${RESINSIGHT_INSTALL_FOLDER}) - endif(OPENSSL_FOUND) + install(FILES ${OPENSSL_BIN_DIR}/libeay32.dll DESTINATION ${RESINSIGHT_INSTALL_FOLDER}) + install(FILES ${OPENSSL_BIN_DIR}/ssleay32.dll DESTINATION ${RESINSIGHT_INSTALL_FOLDER}) + endif(OPENSSL_FOUND) + endif(RESINSIGHT_BUNDLE_OPENSSL) # CRT set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_SKIP ON) From 22e47367ee376497f5d1d4d23502a65d2bf228ba Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 27 Jun 2019 11:37:52 +0200 Subject: [PATCH 228/396] #4506 Deployment : Add _openssl to package name when bundling OpenSSL --- ApplicationCode/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ApplicationCode/CMakeLists.txt b/ApplicationCode/CMakeLists.txt index 50af82455e..55e6e0ed6f 100644 --- a/ApplicationCode/CMakeLists.txt +++ b/ApplicationCode/CMakeLists.txt @@ -775,6 +775,10 @@ if(RESINSIGHT_FOUND_HDF5) set (RESINSIGHT_PACKAGE_NAME "${RESINSIGHT_PACKAGE_NAME}_souring") endif() +if(RESINSIGHT_BUNDLE_OPENSSL AND OPENSSL_FOUND) + set (RESINSIGHT_PACKAGE_NAME "${RESINSIGHT_PACKAGE_NAME}_openssl") +endif() + # Append el5 when compiled on RHEL5 and el6 if compiled on RHEL6 if (NOT "${RESINSIGHT_RHEL_SYSTEM_NAME}" STREQUAL "") set (RESINSIGHT_PACKAGE_NAME "${RESINSIGHT_PACKAGE_NAME}_${RESINSIGHT_RHEL_SYSTEM_NAME}") From b70c88330adebb60c51afc80c2c25100bd8cfeab Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 28 Jun 2019 13:37:37 +0200 Subject: [PATCH 229/396] #4508 Qt5 : Crash when taking snapshot of MDI window --- Fwk/AppFwk/cafViewer/cafViewer.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Fwk/AppFwk/cafViewer/cafViewer.cpp b/Fwk/AppFwk/cafViewer/cafViewer.cpp index 016a7d3134..d95b5b8c21 100644 --- a/Fwk/AppFwk/cafViewer/cafViewer.cpp +++ b/Fwk/AppFwk/cafViewer/cafViewer.cpp @@ -870,6 +870,9 @@ bool caf::Viewer::isShadersSupported() //-------------------------------------------------------------------------------------------------- QImage caf::Viewer::snapshotImage() { + // Qt5 : Call paintEvent() manually to make sure invisible widgets are rendered properly + // If this call is skipped, we get an assert in cvf::FramebufferObject::bind() + paintEvent(nullptr); QImage image; if (m_offscreenFbo.notNull() && m_offscreenViewportWidth > 0 && m_offscreenViewportHeight > 0) From 439913b7b111d07515049364e111319f4d0e274b Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Mon, 10 Jun 2019 20:42:20 +0200 Subject: [PATCH 230/396] #4423 First implementation of PdmObject exchange --- .../Core/RicfCommandObject.h | 3 + .../Core/RicfFieldCapability.cpp | 27 +++ .../Core/RicfFieldCapability.h | 13 ++ .../GrpcInterface/CMakeLists.cmake | 5 +- .../GrpcInterface/CMakeLists.cmake.orig | 206 ------------------ .../GrpcInterface/GrpcProtos/Case.proto | 3 + .../GrpcInterface/GrpcProtos/PdmObject.proto | 37 ++++ .../GrpcInterface/GrpcProtos/Project.proto | 4 +- .../GrpcInterface/Python/rips/Case.py | 10 +- .../GrpcInterface/Python/rips/Instance.py | 9 +- .../GrpcInterface/Python/rips/PdmObject.py | 78 +++++++ .../GrpcInterface/Python/rips/Project.py | 4 +- .../Python/rips/examples/AllCases.py | 30 +++ .../Python/rips/tests/test_cases.py | 12 + .../GrpcInterface/RiaGrpcCaseService.cpp | 16 ++ .../GrpcInterface/RiaGrpcCaseService.h | 3 +- .../GrpcInterface/RiaGrpcPdmObjectService.cpp | 192 ++++++++++++++++ .../GrpcInterface/RiaGrpcPdmObjectService.h | 49 +++++ .../GrpcInterface/RiaGrpcProjectService.cpp | 16 +- .../GrpcInterface/RiaGrpcProjectService.h | 1 + .../GrpcInterface/RiaGrpcServiceInterface.cpp | 79 +++++++ .../GrpcInterface/RiaGrpcServiceInterface.h | 18 ++ .../ProjectDataModel/Rim3dView.cpp | 14 +- ApplicationCode/ProjectDataModel/RimCase.cpp | 4 +- .../RimEclipseResultDefinition.cpp | 8 +- Fwk/AppFwk/cafProjectDataModel/CMakeLists.txt | 1 + .../cafPdmCore/cafPdmObjectHandle.h | 2 +- .../cafProjectDataModel/cafPdmObject.cpp | 98 +++++++++ Fwk/AppFwk/cafProjectDataModel/cafPdmObject.h | 16 ++ 29 files changed, 730 insertions(+), 228 deletions(-) delete mode 100644 ApplicationCode/GrpcInterface/CMakeLists.cmake.orig create mode 100644 ApplicationCode/GrpcInterface/GrpcProtos/PdmObject.proto create mode 100644 ApplicationCode/GrpcInterface/Python/rips/PdmObject.py create mode 100644 ApplicationCode/GrpcInterface/RiaGrpcPdmObjectService.cpp create mode 100644 ApplicationCode/GrpcInterface/RiaGrpcPdmObjectService.h create mode 100644 Fwk/AppFwk/cafProjectDataModel/cafPdmObject.cpp diff --git a/ApplicationCode/CommandFileInterface/Core/RicfCommandObject.h b/ApplicationCode/CommandFileInterface/Core/RicfCommandObject.h index 1007e9ac16..8a0ac50510 100644 --- a/ApplicationCode/CommandFileInterface/Core/RicfCommandObject.h +++ b/ApplicationCode/CommandFileInterface/Core/RicfCommandObject.h @@ -26,6 +26,9 @@ CAF_PDM_InitField(field, keyword, default, uiName, iconResourceName, toolTip, whatsThis); \ AddRicfCapabilityToField(field) +#define RICF_InitFieldNoDefault(field, keyword, uiName, iconResourceName, toolTip, whatsThis) \ +CAF_PDM_InitFieldNoDefault(field, keyword, uiName, iconResourceName, toolTip, whatsThis); \ +AddRicfCapabilityToField(field) //================================================================================================== // diff --git a/ApplicationCode/CommandFileInterface/Core/RicfFieldCapability.cpp b/ApplicationCode/CommandFileInterface/Core/RicfFieldCapability.cpp index 1b0e975aec..0c53a5823e 100644 --- a/ApplicationCode/CommandFileInterface/Core/RicfFieldCapability.cpp +++ b/ApplicationCode/CommandFileInterface/Core/RicfFieldCapability.cpp @@ -19,7 +19,9 @@ #include "RicfFieldCapability.h" #include "RicfMessages.h" +#include "RiaColorTools.h" +#include //-------------------------------------------------------------------------------------------------- @@ -130,3 +132,28 @@ void RicfFieldWriter::writeFieldData(const bool& fieldValue, QTextStream& // Lower-case true/false is used in the documentation. outputStream << (fieldValue ? "true" : "false"); } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicfFieldReader::readFieldData(cvf::Color3f& fieldValue, QTextStream& inputStream, RicfMessages* errorMessageContainer) +{ + QString fieldStringValue; + RicfFieldReader::readFieldData(fieldStringValue, inputStream, errorMessageContainer); + + if (QColor::isValidColor(fieldStringValue)) + { + QColor qColor(fieldStringValue); + fieldValue = RiaColorTools::fromQColorTo3f(qColor); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicfFieldWriter::writeFieldData(const cvf::Color3f& fieldValue, QTextStream& outputStream) +{ + QColor qColor = RiaColorTools::toQColor(fieldValue); + QString fieldStringValue = qColor.name(); + RicfFieldWriter::writeFieldData(fieldStringValue, outputStream); +} \ No newline at end of file diff --git a/ApplicationCode/CommandFileInterface/Core/RicfFieldCapability.h b/ApplicationCode/CommandFileInterface/Core/RicfFieldCapability.h index 960cd69f06..921524ae69 100644 --- a/ApplicationCode/CommandFileInterface/Core/RicfFieldCapability.h +++ b/ApplicationCode/CommandFileInterface/Core/RicfFieldCapability.h @@ -22,6 +22,8 @@ #include "RicfMessages.h" #include "cafAppEnum.h" +#include "cvfBase.h" +#include "cvfColor3.h" #include #include @@ -77,6 +79,17 @@ struct RicfFieldWriter static void writeFieldData(const bool& fieldValue, QTextStream& outputStream); }; +template<> +struct RicfFieldReader +{ + static void readFieldData(cvf::Color3f& fieldValue, QTextStream& inputStream, RicfMessages* errorMessageContainer); +}; + +template<> +struct RicfFieldWriter +{ + static void writeFieldData(const cvf::Color3f& fieldValue, QTextStream& outputStream); +}; template struct RicfFieldReader< caf::AppEnum > diff --git a/ApplicationCode/GrpcInterface/CMakeLists.cmake b/ApplicationCode/GrpcInterface/CMakeLists.cmake index 6096786078..93d2134210 100644 --- a/ApplicationCode/GrpcInterface/CMakeLists.cmake +++ b/ApplicationCode/GrpcInterface/CMakeLists.cmake @@ -11,6 +11,7 @@ set ( SOURCE_GROUP_HEADER_FILES ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcCommandService.h ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcAppService.h ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcPropertiesService.h + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcPdmObjectService.h ) set ( SOURCE_GROUP_SOURCE_FILES @@ -22,6 +23,7 @@ set ( SOURCE_GROUP_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcCommandService.cpp ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcAppService.cpp ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcPropertiesService.cpp + ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcPdmObjectService.cpp ) add_definitions(-DENABLE_GRPC) @@ -76,6 +78,7 @@ endif(PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) # Proto files set(PROTO_FILES "Empty" + "PdmObject" "Case" "Project" "Commands" @@ -156,7 +159,7 @@ if (PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) "rips/Project.py" "rips/Properties.py" "rips/Instance.py" - "rips/examples/AppInfo.py" + "rips/PdmObject.py" "rips/examples/InstanceExample.py" "rips/examples/CommandExample.py" "rips/examples/CaseInfoStreamingExample.py" diff --git a/ApplicationCode/GrpcInterface/CMakeLists.cmake.orig b/ApplicationCode/GrpcInterface/CMakeLists.cmake.orig deleted file mode 100644 index 3a3f4c43df..0000000000 --- a/ApplicationCode/GrpcInterface/CMakeLists.cmake.orig +++ /dev/null @@ -1,206 +0,0 @@ -cmake_minimum_required (VERSION 2.8.12) - -set ( SOURCE_GROUP_HEADER_FILES - ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcServer.h - ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcCallbacks.h - ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcCallbacks.inl - ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcServiceInterface.h - ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcCaseService.h - ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcGridService.h - ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcProjectService.h - ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcCommandService.h - ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcAppService.h - ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcPropertiesService.h -) - -set ( SOURCE_GROUP_SOURCE_FILES - ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcServer.cpp - ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcServiceInterface.cpp - ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcCaseService.cpp - ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcGridService.cpp - ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcProjectService.cpp - ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcCommandService.cpp - ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcAppService.cpp - ${CMAKE_CURRENT_LIST_DIR}/RiaGrpcPropertiesService.cpp -) - -add_definitions(-DENABLE_GRPC) - -if (MSVC) - add_definitions(-D_WIN32_WINNT=0x600) - - # Find Protobuf installation - # Looks for protobuf-config.cmake file installed by Protobuf's cmake installation. - set(protobuf_MODULE_COMPATIBLE ON CACHE DBOOL "") - find_package(Protobuf CONFIG 3.0 QUIET) - if (Protobuf_FOUND) - message(STATUS "Using protobuf ${protobuf_VERSION}") - else() - message(FATAL_ERROR "Protocol Buffers not found. This is required to build with gRPC") - endif() - - # Find gRPC installation - # Looks for gRPCConfig.cmake file installed by gRPC's cmake installation. - find_package(gRPC CONFIG REQUIRED NO_MODULE) - message(STATUS "Using gRPC ${gRPC_VERSION}") - - set(_PROTOBUF_LIBPROTOBUF protobuf::libprotobuf) - set(_PROTOBUF_PROTOC $) - - set(_GRPC_GRPCPP_UNSECURE gRPC::grpc++_unsecure gRPC::grpc_unsecure gRPC::gpr) - set(_GRPC_CPP_PLUGIN_EXECUTABLE $) - set(GRPC_LIBRARIES ${_GRPC_GRPCPP_UNSECURE} ${_PROTOBUF_LIBPROTOBUF}) - - set_target_properties(${GRPC_LIBRARIES} PROPERTIES - MAP_IMPORTED_CONFIG_MINSIZEREL RELEASE - MAP_IMPORTED_CONFIG_RELWITHDEBINFO RELEASE - ) - -else() - if (NOT DEFINED GRPC_INSTALL_PREFIX OR NOT EXISTS ${GRPC_INSTALL_PREFIX}) - message(FATAL_ERROR "You need a valid GRPC_INSTALL_PREFIX set to build with gRPC") - endif() - set(ENV{PKG_CONFIG_PATH} "${GRPC_INSTALL_PREFIX}/lib/pkgconfig") - find_package(PkgConfig REQUIRED) - pkg_check_modules(GRPC REQUIRED grpc++_unsecure>=1.20 grpc_unsecure gpr protobuf) - set(_PROTOBUF_PROTOC "${GRPC_INSTALL_PREFIX}/bin/protoc") - set(_GRPC_CPP_PLUGIN_EXECUTABLE "${GRPC_INSTALL_PREFIX}/bin/grpc_cpp_plugin") - include_directories(AFTER ${GRPC_INCLUDE_DIRS}) -endif() - -# Cannot use the nice new FindPackage modules for python since that is CMake 3.12+ -if(PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) - message(STATUS "Using Python ${PYTHON_EXECUTABLE}") -endif(PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) - -# Proto files -set(PROTO_FILES - "Empty" - "Case" - "Project" - "Commands" - "App" - "Properties" - "Grid" -) - -set(GRPC_PYTHON_SOURCE_PATH "${CMAKE_CURRENT_LIST_DIR}/Python") -set(GRPC_PYTHON_DEST_PATH "${CMAKE_BINARY_DIR}/Python") - -foreach(proto_file ${PROTO_FILES}) - get_filename_component(rips_proto "${CMAKE_CURRENT_LIST_DIR}/GrpcProtos/${proto_file}.proto" ABSOLUTE) - get_filename_component(rips_proto_path "${rips_proto}" PATH) - - list(APPEND GRPC_PROTO_FILES_FULL_PATH ${rips_proto}) - - set(rips_proto_srcs "${CMAKE_BINARY_DIR}/Generated/${proto_file}.pb.cc") - set(rips_proto_hdrs "${CMAKE_BINARY_DIR}/Generated/${proto_file}.pb.h") - set(rips_grpc_srcs "${CMAKE_BINARY_DIR}/Generated/${proto_file}.grpc.pb.cc") - set(rips_grpc_hdrs "${CMAKE_BINARY_DIR}/Generated/${proto_file}.grpc.pb.h") - - add_custom_command( - OUTPUT "${rips_proto_srcs}" "${rips_proto_hdrs}" "${rips_grpc_srcs}" "${rips_grpc_hdrs}" - COMMAND ${_PROTOBUF_PROTOC} - ARGS --grpc_out "${CMAKE_BINARY_DIR}/Generated" - --cpp_out "${CMAKE_BINARY_DIR}/Generated" - -I "${rips_proto_path}" - --plugin=protoc-gen-grpc="${_GRPC_CPP_PLUGIN_EXECUTABLE}" - "${rips_proto}" - DEPENDS "${rips_proto}" - ) - - if (PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) - set(rips_proto_python "generated/${proto_file}_pb2.py") - set(rips_grpc_python "generated/${proto_file}_pb2_grpc.py") - - add_custom_command( - OUTPUT "${GRPC_PYTHON_SOURCE_PATH}/${rips_proto_python}" "${GRPC_PYTHON_SOURCE_PATH}/${rips_grpc_python}" - COMMAND ${PYTHON_EXECUTABLE} - ARGS -m grpc_tools.protoc - -I "${rips_proto_path}" - --python_out "${GRPC_PYTHON_SOURCE_PATH}/generated" - --grpc_python_out "${GRPC_PYTHON_SOURCE_PATH}/generated" - "${rips_proto}" - DEPENDS "${rips_proto}" - COMMENT "Generating ${rips_proto_python} and ${rips_grpc_python}" - VERBATIM - ) - list (APPEND GRPC_PYTHON_GENERATED_SOURCES - ${rips_proto_python} - ${rips_grpc_python} - ) - - endif(PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) - - list( APPEND GRPC_HEADER_FILES - ${rips_proto_hdrs} - ${rips_grpc_hdrs} - ) - - list( APPEND GRPC_CPP_SOURCES - ${rips_proto_srcs} - ${rips_grpc_srcs} - ) - -endforeach(proto_file) - -if (PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) - list(APPEND GRPC_PYTHON_SOURCES - ${GRPC_PYTHON_GENERATED_SOURCES} - "generated/RiaVersionInfo.py" - "rips/__init__.py" - "rips/App.py" - "rips/Case.py" - "rips/Commands.py" - "rips/Grid.py" - "rips/Project.py" - "rips/Properties.py" - "rips/Instance.py" - "examples/CommandExample.py" - "examples/CaseInfoStreamingExample.py" - "examples/SoilPorvAsync.py" - "examples/SoilPorvSync.py" - "examples/SelectedCases.py" - "examples/AllCases.py" - "examples/SetGridProperties.py" - "examples/GridInformation.py" - "examples/InputPropTestSync.py" - "examples/InputPropTestAsync.py" - "examples/SoilAverage.py" - "examples/SoilAverageNoComm.py" - "tests/test_cases.py" -<<<<<<< Updated upstream - "tests/test_commands.py" -======= ->>>>>>> Stashed changes - "tests/test_grids.py" - "tests/test_properties.py" - "tests/conftest.py" - "tests/dataroot.py" - "requirements.txt" - "setup.py.cmake" - "README.md" - "LICENSE" - ) - - foreach(PYTHON_SCRIPT ${GRPC_PYTHON_SOURCES}) - list(APPEND GRPC_PYTHON_SOURCES_FULL_PATH "${GRPC_PYTHON_SOURCE_PATH}/${PYTHON_SCRIPT}") - endforeach() -if (MSVC) - source_group(TREE ${GRPC_PYTHON_SOURCE_PATH} FILES ${GRPC_PYTHON_SOURCES_FULL_PATH} PREFIX "GrpcInterface\\Python") -endif(MSVC) - -endif(PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) - -list ( APPEND GRPC_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES}) -list ( APPEND GRPC_CPP_SOURCES ${SOURCE_GROUP_SOURCE_FILES}) - -CONFIGURE_FILE( ${CMAKE_SOURCE_DIR}/ApplicationCode/Adm/RiaVersionInfo.py.cmake - ${GRPC_PYTHON_SOURCE_PATH}/generated/RiaVersionInfo.py -) -CONFIGURE_FILE( ${GRPC_PYTHON_SOURCE_PATH}/setup.py.cmake - ${GRPC_PYTHON_SOURCE_PATH}/setup.py -) - -source_group( "GrpcInterface" FILES ${SOURCE_GROUP_HEADER_FILES} ${SOURCE_GROUP_SOURCE_FILES} ${CMAKE_CURRENT_LIST_DIR}/CMakeLists.cmake ) -source_group( "GrpcInterface\\GrpcProtos" FILES ${GRPC_PROTO_FILES_FULL_PATH} ) \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/GrpcProtos/Case.proto b/ApplicationCode/GrpcInterface/GrpcProtos/Case.proto index 2752c86016..06701ec612 100644 --- a/ApplicationCode/GrpcInterface/GrpcProtos/Case.proto +++ b/ApplicationCode/GrpcInterface/GrpcProtos/Case.proto @@ -1,5 +1,7 @@ syntax = "proto3"; +import "PdmObject.proto"; + package rips; service Case @@ -11,6 +13,7 @@ service Case rpc GetTimeSteps(CaseRequest) returns (TimeStepDates) {} rpc GetDaysSinceStart(CaseRequest) returns (DaysSinceStart) {} rpc GetCaseInfo(CaseRequest) returns (CaseInfo) {} + rpc GetPdmObject(CaseRequest) returns (PdmObject) {} } message CaseRequest { diff --git a/ApplicationCode/GrpcInterface/GrpcProtos/PdmObject.proto b/ApplicationCode/GrpcInterface/GrpcProtos/PdmObject.proto new file mode 100644 index 0000000000..5d1b150147 --- /dev/null +++ b/ApplicationCode/GrpcInterface/GrpcProtos/PdmObject.proto @@ -0,0 +1,37 @@ +syntax = "proto3"; + +import "Empty.proto"; + +package rips; + +service PdmObjectService +{ + rpc GetDescendantPdmObjects(PdmChildObjectRequest) returns (PdmObjectArray) {} + rpc GetChildPdmObjects(PdmChildObjectRequest) returns (PdmObjectArray) {} + rpc GetAncestorPdmObject(PdmParentObjectRequest) returns (PdmObject) {} + rpc UpdateExistingPdmObject(PdmObject) returns (Empty) {} +} + +message PdmChildObjectRequest +{ + PdmObject object = 1; + string child_keyword = 2; +} + +message PdmParentObjectRequest +{ + PdmObject object = 1; + string parent_keyword = 2; +} + +message PdmObject +{ + string class_keyword = 1; + uint64 address = 2; + map parameters = 3; +} + +message PdmObjectArray +{ + repeated PdmObject objects = 1; +} \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/GrpcProtos/Project.proto b/ApplicationCode/GrpcInterface/GrpcProtos/Project.proto index 1c3c1c4f48..01b4f64a53 100644 --- a/ApplicationCode/GrpcInterface/GrpcProtos/Project.proto +++ b/ApplicationCode/GrpcInterface/GrpcProtos/Project.proto @@ -1,7 +1,8 @@ syntax = "proto3"; -import "Case.proto"; import "Empty.proto"; +import "Case.proto"; +import "PdmObject.proto"; package rips; @@ -11,4 +12,5 @@ service Project { rpc GetAllCaseGroups(Empty) returns (CaseGroups) {} rpc GetAllCases(Empty) returns (CaseInfoArray) {} rpc GetCasesInGroup(CaseGroup) returns (CaseInfoArray) {} + rpc GetPdmObject(Empty) returns (PdmObject) {} } diff --git a/ApplicationCode/GrpcInterface/Python/rips/Case.py b/ApplicationCode/GrpcInterface/Python/rips/Case.py index 202fb3fd24..45add1157a 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Case.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Case.py @@ -3,13 +3,15 @@ import os import sys from .Grid import Grid from .Properties import Properties +from .PdmObject import PdmObject sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'generated')) import Case_pb2 import Case_pb2_grpc +import PdmObject_pb2 -class Case: +class Case (PdmObject): """ResInsight case class Operate on a ResInsight case specified by a Case Id integer. @@ -31,6 +33,7 @@ class Case: self.type = info.type self.properties = Properties(self) self.request = Case_pb2.CaseRequest(id=self.id) + PdmObject.__init__(self, self.stub.GetPdmObject(self.request), self.channel) def gridCount(self): """Get number of grids in the case""" @@ -104,4 +107,7 @@ class Case: def daysSinceStart(self): """Get a list of decimal values representing days since the start of the simulation""" return self.stub.GetDaysSinceStart(self.request).day_decimals - \ No newline at end of file + + def views(self): + return self.children("ReservoirView") + diff --git a/ApplicationCode/GrpcInterface/Python/rips/Instance.py b/ApplicationCode/GrpcInterface/Python/rips/Instance.py index 33a254bc82..2378f3e7b6 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Instance.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Instance.py @@ -69,8 +69,7 @@ class Instance: parameters.append("--console") pid = os.spawnv(os.P_NOWAIT, resInsightExecutable, parameters) if pid: - instance = Instance(port=port) - instance.launched = True + instance = Instance(port=port, launched=True) return instance return None @@ -93,7 +92,7 @@ class Instance: for tryPort in range(startPort, endPort): if Instance.__is_port_in_use(tryPort): - return Instance(tryPort) + return Instance(port=tryPort) print('Error: Could not find any ResInsight instances responding between ports ' + str(startPort) + ' and ' + str(endPort)) return None @@ -106,7 +105,7 @@ class Instance: except grpc.RpcError as e: return False, False - def __init__(self, port = 50051): + def __init__(self, port = 50051, launched = False): """ Attempts to connect to ResInsight at aa specific port on localhost Args: @@ -116,7 +115,7 @@ class Instance: location = "localhost:" + str(port) self.channel = grpc.insecure_channel(location) - self.launched = False + self.launched = launched # Main version check package self.app = App(self.channel) diff --git a/ApplicationCode/GrpcInterface/Python/rips/PdmObject.py b/ApplicationCode/GrpcInterface/Python/rips/PdmObject.py new file mode 100644 index 0000000000..db19cd00a8 --- /dev/null +++ b/ApplicationCode/GrpcInterface/Python/rips/PdmObject.py @@ -0,0 +1,78 @@ +import grpc +import os +import sys + +sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'generated')) + +from Empty_pb2 import Empty +import PdmObject_pb2 +import PdmObject_pb2_grpc + +class PdmObject: + def __init__(self, pb2Object, channel): + self.pb2Object = pb2Object + self.channel = channel + self.stub = PdmObject_pb2_grpc.PdmObjectServiceStub(self.channel) + + def address(self): + return self.pb2Object.address + + def classKeyword(self): + return self.pb2Object.class_keyword + + def keywords(self): + listOfKeywords = [] + for keyword in self.pb2Object.parameters: + listOfKeywords.append(keyword) + return listOfKeywords + + def getValue(self, keyword): + value = self.pb2Object.parameters[keyword] + if value.lower() == 'false': + return False + elif value.lower() == 'true': + return True + else: + try: + intVal = int(value) + return intVal + except ValueError: + try: + floatVal = float(value) + return floatVal + except ValueError: + return value + + def setValue(self, keyword, value): + if isinstance(value, bool): + if value: + self.pb2Object.parameters[keyword] = "true" + else: + self.pb2Object.parameters[keyword] = "false" + elif isinstance(value, str): + self.pb2Object.parameters[keyword] = "\"" + str(value) + "\"" + else: + self.pb2Object.parameters[keyword] = str(value) + + def descendants(self, classKeyword): + request = PdmObject_pb2.PdmChildObjectRequest(object=self.pb2Object, child_keyword=classKeyword) + objectList = self.stub.GetDescendantPdmObjects(request).objects + childList = [] + for object in objectList: + childList.append(PdmObject(object, self.channel)) + return childList + + def children(self, classKeyword): + request = PdmObject_pb2.PdmChildObjectRequest(object=self.pb2Object, child_keyword=classKeyword) + objectList = self.stub.GetChildPdmObjects(request).objects + childList = [] + for object in objectList: + childList.append(PdmObject(object, self.channel)) + return childList + + def ancestor(self, classKeyword): + request = PdmObject_pb2.PdmParentObjectRequest(object=self.pb2Object, parent_keyword=classKeyword) + return PdmObject(self.stub.GetAncestorPdmObject(request), self.channel) + + def update(self): + self.stub.UpdateExistingPdmObject(self.pb2Object) \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/Python/rips/Project.py b/ApplicationCode/GrpcInterface/Python/rips/Project.py index d97aae4504..07207f096b 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Project.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Project.py @@ -4,6 +4,7 @@ import sys from .Case import Case from .Commands import Commands +from .PdmObject import PdmObject sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'generated')) @@ -11,7 +12,7 @@ from Empty_pb2 import Empty import Project_pb2 import Project_pb2_grpc -class Project: +class Project (PdmObject): """ResInsight project. Not intended to be created separately. Automatically created and assigned to Instance. @@ -19,6 +20,7 @@ class Project: def __init__(self, channel): self.channel = channel self.project = Project_pb2_grpc.ProjectStub(channel) + PdmObject.__init__(self, self.project.GetPdmObject(Empty()), self.channel) def open(self, path): """Open a new project from the given path diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/AllCases.py b/ApplicationCode/GrpcInterface/Python/rips/examples/AllCases.py index 3c0a742389..8af6f09442 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/examples/AllCases.py +++ b/ApplicationCode/GrpcInterface/Python/rips/examples/AllCases.py @@ -11,3 +11,33 @@ if resInsight is not None: print ("Got " + str(len(cases)) + " cases: ") for case in cases: print(case.name) + assert(case.address() is not 0) + assert(case.classKeyword() == "EclipseCase") + print("\n#### Case ####") + for keyword in case.keywords(): + print (keyword + ": " + case.getValue(keyword)) + print ("\n####Project#####") + pdmProject = case.ancestor(classKeyword="ResInsightProject") + assert(pdmProject) + assert(pdmProject.address() is not 0) + assert(pdmProject.address() == resInsight.project.address()) + + for keyword in resInsight.project.keywords(): + print (keyword + ": " + resInsight.project.getValue(keyword)) + pdmViews = resInsight.project.descendants(classKeyword="ReservoirView") + for view in pdmViews: + print ("\n####View####") + print(view.classKeyword(), view.address()) + for viewKeyword in view.keywords(): + print(viewKeyword + "-> " + str(view.getValue(viewKeyword))) + view.setValue("ShowGridBox", not view.getValue("ShowGridBox")) + view.setValue("ViewBackgroundColor", "#3388AA") + view.update() + + print ("\n####Cell Result####") + cellResults = view.children(classKeyword="ResultSlot") + for resultKeyword in cellResults[0].keywords(): + print(resultKeyword + "->" + str(cellResults[0].getValue(resultKeyword))) + cellResults[0].setValue("ResultVariable", "SOIL") + cellResults[0].setValue("ResultType", "DYNAMIC_NATIVE") + cellResults[0].update() \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/Python/rips/tests/test_cases.py b/ApplicationCode/GrpcInterface/Python/rips/tests/test_cases.py index ab1579c5e8..f2487c81fd 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/tests/test_cases.py +++ b/ApplicationCode/GrpcInterface/Python/rips/tests/test_cases.py @@ -50,6 +50,18 @@ def test_10k(rips_instance, initializeTest): daysSinceStart = case.daysSinceStart() assert(len(daysSinceStart) == 9) +def test_PdmObject(rips_instance, initializeTest): + casePath = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID" + case = rips_instance.project.loadCase(path=casePath) + pdmObject = case.pdmObject() + assert(pdmObject.address is not 0) + assert(pdmObject.class_keyword == "EclipseCase") + assert(pdmObject.parameters['CaseFileName'] == casePath) + assert(int(pdmObject.parameters['CaseId']) == 0) + for keyword in pdmObject.parameters: + + print (keyword + ": " + pdmObject.parameters[keyword]) + @pytest.mark.skipif(sys.platform.startswith('linux'), reason="Brugge is currently exceptionally slow on Linux") def test_brugge_0010(rips_instance, initializeTest): casePath = dataroot.PATH + "/Case_with_10_timesteps/Real10/BRUGGE_0010.EGRID" diff --git a/ApplicationCode/GrpcInterface/RiaGrpcCaseService.cpp b/ApplicationCode/GrpcInterface/RiaGrpcCaseService.cpp index 09be0fa52f..db238300e5 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcCaseService.cpp +++ b/ApplicationCode/GrpcInterface/RiaGrpcCaseService.cpp @@ -334,6 +334,21 @@ grpc::Status return Status(grpc::NOT_FOUND, "No cases found"); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +grpc::Status + RiaGrpcCaseService::GetPdmObject(grpc::ServerContext* context, const rips::CaseRequest* request, rips::PdmObject* reply) +{ + RimCase* rimCase = findCase(request->id()); + RimEclipseCase* eclipseCase = dynamic_cast(rimCase); + if (eclipseCase) + { + copyPdmObjectFromCafToRips(eclipseCase, reply); + } + return grpc::Status::OK; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -357,6 +372,7 @@ std::vector RiaGrpcCaseService::createCallbacks() new RiaGrpcUnaryCallback(this, &Self::GetTimeSteps, &Self::RequestGetTimeSteps), new RiaGrpcUnaryCallback(this, &Self::GetDaysSinceStart, &Self::RequestGetDaysSinceStart), new RiaGrpcUnaryCallback(this, &Self::GetCaseInfo, &Self::RequestGetCaseInfo), + new RiaGrpcUnaryCallback(this, &Self::GetPdmObject, &Self::RequestGetPdmObject), new RiaGrpcServerStreamCallback( this, &Self::GetCellInfoForActiveCells, &Self::RequestGetCellInfoForActiveCells, new RiaActiveCellInfoStateHandler)}; } diff --git a/ApplicationCode/GrpcInterface/RiaGrpcCaseService.h b/ApplicationCode/GrpcInterface/RiaGrpcCaseService.h index 621d3c3795..9535314790 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcCaseService.h +++ b/ApplicationCode/GrpcInterface/RiaGrpcCaseService.h @@ -27,6 +27,7 @@ namespace rips { class CaseRequest; +class PdmObject; } class RiaGrpcCallbackInterface; @@ -74,7 +75,7 @@ public: grpc::Status GetTimeSteps(grpc::ServerContext* context, const rips::CaseRequest* request, rips::TimeStepDates* reply) override; grpc::Status GetDaysSinceStart(grpc::ServerContext* context, const rips::CaseRequest* request, rips::DaysSinceStart* reply) override; grpc::Status GetCaseInfo(grpc::ServerContext* context, const rips::CaseRequest* request, rips::CaseInfo* reply) override; - + grpc::Status GetPdmObject(grpc::ServerContext* context, const rips::CaseRequest* request, rips::PdmObject* reply) override; grpc::Status GetCellInfoForActiveCells(grpc::ServerContext* context, const rips::CellInfoRequest* request, rips::CellInfoArray* reply, diff --git a/ApplicationCode/GrpcInterface/RiaGrpcPdmObjectService.cpp b/ApplicationCode/GrpcInterface/RiaGrpcPdmObjectService.cpp new file mode 100644 index 0000000000..ae696df503 --- /dev/null +++ b/ApplicationCode/GrpcInterface/RiaGrpcPdmObjectService.cpp @@ -0,0 +1,192 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 "RiaGrpcPdmObjectService.h" + +#include "RiaApplication.h" +#include "RiaGrpcCallbacks.h" +#include "Rim3dView.h" +#include "RimEclipseResultDefinition.h" +#include "RimProject.h" + +#include "cafPdmObject.h" + +using namespace rips; + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +grpc::Status RiaGrpcPdmObjectService::GetAncestorPdmObject(grpc::ServerContext* context, + const rips::PdmParentObjectRequest* request, + rips::PdmObject* reply) +{ + RimProject* project = RiaApplication::instance()->project(); + std::vector objectsOfCurrentClass; + project->descendantsIncludingThisFromClassKeyword(QString::fromStdString(request->object().class_keyword()), + objectsOfCurrentClass); + + caf::PdmObject* matchingObject = nullptr; + for (caf::PdmObject* testObject : objectsOfCurrentClass) + { + if (reinterpret_cast(testObject) == request->object().address()) + { + matchingObject = testObject; + } + } + + if (matchingObject) + { + caf::PdmObject* parentObject = nullptr; + matchingObject->firstAncestorOrThisFromClassKeyword(QString::fromStdString(request->parent_keyword()), parentObject); + if (parentObject) + { + copyPdmObjectFromCafToRips(parentObject, reply); + return grpc::Status::OK; + } + } + return grpc::Status(grpc::NOT_FOUND, "Parent PdmObject not found"); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +grpc::Status RiaGrpcPdmObjectService::GetDescendantPdmObjects(grpc::ServerContext* context, + const rips::PdmChildObjectRequest* request, + rips::PdmObjectArray* reply) +{ + RimProject* project = RiaApplication::instance()->project(); + std::vector objectsOfCurrentClass; + project->descendantsIncludingThisFromClassKeyword(QString::fromStdString(request->object().class_keyword()), + objectsOfCurrentClass); + + caf::PdmObject* matchingObject = nullptr; + for (caf::PdmObject* testObject : objectsOfCurrentClass) + { + if (reinterpret_cast(testObject) == request->object().address()) + { + matchingObject = testObject; + } + } + + if (matchingObject) + { + std::vector childObjects; + matchingObject->descendantsIncludingThisFromClassKeyword(QString::fromStdString(request->child_keyword()), childObjects); + for (auto pdmChild : childObjects) + { + rips::PdmObject* ripsChild = reply->add_objects(); + copyPdmObjectFromCafToRips(pdmChild, ripsChild); + } + return grpc::Status::OK; + } + return grpc::Status(grpc::NOT_FOUND, "Current PdmObject not found"); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +grpc::Status RiaGrpcPdmObjectService::GetChildPdmObjects(grpc::ServerContext* context, + const rips::PdmChildObjectRequest* request, + rips::PdmObjectArray* reply) +{ + RimProject* project = RiaApplication::instance()->project(); + std::vector objectsOfCurrentClass; + project->descendantsIncludingThisFromClassKeyword(QString::fromStdString(request->object().class_keyword()), + objectsOfCurrentClass); + + caf::PdmObject* matchingObject = nullptr; + for (caf::PdmObject* testObject : objectsOfCurrentClass) + { + if (reinterpret_cast(testObject) == request->object().address()) + { + matchingObject = testObject; + } + } + + if (matchingObject) + { + std::vector childObjects; + matchingObject->childrenFromClassKeyword(QString::fromStdString(request->child_keyword()), childObjects); + for (auto pdmChild : childObjects) + { + rips::PdmObject* ripsChild = reply->add_objects(); + copyPdmObjectFromCafToRips(pdmChild, ripsChild); + } + return grpc::Status::OK; + } + return grpc::Status(grpc::NOT_FOUND, "Current PdmObject not found"); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +grpc::Status RiaGrpcPdmObjectService::UpdateExistingPdmObject(grpc::ServerContext* context, + const rips::PdmObject* request, + rips::Empty* response) +{ + RimProject* project = RiaApplication::instance()->project(); + std::vector objectsOfCurrentClass; + project->descendantsIncludingThisFromClassKeyword(QString::fromStdString(request->class_keyword()), objectsOfCurrentClass); + + caf::PdmObject* matchingObject = nullptr; + for (caf::PdmObject* pdmObject : objectsOfCurrentClass) + { + if (reinterpret_cast(pdmObject) == request->address()) + { + matchingObject = pdmObject; + } + } + + if (matchingObject) + { + copyPdmObjectFromRipsToCaf(request, matchingObject); + RimEclipseResultDefinition* resultDefinition = dynamic_cast(matchingObject); + // TODO: Make this more general. Perhaps we need an interface method for updating UI fields + if (resultDefinition) + { + resultDefinition->updateUiFieldsFromActiveResult(); + } + + matchingObject->updateAllRequiredEditors(); + project->scheduleCreateDisplayModelAndRedrawAllViews(); + Rim3dView* view = dynamic_cast(matchingObject); + if (view) + { + view->applyBackgroundColorAndFontChanges(); + } + return grpc::Status::OK; + } + return grpc::Status(grpc::NOT_FOUND, "PdmObject not found"); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RiaGrpcPdmObjectService::createCallbacks() +{ + typedef RiaGrpcPdmObjectService Self; + return + { + new RiaGrpcUnaryCallback(this, &Self::GetAncestorPdmObject, &Self::RequestGetAncestorPdmObject), + new RiaGrpcUnaryCallback(this, &Self::GetDescendantPdmObjects, &Self::RequestGetDescendantPdmObjects), + new RiaGrpcUnaryCallback(this, &Self::GetChildPdmObjects, &Self::RequestGetChildPdmObjects), + new RiaGrpcUnaryCallback(this, &Self::UpdateExistingPdmObject, &Self::RequestUpdateExistingPdmObject), + }; +} + +static bool RiaGrpcPdmObjectService_init = + RiaGrpcServiceFactory::instance()->registerCreator(typeid(RiaGrpcPdmObjectService).hash_code()); diff --git a/ApplicationCode/GrpcInterface/RiaGrpcPdmObjectService.h b/ApplicationCode/GrpcInterface/RiaGrpcPdmObjectService.h new file mode 100644 index 0000000000..dfb5ad33cc --- /dev/null +++ b/ApplicationCode/GrpcInterface/RiaGrpcPdmObjectService.h @@ -0,0 +1,49 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 "PdmObject.grpc.pb.h" +#include "RiaGrpcServiceInterface.h" + + +#include +#include + +//================================================================================================== +// +// gRPC-service answering request searching for PdmObjects in property tree +// +//================================================================================================== +class RiaGrpcPdmObjectService final : public rips::PdmObjectService::AsyncService, public RiaGrpcServiceInterface +{ +public: + grpc::Status GetAncestorPdmObject(grpc::ServerContext* context, + const rips::PdmParentObjectRequest* request, + rips::PdmObject* reply) override; + grpc::Status GetDescendantPdmObjects(grpc::ServerContext* context, + const rips::PdmChildObjectRequest* request, + rips::PdmObjectArray* reply); + grpc::Status GetChildPdmObjects(grpc::ServerContext* context, + const rips::PdmChildObjectRequest* request, + rips::PdmObjectArray* reply); + + grpc::Status + UpdateExistingPdmObject(grpc::ServerContext* context, const rips::PdmObject* request, rips::Empty* response) override; + + std::vector createCallbacks() override; +}; diff --git a/ApplicationCode/GrpcInterface/RiaGrpcProjectService.cpp b/ApplicationCode/GrpcInterface/RiaGrpcProjectService.cpp index 364e7cc15a..2041d59b88 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcProjectService.cpp +++ b/ApplicationCode/GrpcInterface/RiaGrpcProjectService.cpp @@ -179,6 +179,19 @@ grpc::Status return Status(grpc::NOT_FOUND, "No cases found"); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +grpc::Status RiaGrpcProjectService::GetPdmObject(grpc::ServerContext* context, const rips::Empty* request, rips::PdmObject* reply) +{ + RimProject* project = RiaApplication::instance()->project(); + if (project) + { + copyPdmObjectFromCafToRips(project, reply); + } + return grpc::Status::OK; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -191,7 +204,8 @@ std::vector RiaGrpcProjectService::createCallbacks() new RiaGrpcUnaryCallback(this, &Self::GetSelectedCases, &Self::RequestGetSelectedCases), new RiaGrpcUnaryCallback(this, &Self::GetAllCaseGroups, &Self::RequestGetAllCaseGroups), new RiaGrpcUnaryCallback(this, &Self::GetAllCases, &Self::RequestGetAllCases), - new RiaGrpcUnaryCallback(this, &Self::GetCasesInGroup, &Self::RequestGetCasesInGroup)}; + new RiaGrpcUnaryCallback(this, &Self::GetCasesInGroup, &Self::RequestGetCasesInGroup), + new RiaGrpcUnaryCallback(this, &Self::GetPdmObject, &Self::RequestGetPdmObject) }; } static bool RiaGrpcProjectService_init = diff --git a/ApplicationCode/GrpcInterface/RiaGrpcProjectService.h b/ApplicationCode/GrpcInterface/RiaGrpcProjectService.h index 37143c9b8d..7c0383c53e 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcProjectService.h +++ b/ApplicationCode/GrpcInterface/RiaGrpcProjectService.h @@ -43,6 +43,7 @@ public: grpc::Status GetAllCaseGroups(grpc::ServerContext* context, const rips::Empty* request, rips::CaseGroups* reply) override; grpc::Status GetAllCases(grpc::ServerContext* context, const rips::Empty* request, rips::CaseInfoArray* reply) override; grpc::Status GetCasesInGroup(grpc::ServerContext* context, const rips::CaseGroup* request, rips::CaseInfoArray* reply) override; + grpc::Status GetPdmObject(grpc::ServerContext* context, const rips::Empty* request, rips::PdmObject* reply) override; public: std::vector createCallbacks() override; diff --git a/ApplicationCode/GrpcInterface/RiaGrpcServiceInterface.cpp b/ApplicationCode/GrpcInterface/RiaGrpcServiceInterface.cpp index 063cbafd0a..5fb52e367c 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcServiceInterface.cpp +++ b/ApplicationCode/GrpcInterface/RiaGrpcServiceInterface.cpp @@ -21,8 +21,17 @@ #include "RimProject.h" #include "RimCase.h" +#include "RicfFieldHandle.h" +#include "RicfMessages.h" + +#include "cafPdmDataValueField.h" +#include "cafPdmObject.h" +#include "cafPdmXmlFieldHandle.h" + #include +#include +#include //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -52,3 +61,73 @@ size_t RiaGrpcServiceInterface::numberOfMessagesForByteCount(size_t messageSize, return messageCount; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaGrpcServiceInterface::copyPdmObjectFromCafToRips(const caf::PdmObject* source, rips::PdmObject* destination) +{ + CAF_ASSERT(source && destination); + + destination->set_class_keyword(source->classKeyword().toStdString()); + destination->set_address(reinterpret_cast(source)); + std::vector fields; + source->fields(fields); + + auto parametersMap = destination->mutable_parameters(); + for (auto field : fields) + { + auto pdmValueField = dynamic_cast(field); + if (pdmValueField) + { + QString keyword = pdmValueField->keyword(); + auto ricfHandle = field->template capability(); + if (ricfHandle != nullptr) + { + QString text; + QTextStream outStream(&text); + ricfHandle->writeFieldData(outStream); + (*parametersMap)[keyword.toStdString()] = text.toStdString(); + } + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaGrpcServiceInterface::copyPdmObjectFromRipsToCaf(const rips::PdmObject* source, caf::PdmObject* destination) +{ + CAF_ASSERT(source && destination); + CAF_ASSERT(source->class_keyword() == destination->classKeyword().toStdString()); + CAF_ASSERT(source->address() == reinterpret_cast(destination)); + std::vector fields; + destination->fields(fields); + + auto parametersMap = source->parameters(); + for (auto field : fields) + { + auto pdmValueField = dynamic_cast(field); + if (pdmValueField) + { + QString keyword = pdmValueField->keyword(); + QString value = QString::fromStdString(parametersMap[keyword.toStdString()]); + + assignFieldValue(value, pdmValueField); + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaGrpcServiceInterface::assignFieldValue(const QString& stringValue, caf::PdmValueField* field) +{ + auto ricfHandle = field->template capability(); + if (field && ricfHandle != nullptr) + { + QTextStream stream(stringValue.toLatin1()); + RicfMessages messages; + ricfHandle->readFieldData(stream, nullptr, &messages); + } +} + diff --git a/ApplicationCode/GrpcInterface/RiaGrpcServiceInterface.h b/ApplicationCode/GrpcInterface/RiaGrpcServiceInterface.h index 3795ea57f1..a4fecb2d28 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcServiceInterface.h +++ b/ApplicationCode/GrpcInterface/RiaGrpcServiceInterface.h @@ -24,6 +24,19 @@ class RiaGrpcCallbackInterface; class RimCase; +namespace caf +{ +class PdmObject; +class PdmValueField; +} + +namespace rips +{ +class PdmObject; +} + +class QString; + //================================================================================================== // // gRPC-service interface which all gRPC-services has to implement @@ -36,6 +49,11 @@ public: virtual ~RiaGrpcServiceInterface() = default; static RimCase* findCase(int caseId); static size_t numberOfMessagesForByteCount(size_t messageSize, size_t byteCount = 64 * 1024u); + + static void copyPdmObjectFromCafToRips(const caf::PdmObject* source, rips::PdmObject* destination); + static void copyPdmObjectFromRipsToCaf(const rips::PdmObject* source, caf::PdmObject* destination); + + static void assignFieldValue(const QString& stringValue, caf::PdmValueField* field); }; #include "cafFactory.h" diff --git a/ApplicationCode/ProjectDataModel/Rim3dView.cpp b/ApplicationCode/ProjectDataModel/Rim3dView.cpp index 4caf61695b..697048048c 100644 --- a/ApplicationCode/ProjectDataModel/Rim3dView.cpp +++ b/ApplicationCode/ProjectDataModel/Rim3dView.cpp @@ -24,6 +24,8 @@ #include "RiaPreferences.h" #include "RiaViewRedrawScheduler.h" +#include "RicfCommandObject.h" + #include "Rim3dWellLogCurve.h" #include "RimAnnotationInViewCollection.h" #include "RimCase.h" @@ -101,7 +103,7 @@ Rim3dView::Rim3dView(void) CAF_PDM_InitField(&scaleZ, "GridZScale", defaultScaleFactor, "Z Scale", "", "Scales the scene in the Z direction", ""); cvf::Color3f defBackgColor = preferences->defaultViewerBackgroundColor(); - CAF_PDM_InitField(&m_backgroundColor, "ViewBackgroundColor", defBackgColor, "Background", "", "", ""); + RICF_InitField(&m_backgroundColor, "ViewBackgroundColor", defBackgColor, "Background", "", "", ""); CAF_PDM_InitField(&maximumFrameRate, "MaximumFrameRate", 10, "Maximum Frame Rate", "", "", ""); maximumFrameRate.uiCapability()->setUiHidden(true); @@ -115,12 +117,12 @@ Rim3dView::Rim3dView(void) CAF_PDM_InitField(&meshMode, "MeshMode", defaultMeshType, "Grid Lines", "", "", ""); CAF_PDM_InitFieldNoDefault(&surfaceMode, "SurfaceMode", "Grid Surface", "", "", ""); - CAF_PDM_InitField(&m_showGridBox, "ShowGridBox", true, "Show Grid Box", "", "", ""); + RICF_InitField(&m_showGridBox, "ShowGridBox", true, "Show Grid Box", "", "", ""); CAF_PDM_InitField(&m_disableLighting, "DisableLighting", false, "Disable Results Lighting", "", "Disable light model for scalar result colors", ""); CAF_PDM_InitField(&m_showZScaleLabel, "ShowZScale", true, "Show Z Scale Label", "", "", ""); - + m_crossSectionVizModel = new cvf::ModelBasicList; m_crossSectionVizModel->setName("CrossSectionModel"); @@ -135,6 +137,9 @@ Rim3dView::Rim3dView(void) m_measurementPartManager = new RivMeasurementPartMgr(this); this->setAs3DViewMdiWindow(); + + RimProject* proj = RiaApplication::instance()->project(); + proj->assignViewIdToView(this); } //-------------------------------------------------------------------------------------------------- @@ -279,8 +284,7 @@ void Rim3dView::deleteViewWidget() void Rim3dView::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) { caf::PdmUiGroup* viewGroup = uiOrdering.addNewGroupWithKeyword("Viewer", "ViewGroup"); - - //viewGroup->add(m_nameConfig->nameField()); + viewGroup->add(&m_backgroundColor); viewGroup->add(&m_showZScaleLabel); viewGroup->add(&m_showGridBox); diff --git a/ApplicationCode/ProjectDataModel/RimCase.cpp b/ApplicationCode/ProjectDataModel/RimCase.cpp index 6ef3cd59fa..88e74d5c2e 100644 --- a/ApplicationCode/ProjectDataModel/RimCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimCase.cpp @@ -20,6 +20,8 @@ #include "RimCase.h" #include "RiaApplication.h" +#include "RicfCommandObject.h" + #include "RimFormationNames.h" #include "RimFormationNamesCollection.h" #include "RimOilField.h" @@ -42,7 +44,7 @@ CAF_PDM_XML_ABSTRACT_SOURCE_INIT(RimCase, "RimCase"); //-------------------------------------------------------------------------------------------------- RimCase::RimCase() : m_isInActiveDestruction(false) { - CAF_PDM_InitField(&caseUserDescription, "CaseUserDescription", QString(), "Case Name", "", "" ,""); + RICF_InitField(&caseUserDescription, "CaseUserDescription", QString(), "Case Name", "", "" ,""); CAF_PDM_InitField(&caseId, "CaseId", -1, "Case ID", "", "" ,""); caseId.uiCapability()->setUiReadOnly(true); diff --git a/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.cpp b/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.cpp index 898003a450..b284f01a9a 100644 --- a/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.cpp +++ b/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.cpp @@ -24,6 +24,8 @@ #include "RiaLogging.h" #include "RiaQDateTimeTools.h" +#include "RicfCommandObject.h" + #include "RigActiveCellInfo.h" #include "RigCaseCellResultsData.h" #include "RigEclipseCaseData.h" @@ -82,13 +84,13 @@ RimEclipseResultDefinition::RimEclipseResultDefinition(caf::PdmUiItemInfo::Label { CAF_PDM_InitObject("Result Definition", "", "", ""); - CAF_PDM_InitFieldNoDefault(&m_resultType, "ResultType", "Type", "", "", ""); + RICF_InitFieldNoDefault(&m_resultType, "ResultType", "Type", "", "", ""); m_resultType.uiCapability()->setUiHidden(true); - CAF_PDM_InitFieldNoDefault(&m_porosityModel, "PorosityModelType", "Porosity", "", "", ""); + RICF_InitFieldNoDefault(&m_porosityModel, "PorosityModelType", "Porosity", "", "", ""); m_porosityModel.uiCapability()->setUiHidden(true); - CAF_PDM_InitField(&m_resultVariable, "ResultVariable", RiaDefines::undefinedResultName(), "Variable", "", "", ""); + RICF_InitField(&m_resultVariable, "ResultVariable", RiaDefines::undefinedResultName(), "Variable", "", "", ""); m_resultVariable.uiCapability()->setUiHidden(true); CAF_PDM_InitFieldNoDefault(&m_flowSolution, "FlowDiagSolution", "Solution", "", "", ""); diff --git a/Fwk/AppFwk/cafProjectDataModel/CMakeLists.txt b/Fwk/AppFwk/cafProjectDataModel/CMakeLists.txt index 90bb67c169..2a2c037d63 100644 --- a/Fwk/AppFwk/cafProjectDataModel/CMakeLists.txt +++ b/Fwk/AppFwk/cafProjectDataModel/CMakeLists.txt @@ -18,6 +18,7 @@ set( PROJECT_FILES cafPdmDocument.h cafPdmObjectGroup.cpp cafPdmObjectGroup.h + cafPdmObject.cpp cafPdmObject.h cafPdmField.h ) diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/cafPdmObjectHandle.h b/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/cafPdmObjectHandle.h index 87d5e1a7d8..40dc6f18e6 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/cafPdmObjectHandle.h +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/cafPdmObjectHandle.h @@ -47,7 +47,7 @@ public: template void descendantsIncludingThisOfType(std::vector& descendants) const; - // PtrReferences + // PtrReferences /// The PdmPtrField's containing pointers to this PdmObjecthandle /// Use ownerObject() on the fieldHandle to get the PdmObjectHandle void referringPtrFields(std::vector& fieldsReferringToMe) const; diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmObject.cpp b/Fwk/AppFwk/cafProjectDataModel/cafPdmObject.cpp new file mode 100644 index 0000000000..721371c2af --- /dev/null +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmObject.cpp @@ -0,0 +1,98 @@ +#include "cafPdmObject.h" + +using namespace caf; + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void PdmObject::firstAncestorOrThisFromClassKeyword( + const QString& classKeyword, PdmObject*& ancestor) const +{ + ancestor = nullptr; + + // Check if this matches the type + if (this->classKeyword() == classKeyword) + { + ancestor = const_cast(this); + return; + } + + // Search parents for first type match + + PdmObject* parent = nullptr; + PdmFieldHandle* parentField = this->parentField(); + if (parentField) parent = dynamic_cast(parentField->ownerObject()); + + while (parent != nullptr) + { + if (parent->classKeyword() == classKeyword) + { + ancestor = parent; + return; + } + // Get next level parent + + PdmFieldHandle* nextParentField = parent->parentField(); + if (nextParentField) + { + parent = dynamic_cast(nextParentField->ownerObject()); + } + else + { + parent = nullptr; + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void PdmObject::descendantsIncludingThisFromClassKeyword( + const QString& classKeyword, + std::vector& descendants) const +{ + if (this->classKeyword() == classKeyword) + { + descendants.push_back(const_cast(this)); + } + + std::vector fields; + this->fields(fields); + for (auto f : fields) + { + std::vector childObjects; + f->childObjects(&childObjects); + for (auto childObject : childObjects) + { + PdmObject* pdmObjectChild = dynamic_cast(childObject); + if (pdmObjectChild) + { + pdmObjectChild->descendantsIncludingThisFromClassKeyword(classKeyword, descendants); + } + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void PdmObject::childrenFromClassKeyword( + const QString& classKeyword, + std::vector& children) const +{ + std::vector fields; + this->fields(fields); + for (auto f : fields) + { + std::vector childObjects; + f->childObjects(&childObjects); + for (auto childObject : childObjects) + { + PdmObject* pdmObjectChild = dynamic_cast(childObject); + if (pdmObjectChild && pdmObjectChild->classKeyword() == classKeyword) + { + children.push_back(pdmObjectChild); + } + } + } +} diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmObject.h b/Fwk/AppFwk/cafProjectDataModel/cafPdmObject.h index d263892418..f465586e72 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmObject.h +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmObject.h @@ -166,6 +166,22 @@ public: } } + /// Returns _this_ if _this_ has requested class keyword + /// Traverses parents recursively and returns first parent of the requested + /// type. + void firstAncestorOrThisFromClassKeyword(const QString& classKeyword, + PdmObject*& ancestor) const; + + /// Traverses all children recursively to find objects of the requested + /// class keyword. This object is also + /// included if it has the requested class keyword + void descendantsIncludingThisFromClassKeyword(const QString& classKeyword, + std::vector& descendants) const; + + /// Gets all children matching class keyword. Not recursive. + void childrenFromClassKeyword( + const QString& classKeyword, + std::vector& children) const; }; } // End of namespace caf From b7c4a54d9a6c97b3234da4d252e7856465bfc5da Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Mon, 15 Jul 2019 11:43:22 +0200 Subject: [PATCH 231/396] #4513 Add id to views --- .../Core/RicfFieldCapability.h | 16 ++++--- .../Core/RicfFieldHandle.cpp | 1 + .../Core/RicfFieldHandle.h | 14 +++++- .../ProjectDataModel/Rim3dView.cpp | 24 +++++++++- ApplicationCode/ProjectDataModel/Rim3dView.h | 5 ++ .../ProjectDataModel/RimProject.cpp | 48 +++++++++++++++++-- ApplicationCode/ProjectDataModel/RimProject.h | 6 ++- 7 files changed, 97 insertions(+), 17 deletions(-) diff --git a/ApplicationCode/CommandFileInterface/Core/RicfFieldCapability.h b/ApplicationCode/CommandFileInterface/Core/RicfFieldCapability.h index 921524ae69..7b4e454a8a 100644 --- a/ApplicationCode/CommandFileInterface/Core/RicfFieldCapability.h +++ b/ApplicationCode/CommandFileInterface/Core/RicfFieldCapability.h @@ -204,16 +204,18 @@ public: public: void readFieldData (QTextStream& inputStream, caf::PdmObjectFactory* objectFactory, RicfMessages* errorMessageContainer) override { - //m_field->xmlCapability()->assertValid(); - typename FieldType::FieldDataType value; - RicfFieldReader::readFieldData(value, inputStream, errorMessageContainer); - m_field->setValue(value); + typename FieldType::FieldDataType value; + RicfFieldReader::readFieldData(value, inputStream, errorMessageContainer); + + if (this->isIOWriteable()) + { + m_field->setValue(value); + } } void writeFieldData(QTextStream& outputStream) const override - { - //m_field->xmlCapability()->assertValid(); - RicfFieldWriter::writeFieldData(m_field->value(), outputStream); + { + RicfFieldWriter::writeFieldData(m_field->value(), outputStream); } private: diff --git a/ApplicationCode/CommandFileInterface/Core/RicfFieldHandle.cpp b/ApplicationCode/CommandFileInterface/Core/RicfFieldHandle.cpp index b2ba2b7ede..f743484aef 100644 --- a/ApplicationCode/CommandFileInterface/Core/RicfFieldHandle.cpp +++ b/ApplicationCode/CommandFileInterface/Core/RicfFieldHandle.cpp @@ -26,6 +26,7 @@ //-------------------------------------------------------------------------------------------------- RicfFieldHandle::RicfFieldHandle(caf::PdmFieldHandle* owner, bool giveOwnership) { + m_IOWriteable = true; m_owner = owner; owner->addCapability(this, giveOwnership); } diff --git a/ApplicationCode/CommandFileInterface/Core/RicfFieldHandle.h b/ApplicationCode/CommandFileInterface/Core/RicfFieldHandle.h index 03b9b9f565..3e48f984e5 100644 --- a/ApplicationCode/CommandFileInterface/Core/RicfFieldHandle.h +++ b/ApplicationCode/CommandFileInterface/Core/RicfFieldHandle.h @@ -37,10 +37,19 @@ class QTextStream; class RicfFieldHandle : public caf::PdmFieldCapability { public: - RicfFieldHandle(caf::PdmFieldHandle* owner , bool giveOwnership); - + RicfFieldHandle(caf::PdmFieldHandle* owner, bool giveOwnership); ~RicfFieldHandle() override; + bool isIOWriteable() const + { + return m_IOWriteable; + } + + void setIOWriteable(bool writeable) + { + m_IOWriteable = writeable; + } + virtual void readFieldData (QTextStream& inputStream, caf::PdmObjectFactory* objectFactory, RicfMessages* errorMessageContainer ) = 0; @@ -48,6 +57,7 @@ public: private: caf::PdmFieldHandle* m_owner; + bool m_IOWriteable; }; diff --git a/ApplicationCode/ProjectDataModel/Rim3dView.cpp b/ApplicationCode/ProjectDataModel/Rim3dView.cpp index 697048048c..bb99f51c81 100644 --- a/ApplicationCode/ProjectDataModel/Rim3dView.cpp +++ b/ApplicationCode/ProjectDataModel/Rim3dView.cpp @@ -118,11 +118,15 @@ Rim3dView::Rim3dView(void) CAF_PDM_InitFieldNoDefault(&surfaceMode, "SurfaceMode", "Grid Surface", "", "", ""); RICF_InitField(&m_showGridBox, "ShowGridBox", true, "Show Grid Box", "", "", ""); - + CAF_PDM_InitField(&m_disableLighting, "DisableLighting", false, "Disable Results Lighting", "", "Disable light model for scalar result colors", ""); CAF_PDM_InitField(&m_showZScaleLabel, "ShowZScale", true, "Show Z Scale Label", "", "", ""); + RICF_InitField(&m_viewId, "ViewId", -1, "View ID", "", "", ""); + m_viewId.uiCapability()->setUiReadOnly(true); + m_viewId.capability()->setIOWriteable(false); + m_crossSectionVizModel = new cvf::ModelBasicList; m_crossSectionVizModel->setName("CrossSectionModel"); @@ -180,6 +184,22 @@ QString Rim3dView::name() const return m_nameConfig->customName(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +int Rim3dView::id() const +{ + return m_viewId; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void Rim3dView::setId(int id) +{ + m_viewId = id; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -283,6 +303,8 @@ void Rim3dView::deleteViewWidget() //-------------------------------------------------------------------------------------------------- void Rim3dView::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) { + uiOrdering.add(&m_viewId); + caf::PdmUiGroup* viewGroup = uiOrdering.addNewGroupWithKeyword("Viewer", "ViewGroup"); viewGroup->add(&m_backgroundColor); diff --git a/ApplicationCode/ProjectDataModel/Rim3dView.h b/ApplicationCode/ProjectDataModel/Rim3dView.h index 584ce63f75..6d992c2074 100644 --- a/ApplicationCode/ProjectDataModel/Rim3dView.h +++ b/ApplicationCode/ProjectDataModel/Rim3dView.h @@ -105,6 +105,10 @@ public: void setName(const QString& name); QString name() const; + + int id() const; + void setId(int id); + // Implementation of RiuViewerToViewInterface cvf::Color3f backgroundColor() const override { return m_backgroundColor(); } @@ -260,4 +264,5 @@ private: caf::PdmField< cvf::Color3f > m_backgroundColor; caf::PdmField m_showGridBox; caf::PdmField m_showZScaleLabel; + caf::PdmField m_viewId; }; diff --git a/ApplicationCode/ProjectDataModel/RimProject.cpp b/ApplicationCode/ProjectDataModel/RimProject.cpp index ee92d123a2..ed4a300727 100644 --- a/ApplicationCode/ProjectDataModel/RimProject.cpp +++ b/ApplicationCode/ProjectDataModel/RimProject.cpp @@ -109,6 +109,9 @@ RimProject::RimProject(void) CAF_PDM_InitField(&nextValidCaseGroupId, "NextValidCaseGroupId", 0, "Next Valid Case Group ID", "", "" ,""); nextValidCaseGroupId.uiCapability()->setUiHidden(true); + CAF_PDM_InitField(&nextValidViewId, "NextValidViewId", 0, "Next Valid View ID", "", "", ""); + nextValidViewId.uiCapability()->setUiHidden(true); + CAF_PDM_InitFieldNoDefault(&oilFields, "OilFields", "Oil Fields", "", "", ""); oilFields.uiCapability()->setUiHidden(true); @@ -228,6 +231,7 @@ void RimProject::close() nextValidCaseId = 0; nextValidCaseGroupId = 0; + nextValidViewId = 0; mainWindowCurrentModelIndexPath = ""; mainWindowTreeViewState = ""; plotWindowCurrentModelIndexPath = ""; @@ -246,22 +250,22 @@ void RimProject::initScriptDirectories(const QString& scriptDirectories) // Find largest used caseId read from file and make sure all cases have a valid caseId { - int largestId = -1; + int largestCaseId = -1; std::vector cases; allCases(cases); for (size_t i = 0; i < cases.size(); i++) { - if (cases[i]->caseId > largestId) + if (cases[i]->caseId > largestCaseId) { - largestId = cases[i]->caseId; + largestCaseId = cases[i]->caseId; } } - if (largestId > this->nextValidCaseId) + if (largestCaseId > this->nextValidCaseId) { - this->nextValidCaseId = largestId + 1; + this->nextValidCaseId = largestCaseId + 1; } // Assign case Id to cases with an invalid case Id @@ -306,6 +310,28 @@ void RimProject::initScriptDirectories(const QString& scriptDirectories) } } } + + int maxViewId = -1; + std::vector views; + this->descendantsIncludingThisOfType(views); + for (Rim3dView* view : views) + { + maxViewId = std::max(maxViewId, view->id()); + } + + if (maxViewId >= this->nextValidViewId) + { + this->nextValidViewId = maxViewId + 1; + } + + // Assign view id to views with invalid id + for (Rim3dView* view : views) + { + if (view->id() < 0) + { + assignViewIdToView(view); + } + } } @@ -533,6 +559,18 @@ void RimProject::assignIdToCaseGroup(RimIdenticalGridCaseGroup* caseGroup) } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimProject::assignViewIdToView(Rim3dView* view) +{ + if (view) + { + view->setId(nextValidViewId); + nextValidViewId = nextValidViewId + 1; + } +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimProject.h b/ApplicationCode/ProjectDataModel/RimProject.h index 16d4c4fbb7..20761ad898 100644 --- a/ApplicationCode/ProjectDataModel/RimProject.h +++ b/ApplicationCode/ProjectDataModel/RimProject.h @@ -115,6 +115,7 @@ public: void assignCaseIdToCase(RimCase* reservoirCase); void assignIdToCaseGroup(RimIdenticalGridCaseGroup* caseGroup); + void assignViewIdToView(Rim3dView* view); void allCases(std::vector& cases) const; @@ -196,8 +197,9 @@ private: caf::PdmField m_subWindowsTiled3DWindow; caf::PdmField m_subWindowsTiledPlotWindow; - caf::PdmField nextValidCaseId; // Unique case ID within a project, used to identify a case from Octave scripts - caf::PdmField nextValidCaseGroupId; // Unique case group ID within a project, used to identify a case group from Octave scripts + caf::PdmField nextValidCaseId; // Unique case ID within a project, used to identify a case from scripts + caf::PdmField nextValidCaseGroupId; // Unique case group ID within a project, used to identify a case group from scripts + caf::PdmField nextValidViewId; // Unique view ID within a project, used to identify a view from scripts caf::PdmChildArrayField casesObsolete; // obsolete caf::PdmChildArrayField caseGroupsObsolete; // obsolete From dcd3ff67542f82caaa8e29ca5ba72f8ed8e5da0a Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Mon, 15 Jul 2019 11:43:39 +0200 Subject: [PATCH 232/396] #4423 Improve API for setting cell results --- .../GrpcInterface/CMakeLists.cmake | 1 + .../GrpcInterface/Python/rips/Case.py | 22 ++++++++++++- .../GrpcInterface/Python/rips/PdmObject.py | 2 +- .../GrpcInterface/Python/rips/Project.py | 22 +++++++++++++ .../GrpcInterface/Python/rips/View.py | 33 +++++++++++++++++++ .../GrpcInterface/Python/rips/__init__.py | 2 ++ .../Python/rips/examples/AllCases.py | 23 +++++++------ 7 files changed, 93 insertions(+), 12 deletions(-) create mode 100644 ApplicationCode/GrpcInterface/Python/rips/View.py diff --git a/ApplicationCode/GrpcInterface/CMakeLists.cmake b/ApplicationCode/GrpcInterface/CMakeLists.cmake index 93d2134210..36b446443f 100644 --- a/ApplicationCode/GrpcInterface/CMakeLists.cmake +++ b/ApplicationCode/GrpcInterface/CMakeLists.cmake @@ -160,6 +160,7 @@ if (PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) "rips/Properties.py" "rips/Instance.py" "rips/PdmObject.py" + "rips/View.py" "rips/examples/InstanceExample.py" "rips/examples/CommandExample.py" "rips/examples/CaseInfoStreamingExample.py" diff --git a/ApplicationCode/GrpcInterface/Python/rips/Case.py b/ApplicationCode/GrpcInterface/Python/rips/Case.py index 45add1157a..6f24727850 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Case.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Case.py @@ -4,6 +4,7 @@ import sys from .Grid import Grid from .Properties import Properties from .PdmObject import PdmObject +from .View import View sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'generated')) @@ -109,5 +110,24 @@ class Case (PdmObject): return self.stub.GetDaysSinceStart(self.request).day_decimals def views(self): - return self.children("ReservoirView") + """Get a list of views belonging to a case""" + pbmObjects = self.children("ReservoirView") + viewList = [] + for pbmObject in pbmObjects: + viewList.append(View(pbmObject)) + return viewList + + def view(self, id): + """Get a particular view belonging to a case by providing view id + Arguments: + id(int): view id + + Returns: a view object + + """ + views = self.views() + for viewObject in views: + if viewObject.id == id: + return viewObject + return None diff --git a/ApplicationCode/GrpcInterface/Python/rips/PdmObject.py b/ApplicationCode/GrpcInterface/Python/rips/PdmObject.py index db19cd00a8..ff1c32aeb6 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/PdmObject.py +++ b/ApplicationCode/GrpcInterface/Python/rips/PdmObject.py @@ -75,4 +75,4 @@ class PdmObject: return PdmObject(self.stub.GetAncestorPdmObject(request), self.channel) def update(self): - self.stub.UpdateExistingPdmObject(self.pb2Object) \ No newline at end of file + self.stub.UpdateExistingPdmObject(self.pb2Object) diff --git a/ApplicationCode/GrpcInterface/Python/rips/Project.py b/ApplicationCode/GrpcInterface/Python/rips/Project.py index 07207f096b..3882961564 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Project.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Project.py @@ -5,6 +5,7 @@ import sys from .Case import Case from .Commands import Commands from .PdmObject import PdmObject +from .View import View sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'generated')) @@ -92,3 +93,24 @@ class Project (PdmObject): """ return Commands(self.channel).loadCase(path) + def views(self): + """Get a list of views belonging to a project""" + pdmObjects = self.descendants("ReservoirView") + viewList = [] + for pdmObject in pdmObjects: + viewList.append(View(pdmObject)) + return viewList + + def view(self, id): + """Get a particular view belonging to a case by providing view id + Arguments: + id(int): view id + + Returns: a view object + + """ + views = self.views() + for viewObject in views: + if viewObject.id == id: + return viewObject + return None \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/Python/rips/View.py b/ApplicationCode/GrpcInterface/Python/rips/View.py new file mode 100644 index 0000000000..56096f8219 --- /dev/null +++ b/ApplicationCode/GrpcInterface/Python/rips/View.py @@ -0,0 +1,33 @@ +from .PdmObject import PdmObject + +class View (PdmObject): + """ResInsight view class + + Attributes: + id(int): View Id corresponding to the View Id in ResInsight project. + + """ + def __init__(self, pbmObject): + self.id = pbmObject.getValue("ViewId") + + PdmObject.__init__(self, pbmObject.pb2Object, pbmObject.channel) + + def showGridBox(self): + """Check if the grid box is meant to be shown in the view""" + return self.getValue("ShowGridBox") + + def setShowGridBox(self, value): + """Set if the grid box is meant to be shown in the view""" + self.setValue("ShowGridBox", value) + + def backgroundColor(self): + """Get the current background color in the view""" + return self.getValue("ViewBackgroundColor") + + def setBackgroundColor(self, bgColor): + """Set the background color in the view""" + self.setValue("ViewBackgroundColor", bgColor) + + def cellResult(self): + """Retrieve the current cell results""" + return self.children("ResultSlot")[0] \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/Python/rips/__init__.py b/ApplicationCode/GrpcInterface/Python/rips/__init__.py index 1522a01bcc..84a933e156 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/__init__.py +++ b/ApplicationCode/GrpcInterface/Python/rips/__init__.py @@ -5,4 +5,6 @@ from .Properties import Properties from .Instance import Instance from .App import App from .Commands import Commands +from .PdmObject import PdmObject +from .View import View from .Project import Project \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/AllCases.py b/ApplicationCode/GrpcInterface/Python/rips/examples/AllCases.py index 8af6f09442..e552ef6978 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/examples/AllCases.py +++ b/ApplicationCode/GrpcInterface/Python/rips/examples/AllCases.py @@ -24,20 +24,23 @@ if resInsight is not None: for keyword in resInsight.project.keywords(): print (keyword + ": " + resInsight.project.getValue(keyword)) - pdmViews = resInsight.project.descendants(classKeyword="ReservoirView") + pdmViews = resInsight.project.views() for view in pdmViews: print ("\n####View####") print(view.classKeyword(), view.address()) for viewKeyword in view.keywords(): print(viewKeyword + "-> " + str(view.getValue(viewKeyword))) - view.setValue("ShowGridBox", not view.getValue("ShowGridBox")) - view.setValue("ViewBackgroundColor", "#3388AA") + view.setShowGridBox(not view.showGridBox()) + view.setBackgroundColor("#3388AA") view.update() - print ("\n####Cell Result####") - cellResults = view.children(classKeyword="ResultSlot") - for resultKeyword in cellResults[0].keywords(): - print(resultKeyword + "->" + str(cellResults[0].getValue(resultKeyword))) - cellResults[0].setValue("ResultVariable", "SOIL") - cellResults[0].setValue("ResultType", "DYNAMIC_NATIVE") - cellResults[0].update() \ No newline at end of file + print ("\n####Cell Result####") + firstView = case.view(id=0) + assert(firstView is not None) + cellResult = firstView.cellResult() + print(cellResult.classKeyword(), cellResult.address()) + for resultKeyword in cellResult.keywords(): + print(resultKeyword + "->" + str(cellResult.getValue(resultKeyword))) + cellResult.setValue("ResultVariable", "SOIL") + cellResult.setValue("ResultType", "DYNAMIC_NATIVE") + cellResult.update() \ No newline at end of file From 3898b97c8aee0a8745feadb57d5f78fe483fbef8 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Mon, 15 Jul 2019 14:05:34 +0200 Subject: [PATCH 233/396] Fix Python tests --- .../GrpcInterface/Python/rips/PdmObject.py | 12 +++++++----- .../GrpcInterface/Python/rips/tests/test_cases.py | 14 ++++++-------- ApplicationCode/ProjectDataModel/RimCase.cpp | 3 ++- .../ProjectDataModel/RimEclipseResultCase.cpp | 5 ++++- 4 files changed, 19 insertions(+), 15 deletions(-) diff --git a/ApplicationCode/GrpcInterface/Python/rips/PdmObject.py b/ApplicationCode/GrpcInterface/Python/rips/PdmObject.py index ff1c32aeb6..56a52f0f3a 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/PdmObject.py +++ b/ApplicationCode/GrpcInterface/Python/rips/PdmObject.py @@ -12,7 +12,7 @@ class PdmObject: def __init__(self, pb2Object, channel): self.pb2Object = pb2Object self.channel = channel - self.stub = PdmObject_pb2_grpc.PdmObjectServiceStub(self.channel) + self.pdmObjectStub = PdmObject_pb2_grpc.PdmObjectServiceStub(self.channel) def address(self): return self.pb2Object.address @@ -41,6 +41,8 @@ class PdmObject: floatVal = float(value) return floatVal except ValueError: + # We may have a string. Strip internal start and end quotes + value = value.strip('\"') return value def setValue(self, keyword, value): @@ -56,7 +58,7 @@ class PdmObject: def descendants(self, classKeyword): request = PdmObject_pb2.PdmChildObjectRequest(object=self.pb2Object, child_keyword=classKeyword) - objectList = self.stub.GetDescendantPdmObjects(request).objects + objectList = self.pdmObjectStub.GetDescendantPdmObjects(request).objects childList = [] for object in objectList: childList.append(PdmObject(object, self.channel)) @@ -64,7 +66,7 @@ class PdmObject: def children(self, classKeyword): request = PdmObject_pb2.PdmChildObjectRequest(object=self.pb2Object, child_keyword=classKeyword) - objectList = self.stub.GetChildPdmObjects(request).objects + objectList = self.pdmObjectStub.GetChildPdmObjects(request).objects childList = [] for object in objectList: childList.append(PdmObject(object, self.channel)) @@ -72,7 +74,7 @@ class PdmObject: def ancestor(self, classKeyword): request = PdmObject_pb2.PdmParentObjectRequest(object=self.pb2Object, parent_keyword=classKeyword) - return PdmObject(self.stub.GetAncestorPdmObject(request), self.channel) + return PdmObject(self.pdmObjectStub.GetAncestorPdmObject(request), self.channel) def update(self): - self.stub.UpdateExistingPdmObject(self.pb2Object) + self.pdmObjectStub.UpdateExistingPdmObject(self.pb2Object) diff --git a/ApplicationCode/GrpcInterface/Python/rips/tests/test_cases.py b/ApplicationCode/GrpcInterface/Python/rips/tests/test_cases.py index f2487c81fd..32285add17 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/tests/test_cases.py +++ b/ApplicationCode/GrpcInterface/Python/rips/tests/test_cases.py @@ -53,14 +53,12 @@ def test_10k(rips_instance, initializeTest): def test_PdmObject(rips_instance, initializeTest): casePath = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID" case = rips_instance.project.loadCase(path=casePath) - pdmObject = case.pdmObject() - assert(pdmObject.address is not 0) - assert(pdmObject.class_keyword == "EclipseCase") - assert(pdmObject.parameters['CaseFileName'] == casePath) - assert(int(pdmObject.parameters['CaseId']) == 0) - for keyword in pdmObject.parameters: - - print (keyword + ": " + pdmObject.parameters[keyword]) + assert(case.id == 0) + assert(case.address() is not 0) + assert(case.classKeyword() == "EclipseCase") + assert(case.getValue('CaseFileName') == casePath) + caseId = case.getValue('CaseId') + assert(caseId == case.id) @pytest.mark.skipif(sys.platform.startswith('linux'), reason="Brugge is currently exceptionally slow on Linux") def test_brugge_0010(rips_instance, initializeTest): diff --git a/ApplicationCode/ProjectDataModel/RimCase.cpp b/ApplicationCode/ProjectDataModel/RimCase.cpp index 88e74d5c2e..856e766422 100644 --- a/ApplicationCode/ProjectDataModel/RimCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimCase.cpp @@ -46,8 +46,9 @@ RimCase::RimCase() : m_isInActiveDestruction(false) { RICF_InitField(&caseUserDescription, "CaseUserDescription", QString(), "Case Name", "", "" ,""); - CAF_PDM_InitField(&caseId, "CaseId", -1, "Case ID", "", "" ,""); + RICF_InitField(&caseId, "CaseId", -1, "Case ID", "", "" ,""); caseId.uiCapability()->setUiReadOnly(true); + caseId.capability()->setIOWriteable(false); CAF_PDM_InitFieldNoDefault(&activeFormationNames, "DefaultFormationNames", "Formation Names File", "", "", ""); diff --git a/ApplicationCode/ProjectDataModel/RimEclipseResultCase.cpp b/ApplicationCode/ProjectDataModel/RimEclipseResultCase.cpp index ef1a72c049..f89028a499 100644 --- a/ApplicationCode/ProjectDataModel/RimEclipseResultCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimEclipseResultCase.cpp @@ -26,6 +26,8 @@ #include "RiaPreferences.h" #include "RiaRegressionTestRunner.h" +#include "RicfCommandObject.h" + #include "RifEclipseOutputFileTools.h" #include "RifReaderEclipseOutput.h" #include "RifReaderEclipseRft.h" @@ -70,8 +72,9 @@ RimEclipseResultCase::RimEclipseResultCase() { CAF_PDM_InitObject("Eclipse Case", ":/Case48x48.png", "", ""); - CAF_PDM_InitField(&caseFileName, "CaseFileName", QString(), "Case File Name", "", "" ,""); + RICF_InitField(&caseFileName, "CaseFileName", QString(), "Case File Name", "", "" ,""); caseFileName.uiCapability()->setUiReadOnly(true); + caseFileName.capability()->setIOWriteable(false); CAF_PDM_InitFieldNoDefault(&m_unitSystem, "UnitSystem", "Unit System", "", "", ""); m_unitSystem.registerGetMethod(RiaApplication::instance()->project(), &RimProject::commonUnitSystemForAllCases); From 7a77b5688a1d0517af1d063a66583db1f7ee43dc Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Mon, 15 Jul 2019 14:09:27 +0200 Subject: [PATCH 234/396] Fix build problem on Qt 4.6.x --- .../CommandFileInterface/Core/RicfFieldCapability.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ApplicationCode/CommandFileInterface/Core/RicfFieldCapability.cpp b/ApplicationCode/CommandFileInterface/Core/RicfFieldCapability.cpp index 0c53a5823e..0b503b6496 100644 --- a/ApplicationCode/CommandFileInterface/Core/RicfFieldCapability.cpp +++ b/ApplicationCode/CommandFileInterface/Core/RicfFieldCapability.cpp @@ -141,9 +141,9 @@ void RicfFieldReader::readFieldData(cvf::Color3f& fieldValue, QTex QString fieldStringValue; RicfFieldReader::readFieldData(fieldStringValue, inputStream, errorMessageContainer); - if (QColor::isValidColor(fieldStringValue)) + QColor qColor(fieldStringValue); + if (qColor.isValid()) { - QColor qColor(fieldStringValue); fieldValue = RiaColorTools::fromQColorTo3f(qColor); } } From f2c72a0e71a239118c544403a914f83b486313b3 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Mon, 15 Jul 2019 15:50:55 +0200 Subject: [PATCH 235/396] #4484 Added test for replaceCase that fails --- .../Python/rips/tests/test_cases.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/ApplicationCode/GrpcInterface/Python/rips/tests/test_cases.py b/ApplicationCode/GrpcInterface/Python/rips/tests/test_cases.py index 32285add17..03eb0a7227 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/tests/test_cases.py +++ b/ApplicationCode/GrpcInterface/Python/rips/tests/test_cases.py @@ -72,3 +72,21 @@ def test_brugge_0010(rips_instance, initializeTest): assert(len(timeSteps) == 11) daysSinceStart = case.daysSinceStart() assert(len(daysSinceStart) == 11) + +@pytest.mark.skipif(sys.platform.startswith('linux'), reason="Brugge is currently exceptionally slow on Linux") +def test_replaceCase(rips_instance, initializeTest): + project = rips_instance.project.open(dataroot.PATH + "/TEST10K_FLT_LGR_NNC/10KWithWellLog.rsp") + casePath = dataroot.PATH + "/Case_with_10_timesteps/Real10/BRUGGE_0010.EGRID" + case = project.case(id=0) + assert(case is not None) + assert(case.name == "TEST10K_FLT_LGR_NNC") + assert(case.id == 0) + cases = rips_instance.project.cases() + assert(len(cases) is 1) + + rips_instance.commands.replaceCase(newGridFile=casePath, caseId=case.id) + cases = rips_instance.project.cases() + assert(len(cases) is 1) + case = project.case(id=0) + assert(case.name == "BRUGGE_0000") + assert(case.id == 0) \ No newline at end of file From bbc8750d8f13e7c6924d94d46e56093f56c2947d Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Tue, 16 Jul 2019 17:12:08 +0200 Subject: [PATCH 236/396] #4516 Fix replaceCase in Python gRPC --- .../CommandFileInterface/RicfReplaceCase.cpp | 36 +++++++++++++---- .../CommandFileInterface/RicfReplaceCase.h | 2 +- .../GrpcInterface/GrpcProtos/Commands.proto | 6 +++ .../Python/rips/tests/test_cases.py | 6 +-- .../GrpcInterface/RiaGrpcCommandService.cpp | 40 ++++++++++++++----- 5 files changed, 68 insertions(+), 22 deletions(-) diff --git a/ApplicationCode/CommandFileInterface/RicfReplaceCase.cpp b/ApplicationCode/CommandFileInterface/RicfReplaceCase.cpp index dd9c2f6502..04d95d6e8b 100644 --- a/ApplicationCode/CommandFileInterface/RicfReplaceCase.cpp +++ b/ApplicationCode/CommandFileInterface/RicfReplaceCase.cpp @@ -58,15 +58,37 @@ QString RicfSingleCaseReplace::filePath() const //-------------------------------------------------------------------------------------------------- RicfCommandResponse RicfSingleCaseReplace::execute() { - // Never call execute on this object, information is aggregated into RicfMultiCaseReplace - CAF_ASSERT(false); - return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, "Never call execute on a RicfSingleCaseReplace object"); + QString lastProjectPath = RicfCommandFileExecutor::instance()->getLastProjectPath(); + if (lastProjectPath.isNull()) + { + QString errMsg( + "replaceCase: 'openProject' must be called before 'replaceCase' to specify project file to replace case in."); + RiaLogging::error(errMsg); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, errMsg); + } + + cvf::ref projectModifier = new RiaProjectModifier; + + if (m_caseId() < 0) + { + projectModifier->setReplaceCaseFirstOccurrence(m_newGridFile()); + } + else + { + projectModifier->setReplaceCase(m_caseId(), m_newGridFile()); + } + + if (!RiaApplication::instance()->loadProject(lastProjectPath, RiaApplication::PLA_NONE, projectModifier.p())) + { + QString errMsg("Could not reload project"); + RiaLogging::error(errMsg); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, errMsg); + } + + return RicfCommandResponse(); } - - - -CAF_PDM_SOURCE_INIT(RicfMultiCaseReplace, "replaceCaseImpl_no_support_for_command_file_text_parsing"); +CAF_PDM_SOURCE_INIT(RicfMultiCaseReplace, "replaceMultipleCases"); //-------------------------------------------------------------------------------------------------- /// diff --git a/ApplicationCode/CommandFileInterface/RicfReplaceCase.h b/ApplicationCode/CommandFileInterface/RicfReplaceCase.h index 6d579b13b2..04d31ef08c 100644 --- a/ApplicationCode/CommandFileInterface/RicfReplaceCase.h +++ b/ApplicationCode/CommandFileInterface/RicfReplaceCase.h @@ -51,7 +51,7 @@ private: // RicfMultipleReplaceCase represents multiple caseId-gridFileName pairs // // NB! This object has no support for parsing a text command. This object is created by aggregating -// multiple RicfSingleCaseReplace objects +// multiple RicfSingleCaseReplace objects, or through gRPC interface. // //================================================================================================== class RicfMultiCaseReplace : public RicfCommandObject diff --git a/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto b/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto index b44f72918d..f682b66f3a 100644 --- a/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto +++ b/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto @@ -25,6 +25,11 @@ message ReplaceCaseRequest int32 caseId = 2; } +message ReplaceCaseRequests +{ + repeated ReplaceCaseRequest casePairs = 1; +} + message ReplaceSourceCasesRequest { string gridListFile = 1; @@ -264,6 +269,7 @@ message CommandParams CreateMultipleFracRequest createMultipleFractures = 23; CreateLgrForCompRequest createLgrForCompletions = 24; CreateSatPressPlotRequest createSaturationPressurePlots = 25; + ReplaceCaseRequests replaceMultipleCases = 26; } } diff --git a/ApplicationCode/GrpcInterface/Python/rips/tests/test_cases.py b/ApplicationCode/GrpcInterface/Python/rips/tests/test_cases.py index 03eb0a7227..e3c9126052 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/tests/test_cases.py +++ b/ApplicationCode/GrpcInterface/Python/rips/tests/test_cases.py @@ -76,7 +76,7 @@ def test_brugge_0010(rips_instance, initializeTest): @pytest.mark.skipif(sys.platform.startswith('linux'), reason="Brugge is currently exceptionally slow on Linux") def test_replaceCase(rips_instance, initializeTest): project = rips_instance.project.open(dataroot.PATH + "/TEST10K_FLT_LGR_NNC/10KWithWellLog.rsp") - casePath = dataroot.PATH + "/Case_with_10_timesteps/Real10/BRUGGE_0010.EGRID" + casePath = dataroot.PATH + "/Case_with_10_timesteps/Real0/BRUGGE_0000.EGRID" case = project.case(id=0) assert(case is not None) assert(case.name == "TEST10K_FLT_LGR_NNC") @@ -84,9 +84,9 @@ def test_replaceCase(rips_instance, initializeTest): cases = rips_instance.project.cases() assert(len(cases) is 1) - rips_instance.commands.replaceCase(newGridFile=casePath, caseId=case.id) + rips_instance.commands.replaceCase(newGridFile=os.path.abspath(casePath), caseId=case.id) cases = rips_instance.project.cases() assert(len(cases) is 1) case = project.case(id=0) - assert(case.name == "BRUGGE_0000") + assert(case.name == "Real0--BRUGGE_0000.EGRID") assert(case.id == 0) \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/RiaGrpcCommandService.cpp b/ApplicationCode/GrpcInterface/RiaGrpcCommandService.cpp index 3570a13e59..e88ad84283 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcCommandService.cpp +++ b/ApplicationCode/GrpcInterface/RiaGrpcCommandService.cpp @@ -19,6 +19,7 @@ #include "RiaGrpcCallbacks.h" +#include "RicfReplaceCase.h" #include "RicfSetTimeStep.h" #include "cafAssert.h" @@ -52,22 +53,39 @@ grpc::Status RiaGrpcCommandService::Execute(grpc::ServerContext* context, const const Message& params = request->GetReflection()->GetMessage(*request, grpcOneOfMessage); QString grpcOneOfMessageName = QString::fromStdString(grpcOneOfMessage->name()); - auto pdmObjectHandle = caf::PdmDefaultObjectFactory::instance()->create(grpcOneOfMessageName); - auto commandHandle = dynamic_cast(pdmObjectHandle); + auto pdmObjectHandle = caf::PdmDefaultObjectFactory::instance()->create(grpcOneOfMessageName); + auto commandHandle = dynamic_cast(pdmObjectHandle); + if (commandHandle) { - auto subMessageDescriptor = grpcOneOfMessage->message_type(); - int numParameters = subMessageDescriptor->field_count(); - for (int i = 0; i < numParameters; ++i) + RicfMultiCaseReplace* multiCaseReplaceCommand = dynamic_cast(commandHandle); + if (multiCaseReplaceCommand) { - auto parameter = subMessageDescriptor->field(i); - if (parameter) + CAF_ASSERT(request->has_replacemultiplecases()); + auto replaceMultipleCasesRequest = request->replacemultiplecases(); + std::map caseIdFileMap; + for (auto caseGridFilePair : replaceMultipleCasesRequest.casepairs()) { - QString parameterName = QString::fromStdString(parameter->name()); - auto pdmValueFieldHandle = dynamic_cast(pdmObjectHandle->findField(parameterName)); - if (pdmValueFieldHandle) + caseIdFileMap.insert(std::make_pair(caseGridFilePair.caseid(), + QString::fromStdString(caseGridFilePair.newgridfile()))); + } + multiCaseReplaceCommand->setCaseReplacePairs(caseIdFileMap); + } + else + { + auto subMessageDescriptor = grpcOneOfMessage->message_type(); + int numParameters = subMessageDescriptor->field_count(); + for (int i = 0; i < numParameters; ++i) + { + auto parameter = subMessageDescriptor->field(i); + if (parameter) { - assignPdmFieldValue(pdmValueFieldHandle, params, parameter); + QString parameterName = QString::fromStdString(parameter->name()); + auto pdmValueFieldHandle = dynamic_cast(pdmObjectHandle->findField(parameterName)); + if (pdmValueFieldHandle) + { + assignPdmFieldValue(pdmValueFieldHandle, params, parameter); + } } } } From 7a2b9926a044a2c6f8e7cca3bc281ccb794ff689 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Thu, 18 Jul 2019 08:50:58 +0200 Subject: [PATCH 237/396] Allow relative paths in replace case --- .../CommandFileInterface/RicfReplaceCase.cpp | 24 ++++++++++++++++--- .../Python/rips/tests/test_cases.py | 3 +-- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/ApplicationCode/CommandFileInterface/RicfReplaceCase.cpp b/ApplicationCode/CommandFileInterface/RicfReplaceCase.cpp index 04d95d6e8b..170aaaa656 100644 --- a/ApplicationCode/CommandFileInterface/RicfReplaceCase.cpp +++ b/ApplicationCode/CommandFileInterface/RicfReplaceCase.cpp @@ -26,6 +26,9 @@ #include "RimProject.h" +#include +#include + CAF_PDM_SOURCE_INIT(RicfSingleCaseReplace, "replaceCase"); //-------------------------------------------------------------------------------------------------- @@ -69,13 +72,21 @@ RicfCommandResponse RicfSingleCaseReplace::execute() cvf::ref projectModifier = new RiaProjectModifier; + QString filePath = m_newGridFile(); + QFileInfo casePathInfo(filePath); + if (!casePathInfo.exists()) + { + QDir startDir(RiaApplication::instance()->startDir()); + filePath = startDir.absoluteFilePath(m_newGridFile()); + } + if (m_caseId() < 0) { projectModifier->setReplaceCaseFirstOccurrence(m_newGridFile()); } else { - projectModifier->setReplaceCase(m_caseId(), m_newGridFile()); + projectModifier->setReplaceCase(m_caseId(), ); } if (!RiaApplication::instance()->loadProject(lastProjectPath, RiaApplication::PLA_NONE, projectModifier.p())) @@ -128,8 +139,15 @@ RicfCommandResponse RicfMultiCaseReplace::execute() cvf::ref projectModifier = new RiaProjectModifier; for (const auto& a : m_caseIdToGridFileNameMap) { - const auto caseId = a.first; - const auto filePath = a.second; + const int caseId = a.first; + QString filePath = a.second; + QFileInfo casePathInfo(filePath); + if (!casePathInfo.exists()) + { + QDir startDir(RiaApplication::instance()->startDir()); + filePath = startDir.absoluteFilePath(filePath); + } + if (caseId < 0) { projectModifier->setReplaceCaseFirstOccurrence(filePath); diff --git a/ApplicationCode/GrpcInterface/Python/rips/tests/test_cases.py b/ApplicationCode/GrpcInterface/Python/rips/tests/test_cases.py index e3c9126052..0fa827ce95 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/tests/test_cases.py +++ b/ApplicationCode/GrpcInterface/Python/rips/tests/test_cases.py @@ -56,7 +56,6 @@ def test_PdmObject(rips_instance, initializeTest): assert(case.id == 0) assert(case.address() is not 0) assert(case.classKeyword() == "EclipseCase") - assert(case.getValue('CaseFileName') == casePath) caseId = case.getValue('CaseId') assert(caseId == case.id) @@ -84,7 +83,7 @@ def test_replaceCase(rips_instance, initializeTest): cases = rips_instance.project.cases() assert(len(cases) is 1) - rips_instance.commands.replaceCase(newGridFile=os.path.abspath(casePath), caseId=case.id) + rips_instance.commands.replaceCase(newGridFile=casePath, caseId=case.id) cases = rips_instance.project.cases() assert(len(cases) is 1) case = project.case(id=0) From 6b7a9b8da5f0e26072e0156139bb4b2f530ae0fd Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Thu, 18 Jul 2019 10:53:59 +0200 Subject: [PATCH 238/396] #4463 Working creation of grid case groups --- .../Tools/RiaImportEclipseCaseTools.cpp | 10 ++- .../Tools/RiaImportEclipseCaseTools.h | 4 +- .../CMakeLists_files.cmake | 2 + .../RicfCreateGridCaseGroup.cpp | 79 +++++++++++++++++++ .../RicfCreateGridCaseGroup.h | 53 +++++++++++++ .../CommandFileInterface/RicfLoadCase.cpp | 11 +-- .../CommandFileInterface/RicfLoadCase.h | 3 +- .../CommandFileInterface/RicfReplaceCase.cpp | 4 +- .../GrpcInterface/GrpcProtos/Commands.proto | 17 +++- .../GrpcInterface/Python/rips/Commands.py | 22 +++++- .../Python/rips/examples/CaseGridGroup.py | 14 ++++ .../Python/rips/tests/test_cases.py | 2 +- .../Python/rips/tests/test_commands.py | 10 ++- .../GrpcInterface/RiaGrpcCommandService.cpp | 18 ++++- 14 files changed, 228 insertions(+), 21 deletions(-) create mode 100644 ApplicationCode/CommandFileInterface/RicfCreateGridCaseGroup.cpp create mode 100644 ApplicationCode/CommandFileInterface/RicfCreateGridCaseGroup.h create mode 100644 ApplicationCode/GrpcInterface/Python/rips/examples/CaseGridGroup.py diff --git a/ApplicationCode/Application/Tools/RiaImportEclipseCaseTools.cpp b/ApplicationCode/Application/Tools/RiaImportEclipseCaseTools.cpp index f9b273d652..4d184bc5f4 100644 --- a/ApplicationCode/Application/Tools/RiaImportEclipseCaseTools.cpp +++ b/ApplicationCode/Application/Tools/RiaImportEclipseCaseTools.cpp @@ -24,6 +24,7 @@ #include "SummaryPlotCommands/RicNewSummaryCurveFeature.h" #include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RiaLogging.h" #include "RiaPreferences.h" @@ -325,7 +326,7 @@ int RiaImportEclipseCaseTools::openEclipseCaseShowTimeStepFilterImpl(const QStri //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool RiaImportEclipseCaseTools::addEclipseCases(const QStringList& fileNames) +bool RiaImportEclipseCaseTools::addEclipseCases(const QStringList& fileNames, RimIdenticalGridCaseGroup** resultingCaseGroup/*=nullptr*/) { if (fileNames.size() == 0) return true; @@ -407,11 +408,16 @@ bool RiaImportEclipseCaseTools::addEclipseCases(const QStringList& fileNames) { // Create placeholder results and propagate results info from main case to all other cases gridCaseGroup->loadMainCaseAndActiveCellInfo(); + + if (resultingCaseGroup) + { + *resultingCaseGroup = gridCaseGroup; + } } project->activeOilField()->analysisModels()->updateConnectedEditors(); - if (gridCaseGroup->statisticsCaseCollection()->reservoirs.size() > 0) + if (RiaGuiApplication::isRunning() && gridCaseGroup && gridCaseGroup->statisticsCaseCollection()->reservoirs.size() > 0) { RiuMainWindow::instance()->selectAsCurrentItem(gridCaseGroup->statisticsCaseCollection()->reservoirs[0]); } diff --git a/ApplicationCode/Application/Tools/RiaImportEclipseCaseTools.h b/ApplicationCode/Application/Tools/RiaImportEclipseCaseTools.h index e46620e3db..ca35c2d9d2 100644 --- a/ApplicationCode/Application/Tools/RiaImportEclipseCaseTools.h +++ b/ApplicationCode/Application/Tools/RiaImportEclipseCaseTools.h @@ -23,6 +23,8 @@ class QString; class QStringList; +class RimIdenticalGridCaseGroup; + //================================================================================================== /// //================================================================================================== @@ -37,7 +39,7 @@ public: static bool openEclipseInputCaseFromFileNames(const QStringList& fileNames, QString* fileContainingGrid = nullptr); static bool openMockModel(const QString& name); - static bool addEclipseCases(const QStringList& fileNames); + static bool addEclipseCases(const QStringList& fileNames, RimIdenticalGridCaseGroup** resultingCaseGroup = nullptr); private: static int openEclipseCaseFromFile(const QString& fileName); diff --git a/ApplicationCode/CommandFileInterface/CMakeLists_files.cmake b/ApplicationCode/CommandFileInterface/CMakeLists_files.cmake index 8fd95c86d6..7c1d653360 100644 --- a/ApplicationCode/CommandFileInterface/CMakeLists_files.cmake +++ b/ApplicationCode/CommandFileInterface/CMakeLists_files.cmake @@ -29,6 +29,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RicfCreateLgrForCompletions.h ${CMAKE_CURRENT_LIST_DIR}/RicfApplicationTools.h ${CMAKE_CURRENT_LIST_DIR}/RicfCreateSaturationPressurePlots.h ${CMAKE_CURRENT_LIST_DIR}/RicfExportFlowCharacteristics.h +${CMAKE_CURRENT_LIST_DIR}/RicfCreateGridCaseGroup.h ) set (SOURCE_GROUP_SOURCE_FILES @@ -61,6 +62,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RicfCreateLgrForCompletions.cpp ${CMAKE_CURRENT_LIST_DIR}/RicfApplicationTools.cpp ${CMAKE_CURRENT_LIST_DIR}/RicfCreateSaturationPressurePlots.cpp ${CMAKE_CURRENT_LIST_DIR}/RicfExportFlowCharacteristics.cpp +${CMAKE_CURRENT_LIST_DIR}/RicfCreateGridCaseGroup.cpp ) list(APPEND CODE_HEADER_FILES diff --git a/ApplicationCode/CommandFileInterface/RicfCreateGridCaseGroup.cpp b/ApplicationCode/CommandFileInterface/RicfCreateGridCaseGroup.cpp new file mode 100644 index 0000000000..406bf8bbed --- /dev/null +++ b/ApplicationCode/CommandFileInterface/RicfCreateGridCaseGroup.cpp @@ -0,0 +1,79 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- Statoil ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RicfCreateGridCaseGroup.h" + +#include "RiaApplication.h" +#include "RiaImportEclipseCaseTools.h" + +#include "RimIdenticalGridCaseGroup.h" + +#include +#include +#include + +CAF_PDM_SOURCE_INIT(RicfCreateGridCaseGroupResult, "createGridCaseGroupResult"); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RicfCreateGridCaseGroupResult::RicfCreateGridCaseGroupResult(int caseGroupId /*= -1*/, const QString& caseGroupName /*= ""*/) +{ + CAF_PDM_InitObject("case_group_result", "", "", ""); + CAF_PDM_InitField(&this->caseGroupId, "groupId", caseGroupId, "", "", "", ""); + CAF_PDM_InitField(&this->caseGroupName, "groupName", caseGroupName, "", "", "", ""); +} + +CAF_PDM_SOURCE_INIT(RicfCreateGridCaseGroup, "createGridCaseGroup"); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RicfCreateGridCaseGroup::RicfCreateGridCaseGroup() +{ + RICF_InitFieldNoDefault(&m_casePaths, "casePaths", "List of Paths to Case Files", "", "", ""); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RicfCommandResponse RicfCreateGridCaseGroup::execute() +{ + QStringList casePaths; + for (QString casePath : m_casePaths()) + { + QFileInfo casePathInfo(casePath); + if (!casePathInfo.exists()) + { + QDir startDir(RiaApplication::instance()->startDir()); + casePath = startDir.absoluteFilePath(casePath); + } + casePaths.push_back(casePath); + } + + RimIdenticalGridCaseGroup* caseGroup = nullptr; + + if (RiaImportEclipseCaseTools::addEclipseCases(casePaths, &caseGroup) && caseGroup) + { + RicfCommandResponse response; + response.setResult(new RicfCreateGridCaseGroupResult(caseGroup->groupId(), caseGroup->name())); + return response; + } + + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, "Could not load grid case group"); +} diff --git a/ApplicationCode/CommandFileInterface/RicfCreateGridCaseGroup.h b/ApplicationCode/CommandFileInterface/RicfCreateGridCaseGroup.h new file mode 100644 index 0000000000..1e050161df --- /dev/null +++ b/ApplicationCode/CommandFileInterface/RicfCreateGridCaseGroup.h @@ -0,0 +1,53 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 "RicfCommandObject.h" + +#include "cafPdmField.h" + +class RicfCreateGridCaseGroupResult : public caf::PdmObject +{ + CAF_PDM_HEADER_INIT; + +public: + RicfCreateGridCaseGroupResult(int caseGroupId = -1, const QString& caseGroupName = ""); + +public: + caf::PdmField caseGroupId; + caf::PdmField caseGroupName; +}; + +//================================================================================================== +// +// +// +//================================================================================================== +class RicfCreateGridCaseGroup : public RicfCommandObject +{ + CAF_PDM_HEADER_INIT; + +public: + RicfCreateGridCaseGroup(); + + RicfCommandResponse execute() override; + +private: + caf::PdmField> m_casePaths; +}; diff --git a/ApplicationCode/CommandFileInterface/RicfLoadCase.cpp b/ApplicationCode/CommandFileInterface/RicfLoadCase.cpp index 5c1513c5ff..a0ca993e00 100644 --- a/ApplicationCode/CommandFileInterface/RicfLoadCase.cpp +++ b/ApplicationCode/CommandFileInterface/RicfLoadCase.cpp @@ -1,17 +1,18 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2017 Statoil ASA -// +// Copyright (C) 2017-2019 Statoil ASA +// Copyright (C) 2019- 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 +// +// See the GNU General Public License at // for more details. // ///////////////////////////////////////////////////////////////////////////////// diff --git a/ApplicationCode/CommandFileInterface/RicfLoadCase.h b/ApplicationCode/CommandFileInterface/RicfLoadCase.h index 4e5ab85852..b8b1e1f558 100644 --- a/ApplicationCode/CommandFileInterface/RicfLoadCase.h +++ b/ApplicationCode/CommandFileInterface/RicfLoadCase.h @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2017 Statoil ASA +// Copyright (C) 2017-2019 Statoil ASA +// Copyright (C) 2019- 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 diff --git a/ApplicationCode/CommandFileInterface/RicfReplaceCase.cpp b/ApplicationCode/CommandFileInterface/RicfReplaceCase.cpp index 170aaaa656..d06ef5ff43 100644 --- a/ApplicationCode/CommandFileInterface/RicfReplaceCase.cpp +++ b/ApplicationCode/CommandFileInterface/RicfReplaceCase.cpp @@ -82,11 +82,11 @@ RicfCommandResponse RicfSingleCaseReplace::execute() if (m_caseId() < 0) { - projectModifier->setReplaceCaseFirstOccurrence(m_newGridFile()); + projectModifier->setReplaceCaseFirstOccurrence(filePath); } else { - projectModifier->setReplaceCase(m_caseId(), ); + projectModifier->setReplaceCase(m_caseId(), filePath); } if (!RiaApplication::instance()->loadProject(lastProjectPath, RiaApplication::PLA_NONE, projectModifier.p())) diff --git a/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto b/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto index f682b66f3a..e3794b8e18 100644 --- a/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto +++ b/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto @@ -233,6 +233,11 @@ message CreateSatPressPlotRequest repeated int32 caseIds = 1; } +message CreateGridCaseGroupRequest +{ + repeated string casePaths = 1; +} + /* CommandParams handles both command name and parameters in one. * The message type and content is used as parameters and * the name of the variable is used to find the command name. */ @@ -270,17 +275,25 @@ message CommandParams CreateLgrForCompRequest createLgrForCompletions = 24; CreateSatPressPlotRequest createSaturationPressurePlots = 25; ReplaceCaseRequests replaceMultipleCases = 26; + CreateGridCaseGroupRequest createGridCaseGroup = 27; } } +message GridCaseGroupResult +{ + int32 groupId = 1; + string groupName = 2; +} + /* Command reply handles the return values for the generic command * The name of the variable is used to map to the cafPdmObject classKeyword */ message CommandReply { oneof result { - Empty emptyResult = 1; - CaseRequest loadCaseResult = 2; + Empty emptyResult = 1; + CaseRequest loadCaseResult = 2; + GridCaseGroupResult createGridCaseGroupResult = 3; } } diff --git a/ApplicationCode/GrpcInterface/Python/rips/Commands.py b/ApplicationCode/GrpcInterface/Python/rips/Commands.py index 87517aa3a5..26a8a337de 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Commands.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Commands.py @@ -71,7 +71,8 @@ class Commands: """ commandReply = self.__execute(loadCase=Cmd.FilePathRequest(path=path)) - assert commandReply.HasField("loadCaseResult") + assert(commandReply is not None) + assert(commandReply.HasField("loadCaseResult")) return Case(self.channel, commandReply.loadCaseResult.id) def replaceCase(self, newGridFile, caseId=0): @@ -83,7 +84,7 @@ class Commands: """ return self.__execute(replaceCase=Cmd.ReplaceCaseRequest(newGridFile=newGridFile, - caseId=caseId)) + caseId=caseId)) def replaceSourceCases(self, gridListFile, caseGroupId=0): """Replace all source cases within a case group @@ -94,7 +95,22 @@ class Commands: """ return self.__execute(replaceSourceCases=Cmd.ReplaceSourceCasesRequest(gridListFile=gridListFile, - caseGroupId=caseGroupId)) + caseGroupId=caseGroupId)) + + def createGridCaseGroup(self, casePaths): + """Create a Grid Case Group from a list of cases + + Arguments: + casePaths (list): list of file path strings + + Returns: + A case group id and name + """ + commandReply = self.__execute(createGridCaseGroup=Cmd.CreateGridCaseGroupRequest(casePaths=casePaths)) + assert(commandReply is not None) + assert(commandReply.HasField("createGridCaseGroupResult")) + return (commandReply.createGridCaseGroupResult.groupId, commandReply.createGridCaseGroupResult.groupName) + ################## # Export Commands ################## diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/CaseGridGroup.py b/ApplicationCode/GrpcInterface/Python/rips/examples/CaseGridGroup.py new file mode 100644 index 0000000000..5d080fbde8 --- /dev/null +++ b/ApplicationCode/GrpcInterface/Python/rips/examples/CaseGridGroup.py @@ -0,0 +1,14 @@ +import sys +import os + +sys.path.insert(1, os.path.join(sys.path[0], '../../')) +import rips + +resInsight = rips.Instance.find() + +casePaths = [] +casePaths.append("../../../../TestModels/Case_with_10_timesteps/Real0/BRUGGE_0000.EGRID") +casePaths.append("../../../../TestModels/Case_with_10_timesteps/Real10/BRUGGE_0010.EGRID") +groupId, groupName = resInsight.commands.createGridCaseGroup(casePaths=casePaths) +print("Group id = " + str(groupId)) +print("Group name = " + groupName) \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/Python/rips/tests/test_cases.py b/ApplicationCode/GrpcInterface/Python/rips/tests/test_cases.py index 0fa827ce95..76e198ce05 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/tests/test_cases.py +++ b/ApplicationCode/GrpcInterface/Python/rips/tests/test_cases.py @@ -88,4 +88,4 @@ def test_replaceCase(rips_instance, initializeTest): assert(len(cases) is 1) case = project.case(id=0) assert(case.name == "Real0--BRUGGE_0000.EGRID") - assert(case.id == 0) \ No newline at end of file + assert(case.id == 0) diff --git a/ApplicationCode/GrpcInterface/Python/rips/tests/test_commands.py b/ApplicationCode/GrpcInterface/Python/rips/tests/test_commands.py index 906a2902e2..4ee0611871 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/tests/test_commands.py +++ b/ApplicationCode/GrpcInterface/Python/rips/tests/test_commands.py @@ -33,4 +33,12 @@ def test_exportPropertyInView(rips_instance, initializeTest): rips_instance.commands.exportPropertyInViews(0, "3D View", 0) expectedFileName = case.name + "-" + str("3D_View") + "-" + "T0" + "-SOIL" fullPath = tmpdirname + "/" + expectedFileName - assert(os.path.exists(fullPath)) \ No newline at end of file + assert(os.path.exists(fullPath)) + +@pytest.mark.skipif(sys.platform.startswith('linux'), reason="Brugge is currently exceptionally slow on Linux") +def test_loadGridCaseGroup(rips_instance, initializeTest): + casePaths = [] + casePaths.append(dataroot.PATH + "/Case_with_10_timesteps/Real0/BRUGGE_0000.EGRID") + casePaths.append(dataroot.PATH + "/Case_with_10_timesteps/Real10/BRUGGE_0010.EGRID") + groupId, groupName = rips_instance.commands.createGridCaseGroup(casePaths=casePaths) + print(groupId, groupName) \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/RiaGrpcCommandService.cpp b/ApplicationCode/GrpcInterface/RiaGrpcCommandService.cpp index e88ad84283..7567fa2dd2 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcCommandService.cpp +++ b/ApplicationCode/GrpcInterface/RiaGrpcCommandService.cpp @@ -150,6 +150,13 @@ void RiaGrpcCommandService::assignPdmFieldValue(caf::PdmValueField* pdmValueF FieldDescriptor::Type fieldDataType = paramDescriptor->type(); const Reflection* reflection = params.GetReflection(); + if (paramDescriptor->is_repeated() && + fieldDataType != FieldDescriptor::TYPE_INT32 && + fieldDataType != FieldDescriptor::TYPE_STRING) + { + CAF_ASSERT(false && "Only integer and string vectors are implemented as command arguments"); + } + switch (fieldDataType) { case FieldDescriptor::TYPE_BOOL: { @@ -224,10 +231,15 @@ void RiaGrpcCommandService::assignPdmFieldValue(caf::PdmValueField* pdmValueF //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RiaGrpcCommandService::assignGrpcFieldValue(google::protobuf::Message* reply, - const google::protobuf::FieldDescriptor* fieldDescriptor, - const caf::PdmValueField* pdmValueField) +void RiaGrpcCommandService::assignGrpcFieldValue(Message* reply, + const FieldDescriptor* fieldDescriptor, + const caf::PdmValueField* pdmValueField) { + if (fieldDescriptor->is_repeated()) + { + CAF_ASSERT(false && "Assigning vector results to Command Results is not yet implemented"); + } + FieldDescriptor::Type fieldDataType = fieldDescriptor->type(); QVariant qValue = pdmValueField->toQVariant(); From c2c312068c848b9c84920544d55e1016d8bb3bf1 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Wed, 24 Jul 2019 11:13:23 +0200 Subject: [PATCH 239/396] Python: enable more status messages and warnings for gRPC code generation --- ApplicationCode/CMakeLists.txt | 30 ++-- .../GrpcInterface/CMakeLists.cmake | 146 ++++++++++-------- 2 files changed, 96 insertions(+), 80 deletions(-) diff --git a/ApplicationCode/CMakeLists.txt b/ApplicationCode/CMakeLists.txt index 55e6e0ed6f..cc75e1cab8 100644 --- a/ApplicationCode/CMakeLists.txt +++ b/ApplicationCode/CMakeLists.txt @@ -537,19 +537,25 @@ foreach (FILE_TO_COPY ${RI_DLL_FILENAMES}) endforeach() # Copy all grpc libraries and python files -if (RESINSIGHT_ENABLE_GRPC) - if (PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) - add_custom_target(GeneratedPythonSources DEPENDS ${GRPC_GENERATED_PYTHON_SOURCES}) - add_dependencies(ResInsight GeneratedPythonSources) +if (RESINSIGHT_ENABLE_GRPC) + if (PYTHON_EXECUTABLE) + if (EXISTS ${PYTHON_EXECUTABLE}) + add_custom_target(GeneratedPythonSources DEPENDS ${GRPC_GENERATED_PYTHON_SOURCES}) + add_dependencies(ResInsight GeneratedPythonSources) - foreach (PYTHON_SCRIPT ${GRPC_PYTHON_SOURCES}) - if (EXISTS "${GRPC_PYTHON_SOURCE_PATH}/${PYTHON_SCRIPT}") - configure_file("${GRPC_PYTHON_SOURCE_PATH}/${PYTHON_SCRIPT}" - "${GRPC_PYTHON_DEST_PATH}/${PYTHON_SCRIPT}" - COPYONLY) - endif(EXISTS "${GRPC_PYTHON_SOURCE_PATH}/${PYTHON_SCRIPT}") - endforeach(PYTHON_SCRIPT ${GRPC_PYTHON_SOURCES}) - endif(PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) + foreach (PYTHON_SCRIPT ${GRPC_PYTHON_SOURCES}) + if (EXISTS "${GRPC_PYTHON_SOURCE_PATH}/${PYTHON_SCRIPT}") + configure_file("${GRPC_PYTHON_SOURCE_PATH}/${PYTHON_SCRIPT}" + "${GRPC_PYTHON_DEST_PATH}/${PYTHON_SCRIPT}" + COPYONLY) + endif(EXISTS "${GRPC_PYTHON_SOURCE_PATH}/${PYTHON_SCRIPT}") + endforeach(PYTHON_SCRIPT ${GRPC_PYTHON_SOURCES}) + else() + message(STATUS "Error installing python code: PYTHON_EXECUTABLE set but ${PYTHON_EXECUTABLE} not found") + endif(EXISTS ${PYTHON_EXECUTABLE}) + else() + message(STATUS "PYTHON_EXECUTABLE not specified. Will not install GRPC Python code.") + endif(PYTHON_EXECUTABLE) endif(RESINSIGHT_ENABLE_GRPC) ############################################################################# diff --git a/ApplicationCode/GrpcInterface/CMakeLists.cmake b/ApplicationCode/GrpcInterface/CMakeLists.cmake index 36b446443f..d08c9c500a 100644 --- a/ApplicationCode/GrpcInterface/CMakeLists.cmake +++ b/ApplicationCode/GrpcInterface/CMakeLists.cmake @@ -112,28 +112,33 @@ foreach(proto_file ${PROTO_FILES}) DEPENDS "${rips_proto}" ) - if (PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) - set(rips_proto_python "rips/generated/${proto_file}_pb2.py") - set(rips_grpc_python "rips/generated/${proto_file}_pb2_grpc.py") + if (PYTHON_EXECUTABLE) + if (EXISTS ${PYTHON_EXECUTABLE}) + set(rips_proto_python "rips/generated/${proto_file}_pb2.py") + set(rips_grpc_python "rips/generated/${proto_file}_pb2_grpc.py") - add_custom_command( - OUTPUT "${GRPC_PYTHON_SOURCE_PATH}/${rips_proto_python}" "${GRPC_PYTHON_SOURCE_PATH}/${rips_grpc_python}" - COMMAND ${PYTHON_EXECUTABLE} - ARGS -m grpc_tools.protoc - -I "${rips_proto_path}" - --python_out "${GRPC_PYTHON_SOURCE_PATH}/rips/generated" - --grpc_python_out "${GRPC_PYTHON_SOURCE_PATH}/rips/generated" - "${rips_proto}" - DEPENDS "${rips_proto}" - COMMENT "Generating ${rips_proto_python} and ${rips_grpc_python}" - VERBATIM - ) - list (APPEND GRPC_PYTHON_GENERATED_SOURCES - ${rips_proto_python} - ${rips_grpc_python} - ) - - endif(PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) + add_custom_command( + OUTPUT "${GRPC_PYTHON_SOURCE_PATH}/${rips_proto_python}" "${GRPC_PYTHON_SOURCE_PATH}/${rips_grpc_python}" + COMMAND ${PYTHON_EXECUTABLE} + ARGS -m grpc_tools.protoc + -I "${rips_proto_path}" + --python_out "${GRPC_PYTHON_SOURCE_PATH}/rips/generated" + --grpc_python_out "${GRPC_PYTHON_SOURCE_PATH}/rips/generated" + "${rips_proto}" + DEPENDS "${rips_proto}" + COMMENT "Generating ${rips_proto_python} and ${rips_grpc_python}" + VERBATIM + ) + list (APPEND GRPC_PYTHON_GENERATED_SOURCES + ${rips_proto_python} + ${rips_grpc_python} + ) + else() + message(STATUS "Error generating Python for ${rips_proto}: PYTHON_EXECUTABLE set but ${PYTHON_EXECUTABLE} not found") + endif(EXISTS ${PYTHON_EXECUTABLE}) + else() + message(STATUS "PYTHON_EXECUTABLE not specified. Will not generate GRPC Python code.") + endif(PYTHON_EXECUTABLE) list( APPEND GRPC_HEADER_FILES ${rips_proto_hdrs} @@ -147,54 +152,59 @@ foreach(proto_file ${PROTO_FILES}) endforeach(proto_file) -if (PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) - list(APPEND GRPC_PYTHON_SOURCES - ${GRPC_PYTHON_GENERATED_SOURCES} - "rips/generated/RiaVersionInfo.py" - "rips/__init__.py" - "rips/App.py" - "rips/Case.py" - "rips/Commands.py" - "rips/Grid.py" - "rips/Project.py" - "rips/Properties.py" - "rips/Instance.py" - "rips/PdmObject.py" - "rips/View.py" - "rips/examples/InstanceExample.py" - "rips/examples/CommandExample.py" - "rips/examples/CaseInfoStreamingExample.py" - "rips/examples/SoilPorvAsync.py" - "rips/examples/SoilPorvSync.py" - "rips/examples/SelectedCases.py" - "rips/examples/AllCases.py" - "rips/examples/SetGridProperties.py" - "rips/examples/GridInformation.py" - "rips/examples/InputPropTestSync.py" - "rips/examples/InputPropTestAsync.py" - "rips/examples/SoilAverage.py" - "rips/examples/SoilAverageNoComm.py" - "rips/tests/test_cases.py" - "rips/tests/test_commands.py" - "rips/tests/test_grids.py" - "rips/tests/test_properties.py" - "rips/tests/test_project.py" - "rips/tests/conftest.py" - "rips/tests/dataroot.py" - "requirements.txt" - "setup.py.cmake" - "README.md" - "LICENSE" - ) +if (PYTHON_EXECUTABLE) + if (EXISTS ${PYTHON_EXECUTABLE}) + list(APPEND GRPC_PYTHON_SOURCES + ${GRPC_PYTHON_GENERATED_SOURCES} + "rips/generated/RiaVersionInfo.py" + "rips/__init__.py" + "rips/App.py" + "rips/Case.py" + "rips/Commands.py" + "rips/Grid.py" + "rips/Project.py" + "rips/Properties.py" + "rips/Instance.py" + "rips/PdmObject.py" + "rips/View.py" + "rips/examples/InstanceExample.py" + "rips/examples/CommandExample.py" + "rips/examples/CaseInfoStreamingExample.py" + "rips/examples/SoilPorvAsync.py" + "rips/examples/SoilPorvSync.py" + "rips/examples/SelectedCases.py" + "rips/examples/AllCases.py" + "rips/examples/SetGridProperties.py" + "rips/examples/GridInformation.py" + "rips/examples/InputPropTestSync.py" + "rips/examples/InputPropTestAsync.py" + "rips/examples/SoilAverage.py" + "rips/examples/SoilAverageNoComm.py" + "rips/tests/test_cases.py" + "rips/tests/test_commands.py" + "rips/tests/test_grids.py" + "rips/tests/test_properties.py" + "rips/tests/test_project.py" + "rips/tests/conftest.py" + "rips/tests/dataroot.py" + "requirements.txt" + "setup.py.cmake" + "README.md" + "LICENSE" + ) - foreach(PYTHON_SCRIPT ${GRPC_PYTHON_SOURCES}) - list(APPEND GRPC_PYTHON_SOURCES_FULL_PATH "${GRPC_PYTHON_SOURCE_PATH}/${PYTHON_SCRIPT}") - endforeach() -if (MSVC) - source_group(TREE ${GRPC_PYTHON_SOURCE_PATH} FILES ${GRPC_PYTHON_SOURCES_FULL_PATH} PREFIX "GrpcInterface\\Python") -endif(MSVC) - -endif(PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) + foreach(PYTHON_SCRIPT ${GRPC_PYTHON_SOURCES}) + list(APPEND GRPC_PYTHON_SOURCES_FULL_PATH "${GRPC_PYTHON_SOURCE_PATH}/${PYTHON_SCRIPT}") + endforeach() + if (MSVC) + source_group(TREE ${GRPC_PYTHON_SOURCE_PATH} FILES ${GRPC_PYTHON_SOURCES_FULL_PATH} PREFIX "GrpcInterface\\Python") + endif(MSVC) + else() + message(STATUS "Error copying GRPC Python Code to build folder: PYTHON_EXECUTABLE set but ${PYTHON_EXECUTABLE} not found") + endif(EXISTS ${PYTHON_EXECUTABLE}) +else() + message(STATUS "PYTHON_EXECUTABLE not specified. Will not copy grpc Python code to build folder") +endif(PYTHON_EXECUTABLE) list ( APPEND GRPC_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES}) list ( APPEND GRPC_CPP_SOURCES ${SOURCE_GROUP_SOURCE_FILES}) From 2971c74c2eaee1eea74375120d5f8e55e2da5c09 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Thu, 25 Jul 2019 07:36:50 +0200 Subject: [PATCH 240/396] #4519 Fix error in example python script --- .../GrpcInterface/Python/rips/examples/AllCases.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/AllCases.py b/ApplicationCode/GrpcInterface/Python/rips/examples/AllCases.py index e552ef6978..c99949759e 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/examples/AllCases.py +++ b/ApplicationCode/GrpcInterface/Python/rips/examples/AllCases.py @@ -15,7 +15,7 @@ if resInsight is not None: assert(case.classKeyword() == "EclipseCase") print("\n#### Case ####") for keyword in case.keywords(): - print (keyword + ": " + case.getValue(keyword)) + print (keyword + ": " + str(case.getValue(keyword))) print ("\n####Project#####") pdmProject = case.ancestor(classKeyword="ResInsightProject") assert(pdmProject) @@ -23,7 +23,7 @@ if resInsight is not None: assert(pdmProject.address() == resInsight.project.address()) for keyword in resInsight.project.keywords(): - print (keyword + ": " + resInsight.project.getValue(keyword)) + print (keyword + ": " + str(resInsight.project.getValue(keyword))) pdmViews = resInsight.project.views() for view in pdmViews: print ("\n####View####") From d6d1ebd25da6560100fd5ba8a0d0cd47549f3cef Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Thu, 25 Jul 2019 10:37:41 +0200 Subject: [PATCH 241/396] #4518 Set grpc.enable_http_proxy=False in Python client code --- ApplicationCode/GrpcInterface/Python/rips/Instance.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ApplicationCode/GrpcInterface/Python/rips/Instance.py b/ApplicationCode/GrpcInterface/Python/rips/Instance.py index 2378f3e7b6..db05e08044 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Instance.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Instance.py @@ -114,7 +114,7 @@ class Instance: logging.basicConfig() location = "localhost:" + str(port) - self.channel = grpc.insecure_channel(location) + self.channel = grpc.insecure_channel(location, options=[('grpc.enable_http_proxy', False)]) self.launched = launched # Main version check package From 000ce6db5276b55e6ef9cfe494467e628fa469bb Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Thu, 25 Jul 2019 15:54:20 +0200 Subject: [PATCH 242/396] #4509 Guard access to gui application code in import and well path code to avoid crashes in console mode --- .../Tools/RiaImportEclipseCaseTools.cpp | 5 +- .../RifWellPathFormationReader.cpp | 15 ++++-- .../ProjectDataModel/RimGeoMechView.cpp | 10 ++-- .../RimIdenticalGridCaseGroup.cpp | 17 +++++-- .../ProjectDataModel/RimWellLogFile.cpp | 13 ++++-- .../RimWellPathCollection.cpp | 46 +++++++++++++------ .../UserInterface/Riu3DMainWindowTools.cpp | 15 ++++-- .../UserInterface/RiuPlotMainWindowTools.cpp | 39 +++++++++++----- 8 files changed, 113 insertions(+), 47 deletions(-) diff --git a/ApplicationCode/Application/Tools/RiaImportEclipseCaseTools.cpp b/ApplicationCode/Application/Tools/RiaImportEclipseCaseTools.cpp index 4d184bc5f4..7adf661e0a 100644 --- a/ApplicationCode/Application/Tools/RiaImportEclipseCaseTools.cpp +++ b/ApplicationCode/Application/Tools/RiaImportEclipseCaseTools.cpp @@ -180,10 +180,7 @@ bool RiaImportEclipseCaseTools::openEclipseCasesFromFile(const QStringList& file project->activeOilField()->completionTemplateCollection()->setDefaultUnitSystemBasedOnLoadedCases(); - if (RiaGuiApplication::isRunning()) - { - RiuPlotMainWindowTools::refreshToolbars(); - } + RiuPlotMainWindowTools::refreshToolbars(); if (openedFilesOut) { diff --git a/ApplicationCode/FileInterface/RifWellPathFormationReader.cpp b/ApplicationCode/FileInterface/RifWellPathFormationReader.cpp index f4c7a99f7c..d847864628 100644 --- a/ApplicationCode/FileInterface/RifWellPathFormationReader.cpp +++ b/ApplicationCode/FileInterface/RifWellPathFormationReader.cpp @@ -18,6 +18,7 @@ #include "RifWellPathFormationReader.h" +#include "RiaGuiApplication.h" #include "RiaLogging.h" #include "Riu3DMainWindowTools.h" @@ -63,16 +64,22 @@ std::map> if (wellNames.empty() || formationNames.empty()) { - QMessageBox::warning(Riu3DMainWindowTools::mainWindowWidget(), "Import failure", - QString("Failed to parse %1 as a well pick file").arg(filePath)); + if (RiaGuiApplication::isRunning()) + { + QMessageBox::warning(Riu3DMainWindowTools::mainWindowWidget(), "Import failure", + QString("Failed to parse %1 as a well pick file").arg(filePath)); + } RiaLogging::error(QString("Failed to parse %1 as a well pick file").arg(filePath)); return result; } else if (!(mdIsPresent || tvdIsPresent)) { - QMessageBox::warning(Riu3DMainWindowTools::mainWindowWidget(), "Import failure", - QString("Failed to parse %1 as a well pick file. Neither MD or TVD is present.").arg(filePath)); + if (RiaGuiApplication::isRunning()) + { + QMessageBox::warning(Riu3DMainWindowTools::mainWindowWidget(), "Import failure", + QString("Failed to parse %1 as a well pick file. Neither MD or TVD is present.").arg(filePath)); + } RiaLogging::error(QString("Failed to parse %1 as a well pick file. Neither MD or TVD is present.").arg(filePath)); return result; diff --git a/ApplicationCode/ProjectDataModel/RimGeoMechView.cpp b/ApplicationCode/ProjectDataModel/RimGeoMechView.cpp index a8efcb14f8..fdc5c4f4bf 100644 --- a/ApplicationCode/ProjectDataModel/RimGeoMechView.cpp +++ b/ApplicationCode/ProjectDataModel/RimGeoMechView.cpp @@ -142,9 +142,13 @@ void RimGeoMechView::onLoadDataAndUpdate() { QString displayMessage = errorMessage.empty() ? "Could not open the Odb file: \n" + m_geomechCase->caseFileName() : QString::fromStdString(errorMessage); - QMessageBox::warning(Riu3DMainWindowTools::mainWindowWidget(), - "File open error", - displayMessage); + if (RiaGuiApplication::isRunning()) + { + QMessageBox::warning(Riu3DMainWindowTools::mainWindowWidget(), + "File open error", + displayMessage); + } + RiaLogging::error(displayMessage); } m_geomechCase = nullptr; diff --git a/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp b/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp index 64adc6a1ca..3814c4d701 100644 --- a/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp +++ b/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp @@ -20,6 +20,9 @@ #include "RimIdenticalGridCaseGroup.h" +#include "RiaGuiApplication.h" +#include "RiaLogging.h" + #include "RigActiveCellInfo.h" #include "RigCaseCellResultsData.h" #include "RigEclipseCaseData.h" @@ -173,11 +176,15 @@ void RimIdenticalGridCaseGroup::loadMainCaseAndActiveCellInfo() RimEclipseCase* mainCase = caseCollection()->reservoirs[0]; if (!mainCase->openReserviorCase()) { - QMessageBox::warning(Riu3DMainWindowTools::mainWindowWidget(), - "Error when opening project file", - "Could not open the Eclipse Grid file: \n"+ mainCase->gridFileName() + "\n"+ - "Current working directory is: \n" + - QDir::currentPath()); + QString errorMessage = QString("Could not open the Eclipse Grid file: \n") + mainCase->gridFileName() + "\n" + + "Current working directory is: \n" + QDir::currentPath(); + + if (RiaGuiApplication::isRunning()) + { + QMessageBox::warning(Riu3DMainWindowTools::mainWindowWidget(), + "Error when opening project file", errorMessage); + } + RiaLogging::error(errorMessage); return; } diff --git a/ApplicationCode/ProjectDataModel/RimWellLogFile.cpp b/ApplicationCode/ProjectDataModel/RimWellLogFile.cpp index 66c935a5ec..f4c99e69b1 100644 --- a/ApplicationCode/ProjectDataModel/RimWellLogFile.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellLogFile.cpp @@ -19,6 +19,9 @@ #include "RimWellLogFile.h" +#include "RiaGuiApplication.h" +#include "RiaLogging.h" + #include "RiaDateStringParser.h" #include "RiaFieldHandleTools.h" #include "RiaQDateTimeTools.h" @@ -123,9 +126,13 @@ RimWellLogFile* RimWellLogFile::readWellLogFile(const QString& logFilePath) displayMessage += errorMessage; } - QMessageBox::warning(Riu3DMainWindowTools::mainWindowWidget(), - "File open error", - displayMessage); + if (RiaGuiApplication::isRunning()) + { + QMessageBox::warning(Riu3DMainWindowTools::mainWindowWidget(), + "File open error", + displayMessage); + } + RiaLogging::warning(errorMessage); delete wellLogFile; wellLogFile = nullptr; diff --git a/ApplicationCode/ProjectDataModel/RimWellPathCollection.cpp b/ApplicationCode/ProjectDataModel/RimWellPathCollection.cpp index a099abacdf..1e8982e993 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPathCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellPathCollection.cpp @@ -22,6 +22,7 @@ #include "RiaApplication.h" #include "RiaColorTables.h" +#include "RiaGuiApplication.h" #include "RiaLogging.h" #include "RiaPreferences.h" #include "RiaWellNameComparer.h" @@ -144,9 +145,13 @@ void RimWellPathCollection::loadDataAndUpdate() QString errorMessage; if ( !fWPath->readWellPathFile(&errorMessage, m_wellPathImporter) ) { - QMessageBox::warning(Riu3DMainWindowTools::mainWindowWidget(), - "File open error", - errorMessage); + if (RiaGuiApplication::isRunning()) + { + QMessageBox::warning(Riu3DMainWindowTools::mainWindowWidget(), + "File open error", + errorMessage); + } + RiaLogging::warning(errorMessage); } } @@ -165,9 +170,13 @@ void RimWellPathCollection::loadDataAndUpdate() displayMessage += errorMessage; } - QMessageBox::warning(Riu3DMainWindowTools::mainWindowWidget(), - "File open error", - displayMessage); + RiaLogging::warning(errorMessage); + if (RiaGuiApplication::isRunning()) + { + QMessageBox::warning(Riu3DMainWindowTools::mainWindowWidget(), + "File open error", + displayMessage); + } } } } @@ -373,7 +382,10 @@ void RimWellPathCollection::addWellPathFormations(const QStringList& filePaths) if (fileReadSuccess) { - QMessageBox::information(Riu3DMainWindowTools::mainWindowWidget(), "Well Picks Import", outputMessage); + if (RiaGuiApplication::isRunning()) + { + QMessageBox::information(Riu3DMainWindowTools::mainWindowWidget(), "Well Picks Import", outputMessage); + } RiaLogging::info(outputMessage); } @@ -511,9 +523,13 @@ void RimWellPathCollection::readWellPathFormationFiles() QString errorMessage; if (!wellPaths[wpIdx]->readWellPathFormationsFile(&errorMessage, m_wellPathFormationsImporter)) { - QMessageBox::warning(Riu3DMainWindowTools::mainWindowWidget(), - "File open error", - errorMessage); + if (RiaGuiApplication::isRunning()) + { + QMessageBox::warning(Riu3DMainWindowTools::mainWindowWidget(), + "File open error", + errorMessage); + } + RiaLogging::warning(errorMessage); } progress.setProgressDescription(QString("Reading formation file %1").arg(wpIdx)); @@ -533,9 +549,13 @@ void RimWellPathCollection::reloadAllWellPathFormations() QString errorMessage; if (!wellPaths[wpIdx]->reloadWellPathFormationsFile(&errorMessage, m_wellPathFormationsImporter)) { - QMessageBox::warning(Riu3DMainWindowTools::mainWindowWidget(), - "File open error", - errorMessage); + if (RiaGuiApplication::isRunning()) + { + QMessageBox::warning(Riu3DMainWindowTools::mainWindowWidget(), + "File open error", + errorMessage); + } + RiaLogging::warning(errorMessage); } progress.setProgressDescription(QString("Reloading formation file %1").arg(wpIdx)); diff --git a/ApplicationCode/UserInterface/Riu3DMainWindowTools.cpp b/ApplicationCode/UserInterface/Riu3DMainWindowTools.cpp index 58b8c8f7ac..5f57f844e2 100644 --- a/ApplicationCode/UserInterface/Riu3DMainWindowTools.cpp +++ b/ApplicationCode/UserInterface/Riu3DMainWindowTools.cpp @@ -33,7 +33,10 @@ QWidget* Riu3DMainWindowTools::mainWindowWidget() //-------------------------------------------------------------------------------------------------- void Riu3DMainWindowTools::setActiveViewer(QWidget* subWindow) { - RiuMainWindow::instance()->setActiveViewer(subWindow); + if (RiuMainWindow::instance()) + { + RiuMainWindow::instance()->setActiveViewer(subWindow); + } } //-------------------------------------------------------------------------------------------------- @@ -41,7 +44,10 @@ void Riu3DMainWindowTools::setActiveViewer(QWidget* subWindow) //-------------------------------------------------------------------------------------------------- void Riu3DMainWindowTools::setExpanded(const caf::PdmUiItem* uiItem, bool expanded /*= true*/) { - RiuMainWindow::instance()->setExpanded(uiItem, expanded); + if (RiuMainWindow::instance()) + { + RiuMainWindow::instance()->setExpanded(uiItem, expanded); + } } //-------------------------------------------------------------------------------------------------- @@ -49,7 +55,10 @@ void Riu3DMainWindowTools::setExpanded(const caf::PdmUiItem* uiItem, bool expand //-------------------------------------------------------------------------------------------------- void Riu3DMainWindowTools::selectAsCurrentItem(const caf::PdmObject* object, bool allowActiveViewChange /*= true*/) { - RiuMainWindow::instance()->selectAsCurrentItem(object, allowActiveViewChange); + if (RiuMainWindow::instance()) + { + RiuMainWindow::instance()->selectAsCurrentItem(object, allowActiveViewChange); + } } diff --git a/ApplicationCode/UserInterface/RiuPlotMainWindowTools.cpp b/ApplicationCode/UserInterface/RiuPlotMainWindowTools.cpp index 3a55288cd8..fc8f79fc13 100644 --- a/ApplicationCode/UserInterface/RiuPlotMainWindowTools.cpp +++ b/ApplicationCode/UserInterface/RiuPlotMainWindowTools.cpp @@ -25,7 +25,10 @@ //-------------------------------------------------------------------------------------------------- void RiuPlotMainWindowTools::showPlotMainWindow() { - RiaGuiApplication::instance()->getOrCreateAndShowMainPlotWindow(); + if (RiaGuiApplication::isRunning()) + { + RiaGuiApplication::instance()->getOrCreateAndShowMainPlotWindow(); + } } //-------------------------------------------------------------------------------------------------- @@ -33,9 +36,12 @@ void RiuPlotMainWindowTools::showPlotMainWindow() //-------------------------------------------------------------------------------------------------- void RiuPlotMainWindowTools::setActiveViewer(QWidget* subWindow) { - RiuPlotMainWindow* mpw = RiaGuiApplication::instance()->mainPlotWindow(); + if (RiaGuiApplication::isRunning()) + { + RiuPlotMainWindow* mpw = RiaGuiApplication::instance()->mainPlotWindow(); - if (mpw) mpw->setActiveViewer(subWindow); + if (mpw) mpw->setActiveViewer(subWindow); + } } //-------------------------------------------------------------------------------------------------- @@ -43,9 +49,12 @@ void RiuPlotMainWindowTools::setActiveViewer(QWidget* subWindow) //-------------------------------------------------------------------------------------------------- void RiuPlotMainWindowTools::setExpanded(const caf::PdmUiItem* uiItem, bool expanded /*= true*/) { - RiuPlotMainWindow* mpw = RiaGuiApplication::instance()->mainPlotWindow(); + if (RiaGuiApplication::isRunning()) + { + RiuPlotMainWindow* mpw = RiaGuiApplication::instance()->mainPlotWindow(); - if (mpw) mpw->setExpanded(uiItem, expanded); + if (mpw) mpw->setExpanded(uiItem, expanded); + } } //-------------------------------------------------------------------------------------------------- @@ -53,9 +62,12 @@ void RiuPlotMainWindowTools::setExpanded(const caf::PdmUiItem* uiItem, bool expa //-------------------------------------------------------------------------------------------------- void RiuPlotMainWindowTools::selectAsCurrentItem(const caf::PdmObject* object, bool allowActiveViewChange /*= true*/) { - RiuPlotMainWindow* mpw = RiaGuiApplication::instance()->mainPlotWindow(); + if (RiaGuiApplication::isRunning()) + { + RiuPlotMainWindow* mpw = RiaGuiApplication::instance()->mainPlotWindow(); - if (mpw) mpw->selectAsCurrentItem(object, allowActiveViewChange); + if (mpw) mpw->selectAsCurrentItem(object, allowActiveViewChange); + } } //-------------------------------------------------------------------------------------------------- @@ -63,12 +75,15 @@ void RiuPlotMainWindowTools::selectAsCurrentItem(const caf::PdmObject* object, b //-------------------------------------------------------------------------------------------------- void RiuPlotMainWindowTools::refreshToolbars() { - RiuPlotMainWindow* mpw = RiaGuiApplication::instance()->mainPlotWindow(); - - if (mpw) + if (RiaGuiApplication::isRunning()) { - mpw->updateSummaryPlotToolBar(); - mpw->updateWellLogPlotToolBar(); + RiuPlotMainWindow* mpw = RiaGuiApplication::instance()->mainPlotWindow(); + + if (mpw) + { + mpw->updateSummaryPlotToolBar(); + mpw->updateWellLogPlotToolBar(); + } } } From b095ac72264894550fa01162a6525f1d96ac78f8 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Fri, 26 Jul 2019 10:12:08 +0200 Subject: [PATCH 243/396] #4480 Add code for import of layer_zone_table.txt and enable manual import. --- .../RicImportFormationNamesFeature.cpp | 2 +- .../ProjectDataModel/RimFormationNames.cpp | 145 ++++++++++++++---- .../ProjectDataModel/RimFormationNames.h | 7 +- 3 files changed, 119 insertions(+), 35 deletions(-) diff --git a/ApplicationCode/Commands/RicImportFormationNamesFeature.cpp b/ApplicationCode/Commands/RicImportFormationNamesFeature.cpp index 3eab4c5c49..af9b02af9c 100644 --- a/ApplicationCode/Commands/RicImportFormationNamesFeature.cpp +++ b/ApplicationCode/Commands/RicImportFormationNamesFeature.cpp @@ -56,7 +56,7 @@ void RicImportFormationNamesFeature::onActionTriggered(bool isChecked) { RiaApplication* app = RiaApplication::instance(); QString defaultDir = app->lastUsedDialogDirectory("BINARY_GRID"); - QStringList fileNames = QFileDialog::getOpenFileNames(Riu3DMainWindowTools::mainWindowWidget(), "Import Formation Names", defaultDir, "Formation Names description File (*.lyr);;All Files (*.*)"); + QStringList fileNames = QFileDialog::getOpenFileNames(Riu3DMainWindowTools::mainWindowWidget(), "Import Formation Names", defaultDir, "Formation Names description File (*.lyr);;FMU Layer Zone Table(layer_zone_table.txt);;All Files (*.*)"); if (fileNames.isEmpty()) return; diff --git a/ApplicationCode/ProjectDataModel/RimFormationNames.cpp b/ApplicationCode/ProjectDataModel/RimFormationNames.cpp index 535f89f038..59d4841698 100644 --- a/ApplicationCode/ProjectDataModel/RimFormationNames.cpp +++ b/ApplicationCode/ProjectDataModel/RimFormationNames.cpp @@ -25,6 +25,7 @@ #include "Rim3dView.h" #include "RimWellLogTrack.h" +#include "cafAssert.h" #include "cafPdmUiFilePathEditor.h" #include @@ -79,14 +80,6 @@ void RimFormationNames::initAfterRead() updateUiTreeName(); } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimFormationNames::updateUiTreeName() -{ - this->uiCapability()->setUiName(fileNameWoPath()); -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -145,7 +138,7 @@ void RimFormationNames::updateConnectedViews() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimFormationNames::readFormationNamesFile(QString * errorMessage) +void RimFormationNames::readFormationNamesFile(QString* errorMessage) { QFile dataFile(m_formationNamesFileName()); @@ -156,28 +149,63 @@ void RimFormationNames::readFormationNamesFile(QString * errorMessage) } m_formationNamesData = new RigFormationNames; - QTextStream stream(&dataFile); + + QFileInfo fileInfo(m_formationNamesFileName()); + + if (fileInfo.fileName() == "layer_zone_table.txt") + { + readFmuFormationNameFile(stream, errorMessage); + } + else + { + CAF_ASSERT(fileInfo.suffix() == "lyr"); + readLyrFormationNameFile(stream, errorMessage); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFormationNames::updateFilePathsFromProjectPath(const QString& newProjectPath, const QString& oldProjectPath) +{ + m_formationNamesFileName = RimTools::relocateFile(m_formationNamesFileName(), newProjectPath, oldProjectPath, nullptr, nullptr); +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFormationNames::updateUiTreeName() +{ + this->uiCapability()->setUiName(fileNameWoPath()); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFormationNames::readLyrFormationNameFile(QTextStream& stream, QString* errorMessage) +{ int lineNumber = 1; while (!stream.atEnd()) { - QString line = stream.readLine(); + QString line = stream.readLine(); QStringList lineSegs = line.split("'", QString::KeepEmptyParts); - if(lineSegs.size() == 0) continue; // Empty line - if(lineSegs.size() == 1) continue; // No name present. Comment line ? - if(lineSegs.size() == 2) - { + if (lineSegs.size() == 0) continue; // Empty line + if (lineSegs.size() == 1) continue; // No name present. Comment line ? + if (lineSegs.size() == 2) + { if (errorMessage) (*errorMessage) += "Missing quote on line : " + QString::number(lineNumber) + "\n"; - continue; // One quote present + continue; // One quote present } if (lineSegs.size() == 3) // Normal case { - if ( lineSegs[0].contains("--")) continue; // Comment line - QString formationName = lineSegs[1]; - int commentMarkPos = lineSegs[2].indexOf("--"); - QString numberString = lineSegs[2]; + if (lineSegs[0].contains("--")) continue; // Comment line + QString formationName = lineSegs[1]; + int commentMarkPos = lineSegs[2].indexOf("--"); + QString numberString = lineSegs[2]; if (commentMarkPos >= 0) numberString.truncate(commentMarkPos); QStringList numberWords = numberString.split(QRegExp("-"), QString::SkipEmptyParts); @@ -185,8 +213,8 @@ void RimFormationNames::readFormationNamesFile(QString * errorMessage) { bool isNumber1 = false; bool isNumber2 = false; - int startK = numberWords[0].toInt(&isNumber1); - int endK = numberWords[1].toInt(&isNumber2); + int startK = numberWords[0].toInt(&isNumber1); + int endK = numberWords[1].toInt(&isNumber2); if (!(isNumber2 && isNumber1)) { @@ -194,19 +222,20 @@ void RimFormationNames::readFormationNamesFile(QString * errorMessage) continue; } - int tmp = startK; startK = tmp < endK ? tmp : endK; - endK = tmp > endK ? tmp: endK; + int tmp = startK; + startK = tmp < endK ? tmp : endK; + endK = tmp > endK ? tmp : endK; - m_formationNamesData->appendFormationRange(formationName, startK-1, endK-1); + m_formationNamesData->appendFormationRange(formationName, startK - 1, endK - 1); } else if (numberWords.size() == 1) { - bool isNumber1 = false; - int kLayerCount = numberWords[0].toInt(&isNumber1); + bool isNumber1 = false; + int kLayerCount = numberWords[0].toInt(&isNumber1); - if ( !isNumber1 ) + if (!isNumber1) { - if ( errorMessage ) (*errorMessage) += "Format error on line: " + QString::number(lineNumber) + "\n"; + if (errorMessage) (*errorMessage) += "Format error on line: " + QString::number(lineNumber) + "\n"; continue; } @@ -223,10 +252,60 @@ void RimFormationNames::readFormationNamesFile(QString * errorMessage) } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- -void RimFormationNames::updateFilePathsFromProjectPath(const QString& newProjectPath, const QString& oldProjectPath) +void RimFormationNames::readFmuFormationNameFile(QTextStream& stream, QString* errorMessage) { - m_formationNamesFileName = RimTools::relocateFile(m_formationNamesFileName(), newProjectPath, oldProjectPath, nullptr, nullptr); -} + int lineNumber = 1; + QString currentFormationName; + int startK = -1; + int endK = -1; + + while (!stream.atEnd()) + { + QString line = stream.readLine(); + if (line.isNull()) + { + // Make sure we append the last formation + if (!currentFormationName.isEmpty()) + { + m_formationNamesData->appendFormationRange(currentFormationName, startK - 1, endK - 1); + } + break; + } + else + { + QTextStream lineStream(&line); + + double kLayer; + QString formationName; + + lineStream >> kLayer >> formationName; + + if (lineStream.status() != QTextStream::Ok) + { + *errorMessage = QString("Failed to parse line %1 of '%2'").arg(lineNumber).arg(m_formationNamesFileName()); + return; + } + + if (formationName != currentFormationName) + { + // Append previous formation + if (!currentFormationName.isEmpty()) + { + m_formationNamesData->appendFormationRange(currentFormationName, startK - 1, endK - 1); + } + + // Start new formation + currentFormationName = formationName; + startK = kLayer; + endK = kLayer; + } + else + { + endK = kLayer; + } + } + } +} \ No newline at end of file diff --git a/ApplicationCode/ProjectDataModel/RimFormationNames.h b/ApplicationCode/ProjectDataModel/RimFormationNames.h index 04d27b8832..8c7a648e81 100644 --- a/ApplicationCode/ProjectDataModel/RimFormationNames.h +++ b/ApplicationCode/ProjectDataModel/RimFormationNames.h @@ -23,6 +23,8 @@ class RigFormationNames; +class QTextStream; + //================================================================================================== /// //================================================================================================== @@ -41,7 +43,7 @@ public: RigFormationNames* formationNamesData() { return m_formationNamesData.p();} void updateConnectedViews(); - void readFormationNamesFile(QString * errorMessage); + void readFormationNamesFile(QString* errorMessage); void updateFilePathsFromProjectPath(const QString& newProjectPath, const QString& oldProjectPath); protected: @@ -50,7 +52,10 @@ protected: private: void updateUiTreeName(); + void readLyrFormationNameFile(QTextStream& stream, QString* errorMessage); + void readFmuFormationNameFile(QTextStream& stream, QString* errorMessage); +private: caf::PdmField m_formationNamesFileName; cvf::ref m_formationNamesData; From a7879813c9540ebb371c3270084323d591306af9 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Fri, 26 Jul 2019 10:27:10 +0200 Subject: [PATCH 244/396] #4459 Fix memory leak in RFT Reader --- ApplicationCode/FileInterface/RifReaderEclipseRft.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ApplicationCode/FileInterface/RifReaderEclipseRft.cpp b/ApplicationCode/FileInterface/RifReaderEclipseRft.cpp index 2171f8809f..e42ecdac08 100644 --- a/ApplicationCode/FileInterface/RifReaderEclipseRft.cpp +++ b/ApplicationCode/FileInterface/RifReaderEclipseRft.cpp @@ -40,6 +40,10 @@ RifReaderEclipseRft::RifReaderEclipseRft(const QString& fileName): //-------------------------------------------------------------------------------------------------- RifReaderEclipseRft::~RifReaderEclipseRft() { + if (m_ecl_rft_file) + { + ecl_rft_file_free(m_ecl_rft_file); + } } //-------------------------------------------------------------------------------------------------- @@ -113,7 +117,7 @@ void RifReaderEclipseRft::open() m_rftAddressToLibeclNodeIdx[addressGrat] = i; } } - + return; } From 17ee6627bba5dc3d6e7e3d2e0668906a2b9e7fb8 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Fri, 26 Jul 2019 11:36:40 +0200 Subject: [PATCH 245/396] #4520 Report identical fault errors only once. --- .../RifEclipseInputFileTools.cpp | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp b/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp index cc0ddd69e9..17552d0d74 100644 --- a/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp +++ b/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp @@ -1640,6 +1640,9 @@ void RifEclipseInputFileTools::readFaults(QFile& data, // qDebug() << "Reading faults from\n " << data.fileName(); + std::set errorMessages; + std::set warningMessages; + RigFault* fault = nullptr; do @@ -1655,7 +1658,7 @@ void RifEclipseInputFileTools::readFaults(QFile& data, else if (line.startsWith("/", Qt::CaseInsensitive)) { // Detected end of keyword data section - return; + break; } else if (line.startsWith(editKeyword, Qt::CaseInsensitive)) { @@ -1666,7 +1669,7 @@ void RifEclipseInputFileTools::readFaults(QFile& data, *isEditKeywordDetected = true; } - return; + break; } // Replace tab with space to be able to split the string using space as splitter @@ -1704,14 +1707,14 @@ void RifEclipseInputFileTools::readFaults(QFile& data, if (faultName.contains(' ')) { - RiaLogging::error(QString("Fault name '%1' contains spaces").arg(faultName)); + errorMessages.insert(QString("Fault name '%1' contains spaces").arg(faultName)); continue; } else if (faultName.length() > 8) { // Keep going anyway, eclipse files sometimes have longer than // the specified 8 characters in the name without Eclipse complaining - RiaLogging::warning(QString("Fault name '%1' is longer than 8 characters").arg(faultName)); + warningMessages.insert(QString("Fault name '%1' is longer than 8 characters").arg(faultName)); } int i1, i2, j1, j2, k1, k2; @@ -1760,4 +1763,14 @@ void RifEclipseInputFileTools::readFaults(QFile& data, fault->addCellRangeForFace(cellFaceEnum, cellrange); } while (!data.atEnd()); + + for (QString errorMessage : errorMessages) + { + RiaLogging::error(errorMessage); + } + + for (QString warningMessage : warningMessages) + { + RiaLogging::warning(warningMessage); + } } From 8f464e5e231efb9de8e0f751aff8d746e16e1639 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Fri, 26 Jul 2019 11:37:58 +0200 Subject: [PATCH 246/396] #4487 Enable Y-axis scale factor for Auto number formats --- .../RimPlotAxisProperties.cpp | 3 +- .../Summary/RimSummaryCurvesCalculator.cpp | 85 ++++++++----------- 2 files changed, 36 insertions(+), 52 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimPlotAxisProperties.cpp b/ApplicationCode/ProjectDataModel/RimPlotAxisProperties.cpp index bacf9956da..ecc41bf31b 100644 --- a/ApplicationCode/ProjectDataModel/RimPlotAxisProperties.cpp +++ b/ApplicationCode/ProjectDataModel/RimPlotAxisProperties.cpp @@ -200,9 +200,8 @@ void RimPlotAxisProperties::defineUiOrdering(QString uiConfigName, caf::PdmUiOrd if (numberFormat() != NUMBER_FORMAT_AUTO) { scaleGroup.add(&numberOfDecimals); - scaleGroup.add(&scaleFactor); } - + scaleGroup.add(&scaleFactor); scaleGroup.add(&visibleRangeMin); scaleGroup.add(&visibleRangeMax); scaleGroup.add(&m_valuesFontSize); diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurvesCalculator.cpp b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurvesCalculator.cpp index b024c03941..f8be04528f 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurvesCalculator.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurvesCalculator.cpp @@ -43,59 +43,50 @@ // G use E or f format, whichever is the most concise //-------------------------------------------------------------------------------------------------- -class DecimalScaleDraw : public QwtScaleDraw +class SummaryScaleDraw : public QwtScaleDraw { public: - DecimalScaleDraw(double scaleFactor, int numberOfDecimals) + SummaryScaleDraw(double scaleFactor, + int numberOfDecimals, + RimPlotAxisProperties::NumberFormatType numberFormat = RimPlotAxisProperties::NUMBER_FORMAT_AUTO) { m_scaleFactor = scaleFactor; m_numberOfDecimals = numberOfDecimals; + m_numberFormat = numberFormat; } QwtText label(double value) const override { if (qFuzzyCompare(scaledValue(value) + 1.0, 1.0)) value = 0.0; - return QString::number(scaledValue(value), 'f', m_numberOfDecimals); + return QString::number(scaledValue(value), numberFormat(), m_numberOfDecimals); } private: + char numberFormat() const + { + switch (m_numberFormat) + { + case RimPlotAxisProperties::NUMBER_FORMAT_AUTO: + return 'g'; + case RimPlotAxisProperties::NUMBER_FORMAT_DECIMAL: + return 'f'; + case RimPlotAxisProperties::NUMBER_FORMAT_SCIENTIFIC: + return 'e'; + default: + return 'g'; + } + } + double scaledValue(double value) const { return value / m_scaleFactor; } - double m_scaleFactor; - int m_numberOfDecimals; -}; - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -class ScientificScaleDraw : public QwtScaleDraw -{ -public: - ScientificScaleDraw(double scaleFactor, int numberOfDecimals) - { - m_scaleFactor = scaleFactor; - m_numberOfDecimals = numberOfDecimals; - } - - QwtText label(double value) const override - { - if (qFuzzyCompare(scaledValue(value) + 1.0, 1.0)) value = 0.0; - - return QString::number(scaledValue(value), 'e', m_numberOfDecimals); - } - private: - double scaledValue(double value) const - { - return value / m_scaleFactor; - } - - double m_scaleFactor; - int m_numberOfDecimals; + double m_scaleFactor; + int m_numberOfDecimals; + RimPlotAxisProperties::NumberFormatType m_numberFormat; }; //-------------------------------------------------------------------------------------------------- @@ -153,21 +144,18 @@ void RimSummaryPlotYAxisFormatter::applyYAxisPropertiesToPlot(RiuSummaryQwtPlot* } { - if (m_axisProperties->numberFormat == RimPlotAxisProperties::NUMBER_FORMAT_AUTO) + if (m_axisProperties->numberFormat == RimPlotAxisProperties::NUMBER_FORMAT_AUTO && + m_axisProperties->scaleFactor() == 1.0) { + // Default to Qwt's own scale draw to avoid changing too much for default values qwtPlot->setAxisScaleDraw(m_axisProperties->qwtPlotAxisType(), new QwtScaleDraw); } - else if (m_axisProperties->numberFormat == RimPlotAxisProperties::NUMBER_FORMAT_DECIMAL) + else { - qwtPlot->setAxisScaleDraw( - m_axisProperties->qwtPlotAxisType(), - new DecimalScaleDraw(m_axisProperties->scaleFactor(), m_axisProperties->numberOfDecimals())); - } - else if (m_axisProperties->numberFormat == RimPlotAxisProperties::NUMBER_FORMAT_SCIENTIFIC) - { - qwtPlot->setAxisScaleDraw( - m_axisProperties->qwtPlotAxisType(), - new ScientificScaleDraw(m_axisProperties->scaleFactor(), m_axisProperties->numberOfDecimals())); + qwtPlot->setAxisScaleDraw(m_axisProperties->qwtPlotAxisType(), + new SummaryScaleDraw(m_axisProperties->scaleFactor(), + m_axisProperties->numberOfDecimals(), + m_axisProperties->numberFormat())); } } @@ -263,13 +251,10 @@ QString RimSummaryPlotYAxisFormatter::autoAxisTitle() const QString assembledYAxisText; QString scaleFactorText = ""; - if (m_axisProperties->numberFormat() != RimPlotAxisProperties::NUMBER_FORMAT_AUTO) + if (m_axisProperties->scaleFactor() != 1.0) { - if (m_axisProperties->scaleFactor() != 1.0) - { - int exponent = std::log10(m_axisProperties->scaleFactor()); - scaleFactorText = QString(" x 10%1 ").arg(QString::number(exponent)); - } + int exponent = std::log10(m_axisProperties->scaleFactor()); + scaleFactorText = QString(" x 10%1 ").arg(QString::number(exponent)); } for (auto unitIt : unitToQuantityNameMap) From 3ba962aefbb558bc98b592a672623982e0794537 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Fri, 26 Jul 2019 14:54:54 +0200 Subject: [PATCH 247/396] #4471 Implement python script running and editor in ResInsight GUI, same as Octave. --- .../Application/RiaApplication.cpp | 102 ++++++++++++------ ApplicationCode/Application/RiaApplication.h | 9 +- .../Application/RiaGuiApplication.cpp | 4 +- .../Application/RiaPreferences.cpp | 7 ++ ApplicationCode/Application/RiaPreferences.h | 2 + .../RicfRunOctaveScript.cpp | 4 +- .../RicExecuteScriptFeature.cpp | 21 +++- .../RicExecuteScriptForCasesFeature.cpp | 2 +- .../ProjectDataModel/RimCalcScript.cpp | 65 +++++++++-- .../ProjectDataModel/RimCalcScript.h | 14 +++ .../ProjectDataModel/RimCommandObject.cpp | 2 +- .../ProjectDataModel/RimScriptCollection.cpp | 4 +- .../Resources/PythonScriptFile16x16.png | Bin 0 -> 802 bytes ApplicationCode/Resources/ResInsight.qrc | 1 + Fwk/AppFwk/CommonCode/cafUtils.cpp | 21 +++- Fwk/AppFwk/CommonCode/cafUtils.h | 3 +- 16 files changed, 200 insertions(+), 61 deletions(-) create mode 100644 ApplicationCode/Resources/PythonScriptFile16x16.png diff --git a/ApplicationCode/Application/RiaApplication.cpp b/ApplicationCode/Application/RiaApplication.cpp index 8f000f6b83..a4ca703e96 100644 --- a/ApplicationCode/Application/RiaApplication.cpp +++ b/ApplicationCode/Application/RiaApplication.cpp @@ -899,7 +899,73 @@ QStringList RiaApplication::octaveArguments() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool RiaApplication::launchProcess(const QString& program, const QStringList& arguments) +QProcessEnvironment RiaApplication::octaveProcessEnvironment() const +{ + QProcessEnvironment penv = QProcessEnvironment::systemEnvironment(); + +#ifdef WIN32 + // Octave plugins compiled by ResInsight are dependent on Qt (currently Qt 32-bit only) + // Some Octave installations for Windows have included Qt, and some don't. To make sure these plugins always can be + // executed, the path to octave_plugin_dependencies is added to global path + + QString pathString = penv.value("PATH", ""); + + if (pathString == "") + pathString = QApplication::applicationDirPath() + "\\octave_plugin_dependencies"; + else + pathString = QApplication::applicationDirPath() + "\\octave_plugin_dependencies" + ";" + pathString; + + penv.insert("PATH", pathString); +#else + // Set the LD_LIBRARY_PATH to make the octave plugins find the embedded Qt + QString ldPath = penv.value("LD_LIBRARY_PATH", ""); + + if (ldPath == "") + ldPath = QApplication::applicationDirPath(); + else + ldPath = QApplication::applicationDirPath() + ":" + ldPath; + + penv.insert("LD_LIBRARY_PATH", ldPath); +#endif + + return penv; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RiaApplication::pythonPath() const +{ + return m_preferences->pythonExecutable(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QProcessEnvironment RiaApplication::pythonProcessEnvironment() const +{ + QProcessEnvironment penv = QProcessEnvironment::systemEnvironment(); + penv.insert("RESINSIGHT_GRPC_PORT", QString("%1").arg(m_grpcServer->portNumber())); + penv.insert("RESINSIGHT_EXECUTABLE", QCoreApplication::applicationFilePath()); + + QStringList ripsLocations; +#ifdef WIN32 + ripsLocations << QCoreApplication::applicationDirPath() + "\\Python" + << QCoreApplication::applicationDirPath() + "\\..\\..\\Python"; + +#else + ripsLocations << QCoreApplication::applicationDirPath() + "/Python"; +#endif + + penv.insert("PYTHONPATH", QString("%1;%2").arg(penv.value("PYTHONPATH")).arg(ripsLocations.join(";"))); + + return penv; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RiaApplication::launchProcess(const QString& program, const QStringList& arguments, const QProcessEnvironment& processEnvironment) { if (m_workerProcess == nullptr) { @@ -920,34 +986,7 @@ bool RiaApplication::launchProcess(const QString& program, const QStringList& ar m_runningWorkerProcess = true; m_workerProcess = new caf::UiProcess(QCoreApplication::instance()); - QProcessEnvironment penv = QProcessEnvironment::systemEnvironment(); - -#ifdef WIN32 - // Octave plugins compiled by ResInsight are dependent on Qt (currently Qt 32-bit only) - // Some Octave installations for Windows have included Qt, and some don't. To make sure these plugins always can be - // executed, the path to octave_plugin_dependencies is added to global path - - QString pathString = penv.value("PATH", ""); - - if (pathString == "") - pathString = QApplication::applicationDirPath() + "\\octave_plugin_dependencies"; - else - pathString = QApplication::applicationDirPath() + "\\octave_plugin_dependencies" + ";" + pathString; - - penv.insert("PATH", pathString); -#else - // Set the LD_LIBRARY_PATH to make the octave plugins find the embedded Qt - QString ldPath = penv.value("LD_LIBRARY_PATH", ""); - - if (ldPath == "") - ldPath = QApplication::applicationDirPath(); - else - ldPath = QApplication::applicationDirPath() + ":" + ldPath; - - penv.insert("LD_LIBRARY_PATH", ldPath); -#endif - - m_workerProcess->setProcessEnvironment(penv); + m_workerProcess->setProcessEnvironment(processEnvironment); QCoreApplication::instance()->connect(m_workerProcess, SIGNAL(finished(int, QProcess::ExitStatus)), @@ -989,7 +1028,8 @@ bool RiaApplication::launchProcess(const QString& program, const QStringList& ar //-------------------------------------------------------------------------------------------------- bool RiaApplication::launchProcessForMultipleCases(const QString& program, const QStringList& arguments, - const std::vector& caseIds) + const std::vector& caseIds, + const QProcessEnvironment& processEnvironment) { m_currentCaseIds.clear(); std::copy(caseIds.begin(), caseIds.end(), std::back_inserter(m_currentCaseIds)); @@ -997,7 +1037,7 @@ bool RiaApplication::launchProcessForMultipleCases(const QString& progr m_currentProgram = program; m_currentArguments = arguments; - return launchProcess(m_currentProgram, m_currentArguments); + return launchProcess(m_currentProgram, m_currentArguments, processEnvironment); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/Application/RiaApplication.h b/ApplicationCode/Application/RiaApplication.h index 09f0f7326a..8ebb5484c1 100644 --- a/ApplicationCode/Application/RiaApplication.h +++ b/ApplicationCode/Application/RiaApplication.h @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -144,9 +145,13 @@ public: QString octavePath() const; QStringList octaveArguments() const; + QProcessEnvironment octaveProcessEnvironment() const; - bool launchProcess(const QString& program, const QStringList& arguments); - bool launchProcessForMultipleCases(const QString& program, const QStringList& arguments, const std::vector& caseIds); + QString pythonPath() const; + QProcessEnvironment pythonProcessEnvironment() const; + + bool launchProcess(const QString& program, const QStringList& arguments, const QProcessEnvironment& processEnvironment); + bool launchProcessForMultipleCases(const QString& program, const QStringList& arguments, const std::vector& caseIds, const QProcessEnvironment& processEnvironment); void terminateProcess(); void waitForProcess() const; diff --git a/ApplicationCode/Application/RiaGuiApplication.cpp b/ApplicationCode/Application/RiaGuiApplication.cpp index 78783583c0..e0c278aad1 100644 --- a/ApplicationCode/Application/RiaGuiApplication.cpp +++ b/ApplicationCode/Application/RiaGuiApplication.cpp @@ -1655,6 +1655,8 @@ void RiaGuiApplication::slotWorkerProcessFinished(int exitCode, QProcess::ExitSt { m_mainWindow->processMonitor()->stopMonitorWorkProcess(); + QProcessEnvironment processEnvironment = m_workerProcess->processEnvironment(); + // Execute delete later so that other slots that are hooked up // get a chance to run before we delete the object if (m_workerProcess) @@ -1684,7 +1686,7 @@ void RiaGuiApplication::slotWorkerProcessFinished(int exitCode, QProcess::ExitSt // If multiple cases are present, invoke launchProcess() which will set next current case, and run script on this case if (!m_currentCaseIds.empty()) { - launchProcess(m_currentProgram, m_currentArguments); + launchProcess(m_currentProgram, m_currentArguments, processEnvironment); } else { diff --git a/ApplicationCode/Application/RiaPreferences.cpp b/ApplicationCode/Application/RiaPreferences.cpp index 382478c581..e5363704f9 100644 --- a/ApplicationCode/Application/RiaPreferences.cpp +++ b/ApplicationCode/Application/RiaPreferences.cpp @@ -67,6 +67,10 @@ RiaPreferences::RiaPreferences(void) CAF_PDM_InitField(&octaveShowHeaderInfoWhenExecutingScripts, "octaveShowHeaderInfoWhenExecutingScripts", false, "Show Text Header When Executing Scripts", "", "", ""); octaveShowHeaderInfoWhenExecutingScripts.uiCapability()->setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN); + CAF_PDM_InitField(&pythonExecutable, "pythonExecutable", QString("python"), "Python Executable Location", "", "", ""); + pythonExecutable.uiCapability()->setUiEditorTypeName(caf::PdmUiFilePathEditor::uiEditorTypeName()); + pythonExecutable.uiCapability()->setUiLabelPosition(caf::PdmUiItemInfo::TOP); + CAF_PDM_InitField(&ssihubAddress, "ssihubAddress", QString("http://"), "SSIHUB Address", "", "", ""); ssihubAddress.uiCapability()->setUiLabelPosition(caf::PdmUiItemInfo::TOP); @@ -273,6 +277,9 @@ void RiaPreferences::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& octaveGroup->add(&octaveExecutable); octaveGroup->add(&octaveShowHeaderInfoWhenExecutingScripts); + caf::PdmUiGroup* pythonGroup = uiOrdering.addNewGroup("Python"); + pythonGroup->add(&pythonExecutable); + caf::PdmUiGroup* scriptGroup = uiOrdering.addNewGroup("Script files"); scriptGroup->add(&scriptDirectories); scriptGroup->add(&scriptEditorExecutable); diff --git a/ApplicationCode/Application/RiaPreferences.h b/ApplicationCode/Application/RiaPreferences.h index ebace447ab..dca4eb8d15 100644 --- a/ApplicationCode/Application/RiaPreferences.h +++ b/ApplicationCode/Application/RiaPreferences.h @@ -77,6 +77,8 @@ public: // Pdm Fields caf::PdmField octaveExecutable; caf::PdmField octaveShowHeaderInfoWhenExecutingScripts; + caf::PdmField pythonExecutable; + caf::PdmField ssihubAddress; caf::PdmField> defaultMeshModeType; diff --git a/ApplicationCode/CommandFileInterface/RicfRunOctaveScript.cpp b/ApplicationCode/CommandFileInterface/RicfRunOctaveScript.cpp index c9cf89e180..b43d8207c8 100644 --- a/ApplicationCode/CommandFileInterface/RicfRunOctaveScript.cpp +++ b/ApplicationCode/CommandFileInterface/RicfRunOctaveScript.cpp @@ -65,11 +65,11 @@ RicfCommandResponse RicfRunOctaveScript::execute() bool ok; if (caseIds.empty()) { - ok = RiaApplication::instance()->launchProcess(octavePath, processArguments); + ok = RiaApplication::instance()->launchProcess(octavePath, processArguments, RiaApplication::instance()->octaveProcessEnvironment()); } else { - ok = RiaApplication::instance()->launchProcessForMultipleCases(octavePath, processArguments, caseIds); + ok = RiaApplication::instance()->launchProcessForMultipleCases(octavePath, processArguments, caseIds, RiaApplication::instance()->octaveProcessEnvironment()); } RicfCommandResponse response; diff --git a/ApplicationCode/Commands/OctaveScriptCommands/RicExecuteScriptFeature.cpp b/ApplicationCode/Commands/OctaveScriptCommands/RicExecuteScriptFeature.cpp index e52539aa29..b01fb43976 100644 --- a/ApplicationCode/Commands/OctaveScriptCommands/RicExecuteScriptFeature.cpp +++ b/ApplicationCode/Commands/OctaveScriptCommands/RicExecuteScriptFeature.cpp @@ -56,12 +56,23 @@ void RicExecuteScriptFeature::onActionTriggered(bool isChecked) RimCalcScript* calcScript = selection[0]; RiaApplication* app = RiaApplication::instance(); - QString octavePath = app->octavePath(); - if (!octavePath.isEmpty()) + if (calcScript->scriptType() == RimCalcScript::OCTAVE) { - QStringList arguments = RimCalcScript::createCommandLineArguments(calcScript->absoluteFileName()); - - RiaApplication::instance()->launchProcess(octavePath, arguments); + QString octavePath = app->octavePath(); + if (!octavePath.isEmpty()) + { + QStringList arguments = RimCalcScript::createCommandLineArguments(calcScript->absoluteFileName()); + RiaApplication::instance()->launchProcess(octavePath, arguments, app->octaveProcessEnvironment()); + } + } + else if (calcScript->scriptType() == RimCalcScript::PYTHON) + { + QString pythonPath = app->pythonPath(); + if (!pythonPath.isEmpty()) + { + QStringList arguments = RimCalcScript::createCommandLineArguments(calcScript->absoluteFileName()); + RiaApplication::instance()->launchProcess(pythonPath, arguments, app->pythonProcessEnvironment()); + } } } diff --git a/ApplicationCode/Commands/OctaveScriptCommands/RicExecuteScriptForCasesFeature.cpp b/ApplicationCode/Commands/OctaveScriptCommands/RicExecuteScriptForCasesFeature.cpp index 9c3f0e1192..98fa643ee8 100644 --- a/ApplicationCode/Commands/OctaveScriptCommands/RicExecuteScriptForCasesFeature.cpp +++ b/ApplicationCode/Commands/OctaveScriptCommands/RicExecuteScriptForCasesFeature.cpp @@ -80,7 +80,7 @@ void RicExecuteScriptForCasesFeature::onActionTriggered(bool isChecked) if (caseIdsInSelection.size() > 0) { - RiaApplication::instance()->launchProcessForMultipleCases(octavePath, arguments, caseIdsInSelection); + RiaApplication::instance()->launchProcessForMultipleCases(octavePath, arguments, caseIdsInSelection, app->octaveProcessEnvironment()); } } } diff --git a/ApplicationCode/ProjectDataModel/RimCalcScript.cpp b/ApplicationCode/ProjectDataModel/RimCalcScript.cpp index ffaccf9832..2fe0ee41e4 100644 --- a/ApplicationCode/ProjectDataModel/RimCalcScript.cpp +++ b/ApplicationCode/ProjectDataModel/RimCalcScript.cpp @@ -48,6 +48,31 @@ RimCalcScript::RimCalcScript() //-------------------------------------------------------------------------------------------------- RimCalcScript::~RimCalcScript() {} +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimCalcScript::ScriptType RimCalcScript::scriptType(const QString& absoluteFileNameScript) +{ + QFileInfo fileInfo(absoluteFileNameScript); + if (fileInfo.suffix() == "py") + { + return PYTHON; + } + else if (fileInfo.suffix() == "m") + { + return OCTAVE; + } + return UNKNOWN; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimCalcScript::ScriptType RimCalcScript::scriptType() const +{ + return scriptType(absoluteFileName()); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -55,20 +80,27 @@ QStringList RimCalcScript::createCommandLineArguments(const QString& absoluteFil { QStringList arguments; + if (scriptType(absoluteFileNameScript) == PYTHON) { - auto app = RiaApplication::instance(); - - arguments = app->octaveArguments(); - arguments.append("--path"); + arguments.append(absoluteFileNameScript); } - + else if (scriptType(absoluteFileNameScript) == OCTAVE) { - QFileInfo fi(absoluteFileNameScript); - QString octaveFunctionSearchPath = fi.absolutePath(); - QString absFilePath = fi.absoluteFilePath(); + { + auto app = RiaApplication::instance(); - arguments << octaveFunctionSearchPath; - arguments << absFilePath; + arguments = app->octaveArguments(); + arguments.append("--path"); + } + + { + QFileInfo fi(absoluteFileNameScript); + QString octaveFunctionSearchPath = fi.absolutePath(); + QString absFilePath = fi.absoluteFilePath(); + + arguments << octaveFunctionSearchPath; + arguments << absFilePath; + } } bool debugPrintArgumentText = false; @@ -76,8 +108,19 @@ QStringList RimCalcScript::createCommandLineArguments(const QString& absoluteFil { QString argumentString = arguments.join(" "); - RiaLogging::info("Octave arguments : " + argumentString); + RiaLogging::info("Scriptarguments : " + argumentString); } return arguments; } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimCalcScript::defineUiTreeOrdering(caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName /*= ""*/) +{ + if (scriptType() == PYTHON) + { + uiCapability()->setUiIconFromResourceString(":/PythonScriptFile16x16.png"); + } +} diff --git a/ApplicationCode/ProjectDataModel/RimCalcScript.h b/ApplicationCode/ProjectDataModel/RimCalcScript.h index 442bc97cf0..f477fa2ee1 100644 --- a/ApplicationCode/ProjectDataModel/RimCalcScript.h +++ b/ApplicationCode/ProjectDataModel/RimCalcScript.h @@ -30,11 +30,25 @@ class RimCalcScript : public caf::PdmObject CAF_PDM_HEADER_INIT; public: + enum ScriptType + { + OCTAVE = 0, + PYTHON = 1, + UNKNOWN = 2 + }; + RimCalcScript(); ~RimCalcScript() override; + ScriptType scriptType() const; + static ScriptType scriptType(const QString& fileName); + static QStringList createCommandLineArguments(const QString& absoluteFileNameScript); caf::PdmField absoluteFileName; caf::PdmField content; // TODO: Obsolete field, can be deleted on next project file revision. + +protected: + void defineUiTreeOrdering(caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName = "") override; + }; diff --git a/ApplicationCode/ProjectDataModel/RimCommandObject.cpp b/ApplicationCode/ProjectDataModel/RimCommandObject.cpp index b260a82817..59f8704f21 100644 --- a/ApplicationCode/ProjectDataModel/RimCommandObject.cpp +++ b/ApplicationCode/ProjectDataModel/RimCommandObject.cpp @@ -96,7 +96,7 @@ void RimCommandExecuteScript::redo() arguments.append("--eval"); arguments << this->scriptText(); - RiaApplication::instance()->launchProcess(octavePath, arguments); + RiaApplication::instance()->launchProcess(octavePath, arguments, app->octaveProcessEnvironment()); } } diff --git a/ApplicationCode/ProjectDataModel/RimScriptCollection.cpp b/ApplicationCode/ProjectDataModel/RimScriptCollection.cpp index 523663027a..a464b2305a 100644 --- a/ApplicationCode/ProjectDataModel/RimScriptCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimScriptCollection.cpp @@ -81,8 +81,8 @@ void RimScriptCollection::readContentFromDisc() // Build a list of all scripts in the specified directory { - QString filter = "*.m"; - QStringList fileList = caf::Utils::getFilesInDirectory(directory, filter, true); + QStringList nameFilters; nameFilters << "*.m" << "*.py"; + QStringList fileList = caf::Utils::getFilesInDirectory(directory, nameFilters, true); int i; for (i = 0; i < fileList.size(); i++) diff --git a/ApplicationCode/Resources/PythonScriptFile16x16.png b/ApplicationCode/Resources/PythonScriptFile16x16.png new file mode 100644 index 0000000000000000000000000000000000000000..351c1ac7387e5337f96e9ac55181a19609053f94 GIT binary patch literal 802 zcmV+-1Ks?IP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!~g&e!~vBn z4jTXf02y>eSaefwW^{L9a%BK_cXuvnZfkR6VQ^(GZ*pgw?mQX*00M$ZL_t(IPmNPe zOcOyA{$_vrM=RLqfr?SUlAy&v^aLjpPsT`M;@yKc6E8-NTnr~}9zA%`lL?6@&?88)3K6 zz{JEvB(T1|PKpBvcp%9;Z4YltyZE`?BBG1g@zc0IP2QLy+>;QnXBf!m^PrUojJ&Ai zJ(JM!X048=#WIR(RlNIF!_vwpv@9RGuF)Ba?nr8V0YRoHQQdcNYi1ZL59Ux@yaCIy z(Kao4FPfr5)#5U(186-c|XLA|dUytGZSU}kN z00cG-j|Alx@x;VM2U0|fx2N%Feg;EHj==f|_;oP9LDoj-b-}xJ_{mvtE|V72!$vxp z%_13((MZ6t8&J0IOK;)uGR)>5G>q4RwKxoj8b&!iFh`?xqcDaitd1?_|A>Ja#;hd?ZkP|Lwi-Gu2Ru)6vMqod>U zAss-bP%4#>%jFP@#bk*X^#o%Yy^H8jskDK8V+)1CB_f}Q7JHBa2K9BNQt2%nho)&5 g8yk}^@LvFb0dT?~9fQ_OEdT%j07*qoM6N<$g6+{+)c^nh literal 0 HcmV?d00001 diff --git a/ApplicationCode/Resources/ResInsight.qrc b/ApplicationCode/Resources/ResInsight.qrc index fe34b9b7f5..f92441653c 100644 --- a/ApplicationCode/Resources/ResInsight.qrc +++ b/ApplicationCode/Resources/ResInsight.qrc @@ -23,6 +23,7 @@ WellCollection.png octave.png OctaveScriptFile16x16.png + PythonScriptFile16x16.png Folder.png EclipseInput48x48.png Cases16x16.png diff --git a/Fwk/AppFwk/CommonCode/cafUtils.cpp b/Fwk/AppFwk/CommonCode/cafUtils.cpp index 04876063b8..f10bf8b3e2 100644 --- a/Fwk/AppFwk/CommonCode/cafUtils.cpp +++ b/Fwk/AppFwk/CommonCode/cafUtils.cpp @@ -80,18 +80,32 @@ QString Utils::absoluteFileName(const QString& fileName) return QDir::toNativeSeparators(fi.absoluteFilePath()); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QStringList Utils::getFilesInDirectory(const QString& dirPath, + const QString& nameFilter, + bool getAbsoluteFileNames) +{ + QStringList nameFilters; nameFilters << nameFilter; + return getFilesInDirectory(dirPath, nameFilters, getAbsoluteFileNames); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QStringList Utils::getFilesInDirectory(const QString& dirPath, const QString& filter, bool getAbsoluteFileNames) +QStringList Utils::getFilesInDirectory(const QString& dirPath, const QStringList& nameFilters, bool getAbsoluteFileNames) { QDir::SortFlags sortFlags = QDir::SortFlags(QDir::Name | QDir::IgnoreCase); // Only get files - QDir::Filters filters = QDir::Files; + QDir::Filters typeFilter = QDir::Files; - QDir dir(dirPath, filter, sortFlags, filters); + QDir dir(dirPath); + dir.setFilter(typeFilter); + dir.setNameFilters(nameFilters); + dir.setSorting(sortFlags); QFileInfoList fileInfoList = dir.entryInfoList(); @@ -110,7 +124,6 @@ QStringList Utils::getFilesInDirectory(const QString& dirPath, const QString& fi return retFileNames; } - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/Fwk/AppFwk/CommonCode/cafUtils.h b/Fwk/AppFwk/CommonCode/cafUtils.h index 5bef77dfee..51430951b1 100644 --- a/Fwk/AppFwk/CommonCode/cafUtils.h +++ b/Fwk/AppFwk/CommonCode/cafUtils.h @@ -56,7 +56,8 @@ public: static double editToDouble(QLineEdit* lineEdit, double defaultVal); static QString absoluteFileName(const QString& fileName); - static QStringList getFilesInDirectory(const QString& dirPath, const QString& filter, bool getAbsoluteFileNames); + static QStringList getFilesInDirectory(const QString& dirPath, const QString& nameFilter, bool getAbsoluteFileNames); + static QStringList getFilesInDirectory(const QString& dirPath, const QStringList& nameFilters, bool getAbsoluteFileNames); static QString constructFullFileName(const QString& folder, const QString& baseFileName, const QString& extension); static QString makeValidFileBasename(const QString& fileBasenameCandidate); From c1a89ec10e66dfb054c6dabfd9a9f49a29f9fae3 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Fri, 26 Jul 2019 16:25:04 +0200 Subject: [PATCH 248/396] #4522 Ensure ResInsight does not run if the setuid bit is set on the executable. * If you run a GUI-version this is likely to be checked anyway through Qt or GTK+ but not the console version. --- ApplicationCode/Application/RiaMain.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/ApplicationCode/Application/RiaMain.cpp b/ApplicationCode/Application/RiaMain.cpp index 18fefb4f09..d63188df3d 100644 --- a/ApplicationCode/Application/RiaMain.cpp +++ b/ApplicationCode/Application/RiaMain.cpp @@ -24,6 +24,11 @@ #include "cvfProgramOptions.h" #include "cvfqtUtils.h" +#ifndef WIN32 +#include +#include +#endif + RiaApplication* createApplication(int &argc, char *argv[]) { for (int i = 1; i < argc; ++i) @@ -38,6 +43,15 @@ RiaApplication* createApplication(int &argc, char *argv[]) int main(int argc, char *argv[]) { +#ifndef WIN32 + // From Qt 5.3 and onwards Qt has a mechanism for checking this automatically + // But it only checks user id not group id, so better to do it ourselves. + if (getuid() != geteuid() || getgid() != getegid()) + { + std::cerr << "FATAL: The application binary appears to be running setuid or setgid, this is a security hole." << std::endl; + return 1; + } +#endif RiaLogging::loggerInstance()->setLevel(RI_LL_DEBUG); std::unique_ptr app (createApplication(argc, argv)); From 783f4f5bb9a4e2f1ff1c892475d8b52333ceb3f4 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Fri, 26 Jul 2019 16:46:56 +0200 Subject: [PATCH 249/396] #4521 Fix build failure in RimGeoMechView.cpp * Include RiaLogging.h --- ApplicationCode/ProjectDataModel/RimGeoMechView.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/ApplicationCode/ProjectDataModel/RimGeoMechView.cpp b/ApplicationCode/ProjectDataModel/RimGeoMechView.cpp index fdc5c4f4bf..d46cc390a5 100644 --- a/ApplicationCode/ProjectDataModel/RimGeoMechView.cpp +++ b/ApplicationCode/ProjectDataModel/RimGeoMechView.cpp @@ -20,6 +20,7 @@ #include "RimGeoMechView.h" #include "RiaApplication.h" +#include "RiaLogging.h" #include "RiaPreferences.h" #include "RiaRegressionTestRunner.h" From acde63a7e0c8a2f5597ca004c4e3b112b9deb52a Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Sat, 27 Jul 2019 11:15:32 +0200 Subject: [PATCH 250/396] Fix build problem without GRPC enabled in RiaApplication.cpp --- ApplicationCode/Application/RiaApplication.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ApplicationCode/Application/RiaApplication.cpp b/ApplicationCode/Application/RiaApplication.cpp index a4ca703e96..44dcd93626 100644 --- a/ApplicationCode/Application/RiaApplication.cpp +++ b/ApplicationCode/Application/RiaApplication.cpp @@ -945,6 +945,7 @@ QString RiaApplication::pythonPath() const QProcessEnvironment RiaApplication::pythonProcessEnvironment() const { QProcessEnvironment penv = QProcessEnvironment::systemEnvironment(); +#ifdef ENABLE_GRPC penv.insert("RESINSIGHT_GRPC_PORT", QString("%1").arg(m_grpcServer->portNumber())); penv.insert("RESINSIGHT_EXECUTABLE", QCoreApplication::applicationFilePath()); @@ -958,7 +959,7 @@ QProcessEnvironment RiaApplication::pythonProcessEnvironment() const #endif penv.insert("PYTHONPATH", QString("%1;%2").arg(penv.value("PYTHONPATH")).arg(ripsLocations.join(";"))); - +#endif return penv; } From a20c56d21ded4de04835ac09136f57f1099934ef Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 30 Jul 2019 10:35:46 +0200 Subject: [PATCH 251/396] Python : Fix wrong casing --- ApplicationCode/GrpcInterface/Python/rips/Commands.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ApplicationCode/GrpcInterface/Python/rips/Commands.py b/ApplicationCode/GrpcInterface/Python/rips/Commands.py index 26a8a337de..aebab38b64 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Commands.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Commands.py @@ -192,7 +192,7 @@ class Commands: def exportWellPaths(self, wellPaths=[], mdStepSize=5.0): if isinstance(wellPaths, str): - wellPaths = [wellpaths] + wellPaths = [wellPaths] return self.__execute(exportWellPaths=Cmd.ExportWellPathRequest(wellPathNames=wellPaths, mdStepSize=mdStepSize)) def exportVisibleCells(self, caseId, viewName, exportKeyword='FLUXNUM', visibleActiveCellsValue=1, hiddenActiveCellsValue=0, inactiveCellsValue=0): From 6e76e043c62117829d3bc34724a97c73856fecf0 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 30 Jul 2019 10:36:06 +0200 Subject: [PATCH 252/396] Fix copyright header --- .../CommandFileInterface/RicfExportFlowCharacteristics.cpp | 2 +- .../CommandFileInterface/RicfExportFlowCharacteristics.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ApplicationCode/CommandFileInterface/RicfExportFlowCharacteristics.cpp b/ApplicationCode/CommandFileInterface/RicfExportFlowCharacteristics.cpp index d512081dc5..7155839ea6 100644 --- a/ApplicationCode/CommandFileInterface/RicfExportFlowCharacteristics.cpp +++ b/ApplicationCode/CommandFileInterface/RicfExportFlowCharacteristics.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2017 Statoil ASA +// Copyright (C) 2019- 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 diff --git a/ApplicationCode/CommandFileInterface/RicfExportFlowCharacteristics.h b/ApplicationCode/CommandFileInterface/RicfExportFlowCharacteristics.h index 37a510d0e2..8433636f1e 100644 --- a/ApplicationCode/CommandFileInterface/RicfExportFlowCharacteristics.h +++ b/ApplicationCode/CommandFileInterface/RicfExportFlowCharacteristics.h @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2017 Statoil ASA +// Copyright (C) 2019- 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 From b8f0fcd7e99190e9eac7a9a12cbe360b938569d9 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 30 Jul 2019 11:23:31 +0200 Subject: [PATCH 253/396] Flow Diag : Do not assert when tracername is not found --- ApplicationCode/ProjectDataModel/Flow/RimFlowDiagSolution.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/Flow/RimFlowDiagSolution.cpp b/ApplicationCode/ProjectDataModel/Flow/RimFlowDiagSolution.cpp index db8412da42..b5ee898fcb 100644 --- a/ApplicationCode/ProjectDataModel/Flow/RimFlowDiagSolution.cpp +++ b/ApplicationCode/ProjectDataModel/Flow/RimFlowDiagSolution.cpp @@ -309,8 +309,6 @@ RimFlowDiagSolution::TracerStatusType RimFlowDiagSolution::tracerStatusInTimeSte CVF_ASSERT(false); } } - - CVF_ASSERT(false); } return UNDEFINED; From e54d42a0da0b65ca58e1c2a55a83f845c52ba133 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 30 Jul 2019 11:27:25 +0200 Subject: [PATCH 254/396] #4527 Export Flow Characteristics : Add support for Python execution --- .../GrpcInterface/GrpcProtos/Commands.proto | 12 ++++++++++++ .../GrpcInterface/Python/rips/Commands.py | 14 ++++++++++++++ .../Python/rips/tests/test_commands.py | 10 +++++++++- 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto b/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto index e3794b8e18..b2c9d790c2 100644 --- a/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto +++ b/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto @@ -238,6 +238,17 @@ message CreateGridCaseGroupRequest repeated string casePaths = 1; } +message ExportFlowInfoRequest +{ + int32 caseId = 1; + repeated int32 timeSteps = 2; + repeated string injectors = 3; + repeated string producers = 4; + string fileName = 5; + double minimumCommunication = 6; + double aquiferCellThreshold = 7; +} + /* CommandParams handles both command name and parameters in one. * The message type and content is used as parameters and * the name of the variable is used to find the command name. */ @@ -276,6 +287,7 @@ message CommandParams CreateSatPressPlotRequest createSaturationPressurePlots = 25; ReplaceCaseRequests replaceMultipleCases = 26; CreateGridCaseGroupRequest createGridCaseGroup = 27; + ExportFlowInfoRequest exportFlowCharacteristics = 28; } } diff --git a/ApplicationCode/GrpcInterface/Python/rips/Commands.py b/ApplicationCode/GrpcInterface/Python/rips/Commands.py index aebab38b64..7a6c4f90c7 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Commands.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Commands.py @@ -267,3 +267,17 @@ class Commands: caseIds = [caseIds] return self.__execute(createSaturationPressurePlots=Cmd.CreateSatPressPlotRequest(caseIds=caseIds)) + def exportFlowCharacteristics(self, caseId, timeSteps, injectors, producers, fileName, minimumCommunication=0.0, aquiferCellThreshold=0.1): + if isinstance(timeSteps, int): + timeSteps = [timeSteps] + if isinstance(injectors, str): + injectors = [injectors] + if isinstance(producers, str): + producers = [producers] + return self.__execute(exportFlowCharacteristics=Cmd.ExportFlowInfoRequest(caseId=caseId, + timeSteps=timeSteps, + injectors=injectors, + producers=producers, + fileName=fileName, + minimumCommunication = minimumCommunication, + aquiferCellThreshold = aquiferCellThreshold)) diff --git a/ApplicationCode/GrpcInterface/Python/rips/tests/test_commands.py b/ApplicationCode/GrpcInterface/Python/rips/tests/test_commands.py index 4ee0611871..c5f88482fe 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/tests/test_commands.py +++ b/ApplicationCode/GrpcInterface/Python/rips/tests/test_commands.py @@ -41,4 +41,12 @@ def test_loadGridCaseGroup(rips_instance, initializeTest): casePaths.append(dataroot.PATH + "/Case_with_10_timesteps/Real0/BRUGGE_0000.EGRID") casePaths.append(dataroot.PATH + "/Case_with_10_timesteps/Real10/BRUGGE_0010.EGRID") groupId, groupName = rips_instance.commands.createGridCaseGroup(casePaths=casePaths) - print(groupId, groupName) \ No newline at end of file + print(groupId, groupName) + +def test_exportFlowCharacteristics(rips_instance, initializeTest): + casePath = dataroot.PATH + "/Case_with_10_timesteps/Real0/BRUGGE_0000.EGRID" + rips_instance.project.loadCase(casePath) + with tempfile.TemporaryDirectory(prefix="rips") as tmpdirname: + print("Temporary folder: ", tmpdirname) + fileName = tmpdirname + "/exportFlowChar.txt" + rips_instance.commands.exportFlowCharacteristics(caseId=0, timeSteps=8, producers=[], injectors = "I01", fileName = fileName) \ No newline at end of file From 4e33b7454f5baa27adcd7a765c8223065fbfce72 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 30 Jul 2019 11:55:13 +0200 Subject: [PATCH 255/396] Python : Avoid closing existing ResInsight when pytest is closing down --- ApplicationCode/GrpcInterface/Python/rips/tests/conftest.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ApplicationCode/GrpcInterface/Python/rips/tests/conftest.py b/ApplicationCode/GrpcInterface/Python/rips/tests/conftest.py index 996ea6688e..15d630729c 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/tests/conftest.py +++ b/ApplicationCode/GrpcInterface/Python/rips/tests/conftest.py @@ -34,5 +34,6 @@ def pytest_configure(config): print("Need a valid ResInsight executable to launch tests") exit(0) -def pytest_unconfigure(): - _rips_instance.app.exit() \ No newline at end of file +def pytest_unconfigure(config): + if not config.getoption('--existing'): + _rips_instance.app.exit() From beb6256f53eb61f77d547ac32ac386d7042a17e8 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Thu, 18 Jul 2019 16:01:11 +0200 Subject: [PATCH 256/396] Make it possible to edit case group statistics --- .../GrpcInterface/CMakeLists.cmake | 1 + .../GrpcInterface/Python/rips/PdmObject.py | 42 +++++++++++++++---- .../Python/rips/examples/CaseGridGroup.py | 15 ++++++- .../RimEclipseStatisticsCase.cpp | 35 ++++++++-------- .../RimIdenticalGridCaseGroup.cpp | 9 +++- 5 files changed, 73 insertions(+), 29 deletions(-) diff --git a/ApplicationCode/GrpcInterface/CMakeLists.cmake b/ApplicationCode/GrpcInterface/CMakeLists.cmake index d08c9c500a..d8bdf5ba40 100644 --- a/ApplicationCode/GrpcInterface/CMakeLists.cmake +++ b/ApplicationCode/GrpcInterface/CMakeLists.cmake @@ -169,6 +169,7 @@ if (PYTHON_EXECUTABLE) "rips/View.py" "rips/examples/InstanceExample.py" "rips/examples/CommandExample.py" + "rips/examples/CaseGridGroup.py" "rips/examples/CaseInfoStreamingExample.py" "rips/examples/SoilPorvAsync.py" "rips/examples/SoilPorvSync.py" diff --git a/ApplicationCode/GrpcInterface/Python/rips/PdmObject.py b/ApplicationCode/GrpcInterface/Python/rips/PdmObject.py index 56a52f0f3a..e19cb98980 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/PdmObject.py +++ b/ApplicationCode/GrpcInterface/Python/rips/PdmObject.py @@ -26,10 +26,9 @@ class PdmObject: listOfKeywords.append(keyword) return listOfKeywords - def getValue(self, keyword): - value = self.pb2Object.parameters[keyword] + def __toValue(self, value): if value.lower() == 'false': - return False + return False elif value.lower() == 'true': return True else: @@ -43,18 +42,43 @@ class PdmObject: except ValueError: # We may have a string. Strip internal start and end quotes value = value.strip('\"') + if self.__islist(value): + return self.__makelist(value) return value - - def setValue(self, keyword, value): + def __fromValue(self, value): if isinstance(value, bool): if value: - self.pb2Object.parameters[keyword] = "true" + return "true" else: - self.pb2Object.parameters[keyword] = "false" + return "false" + elif isinstance(value, list): + listofstrings = [] + for val in value: + listofstrings.append(self.__fromValue(val)) + return "[" + ", ".join(listofstrings) + "]" elif isinstance(value, str): - self.pb2Object.parameters[keyword] = "\"" + str(value) + "\"" + return "\"" + str(value) + "\"" else: - self.pb2Object.parameters[keyword] = str(value) + return str(value) + + def getValue(self, keyword): + value = self.pb2Object.parameters[keyword] + return self.__toValue(value) + + def __islist(self, value): + return value.startswith("[") and value.endswith("]") + + def __makelist(self, liststring): + liststring = liststring.lstrip("[") + liststring = liststring.rstrip("]") + strings = liststring.split(", ") + values = [] + for string in strings: + values.append(self.__toValue(string)) + return values + + def setValue(self, keyword, value): + self.pb2Object.parameters[keyword] = self.__fromValue(value) def descendants(self, classKeyword): request = PdmObject_pb2.PdmChildObjectRequest(object=self.pb2Object, child_keyword=classKeyword) diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/CaseGridGroup.py b/ApplicationCode/GrpcInterface/Python/rips/examples/CaseGridGroup.py index 5d080fbde8..4c3edd8580 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/examples/CaseGridGroup.py +++ b/ApplicationCode/GrpcInterface/Python/rips/examples/CaseGridGroup.py @@ -11,4 +11,17 @@ casePaths.append("../../../../TestModels/Case_with_10_timesteps/Real0/BRUGGE_000 casePaths.append("../../../../TestModels/Case_with_10_timesteps/Real10/BRUGGE_0010.EGRID") groupId, groupName = resInsight.commands.createGridCaseGroup(casePaths=casePaths) print("Group id = " + str(groupId)) -print("Group name = " + groupName) \ No newline at end of file +print("Group name = " + groupName) + +caseGroups = resInsight.project.descendants("RimIdenticalGridCaseGroup"); +for caseGroup in caseGroups: + print ("#### Case Group ####") + for kw in caseGroup.keywords(): + print (kw, caseGroup.getValue(kw)) + statCases = caseGroup.descendants("RimStatisticalCalculation") + for statCase in statCases: + print(" ## Stat Case ##") + for skw in statCase.keywords(): + print(" ", skw, statCase.getValue(skw)) + statCase.setValue("DynamicPropertiesToCalculate", statCase.getValue("DynamicPropertiesToCalculate") + ["SWAT"]) + statCase.update() \ No newline at end of file diff --git a/ApplicationCode/ProjectDataModel/RimEclipseStatisticsCase.cpp b/ApplicationCode/ProjectDataModel/RimEclipseStatisticsCase.cpp index 26d320dd5e..0c69545135 100644 --- a/ApplicationCode/ProjectDataModel/RimEclipseStatisticsCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimEclipseStatisticsCase.cpp @@ -20,6 +20,7 @@ #include "RimEclipseStatisticsCase.h" +#include "RicfCommandObject.h" #include "RicNewViewFeature.h" #include "RigCaseCellResultsData.h" @@ -73,20 +74,20 @@ RimEclipseStatisticsCase::RimEclipseStatisticsCase() m_selectionSummary.uiCapability()->setUiEditorTypeName(caf::PdmUiTextEditor::uiEditorTypeName()); m_selectionSummary.uiCapability()->setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN); - CAF_PDM_InitFieldNoDefault(&m_resultType, "ResultType", "Result Type", "", "", ""); + RICF_InitFieldNoDefault(&m_resultType, "ResultType", "Result Type", "", "", ""); m_resultType.xmlCapability()->setIOWritable(false); - CAF_PDM_InitFieldNoDefault(&m_porosityModel, "PorosityModel", "Porosity Model", "", "", ""); + RICF_InitFieldNoDefault(&m_porosityModel, "PorosityModel", "Porosity Model", "", "", ""); m_porosityModel.xmlCapability()->setIOWritable(false); - CAF_PDM_InitFieldNoDefault(&m_selectedDynamicProperties, "DynamicPropertiesToCalculate", "Dyn Prop", "", "", ""); - CAF_PDM_InitFieldNoDefault(&m_selectedStaticProperties, "StaticPropertiesToCalculate", "Stat Prop", "", "", ""); - CAF_PDM_InitFieldNoDefault(&m_selectedGeneratedProperties, "GeneratedPropertiesToCalculate", "", "", "", ""); - CAF_PDM_InitFieldNoDefault(&m_selectedInputProperties, "InputPropertiesToCalculate", "", "", "", ""); + RICF_InitFieldNoDefault(&m_selectedDynamicProperties, "DynamicPropertiesToCalculate", "Dyn Prop", "", "", ""); + RICF_InitFieldNoDefault(&m_selectedStaticProperties, "StaticPropertiesToCalculate", "Stat Prop", "", "", ""); + RICF_InitFieldNoDefault(&m_selectedGeneratedProperties, "GeneratedPropertiesToCalculate", "", "", "", ""); + RICF_InitFieldNoDefault(&m_selectedInputProperties, "InputPropertiesToCalculate", "", "", "", ""); - CAF_PDM_InitFieldNoDefault(&m_selectedFractureDynamicProperties, "FractureDynamicPropertiesToCalculate", "", "", "", ""); - CAF_PDM_InitFieldNoDefault(&m_selectedFractureStaticProperties, "FractureStaticPropertiesToCalculate", "", "", "", ""); - CAF_PDM_InitFieldNoDefault(&m_selectedFractureGeneratedProperties, "FractureGeneratedPropertiesToCalculate", "", "", "", ""); - CAF_PDM_InitFieldNoDefault(&m_selectedFractureInputProperties, "FractureInputPropertiesToCalculate", "", "", "", ""); + RICF_InitFieldNoDefault(&m_selectedFractureDynamicProperties, "FractureDynamicPropertiesToCalculate", "", "", "", ""); + RICF_InitFieldNoDefault(&m_selectedFractureStaticProperties, "FractureStaticPropertiesToCalculate", "", "", "", ""); + RICF_InitFieldNoDefault(&m_selectedFractureGeneratedProperties, "FractureGeneratedPropertiesToCalculate", "", "", "", ""); + RICF_InitFieldNoDefault(&m_selectedFractureInputProperties, "FractureInputPropertiesToCalculate", "", "", "", ""); m_selectedDynamicProperties.uiCapability()->setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN); m_selectedStaticProperties.uiCapability()->setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN); @@ -98,16 +99,16 @@ RimEclipseStatisticsCase::RimEclipseStatisticsCase() m_selectedFractureGeneratedProperties.uiCapability()->setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN); m_selectedFractureInputProperties.uiCapability()->setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN); - CAF_PDM_InitField(&m_calculatePercentiles, "CalculatePercentiles", true, "Calculate Percentiles", "", "", ""); - CAF_PDM_InitFieldNoDefault(&m_percentileCalculationType, "PercentileCalculationType", "Method", "", "", ""); + RICF_InitField(&m_calculatePercentiles, "CalculatePercentiles", true, "Calculate Percentiles", "", "", ""); + RICF_InitFieldNoDefault(&m_percentileCalculationType, "PercentileCalculationType", "Method", "", "", ""); - CAF_PDM_InitField(&m_lowPercentile, "LowPercentile", 10.0, "Low", "", "", ""); - CAF_PDM_InitField(&m_midPercentile, "MidPercentile", 50.0, "Mid", "", "", ""); - CAF_PDM_InitField(&m_highPercentile, "HighPercentile", 90.0, "High", "", "", ""); + RICF_InitField(&m_lowPercentile, "LowPercentile", 10.0, "Low", "", "", ""); + RICF_InitField(&m_midPercentile, "MidPercentile", 50.0, "Mid", "", "", ""); + RICF_InitField(&m_highPercentile, "HighPercentile", 90.0, "High", "", "", ""); - CAF_PDM_InitField(&m_wellDataSourceCase, "WellDataSourceCase", RiaDefines::undefinedResultName(), "Well Data Source Case", "", "", "" ); + RICF_InitField(&m_wellDataSourceCase, "WellDataSourceCase", RiaDefines::undefinedResultName(), "Well Data Source Case", "", "", "" ); - CAF_PDM_InitField(&m_useZeroAsInactiveCellValue, "UseZeroAsInactiveCellValue", false, "Use Zero as Inactive Cell Value", "", "", ""); + RICF_InitField(&m_useZeroAsInactiveCellValue, "UseZeroAsInactiveCellValue", false, "Use Zero as Inactive Cell Value", "", "", ""); m_populateSelectionAfterLoadingGrid = false; diff --git a/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp b/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp index 3814c4d701..626417e76e 100644 --- a/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp +++ b/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp @@ -23,6 +23,9 @@ #include "RiaGuiApplication.h" #include "RiaLogging.h" +#include "RicfCommandObject.h" + + #include "RigActiveCellInfo.h" #include "RigCaseCellResultsData.h" #include "RigEclipseCaseData.h" @@ -55,10 +58,12 @@ RimIdenticalGridCaseGroup::RimIdenticalGridCaseGroup() { CAF_PDM_InitObject("Grid Case Group", ":/GridCaseGroup16x16.png", "", ""); - CAF_PDM_InitField(&name, "UserDescription", QString("Grid Case Group"), "Name", "", "", ""); + RICF_InitField(&name, "UserDescription", QString("Grid Case Group"), "Name", "", "", ""); - CAF_PDM_InitField(&groupId, "GroupId", -1, "Case Group ID", "", "" ,""); + RICF_InitField(&groupId, "GroupId", -1, "Case Group ID", "", "" ,""); groupId.uiCapability()->setUiReadOnly(true); + groupId.capability()->setIOWriteable(false); + CAF_PDM_InitFieldNoDefault(&statisticsCaseCollection, "StatisticsCaseCollection", "statisticsCaseCollection ChildArrayField", "", "", ""); statisticsCaseCollection.uiCapability()->setUiHidden(true); From d9a0953b45a4f9319619863de464f20d0e81146f Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Fri, 19 Jul 2019 13:54:15 +0200 Subject: [PATCH 257/396] #4463 Added command for creating grid statistics --- .../CMakeLists_files.cmake | 2 + .../RicfCreateStatisticsCase.cpp | 77 +++++++++++++++++++ .../RicfCreateStatisticsCase.h | 52 +++++++++++++ .../GrpcInterface/GrpcProtos/Commands.proto | 22 +++++- .../GrpcInterface/GrpcProtos/PdmObject.proto | 20 ++++- .../GrpcInterface/Python/rips/Commands.py | 6 ++ .../GrpcInterface/Python/rips/PdmObject.py | 10 ++- .../Python/rips/examples/CaseGridGroup.py | 27 +++++-- .../GrpcInterface/RiaGrpcPdmObjectService.cpp | 67 +++++++++++++--- .../GrpcInterface/RiaGrpcPdmObjectService.h | 12 ++- .../GrpcInterface/RiaGrpcServiceInterface.cpp | 34 ++++++++ .../GrpcInterface/RiaGrpcServiceInterface.h | 2 + 12 files changed, 301 insertions(+), 30 deletions(-) create mode 100644 ApplicationCode/CommandFileInterface/RicfCreateStatisticsCase.cpp create mode 100644 ApplicationCode/CommandFileInterface/RicfCreateStatisticsCase.h diff --git a/ApplicationCode/CommandFileInterface/CMakeLists_files.cmake b/ApplicationCode/CommandFileInterface/CMakeLists_files.cmake index 7c1d653360..17f60f1f6e 100644 --- a/ApplicationCode/CommandFileInterface/CMakeLists_files.cmake +++ b/ApplicationCode/CommandFileInterface/CMakeLists_files.cmake @@ -30,6 +30,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RicfApplicationTools.h ${CMAKE_CURRENT_LIST_DIR}/RicfCreateSaturationPressurePlots.h ${CMAKE_CURRENT_LIST_DIR}/RicfExportFlowCharacteristics.h ${CMAKE_CURRENT_LIST_DIR}/RicfCreateGridCaseGroup.h +${CMAKE_CURRENT_LIST_DIR}/RicfCreateStatisticsCase.h ) set (SOURCE_GROUP_SOURCE_FILES @@ -63,6 +64,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RicfApplicationTools.cpp ${CMAKE_CURRENT_LIST_DIR}/RicfCreateSaturationPressurePlots.cpp ${CMAKE_CURRENT_LIST_DIR}/RicfExportFlowCharacteristics.cpp ${CMAKE_CURRENT_LIST_DIR}/RicfCreateGridCaseGroup.cpp +${CMAKE_CURRENT_LIST_DIR}/RicfCreateStatisticsCase.cpp ) list(APPEND CODE_HEADER_FILES diff --git a/ApplicationCode/CommandFileInterface/RicfCreateStatisticsCase.cpp b/ApplicationCode/CommandFileInterface/RicfCreateStatisticsCase.cpp new file mode 100644 index 0000000000..5d4988b5c2 --- /dev/null +++ b/ApplicationCode/CommandFileInterface/RicfCreateStatisticsCase.cpp @@ -0,0 +1,77 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- Statoil ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RicfCreateStatisticsCase.h" + +#include "RimCaseCollection.h" +#include "RimEclipseStatisticsCase.h" +#include "RimEclipseStatisticsCaseCollection.h" +#include "RimIdenticalGridCaseGroup.h" +#include "RimProject.h" + +#include "RiaApplication.h" +#include "Riu3DMainWindowTools.h" + +#include "cafSelectionManager.h" + +#include + +CAF_PDM_SOURCE_INIT(RicfCreateStatisticsCaseResult, "createStatisticsCaseResult"); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RicfCreateStatisticsCaseResult::RicfCreateStatisticsCaseResult(int caseId /*= -1*/) +{ + CAF_PDM_InitObject("statistics_case_result", "", "", ""); + CAF_PDM_InitField(&this->caseId, "caseId", caseId, "", "", "", ""); +} + +CAF_PDM_SOURCE_INIT(RicfCreateStatisticsCase, "createStatisticsCase"); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RicfCreateStatisticsCase::RicfCreateStatisticsCase() +{ + RICF_InitField(&m_caseGroupId, "caseGroupId", -1, "Case Group Id", "", "", ""); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RicfCommandResponse RicfCreateStatisticsCase::execute() +{ + RimProject* project = RiaApplication::instance()->project(); + + std::vector gridCaseGroups; + project->descendantsIncludingThisOfType(gridCaseGroups); + for (auto gridCaseGroup : gridCaseGroups) + { + if (gridCaseGroup->groupId() == m_caseGroupId()) + { + RimEclipseStatisticsCase* createdObject = gridCaseGroup->createAndAppendStatisticsCase(); + project->assignCaseIdToCase(createdObject); + gridCaseGroup->updateConnectedEditors(); + RicfCommandResponse response; + response.setResult(new RicfCreateStatisticsCaseResult(createdObject->caseId())); + return response; + } + } + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, "Could not find grid case group"); +} diff --git a/ApplicationCode/CommandFileInterface/RicfCreateStatisticsCase.h b/ApplicationCode/CommandFileInterface/RicfCreateStatisticsCase.h new file mode 100644 index 0000000000..d212318b9b --- /dev/null +++ b/ApplicationCode/CommandFileInterface/RicfCreateStatisticsCase.h @@ -0,0 +1,52 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 "RicfCommandObject.h" + +#include "cafPdmField.h" + +class RicfCreateStatisticsCaseResult : public caf::PdmObject +{ + CAF_PDM_HEADER_INIT; + +public: + RicfCreateStatisticsCaseResult(int caseId = -1); + +public: + caf::PdmField caseId; +}; + +//================================================================================================== +// +// +// +//================================================================================================== +class RicfCreateStatisticsCase : public RicfCommandObject +{ + CAF_PDM_HEADER_INIT; + +public: + RicfCreateStatisticsCase(); + + RicfCommandResponse execute() override; + +private: + caf::PdmField m_caseGroupId; +}; diff --git a/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto b/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto index b2c9d790c2..acb0909ece 100644 --- a/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto +++ b/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto @@ -238,6 +238,11 @@ message CreateGridCaseGroupRequest repeated string casePaths = 1; } +message CreateStatisticsCaseRequest +{ + int32 caseGroupId = 1; +} + message ExportFlowInfoRequest { int32 caseId = 1; @@ -287,7 +292,10 @@ message CommandParams CreateSatPressPlotRequest createSaturationPressurePlots = 25; ReplaceCaseRequests replaceMultipleCases = 26; CreateGridCaseGroupRequest createGridCaseGroup = 27; - ExportFlowInfoRequest exportFlowCharacteristics = 28; + CreateStatisticsCaseRequest createStatisticsCase = 28; + ExportFlowInfoRequest exportFlowCharacteristics = 29; + + } } @@ -297,15 +305,21 @@ message GridCaseGroupResult string groupName = 2; } +message CreateStatisticsCaseResult +{ + int32 caseId = 1; +} + /* Command reply handles the return values for the generic command * The name of the variable is used to map to the cafPdmObject classKeyword */ message CommandReply { oneof result { - Empty emptyResult = 1; - CaseRequest loadCaseResult = 2; - GridCaseGroupResult createGridCaseGroupResult = 3; + Empty emptyResult = 1; + CaseRequest loadCaseResult = 2; + GridCaseGroupResult createGridCaseGroupResult = 3; + CreateStatisticsCaseResult createStatisticsCaseResult = 4; } } diff --git a/ApplicationCode/GrpcInterface/GrpcProtos/PdmObject.proto b/ApplicationCode/GrpcInterface/GrpcProtos/PdmObject.proto index 5d1b150147..6d9a8ad709 100644 --- a/ApplicationCode/GrpcInterface/GrpcProtos/PdmObject.proto +++ b/ApplicationCode/GrpcInterface/GrpcProtos/PdmObject.proto @@ -6,16 +6,30 @@ package rips; service PdmObjectService { - rpc GetDescendantPdmObjects(PdmChildObjectRequest) returns (PdmObjectArray) {} + rpc GetDescendantPdmObjects(PdmDescendantObjectRequest) returns (PdmObjectArray) {} rpc GetChildPdmObjects(PdmChildObjectRequest) returns (PdmObjectArray) {} rpc GetAncestorPdmObject(PdmParentObjectRequest) returns (PdmObject) {} + rpc CreateChildPdmObject(CreatePdmChildObjectRequest) returns (PdmObject) {} rpc UpdateExistingPdmObject(PdmObject) returns (Empty) {} } +message PdmDescendantObjectRequest +{ + PdmObject object = 1; + string child_keyword = 2; +} + message PdmChildObjectRequest { - PdmObject object = 1; - string child_keyword = 2; + PdmObject object = 1; + string child_field = 2; +} + +message CreatePdmChildObjectRequest +{ + PdmObject object = 1; + string child_field = 2; + string child_class = 3; } message PdmParentObjectRequest diff --git a/ApplicationCode/GrpcInterface/Python/rips/Commands.py b/ApplicationCode/GrpcInterface/Python/rips/Commands.py index 7a6c4f90c7..c78713d548 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Commands.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Commands.py @@ -111,6 +111,12 @@ class Commands: assert(commandReply.HasField("createGridCaseGroupResult")) return (commandReply.createGridCaseGroupResult.groupId, commandReply.createGridCaseGroupResult.groupName) + def createStatisticsCase(self, caseGroupId): + commandReply = self.__execute(createStatisticsCase=Cmd.CreateStatisticsCaseRequest(caseGroupId=caseGroupId)) + assert(commandReply is not None) + assert(commandReply.HasField("createStatisticsCaseResult")) + return commandReply.createStatisticsCaseResult.caseId; + ################## # Export Commands ################## diff --git a/ApplicationCode/GrpcInterface/Python/rips/PdmObject.py b/ApplicationCode/GrpcInterface/Python/rips/PdmObject.py index e19cb98980..806525e0ab 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/PdmObject.py +++ b/ApplicationCode/GrpcInterface/Python/rips/PdmObject.py @@ -81,15 +81,15 @@ class PdmObject: self.pb2Object.parameters[keyword] = self.__fromValue(value) def descendants(self, classKeyword): - request = PdmObject_pb2.PdmChildObjectRequest(object=self.pb2Object, child_keyword=classKeyword) + request = PdmObject_pb2.PdmDescendantObjectRequest(object=self.pb2Object, child_keyword=classKeyword) objectList = self.pdmObjectStub.GetDescendantPdmObjects(request).objects childList = [] for object in objectList: childList.append(PdmObject(object, self.channel)) return childList - def children(self, classKeyword): - request = PdmObject_pb2.PdmChildObjectRequest(object=self.pb2Object, child_keyword=classKeyword) + def children(self, childField): + request = PdmObject_pb2.PdmChildObjectRequest(object=self.pb2Object, child_field=childField) objectList = self.pdmObjectStub.GetChildPdmObjects(request).objects childList = [] for object in objectList: @@ -102,3 +102,7 @@ class PdmObject: def update(self): self.pdmObjectStub.UpdateExistingPdmObject(self.pb2Object) + +# def createChild(self, childField, childClassKeyword): +# childRequest = PdmObject_pb2.CreatePdmChildObjectRequest(object=self.pb2Object, child_field=childField, child_class=childClassKeyword) +# return PdmObject(self.pdmObjectStub.CreateChildPdmObject(childRequest), self.channel) diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/CaseGridGroup.py b/ApplicationCode/GrpcInterface/Python/rips/examples/CaseGridGroup.py index 4c3edd8580..f4cf7bea64 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/examples/CaseGridGroup.py +++ b/ApplicationCode/GrpcInterface/Python/rips/examples/CaseGridGroup.py @@ -13,15 +13,28 @@ groupId, groupName = resInsight.commands.createGridCaseGroup(casePaths=casePaths print("Group id = " + str(groupId)) print("Group name = " + groupName) +caseId = resInsight.commands.createStatisticsCase(caseGroupId=groupId) + caseGroups = resInsight.project.descendants("RimIdenticalGridCaseGroup"); + +caseIds = [] for caseGroup in caseGroups: print ("#### Case Group ####") for kw in caseGroup.keywords(): print (kw, caseGroup.getValue(kw)) - statCases = caseGroup.descendants("RimStatisticalCalculation") - for statCase in statCases: - print(" ## Stat Case ##") - for skw in statCase.keywords(): - print(" ", skw, statCase.getValue(skw)) - statCase.setValue("DynamicPropertiesToCalculate", statCase.getValue("DynamicPropertiesToCalculate") + ["SWAT"]) - statCase.update() \ No newline at end of file + + for caseCollection in caseGroup.children("StatisticsCaseCollection"): + print (" ### Case Collection ###") + statCases = caseCollection.children("Reservoirs") + + for statCase in statCases: + print(" ## Stat Case ##") + for skw in statCase.keywords(): + print(" ", skw, statCase.getValue(skw)) + statCase.setValue("DynamicPropertiesToCalculate", statCase.getValue("DynamicPropertiesToCalculate") + ["SWAT"]) + statCase.update() + caseIds.append(statCase.getValue("CaseId")) + +print(caseIds) +resInsight.commands.computeCaseGroupStatistics(caseIds=caseIds) + \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/RiaGrpcPdmObjectService.cpp b/ApplicationCode/GrpcInterface/RiaGrpcPdmObjectService.cpp index ae696df503..1048b26947 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcPdmObjectService.cpp +++ b/ApplicationCode/GrpcInterface/RiaGrpcPdmObjectService.cpp @@ -65,8 +65,8 @@ grpc::Status RiaGrpcPdmObjectService::GetAncestorPdmObject(grpc::ServerContext* /// //-------------------------------------------------------------------------------------------------- grpc::Status RiaGrpcPdmObjectService::GetDescendantPdmObjects(grpc::ServerContext* context, - const rips::PdmChildObjectRequest* request, - rips::PdmObjectArray* reply) + const rips::PdmDescendantObjectRequest* request, + rips::PdmObjectArray* reply) { RimProject* project = RiaApplication::instance()->project(); std::vector objectsOfCurrentClass; @@ -119,14 +119,24 @@ grpc::Status RiaGrpcPdmObjectService::GetChildPdmObjects(grpc::ServerContext* if (matchingObject) { - std::vector childObjects; - matchingObject->childrenFromClassKeyword(QString::fromStdString(request->child_keyword()), childObjects); - for (auto pdmChild : childObjects) + QString fieldName = QString::fromStdString(request->child_field()); + std::vector fields; + matchingObject->fields(fields); + for (auto field : fields) { - rips::PdmObject* ripsChild = reply->add_objects(); - copyPdmObjectFromCafToRips(pdmChild, ripsChild); + if (field->keyword() == fieldName) + { + std::vector childObjects; + field->childObjects(&childObjects); + for (auto pdmChild : childObjects) + { + rips::PdmObject* ripsChild = reply->add_objects(); + copyPdmObjectFromCafToRips(static_cast(pdmChild), ripsChild); + } + return grpc::Status::OK; + } } - return grpc::Status::OK; + return grpc::Status(grpc::NOT_FOUND, "Child field not found"); } return grpc::Status(grpc::NOT_FOUND, "Current PdmObject not found"); } @@ -173,6 +183,44 @@ grpc::Status RiaGrpcPdmObjectService::UpdateExistingPdmObject(grpc::ServerContex return grpc::Status(grpc::NOT_FOUND, "PdmObject not found"); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +grpc::Status RiaGrpcPdmObjectService::CreateChildPdmObject(grpc::ServerContext* context, + const rips::CreatePdmChildObjectRequest* request, + rips::PdmObject* reply) +{ + RimProject* project = RiaApplication::instance()->project(); + std::vector objectsOfCurrentClass; + project->descendantsIncludingThisFromClassKeyword(QString::fromStdString(request->object().class_keyword()), + objectsOfCurrentClass); + + caf::PdmObject* matchingObject = nullptr; + for (caf::PdmObject* testObject : objectsOfCurrentClass) + { + if (reinterpret_cast(testObject) == request->object().address()) + { + matchingObject = testObject; + } + } + + if (matchingObject) + { + CAF_ASSERT(request); + + caf::PdmObject* pdmObject = emplaceChildArrayField(matchingObject, + QString::fromStdString(request->child_field()), + QString::fromStdString(request->child_class())); + if (pdmObject) + { + copyPdmObjectFromCafToRips(pdmObject, reply); + return grpc::Status::OK; + } + return grpc::Status(grpc::NOT_FOUND, "Could not create PdmObject"); + } + return grpc::Status(grpc::NOT_FOUND, "Could not find PdmObject"); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -182,9 +230,10 @@ std::vector RiaGrpcPdmObjectService::createCallbacks( return { new RiaGrpcUnaryCallback(this, &Self::GetAncestorPdmObject, &Self::RequestGetAncestorPdmObject), - new RiaGrpcUnaryCallback(this, &Self::GetDescendantPdmObjects, &Self::RequestGetDescendantPdmObjects), + new RiaGrpcUnaryCallback(this, &Self::GetDescendantPdmObjects, &Self::RequestGetDescendantPdmObjects), new RiaGrpcUnaryCallback(this, &Self::GetChildPdmObjects, &Self::RequestGetChildPdmObjects), new RiaGrpcUnaryCallback(this, &Self::UpdateExistingPdmObject, &Self::RequestUpdateExistingPdmObject), + new RiaGrpcUnaryCallback(this, &Self::CreateChildPdmObject, &Self::RequestCreateChildPdmObject) }; } diff --git a/ApplicationCode/GrpcInterface/RiaGrpcPdmObjectService.h b/ApplicationCode/GrpcInterface/RiaGrpcPdmObjectService.h index dfb5ad33cc..a919e9384a 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcPdmObjectService.h +++ b/ApplicationCode/GrpcInterface/RiaGrpcPdmObjectService.h @@ -35,12 +35,16 @@ public: grpc::Status GetAncestorPdmObject(grpc::ServerContext* context, const rips::PdmParentObjectRequest* request, rips::PdmObject* reply) override; - grpc::Status GetDescendantPdmObjects(grpc::ServerContext* context, - const rips::PdmChildObjectRequest* request, - rips::PdmObjectArray* reply); + grpc::Status GetDescendantPdmObjects(grpc::ServerContext* context, + const rips::PdmDescendantObjectRequest* request, + rips::PdmObjectArray* reply) override; grpc::Status GetChildPdmObjects(grpc::ServerContext* context, const rips::PdmChildObjectRequest* request, - rips::PdmObjectArray* reply); + rips::PdmObjectArray* reply) override; + + grpc::Status CreateChildPdmObject(grpc::ServerContext* context, + const rips::CreatePdmChildObjectRequest* request, + rips::PdmObject* reply) override; grpc::Status UpdateExistingPdmObject(grpc::ServerContext* context, const rips::PdmObject* request, rips::Empty* response) override; diff --git a/ApplicationCode/GrpcInterface/RiaGrpcServiceInterface.cpp b/ApplicationCode/GrpcInterface/RiaGrpcServiceInterface.cpp index 5fb52e367c..0a8f7a61f0 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcServiceInterface.cpp +++ b/ApplicationCode/GrpcInterface/RiaGrpcServiceInterface.cpp @@ -131,3 +131,37 @@ void RiaGrpcServiceInterface::assignFieldValue(const QString& stringValue, caf:: } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +caf::PdmObject* RiaGrpcServiceInterface::emplaceChildArrayField(caf::PdmObject* parent, const QString& fieldLabel, const QString& classKeyword) +{ + std::vector fields; + parent->fields(fields); + + QString childClassKeyword = classKeyword; + + for (auto field : fields) + { + auto pdmChildArrayField = dynamic_cast(field); + if (pdmChildArrayField && pdmChildArrayField->keyword() == fieldLabel) + { + if (childClassKeyword.isEmpty()) + { + childClassKeyword = pdmChildArrayField->xmlCapability()->childClassKeyword(); + } + + auto pdmObjectHandle = + caf::PdmDefaultObjectFactory::instance()->create(childClassKeyword); + caf::PdmObject* pdmObject = dynamic_cast(pdmObjectHandle); + CAF_ASSERT(pdmObject); + if (pdmObject) + { + pdmChildArrayField->insertAt(-1, pdmObject); + return pdmObject; + } + } + } + return nullptr; +} + diff --git a/ApplicationCode/GrpcInterface/RiaGrpcServiceInterface.h b/ApplicationCode/GrpcInterface/RiaGrpcServiceInterface.h index a4fecb2d28..3641a3f9a4 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcServiceInterface.h +++ b/ApplicationCode/GrpcInterface/RiaGrpcServiceInterface.h @@ -54,6 +54,8 @@ public: static void copyPdmObjectFromRipsToCaf(const rips::PdmObject* source, caf::PdmObject* destination); static void assignFieldValue(const QString& stringValue, caf::PdmValueField* field); + + static caf::PdmObject* emplaceChildArrayField(caf::PdmObject* parent, const QString& fieldLabel, const QString& classKeyword); }; #include "cafFactory.h" From 21a444fd702d7e42c2e47dd25667e1ae5f484b6a Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Mon, 29 Jul 2019 12:55:02 +0200 Subject: [PATCH 258/396] #4523 Add simplified interface for grid case group statistics --- .../RicfComputeCaseGroupStatistics.cpp | 16 ++++++- .../RicfComputeCaseGroupStatistics.h | 1 + .../GrpcInterface/CMakeLists.cmake | 1 + .../GrpcInterface/GrpcProtos/Commands.proto | 1 + .../GrpcInterface/Python/rips/Commands.py | 7 ++- .../Python/rips/GridCaseGroup.py | 48 +++++++++++++++++++ .../GrpcInterface/Python/rips/Project.py | 28 ++++++++++- .../Python/rips/examples/CaseGridGroup.py | 44 +++++++---------- 8 files changed, 114 insertions(+), 32 deletions(-) create mode 100644 ApplicationCode/GrpcInterface/Python/rips/GridCaseGroup.py diff --git a/ApplicationCode/CommandFileInterface/RicfComputeCaseGroupStatistics.cpp b/ApplicationCode/CommandFileInterface/RicfComputeCaseGroupStatistics.cpp index 02d7a3eb9b..2a40aa9683 100644 --- a/ApplicationCode/CommandFileInterface/RicfComputeCaseGroupStatistics.cpp +++ b/ApplicationCode/CommandFileInterface/RicfComputeCaseGroupStatistics.cpp @@ -37,6 +37,7 @@ CAF_PDM_SOURCE_INIT(RicfComputeCaseGroupStatistics, "computeCaseGroupStatistics" //-------------------------------------------------------------------------------------------------- RicfComputeCaseGroupStatistics::RicfComputeCaseGroupStatistics() { + RICF_InitField(&m_groupId, "caseGroupId", -1, "Case Group ID", "", "", ""); RICF_InitField(&m_caseIds, "caseIds", std::vector(), "Case IDs", "", "", ""); } @@ -47,7 +48,20 @@ RicfCommandResponse RicfComputeCaseGroupStatistics::execute() { RicfCommandResponse response; - for (int caseId : m_caseIds()) + std::vector caseIds = m_caseIds.v(); + + if (m_groupId() >= 0) + { + for (RimIdenticalGridCaseGroup* group : RiaApplication::instance()->project()->activeOilField()->analysisModels()->caseGroups) + { + for (RimEclipseCase* c : group->statisticsCaseCollection->reservoirs) + { + caseIds.push_back(c->caseId()); + } + } + } + + for (int caseId : caseIds) { bool foundCase = false; for (RimIdenticalGridCaseGroup* group : RiaApplication::instance()->project()->activeOilField()->analysisModels()->caseGroups) diff --git a/ApplicationCode/CommandFileInterface/RicfComputeCaseGroupStatistics.h b/ApplicationCode/CommandFileInterface/RicfComputeCaseGroupStatistics.h index a546676229..1536dce62b 100644 --- a/ApplicationCode/CommandFileInterface/RicfComputeCaseGroupStatistics.h +++ b/ApplicationCode/CommandFileInterface/RicfComputeCaseGroupStatistics.h @@ -37,5 +37,6 @@ public: RicfCommandResponse execute() override; private: + caf::PdmField< int > m_groupId; caf::PdmField< std::vector > m_caseIds; }; diff --git a/ApplicationCode/GrpcInterface/CMakeLists.cmake b/ApplicationCode/GrpcInterface/CMakeLists.cmake index d8bdf5ba40..2a97999a08 100644 --- a/ApplicationCode/GrpcInterface/CMakeLists.cmake +++ b/ApplicationCode/GrpcInterface/CMakeLists.cmake @@ -162,6 +162,7 @@ if (PYTHON_EXECUTABLE) "rips/Case.py" "rips/Commands.py" "rips/Grid.py" + "rips/GridCaseGroup.py" "rips/Project.py" "rips/Properties.py" "rips/Instance.py" diff --git a/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto b/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto index acb0909ece..eaf7335da6 100644 --- a/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto +++ b/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto @@ -168,6 +168,7 @@ message SetMainWindowSizeParams message ComputeCaseGroupStatRequest { repeated int32 caseIds = 1; + int32 caseGroupId = 2; } message SetTimeStepParams diff --git a/ApplicationCode/GrpcInterface/Python/rips/Commands.py b/ApplicationCode/GrpcInterface/Python/rips/Commands.py index c78713d548..5a385cf926 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Commands.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Commands.py @@ -223,10 +223,9 @@ class Commands: def setMainWindowSize(self, width, height): return self.__execute(setMainWindowSize=Cmd.SetMainWindowSizeParams(width=width, height=height)) - def computeCaseGroupStatistics(self, caseIds): - if isinstance(caseIds, int): - caseIds = [caseIds] - return self.__execute(computeCaseGroupStatistics=Cmd.ComputeCaseGroupStatRequest(caseIds=caseIds)) + def computeCaseGroupStatistics(self, caseIds = [], caseGroupId = -1): + return self.__execute(computeCaseGroupStatistics=Cmd.ComputeCaseGroupStatRequest(caseIds=caseIds, + caseGroupId=caseGroupId)) def setTimeStep(self, caseId, timeStep): return self.__execute(setTimeStep=Cmd.SetTimeStepParams(caseId=caseId, timeStep=timeStep)) diff --git a/ApplicationCode/GrpcInterface/Python/rips/GridCaseGroup.py b/ApplicationCode/GrpcInterface/Python/rips/GridCaseGroup.py new file mode 100644 index 0000000000..77b5842a65 --- /dev/null +++ b/ApplicationCode/GrpcInterface/Python/rips/GridCaseGroup.py @@ -0,0 +1,48 @@ +import grpc +import os +import sys +from .PdmObject import PdmObject +from .View import View + +sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'generated')) + +import PdmObject_pb2 + +class GridCaseGroup (PdmObject): + """ResInsight Grid Case Group class + + Operate on a ResInsight case group specified by a Case Group Id integer. + + Attributes: + id (int): Grid Case Group Id corresponding to case group Id in ResInsight project. + name (str): Case name + """ + def __init__(self, pdmObject): + self.groupId = pdmObject.getValue("GroupId") + PdmObject.__init__(self, pdmObject.pb2Object, pdmObject.channel) + + def statisticsCases(self): + statCaseCollection = self.children("StatisticsCaseCollection")[0] + return statCaseCollection.children("Reservoirs") + + def views(self): + """Get a list of views belonging to a grid case group""" + pbmObjects = self.descendants("ReservoirView") + viewList = [] + for pbmObject in pbmObjects: + viewList.append(View(pbmObject)) + return viewList + + def view(self, id): + """Get a particular view belonging to a case group by providing view id + Arguments: + id(int): view id + + Returns: a view object + + """ + views = self.views() + for viewObject in views: + if viewObject.id == id: + return viewObject + return None diff --git a/ApplicationCode/GrpcInterface/Python/rips/Project.py b/ApplicationCode/GrpcInterface/Python/rips/Project.py index 3882961564..76fedbb1e0 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Project.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Project.py @@ -4,6 +4,7 @@ import sys from .Case import Case from .Commands import Commands +from .GridCaseGroup import GridCaseGroup from .PdmObject import PdmObject from .View import View @@ -113,4 +114,29 @@ class Project (PdmObject): for viewObject in views: if viewObject.id == id: return viewObject - return None \ No newline at end of file + return None + + def gridCaseGroups(self): + caseGroups = self.descendants("RimIdenticalGridCaseGroup"); + + caseGroupList = [] + for pb2Group in caseGroups: + caseGroupList.append(GridCaseGroup(pb2Group)) + return caseGroupList + + def gridCaseGroup(self, groupId): + """Get a particular grid case group belonging to a project + Arguments: + groupId(int): group id + + Returns: a grid case group object + """ + caseGroups = self.gridCaseGroups() + for caseGroup in caseGroups: + if caseGroup.groupId == groupId: + return caseGroup + return None + + def createGridCaseGroup(self, casePaths): + groupId, groupName = Commands(self.channel).createGridCaseGroup(casePaths) + return self.gridCaseGroup(groupId) \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/CaseGridGroup.py b/ApplicationCode/GrpcInterface/Python/rips/examples/CaseGridGroup.py index f4cf7bea64..fa834c8026 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/examples/CaseGridGroup.py +++ b/ApplicationCode/GrpcInterface/Python/rips/examples/CaseGridGroup.py @@ -7,34 +7,26 @@ import rips resInsight = rips.Instance.find() casePaths = [] -casePaths.append("../../../../TestModels/Case_with_10_timesteps/Real0/BRUGGE_0000.EGRID") -casePaths.append("../../../../TestModels/Case_with_10_timesteps/Real10/BRUGGE_0010.EGRID") -groupId, groupName = resInsight.commands.createGridCaseGroup(casePaths=casePaths) -print("Group id = " + str(groupId)) -print("Group name = " + groupName) +casePaths.append("C:/Users/lindkvis/Projects/ResInsight/TestModels/Case_with_10_timesteps/Real0/BRUGGE_0000.EGRID") +casePaths.append("C:/Users/lindkvis/Projects/ResInsight/TestModels/Case_with_10_timesteps/Real10/BRUGGE_0010.EGRID") +for casePath in casePaths: + assert os.path.exists(casePath), "You need to set valid case paths for this script to work" -caseId = resInsight.commands.createStatisticsCase(caseGroupId=groupId) +caseGroup = resInsight.project.createGridCaseGroup(casePaths=casePaths) -caseGroups = resInsight.project.descendants("RimIdenticalGridCaseGroup"); +caseGroup.printObjectInfo() + +#statCases = caseGroup.statisticsCases() +#caseIds = [] +#for statCase in statCases: +# statCase.setValue("DynamicPropertiesToCalculate", ["SWAT"]) +# statCase.update() +# caseIds.append(statCase.getValue("CaseId")) -caseIds = [] -for caseGroup in caseGroups: - print ("#### Case Group ####") - for kw in caseGroup.keywords(): - print (kw, caseGroup.getValue(kw)) +resInsight.commands.computeCaseGroupStatistics(caseGroupId=caseGroup.groupId) - for caseCollection in caseGroup.children("StatisticsCaseCollection"): - print (" ### Case Collection ###") - statCases = caseCollection.children("Reservoirs") - - for statCase in statCases: - print(" ## Stat Case ##") - for skw in statCase.keywords(): - print(" ", skw, statCase.getValue(skw)) - statCase.setValue("DynamicPropertiesToCalculate", statCase.getValue("DynamicPropertiesToCalculate") + ["SWAT"]) - statCase.update() - caseIds.append(statCase.getValue("CaseId")) - -print(caseIds) -resInsight.commands.computeCaseGroupStatistics(caseIds=caseIds) +view = caseGroup.views()[0] +cellResult = view.cellResult() +cellResult.setValue("ResultVariable", "PRESSURE_DEV") +cellResult.update() \ No newline at end of file From 979101fe96cc676a8822e3458406ebf7d28b9d18 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Mon, 29 Jul 2019 13:00:07 +0200 Subject: [PATCH 259/396] #4526 Enable setting of flow diagnostics to cell results --- .../ProjectDataModel/RimEclipseResultDefinition.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.cpp b/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.cpp index b284f01a9a..7d34398e1a 100644 --- a/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.cpp +++ b/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.cpp @@ -111,17 +111,17 @@ RimEclipseResultDefinition::RimEclipseResultDefinition(caf::PdmUiItemInfo::Label CAF_PDM_InitFieldNoDefault(&m_selectedTracers_OBSOLETE, "SelectedTracers", "Tracers", "", "", ""); m_selectedTracers_OBSOLETE.uiCapability()->setUiHidden(true); - CAF_PDM_InitFieldNoDefault(&m_selectedInjectorTracers, "SelectedInjectorTracers", "Injector Tracers", "", "", ""); + RICF_InitFieldNoDefault(&m_selectedInjectorTracers, "SelectedInjectorTracers", "Injector Tracers", "", "", ""); m_selectedInjectorTracers.uiCapability()->setUiHidden(true); - CAF_PDM_InitFieldNoDefault(&m_selectedProducerTracers, "SelectedProducerTracers", "Producer Tracers", "", "", ""); + RICF_InitFieldNoDefault(&m_selectedProducerTracers, "SelectedProducerTracers", "Producer Tracers", "", "", ""); m_selectedProducerTracers.uiCapability()->setUiHidden(true); - CAF_PDM_InitFieldNoDefault(&m_selectedSouringTracers, "SelectedSouringTracers", "Tracers", "", "", ""); + RICF_InitFieldNoDefault(&m_selectedSouringTracers, "SelectedSouringTracers", "Tracers", "", "", ""); m_selectedSouringTracers.uiCapability()->setUiHidden(true); - CAF_PDM_InitFieldNoDefault(&m_flowTracerSelectionMode, "FlowTracerSelectionMode", "Tracers", "", "", ""); - CAF_PDM_InitFieldNoDefault(&m_phaseSelection, "PhaseSelection", "Phases", "", "", ""); + RICF_InitFieldNoDefault(&m_flowTracerSelectionMode, "FlowTracerSelectionMode", "Tracers", "", "", ""); + RICF_InitFieldNoDefault(&m_phaseSelection, "PhaseSelection", "Phases", "", "", ""); m_phaseSelection.uiCapability()->setUiLabelPosition(m_labelPosition); // Ui only fields From f61df01694eca8621e02f613292b400d9642ed88 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Tue, 30 Jul 2019 09:21:43 +0200 Subject: [PATCH 260/396] #4526 enable setting flow diagnostics results through Python --- .../Core/RicfFieldCapability.cpp | 44 ++++++++++++++----- .../Core/RicfFieldCapability.h | 34 +++++++------- .../Core/RicfFieldHandle.h | 7 ++- .../GrpcInterface/Python/rips/PdmObject.py | 2 - .../Python/rips/examples/SetCellResult.py | 14 ++++++ .../GrpcInterface/RiaGrpcServiceInterface.cpp | 4 +- 6 files changed, 70 insertions(+), 35 deletions(-) create mode 100644 ApplicationCode/GrpcInterface/Python/rips/examples/SetCellResult.py diff --git a/ApplicationCode/CommandFileInterface/Core/RicfFieldCapability.cpp b/ApplicationCode/CommandFileInterface/Core/RicfFieldCapability.cpp index 0b503b6496..d226852067 100644 --- a/ApplicationCode/CommandFileInterface/Core/RicfFieldCapability.cpp +++ b/ApplicationCode/CommandFileInterface/Core/RicfFieldCapability.cpp @@ -23,19 +23,29 @@ #include - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicfFieldReader::readFieldData(QString& fieldValue, QTextStream& inputStream, RicfMessages* errorMessageContainer) +void RicfFieldReader::readFieldData(QString& fieldValue, QTextStream& inputStream, RicfMessages* errorMessageContainer, bool stringsAreQuoted) { fieldValue = ""; errorMessageContainer->skipWhiteSpaceWithLineNumberCount(inputStream); QString accumulatedFieldValue; + QChar currentChar; - currentChar = errorMessageContainer->readCharWithLineNumberCount(inputStream); - if ( currentChar == QChar('"') ) + bool validStringStart = !stringsAreQuoted; + bool validStringEnd = !stringsAreQuoted; + if (stringsAreQuoted) + { + currentChar = errorMessageContainer->readCharWithLineNumberCount(inputStream); + if (currentChar == QChar('"')) + { + validStringStart = true; + } + } + + if (validStringStart) { while ( !inputStream.atEnd() ) { @@ -45,6 +55,7 @@ void RicfFieldReader::readFieldData(QString& fieldValue, QTextStream& i if ( currentChar == QChar('"') ) // End Quote { // Reached end of string + validStringEnd = true; break; } else @@ -59,7 +70,7 @@ void RicfFieldReader::readFieldData(QString& fieldValue, QTextStream& i } } } - else + if (!validStringStart) { // Unexpected start of string, Missing '"' // Error message @@ -68,6 +79,15 @@ void RicfFieldReader::readFieldData(QString& fieldValue, QTextStream& i + errorMessageContainer->currentCommand + "\"" ); // Could interpret as unquoted text } + else if (!validStringEnd) + { + // Unexpected end of string, Missing '"' + // Error message + errorMessageContainer->addError("String argument does not seem to be quoted. Missing the end '\"' in the \"" + + errorMessageContainer->currentArgument + "\" argument of the command: \"" + + errorMessageContainer->currentCommand + "\""); + // Could interpret as unquoted text + } fieldValue = accumulatedFieldValue; } @@ -75,7 +95,7 @@ void RicfFieldReader::readFieldData(QString& fieldValue, QTextStream& i //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicfFieldWriter::writeFieldData(const QString& fieldValue, QTextStream& outputStream) +void RicfFieldWriter::writeFieldData(const QString& fieldValue, QTextStream& outputStream, bool quoteStrings) { outputStream << "\""; for ( int i = 0; i < fieldValue.size(); ++i ) @@ -92,7 +112,7 @@ void RicfFieldWriter::writeFieldData(const QString& fieldValue, QTextSt //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicfFieldReader::readFieldData(bool& fieldValue, QTextStream& inputStream, RicfMessages* errorMessageContainer) +void RicfFieldReader::readFieldData(bool& fieldValue, QTextStream& inputStream, RicfMessages* errorMessageContainer, bool stringsAreQuoted) { errorMessageContainer->skipWhiteSpaceWithLineNumberCount(inputStream); QString accumulatedFieldValue; @@ -127,7 +147,7 @@ void RicfFieldReader::readFieldData(bool& fieldValue, QTextStream& inputSt //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicfFieldWriter::writeFieldData(const bool& fieldValue, QTextStream& outputStream) +void RicfFieldWriter::writeFieldData(const bool& fieldValue, QTextStream& outputStream, bool quoteStrings) { // Lower-case true/false is used in the documentation. outputStream << (fieldValue ? "true" : "false"); @@ -136,10 +156,10 @@ void RicfFieldWriter::writeFieldData(const bool& fieldValue, QTextStream& //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicfFieldReader::readFieldData(cvf::Color3f& fieldValue, QTextStream& inputStream, RicfMessages* errorMessageContainer) +void RicfFieldReader::readFieldData(cvf::Color3f& fieldValue, QTextStream& inputStream, RicfMessages* errorMessageContainer, bool stringsAreQuoted) { QString fieldStringValue; - RicfFieldReader::readFieldData(fieldStringValue, inputStream, errorMessageContainer); + RicfFieldReader::readFieldData(fieldStringValue, inputStream, errorMessageContainer, stringsAreQuoted); QColor qColor(fieldStringValue); if (qColor.isValid()) @@ -151,9 +171,9 @@ void RicfFieldReader::readFieldData(cvf::Color3f& fieldValue, QTex //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicfFieldWriter::writeFieldData(const cvf::Color3f& fieldValue, QTextStream& outputStream) +void RicfFieldWriter::writeFieldData(const cvf::Color3f& fieldValue, QTextStream& outputStream, bool quoteStrings) { QColor qColor = RiaColorTools::toQColor(fieldValue); QString fieldStringValue = qColor.name(); - RicfFieldWriter::writeFieldData(fieldStringValue, outputStream); + RicfFieldWriter::writeFieldData(fieldStringValue, outputStream, quoteStrings); } \ No newline at end of file diff --git a/ApplicationCode/CommandFileInterface/Core/RicfFieldCapability.h b/ApplicationCode/CommandFileInterface/Core/RicfFieldCapability.h index 7b4e454a8a..6b4964701c 100644 --- a/ApplicationCode/CommandFileInterface/Core/RicfFieldCapability.h +++ b/ApplicationCode/CommandFileInterface/Core/RicfFieldCapability.h @@ -32,7 +32,7 @@ template struct RicfFieldReader { - static void readFieldData(DataType & fieldValue, QTextStream& inputStream, RicfMessages* errorMessageContainer) + static void readFieldData(DataType & fieldValue, QTextStream& inputStream, RicfMessages* errorMessageContainer, bool stringsAreQuoted = true) { inputStream >> fieldValue; if (inputStream.status() == QTextStream::ReadCorruptData) @@ -49,7 +49,7 @@ struct RicfFieldReader template struct RicfFieldWriter { - static void writeFieldData(const DataType & fieldValue, QTextStream& outputStream) + static void writeFieldData(const DataType & fieldValue, QTextStream& outputStream, bool quoteStrings = true) { outputStream << fieldValue; } @@ -58,43 +58,43 @@ struct RicfFieldWriter template <> struct RicfFieldReader { - static void readFieldData(QString & fieldValue, QTextStream& inputStream, RicfMessages* errorMessageContainer); + static void readFieldData(QString & fieldValue, QTextStream& inputStream, RicfMessages* errorMessageContainer, bool stringsAreQuoted = true); }; template <> struct RicfFieldWriter { - static void writeFieldData(const QString & fieldValue, QTextStream& outputStream); + static void writeFieldData(const QString & fieldValue, QTextStream& outputStream, bool quoteStrings = true); }; template <> struct RicfFieldReader { - static void readFieldData(bool& fieldValue, QTextStream& inputStream, RicfMessages* errorMessageContainer); + static void readFieldData(bool& fieldValue, QTextStream& inputStream, RicfMessages* errorMessageContainer, bool stringsAreQuoted = true); }; template <> struct RicfFieldWriter { - static void writeFieldData(const bool& fieldValue, QTextStream& outputStream); + static void writeFieldData(const bool& fieldValue, QTextStream& outputStream, bool quoteStrings = true); }; template<> struct RicfFieldReader { - static void readFieldData(cvf::Color3f& fieldValue, QTextStream& inputStream, RicfMessages* errorMessageContainer); + static void readFieldData(cvf::Color3f& fieldValue, QTextStream& inputStream, RicfMessages* errorMessageContainer, bool stringsAreQuoted = true); }; template<> struct RicfFieldWriter { - static void writeFieldData(const cvf::Color3f& fieldValue, QTextStream& outputStream); + static void writeFieldData(const cvf::Color3f& fieldValue, QTextStream& outputStream, bool quoteStrings = true); }; template struct RicfFieldReader< caf::AppEnum > { - static void readFieldData(caf::AppEnum& fieldValue, QTextStream& inputStream, RicfMessages* errorMessageContainer) + static void readFieldData(caf::AppEnum& fieldValue, QTextStream& inputStream, RicfMessages* errorMessageContainer, bool stringsAreQuoted = true) { errorMessageContainer->skipWhiteSpaceWithLineNumberCount(inputStream); QString accumulatedFieldValue; @@ -127,7 +127,7 @@ struct RicfFieldReader< caf::AppEnum > template struct RicfFieldWriter< caf::AppEnum > { - static void writeFieldData(const caf::AppEnum& fieldValue, QTextStream& outputStream) + static void writeFieldData(const caf::AppEnum& fieldValue, QTextStream& outputStream, bool quoteStrings = true) { outputStream << fieldValue; } @@ -136,7 +136,7 @@ struct RicfFieldWriter< caf::AppEnum > template struct RicfFieldReader< std::vector > { - static void readFieldData(std::vector& fieldValue, QTextStream& inputStream, RicfMessages* errorMessageContainer) + static void readFieldData(std::vector& fieldValue, QTextStream& inputStream, RicfMessages* errorMessageContainer, bool stringsAreQuoted = true) { errorMessageContainer->skipWhiteSpaceWithLineNumberCount(inputStream); QChar chr = errorMessageContainer->readCharWithLineNumberCount(inputStream); @@ -157,7 +157,7 @@ struct RicfFieldReader< std::vector > } T value; - RicfFieldReader::readFieldData(value, inputStream, errorMessageContainer); + RicfFieldReader::readFieldData(value, inputStream, errorMessageContainer, true); fieldValue.push_back(value); } } @@ -172,7 +172,7 @@ struct RicfFieldReader< std::vector > template struct RicfFieldWriter< std::vector > { - static void writeFieldData(const std::vector& fieldValue, QTextStream& outputStream) + static void writeFieldData(const std::vector& fieldValue, QTextStream& outputStream, bool quoteStrings = true) { outputStream << "["; for (size_t i = 0; i < fieldValue.size(); ++i) @@ -202,10 +202,10 @@ public: // Xml Serializing public: - void readFieldData (QTextStream& inputStream, caf::PdmObjectFactory* objectFactory, RicfMessages* errorMessageContainer) override + void readFieldData (QTextStream& inputStream, caf::PdmObjectFactory* objectFactory, RicfMessages* errorMessageContainer, bool stringsAreQuoted = true) override { typename FieldType::FieldDataType value; - RicfFieldReader::readFieldData(value, inputStream, errorMessageContainer); + RicfFieldReader::readFieldData(value, inputStream, errorMessageContainer, stringsAreQuoted); if (this->isIOWriteable()) { @@ -213,9 +213,9 @@ public: } } - void writeFieldData(QTextStream& outputStream) const override + void writeFieldData(QTextStream& outputStream, bool quoteStrings = true) const override { - RicfFieldWriter::writeFieldData(m_field->value(), outputStream); + RicfFieldWriter::writeFieldData(m_field->value(), outputStream, quoteStrings); } private: diff --git a/ApplicationCode/CommandFileInterface/Core/RicfFieldHandle.h b/ApplicationCode/CommandFileInterface/Core/RicfFieldHandle.h index 3e48f984e5..7e25a40977 100644 --- a/ApplicationCode/CommandFileInterface/Core/RicfFieldHandle.h +++ b/ApplicationCode/CommandFileInterface/Core/RicfFieldHandle.h @@ -19,6 +19,8 @@ #pragma once #include "cafPdmFieldCapability.h" +#include + namespace caf { class PdmObjectFactory; @@ -52,8 +54,9 @@ public: virtual void readFieldData (QTextStream& inputStream, caf::PdmObjectFactory* objectFactory, - RicfMessages* errorMessageContainer ) = 0; - virtual void writeFieldData(QTextStream& outputStream) const = 0; + RicfMessages* errorMessageContainer, + bool stringsAreQuoted = true) = 0; + virtual void writeFieldData(QTextStream& outputStream, bool quoteStrings = true) const = 0; private: caf::PdmFieldHandle* m_owner; diff --git a/ApplicationCode/GrpcInterface/Python/rips/PdmObject.py b/ApplicationCode/GrpcInterface/Python/rips/PdmObject.py index 806525e0ab..ac7d9aac0a 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/PdmObject.py +++ b/ApplicationCode/GrpcInterface/Python/rips/PdmObject.py @@ -56,8 +56,6 @@ class PdmObject: for val in value: listofstrings.append(self.__fromValue(val)) return "[" + ", ".join(listofstrings) + "]" - elif isinstance(value, str): - return "\"" + str(value) + "\"" else: return str(value) diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/SetCellResult.py b/ApplicationCode/GrpcInterface/Python/rips/examples/SetCellResult.py new file mode 100644 index 0000000000..2414744387 --- /dev/null +++ b/ApplicationCode/GrpcInterface/Python/rips/examples/SetCellResult.py @@ -0,0 +1,14 @@ +import rips + +resInsight = rips.Instance.find() + +view = resInsight.project.view(0) + +cellResult = view.cellResult() + +cellResult.printObjectInfo() + +cellResult.setValue("ResultType", "FLOW_DIAGNOSTICS") +cellResult.setValue("ResultVariable", "TOF") + +cellResult.update() \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/RiaGrpcServiceInterface.cpp b/ApplicationCode/GrpcInterface/RiaGrpcServiceInterface.cpp index 0a8f7a61f0..935a521980 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcServiceInterface.cpp +++ b/ApplicationCode/GrpcInterface/RiaGrpcServiceInterface.cpp @@ -85,7 +85,7 @@ void RiaGrpcServiceInterface::copyPdmObjectFromCafToRips(const caf::PdmObject* s { QString text; QTextStream outStream(&text); - ricfHandle->writeFieldData(outStream); + ricfHandle->writeFieldData(outStream, false); (*parametersMap)[keyword.toStdString()] = text.toStdString(); } } @@ -127,7 +127,7 @@ void RiaGrpcServiceInterface::assignFieldValue(const QString& stringValue, caf:: { QTextStream stream(stringValue.toLatin1()); RicfMessages messages; - ricfHandle->readFieldData(stream, nullptr, &messages); + ricfHandle->readFieldData(stream, nullptr, &messages, false); } } From 7c30af62c2b08bdff03e6fcd959854a32f0b0e51 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Tue, 30 Jul 2019 10:36:05 +0200 Subject: [PATCH 261/396] #4528 #4512 Fix script-locations when loading project and remove initScriptDirectories() * Disable IO for scriptlocations and make sure we save it in preferences when editing * The next valid case Id stuff in initDirectories is irrelevant because it always runs on an empty project --- .../Application/RiaApplication.cpp | 3 +- .../RicEditPreferencesFeature.cpp | 1 - .../RicDeleteScriptPathFeature.cpp | 16 +-- .../ProjectDataModel/RimCalcScript.cpp | 4 +- .../ProjectDataModel/RimCalcScript.h | 1 - .../ProjectDataModel/RimProject.cpp | 98 +------------------ ApplicationCode/ProjectDataModel/RimProject.h | 1 - 7 files changed, 8 insertions(+), 116 deletions(-) diff --git a/ApplicationCode/Application/RiaApplication.cpp b/ApplicationCode/Application/RiaApplication.cpp index 44dcd93626..613610730c 100644 --- a/ApplicationCode/Application/RiaApplication.cpp +++ b/ApplicationCode/Application/RiaApplication.cpp @@ -1098,6 +1098,7 @@ void RiaApplication::applyPreferences(const RiaPreferences* oldPreferences) this->project()->setScriptDirectories(m_preferences->scriptDirectories()); this->project()->updateConnectedEditors(); } + caf::PdmSettings::writeFieldsToApplicationStore(m_preferences); } @@ -1382,7 +1383,7 @@ void RiaApplication::initialize() // Start with a project m_project = new RimProject; - m_project->initScriptDirectories(m_preferences->scriptDirectories()); + m_project->setScriptDirectories(m_preferences->scriptDirectories()); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/Commands/ApplicationCommands/RicEditPreferencesFeature.cpp b/ApplicationCode/Commands/ApplicationCommands/RicEditPreferencesFeature.cpp index 242f73c849..17845b47be 100644 --- a/ApplicationCode/Commands/ApplicationCommands/RicEditPreferencesFeature.cpp +++ b/ApplicationCode/Commands/ApplicationCommands/RicEditPreferencesFeature.cpp @@ -55,7 +55,6 @@ void RicEditPreferencesFeature::onActionTriggered(bool isChecked) if (propertyDialog.exec() == QDialog::Accepted) { // Write preferences using QSettings and apply them to the application - caf::PdmSettings::writeFieldsToApplicationStore(app->preferences()); app->applyPreferences(oldPreferences.get()); app->applyGuiPreferences(oldPreferences.get()); app->updateGrpcServer(); diff --git a/ApplicationCode/Commands/OctaveScriptCommands/RicDeleteScriptPathFeature.cpp b/ApplicationCode/Commands/OctaveScriptCommands/RicDeleteScriptPathFeature.cpp index fe5e2c6323..bba2f0f3d3 100644 --- a/ApplicationCode/Commands/OctaveScriptCommands/RicDeleteScriptPathFeature.cpp +++ b/ApplicationCode/Commands/OctaveScriptCommands/RicDeleteScriptPathFeature.cpp @@ -31,6 +31,7 @@ #include "cvfAssert.h" #include +#include CAF_CMD_SOURCE_INIT(RicDeleteScriptPathFeature, "RicDeleteScriptPathFeature"); @@ -55,18 +56,9 @@ void RicDeleteScriptPathFeature::onActionTriggered(bool isChecked) QString toBeRemoved = scriptCollection->directory; QString originalFilePathString = RiaApplication::instance()->preferences()->scriptDirectories(); - QString filePathString = originalFilePathString.remove(toBeRemoved); - - // Remove duplicate separators - QChar separator(';'); - QString regExpString = QString("%1{1,5}").arg(separator); - filePathString.replace(QRegExp(regExpString), separator); - - // Remove separator at end - if (filePathString.endsWith(separator)) - { - filePathString = filePathString.left(filePathString.size() - 1); - } + QStringList allFilePaths = originalFilePathString.split(';'); + allFilePaths.removeOne(toBeRemoved); + QString filePathString = allFilePaths.join(';'); RiaApplication::instance()->preferences()->scriptDirectories = filePathString; RiaApplication::instance()->applyPreferences(); diff --git a/ApplicationCode/ProjectDataModel/RimCalcScript.cpp b/ApplicationCode/ProjectDataModel/RimCalcScript.cpp index 2fe0ee41e4..e48d7b39a7 100644 --- a/ApplicationCode/ProjectDataModel/RimCalcScript.cpp +++ b/ApplicationCode/ProjectDataModel/RimCalcScript.cpp @@ -37,9 +37,7 @@ RimCalcScript::RimCalcScript() CAF_PDM_InitObject("CalcScript", ":/OctaveScriptFile16x16.png", "Calc Script", ""); CAF_PDM_InitField(&absoluteFileName, "AbsolutePath", QString(), "Location", "", "", ""); - CAF_PDM_InitField(&content, "Content", QString(), "Directory", "", "", ""); - RiaFieldhandleTools::disableWriteAndSetFieldHidden(&content); - + absoluteFileName.uiCapability()->setUiEditorTypeName(caf::PdmUiFilePathEditor::uiEditorTypeName()); } diff --git a/ApplicationCode/ProjectDataModel/RimCalcScript.h b/ApplicationCode/ProjectDataModel/RimCalcScript.h index f477fa2ee1..ca6d794ad6 100644 --- a/ApplicationCode/ProjectDataModel/RimCalcScript.h +++ b/ApplicationCode/ProjectDataModel/RimCalcScript.h @@ -46,7 +46,6 @@ public: static QStringList createCommandLineArguments(const QString& absoluteFileNameScript); caf::PdmField absoluteFileName; - caf::PdmField content; // TODO: Obsolete field, can be deleted on next project file revision. protected: void defineUiTreeOrdering(caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName = "") override; diff --git a/ApplicationCode/ProjectDataModel/RimProject.cpp b/ApplicationCode/ProjectDataModel/RimProject.cpp index ed4a300727..371ca23b70 100644 --- a/ApplicationCode/ProjectDataModel/RimProject.cpp +++ b/ApplicationCode/ProjectDataModel/RimProject.cpp @@ -117,6 +117,7 @@ RimProject::RimProject(void) CAF_PDM_InitFieldNoDefault(&scriptCollection, "ScriptCollection", "Octave Scripts", ":/octave.png", "", ""); scriptCollection.uiCapability()->setUiHidden(true); + scriptCollection.xmlCapability()->disableIO(); CAF_PDM_InitFieldNoDefault(&wellPathImport, "WellPathImport", "WellPathImport", "", "", ""); wellPathImport = new RimWellPathImport(); @@ -238,103 +239,6 @@ void RimProject::close() plotWindowTreeViewState = ""; } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimProject::initScriptDirectories(const QString& scriptDirectories) -{ - // - // TODO : Must store content of scripts in project file and notify user if stored content is different from disk on execute and edit - // - this->setScriptDirectories(scriptDirectories); - - // Find largest used caseId read from file and make sure all cases have a valid caseId - { - int largestCaseId = -1; - - std::vector cases; - allCases(cases); - - for (size_t i = 0; i < cases.size(); i++) - { - if (cases[i]->caseId > largestCaseId) - { - largestCaseId = cases[i]->caseId; - } - } - - if (largestCaseId > this->nextValidCaseId) - { - this->nextValidCaseId = largestCaseId + 1; - } - - // Assign case Id to cases with an invalid case Id - for (size_t i = 0; i < cases.size(); i++) - { - if (cases[i]->caseId < 0) - { - assignCaseIdToCase(cases[i]); - } - } - } - - // Find largest used groupId read from file and make sure all groups have a valid groupId - RimEclipseCaseCollection* analysisModels = activeOilField() ? activeOilField()->analysisModels() : nullptr; - if (analysisModels) - { - int largestGroupId = -1; - - for (size_t i = 0; i < analysisModels->caseGroups().size(); i++) - { - RimIdenticalGridCaseGroup* cg = analysisModels->caseGroups()[i]; - - if (cg->groupId > largestGroupId) - { - largestGroupId = cg->groupId; - } - } - - if (largestGroupId > this->nextValidCaseGroupId) - { - this->nextValidCaseGroupId = largestGroupId + 1; - } - - // Assign group Id to groups with an invalid Id - for (size_t i = 0; i < analysisModels->caseGroups().size(); i++) - { - RimIdenticalGridCaseGroup* cg = analysisModels->caseGroups()[i]; - - if (cg->groupId < 0) - { - assignIdToCaseGroup(cg); - } - } - } - - int maxViewId = -1; - std::vector views; - this->descendantsIncludingThisOfType(views); - for (Rim3dView* view : views) - { - maxViewId = std::max(maxViewId, view->id()); - } - - if (maxViewId >= this->nextValidViewId) - { - this->nextValidViewId = maxViewId + 1; - } - - // Assign view id to views with invalid id - for (Rim3dView* view : views) - { - if (view->id() < 0) - { - assignViewIdToView(view); - } - } -} - - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimProject.h b/ApplicationCode/ProjectDataModel/RimProject.h index 20761ad898..ec616a302a 100644 --- a/ApplicationCode/ProjectDataModel/RimProject.h +++ b/ApplicationCode/ProjectDataModel/RimProject.h @@ -105,7 +105,6 @@ public: caf::PdmField plotWindowCurrentModelIndexPath; void setScriptDirectories(const QString& scriptDirectories); - void initScriptDirectories(const QString& scriptDirectories); QString projectFileVersionString() const; bool isProjectFileVersionEqualOrOlderThan(const QString& otherProjectFileVersion) const; From 92bc71d934bf6a295b583c70e0e4b6c66b1bf603 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Tue, 30 Jul 2019 11:19:26 +0200 Subject: [PATCH 262/396] #4528 Fix script paths and adding new scripts --- .../CMakeLists_files.cmake | 6 +- ...ture.cpp => RicNewOctaveScriptFeature.cpp} | 24 ++- ...tFeature.h => RicNewOctaveScriptFeature.h} | 2 +- .../RicNewPythonScriptFeature.cpp | 155 ++++++++++++++++++ .../RicNewPythonScriptFeature.h | 37 +++++ .../RimContextCommandBuilder.cpp | 10 +- 6 files changed, 222 insertions(+), 12 deletions(-) rename ApplicationCode/Commands/OctaveScriptCommands/{RicNewScriptFeature.cpp => RicNewOctaveScriptFeature.cpp} (84%) rename ApplicationCode/Commands/OctaveScriptCommands/{RicNewScriptFeature.h => RicNewOctaveScriptFeature.h} (95%) create mode 100644 ApplicationCode/Commands/OctaveScriptCommands/RicNewPythonScriptFeature.cpp create mode 100644 ApplicationCode/Commands/OctaveScriptCommands/RicNewPythonScriptFeature.h diff --git a/ApplicationCode/Commands/OctaveScriptCommands/CMakeLists_files.cmake b/ApplicationCode/Commands/OctaveScriptCommands/CMakeLists_files.cmake index dc59b75adc..1c110b0e32 100644 --- a/ApplicationCode/Commands/OctaveScriptCommands/CMakeLists_files.cmake +++ b/ApplicationCode/Commands/OctaveScriptCommands/CMakeLists_files.cmake @@ -5,7 +5,8 @@ ${CMAKE_CURRENT_LIST_DIR}/RicDeleteScriptPathFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicEditScriptFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicExecuteScriptFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicExecuteScriptForCasesFeature.h -${CMAKE_CURRENT_LIST_DIR}/RicNewScriptFeature.h +${CMAKE_CURRENT_LIST_DIR}/RicNewOctaveScriptFeature.h +${CMAKE_CURRENT_LIST_DIR}/RicNewPythonScriptFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicScriptFeatureImpl.h ${CMAKE_CURRENT_LIST_DIR}/RicRefreshScriptsFeature.h ) @@ -16,7 +17,8 @@ ${CMAKE_CURRENT_LIST_DIR}/RicDeleteScriptPathFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicEditScriptFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicExecuteScriptFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicExecuteScriptForCasesFeature.cpp -${CMAKE_CURRENT_LIST_DIR}/RicNewScriptFeature.cpp +${CMAKE_CURRENT_LIST_DIR}/RicNewOctaveScriptFeature.cpp +${CMAKE_CURRENT_LIST_DIR}/RicNewPythonScriptFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicScriptFeatureImpl.cpp ${CMAKE_CURRENT_LIST_DIR}/RicRefreshScriptsFeature.cpp ) diff --git a/ApplicationCode/Commands/OctaveScriptCommands/RicNewScriptFeature.cpp b/ApplicationCode/Commands/OctaveScriptCommands/RicNewOctaveScriptFeature.cpp similarity index 84% rename from ApplicationCode/Commands/OctaveScriptCommands/RicNewScriptFeature.cpp rename to ApplicationCode/Commands/OctaveScriptCommands/RicNewOctaveScriptFeature.cpp index 7864db945d..91422940ab 100644 --- a/ApplicationCode/Commands/OctaveScriptCommands/RicNewScriptFeature.cpp +++ b/ApplicationCode/Commands/OctaveScriptCommands/RicNewOctaveScriptFeature.cpp @@ -17,7 +17,7 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RicNewScriptFeature.h" +#include "RicNewOctaveScriptFeature.h" #include "RiaApplication.h" @@ -38,20 +38,30 @@ #include #include -CAF_CMD_SOURCE_INIT(RicNewScriptFeature, "RicNewScriptFeature"); +CAF_CMD_SOURCE_INIT(RicNewOctaveScriptFeature, "RicNewOctaveScriptFeature"); //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool RicNewScriptFeature::isCommandEnabled() +bool RicNewOctaveScriptFeature::isCommandEnabled() { - return true; + std::vector calcScripts = RicScriptFeatureImpl::selectedScripts(); + std::vector calcScriptCollections = RicScriptFeatureImpl::selectedScriptCollections(); + if (calcScripts.size() == 1u && calcScripts.front()->scriptType() == RimCalcScript::OCTAVE) + { + return true; + } + else if (calcScriptCollections.size() == 1u && !calcScriptCollections.front()->directory().isEmpty()) + { + return true; + } + return false; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicNewScriptFeature::onActionTriggered(bool isChecked) +void RicNewOctaveScriptFeature::onActionTriggered(bool isChecked) { std::vector calcScripts = RicScriptFeatureImpl::selectedScripts(); std::vector calcScriptCollections = RicScriptFeatureImpl::selectedScriptCollections(); @@ -132,7 +142,7 @@ void RicNewScriptFeature::onActionTriggered(bool isChecked) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicNewScriptFeature::setupActionLook(QAction* actionToSetup) +void RicNewOctaveScriptFeature::setupActionLook(QAction* actionToSetup) { - actionToSetup->setText("New"); + actionToSetup->setText("New Octave Script"); } diff --git a/ApplicationCode/Commands/OctaveScriptCommands/RicNewScriptFeature.h b/ApplicationCode/Commands/OctaveScriptCommands/RicNewOctaveScriptFeature.h similarity index 95% rename from ApplicationCode/Commands/OctaveScriptCommands/RicNewScriptFeature.h rename to ApplicationCode/Commands/OctaveScriptCommands/RicNewOctaveScriptFeature.h index 24e2194bb8..bb0f9484ec 100644 --- a/ApplicationCode/Commands/OctaveScriptCommands/RicNewScriptFeature.h +++ b/ApplicationCode/Commands/OctaveScriptCommands/RicNewOctaveScriptFeature.h @@ -26,7 +26,7 @@ //================================================================================================== /// //================================================================================================== -class RicNewScriptFeature : public caf::CmdFeature +class RicNewOctaveScriptFeature : public caf::CmdFeature { CAF_CMD_HEADER_INIT; diff --git a/ApplicationCode/Commands/OctaveScriptCommands/RicNewPythonScriptFeature.cpp b/ApplicationCode/Commands/OctaveScriptCommands/RicNewPythonScriptFeature.cpp new file mode 100644 index 0000000000..4a47ad2dbd --- /dev/null +++ b/ApplicationCode/Commands/OctaveScriptCommands/RicNewPythonScriptFeature.cpp @@ -0,0 +1,155 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- Equinor ASA +// Copyright (C) 2015- Ceetron Solutions AS +// +// 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 "RicNewPythonScriptFeature.h" + +#include "RiaApplication.h" + +#include "RicRefreshScriptsFeature.h" +#include "RicScriptFeatureImpl.h" + +#include "RimCalcScript.h" +#include "RimScriptCollection.h" + +#include "Riu3DMainWindowTools.h" +#include "RiuTools.h" + +#include "cafUtils.h" + +#include +#include +#include +#include +#include + +CAF_CMD_SOURCE_INIT(RicNewPythonScriptFeature, "RicNewPythonScriptFeature"); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RicNewPythonScriptFeature::isCommandEnabled() +{ + std::vector calcScripts = RicScriptFeatureImpl::selectedScripts(); + std::vector calcScriptCollections = RicScriptFeatureImpl::selectedScriptCollections(); + if (calcScripts.size() == 1u && calcScripts.front()->scriptType() == RimCalcScript::PYTHON) + { + return true; + } + else if (calcScriptCollections.size() == 1u && !calcScriptCollections.front()->directory().isEmpty()) + { + return true; + } + return false; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicNewPythonScriptFeature::onActionTriggered(bool isChecked) +{ + std::vector calcScripts = RicScriptFeatureImpl::selectedScripts(); + std::vector calcScriptCollections = RicScriptFeatureImpl::selectedScriptCollections(); + + RimCalcScript* calcScript = calcScripts.size() > 0 ? calcScripts[0] : nullptr; + RimScriptCollection* scriptColl = calcScriptCollections.size() > 0 ? calcScriptCollections[0] : nullptr; + + QString fullPathNewScript; + + if (calcScript) + { + QFileInfo existingScriptFileInfo(calcScript->absoluteFileName()); + fullPathNewScript = existingScriptFileInfo.absolutePath(); + } + else if (scriptColl) + { + fullPathNewScript = scriptColl->directory(); + } + else + { + return; + } + + QString fullPathFilenameNewScript; + + fullPathFilenameNewScript = fullPathNewScript + "/untitled.py"; + int num = 1; + while (caf::Utils::fileExists(fullPathFilenameNewScript)) + { + fullPathFilenameNewScript = fullPathNewScript + "/untitled" + QString::number(num) + ".py"; + num++; + } + + bool ok; + fullPathFilenameNewScript = QInputDialog::getText(nullptr, + "Specify new script file", + "File name", + QLineEdit::Normal, + fullPathFilenameNewScript, + &ok, + RiuTools::defaultDialogFlags()); + + if (ok && !fullPathFilenameNewScript.isEmpty()) + { + QFile file(fullPathFilenameNewScript); + if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) + { + QMessageBox::warning( + Riu3DMainWindowTools::mainWindowWidget(), "Script editor", "Failed to create file\n" + fullPathFilenameNewScript); + + return; + } + + RicRefreshScriptsFeature::refreshScriptFolders(); + + if (calcScript) + { + Riu3DMainWindowTools::selectAsCurrentItem(calcScript); + } + + RiaApplication* app = RiaApplication::instance(); + QString scriptEditor = app->scriptEditorPath(); + if (!scriptEditor.isEmpty()) + { + QStringList arguments; + arguments << fullPathFilenameNewScript; + + QProcess* myProcess = new QProcess(this); + myProcess->start(scriptEditor, arguments); + + if (!myProcess->waitForStarted(1000)) + { + QMessageBox::warning(Riu3DMainWindowTools::mainWindowWidget(), + "Script editor", + "Failed to start script editor executable\n" + scriptEditor); + } + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicNewPythonScriptFeature::setupActionLook(QAction* actionToSetup) +{ + actionToSetup->setText("New Python Script"); +} + + + + diff --git a/ApplicationCode/Commands/OctaveScriptCommands/RicNewPythonScriptFeature.h b/ApplicationCode/Commands/OctaveScriptCommands/RicNewPythonScriptFeature.h new file mode 100644 index 0000000000..2010c5553c --- /dev/null +++ b/ApplicationCode/Commands/OctaveScriptCommands/RicNewPythonScriptFeature.h @@ -0,0 +1,37 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 + +//================================================================================================== +/// +//================================================================================================== +class RicNewPythonScriptFeature : public caf::CmdFeature +{ + CAF_CMD_HEADER_INIT; + +protected: + // Overrides + bool isCommandEnabled() override; + void onActionTriggered(bool isChecked) override; + void setupActionLook(QAction* actionToSetup) override; +}; diff --git a/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp b/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp index 7b6addfef3..21c580bbf6 100644 --- a/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp +++ b/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp @@ -427,13 +427,19 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection() { menuBuilder << "RicEditScriptFeature"; menuBuilder << "Separator"; - menuBuilder << "RicNewScriptFeature"; + menuBuilder << "RicNewOctaveScriptFeature"; +#ifdef ENABLE_GRPC + menuBuilder << "RicNewPythonScriptFeature"; +#endif menuBuilder << "Separator"; menuBuilder << "RicExecuteScriptFeature"; } else if (dynamic_cast(uiItem)) { - menuBuilder << "RicNewScriptFeature"; + menuBuilder << "RicNewOctaveScriptFeature"; +#ifdef ENABLE_GRPC + menuBuilder << "RicNewPythonScriptFeature"; +#endif menuBuilder << "Separator"; menuBuilder << "RicAddScriptPathFeature"; menuBuilder << "RicRefreshScriptsFeature"; From 7fcb1afe6c65371b0d65f753f2f1bbbc41a5158b Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Tue, 30 Jul 2019 11:29:20 +0200 Subject: [PATCH 263/396] Python: Move gRPC settings into Python group and rename UI items to remove gRPC-terminology --- ApplicationCode/Application/RiaPreferences.cpp | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/ApplicationCode/Application/RiaPreferences.cpp b/ApplicationCode/Application/RiaPreferences.cpp index e5363704f9..4613f1da5b 100644 --- a/ApplicationCode/Application/RiaPreferences.cpp +++ b/ApplicationCode/Application/RiaPreferences.cpp @@ -51,8 +51,8 @@ RiaPreferences::RiaPreferences(void) { CAF_PDM_InitField(&navigationPolicy, "navigationPolicy", caf::AppEnum(RiaGuiApplication::NAVIGATION_POLICY_RMS), "Navigation Mode", "", "", ""); - CAF_PDM_InitField(&enableGrpcServer, "enableGrpcServer", true, "Enable gRPC script server", "", "Remote Procedure Call Scripting Engine", ""); - CAF_PDM_InitField(&defaultGrpcPortNumber, "defaultGrpcPort", 50051, "Default gRPC port", "", "", ""); + CAF_PDM_InitField(&enableGrpcServer, "enableGrpcServer", true, "Enable Python Script Server", "", "Remote Procedure Call Scripting Engine", ""); + CAF_PDM_InitField(&defaultGrpcPortNumber, "defaultGrpcPort", 50051, "Default Python Script Server Port", "", "", ""); CAF_PDM_InitFieldNoDefault(&scriptDirectories, "scriptDirectory", "Shared Script Folder(s)", "", "", ""); scriptDirectories.uiCapability()->setUiEditorTypeName(caf::PdmUiFilePathEditor::uiEditorTypeName()); @@ -267,19 +267,16 @@ void RiaPreferences::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& } else if (uiConfigName == m_tabNames[2]) { -#ifdef ENABLE_GRPC - caf::PdmUiGroup* grpcGroup = uiOrdering.addNewGroup("gRPC Server"); - grpcGroup->add(&enableGrpcServer); - grpcGroup->add(&defaultGrpcPortNumber); -#endif - caf::PdmUiGroup* octaveGroup = uiOrdering.addNewGroup("Octave"); octaveGroup->add(&octaveExecutable); octaveGroup->add(&octaveShowHeaderInfoWhenExecutingScripts); +#ifdef ENABLE_GRPC caf::PdmUiGroup* pythonGroup = uiOrdering.addNewGroup("Python"); + pythonGroup->add(&enableGrpcServer); + pythonGroup->add(&defaultGrpcPortNumber); pythonGroup->add(&pythonExecutable); - +#endif caf::PdmUiGroup* scriptGroup = uiOrdering.addNewGroup("Script files"); scriptGroup->add(&scriptDirectories); scriptGroup->add(&scriptEditorExecutable); From 086ee60d8c8487772ee193fe01e530343260d4be Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Tue, 30 Jul 2019 12:50:08 +0200 Subject: [PATCH 264/396] #4530 Wait until after Save Project has been asked to hide dock windows. --- ApplicationCode/UserInterface/RiuMainWindow.cpp | 3 +-- ApplicationCode/UserInterface/RiuPlotMainWindow.cpp | 4 +--- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/ApplicationCode/UserInterface/RiuMainWindow.cpp b/ApplicationCode/UserInterface/RiuMainWindow.cpp index b397ab9004..11bb59b6b4 100644 --- a/ApplicationCode/UserInterface/RiuMainWindow.cpp +++ b/ApplicationCode/UserInterface/RiuMainWindow.cpp @@ -271,7 +271,6 @@ void RiuMainWindow::cleanupGuiBeforeProjectClose() void RiuMainWindow::closeEvent(QCloseEvent* event) { this->saveWinGeoAndDockToolBarLayout(); - this->hideAllDockWidgets(); RiaGuiApplication* app = RiaGuiApplication::instance(); if (app->isMainPlotWindowVisible()) @@ -287,8 +286,8 @@ void RiuMainWindow::closeEvent(QCloseEvent* event) return; } + this->hideAllDockWidgets(); app->closeMainPlotWindowIfOpenButHidden(); - app->closeProject(); } diff --git a/ApplicationCode/UserInterface/RiuPlotMainWindow.cpp b/ApplicationCode/UserInterface/RiuPlotMainWindow.cpp index 6599646c1c..9e1d40998d 100644 --- a/ApplicationCode/UserInterface/RiuPlotMainWindow.cpp +++ b/ApplicationCode/UserInterface/RiuPlotMainWindow.cpp @@ -181,8 +181,6 @@ void RiuPlotMainWindow::closeEvent(QCloseEvent* event) { this->saveWinGeoAndDockToolBarLayout(); - this->hideAllDockWidgets(); - RiaGuiApplication* app = RiaGuiApplication::instance(); if (app->isMain3dWindowVisible()) @@ -198,8 +196,8 @@ void RiuPlotMainWindow::closeEvent(QCloseEvent* event) return; } + this->hideAllDockWidgets(); app->closeMainWindowIfOpenButHidden(); - app->closeProject(); } From 357c722b4b5296d241b4d3dace3e1aa25248e4c1 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Tue, 30 Jul 2019 12:51:18 +0200 Subject: [PATCH 265/396] #4525 Increase default plot font size to 10 --- ApplicationCode/Application/RiaPreferences.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ApplicationCode/Application/RiaPreferences.cpp b/ApplicationCode/Application/RiaPreferences.cpp index 4613f1da5b..725e2cd101 100644 --- a/ApplicationCode/Application/RiaPreferences.cpp +++ b/ApplicationCode/Application/RiaPreferences.cpp @@ -84,10 +84,11 @@ RiaPreferences::RiaPreferences(void) CAF_PDM_InitField(&defaultScaleFactorZ, "defaultScaleFactorZ", 5, "Default Z Scale Factor", "", "", ""); caf::AppEnum fontSize = RiaFontCache::FONT_SIZE_8; + caf::AppEnum plotFontSize = RiaFontCache::FONT_SIZE_10; CAF_PDM_InitField(&defaultSceneFontSize, "fontSizeInScene", fontSize, "Viewer Font Size", "", "", ""); CAF_PDM_InitField(&defaultAnnotationFontSize, "defaultAnnotationFontSize", fontSize, "Annotation Font Size", "", "", ""); CAF_PDM_InitField(&defaultWellLabelFontSize, "wellLabelFontSize", fontSize, "Well Label Font Size", "", "", ""); - CAF_PDM_InitField(&defaultPlotFontSize, "defaultPlotFontSize", fontSize, "Plot Font Size", "", "", ""); + CAF_PDM_InitField(&defaultPlotFontSize, "defaultPlotFontSize", plotFontSize, "Plot Font Size", "", "", ""); CAF_PDM_InitField(&showLasCurveWithoutTvdWarning, "showLasCurveWithoutTvdWarning", true, "Show LAS Curve Without TVD Warning", "", "", ""); showLasCurveWithoutTvdWarning.uiCapability()->setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN); From 1d04f1034fd3ecc420b9cbceec2ba508fc4adab7 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Tue, 30 Jul 2019 13:12:19 +0200 Subject: [PATCH 266/396] #4471 Fill in "import rips" and other example code when creating a Python script from within ResInsight --- .../OctaveScriptCommands/RicNewPythonScriptFeature.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ApplicationCode/Commands/OctaveScriptCommands/RicNewPythonScriptFeature.cpp b/ApplicationCode/Commands/OctaveScriptCommands/RicNewPythonScriptFeature.cpp index 4a47ad2dbd..8407362d1b 100644 --- a/ApplicationCode/Commands/OctaveScriptCommands/RicNewPythonScriptFeature.cpp +++ b/ApplicationCode/Commands/OctaveScriptCommands/RicNewPythonScriptFeature.cpp @@ -114,6 +114,11 @@ void RicNewPythonScriptFeature::onActionTriggered(bool isChecked) return; } + else + { + QTextStream stream(&file); + stream << "# Load ResInsight Processing Server Client Library\nimport rips\n# Connect to ResInsight instance\nresInsight = rips.Instance.find()\n# Example code\nprint(\"ResInsight version:\" + resInsight.app.versionString())\n"; + } RicRefreshScriptsFeature::refreshScriptFolders(); From e89623525c333ff6d30e659c8ae66efe070563ae Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Tue, 30 Jul 2019 13:14:54 +0200 Subject: [PATCH 267/396] Fix build problem on Qt4 --- .../OctaveScriptCommands/RicDeleteScriptPathFeature.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ApplicationCode/Commands/OctaveScriptCommands/RicDeleteScriptPathFeature.cpp b/ApplicationCode/Commands/OctaveScriptCommands/RicDeleteScriptPathFeature.cpp index bba2f0f3d3..966396d6c0 100644 --- a/ApplicationCode/Commands/OctaveScriptCommands/RicDeleteScriptPathFeature.cpp +++ b/ApplicationCode/Commands/OctaveScriptCommands/RicDeleteScriptPathFeature.cpp @@ -56,9 +56,9 @@ void RicDeleteScriptPathFeature::onActionTriggered(bool isChecked) QString toBeRemoved = scriptCollection->directory; QString originalFilePathString = RiaApplication::instance()->preferences()->scriptDirectories(); - QStringList allFilePaths = originalFilePathString.split(';'); + QStringList allFilePaths = originalFilePathString.split(";"); allFilePaths.removeOne(toBeRemoved); - QString filePathString = allFilePaths.join(';'); + QString filePathString = allFilePaths.join(";"); RiaApplication::instance()->preferences()->scriptDirectories = filePathString; RiaApplication::instance()->applyPreferences(); From 1e688642a43ec8b0a07a02333d264d4df0c96526 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Tue, 30 Jul 2019 13:44:47 +0200 Subject: [PATCH 268/396] #4528 Only update the parts of project tree that is required when adding new scripts --- .../OctaveScriptCommands/RicNewPythonScriptFeature.cpp | 4 +++- .../OctaveScriptCommands/RicRefreshScriptsFeature.cpp | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/ApplicationCode/Commands/OctaveScriptCommands/RicNewPythonScriptFeature.cpp b/ApplicationCode/Commands/OctaveScriptCommands/RicNewPythonScriptFeature.cpp index 8407362d1b..3d27f3d883 100644 --- a/ApplicationCode/Commands/OctaveScriptCommands/RicNewPythonScriptFeature.cpp +++ b/ApplicationCode/Commands/OctaveScriptCommands/RicNewPythonScriptFeature.cpp @@ -75,6 +75,7 @@ void RicNewPythonScriptFeature::onActionTriggered(bool isChecked) { QFileInfo existingScriptFileInfo(calcScript->absoluteFileName()); fullPathNewScript = existingScriptFileInfo.absolutePath(); + calcScript->firstAncestorOrThisOfTypeAsserted(scriptColl); } else if (scriptColl) { @@ -120,7 +121,8 @@ void RicNewPythonScriptFeature::onActionTriggered(bool isChecked) stream << "# Load ResInsight Processing Server Client Library\nimport rips\n# Connect to ResInsight instance\nresInsight = rips.Instance.find()\n# Example code\nprint(\"ResInsight version:\" + resInsight.app.versionString())\n"; } - RicRefreshScriptsFeature::refreshScriptFolders(); + scriptColl->readContentFromDisc(); + scriptColl->updateConnectedEditors(); if (calcScript) { diff --git a/ApplicationCode/Commands/OctaveScriptCommands/RicRefreshScriptsFeature.cpp b/ApplicationCode/Commands/OctaveScriptCommands/RicRefreshScriptsFeature.cpp index 5cb4223fe6..0717efab29 100644 --- a/ApplicationCode/Commands/OctaveScriptCommands/RicRefreshScriptsFeature.cpp +++ b/ApplicationCode/Commands/OctaveScriptCommands/RicRefreshScriptsFeature.cpp @@ -22,6 +22,7 @@ #include "RiaPreferences.h" #include "RimProject.h" +#include "RimScriptCollection.h" #include @@ -61,5 +62,5 @@ void RicRefreshScriptsFeature::refreshScriptFolders() RiaPreferences* prefs = RiaApplication::instance()->preferences(); proj->setScriptDirectories(prefs->scriptDirectories()); - proj->updateConnectedEditors(); + proj->scriptCollection()->updateConnectedEditors(); } From 20832dfc887ec2c8039f13a5401490543b107a64 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Tue, 30 Jul 2019 14:04:51 +0200 Subject: [PATCH 269/396] Scripts: set sensible default editors on Windows and Linux --- ApplicationCode/Application/RiaPreferences.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/ApplicationCode/Application/RiaPreferences.cpp b/ApplicationCode/Application/RiaPreferences.cpp index 725e2cd101..ebfb3cf641 100644 --- a/ApplicationCode/Application/RiaPreferences.cpp +++ b/ApplicationCode/Application/RiaPreferences.cpp @@ -30,6 +30,10 @@ #include "cafPdmUiFieldHandle.h" #include "cafPdmUiFilePathEditor.h" +#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) +#include +#endif + namespace caf { template<> @@ -57,6 +61,20 @@ RiaPreferences::RiaPreferences(void) CAF_PDM_InitFieldNoDefault(&scriptDirectories, "scriptDirectory", "Shared Script Folder(s)", "", "", ""); scriptDirectories.uiCapability()->setUiEditorTypeName(caf::PdmUiFilePathEditor::uiEditorTypeName()); + QString defaultTextEditor; +#ifdef WIN32 + defaultTextEditor = QString("notepad.exe"); +#else + defaultTextEditor = QString("kate"); +#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) + defaultTextEditor = QStandardPaths::findExecutable("kate"); + if (defaultTextEditor.isEmpty()) + { + defaultTextEditor = QStandardPaths::findExecutable("gedit"); + } +#endif +#endif + CAF_PDM_InitField(&scriptEditorExecutable, "scriptEditorExecutable", QString("kate"), "Script Editor", "", "", ""); scriptEditorExecutable.uiCapability()->setUiEditorTypeName(caf::PdmUiFilePathEditor::uiEditorTypeName()); From 010b573afbdf6c56f88bd0bfee495a5a8cc47870 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Tue, 30 Jul 2019 14:11:19 +0200 Subject: [PATCH 270/396] Python: add extra path to PythonPath for Linux --- ApplicationCode/Application/RiaApplication.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/ApplicationCode/Application/RiaApplication.cpp b/ApplicationCode/Application/RiaApplication.cpp index 613610730c..696a7d10a6 100644 --- a/ApplicationCode/Application/RiaApplication.cpp +++ b/ApplicationCode/Application/RiaApplication.cpp @@ -95,6 +95,8 @@ #include #include +#include + #ifdef WIN32 #include #else @@ -950,15 +952,18 @@ QProcessEnvironment RiaApplication::pythonProcessEnvironment() const penv.insert("RESINSIGHT_EXECUTABLE", QCoreApplication::applicationFilePath()); QStringList ripsLocations; + QString separator; #ifdef WIN32 ripsLocations << QCoreApplication::applicationDirPath() + "\\Python" << QCoreApplication::applicationDirPath() + "\\..\\..\\Python"; + separator = ";"; #else - ripsLocations << QCoreApplication::applicationDirPath() + "/Python"; + ripsLocations << QCoreApplication::applicationDirPath() + "/Python" + << QCoreApplication::applicationDirPath() + "/../../Python"; + separator = ":"; #endif - - penv.insert("PYTHONPATH", QString("%1;%2").arg(penv.value("PYTHONPATH")).arg(ripsLocations.join(";"))); + penv.insert("PYTHONPATH", QString("%1%2%3").arg(penv.value("PYTHONPATH")).arg(separator).arg(ripsLocations.join(separator))); #endif return penv; } From 8d1e8fc022e41fa4debd1da215cddd3622396764 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Tue, 30 Jul 2019 14:38:10 +0200 Subject: [PATCH 271/396] Python: Space in example code --- .../Commands/OctaveScriptCommands/RicNewPythonScriptFeature.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ApplicationCode/Commands/OctaveScriptCommands/RicNewPythonScriptFeature.cpp b/ApplicationCode/Commands/OctaveScriptCommands/RicNewPythonScriptFeature.cpp index 3d27f3d883..4d34a7b61b 100644 --- a/ApplicationCode/Commands/OctaveScriptCommands/RicNewPythonScriptFeature.cpp +++ b/ApplicationCode/Commands/OctaveScriptCommands/RicNewPythonScriptFeature.cpp @@ -118,7 +118,7 @@ void RicNewPythonScriptFeature::onActionTriggered(bool isChecked) else { QTextStream stream(&file); - stream << "# Load ResInsight Processing Server Client Library\nimport rips\n# Connect to ResInsight instance\nresInsight = rips.Instance.find()\n# Example code\nprint(\"ResInsight version:\" + resInsight.app.versionString())\n"; + stream << "# Load ResInsight Processing Server Client Library\nimport rips\n# Connect to ResInsight instance\nresInsight = rips.Instance.find()\n# Example code\nprint(\"ResInsight version: \" + resInsight.app.versionString())\n"; } scriptColl->readContentFromDisc(); From 416117160887d9dcd50e5be9d3d1f53a183ee9b1 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Tue, 30 Jul 2019 15:05:22 +0200 Subject: [PATCH 272/396] Python: avoid __pycache__ turning up as sub-folder in Script Collection --- .../ProjectDataModel/RimScriptCollection.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimScriptCollection.cpp b/ApplicationCode/ProjectDataModel/RimScriptCollection.cpp index a464b2305a..2f3f5641cb 100644 --- a/ApplicationCode/ProjectDataModel/RimScriptCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimScriptCollection.cpp @@ -37,7 +37,7 @@ RimScriptCollection::RimScriptCollection() { CAF_PDM_InitObject("ScriptLocation", ":/Folder.png", "", ""); - CAF_PDM_InitFieldNoDefault(&directory, "ScriptDirectory", "Dir", "", "", ""); + CAF_PDM_InitFieldNoDefault(&directory, "ScriptDirectory", "Folder", "", "", ""); CAF_PDM_InitFieldNoDefault(&calcScripts, "CalcScripts", "", "", "", ""); calcScripts.uiCapability()->setUiHidden(true); CAF_PDM_InitFieldNoDefault(&subDirectories, "SubDirectories", "", "", "", ""); @@ -113,13 +113,15 @@ void RimScriptCollection::readContentFromDisc() while (it.hasNext()) { QFileInfo fi = it.next(); + if (fi.baseName() != "__pycache__") + { + RimScriptCollection* scriptLocation = new RimScriptCollection; + scriptLocation->directory = fi.absoluteFilePath(); + scriptLocation->setUiName(fi.baseName()); + scriptLocation->readContentFromDisc(); - RimScriptCollection* scriptLocation = new RimScriptCollection; - scriptLocation->directory = fi.absoluteFilePath(); - scriptLocation->setUiName(fi.baseName()); - scriptLocation->readContentFromDisc(); - - subDirectories.push_back(scriptLocation); + subDirectories.push_back(scriptLocation); + } } } } From 2940713a424d498c2b1a18d829dc0e4a8c653e86 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Tue, 30 Jul 2019 15:26:38 +0200 Subject: [PATCH 273/396] Python: fixes that makes all examples run properly again --- ApplicationCode/GrpcInterface/Python/rips/Case.py | 2 +- ApplicationCode/GrpcInterface/Python/rips/PdmObject.py | 5 +++++ ApplicationCode/GrpcInterface/Python/rips/View.py | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/ApplicationCode/GrpcInterface/Python/rips/Case.py b/ApplicationCode/GrpcInterface/Python/rips/Case.py index 6f24727850..3b6bb7ec49 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Case.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Case.py @@ -111,7 +111,7 @@ class Case (PdmObject): def views(self): """Get a list of views belonging to a case""" - pbmObjects = self.children("ReservoirView") + pbmObjects = self.children("ReservoirViews") viewList = [] for pbmObject in pbmObjects: viewList.append(View(pbmObject)) diff --git a/ApplicationCode/GrpcInterface/Python/rips/PdmObject.py b/ApplicationCode/GrpcInterface/Python/rips/PdmObject.py index ac7d9aac0a..6de90478c3 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/PdmObject.py +++ b/ApplicationCode/GrpcInterface/Python/rips/PdmObject.py @@ -26,6 +26,11 @@ class PdmObject: listOfKeywords.append(keyword) return listOfKeywords + def printObjectInfo(self): + print ("Class Keyword: " + self.classKeyword()) + for keyword in self.keywords(): + print(keyword + " [" + type(self.getValue(keyword)).__name__ + "]: " + str(self.getValue(keyword))) + def __toValue(self, value): if value.lower() == 'false': return False diff --git a/ApplicationCode/GrpcInterface/Python/rips/View.py b/ApplicationCode/GrpcInterface/Python/rips/View.py index 56096f8219..b47496545c 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/View.py +++ b/ApplicationCode/GrpcInterface/Python/rips/View.py @@ -30,4 +30,4 @@ class View (PdmObject): def cellResult(self): """Retrieve the current cell results""" - return self.children("ResultSlot")[0] \ No newline at end of file + return self.children("GridCellResult")[0] \ No newline at end of file From 213591f522d1c18c7e62018879ae8c1d01b38bcf Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Wed, 31 Jul 2019 09:53:15 +0200 Subject: [PATCH 274/396] #4526 Make sure setting wells for flow diagnostics result works and add simplified API --- .../GrpcInterface/CMakeLists.cmake | 4 +- .../GrpcInterface/Python/rips/PdmObject.py | 2 +- .../GrpcInterface/Python/rips/View.py | 46 ++++++++++++++++++- .../Python/rips/examples/SetCellResult.py | 10 +--- .../rips/examples/SetFlowDiagnosticsResult.py | 14 ++++++ .../RimEclipseResultDefinition.cpp | 8 +++- 6 files changed, 70 insertions(+), 14 deletions(-) create mode 100644 ApplicationCode/GrpcInterface/Python/rips/examples/SetFlowDiagnosticsResult.py diff --git a/ApplicationCode/GrpcInterface/CMakeLists.cmake b/ApplicationCode/GrpcInterface/CMakeLists.cmake index 2a97999a08..d2f39634c0 100644 --- a/ApplicationCode/GrpcInterface/CMakeLists.cmake +++ b/ApplicationCode/GrpcInterface/CMakeLists.cmake @@ -170,13 +170,15 @@ if (PYTHON_EXECUTABLE) "rips/View.py" "rips/examples/InstanceExample.py" "rips/examples/CommandExample.py" - "rips/examples/CaseGridGroup.py" + "rips/examples/CaseGridGroup.py" "rips/examples/CaseInfoStreamingExample.py" "rips/examples/SoilPorvAsync.py" "rips/examples/SoilPorvSync.py" "rips/examples/SelectedCases.py" "rips/examples/AllCases.py" "rips/examples/SetGridProperties.py" + "rips/examples/SetCellResult.py" + "rips/examples/SetFlowDiagnosticsResult.py" "rips/examples/GridInformation.py" "rips/examples/InputPropTestSync.py" "rips/examples/InputPropTestAsync.py" diff --git a/ApplicationCode/GrpcInterface/Python/rips/PdmObject.py b/ApplicationCode/GrpcInterface/Python/rips/PdmObject.py index 6de90478c3..1369a8dceb 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/PdmObject.py +++ b/ApplicationCode/GrpcInterface/Python/rips/PdmObject.py @@ -59,7 +59,7 @@ class PdmObject: elif isinstance(value, list): listofstrings = [] for val in value: - listofstrings.append(self.__fromValue(val)) + listofstrings.append(self.__fromValue('\"' + val + '\"')) return "[" + ", ".join(listofstrings) + "]" else: return str(value) diff --git a/ApplicationCode/GrpcInterface/Python/rips/View.py b/ApplicationCode/GrpcInterface/Python/rips/View.py index b47496545c..d895e1bf34 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/View.py +++ b/ApplicationCode/GrpcInterface/Python/rips/View.py @@ -30,4 +30,48 @@ class View (PdmObject): def cellResult(self): """Retrieve the current cell results""" - return self.children("GridCellResult")[0] \ No newline at end of file + return self.children("GridCellResult")[0] + + def applyCellResult(self, resultType, resultVariable): + """Apply a regular cell result + Arguments: + resultType [str]: String representing the result category + The valid values are: "DYNAMIC_NATIVE", "STATIC_NATIVE", "SOURSIMRL", + "GENERATED", "INPUT_PROPERTY", "FORMATION_NAMES", + "FLOW_DIAGNOSTICS" and "INJECTION_FLOODING" + resultVariable [str]: String representing the result value. + """ + cellResult = self.cellResult() + cellResult.setValue("ResultType", resultType) + cellResult.setValue("ResultVariable", resultVariable) + cellResult.update() + + def applyFlowDiagnosticsCellResult(self, + resultVariable = 'TOF', + selectionMode = 'FLOW_TR_BY_SELECTION', + injectors = [], + producers = []): + """Apply a flow diagnostics cell result + + Arguments: + resultVariable [str]: String representing the result value + The valid values are 'TOF', 'Fraction', 'MaxFractionTracer' and 'Communication'. + selectionMode [str]: String specifying which tracers to select. + The valid values are FLOW_TR_INJ_AND_PROD (all injector and producer tracers) + FLOW_TR_PRODUCERS (all producers) + FLOW_TR_INJECTORS (all injectors) + FLOW_TR_BY_SELECTION (specify individual tracers in the + injectorTracers and producerTracers variables) + injectorTracers [list]: List of injector names (strings) to select. + Requires selectionMode to be 'FLOW_TR_BY_SELECTION'. + producerTracers [list]: List of producer tracers (strings) to select. + Requires selectionMode to be 'FLOW_TR_BY_SELECTION'. + """ + cellResult = self.cellResult() + cellResult.setValue("ResultType", "FLOW_DIAGNOSTICS") + cellResult.setValue("ResultVariable", resultVariable) + cellResult.setValue("FlowTracerSelectionMode", selectionMode) + if selectionMode == 'FLOW_TR_BY_SELECTION': + cellResult.setValue("SelectedInjectorTracers", injectors) + cellResult.setValue("SelectedProducerTracers", producers) + cellResult.update() \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/SetCellResult.py b/ApplicationCode/GrpcInterface/Python/rips/examples/SetCellResult.py index 2414744387..de0b3e31b1 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/examples/SetCellResult.py +++ b/ApplicationCode/GrpcInterface/Python/rips/examples/SetCellResult.py @@ -3,12 +3,4 @@ import rips resInsight = rips.Instance.find() view = resInsight.project.view(0) - -cellResult = view.cellResult() - -cellResult.printObjectInfo() - -cellResult.setValue("ResultType", "FLOW_DIAGNOSTICS") -cellResult.setValue("ResultVariable", "TOF") - -cellResult.update() \ No newline at end of file +view.applyCellResult(resultType='STATIC_NATIVE', resultVariable='DX') diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/SetFlowDiagnosticsResult.py b/ApplicationCode/GrpcInterface/Python/rips/examples/SetFlowDiagnosticsResult.py new file mode 100644 index 0000000000..3e13e32dca --- /dev/null +++ b/ApplicationCode/GrpcInterface/Python/rips/examples/SetFlowDiagnosticsResult.py @@ -0,0 +1,14 @@ +# Load ResInsight Processing Server Client Library +import rips +# Connect to ResInsight instance +resInsight = rips.Instance.find() + +view = resInsight.project.view(0) +view.applyFlowDiagnosticsCellResult(resultVariable='Fraction', + selectionMode='FLOW_TR_INJ_AND_PROD') + +# Example of setting individual wells. Commented out because well names are case specific. +#view.applyFlowDiagnosticsCellResult(resultVariable='Fraction', +# selectionMode='FLOW_TR_BY_SELECTION', +# injectors = ['C-1H', 'C-2H', 'F-2H'], +# producers = ['B-1AH', 'B-3H', 'D-1H']) diff --git a/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.cpp b/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.cpp index 7d34398e1a..76a2a903ba 100644 --- a/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.cpp +++ b/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.cpp @@ -1210,8 +1210,12 @@ void RimEclipseResultDefinition::setSelectedSouringTracers(const std::vector Date: Wed, 31 Jul 2019 11:02:42 +0200 Subject: [PATCH 275/396] Python: Update API documentation --- .../Python/rips/GridCaseGroup.py | 1 + .../GrpcInterface/Python/rips/PdmObject.py | 41 +++++++++++++++++++ .../GrpcInterface/Python/rips/Project.py | 7 ++++ 3 files changed, 49 insertions(+) diff --git a/ApplicationCode/GrpcInterface/Python/rips/GridCaseGroup.py b/ApplicationCode/GrpcInterface/Python/rips/GridCaseGroup.py index 77b5842a65..1f2802fb45 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/GridCaseGroup.py +++ b/ApplicationCode/GrpcInterface/Python/rips/GridCaseGroup.py @@ -22,6 +22,7 @@ class GridCaseGroup (PdmObject): PdmObject.__init__(self, pdmObject.pb2Object, pdmObject.channel) def statisticsCases(self): + """Get a list of all statistics cases in the Grid Case Group""" statCaseCollection = self.children("StatisticsCaseCollection")[0] return statCaseCollection.children("Reservoirs") diff --git a/ApplicationCode/GrpcInterface/Python/rips/PdmObject.py b/ApplicationCode/GrpcInterface/Python/rips/PdmObject.py index 1369a8dceb..64189b10ef 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/PdmObject.py +++ b/ApplicationCode/GrpcInterface/Python/rips/PdmObject.py @@ -15,18 +15,27 @@ class PdmObject: self.pdmObjectStub = PdmObject_pb2_grpc.PdmObjectServiceStub(self.channel) def address(self): + """Get the unique address of the PdmObject + + Returns: + A 64-bit unsigned integer address + """ + return self.pb2Object.address def classKeyword(self): + """Get the class keyword in the ResInsight Data Model for the given PdmObject""" return self.pb2Object.class_keyword def keywords(self): + """Get a list of all parameter keywords available in the object""" listOfKeywords = [] for keyword in self.pb2Object.parameters: listOfKeywords.append(keyword) return listOfKeywords def printObjectInfo(self): + """Print the structure and data content of the PdmObject""" print ("Class Keyword: " + self.classKeyword()) for keyword in self.keywords(): print(keyword + " [" + type(self.getValue(keyword)).__name__ + "]: " + str(self.getValue(keyword))) @@ -65,6 +74,13 @@ class PdmObject: return str(value) def getValue(self, keyword): + """Get the value associated with the provided keyword + Arguments: + keyword(str): A string containing the parameter keyword + + Returns: + The value of the parameter. Can be int, str or list. + """ value = self.pb2Object.parameters[keyword] return self.__toValue(value) @@ -81,9 +97,23 @@ class PdmObject: return values def setValue(self, keyword, value): + """Set the value associated with the provided keyword + Arguments: + keyword(str): A string containing the parameter keyword + value(varying): A value matching the type of the parameter. + See keyword documentation and/or printObjectInfo() to find + the correct data type. + """ self.pb2Object.parameters[keyword] = self.__fromValue(value) def descendants(self, classKeyword): + """Get a list of all project tree descendants matching the class keyword + Arguments: + classKeyword[str]: A class keyword matching the type of class wanted + + Returns: + A list of PdmObjects matching the keyword provided + """ request = PdmObject_pb2.PdmDescendantObjectRequest(object=self.pb2Object, child_keyword=classKeyword) objectList = self.pdmObjectStub.GetDescendantPdmObjects(request).objects childList = [] @@ -92,6 +122,12 @@ class PdmObject: return childList def children(self, childField): + """Get a list of all direct project tree children inside the provided childField + Arguments: + childField[str]: A field name + Returns: + A list of PdmObjects inside the childField + """ request = PdmObject_pb2.PdmChildObjectRequest(object=self.pb2Object, child_field=childField) objectList = self.pdmObjectStub.GetChildPdmObjects(request).objects childList = [] @@ -100,10 +136,15 @@ class PdmObject: return childList def ancestor(self, classKeyword): + """Find the first ancestor that matches the provided classKeyword + Arguments: + classKeyword[str]: A class keyword matching the type of class wanted + """ request = PdmObject_pb2.PdmParentObjectRequest(object=self.pb2Object, parent_keyword=classKeyword) return PdmObject(self.pdmObjectStub.GetAncestorPdmObject(request), self.channel) def update(self): + """Sync all fields from the Python Object to ResInsight""" self.pdmObjectStub.UpdateExistingPdmObject(self.pb2Object) # def createChild(self, childField, childClassKeyword): diff --git a/ApplicationCode/GrpcInterface/Python/rips/Project.py b/ApplicationCode/GrpcInterface/Python/rips/Project.py index 76fedbb1e0..4cf10e7d31 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Project.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Project.py @@ -117,6 +117,7 @@ class Project (PdmObject): return None def gridCaseGroups(self): + """Get a list of all grid case groups in the project""" caseGroups = self.descendants("RimIdenticalGridCaseGroup"); caseGroupList = [] @@ -138,5 +139,11 @@ class Project (PdmObject): return None def createGridCaseGroup(self, casePaths): + """Create a new grid case group from the provided case paths + Arguments: + casePaths(list): a list of paths to the cases to be loaded and included in the group + Returns: + A new grid case group object + """ groupId, groupName = Commands(self.channel).createGridCaseGroup(casePaths) return self.gridCaseGroup(groupId) \ No newline at end of file From b8d6c6b958a50ee00ce1171cf13afc04950f7c29 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Wed, 31 Jul 2019 11:40:36 +0200 Subject: [PATCH 276/396] Make sure default text editor is actually used in RiaPreferences-defaults --- ApplicationCode/Application/RiaPreferences.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ApplicationCode/Application/RiaPreferences.cpp b/ApplicationCode/Application/RiaPreferences.cpp index ebfb3cf641..7ff8fa389d 100644 --- a/ApplicationCode/Application/RiaPreferences.cpp +++ b/ApplicationCode/Application/RiaPreferences.cpp @@ -75,7 +75,7 @@ RiaPreferences::RiaPreferences(void) #endif #endif - CAF_PDM_InitField(&scriptEditorExecutable, "scriptEditorExecutable", QString("kate"), "Script Editor", "", "", ""); + CAF_PDM_InitField(&scriptEditorExecutable, "scriptEditorExecutable", defaultTextEditor, "Script Editor", "", "", ""); scriptEditorExecutable.uiCapability()->setUiEditorTypeName(caf::PdmUiFilePathEditor::uiEditorTypeName()); CAF_PDM_InitField(&octaveExecutable, "octaveExecutable", QString("octave"), "Octave Executable Location", "", "", ""); From ef5ee1e2e0ed1da86e2c5211aa6affed54e9f381 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 31 Jul 2019 12:58:23 +0200 Subject: [PATCH 277/396] Set version to 2019.04-dev.04 --- ResInsightVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ResInsightVersion.cmake b/ResInsightVersion.cmake index fd54d6ebf7..18fea3e40e 100644 --- a/ResInsightVersion.cmake +++ b/ResInsightVersion.cmake @@ -10,7 +10,7 @@ set(RESINSIGHT_VERSION_TEXT "-dev") # 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 ".03") +set(RESINSIGHT_DEV_VERSION ".04") # https://github.com/CRAVA/crava/tree/master/libs/nrlib set(NRLIB_GITHUB_SHA "ba35d4359882f1c6f5e9dc30eb95fe52af50fd6f") From 74f234784b89b17ce3a7d404e18841924429c758 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 31 Jul 2019 18:25:54 +0200 Subject: [PATCH 278/396] #4411 Grid Cross Plot : Add comments --- .../ProjectDataModel/GridCrossPlots/RimGridCrossPlotDataSet.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ApplicationCode/ProjectDataModel/GridCrossPlots/RimGridCrossPlotDataSet.cpp b/ApplicationCode/ProjectDataModel/GridCrossPlots/RimGridCrossPlotDataSet.cpp index 53ca83b74b..f07ee9f64f 100644 --- a/ApplicationCode/ProjectDataModel/GridCrossPlots/RimGridCrossPlotDataSet.cpp +++ b/ApplicationCode/ProjectDataModel/GridCrossPlots/RimGridCrossPlotDataSet.cpp @@ -580,6 +580,7 @@ void RimGridCrossPlotDataSet::createCurves(const RigEclipseCrossPlotResult& resu legendConfig()->scalarMapper()->majorTickValues(&tickValues); } + // NB : Make sure iteration of curve and groups are syncronized with createCurves() for (auto it = m_groupedResults.rbegin(); it != m_groupedResults.rend(); ++it) { RimGridCrossPlotCurve* curve = new RimGridCrossPlotCurve(); @@ -619,6 +620,7 @@ void RimGridCrossPlotDataSet::fillCurveDataInExistingCurves(const RigEclipseCros } else { + // NB : Make sure iteration of curve and groups are syncronized with fillCurveDataInExistingCurves() auto curveIt = m_crossPlotCurves.begin(); auto groupIt = m_groupedResults.begin(); for (; curveIt != m_crossPlotCurves.end() && groupIt != m_groupedResults.end(); ++curveIt, ++groupIt) From be40ca25af4d739999ba81422122119af7c6ef66 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 31 Jul 2019 18:26:50 +0200 Subject: [PATCH 279/396] #4411 Grid Cross Plot : Ensure same ordering when updating data --- .../GridCrossPlots/RimGridCrossPlotDataSet.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/GridCrossPlots/RimGridCrossPlotDataSet.cpp b/ApplicationCode/ProjectDataModel/GridCrossPlots/RimGridCrossPlotDataSet.cpp index f07ee9f64f..c1de85dcdb 100644 --- a/ApplicationCode/ProjectDataModel/GridCrossPlots/RimGridCrossPlotDataSet.cpp +++ b/ApplicationCode/ProjectDataModel/GridCrossPlots/RimGridCrossPlotDataSet.cpp @@ -622,8 +622,8 @@ void RimGridCrossPlotDataSet::fillCurveDataInExistingCurves(const RigEclipseCros { // NB : Make sure iteration of curve and groups are syncronized with fillCurveDataInExistingCurves() auto curveIt = m_crossPlotCurves.begin(); - auto groupIt = m_groupedResults.begin(); - for (; curveIt != m_crossPlotCurves.end() && groupIt != m_groupedResults.end(); ++curveIt, ++groupIt) + auto groupIt = m_groupedResults.rbegin(); + for (; curveIt != m_crossPlotCurves.end() && groupIt != m_groupedResults.rend(); ++curveIt, ++groupIt) { RimGridCrossPlotCurve* curve = *curveIt; curve->setSamples(groupIt->second.xValues, groupIt->second.yValues); From 25f13122a237cebe72e1eb1f821081d21240b22b Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Fri, 2 Aug 2019 13:13:23 +0200 Subject: [PATCH 280/396] #4517 Implement highlighting function for plot curves --- .../Application/Tools/RiaColorTools.cpp | 13 +++ .../Application/Tools/RiaColorTools.h | 2 + .../UserInterface/RiuGridCrossQwtPlot.cpp | 2 - ApplicationCode/UserInterface/RiuQwtPlot.cpp | 107 +++++++++++++++++- ApplicationCode/UserInterface/RiuQwtPlot.h | 12 ++ 5 files changed, 131 insertions(+), 5 deletions(-) diff --git a/ApplicationCode/Application/Tools/RiaColorTools.cpp b/ApplicationCode/Application/Tools/RiaColorTools.cpp index fbbec44c89..a15f4ed9b4 100644 --- a/ApplicationCode/Application/Tools/RiaColorTools.cpp +++ b/ApplicationCode/Application/Tools/RiaColorTools.cpp @@ -19,6 +19,7 @@ #include "RiaColorTools.h" +#include "cvfAssert.h" #include "cvfMath.h" #include @@ -141,6 +142,18 @@ cvf::Color3f RiaColorTools::fromQColorTo3f(QColor color) return cvf::Color3f(color.redF(), color.greenF(), color.blueF()); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QColor RiaColorTools::blendQColors(const QColor& color1, const QColor& color2, int weight1 /*= 1*/, int weight2 /*= 1*/) +{ + CVF_ASSERT(weight1 > 0 && weight2 > 0); + int weightsum = weight1 + weight2; + return QColor((color1.red() * weight1 + color2.red() * weight2) / weightsum, + (color1.green() * weight1 + color2.green() * weight2) / weightsum, + (color1.blue() * weight1 + color2.blue() * weight2) / weightsum); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/Application/Tools/RiaColorTools.h b/ApplicationCode/Application/Tools/RiaColorTools.h index e99221325b..55fc12ac28 100644 --- a/ApplicationCode/Application/Tools/RiaColorTools.h +++ b/ApplicationCode/Application/Tools/RiaColorTools.h @@ -43,6 +43,8 @@ public: static QColor toQColor(cvf::Color4f color); static cvf::Color3f fromQColorTo3f(QColor); + static QColor blendQColors(const QColor& color1, const QColor& color2, int weight1 = 1, int weight2 = 1); + private: static float relativeLuminance(cvf::Color3f backgroundColor); static float calculateNonLinearColorValue(float colorFraction); diff --git a/ApplicationCode/UserInterface/RiuGridCrossQwtPlot.cpp b/ApplicationCode/UserInterface/RiuGridCrossQwtPlot.cpp index 8580aaddb5..b2e74aaff4 100644 --- a/ApplicationCode/UserInterface/RiuGridCrossQwtPlot.cpp +++ b/ApplicationCode/UserInterface/RiuGridCrossQwtPlot.cpp @@ -398,7 +398,6 @@ void RiuGridCrossQwtPlot::selectSample(QwtPlotCurve* curve, int sampleNumber) curveLabel.setBorderRadius(2.0); m_selectedPointMarker->setLabel(curveLabel); } - replot(); } //-------------------------------------------------------------------------------------------------- @@ -407,7 +406,6 @@ void RiuGridCrossQwtPlot::selectSample(QwtPlotCurve* curve, int sampleNumber) void RiuGridCrossQwtPlot::clearSampleSelection() { m_selectedPointMarker->detach(); - replot(); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/UserInterface/RiuQwtPlot.cpp b/ApplicationCode/UserInterface/RiuQwtPlot.cpp index ccbb7dde03..d4b06b8dfa 100644 --- a/ApplicationCode/UserInterface/RiuQwtPlot.cpp +++ b/ApplicationCode/UserInterface/RiuQwtPlot.cpp @@ -18,6 +18,8 @@ #include "RiuQwtPlot.h" +#include "RiaColorTools.h" + #include "RimProject.h" #include "RiuPlotMainWindowTools.h" @@ -82,6 +84,7 @@ RiuQwtPlot::RiuQwtPlot(RimViewWindow* viewWindow, QWidget* parent) : QwtPlot(par RiuQwtPlotTools::setCommonPlotBehaviour(this); RiuQwtPlotTools::setDefaultAxes(this); + } //-------------------------------------------------------------------------------------------------- @@ -124,7 +127,7 @@ QSize RiuQwtPlot::minimumSizeHint() const /// Empty default implementation //-------------------------------------------------------------------------------------------------- void RiuQwtPlot::selectSample(QwtPlotCurve* curve, int sampleNumber) -{ +{ } //-------------------------------------------------------------------------------------------------- @@ -134,6 +137,15 @@ void RiuQwtPlot::clearSampleSelection() { } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuQwtPlot::hideEvent(QHideEvent* event) +{ + resetCurveHighlighting(); + QwtPlot::hideEvent(event); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -195,6 +207,7 @@ void RiuQwtPlot::selectClosestCurve(const QPoint& pos) } } + resetCurveHighlighting(); if (closestCurve && distMin < 20) { CVF_ASSERT(closestCurvePoint >= 0); @@ -209,18 +222,106 @@ void RiuQwtPlot::selectClosestCurve(const QPoint& pos) { RiuPlotMainWindowTools::showPlotMainWindow(); RiuPlotMainWindowTools::selectAsCurrentItem(selectedPlotObject); + highlightCurve(closestCurve); } } } - + if (closestCurve && distMin < 10) { - selectSample(closestCurve, closestCurvePoint); + selectSample(closestCurve, closestCurvePoint); } else { clearSampleSelection(); } + + replot(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuQwtPlot::highlightCurve(const QwtPlotCurve* closestCurve) +{ + for (QwtPlotItem* plotItem : this->itemList()) + { + QwtPlotCurve* plotCurve = dynamic_cast(plotItem); + if (plotCurve) + { + QPen existingPen = plotCurve->pen(); + QColor bgColor = this->canvasBackground().color(); + + QColor curveColor = existingPen.color(); + QColor symbolColor; + QColor symbolLineColor; + + QwtSymbol* symbol = const_cast(plotCurve->symbol()); + if (symbol) + { + symbolColor = symbol->brush().color(); + symbolLineColor = symbol->pen().color(); + } + + if (plotCurve == closestCurve) + { + cvf::Color3f cvfBgColor = RiaColorTools::fromQColorTo3f(bgColor); + cvf::Color3f cvfFgColor = RiaColorTools::contrastColor(cvfBgColor); + QColor fgColor = RiaColorTools::toQColor(cvfFgColor); + + QColor blendedColor = RiaColorTools::blendQColors(fgColor, curveColor, 1, 2); + QColor blendedSymbolColor = RiaColorTools::blendQColors(fgColor, symbolColor, 1, 2); + QColor blendedSymbolLineColor = RiaColorTools::blendQColors(fgColor, symbolLineColor, 1, 2); + + plotCurve->setPen(blendedColor, existingPen.width(), existingPen.style()); + if (symbol) + { + symbol->setColor(blendedSymbolColor); + symbol->setPen(blendedSymbolLineColor, symbol->pen().width(), symbol->pen().style()); + } + } + else + { + QColor blendedColor = RiaColorTools::blendQColors(bgColor, curveColor, 3, 1); + QColor blendedSymbolColor = RiaColorTools::blendQColors(bgColor, symbolColor, 3, 1); + QColor blendedSymbolLineColor = RiaColorTools::blendQColors(bgColor, symbolLineColor, 3, 1); + + plotCurve->setPen(blendedColor, existingPen.width(), existingPen.style()); + if (symbol) + { + symbol->setColor(blendedSymbolColor); + symbol->setPen(blendedSymbolLineColor, symbol->pen().width(), symbol->pen().style()); + } + } + CurveColors curveColors = {curveColor, symbolColor, symbolLineColor}; + m_originalCurveColors.insert(std::make_pair(plotCurve, curveColors)); + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuQwtPlot::resetCurveHighlighting() +{ + for (QwtPlotItem* plotItem : this->itemList()) + { + QwtPlotCurve* plotCurve = dynamic_cast(plotItem); + if (plotCurve && m_originalCurveColors.count(plotCurve)) + { + const QPen& existingPen = plotCurve->pen(); + auto colors = m_originalCurveColors[plotCurve]; + plotCurve->setPen(colors.lineColor, existingPen.width(), existingPen.style()); + + QwtSymbol* symbol = const_cast(plotCurve->symbol()); + if (symbol) + { + symbol->setColor(colors.symbolColor); + symbol->setPen(colors.symbolLineColor, symbol->pen().width(), symbol->pen().style()); + } + } + } + m_originalCurveColors.clear(); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/UserInterface/RiuQwtPlot.h b/ApplicationCode/UserInterface/RiuQwtPlot.h index ff81a5d539..e61541e605 100644 --- a/ApplicationCode/UserInterface/RiuQwtPlot.h +++ b/ApplicationCode/UserInterface/RiuQwtPlot.h @@ -61,18 +61,30 @@ protected: virtual void selectSample(QwtPlotCurve* curve, int sampleNumber); virtual void clearSampleSelection(); + + virtual void hideEvent(QHideEvent *event) override; + private: void selectClosestCurve(const QPoint& pos); + void highlightCurve(const QwtPlotCurve* closestCurve); + void resetCurveHighlighting(); private slots: void onZoomedSlot( ); void onAxisClicked(int axis, double value); private: + struct CurveColors + { + QColor lineColor; + QColor symbolColor; + QColor symbolLineColor; + }; caf::PdmPointer m_ownerViewWindow; QPointer m_zoomerLeft; QPointer m_zoomerRight; + std::map m_originalCurveColors; }; From a9ee69587d3cecb984abdae032fa5c07a0fb5f5f Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Sat, 3 Aug 2019 16:08:07 +0200 Subject: [PATCH 281/396] #4536 Make sure we guard against calculating Mobile Volume Weighted Mean for visible cell stats and not just all cell stats. --- .../ProjectDataModel/Rim3dOverlayInfoConfig.cpp | 16 +++++++++++++++- .../RigEclipseNativeVisibleCellsStatCalc.cpp | 7 +++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp b/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp index e5874c4ddd..4337dc8fc3 100644 --- a/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp +++ b/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp @@ -48,6 +48,7 @@ #include "RimEclipseContourMapView.h" #include "RimEclipseFaultColors.h" #include "RimEclipsePropertyFilterCollection.h" +#include "RimEclipseStatisticsCase.h" #include "RimEclipseView.h" #include "RimFaultInViewCollection.h" #include "RimGeoMechCase.h" @@ -926,6 +927,11 @@ void Rim3dOverlayInfoConfig::update3DInfo() RimEclipseView* reservoirView = dynamic_cast(m_viewDef.p()); if (reservoirView) { + const RimEclipseStatisticsCase* eclipseStat = dynamic_cast(reservoirView->eclipseCase()); + if (eclipseStat) + { + m_showVolumeWeightedMean = false; + } updateEclipse3DInfo(reservoirView); // Update statistics dialog @@ -933,6 +939,7 @@ void Rim3dOverlayInfoConfig::update3DInfo() } RimGeoMechView* geoMechView = dynamic_cast(m_viewDef.p()); + if (geoMechView) { m_showVolumeWeightedMean = false; @@ -964,11 +971,18 @@ void Rim3dOverlayInfoConfig::defineUiOrdering(QString uiConfigName, caf::PdmUiOr RimEclipseView* eclipseView = dynamic_cast(m_viewDef.p()); RimEclipseContourMapView* contourMap = dynamic_cast(eclipseView); RimGeoMechView* geoMechView = dynamic_cast(m_viewDef.p()); + + bool isEclipseStatsCase = false; + if (eclipseView) + { + isEclipseStatsCase = dynamic_cast(eclipseView->eclipseCase()) != nullptr; + } + visGroup->add(&m_showAnimProgress); visGroup->add(&m_showCaseInfo); visGroup->add(&m_showResultInfo); - if (!geoMechView && !contourMap) + if (!geoMechView && !contourMap && !isEclipseStatsCase) { visGroup->add(&m_showVolumeWeightedMean); } diff --git a/ApplicationCode/ReservoirDataModel/RigEclipseNativeVisibleCellsStatCalc.cpp b/ApplicationCode/ReservoirDataModel/RigEclipseNativeVisibleCellsStatCalc.cpp index 597c4762f9..0eab39b8c1 100644 --- a/ApplicationCode/ReservoirDataModel/RigEclipseNativeVisibleCellsStatCalc.cpp +++ b/ApplicationCode/ReservoirDataModel/RigEclipseNativeVisibleCellsStatCalc.cpp @@ -107,6 +107,13 @@ void RigEclipseNativeVisibleCellsStatCalc::mobileVolumeWeightedMean(size_t timeS { RigEclipseResultAddress mobPorvAddress(RiaDefines::ResultCatType::STATIC_NATIVE, RiaDefines::mobilePoreVolumeName()); + // For statistics result cases, the pore volume is not available, as RigCaseCellResultsData::createPlaceholderResultEntries + // has not been executed + if (!m_caseData->ensureKnownResultLoaded(mobPorvAddress)) + { + return; + } + m_caseData->ensureKnownResultLoaded(mobPorvAddress); const std::vector& weights = m_caseData->cellScalarResults(mobPorvAddress, 0); From ec1cf83b4e722041517b031725dc64005022ab46 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 5 Aug 2019 21:53:48 +0200 Subject: [PATCH 282/396] #4483 Summary Plot: Data source for well segment number and completions --- .../Tools/RiaSummaryCurveAnalyzer.cpp | 107 +++++++- .../Tools/RiaSummaryCurveAnalyzer.h | 25 +- .../RifEclipseSummaryAddress.cpp | 24 +- .../FileInterface/RifEclipseSummaryAddress.h | 4 +- .../Summary/RimSummaryPlotNameHelper.cpp | 73 +++++- .../Summary/RimSummaryPlotNameHelper.h | 6 + .../Summary/RimSummaryPlotSourceStepping.cpp | 228 +++++++++++------- .../Summary/RimSummaryPlotSourceStepping.h | 7 +- .../UnitTests/CMakeLists_files.cmake | 1 + .../RiaSummaryCurveAnalyzer-Test.cpp | 134 ++++++++++ 10 files changed, 488 insertions(+), 121 deletions(-) create mode 100644 ApplicationCode/UnitTests/RiaSummaryCurveAnalyzer-Test.cpp diff --git a/ApplicationCode/Application/Tools/RiaSummaryCurveAnalyzer.cpp b/ApplicationCode/Application/Tools/RiaSummaryCurveAnalyzer.cpp index 9b0f7f973a..35feb92961 100644 --- a/ApplicationCode/Application/Tools/RiaSummaryCurveAnalyzer.cpp +++ b/ApplicationCode/Application/Tools/RiaSummaryCurveAnalyzer.cpp @@ -26,8 +26,6 @@ #include -#include - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -125,6 +123,50 @@ std::set RiaSummaryCurveAnalyzer::regionNumbers() const return m_regionNumbers; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::set RiaSummaryCurveAnalyzer::wellCompletions(const std::string& wellName) const +{ + std::set connections; + + for (const auto& conn : m_wellCompletions) + { + if (conn.first == wellName) + { + connections.insert(conn.second); + } + } + + return connections; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::set RiaSummaryCurveAnalyzer::wellSegmentNumbers(const std::string& wellName) const +{ + std::set segmentNumberForWell; + + for (const auto& wellSegment : m_wellSegmentNumbers) + { + if (wellName.empty() || std::get<0>(wellSegment) == wellName) + { + segmentNumberForWell.insert(std::get<1>(wellSegment)); + } + } + + return segmentNumberForWell; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::set RiaSummaryCurveAnalyzer::blocks() const +{ + return m_blocks; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -136,33 +178,57 @@ std::set RiaSummaryCurveAnalyzer:: //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::vector RiaSummaryCurveAnalyzer::identifierTexts(RifEclipseSummaryAddress::SummaryVarCategory category) const +std::vector RiaSummaryCurveAnalyzer::identifierTexts(RifEclipseSummaryAddress::SummaryVarCategory category, + const std::string& secondaryIdentifier) const { - std::vector stringSet; + std::vector identifierStrings; if (category == RifEclipseSummaryAddress::SUMMARY_REGION) { for (const auto& regionNumber : m_regionNumbers) { - stringSet.push_back(QString::number(regionNumber)); + identifierStrings.push_back(QString::number(regionNumber)); } } else if (category == RifEclipseSummaryAddress::SUMMARY_WELL) { for (const auto& wellName : m_wellNames) { - stringSet.push_back(QString::fromStdString(wellName)); + identifierStrings.push_back(QString::fromStdString(wellName)); } } else if (category == RifEclipseSummaryAddress::SUMMARY_WELL_GROUP) { for (const auto& wellGroupName : m_wellGroupNames) { - stringSet.push_back(QString::fromStdString(wellGroupName)); + identifierStrings.push_back(QString::fromStdString(wellGroupName)); + } + } + else if (category == RifEclipseSummaryAddress::SUMMARY_BLOCK) + { + for (const auto& ijkBlock : m_blocks) + { + identifierStrings.push_back(QString::fromStdString(ijkBlock)); + } + } + else if (category == RifEclipseSummaryAddress::SUMMARY_WELL_SEGMENT) + { + auto segmentNumbers = wellSegmentNumbers(secondaryIdentifier); + for (const auto& segment : segmentNumbers) + { + identifierStrings.push_back(QString::number(segment)); + } + } + else if (category == RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION) + { + auto connections = wellCompletions(secondaryIdentifier); + for (const auto& conn : connections) + { + identifierStrings.push_back(QString::fromStdString(conn)); } } - return stringSet; + return identifierStrings; } //-------------------------------------------------------------------------------------------------- @@ -213,6 +279,9 @@ void RiaSummaryCurveAnalyzer::clear() m_wellGroupNames.clear(); m_regionNumbers.clear(); m_categories.clear(); + m_wellCompletions.clear(); + m_wellSegmentNumbers.clear(); + m_blocks.clear(); } //-------------------------------------------------------------------------------------------------- @@ -267,9 +336,11 @@ void RiaSummaryCurveAnalyzer::computeQuantityNamesWithHistory() const //-------------------------------------------------------------------------------------------------- void RiaSummaryCurveAnalyzer::analyzeSingleAddress(const RifEclipseSummaryAddress& address) { - if (!address.wellName().empty()) + const std::string& wellName = address.wellName(); + + if (!wellName.empty()) { - m_wellNames.insert(address.wellName()); + m_wellNames.insert(wellName); } if (!address.quantityName().empty()) @@ -287,6 +358,22 @@ void RiaSummaryCurveAnalyzer::analyzeSingleAddress(const RifEclipseSummaryAddres m_regionNumbers.insert(address.regionNumber()); } + if (address.category() == RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION) + { + auto wellNameAndCompletion = std::make_pair(wellName, address.blockAsString()); + m_wellCompletions.insert(wellNameAndCompletion); + } + else if (address.category() == RifEclipseSummaryAddress::SUMMARY_WELL_SEGMENT) + { + auto wellNameAndSegment = std::make_pair(wellName, address.wellSegmentNumber()); + m_wellSegmentNumbers.insert(wellNameAndSegment); + } + else if (address.category() == RifEclipseSummaryAddress::SUMMARY_BLOCK) + { + auto text = address.blockAsString(); + m_blocks.insert(text); + } + if (address.category() != RifEclipseSummaryAddress::SUMMARY_INVALID) { m_categories.insert(address.category()); diff --git a/ApplicationCode/Application/Tools/RiaSummaryCurveAnalyzer.h b/ApplicationCode/Application/Tools/RiaSummaryCurveAnalyzer.h index fea237f115..4e1070eea0 100644 --- a/ApplicationCode/Application/Tools/RiaSummaryCurveAnalyzer.h +++ b/ApplicationCode/Application/Tools/RiaSummaryCurveAnalyzer.h @@ -22,6 +22,7 @@ #include #include +#include #include class RimSummaryCurveCollection; @@ -44,18 +45,23 @@ public: std::set quantities() const; std::set quantityNamesWithHistory() const; std::set quantityNamesNoHistory() const; - + std::string quantityNameForTitle() const; std::set wellNames() const; std::set wellGroupNames() const; std::set regionNumbers() const; + std::set wellCompletions(const std::string& wellName) const; + std::set wellSegmentNumbers(const std::string& wellName) const; + std::set blocks() const; + std::set categories() const; - std::vector identifierTexts(RifEclipseSummaryAddress::SummaryVarCategory category) const; + std::vector identifierTexts(RifEclipseSummaryAddress::SummaryVarCategory category, + const std::string& secondaryIdentifier) const; - static std::vector addressesForCategory(const std::set& addresses, + static std::vector addressesForCategory(const std::set& addresses, RifEclipseSummaryAddress::SummaryVarCategory category); static std::string correspondingHistorySummaryCurveName(const std::string& curveName); @@ -67,13 +73,16 @@ private: void analyzeSingleAddress(const RifEclipseSummaryAddress& address); private: - std::set m_quantities; + std::set m_quantities; mutable std::set m_quantitiesWithMatchingHistory; mutable std::set m_quantitiesNoMatchingHistory; - - std::set m_wellNames; - std::set m_wellGroupNames; - std::set m_regionNumbers; + + std::set m_wellNames; + std::set m_wellGroupNames; + std::set m_regionNumbers; + std::set> m_wellCompletions; + std::set> m_wellSegmentNumbers; + std::set m_blocks; std::set m_categories; }; diff --git a/ApplicationCode/FileInterface/RifEclipseSummaryAddress.cpp b/ApplicationCode/FileInterface/RifEclipseSummaryAddress.cpp index ea8c0fd9d0..d1bdd2a451 100644 --- a/ApplicationCode/FileInterface/RifEclipseSummaryAddress.cpp +++ b/ApplicationCode/FileInterface/RifEclipseSummaryAddress.cpp @@ -581,7 +581,7 @@ std::string RifEclipseSummaryAddress::uiText() const case SUMMARY_WELL_COMPLETION: { text += ":" + this->wellName(); - text += ":" + formatUiTextIJK(); + text += ":" + blockAsString(); } break; case SUMMARY_WELL_LGR: @@ -594,7 +594,7 @@ std::string RifEclipseSummaryAddress::uiText() const { text += ":" + this->lgrName(); text += ":" + this->wellName(); - text += ":" + formatUiTextIJK(); + text += ":" + blockAsString(); } break; case SUMMARY_WELL_SEGMENT: @@ -605,13 +605,13 @@ std::string RifEclipseSummaryAddress::uiText() const break; case SUMMARY_BLOCK: { - text += ":" + formatUiTextIJK(); + text += ":" + blockAsString(); } break; case SUMMARY_BLOCK_LGR: { text += ":" + this->lgrName(); - text += ":" + formatUiTextIJK(); + text += ":" + blockAsString(); } break; case SUMMARY_AQUIFER: @@ -635,7 +635,7 @@ std::string RifEclipseSummaryAddress::uiText(RifEclipseSummaryAddress::SummaryId case INPUT_REGION_2_REGION: return formatUiTextRegionToRegion(); case INPUT_WELL_NAME: return wellName(); case INPUT_WELL_GROUP_NAME: return wellGroupName(); - case INPUT_CELL_IJK: return formatUiTextIJK(); + case INPUT_CELL_IJK: return blockAsString(); case INPUT_LGR_NAME: return lgrName(); case INPUT_SEGMENT_NUMBER: return std::to_string(wellSegmentNumber()); case INPUT_AQUIFER_NUMBER: return std::to_string(aquiferNumber()); @@ -719,6 +719,18 @@ bool RifEclipseSummaryAddress::isValid() const return true; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RifEclipseSummaryAddress::setCellIjk(const std::string& uiText) +{ + auto vec = RifEclipseSummaryAddress::ijkTupleFromUiText(uiText); + + m_cellI = std::get<0>(vec); + m_cellJ = std::get<1>(vec); + m_cellK = std::get<2>(vec); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -770,7 +782,7 @@ std::string RifEclipseSummaryAddress::baseQuantityName(const std::string& quanti //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::string RifEclipseSummaryAddress::formatUiTextIJK() const +std::string RifEclipseSummaryAddress::blockAsString() const { return std::to_string(this->cellI()) + ", " + std::to_string(this->cellJ()) + ", " diff --git a/ApplicationCode/FileInterface/RifEclipseSummaryAddress.h b/ApplicationCode/FileInterface/RifEclipseSummaryAddress.h index b321d648bf..8635f029da 100644 --- a/ApplicationCode/FileInterface/RifEclipseSummaryAddress.h +++ b/ApplicationCode/FileInterface/RifEclipseSummaryAddress.h @@ -162,6 +162,7 @@ public: int cellJ() const { return m_cellJ; } int cellK() const { return m_cellK; } int aquiferNumber() const { return m_aquiferNumber; } + std::string blockAsString() const; const std::string ensembleStatisticsQuantityName() const; @@ -176,6 +177,8 @@ public: void setWellGroupName(const std::string& wellGroupName) { m_wellGroupName = wellGroupName; } void setRegion(int region) { m_regionNumber = (int16_t)region; } void setAquiferNumber(int aquiferNumber) { m_aquiferNumber = (int16_t)aquiferNumber; } + void setCellIjk(const std::string& uiText); + void setWellSegmentNumber(int segment) { m_wellSegmentNumber = (int16_t)segment; } void setAsErrorResult() { m_isErrorResult = true; } bool isErrorResult() const { return m_isErrorResult; } @@ -184,7 +187,6 @@ public: private: bool isValidEclipseCategory() const; static std::string baseQuantityName(const std::string& quantityName); - std::string formatUiTextIJK() const; static std::tuple ijkTupleFromUiText(const std::string &s); std::string formatUiTextRegionToRegion() const; std::pair regionToRegionPairFromUiText(const std::string &s); diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlotNameHelper.cpp b/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlotNameHelper.cpp index 367f19f6cb..e20b651947 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlotNameHelper.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlotNameHelper.cpp @@ -117,6 +117,24 @@ QString RimSummaryPlotNameHelper::plotTitle() const title += "Region : " + QString::fromStdString(m_titleRegion); } + if (!m_titleBlock.empty()) + { + if (!title.isEmpty()) title += ", "; + title += "Block : " + QString::fromStdString(m_titleBlock); + } + + if (!m_titleSegment.empty()) + { + if (!title.isEmpty()) title += ", "; + title += "Segment : " + QString::fromStdString(m_titleSegment); + } + + if (!m_titleCompletion.empty()) + { + if (!title.isEmpty()) title += ", "; + title += "Completion : " + QString::fromStdString(m_titleCompletion); + } + if (!m_titleQuantity.empty()) { if (!title.isEmpty()) title += ", "; @@ -171,6 +189,30 @@ bool RimSummaryPlotNameHelper::isCaseInTitle() const return !m_titleCaseName.isEmpty(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimSummaryPlotNameHelper::isBlockInTitle() const +{ + return !m_titleBlock.empty(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimSummaryPlotNameHelper::isSegmentInTitle() const +{ + return !m_titleSegment.empty(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimSummaryPlotNameHelper::isCompletionInTitle() const +{ + return !m_titleCompletion.empty(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -180,6 +222,9 @@ void RimSummaryPlotNameHelper::clearTitleSubStrings() m_titleRegion.clear(); m_titleWellName.clear(); m_titleRegion.clear(); + m_titleBlock.clear(); + m_titleSegment.clear(); + m_titleCompletion.clear(); m_titleCaseName.clear(); } @@ -195,6 +240,7 @@ void RimSummaryPlotNameHelper::extractPlotTitleSubStrings() auto wellNames = m_analyzer.wellNames(); auto wellGroupNames = m_analyzer.wellGroupNames(); auto regions = m_analyzer.regionNumbers(); + auto blocks = m_analyzer.blocks(); auto categories = m_analyzer.categories(); if (categories.size() == 1) @@ -207,6 +253,22 @@ void RimSummaryPlotNameHelper::extractPlotTitleSubStrings() if (wellNames.size() == 1) { m_titleWellName = *(wellNames.begin()); + + { + auto segments = m_analyzer.wellSegmentNumbers(m_titleWellName); + if (segments.size() == 1) + { + m_titleSegment = std::to_string(*(segments.begin())); + } + } + + { + auto completions = m_analyzer.wellCompletions(m_titleWellName); + if (completions.size() == 1) + { + m_titleCompletion = *(completions.begin()); + } + } } if (wellGroupNames.size() == 1) @@ -218,9 +280,14 @@ void RimSummaryPlotNameHelper::extractPlotTitleSubStrings() { m_titleRegion = std::to_string(*(regions.begin())); } + + if (blocks.size() == 1) + { + m_titleBlock = *(blocks.begin()); + } } - auto summaryCases = setOfSummaryCases(); + auto summaryCases = setOfSummaryCases(); auto ensembleCases = setOfEnsembleCases(); if (summaryCases.size() == 1 && ensembleCases.empty()) @@ -243,7 +310,7 @@ void RimSummaryPlotNameHelper::extractPlotTitleSubStrings() } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- std::set RimSummaryPlotNameHelper::setOfSummaryCases() const { @@ -258,7 +325,7 @@ std::set RimSummaryPlotNameHelper::setOfSummaryCases() const } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- std::set RimSummaryPlotNameHelper::setOfEnsembleCases() const { diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlotNameHelper.h b/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlotNameHelper.h index 6c4bc4d237..b9c5d372d9 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlotNameHelper.h +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlotNameHelper.h @@ -54,6 +54,9 @@ public: bool isWellGroupNameInTitle() const; bool isRegionInTitle() const; bool isCaseInTitle() const; + bool isBlockInTitle() const; + bool isSegmentInTitle() const; + bool isCompletionInTitle() const; private: void clearTitleSubStrings(); @@ -73,6 +76,9 @@ private: std::string m_titleWellName; std::string m_titleWellGroupName; std::string m_titleRegion; + std::string m_titleBlock; + std::string m_titleSegment; + std::string m_titleCompletion; QString m_titleCaseName; }; diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlotSourceStepping.cpp b/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlotSourceStepping.cpp index 0712440fcb..5ed60b46a4 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlotSourceStepping.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlotSourceStepping.cpp @@ -67,7 +67,11 @@ RimSummaryPlotSourceStepping::RimSummaryPlotSourceStepping() CAF_PDM_InitFieldNoDefault(&m_wellGroupName, "GroupName", "Group Name", "", "", ""); CAF_PDM_InitFieldNoDefault(&m_region, "Region", "Region", "", "", ""); CAF_PDM_InitFieldNoDefault(&m_quantity, "Quantities", "Quantity", "", "", ""); - + + CAF_PDM_InitFieldNoDefault(&m_cellBlock, "CellBlock", "Block", "", "", ""); + CAF_PDM_InitFieldNoDefault(&m_segment, "Segment", "Segment", "", "", ""); + CAF_PDM_InitFieldNoDefault(&m_completion, "Completion", "Completion", "", "", ""); + CAF_PDM_InitFieldNoDefault(&m_ensemble, "Ensemble", "Ensemble", "", "", ""); CAF_PDM_InitFieldNoDefault(&m_placeholderForLabel, "Placeholder", "", "", "", ""); @@ -284,6 +288,7 @@ QList RimSummaryPlotSourceStepping::calculateValueOption else { RifEclipseSummaryAddress::SummaryVarCategory category = RifEclipseSummaryAddress::SUMMARY_INVALID; + std::string secondaryIdentifier; if (fieldNeedingOptions == &m_wellName) { @@ -297,8 +302,22 @@ QList RimSummaryPlotSourceStepping::calculateValueOption { category = RifEclipseSummaryAddress::SUMMARY_WELL_GROUP; } + else if (fieldNeedingOptions == &m_cellBlock) + { + category = RifEclipseSummaryAddress::SUMMARY_BLOCK; + } + else if (fieldNeedingOptions == &m_segment) + { + secondaryIdentifier = m_wellName().toStdString(); + category = RifEclipseSummaryAddress::SUMMARY_WELL_SEGMENT; + } + else if (fieldNeedingOptions == &m_completion) + { + secondaryIdentifier = m_wellName().toStdString(); + category = RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION; + } - std::set identifierTexts; + std::vector identifierTexts; if (category != RifEclipseSummaryAddress::SUMMARY_INVALID) { @@ -308,10 +327,7 @@ QList RimSummaryPlotSourceStepping::calculateValueOption if (analyzer) { - for (const auto& t : analyzer->identifierTexts(category)) - { - identifierTexts.insert(t); - } + identifierTexts = analyzer->identifierTexts(category, secondaryIdentifier); } } } @@ -432,68 +448,6 @@ void RimSummaryPlotSourceStepping::fieldChangedByUi(const caf::PdmFieldHandle* c m_region.uiCapability()->updateConnectedEditors(); m_quantity.uiCapability()->updateConnectedEditors(); } - else if (changedField == &m_wellName) - { - for (auto curve : curves) - { - if (isYAxisStepping()) - { - RifEclipseSummaryAddress adr = curve->summaryAddressY(); - updateAddressIfMatching(oldValue, newValue, RifEclipseSummaryAddress::SUMMARY_WELL, &adr); - curve->setSummaryAddressY(adr); - } - - if (isXAxisStepping()) - { - RifEclipseSummaryAddress adr = curve->summaryAddressX(); - updateAddressIfMatching(oldValue, newValue, RifEclipseSummaryAddress::SUMMARY_WELL, &adr); - curve->setSummaryAddressX(adr); - } - } - - if (ensembleCurveColl) - { - for (auto curveSet : ensembleCurveColl->curveSets()) - { - auto adr = curveSet->summaryAddress(); - updateAddressIfMatching(oldValue, newValue, RifEclipseSummaryAddress::SUMMARY_WELL, &adr); - curveSet->setSummaryAddress(adr); - } - } - - triggerLoadDataAndUpdate = true; - } - else if (changedField == &m_region) - { - for (auto curve : curves) - { - if (isYAxisStepping()) - { - RifEclipseSummaryAddress adr = curve->summaryAddressY(); - updateAddressIfMatching(oldValue, newValue, RifEclipseSummaryAddress::SUMMARY_REGION, &adr); - curve->setSummaryAddressY(adr); - } - - if (isXAxisStepping()) - { - RifEclipseSummaryAddress adr = curve->summaryAddressX(); - updateAddressIfMatching(oldValue, newValue, RifEclipseSummaryAddress::SUMMARY_REGION, &adr); - curve->setSummaryAddressX(adr); - } - } - - if (ensembleCurveColl) - { - for (auto curveSet : ensembleCurveColl->curveSets()) - { - auto adr = curveSet->summaryAddress(); - updateAddressIfMatching(oldValue, newValue, RifEclipseSummaryAddress::SUMMARY_REGION, &adr); - curveSet->setSummaryAddress(adr); - } - } - - triggerLoadDataAndUpdate = true; - } else if (changedField == &m_quantity) { for (auto curve : curves) @@ -525,36 +479,65 @@ void RimSummaryPlotSourceStepping::fieldChangedByUi(const caf::PdmFieldHandle* c triggerLoadDataAndUpdate = true; } - else if (changedField == &m_wellGroupName) + { - for (auto curve : curves) + RifEclipseSummaryAddress::SummaryVarCategory summaryCategoryToModify = RifEclipseSummaryAddress::SUMMARY_INVALID; + if (changedField == &m_wellName) { - if (isYAxisStepping()) - { - RifEclipseSummaryAddress adr = curve->summaryAddressY(); - updateAddressIfMatching(oldValue, newValue, RifEclipseSummaryAddress::SUMMARY_WELL_GROUP, &adr); - curve->setSummaryAddressY(adr); - } - - if (isXAxisStepping()) - { - RifEclipseSummaryAddress adr = curve->summaryAddressX(); - updateAddressIfMatching(oldValue, newValue, RifEclipseSummaryAddress::SUMMARY_WELL_GROUP, &adr); - curve->setSummaryAddressX(adr); - } + summaryCategoryToModify = RifEclipseSummaryAddress::SUMMARY_WELL; + } + else if (changedField == &m_region) + { + summaryCategoryToModify = RifEclipseSummaryAddress::SUMMARY_REGION; + } + else if (changedField == &m_wellGroupName) + { + summaryCategoryToModify = RifEclipseSummaryAddress::SUMMARY_WELL_GROUP; + } + else if (changedField == &m_cellBlock) + { + summaryCategoryToModify = RifEclipseSummaryAddress::SUMMARY_BLOCK; + } + else if (changedField == &m_segment) + { + summaryCategoryToModify = RifEclipseSummaryAddress::SUMMARY_WELL_SEGMENT; + } + else if (changedField == &m_completion) + { + summaryCategoryToModify = RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION; } - if (ensembleCurveColl) + if (summaryCategoryToModify != RifEclipseSummaryAddress::SUMMARY_INVALID) { - for (auto curveSet : ensembleCurveColl->curveSets()) + for (auto curve : curves) { - auto adr = curveSet->summaryAddress(); - updateAddressIfMatching(oldValue, newValue, RifEclipseSummaryAddress::SUMMARY_WELL_GROUP, &adr); - curveSet->setSummaryAddress(adr); - } - } + if (isYAxisStepping()) + { + RifEclipseSummaryAddress adr = curve->summaryAddressY(); + updateAddressIfMatching(oldValue, newValue, summaryCategoryToModify, &adr); + curve->setSummaryAddressY(adr); + } - triggerLoadDataAndUpdate = true; + if (isXAxisStepping()) + { + RifEclipseSummaryAddress adr = curve->summaryAddressX(); + updateAddressIfMatching(oldValue, newValue, summaryCategoryToModify, &adr); + curve->setSummaryAddressX(adr); + } + } + + if (ensembleCurveColl) + { + for (auto curveSet : ensembleCurveColl->curveSets()) + { + auto adr = curveSet->summaryAddress(); + updateAddressIfMatching(oldValue, newValue, summaryCategoryToModify, &adr); + curveSet->setSummaryAddress(adr); + } + } + + triggerLoadDataAndUpdate = true; + } } if (triggerLoadDataAndUpdate) @@ -654,6 +637,21 @@ caf::PdmValueField* RimSummaryPlotSourceStepping::fieldToModify() return &m_region; } + if (analyzer.blocks().size() == 1) + { + return &m_cellBlock; + } + + if (analyzer.wellNames().size() == 1) + { + auto wellName = *(analyzer.wellNames().begin()); + + if (analyzer.wellSegmentNumbers(wellName).size() == 1) + { + return &m_segment; + } + } + return nullptr; } @@ -833,6 +831,30 @@ std::vector RimSummaryPlotSourceStepping::computeVisibleFi fieldsCommonForAllCurves.push_back(&m_region); } + if (analyzer.wellSegmentNumbers(m_wellName().toStdString()).size() == 1) + { + QString txt = QString::number(*(analyzer.wellSegmentNumbers(m_wellName().toStdString()).begin())); + m_segment = txt; + + fieldsCommonForAllCurves.push_back(&m_segment); + } + + if (analyzer.blocks().size() == 1) + { + QString txt = QString::fromStdString(*(analyzer.blocks().begin())); + m_cellBlock = txt; + + fieldsCommonForAllCurves.push_back(&m_cellBlock); + } + + if (analyzer.wellCompletions(m_wellName().toStdString()).size() == 1) + { + QString txt = QString::fromStdString(*(analyzer.wellCompletions(m_wellName().toStdString()).begin())); + m_completion = txt; + + fieldsCommonForAllCurves.push_back(&m_completion); + } + if (!analyzer.quantityNameForTitle().empty()) { QString txt = QString::fromStdString(analyzer.quantityNameForTitle()); @@ -959,7 +981,7 @@ bool RimSummaryPlotSourceStepping::updateAddressIfMatching(const QVariant& return true; } } - else if (RifEclipseSummaryAddress::isDependentOnWellName(category)) + else if (category == RifEclipseSummaryAddress::SUMMARY_WELL) { std::string oldString = oldValue.toString().toStdString(); std::string newString = newValue.toString().toStdString(); @@ -971,6 +993,28 @@ bool RimSummaryPlotSourceStepping::updateAddressIfMatching(const QVariant& return true; } } + else if (category == RifEclipseSummaryAddress::SUMMARY_BLOCK || RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION) + { + std::string oldString = oldValue.toString().toStdString(); + std::string newString = newValue.toString().toStdString(); + if (adr->blockAsString() == oldString) + { + adr->setCellIjk(newString); + + return true; + } + } + else if (category == RifEclipseSummaryAddress::SUMMARY_WELL_SEGMENT) + { + int oldInt = oldValue.toInt(); + int newInt = newValue.toInt(); + if (adr->wellSegmentNumber() == oldInt) + { + adr->setWellSegmentNumber(newInt); + + return true; + } + } return false; } diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlotSourceStepping.h b/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlotSourceStepping.h index 3fb33e26ca..746ec9777b 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlotSourceStepping.h +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlotSourceStepping.h @@ -18,6 +18,7 @@ #pragma once + #include "RiaSummaryCurveAnalyzer.h" #include "RifEclipseSummaryAddress.h" @@ -114,7 +115,11 @@ private: caf::PdmField m_region; caf::PdmField m_quantity; caf::PdmField m_placeholderForLabel; - + + caf::PdmField m_cellBlock; + caf::PdmField m_segment; + caf::PdmField m_completion; + caf::PdmField m_includeEnsembleCasesForCaseStepping; SourceSteppingType m_sourceSteppingType; diff --git a/ApplicationCode/UnitTests/CMakeLists_files.cmake b/ApplicationCode/UnitTests/CMakeLists_files.cmake index 160b3fda66..7f7dec4dcb 100644 --- a/ApplicationCode/UnitTests/CMakeLists_files.cmake +++ b/ApplicationCode/UnitTests/CMakeLists_files.cmake @@ -57,6 +57,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RimWellPathCompletions-Test.cpp ${CMAKE_CURRENT_LIST_DIR}/RimSummaryCaseCollection-Test.cpp ${CMAKE_CURRENT_LIST_DIR}/RifActiveCellsReader-Test.cpp ${CMAKE_CURRENT_LIST_DIR}/RifCsvDataTableFormatter-Test.cpp +${CMAKE_CURRENT_LIST_DIR}/RiaSummaryCurveAnalyzer-Test.cpp ) if (RESINSIGHT_ENABLE_GRPC) diff --git a/ApplicationCode/UnitTests/RiaSummaryCurveAnalyzer-Test.cpp b/ApplicationCode/UnitTests/RiaSummaryCurveAnalyzer-Test.cpp new file mode 100644 index 0000000000..8ef1d3efcd --- /dev/null +++ b/ApplicationCode/UnitTests/RiaSummaryCurveAnalyzer-Test.cpp @@ -0,0 +1,134 @@ +#include "gtest/gtest.h" + +#include "RiaSummaryCurveAnalyzer.h" + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +TEST(RiaSummaryCurveAnalyzer, WellCompletions) +{ + std::vector addresses; + + // Well A + std::string wellNameA = "well_name_a"; + { + RifEclipseSummaryAddress adr = RifEclipseSummaryAddress::wellCompletionAddress("quantity_name", wellNameA, 1, 2, 3); + addresses.push_back(adr); + } + { + RifEclipseSummaryAddress adr = RifEclipseSummaryAddress::wellCompletionAddress("quantity_name", wellNameA, 1, 2, 3); + addresses.push_back(adr); + } + { + RifEclipseSummaryAddress adr = RifEclipseSummaryAddress::wellCompletionAddress("quantity_name", wellNameA, 5, 2, 3); + addresses.push_back(adr); + } + + // Well B + std::string wellNameB = "well_name_b"; + { + RifEclipseSummaryAddress adr = RifEclipseSummaryAddress::wellCompletionAddress("quantity_name", wellNameB, 5, 2, 3); + addresses.push_back(adr); + } + { + RifEclipseSummaryAddress adr = RifEclipseSummaryAddress::wellCompletionAddress("quantity_name", wellNameB, 5, 4, 3); + addresses.push_back(adr); + } + { + RifEclipseSummaryAddress adr = RifEclipseSummaryAddress::wellCompletionAddress("quantity_name", wellNameB, 5, 4, 30); + addresses.push_back(adr); + } + + RiaSummaryCurveAnalyzer analyzer; + analyzer.appendAdresses(addresses); + + EXPECT_EQ(2u, analyzer.wellNames().size()); + + auto completionsForA = analyzer.wellCompletions(wellNameA); + EXPECT_EQ(2u, completionsForA.size()); + + auto completionsForB = analyzer.wellCompletions(wellNameB); + EXPECT_EQ(3u, completionsForB.size()); + std::string tupleToFind = "5, 4, 30"; + EXPECT_TRUE(completionsForB.find(tupleToFind) != completionsForB.end()); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +TEST(RiaSummaryCurveAnalyzer, WellSegments) +{ + std::vector addresses; + + // Well A + std::string wellNameA = "well_name_a"; + { + RifEclipseSummaryAddress adr = RifEclipseSummaryAddress::wellSegmentAddress("quantity_name", wellNameA, 1); + addresses.push_back(adr); + } + { + RifEclipseSummaryAddress adr = RifEclipseSummaryAddress::wellSegmentAddress("quantity_name", wellNameA, 1); + addresses.push_back(adr); + } + { + RifEclipseSummaryAddress adr = RifEclipseSummaryAddress::wellSegmentAddress("quantity_name", wellNameA, 30); + addresses.push_back(adr); + } + + // Well B + std::string wellNameB = "well_name_b"; + { + RifEclipseSummaryAddress adr = RifEclipseSummaryAddress::wellSegmentAddress("quantity_name", wellNameB, 1); + addresses.push_back(adr); + } + { + RifEclipseSummaryAddress adr = RifEclipseSummaryAddress::wellSegmentAddress("quantity_name", wellNameB, 3); + addresses.push_back(adr); + } + { + RifEclipseSummaryAddress adr = RifEclipseSummaryAddress::wellSegmentAddress("quantity_name", wellNameB, 10); + addresses.push_back(adr); + } + + RiaSummaryCurveAnalyzer analyzer; + analyzer.appendAdresses(addresses); + + EXPECT_EQ(2u, analyzer.wellNames().size()); + + auto segmentsForA = analyzer.wellSegmentNumbers(wellNameA); + EXPECT_EQ(2u, segmentsForA.size()); + + auto segmentsForB = analyzer.wellSegmentNumbers(wellNameB); + EXPECT_EQ(3u, segmentsForB.size()); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +TEST(RiaSummaryCurveAnalyzer, CellBlocks) +{ + std::vector addresses; + + { + RifEclipseSummaryAddress adr = RifEclipseSummaryAddress::blockAddress("quantity_name", 1, 2, 3); + addresses.push_back(adr); + } + { + RifEclipseSummaryAddress adr = RifEclipseSummaryAddress::blockAddress("quantity_name", 1, 2, 3); + addresses.push_back(adr); + } + { + RifEclipseSummaryAddress adr = RifEclipseSummaryAddress::blockAddress("quantity_name", 2, 2, 3); + addresses.push_back(adr); + } + { + RifEclipseSummaryAddress adr = RifEclipseSummaryAddress::blockAddress("quantity_name", 5, 2, 3); + addresses.push_back(adr); + } + + RiaSummaryCurveAnalyzer analyzer; + analyzer.appendAdresses(addresses); + + auto blocks = analyzer.blocks(); + EXPECT_EQ(3u, blocks.size()); +} From 712fd2a160922c1d49135dd5e818ed33f5bbaf67 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Thu, 1 Aug 2019 15:10:09 +0200 Subject: [PATCH 283/396] Python: add Python process environment to launch of script editor. --- .../Commands/OctaveScriptCommands/RicEditScriptFeature.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/ApplicationCode/Commands/OctaveScriptCommands/RicEditScriptFeature.cpp b/ApplicationCode/Commands/OctaveScriptCommands/RicEditScriptFeature.cpp index 1244ef4ef1..e4a70d21b6 100644 --- a/ApplicationCode/Commands/OctaveScriptCommands/RicEditScriptFeature.cpp +++ b/ApplicationCode/Commands/OctaveScriptCommands/RicEditScriptFeature.cpp @@ -61,6 +61,7 @@ void RicEditScriptFeature::onActionTriggered(bool isChecked) arguments << calcScript->absoluteFileName; QProcess* myProcess = new QProcess(this); + myProcess->setProcessEnvironment(app->pythonProcessEnvironment()); myProcess->start(scriptEditor, arguments); if (!myProcess->waitForStarted(1000)) From 1417fc2be7b89f6206e8f38ada4b899591dc0e41 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Tue, 6 Aug 2019 11:39:09 +0200 Subject: [PATCH 284/396] #4542 Bring highlighted curve to the top and stop altering color of selected curve --- ApplicationCode/UserInterface/RiuQwtPlot.cpp | 22 +++++++------------- ApplicationCode/UserInterface/RiuQwtPlot.h | 1 + 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/ApplicationCode/UserInterface/RiuQwtPlot.cpp b/ApplicationCode/UserInterface/RiuQwtPlot.cpp index d4b06b8dfa..c8ccef6f6c 100644 --- a/ApplicationCode/UserInterface/RiuQwtPlot.cpp +++ b/ApplicationCode/UserInterface/RiuQwtPlot.cpp @@ -263,22 +263,10 @@ void RiuQwtPlot::highlightCurve(const QwtPlotCurve* closestCurve) symbolLineColor = symbol->pen().color(); } + double zValue = plotCurve->z(); if (plotCurve == closestCurve) { - cvf::Color3f cvfBgColor = RiaColorTools::fromQColorTo3f(bgColor); - cvf::Color3f cvfFgColor = RiaColorTools::contrastColor(cvfBgColor); - QColor fgColor = RiaColorTools::toQColor(cvfFgColor); - - QColor blendedColor = RiaColorTools::blendQColors(fgColor, curveColor, 1, 2); - QColor blendedSymbolColor = RiaColorTools::blendQColors(fgColor, symbolColor, 1, 2); - QColor blendedSymbolLineColor = RiaColorTools::blendQColors(fgColor, symbolLineColor, 1, 2); - - plotCurve->setPen(blendedColor, existingPen.width(), existingPen.style()); - if (symbol) - { - symbol->setColor(blendedSymbolColor); - symbol->setPen(blendedSymbolLineColor, symbol->pen().width(), symbol->pen().style()); - } + plotCurve->setZ(zValue + 100.0); } else { @@ -295,6 +283,7 @@ void RiuQwtPlot::highlightCurve(const QwtPlotCurve* closestCurve) } CurveColors curveColors = {curveColor, symbolColor, symbolLineColor}; m_originalCurveColors.insert(std::make_pair(plotCurve, curveColors)); + m_originalZValues.insert(std::make_pair(plotCurve, zValue)); } } } @@ -311,8 +300,10 @@ void RiuQwtPlot::resetCurveHighlighting() { const QPen& existingPen = plotCurve->pen(); auto colors = m_originalCurveColors[plotCurve]; + double zValue = m_originalZValues[plotCurve]; + plotCurve->setPen(colors.lineColor, existingPen.width(), existingPen.style()); - + plotCurve->setZ(zValue); QwtSymbol* symbol = const_cast(plotCurve->symbol()); if (symbol) { @@ -322,6 +313,7 @@ void RiuQwtPlot::resetCurveHighlighting() } } m_originalCurveColors.clear(); + m_originalZValues.clear(); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/UserInterface/RiuQwtPlot.h b/ApplicationCode/UserInterface/RiuQwtPlot.h index e61541e605..065963219f 100644 --- a/ApplicationCode/UserInterface/RiuQwtPlot.h +++ b/ApplicationCode/UserInterface/RiuQwtPlot.h @@ -86,5 +86,6 @@ private: QPointer m_zoomerRight; std::map m_originalCurveColors; + std::map m_originalZValues; }; From 7317e75baecdef888fc114d4d30727e96a4e3248 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Wed, 7 Aug 2019 09:37:55 +0200 Subject: [PATCH 285/396] Added a note on grpc installation when using cmake-gui --- GRPC_install_instructions.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/GRPC_install_instructions.txt b/GRPC_install_instructions.txt index 9800a105a4..b0c7c33072 100644 --- a/GRPC_install_instructions.txt +++ b/GRPC_install_instructions.txt @@ -17,10 +17,13 @@ git clone https://github.com/microsoft/vcpkg.git python -m pip install grpcio-tools * Make sure the python executable is found by setting -DPYTHON_EXECUTABLE=LOCATION_OF_PYTHON.EXE -5. Run cmake with the following statements +5. Run cmake with the following statements: -DRESINSIGHT_ENABLE_GRPC=true -DPYTHON_EXECUTABLE=LOCATION_OF_PYTHON.EXE -DCMAKE_TOOLCHAIN_FILE=LOCATION_OF_VCPKG/scripts/buildsystems/vcpkg.cmake +NOTE: When using the CMake gui, you need to select "Specify toolchain for cross-compiling" + and enter the "LOCATION_OF_VCPKG/scripts/buildsystems/vcpkg.cmake" there. + This path ends up in the CMAKE_TOOLCHAIN_FILE variable. If you do not, protobuffers are not found. -A x64 ############ Linux as STANDALONE GPRC #################################################################### From ecd0c625d20d95a5a20a355af5797a99bacbc2fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Wed, 7 Aug 2019 09:38:42 +0200 Subject: [PATCH 286/396] Put the strange chatch2 from libecl into the Thirdparty folder --- CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1fde6e8c82..d46f908ef0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -137,7 +137,8 @@ else() endif() list(APPEND THIRD_PARTY_LIBRARIES - ecl + ecl + catch2 ) if (MSVC) From 5e2485863c02dafbdabda679ea4b92943bc5be80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Wed, 7 Aug 2019 09:39:24 +0200 Subject: [PATCH 287/396] Fixed missing copy of qt dll's on msvc using cotire --- ApplicationCode/CMakeLists.txt | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/ApplicationCode/CMakeLists.txt b/ApplicationCode/CMakeLists.txt index cc75e1cab8..8a24b8225b 100644 --- a/ApplicationCode/CMakeLists.txt +++ b/ApplicationCode/CMakeLists.txt @@ -483,13 +483,23 @@ endif() if (MSVC) # Qt DLLs - if (RESINSIGHT_BUILD_WITH_QT5) + if (RESINSIGHT_BUILD_WITH_QT5) message(STATUS "Creating post build step for copying Qt DLLs") - foreach (qtlib ${QT_LIBRARIES}) - add_custom_command(TARGET ResInsight POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_if_different $ $ - ) - endforeach(qtlib) + + foreach (qtlib ${QT_LIBRARIES}) + add_custom_command(TARGET ResInsight POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different $ $ + ) + endforeach(qtlib) + + if (_unityTargetName) + foreach (qtlib ${QT_LIBRARIES}) + add_custom_command(TARGET ${_unityTargetName} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different $ $ + ) + endforeach(qtlib) + endif(_unityTargetName) + else() set (QTLIBLIST QtCore QtGui QtGui QtOpenGl QtNetwork QtScript QtScriptTools) foreach (qtlib ${QTLIBLIST}) From 58cef265ec7165293a754e905127abdc1e6404ed Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 7 Aug 2019 14:21:37 +0200 Subject: [PATCH 288/396] #4538 Skip Save project at exit when no data has changed Guard changes in preferences and reset change detector when project is closed --- ApplicationCode/Application/RiaApplication.cpp | 15 ++++++++++++++- ApplicationCode/Application/RiaApplication.h | 1 + ApplicationCode/Application/RiaGuiApplication.cpp | 2 +- .../RicEditPreferencesFeature.cpp | 8 ++++++++ .../RicWellPathsImportSsihubFeature.cpp | 6 ++---- 5 files changed, 26 insertions(+), 6 deletions(-) diff --git a/ApplicationCode/Application/RiaApplication.cpp b/ApplicationCode/Application/RiaApplication.cpp index 696a7d10a6..a4ef5a623b 100644 --- a/ApplicationCode/Application/RiaApplication.cpp +++ b/ApplicationCode/Application/RiaApplication.cpp @@ -84,6 +84,7 @@ #include "RimWellRftPlot.h" #include "cafPdmSettings.h" +#include "cafPdmUiModelChangeDetector.h" #include "cafProgressInfo.h" #include "cafUiProcess.h" #include "cafUtils.h" @@ -305,6 +306,16 @@ bool RiaApplication::openFile(const QString& fileName) return loadingSucceded; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RiaApplication::isProjectSavedToDisc() const +{ + if (m_project.isNull()) return false; + + return caf::Utils::fileExists(m_project->fileName()); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -370,7 +381,7 @@ bool RiaApplication::loadProject(const QString& projectFileName, // Create a absolute path file name, as this is required for update of file references in the project modifier object QString fullPathProjectFileName = caf::Utils::absoluteFileName(projectFileName); - if (!caf::Utils::fileExists(fullPathProjectFileName)) + if (!isProjectSavedToDisc()) { RiaLogging::info(QString("File does not exist : '%1'").arg(fullPathProjectFileName)); return false; @@ -677,6 +688,8 @@ void RiaApplication::closeProject() m_commandQueue.clear(); onProjectClosed(); + + caf::PdmUiModelChangeDetector::instance()->reset(); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/Application/RiaApplication.h b/ApplicationCode/Application/RiaApplication.h index 8ebb5484c1..816c045657 100644 --- a/ApplicationCode/Application/RiaApplication.h +++ b/ApplicationCode/Application/RiaApplication.h @@ -121,6 +121,7 @@ public: bool openFile(const QString& fileName); + bool isProjectSavedToDisc() const; QString currentProjectPath() const; QString createAbsolutePathFromProjectRelativePath(QString projectRelativePath); bool loadProject(const QString& projectFileName); diff --git a/ApplicationCode/Application/RiaGuiApplication.cpp b/ApplicationCode/Application/RiaGuiApplication.cpp index e0c278aad1..f5b6d4740e 100644 --- a/ApplicationCode/Application/RiaGuiApplication.cpp +++ b/ApplicationCode/Application/RiaGuiApplication.cpp @@ -204,7 +204,7 @@ bool RiaGuiApplication::saveProject() { CVF_ASSERT(m_project.notNull()); - if (!caf::Utils::fileExists(m_project->fileName())) + if (!isProjectSavedToDisc()) { return saveProjectPromptForFileName(); } diff --git a/ApplicationCode/Commands/ApplicationCommands/RicEditPreferencesFeature.cpp b/ApplicationCode/Commands/ApplicationCommands/RicEditPreferencesFeature.cpp index 17845b47be..eef944c8d4 100644 --- a/ApplicationCode/Commands/ApplicationCommands/RicEditPreferencesFeature.cpp +++ b/ApplicationCode/Commands/ApplicationCommands/RicEditPreferencesFeature.cpp @@ -24,6 +24,7 @@ #include "RiuPropertyViewTabWidget.h" #include "cafPdmSettings.h" +#include "cafPdmUiModelChangeDetector.h" #include @@ -65,6 +66,13 @@ void RicEditPreferencesFeature::onActionTriggered(bool isChecked) caf::PdmSettings::readFieldsFromApplicationStore(app->preferences()); app->preferences()->initAfterReadRecursively(); } + + if (!app->isProjectSavedToDisc()) + { + // Always reset change detector when modifying preferences, as these changes are irrelevant + // when the project we work on is not saved to disc + caf::PdmUiModelChangeDetector::instance()->reset(); + } } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/Commands/SsiHubImportCommands/RicWellPathsImportSsihubFeature.cpp b/ApplicationCode/Commands/SsiHubImportCommands/RicWellPathsImportSsihubFeature.cpp index 0b9d0e3514..a035e6b25e 100644 --- a/ApplicationCode/Commands/SsiHubImportCommands/RicWellPathsImportSsihubFeature.cpp +++ b/ApplicationCode/Commands/SsiHubImportCommands/RicWellPathsImportSsihubFeature.cpp @@ -27,8 +27,6 @@ #include "RiuMainWindow.h" #include "RiuWellImportWizard.h" -#include "cafUtils.h" - #include #include #include @@ -52,7 +50,7 @@ void RicWellPathsImportSsihubFeature::onActionTriggered(bool isChecked) RiaApplication* app = RiaApplication::instance(); if (!app->project()) return; - if (!caf::Utils::fileExists(app->project()->fileName())) + if (!app->isProjectSavedToDisc()) { RiaGuiApplication* guiApp = RiaGuiApplication::instance(); if (guiApp) @@ -74,7 +72,7 @@ void RicWellPathsImportSsihubFeature::onActionTriggered(bool isChecked) } } - if (!caf::Utils::fileExists(app->project()->fileName())) + if (!app->isProjectSavedToDisc()) { return; } From 194c8b7278b03690857eee1f428b986950d8e067 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 7 Aug 2019 15:09:52 +0200 Subject: [PATCH 289/396] Avoid linking ResInsight with catch2 --- CMakeLists.txt | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d46f908ef0..387933f46f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -138,15 +138,12 @@ else() list(APPEND THIRD_PARTY_LIBRARIES ecl - catch2 ) - if (MSVC) - set_property(TARGET - ecl - PROPERTY FOLDER "Thirdparty/ERT" - ) - endif() + set_property(TARGET + catch2 + PROPERTY FOLDER "Thirdparty" + ) # Restore original state set(BUILD_SHARED_LIBS ${ORIGINAL_BUILD_SHARED_LIBS}) From 8cb3ac5b1f50b2bf22a55e338db4ed95f8203d8c Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 7 Aug 2019 16:32:07 +0200 Subject: [PATCH 290/396] #4538 Check fullPathProjectFileName instead of project --- ApplicationCode/Application/RiaApplication.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ApplicationCode/Application/RiaApplication.cpp b/ApplicationCode/Application/RiaApplication.cpp index a4ef5a623b..cdc0ff382e 100644 --- a/ApplicationCode/Application/RiaApplication.cpp +++ b/ApplicationCode/Application/RiaApplication.cpp @@ -381,7 +381,7 @@ bool RiaApplication::loadProject(const QString& projectFileName, // Create a absolute path file name, as this is required for update of file references in the project modifier object QString fullPathProjectFileName = caf::Utils::absoluteFileName(projectFileName); - if (!isProjectSavedToDisc()) + if (!caf::Utils::fileExists(fullPathProjectFileName)) { RiaLogging::info(QString("File does not exist : '%1'").arg(fullPathProjectFileName)); return false; From 4381f679e5a909906bd5517efa2b49d9c436bdf7 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 8 Aug 2019 08:15:04 +0200 Subject: [PATCH 291/396] Python pytest : Issue project.close() after each test --- ApplicationCode/GrpcInterface/Python/rips/tests/conftest.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ApplicationCode/GrpcInterface/Python/rips/tests/conftest.py b/ApplicationCode/GrpcInterface/Python/rips/tests/conftest.py index 15d630729c..14345eabd1 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/tests/conftest.py +++ b/ApplicationCode/GrpcInterface/Python/rips/tests/conftest.py @@ -14,7 +14,9 @@ def rips_instance(): @pytest.fixture def initializeTest(): - _rips_instance.project.close() + _rips_instance.project.close() # make sure ResInsight is clean before execution of test + yield initializeTest + _rips_instance.project.close() # make sure ResInsight is clean after test def pytest_addoption(parser): parser.addoption("--console", action="store_true", default=False, help="Run as console application") From 209040899ab0780aea3350f816fc9c5a290bfc8b Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 8 Aug 2019 08:23:03 +0200 Subject: [PATCH 292/396] Python : Add comment --- ApplicationCode/GrpcInterface/Python/rips/tests/dataroot.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ApplicationCode/GrpcInterface/Python/rips/tests/dataroot.py b/ApplicationCode/GrpcInterface/Python/rips/tests/dataroot.py index 63ac446863..48680eca32 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/tests/dataroot.py +++ b/ApplicationCode/GrpcInterface/Python/rips/tests/dataroot.py @@ -1 +1,3 @@ -PATH = "../../../../TestModels" \ No newline at end of file +# The path here is intended to be used when pytest is launced from the source tree of the ResInsight repository +# This enables use of test datasets from the TestModels folder +PATH = "../../../../TestModels" From 44ccbff9eecc9c6b6027cb33b6af42c4061f1934 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 8 Aug 2019 09:13:59 +0200 Subject: [PATCH 293/396] #4483 Summary Plot: Fix well segment stepping --- .../ProjectDataModel/Summary/RimSummaryPlotSourceStepping.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlotSourceStepping.cpp b/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlotSourceStepping.cpp index 5ed60b46a4..62fc50d1f1 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlotSourceStepping.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlotSourceStepping.cpp @@ -993,7 +993,7 @@ bool RimSummaryPlotSourceStepping::updateAddressIfMatching(const QVariant& return true; } } - else if (category == RifEclipseSummaryAddress::SUMMARY_BLOCK || RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION) + else if (category == RifEclipseSummaryAddress::SUMMARY_BLOCK || category == RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION) { std::string oldString = oldValue.toString().toStdString(); std::string newString = newValue.toString().toStdString(); From e26cd1a896a30637841bcb531a7281014cbfdbf4 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 8 Aug 2019 09:39:03 +0200 Subject: [PATCH 294/396] #4483 Summary Plot: Fix curve names for segment/block/conmpletions --- .../Summary/RimSummaryCurveAutoName.cpp | 81 ++++++++++--------- 1 file changed, 45 insertions(+), 36 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurveAutoName.cpp b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurveAutoName.cpp index ea8bb162fe..b94b181d27 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurveAutoName.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurveAutoName.cpp @@ -217,8 +217,7 @@ void RimSummaryCurveAutoName::appendAddressDetails(std::string& { switch (summaryAddress.category()) { - case RifEclipseSummaryAddress::SUMMARY_AQUIFER: - { + case RifEclipseSummaryAddress::SUMMARY_AQUIFER: { if (m_aquiferNumber) { if (!text.empty()) text += ":"; @@ -226,8 +225,7 @@ void RimSummaryCurveAutoName::appendAddressDetails(std::string& } } break; - case RifEclipseSummaryAddress::SUMMARY_REGION: - { + case RifEclipseSummaryAddress::SUMMARY_REGION: { if (m_regionNumber) { bool skipSubString = nameHelper && nameHelper->isRegionInTitle(); @@ -239,8 +237,7 @@ void RimSummaryCurveAutoName::appendAddressDetails(std::string& } } break; - case RifEclipseSummaryAddress::SUMMARY_REGION_2_REGION: - { + case RifEclipseSummaryAddress::SUMMARY_REGION_2_REGION: { if (m_regionNumber) { if (!text.empty()) text += ":"; @@ -249,8 +246,7 @@ void RimSummaryCurveAutoName::appendAddressDetails(std::string& } } break; - case RifEclipseSummaryAddress::SUMMARY_WELL_GROUP: - { + case RifEclipseSummaryAddress::SUMMARY_WELL_GROUP: { if (m_wellGroupName) { bool skipSubString = nameHelper && nameHelper->isWellGroupNameInTitle(); @@ -262,72 +258,85 @@ void RimSummaryCurveAutoName::appendAddressDetails(std::string& } } break; - case RifEclipseSummaryAddress::SUMMARY_WELL: - { + case RifEclipseSummaryAddress::SUMMARY_WELL: { appendWellName(text, summaryAddress, nameHelper); } break; - case RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION: - { + case RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION: { appendWellName(text, summaryAddress, nameHelper); if (m_completion) { - if (!text.empty()) text += ":"; - text += std::to_string(summaryAddress.cellI()) + ", " + std::to_string(summaryAddress.cellJ()) + ", " + - std::to_string(summaryAddress.cellK()); + bool skipSubString = nameHelper && nameHelper->isCompletionInTitle(); + if (!skipSubString) + { + if (!text.empty()) text += ":"; + text += std::to_string(summaryAddress.cellI()) + ", " + std::to_string(summaryAddress.cellJ()) + ", " + + std::to_string(summaryAddress.cellK()); + } } } break; - case RifEclipseSummaryAddress::SUMMARY_WELL_LGR: - { + case RifEclipseSummaryAddress::SUMMARY_WELL_LGR: { appendLgrName(text, summaryAddress); appendWellName(text, summaryAddress, nameHelper); } break; - case RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION_LGR: - { + case RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION_LGR: { appendLgrName(text, summaryAddress); appendWellName(text, summaryAddress, nameHelper); if (m_completion) { - if (!text.empty()) text += ":"; - text += std::to_string(summaryAddress.cellI()) + ", " + std::to_string(summaryAddress.cellJ()) + ", " + - std::to_string(summaryAddress.cellK()); + bool skipSubString = nameHelper && nameHelper->isCompletionInTitle(); + if (!skipSubString) + { + if (!text.empty()) text += ":"; + text += std::to_string(summaryAddress.cellI()) + ", " + std::to_string(summaryAddress.cellJ()) + ", " + + std::to_string(summaryAddress.cellK()); + } } } break; - case RifEclipseSummaryAddress::SUMMARY_WELL_SEGMENT: - { + case RifEclipseSummaryAddress::SUMMARY_WELL_SEGMENT: { appendWellName(text, summaryAddress, nameHelper); if (m_wellSegmentNumber) { - if (!text.empty()) text += ":"; - text += std::to_string(summaryAddress.wellSegmentNumber()); + bool skipSubString = nameHelper && nameHelper->isSegmentInTitle(); + if (!skipSubString) + { + if (!text.empty()) text += ":"; + text += std::to_string(summaryAddress.wellSegmentNumber()); + } } } break; - case RifEclipseSummaryAddress::SUMMARY_BLOCK: - { + case RifEclipseSummaryAddress::SUMMARY_BLOCK: { if (m_completion) { - if (!text.empty()) text += ":"; - text += std::to_string(summaryAddress.cellI()) + ", " + std::to_string(summaryAddress.cellJ()) + ", " + - std::to_string(summaryAddress.cellK()); + bool skipSubString = nameHelper && nameHelper->isBlockInTitle(); + if (!skipSubString) + { + if (!text.empty()) text += ":"; + text += std::to_string(summaryAddress.cellI()) + ", " + std::to_string(summaryAddress.cellJ()) + ", " + + std::to_string(summaryAddress.cellK()); + } } } break; - case RifEclipseSummaryAddress::SUMMARY_BLOCK_LGR: - { + case RifEclipseSummaryAddress::SUMMARY_BLOCK_LGR: { appendLgrName(text, summaryAddress); if (m_completion) { - if (!text.empty()) text += ":"; - text += std::to_string(summaryAddress.cellI()) + ", " + std::to_string(summaryAddress.cellJ()) + ", " + - std::to_string(summaryAddress.cellK()); + bool skipSubString = nameHelper && nameHelper->isBlockInTitle(); + if (!skipSubString) + { + if (!text.empty()) text += ":"; + text += std::to_string(summaryAddress.cellI()) + ", " + std::to_string(summaryAddress.cellJ()) + ", " + + std::to_string(summaryAddress.cellK()); + } } } break; From 1caee676bcaec97ebaf09ff6113acd5eefdc9cbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Thu, 8 Aug 2019 10:33:35 +0200 Subject: [PATCH 295/396] Use the Socket Server error message channel for writeBlockData errors, as all the socket server related errors use. Done to prepare for fixing #4543 and #4544 --- ApplicationCode/SocketInterface/RiaSocketTools.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/ApplicationCode/SocketInterface/RiaSocketTools.cpp b/ApplicationCode/SocketInterface/RiaSocketTools.cpp index 26ac13f5f6..2309609c9d 100644 --- a/ApplicationCode/SocketInterface/RiaSocketTools.cpp +++ b/ApplicationCode/SocketInterface/RiaSocketTools.cpp @@ -130,13 +130,8 @@ bool RiaSocketTools::writeBlockData(RiaSocketServer* server, QTcpSocket* socket, { for (int i = 0; i < errorMessages.size(); i++) { - RiaApplication::instance()->showErrorMessage(errorMessages[i]); + server->showErrorMessage(errorMessages[i]); } - -// double totalTimeMS = timer.time() * 1000.0; -// QString resultInfo = QString("Total time '%1 ms'").arg(totalTimeMS); -// -// RiaApplication::instance()->showErrorMessage(resultInfo); } return writeSucceded; From 81de872c7b76a81b3cad717439428fc54a875608 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Thu, 8 Aug 2019 10:45:02 +0200 Subject: [PATCH 296/396] #4543, #4544 Fixed missing command line help text from menu-command and --help option. Improved the error text when an unknown option is used. Improved the dialog used to show command line options, and make the text selectable --- .../Application/RiaApplication.cpp | 10 +++ ApplicationCode/Application/RiaApplication.h | 8 +-- .../Application/RiaConsoleApplication.cpp | 23 ++++--- .../Application/RiaConsoleApplication.h | 3 +- .../Application/RiaGuiApplication.cpp | 61 +++++++++++++------ .../Application/RiaGuiApplication.h | 3 +- ApplicationCode/Application/RiaMain.cpp | 16 +++-- .../Application/Tools/RiaArgumentParser.cpp | 6 +- .../ApplicationCommands/RicHelpFeatures.cpp | 2 +- 9 files changed, 82 insertions(+), 50 deletions(-) diff --git a/ApplicationCode/Application/RiaApplication.cpp b/ApplicationCode/Application/RiaApplication.cpp index cdc0ff382e..1d3cbbf22e 100644 --- a/ApplicationCode/Application/RiaApplication.cpp +++ b/ApplicationCode/Application/RiaApplication.cpp @@ -1127,6 +1127,8 @@ QString RiaApplication::commandLineParameterHelp() { QString helpText = QString("\n%1 v. %2\n").arg(RI_APPLICATION_NAME).arg(RiaApplication::getVersionStringApp(false)); helpText += "Copyright Equinor ASA, Ceetron Solution AS, Ceetron AS\n\n"; + helpText += m_commandLineHelpText; + return helpText; } @@ -1297,6 +1299,14 @@ void RiaApplication::setStartDir(const QString& startDir) m_startupDefaultDirectory = startDir; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaApplication::setCommandLineHelpText(const QString& commandLineHelpText) +{ + m_commandLineHelpText = commandLineHelpText; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/Application/RiaApplication.h b/ApplicationCode/Application/RiaApplication.h index 816c045657..a890acf9b4 100644 --- a/ApplicationCode/Application/RiaApplication.h +++ b/ApplicationCode/Application/RiaApplication.h @@ -159,7 +159,8 @@ public: RiaPreferences* preferences(); void applyPreferences(const RiaPreferences* oldPreferences = nullptr); - static QString commandLineParameterHelp(); + QString commandLineParameterHelp(); + void setCommandLineHelpText(const QString& commandLineHelpText); void setCacheDataObject(const QString& key, const QVariant& dataObject); QVariant cacheDataObject(const QString& key) const; @@ -187,8 +188,7 @@ public: virtual ApplicationStatus handleArguments(cvf::ProgramOptions* progOpt) = 0; virtual int launchUnitTestsWithConsole(); virtual void addToRecentFiles(const QString& fileName) {} - virtual void showInformationMessage(const QString& infoText) = 0; - virtual void showErrorMessage(const QString& errMsg) = 0; + virtual void showFormattedTextInMessageBoxOrConsole(const QString& errMsg) = 0; virtual void launchGrpcServer() = 0; @@ -230,7 +230,7 @@ protected: std::map m_fileDialogDefaultDirectories; QString m_startupDefaultDirectory; - + QString m_commandLineHelpText; QMap m_sessionCache; // Session cache used to store username/passwords per session std::list m_commandQueue; diff --git a/ApplicationCode/Application/RiaConsoleApplication.cpp b/ApplicationCode/Application/RiaConsoleApplication.cpp index 5c4e6cf53d..1677b862cf 100644 --- a/ApplicationCode/Application/RiaConsoleApplication.cpp +++ b/ApplicationCode/Application/RiaConsoleApplication.cpp @@ -100,6 +100,13 @@ RiaApplication::ApplicationStatus RiaConsoleApplication::handleArguments(cvf::Pr return KEEP_GOING; } + if (progOpt->option("help") || progOpt->option("?")) + { + this->showFormattedTextInMessageBoxOrConsole("\nThe current command line options in ResInsight are:\n" + + this->commandLineParameterHelp()); + return RiaApplication::EXIT_COMPLETED; + } + // Unit testing // -------------------------------------------------------- if (cvf::Option o = progOpt->option("unittest")) @@ -324,19 +331,11 @@ RiaApplication::ApplicationStatus RiaConsoleApplication::handleArguments(cvf::Pr } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- -void RiaConsoleApplication::showInformationMessage(const QString& text) +void RiaConsoleApplication::showFormattedTextInMessageBoxOrConsole(const QString& errMsg) { - RiaLogging::info(text); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiaConsoleApplication::showErrorMessage(const QString& errMsg) -{ - RiaLogging::error(errMsg); + std::cout << errMsg.toStdString(); } //-------------------------------------------------------------------------------------------------- @@ -375,7 +374,7 @@ void RiaConsoleApplication::invokeProcessEvents(QEventLoop::ProcessEventsFlags f //-------------------------------------------------------------------------------------------------- void RiaConsoleApplication::onProjectOpeningError(const QString& errMsg) { - showErrorMessage(errMsg); + RiaLogging::error(errMsg); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/Application/RiaConsoleApplication.h b/ApplicationCode/Application/RiaConsoleApplication.h index 7506a1125e..5097c2a6d5 100644 --- a/ApplicationCode/Application/RiaConsoleApplication.h +++ b/ApplicationCode/Application/RiaConsoleApplication.h @@ -42,8 +42,7 @@ public: // Public RiaApplication overrides void initialize() override; ApplicationStatus handleArguments(cvf::ProgramOptions* progOpt) override; - void showInformationMessage(const QString& text) override; - void showErrorMessage(const QString& errMsg) override; + void showFormattedTextInMessageBoxOrConsole(const QString& errMsg) override; void launchGrpcServer() override; #ifdef ENABLE_GRPC RiaGrpcServer* grpcServer() const override; diff --git a/ApplicationCode/Application/RiaGuiApplication.cpp b/ApplicationCode/Application/RiaGuiApplication.cpp index f5b6d4740e..adcbf82629 100644 --- a/ApplicationCode/Application/RiaGuiApplication.cpp +++ b/ApplicationCode/Application/RiaGuiApplication.cpp @@ -120,6 +120,9 @@ #include #include #include +#include +#include +#include #include @@ -152,6 +155,7 @@ void AppEnum::setUp() /// //================================================================================================== + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -588,6 +592,13 @@ RiaApplication::ApplicationStatus RiaGuiApplication::handleArguments(cvf::Progra return KEEP_GOING; } + if (progOpt->option("help") || progOpt->option("?")) + { + this->showFormattedTextInMessageBoxOrConsole("The current command line options in ResInsight are:\n" + + this->commandLineParameterHelp()); + return RiaApplication::EXIT_COMPLETED; + } + // Unit testing // -------------------------------------------------------- if (cvf::Option o = progOpt->option("unittest")) @@ -1201,33 +1212,43 @@ void RiaGuiApplication::clearAllSelections() } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- -void RiaGuiApplication::showInformationMessage(const QString& text) +void RiaGuiApplication::showFormattedTextInMessageBoxOrConsole(const QString& text) { - QString helpText = text; + // Create a message dialog with cut/paste friendly text + QDialog dlg(RiuMainWindow::instance()); + dlg.setModal(true); - QMessageBox msgBox; - msgBox.setIcon(QMessageBox::Information); - msgBox.setWindowTitle("ResInsight"); + QGridLayout* layout = new QGridLayout; + dlg.setLayout(layout); - helpText.replace("&", "&"); - helpText.replace("<", "<"); - helpText.replace(">", ">"); + QTextEdit* textEdit = new QTextEdit(&dlg); + layout->addWidget(textEdit, 0, 1, 1, 2); + layout->setColumnStretch(1,3); - helpText = QString("

%1
").arg(helpText); - msgBox.setText(helpText); + QPushButton* okButton = new QPushButton; + okButton->setText("Ok"); + layout->addWidget(okButton,2,2); + QObject::connect(okButton, SIGNAL(clicked()), &dlg, SLOT(accept())); - msgBox.exec(); -} + // Convert text to text edit friendly format + QString formattedText = text; + formattedText.replace("&", "&"); + formattedText.replace("<", "<"); + formattedText.replace(">", ">"); + formattedText = QString("
%1
").arg(formattedText); + + textEdit->setText(formattedText); + + // Resize dialog to fit text etc. + textEdit->document()->adjustSize(); + QSizeF docSize = textEdit->document()->size(); + dlg.resize( 20 + docSize.width() + 2*layout->margin(), + 20 + docSize.height() + 2*layout->margin() + layout->spacing() + okButton->sizeHint().height()); + + dlg.exec(); -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiaGuiApplication::showErrorMessage(const QString& errMsg) -{ - QErrorMessage errDialog(mainWindow()); - errDialog.showMessage(errMsg); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/Application/RiaGuiApplication.h b/ApplicationCode/Application/RiaGuiApplication.h index 6ff68c02f1..03918f5602 100644 --- a/ApplicationCode/Application/RiaGuiApplication.h +++ b/ApplicationCode/Application/RiaGuiApplication.h @@ -130,8 +130,7 @@ public: ApplicationStatus handleArguments(cvf::ProgramOptions* progOpt) override; int launchUnitTestsWithConsole() override; void addToRecentFiles(const QString& fileName) override; - void showInformationMessage(const QString& text) override; - void showErrorMessage(const QString& errMsg) override; + void showFormattedTextInMessageBoxOrConsole(const QString& errMsg) override; void launchGrpcServer() override; #ifdef ENABLE_GRPC RiaGrpcServer* grpcServer() const override; diff --git a/ApplicationCode/Application/RiaMain.cpp b/ApplicationCode/Application/RiaMain.cpp index d63188df3d..d6f30f473d 100644 --- a/ApplicationCode/Application/RiaMain.cpp +++ b/ApplicationCode/Application/RiaMain.cpp @@ -59,21 +59,25 @@ int main(int argc, char *argv[]) cvf::ProgramOptions progOpt; bool result = RiaArgumentParser::parseArguments(&progOpt); + const cvf::String usageText = progOpt.usageText(110, 30); app->initialize(); + app->setCommandLineHelpText( cvfqt::Utils::toQString(usageText) ); if (!result) { std::vector unknownOptions = progOpt.unknownOptions(); - QStringList unknownOptionsText; + QString unknownOptionsText; for (cvf::String option : unknownOptions) { - unknownOptionsText += QString("Unknown option: %1").arg(cvfqt::Utils::toQString(option)); + unknownOptionsText += QString("\tUnknown option: %1\n").arg(cvfqt::Utils::toQString(option)); } - const cvf::String usageText = progOpt.usageText(110, 30); - app->showErrorMessage(RiaApplication::commandLineParameterHelp() + - cvfqt::Utils::toQString(usageText) + - unknownOptionsText.join("\n")); + app->showFormattedTextInMessageBoxOrConsole("ERROR: Unknown command line options detected ! \n" + + unknownOptionsText + + "\n\n" + + "The current command line options in ResInsight are:\n" + + app->commandLineParameterHelp()); + if (dynamic_cast(app.get()) == nullptr) { return 1; diff --git a/ApplicationCode/Application/Tools/RiaArgumentParser.cpp b/ApplicationCode/Application/Tools/RiaArgumentParser.cpp index 4d100532c0..938c777650 100644 --- a/ApplicationCode/Application/Tools/RiaArgumentParser.cpp +++ b/ApplicationCode/Application/Tools/RiaArgumentParser.cpp @@ -103,8 +103,8 @@ bool RiaArgumentParser::parseArguments(cvf::ProgramOptions* progOpt) "[] ", "Supply list of cases to replace in project, performing command file for each case.", cvf::ProgramOptions::SINGLE_VALUE); - progOpt->registerOption("help", "", "Displays help text."); - progOpt->registerOption("?", "", "Displays help text."); + progOpt->registerOption("help", "", "Displays help text and exits."); + progOpt->registerOption("?", "", "Displays help text and exits."); progOpt->registerOption("regressiontest", "", "System command", cvf::ProgramOptions::SINGLE_VALUE); progOpt->registerOption("updateregressiontestbase", "", "System command", cvf::ProgramOptions::SINGLE_VALUE); #ifdef USE_UNIT_TESTS @@ -120,7 +120,7 @@ bool RiaArgumentParser::parseArguments(cvf::ProgramOptions* progOpt) // If positional parameter functionality is to be supported, the test for existence of positionalParameters must be removed // This is based on a pull request by @andlaus https://github.com/OPM/ResInsight/pull/162 - if (!parseOk || progOpt->hasOption("help") || progOpt->hasOption("?") || !progOpt->positionalParameters().empty()) + if (!parseOk || !progOpt->positionalParameters().empty()) { return false; } diff --git a/ApplicationCode/Commands/ApplicationCommands/RicHelpFeatures.cpp b/ApplicationCode/Commands/ApplicationCommands/RicHelpFeatures.cpp index d77a880452..1786d04e65 100644 --- a/ApplicationCode/Commands/ApplicationCommands/RicHelpFeatures.cpp +++ b/ApplicationCode/Commands/ApplicationCommands/RicHelpFeatures.cpp @@ -192,7 +192,7 @@ void RicHelpCommandLineFeature::onActionTriggered(bool isChecked) RiaApplication* app = RiaApplication::instance(); QString text = app->commandLineParameterHelp(); - app->showInformationMessage(text); + app->showFormattedTextInMessageBoxOrConsole(text); } //-------------------------------------------------------------------------------------------------- From b2adea51e318b8f4d728570c3cb37342feb437d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Thu, 8 Aug 2019 13:33:51 +0200 Subject: [PATCH 297/396] #4001 Improved windows console support. Other shells than native also supported. Preparations for Summary plotting command line parameters. --- .../Application/RiaConsoleApplication.cpp | 29 +++++++++++++++++-- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/ApplicationCode/Application/RiaConsoleApplication.cpp b/ApplicationCode/Application/RiaConsoleApplication.cpp index 1677b862cf..a93e12fd4a 100644 --- a/ApplicationCode/Application/RiaConsoleApplication.cpp +++ b/ApplicationCode/Application/RiaConsoleApplication.cpp @@ -70,11 +70,34 @@ void RiaConsoleApplication::initialize() #ifdef _WIN32 #pragma warning(push) // Saves the current warning state. #pragma warning(disable : 4996) // Temporarily disables warning 4996. - if (AttachConsole(ATTACH_PARENT_PROCESS) || AllocConsole()) + + bool isReOpenStdToConsoleNeeded = false; + + if ( AttachConsole(ATTACH_PARENT_PROCESS) ) { - freopen("CONOUT$", "w", stdout); - freopen("CONOUT$", "w", stderr); + int fileType = GetFileType(GetStdHandle(STD_OUTPUT_HANDLE)); + + // FILE_TYPE_CHAR indicates a windows console buffer. + // FILE_TYPE_PIPE indicates redirection imposed by the starting shell (eg migw shell) + // If we are dealing with a pipe, we do not want to do the reopen, and destroy the connection. + + if (fileType == FILE_TYPE_CHAR ) + { + isReOpenStdToConsoleNeeded = true; + } } + else if ( AllocConsole() ) + { + isReOpenStdToConsoleNeeded = true; + } + + if (isReOpenStdToConsoleNeeded) + { + freopen("conout$", "w", stdout); + freopen("conout$", "w", stderr); + freopen("conin$", "r", stdin); + } + #pragma warning(pop) #endif From d9b1cfec3a2408336de2fb0e4ee2ec61b3924a83 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 8 Aug 2019 11:04:24 +0200 Subject: [PATCH 298/396] Update sphinx doc --- .../GrpcInterface/Python/doc/README_DOCUMENTATION.txt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ApplicationCode/GrpcInterface/Python/doc/README_DOCUMENTATION.txt b/ApplicationCode/GrpcInterface/Python/doc/README_DOCUMENTATION.txt index 51fff95b6b..85832119f1 100644 --- a/ApplicationCode/GrpcInterface/Python/doc/README_DOCUMENTATION.txt +++ b/ApplicationCode/GrpcInterface/Python/doc/README_DOCUMENTATION.txt @@ -1,4 +1,7 @@ -You need sphinx (pip install sphinx) to update the documentation. +You need sphinx to update the documentation. -To update run "make html" to update to reflect changes to the python code. +pip install sphinx sphinx-markdown-builder + +To update run "make markdown" to update to reflect changes to the python code. +The generated files are located in build/markdown From 54ed32e474210c55a11fa928ebdcc81bfc394094 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 8 Aug 2019 11:24:25 +0200 Subject: [PATCH 299/396] Python doc : Update to hugo syntax --- .../GrpcInterface/Python/doc/source/header.rst | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/ApplicationCode/GrpcInterface/Python/doc/source/header.rst b/ApplicationCode/GrpcInterface/Python/doc/source/header.rst index e2c497489b..c794ea15d6 100644 --- a/ApplicationCode/GrpcInterface/Python/doc/source/header.rst +++ b/ApplicationCode/GrpcInterface/Python/doc/source/header.rst @@ -1,9 +1,9 @@ ---- -layout: docs -title: rips - gRPC Python API -permalink: /docs/python/ -published: true ---- ++++ +title = "Python API - rips" +published = true +weight = 20 ++++ + ResInsight has a `gRPC Remote Procedure Call `_ interface with a Python Client interface. This interface allows you to interact with a running ResInsight instance from a Python script. @@ -13,8 +13,8 @@ On some systems the ``pip`` command may have to be replaced by ``python -m pip`` In order for gRPC to be available, ResInsight needs to be built with the ``RESINSIGHT_ENABLE_GRPC`` option set. A valid gRPC build will show a message in the About dialog confirming gRPC is available: -.. image:: ../images/AboutGrpc.png +.. image:: {{< relref "" >}}images/scripting/AboutGrpc.png Furthermore, gRPC needs to be enabled in the Scripting tab of the Preference dialog: -.. image:: ../images/PrefGrpc.png +.. image:: {{< relref "" >}}images/scripting/PrefGrpc.png From 136251c4b15b969a1047af78d055e530baa95d94 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 8 Aug 2019 11:38:01 +0200 Subject: [PATCH 300/396] Python doc : Add modules GridCaseGroup and View --- .../GrpcInterface/Python/doc/source/rips.rst | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/ApplicationCode/GrpcInterface/Python/doc/source/rips.rst b/ApplicationCode/GrpcInterface/Python/doc/source/rips.rst index c03c530f93..f20e954542 100644 --- a/ApplicationCode/GrpcInterface/Python/doc/source/rips.rst +++ b/ApplicationCode/GrpcInterface/Python/doc/source/rips.rst @@ -71,6 +71,13 @@ Example print(dimensions.j) print(dimensions.k) +GridCaseGroup Module +=========== + +.. autoclass:: rips.GridCaseGroup + :members: + + Project Module ============== @@ -83,7 +90,13 @@ Properties Module .. autoclass:: rips.Properties :members: -Synchronous Example +View Module +================= + +.. autoclass:: rips.View + :members: + + Synchronous Example -------------------- Read two properties, multiply them together and push the results back to ResInsight in a naïve way, by reading PORO into a list, then reading PERMX into a list, then multiplying them both in a resulting list and finally transferring back the list. From 0a30e6c34091e670b03f943071ec0ae780986b8f Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Wed, 7 Aug 2019 23:33:08 +0200 Subject: [PATCH 301/396] #4547 Add simplified synchronous methods for activeCellProperty and gridProperty --- .../GrpcInterface/CMakeLists.cmake | 3 +- .../GrpcInterface/Python/rips/Properties.py | 44 ++++++++++++++++++- .../Python/rips/examples/AllCases.py | 32 +------------- .../rips/examples/InputPropTestAsync.py | 4 +- .../Python/rips/examples/InputPropTestSync.py | 14 +----- .../{SoilAverage.py => SoilAverageAsync.py} | 2 +- .../Python/rips/examples/SoilAverageSync.py | 24 ++++++++++ .../Python/rips/examples/SoilPorvAsync.py | 4 +- .../Python/rips/examples/SoilPorvSync.py | 13 +----- .../Python/rips/tests/test_properties.py | 31 ++++++++----- 10 files changed, 99 insertions(+), 72 deletions(-) rename ApplicationCode/GrpcInterface/Python/rips/examples/{SoilAverage.py => SoilAverageAsync.py} (84%) create mode 100644 ApplicationCode/GrpcInterface/Python/rips/examples/SoilAverageSync.py diff --git a/ApplicationCode/GrpcInterface/CMakeLists.cmake b/ApplicationCode/GrpcInterface/CMakeLists.cmake index d2f39634c0..748d126b31 100644 --- a/ApplicationCode/GrpcInterface/CMakeLists.cmake +++ b/ApplicationCode/GrpcInterface/CMakeLists.cmake @@ -182,7 +182,8 @@ if (PYTHON_EXECUTABLE) "rips/examples/GridInformation.py" "rips/examples/InputPropTestSync.py" "rips/examples/InputPropTestAsync.py" - "rips/examples/SoilAverage.py" + "rips/examples/SoilAverageAsync.py" + "rips/examples/SoilAverageSync.py" "rips/examples/SoilAverageNoComm.py" "rips/tests/test_cases.py" "rips/tests/test_commands.py" diff --git a/ApplicationCode/GrpcInterface/Python/rips/Properties.py b/ApplicationCode/GrpcInterface/Python/rips/Properties.py index 9bd5a3dc7b..301fed723c 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Properties.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Properties.py @@ -78,7 +78,7 @@ class Properties: porosity_model = porosityModelEnum) return self.propertiesStub.GetAvailableProperties(request).property_names - def activeCellProperty(self, propertyType, propertyName, timeStep, porosityModel = 'MATRIX_MODEL'): + def activeCellPropertyAsync(self, propertyType, propertyName, timeStep, porosityModel = 'MATRIX_MODEL'): """Get a cell property for all active cells. Async, so returns an iterator Arguments: @@ -101,7 +101,27 @@ class Properties: for chunk in self.propertiesStub.GetActiveCellProperty(request): yield chunk - def gridProperty(self, propertyType, propertyName, timeStep, gridIndex = 0, porosityModel = 'MATRIX_MODEL'): + def activeCellProperty(self, propertyType, propertyName, timeStep, porosityModel = 'MATRIX_MODEL'): + """Get a cell property for all active cells. Sync, so returns a list + + Arguments: + propertyType(str): string enum. See available() + propertyName(str): name of an Eclipse property + timeStep(int): the time step for which to get the property for + porosityModel(str): string enum. See available() + + Returns: + A list containing double values + You first loop through the chunks and then the values within the chunk to get all values. + """ + allValues = [] + generator = self.activeCellPropertyAsync(propertyType, propertyName, timeStep, porosityModel) + for chunk in generator: + for value in chunk.values: + allValues.append(value) + return allValues + + def gridPropertyAsync(self, propertyType, propertyName, timeStep, gridIndex = 0, porosityModel = 'MATRIX_MODEL'): """Get a cell property for all grid cells. Async, so returns an iterator Arguments: @@ -126,6 +146,26 @@ class Properties: for chunk in self.propertiesStub.GetGridProperty(request): yield chunk + def gridProperty(self, propertyType, propertyName, timeStep, gridIndex = 0, porosityModel = 'MATRIX_MODEL'): + """Get a cell property for all grid cells. Synchronous, so returns a list + + Arguments: + propertyType(str): string enum. See available() + propertyName(str): name of an Eclipse property + timeStep(int): the time step for which to get the property for + gridIndex(int): index to the grid we're getting values for + porosityModel(str): string enum. See available() + + Returns: + A list of double values + """ + allValues = [] + generator = self.gridPropertyAsync(propertyType, propertyName, timeStep, gridIndex, porosityModel) + for chunk in generator: + for value in chunk.values: + allValues.append(value) + return allValues + def setActiveCellPropertyAsync(self, values_iterator, propertyType, propertyName, timeStep, porosityModel = 'MATRIX_MODEL'): """Set a cell property for all active cells. Async, and so takes an iterator to the input values diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/AllCases.py b/ApplicationCode/GrpcInterface/Python/rips/examples/AllCases.py index c99949759e..acbe3745bd 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/examples/AllCases.py +++ b/ApplicationCode/GrpcInterface/Python/rips/examples/AllCases.py @@ -11,36 +11,8 @@ if resInsight is not None: print ("Got " + str(len(cases)) + " cases: ") for case in cases: print(case.name) - assert(case.address() is not 0) - assert(case.classKeyword() == "EclipseCase") - print("\n#### Case ####") - for keyword in case.keywords(): - print (keyword + ": " + str(case.getValue(keyword))) - print ("\n####Project#####") - pdmProject = case.ancestor(classKeyword="ResInsightProject") - assert(pdmProject) - assert(pdmProject.address() is not 0) - assert(pdmProject.address() == resInsight.project.address()) - - for keyword in resInsight.project.keywords(): - print (keyword + ": " + str(resInsight.project.getValue(keyword))) - pdmViews = resInsight.project.views() - for view in pdmViews: - print ("\n####View####") - print(view.classKeyword(), view.address()) - for viewKeyword in view.keywords(): - print(viewKeyword + "-> " + str(view.getValue(viewKeyword))) + views = case.views() + for view in views: view.setShowGridBox(not view.showGridBox()) view.setBackgroundColor("#3388AA") view.update() - - print ("\n####Cell Result####") - firstView = case.view(id=0) - assert(firstView is not None) - cellResult = firstView.cellResult() - print(cellResult.classKeyword(), cellResult.address()) - for resultKeyword in cellResult.keywords(): - print(resultKeyword + "->" + str(cellResult.getValue(resultKeyword))) - cellResult.setValue("ResultVariable", "SOIL") - cellResult.setValue("ResultType", "DYNAMIC_NATIVE") - cellResult.update() \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/InputPropTestAsync.py b/ApplicationCode/GrpcInterface/Python/rips/examples/InputPropTestAsync.py index b4bfdc133c..335c97d306 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/examples/InputPropTestAsync.py +++ b/ApplicationCode/GrpcInterface/Python/rips/examples/InputPropTestAsync.py @@ -16,8 +16,8 @@ resInsight = rips.Instance.find() start = time.time() case = resInsight.project.case(id=0) -poroChunks = case.properties.activeCellProperty('STATIC_NATIVE', 'PORO', 0) -permxChunks = case.properties.activeCellProperty('STATIC_NATIVE', 'PERMX', 0) +poroChunks = case.properties.activeCellPropertyAsync('STATIC_NATIVE', 'PORO', 0) +permxChunks = case.properties.activeCellPropertyAsync('STATIC_NATIVE', 'PERMX', 0) case.properties.setActiveCellPropertyAsync(createResult(poroChunks, permxChunks), 'GENERATED', 'POROPERMXAS', 0) diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/InputPropTestSync.py b/ApplicationCode/GrpcInterface/Python/rips/examples/InputPropTestSync.py index 62b09804a2..5d7d862e03 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/examples/InputPropTestSync.py +++ b/ApplicationCode/GrpcInterface/Python/rips/examples/InputPropTestSync.py @@ -9,17 +9,8 @@ resInsight = rips.Instance.find() start = time.time() case = resInsight.project.case(id=0) -poroChunks = case.properties.activeCellProperty('STATIC_NATIVE', 'PORO', 0) -poroResults = [] -for poroChunk in poroChunks: - for poro in poroChunk.values: - poroResults.append(poro) - -permxChunks = case.properties.activeCellProperty('STATIC_NATIVE', 'PERMX', 0) -permxResults = [] -for permxChunk in permxChunks: - for permx in permxChunk.values: - permxResults.append(permx) +poroResults = case.properties.activeCellProperty('STATIC_NATIVE', 'PORO', 0) +permxResults = case.properties.activeCellProperty('STATIC_NATIVE', 'PERMX', 0) results = [] for (poro, permx) in zip(poroResults, permxResults): @@ -29,5 +20,4 @@ case.properties.setActiveCellProperty(results, 'GENERATED', 'POROPERMXSY', 0) end = time.time() print("Time elapsed: ", end - start) - print("Transferred all results back") \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/SoilAverage.py b/ApplicationCode/GrpcInterface/Python/rips/examples/SoilAverageAsync.py similarity index 84% rename from ApplicationCode/GrpcInterface/Python/rips/examples/SoilAverage.py rename to ApplicationCode/GrpcInterface/Python/rips/examples/SoilAverageAsync.py index 6b89ce95a7..6da3d6ee3b 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/examples/SoilAverage.py +++ b/ApplicationCode/GrpcInterface/Python/rips/examples/SoilAverageAsync.py @@ -15,7 +15,7 @@ timeSteps = case.timeSteps() averages = [] for i in range(0, len(timeSteps)): - resultChunks = case.properties.activeCellProperty('DYNAMIC_NATIVE', 'SOIL', i) + resultChunks = case.properties.activeCellPropertyAsync('DYNAMIC_NATIVE', 'SOIL', i) mysum = 0.0 count = 0 for chunk in resultChunks: diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/SoilAverageSync.py b/ApplicationCode/GrpcInterface/Python/rips/examples/SoilAverageSync.py new file mode 100644 index 0000000000..b644d7dc78 --- /dev/null +++ b/ApplicationCode/GrpcInterface/Python/rips/examples/SoilAverageSync.py @@ -0,0 +1,24 @@ +import sys +import os +sys.path.insert(1, os.path.join(sys.path[0], '../../')) +import rips +import itertools +import time + +resInsight = rips.Instance.find() + +start = time.time() +case = resInsight.project.case(id=0) +grid = case.grid(index = 0) + +timeSteps = case.timeSteps() + +averages = [] +for i in range(0, len(timeSteps)): + results = case.properties.activeCellProperty('DYNAMIC_NATIVE', 'SOIL', i) + mysum = sum(results) + averages.append(mysum/len(results)) + +end = time.time() +print("Time elapsed: ", end - start) +print(averages) \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/SoilPorvAsync.py b/ApplicationCode/GrpcInterface/Python/rips/examples/SoilPorvAsync.py index 640468beda..e42b25a270 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/examples/SoilPorvAsync.py +++ b/ApplicationCode/GrpcInterface/Python/rips/examples/SoilPorvAsync.py @@ -18,13 +18,13 @@ resInsight = rips.Instance.find() case = resInsight.project.case(id=0) timeStepInfo = case.timeSteps() -porvChunks = case.properties.activeCellProperty('STATIC_NATIVE', 'PORV', 0) +porvChunks = case.properties.activeCellPropertyAsync('STATIC_NATIVE', 'PORV', 0) porvArray = [] for porvChunk in porvChunks: porvArray.append(porvChunk) for i in range (0, len(timeStepInfo)): - soilChunks = case.properties.activeCellProperty('DYNAMIC_NATIVE', 'SOIL', i) + soilChunks = case.properties.activeCellPropertyAsync('DYNAMIC_NATIVE', 'SOIL', i) input_iterator = createResult(soilChunks, iter(porvArray)) case.properties.setActiveCellPropertyAsync(input_iterator, 'GENERATED', 'SOILPORVAsync', i) diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/SoilPorvSync.py b/ApplicationCode/GrpcInterface/Python/rips/examples/SoilPorvSync.py index 4c8b44537c..4500feaab1 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/examples/SoilPorvSync.py +++ b/ApplicationCode/GrpcInterface/Python/rips/examples/SoilPorvSync.py @@ -6,20 +6,11 @@ import rips resInsight = rips.Instance.find() case = resInsight.project.case(id=0) -porvChunks = case.properties.activeCellProperty('STATIC_NATIVE', 'PORV', 0) -porvResults = [] -for porvChunk in porvChunks: - for porv in porvChunk.values: - porvResults.append(porv) - +porvResults = case.properties.activeCellProperty('STATIC_NATIVE', 'PORV', 0) timeStepInfo = case.timeSteps() for i in range (0, len(timeStepInfo)): - soilChunks = case.properties.activeCellProperty('DYNAMIC_NATIVE', 'SOIL', i) - soilResults = [] - for soilChunk in soilChunks: - for soil in soilChunk.values: - soilResults.append(soil) + soilResults = case.properties.activeCellProperty('DYNAMIC_NATIVE', 'SOIL', i) results = [] for (soil, porv) in zip(soilResults, porvResults): results.append(soil * porv) diff --git a/ApplicationCode/GrpcInterface/Python/rips/tests/test_properties.py b/ApplicationCode/GrpcInterface/Python/rips/tests/test_properties.py index 0966df800c..a363d74f3b 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/tests/test_properties.py +++ b/ApplicationCode/GrpcInterface/Python/rips/tests/test_properties.py @@ -7,11 +7,11 @@ import rips import dataroot -def test_10k(rips_instance, initializeTest): +def test_10kAsync(rips_instance, initializeTest): casePath = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID" case = rips_instance.project.loadCase(path=casePath) - resultChunks = case.properties.activeCellProperty('DYNAMIC_NATIVE', 'SOIL', 1) + resultChunks = case.properties.activeCellPropertyAsync('DYNAMIC_NATIVE', 'SOIL', 1) mysum = 0.0 count = 0 for chunk in resultChunks: @@ -22,6 +22,16 @@ def test_10k(rips_instance, initializeTest): assert(average != pytest.approx(0.0158893, abs=0.0000001)) assert(average == pytest.approx(0.0558893, abs=0.0000001)) +def test_10kSync(rips_instance, initializeTest): + casePath = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID" + case = rips_instance.project.loadCase(path=casePath) + + results = case.properties.activeCellProperty('DYNAMIC_NATIVE', 'SOIL', 1) + mysum = sum(results) + average = mysum / len(results) + assert(mysum == pytest.approx(621.768, abs=0.001)) + assert(average != pytest.approx(0.0158893, abs=0.0000001)) + assert(average == pytest.approx(0.0558893, abs=0.0000001)) def createResult(poroChunks, permxChunks): for (poroChunk, permxChunk) in zip(poroChunks, permxChunks): @@ -30,9 +40,8 @@ def createResult(poroChunks, permxChunks): resultChunk.append(poro * permx) yield resultChunk -def checkResults(poroChunks, permxChunks, poroPermXChunks): - for (poroChunk, permxChunk, poroPermXChunk) in zip(poroChunks, permxChunks, poroPermXChunks): - for (poro, permx, poropermx) in zip(poroChunk.values, permxChunk.values, poroPermXChunk.values): +def checkResults(poroValues, permxValues, poropermxValues): + for (poro, permx, poropermx) in zip(poroValues, permxValues, poropermxValues): recalc = poro * permx assert(recalc == pytest.approx(poropermx, rel=1.0e-10)) @@ -40,16 +49,16 @@ def test_10k_PoroPermX(rips_instance, initializeTest): casePath = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID" case = rips_instance.project.loadCase(path=casePath) - poroChunks = case.properties.activeCellProperty('STATIC_NATIVE', 'PORO', 0) - permxChunks = case.properties.activeCellProperty('STATIC_NATIVE', 'PERMX', 0) + poroChunks = case.properties.activeCellPropertyAsync('STATIC_NATIVE', 'PORO', 0) + permxChunks = case.properties.activeCellPropertyAsync('STATIC_NATIVE', 'PERMX', 0) case.properties.setActiveCellPropertyAsync(createResult(poroChunks, permxChunks), 'GENERATED', 'POROPERMXAS', 0) - poroChunks = case.properties.activeCellProperty('STATIC_NATIVE', 'PORO', 0) - permxChunks = case.properties.activeCellProperty('STATIC_NATIVE', 'PERMX', 0) - poroPermXChunks = case.properties.activeCellProperty('GENERATED', 'POROPERMXAS', 0) + poro = case.properties.activeCellProperty('STATIC_NATIVE', 'PORO', 0) + permx = case.properties.activeCellProperty('STATIC_NATIVE', 'PERMX', 0) + poroPermX = case.properties.activeCellProperty('GENERATED', 'POROPERMXAS', 0) - checkResults(poroChunks, permxChunks, poroPermXChunks) + checkResults(poro, permx, poroPermX) \ No newline at end of file From 0d456a1f1ba8bdf11b43860f485ad3e14e50afe9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Thu, 8 Aug 2019 16:22:00 +0200 Subject: [PATCH 302/396] #4002 Renamed feature that opens the plot editor and created feature to create a new plot directly. The new feature uses the selected summary cases and creates a default curve for each. --- .../RicNewSummaryCurveFeature.cpp | 5 +- .../RicNewSummaryPlotFeature.cpp | 93 ++++++++++++++++++- .../RicNewSummaryPlotFeature.h | 14 +++ .../RimContextCommandBuilder.cpp | 5 + 4 files changed, 113 insertions(+), 4 deletions(-) diff --git a/ApplicationCode/Commands/SummaryPlotCommands/RicNewSummaryCurveFeature.cpp b/ApplicationCode/Commands/SummaryPlotCommands/RicNewSummaryCurveFeature.cpp index 9f82c5683b..6eb7a2c8ab 100644 --- a/ApplicationCode/Commands/SummaryPlotCommands/RicNewSummaryCurveFeature.cpp +++ b/ApplicationCode/Commands/SummaryPlotCommands/RicNewSummaryCurveFeature.cpp @@ -54,7 +54,7 @@ RimSummaryCurve* RicNewSummaryCurveFeature::addCurveToPlot(RimSummaryPlot* plot, cvf::Color3f curveColor = RiaColorTables::summaryCurveDefaultPaletteColors().cycledColor3f(plot->singleColorCurveCount()); newCurve->setColor(curveColor); - plot->addCurveAndUpdate(newCurve); + plot->addCurveNoUpdate(newCurve); if (summaryCase) { @@ -63,8 +63,6 @@ RimSummaryCurve* RicNewSummaryCurveFeature::addCurveToPlot(RimSummaryPlot* plot, newCurve->setSummaryAddressYAndApplyInterpolation(RifEclipseSummaryAddress::fieldAddress("FOPT")); - newCurve->loadDataAndUpdate(true); - return newCurve; } @@ -132,6 +130,7 @@ void RicNewSummaryCurveFeature::onActionTriggered(bool isChecked) RimSummaryCurve* newCurve = addCurveToPlot(plot, defaultCase); + plot->loadDataAndUpdate(); plot->updateConnectedEditors(); app->getOrCreateAndShowMainPlotWindow()->selectAsCurrentItem(newCurve); diff --git a/ApplicationCode/Commands/SummaryPlotCommands/RicNewSummaryPlotFeature.cpp b/ApplicationCode/Commands/SummaryPlotCommands/RicNewSummaryPlotFeature.cpp index 73f5724800..b2c25982e2 100644 --- a/ApplicationCode/Commands/SummaryPlotCommands/RicNewSummaryPlotFeature.cpp +++ b/ApplicationCode/Commands/SummaryPlotCommands/RicNewSummaryPlotFeature.cpp @@ -141,7 +141,98 @@ void RicNewSummaryPlotFeature::onActionTriggered(bool isChecked) //-------------------------------------------------------------------------------------------------- void RicNewSummaryPlotFeature::setupActionLook(QAction* actionToSetup) { - actionToSetup->setText("New Summary Plot"); + actionToSetup->setText("Open Summary Plot Editor"); actionToSetup->setIcon(QIcon(":/SummaryPlotLight16x16.png")); } +#include "RiuPlotMainWindowTools.h" +#include "RicNewSummaryCurveFeature.h" +#include "RimMainPlotCollection.h" + +CAF_CMD_SOURCE_INIT(RicNewSummaryPlotDirectFeature, "RicNewSummaryPlotDirectFeature"); + + +auto extractSumPlotCollectionOrSelectedSumCasesFromSelection() +{ + std::vector selectedSumCases; + RimSummaryPlotCollection* sumPlotColl = nullptr; + + std::vector selectedItems; + caf::SelectionManager::instance()->selectedItems(selectedItems); + + if ( selectedItems.size() ) + { + caf::PdmObject* selObj = dynamic_cast(selectedItems[0]); + sumPlotColl = RiaSummaryTools::parentSummaryPlotCollection(selObj); + } + + if (!sumPlotColl) + { + caf::SelectionManager::instance()->objectsByTypeStrict(&selectedSumCases); + } + + return std::make_pair(sumPlotColl, selectedSumCases); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RicNewSummaryPlotDirectFeature::isCommandEnabled() +{ + auto sumPlotSumCasesPair = extractSumPlotCollectionOrSelectedSumCasesFromSelection(); + + return sumPlotSumCasesPair.first || sumPlotSumCasesPair.second.size(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicNewSummaryPlotDirectFeature::onActionTriggered(bool isChecked) +{ + auto sumPlotSumCasesPair = extractSumPlotCollectionOrSelectedSumCasesFromSelection(); + + RimSummaryPlotCollection* sumPlotColl = RiaApplication::instance()->project()->mainPlotCollection()->summaryPlotCollection(); + + RimSummaryPlot* newPlot = nullptr; + + if (sumPlotSumCasesPair.first) + { + auto sumCaseVector = RiaApplication::instance()->project()->allSummaryCases(); + + newPlot = sumPlotColl->createSummaryPlotWithAutoTitle(); + + if (sumCaseVector.size()) + { + RicNewSummaryCurveFeature::addCurveToPlot(newPlot, sumCaseVector[0]); + } + } + else if (sumPlotSumCasesPair.second.size()) + { + newPlot = sumPlotColl->createSummaryPlotWithAutoTitle(); + + for (RimSummaryCase* sumCase : sumPlotSumCasesPair.second) + { + RicNewSummaryCurveFeature::addCurveToPlot(newPlot, sumCase); + } + } + + if ( newPlot ) + { + newPlot->loadDataAndUpdate(); + + sumPlotColl->updateConnectedEditors(); + + RiuPlotMainWindowTools::setExpanded(newPlot); + RiuPlotMainWindowTools::selectAsCurrentItem(newPlot); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicNewSummaryPlotDirectFeature::setupActionLook(QAction* actionToSetup) +{ + actionToSetup->setText("New Summary Plot"); + actionToSetup->setIcon(QIcon(":/SummaryPlotLight16x16.png")); + +} diff --git a/ApplicationCode/Commands/SummaryPlotCommands/RicNewSummaryPlotFeature.h b/ApplicationCode/Commands/SummaryPlotCommands/RicNewSummaryPlotFeature.h index d936e2ac10..3ae0904059 100644 --- a/ApplicationCode/Commands/SummaryPlotCommands/RicNewSummaryPlotFeature.h +++ b/ApplicationCode/Commands/SummaryPlotCommands/RicNewSummaryPlotFeature.h @@ -37,3 +37,17 @@ protected: void onActionTriggered( bool isChecked ) override; void setupActionLook(QAction* actionToSetup) override; }; + +//================================================================================================== +/// +//================================================================================================== +class RicNewSummaryPlotDirectFeature : public caf::CmdFeature +{ + CAF_CMD_HEADER_INIT; + +protected: + // Overrides + bool isCommandEnabled() override; + void onActionTriggered( bool isChecked ) override; + void setupActionLook(QAction* actionToSetup) override; +}; diff --git a/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp b/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp index 21c580bbf6..7795866a05 100644 --- a/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp +++ b/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp @@ -477,6 +477,7 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection() menuBuilder << "RicPasteAsciiDataToSummaryPlotFeature"; menuBuilder << "Separator"; menuBuilder << "RicNewSummaryPlotFeature"; + menuBuilder << "RicNewSummaryPlotDirectFeature"; menuBuilder << "Separator"; menuBuilder << "RicShowSummaryCurveCalculatorFeature"; } @@ -542,6 +543,7 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection() menuBuilder << "Separator"; menuBuilder << "RicEditSummaryPlotFeature"; menuBuilder << "RicNewSummaryPlotFeature"; + menuBuilder << "RicNewSummaryPlotDirectFeature"; menuBuilder << "RicDuplicateSummaryPlotFeature"; menuBuilder << "RicNewSummaryCurveFeature"; menuBuilder << "RicNewSummaryEnsembleCurveSetFeature"; @@ -621,6 +623,7 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection() menuBuilder.addSeparator(); menuBuilder << "RicNewDerivedEnsembleFeature"; menuBuilder << "RicNewSummaryPlotFeature"; + menuBuilder << "RicNewSummaryPlotDirectFeature"; menuBuilder << "RicNewSummaryCrossPlotFeature"; menuBuilder.addSeparator(); menuBuilder << "RicConvertGroupToEnsembleFeature"; @@ -636,6 +639,7 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection() menuBuilder.subMenuEnd(); menuBuilder.addSeparator(); menuBuilder << "RicNewSummaryPlotFeature"; + menuBuilder << "RicNewSummaryPlotDirectFeature"; menuBuilder << "RicNewSummaryCrossPlotFeature"; menuBuilder.addSeparator(); @@ -820,6 +824,7 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection() menuBuilder << "RicNewDerivedEnsembleFeature"; menuBuilder << "RicNewSummaryPlotFeature"; + menuBuilder << "RicNewSummaryPlotDirectFeature"; menuBuilder << "RicNewSummaryCrossPlotFeature"; menuBuilder << "RicSummaryCurveSwitchAxisFeature"; menuBuilder.addSeparator(); From 4ed30ad4afffba2d86cb3a4a5aa3c82d68872df0 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 9 Aug 2019 08:05:53 +0200 Subject: [PATCH 303/396] Avoid using c++-14 --- .../Commands/SummaryPlotCommands/RicNewSummaryPlotFeature.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ApplicationCode/Commands/SummaryPlotCommands/RicNewSummaryPlotFeature.cpp b/ApplicationCode/Commands/SummaryPlotCommands/RicNewSummaryPlotFeature.cpp index b2c25982e2..66d9baa6bb 100644 --- a/ApplicationCode/Commands/SummaryPlotCommands/RicNewSummaryPlotFeature.cpp +++ b/ApplicationCode/Commands/SummaryPlotCommands/RicNewSummaryPlotFeature.cpp @@ -152,7 +152,7 @@ void RicNewSummaryPlotFeature::setupActionLook(QAction* actionToSetup) CAF_CMD_SOURCE_INIT(RicNewSummaryPlotDirectFeature, "RicNewSummaryPlotDirectFeature"); -auto extractSumPlotCollectionOrSelectedSumCasesFromSelection() +std::pair> extractSumPlotCollectionOrSelectedSumCasesFromSelection() { std::vector selectedSumCases; RimSummaryPlotCollection* sumPlotColl = nullptr; From e915c8e18c6207bbd345419016d6e85fd692bb46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Fri, 9 Aug 2019 09:54:55 +0200 Subject: [PATCH 304/396] #4003 Refactoring to prepare for preferences based default summary plot curves --- .../Application/RiaPreferences.cpp | 7 ++ ApplicationCode/Application/RiaPreferences.h | 2 + .../Tools/RiaImportEclipseCaseTools.cpp | 3 +- .../Commands/RicImportSummaryCasesFeature.cpp | 16 +--- .../Commands/RicImportSummaryCasesFeature.h | 1 - .../CMakeLists_files.cmake | 2 + .../RicNewSummaryCurveFeature.cpp | 63 +----------- .../RicNewSummaryCurveFeature.h | 3 - .../RicNewSummaryPlotFeature.cpp | 17 ++-- .../RicNewSummaryPlotFeature.h | 2 +- .../RicSummaryPlotFeatureImpl.cpp | 95 +++++++++++++++++++ .../RicSummaryPlotFeatureImpl.h | 33 +++++++ .../RimContextCommandBuilder.cpp | 10 +- 13 files changed, 163 insertions(+), 91 deletions(-) create mode 100644 ApplicationCode/Commands/SummaryPlotCommands/RicSummaryPlotFeatureImpl.cpp create mode 100644 ApplicationCode/Commands/SummaryPlotCommands/RicSummaryPlotFeatureImpl.h diff --git a/ApplicationCode/Application/RiaPreferences.cpp b/ApplicationCode/Application/RiaPreferences.cpp index 7ff8fa389d..cd9bab914e 100644 --- a/ApplicationCode/Application/RiaPreferences.cpp +++ b/ApplicationCode/Application/RiaPreferences.cpp @@ -141,6 +141,8 @@ RiaPreferences::RiaPreferences(void) CAF_PDM_InitField(&gridImportMode, "gridImportMode", SummaryRestartFilesImportModeType(RiaPreferences::NOT_IMPORT), "Default Grid Import Option", "", "", ""); CAF_PDM_InitField(&summaryEnsembleImportMode, "summaryEnsembleImportMode", SummaryRestartFilesImportModeType(RiaPreferences::IMPORT), "Default Ensemble Summary Import Option", "", "", ""); + CAF_PDM_InitField(&defaultSummaryCurvesTextFilter, "defaultSummaryCurvesTextFilter", QString("FOPT"), "Default Summary Curves", "", "Semicolon separated list of filters used to create curves in new summary plots", ""); + CAF_PDM_InitFieldNoDefault(&m_holoLensExportFolder, "holoLensExportFolder", "HoloLens Export Folder", "", "", ""); m_holoLensExportFolder.uiCapability()->setUiLabelPosition(caf::PdmUiItemInfo::TOP); m_holoLensExportFolder.uiCapability()->setUiEditorTypeName(caf::PdmUiFilePathEditor::uiEditorTypeName()); @@ -283,6 +285,11 @@ void RiaPreferences::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& caf::PdmUiGroup* group = restartBehaviourGroup->addNewGroup("Origin Ensemble Summary Files"); group->add(&summaryEnsembleImportMode); } + + { + caf::PdmUiGroup* summaryPlotsGroup = uiOrdering.addNewGroup("Summary Plots"); + summaryPlotsGroup->add(&defaultSummaryCurvesTextFilter); + } } else if (uiConfigName == m_tabNames[2]) { diff --git a/ApplicationCode/Application/RiaPreferences.h b/ApplicationCode/Application/RiaPreferences.h index dca4eb8d15..7a412e2439 100644 --- a/ApplicationCode/Application/RiaPreferences.h +++ b/ApplicationCode/Application/RiaPreferences.h @@ -110,6 +110,8 @@ public: // Pdm Fields caf::PdmField gridImportMode; caf::PdmField summaryEnsembleImportMode; + caf::PdmField defaultSummaryCurvesTextFilter; + caf::PdmField holoLensDisableCertificateVerification; caf::PdmField csvTextExportFieldSeparator; diff --git a/ApplicationCode/Application/Tools/RiaImportEclipseCaseTools.cpp b/ApplicationCode/Application/Tools/RiaImportEclipseCaseTools.cpp index 7adf661e0a..a458e76082 100644 --- a/ApplicationCode/Application/Tools/RiaImportEclipseCaseTools.cpp +++ b/ApplicationCode/Application/Tools/RiaImportEclipseCaseTools.cpp @@ -22,6 +22,7 @@ #include "SummaryPlotCommands/RicNewSummaryPlotFeature.h" #include "SummaryPlotCommands/RicNewSummaryCurveFeature.h" +#include "SummaryPlotCommands/RicSummaryPlotFeatureImpl.h" #include "RiaApplication.h" #include "RiaGuiApplication.h" @@ -165,7 +166,7 @@ bool RiaImportEclipseCaseTools::openEclipseCasesFromFile(const QStringList& file { RimSummaryPlotCollection* summaryPlotColl = project->mainPlotCollection()->summaryPlotCollection(); - RicNewSummaryCurveFeature::ensureAtLeastOnePlot(summaryPlotColl, newSumCases.front()); + RicSummaryPlotFeatureImpl::ensureAtLeastOnePlot(summaryPlotColl, newSumCases.front()); RiuPlotMainWindowTools::setExpanded(newSumCases.front()); } diff --git a/ApplicationCode/Commands/RicImportSummaryCasesFeature.cpp b/ApplicationCode/Commands/RicImportSummaryCasesFeature.cpp index 64877e509c..9730dfa701 100644 --- a/ApplicationCode/Commands/RicImportSummaryCasesFeature.cpp +++ b/ApplicationCode/Commands/RicImportSummaryCasesFeature.cpp @@ -44,6 +44,7 @@ #include "SummaryPlotCommands/RicNewSummaryEnsembleCurveSetFeature.h" #include "SummaryPlotCommands/RicNewSummaryPlotFeature.h" +#include "SummaryPlotCommands/RicSummaryPlotFeatureImpl.h" #include "cafProgressInfo.h" #include "cafSelectionManagerTools.h" @@ -83,7 +84,7 @@ void RicImportSummaryCasesFeature::onActionTriggered(bool isChecked) addSummaryCases(cases); if (!cases.empty()) { - createNewPlot(cases.front()); + RicSummaryPlotFeatureImpl::createDefaultSummaryPlot(cases.front()); } addCasesToGroupIfRelevant(cases); @@ -132,7 +133,7 @@ bool RicImportSummaryCasesFeature::createAndAddSummaryCasesFromFiles(const QStri addSummaryCases(*cases); if (!cases->empty()) { - createNewPlot(cases->back()); + RicSummaryPlotFeatureImpl::createDefaultSummaryPlot(cases->back()); } RiuPlotMainWindow* mainPlotWindow = app->getOrCreateAndShowMainPlotWindow(); @@ -232,17 +233,6 @@ void RicImportSummaryCasesFeature::addCasesToGroupIfRelevant(const std::vectorproject(); - - RicNewSummaryCurveFeature::createNewPlot(proj->mainPlotCollection->summaryPlotCollection(), summaryCase); -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/Commands/RicImportSummaryCasesFeature.h b/ApplicationCode/Commands/RicImportSummaryCasesFeature.h index 0a1635390b..14afbad64a 100644 --- a/ApplicationCode/Commands/RicImportSummaryCasesFeature.h +++ b/ApplicationCode/Commands/RicImportSummaryCasesFeature.h @@ -42,7 +42,6 @@ public: static bool createSummaryCasesFromFiles(const QStringList& fileName, std::vector* newCases, bool ensembleOrGroup = false); static void addSummaryCases(const std::vector cases); static void addCasesToGroupIfRelevant(const std::vector cases); - static void createNewPlot(RimSummaryCase* summaryCase); static QStringList runRecursiveSummaryCaseFileSearchDialog(const QString& dialogTitle, const QString& pathCacheName); diff --git a/ApplicationCode/Commands/SummaryPlotCommands/CMakeLists_files.cmake b/ApplicationCode/Commands/SummaryPlotCommands/CMakeLists_files.cmake index c0b6833655..64b1b1429d 100644 --- a/ApplicationCode/Commands/SummaryPlotCommands/CMakeLists_files.cmake +++ b/ApplicationCode/Commands/SummaryPlotCommands/CMakeLists_files.cmake @@ -3,6 +3,7 @@ set (SOURCE_GROUP_HEADER_FILES ${CMAKE_CURRENT_LIST_DIR}/RicNewSummaryPlotFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicNewSummaryCrossPlotFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicNewSummaryCurveFeature.h +${CMAKE_CURRENT_LIST_DIR}/RicSummaryPlotFeatureImpl.h ${CMAKE_CURRENT_LIST_DIR}/RicDuplicateSummaryPlotFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicDuplicateSummaryCurveFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicDuplicateSummaryCrossPlotFeature.h @@ -46,6 +47,7 @@ set (SOURCE_GROUP_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/RicNewSummaryPlotFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicNewSummaryCrossPlotFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicNewSummaryCurveFeature.cpp +${CMAKE_CURRENT_LIST_DIR}/RicSummaryPlotFeatureImpl.cpp ${CMAKE_CURRENT_LIST_DIR}/RicDuplicateSummaryPlotFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicDuplicateSummaryCurveFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicDuplicateSummaryCrossPlotFeature.cpp diff --git a/ApplicationCode/Commands/SummaryPlotCommands/RicNewSummaryCurveFeature.cpp b/ApplicationCode/Commands/SummaryPlotCommands/RicNewSummaryCurveFeature.cpp index 6eb7a2c8ab..65b5b5c459 100644 --- a/ApplicationCode/Commands/SummaryPlotCommands/RicNewSummaryCurveFeature.cpp +++ b/ApplicationCode/Commands/SummaryPlotCommands/RicNewSummaryCurveFeature.cpp @@ -38,69 +38,10 @@ #include #include "RiuPlotMainWindowTools.h" +#include "RicSummaryPlotFeatureImpl.h" CAF_CMD_SOURCE_INIT(RicNewSummaryCurveFeature, "RicNewSummaryCurveFeature"); -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -RimSummaryCurve* RicNewSummaryCurveFeature::addCurveToPlot(RimSummaryPlot* plot, RimSummaryCase* summaryCase) -{ - if (plot) - { - RimSummaryCurve* newCurve = new RimSummaryCurve(); - - // Use same counting as RicNewSummaryEnsembleCurveSetFeature::onActionTriggered - cvf::Color3f curveColor = RiaColorTables::summaryCurveDefaultPaletteColors().cycledColor3f(plot->singleColorCurveCount()); - newCurve->setColor(curveColor); - - plot->addCurveNoUpdate(newCurve); - - if (summaryCase) - { - newCurve->setSummaryCaseY(summaryCase); - } - - newCurve->setSummaryAddressYAndApplyInterpolation(RifEclipseSummaryAddress::fieldAddress("FOPT")); - - return newCurve; - } - - return nullptr; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RicNewSummaryCurveFeature::ensureAtLeastOnePlot(RimSummaryPlotCollection* summaryPlotCollection, RimSummaryCase* summaryCase) -{ - if (summaryPlotCollection && summaryCase) - { - if (summaryPlotCollection->summaryPlots.empty()) - { - createNewPlot(summaryPlotCollection, summaryCase); - } - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RicNewSummaryCurveFeature::createNewPlot(RimSummaryPlotCollection* summaryPlotCollection, RimSummaryCase* summaryCase) -{ - if (summaryPlotCollection && summaryCase) - { - auto plot = summaryPlotCollection->createSummaryPlotWithAutoTitle(); - - auto curve = RicNewSummaryCurveFeature::addCurveToPlot(plot, summaryCase); - plot->loadDataAndUpdate(); - - summaryPlotCollection->updateConnectedEditors(); - - RiuPlotMainWindowTools::setExpanded(curve); - RiuPlotMainWindowTools::selectAsCurrentItem(curve); - } -} //-------------------------------------------------------------------------------------------------- /// @@ -128,7 +69,7 @@ void RicNewSummaryCurveFeature::onActionTriggered(bool isChecked) defaultCase = project->activeOilField()->summaryCaseMainCollection()->summaryCase(0); } - RimSummaryCurve* newCurve = addCurveToPlot(plot, defaultCase); + RimSummaryCurve* newCurve = RicSummaryPlotFeatureImpl::addDefaultCurveToPlot(plot, defaultCase); plot->loadDataAndUpdate(); plot->updateConnectedEditors(); diff --git a/ApplicationCode/Commands/SummaryPlotCommands/RicNewSummaryCurveFeature.h b/ApplicationCode/Commands/SummaryPlotCommands/RicNewSummaryCurveFeature.h index da3b28aa2f..dc62e52f94 100644 --- a/ApplicationCode/Commands/SummaryPlotCommands/RicNewSummaryCurveFeature.h +++ b/ApplicationCode/Commands/SummaryPlotCommands/RicNewSummaryCurveFeature.h @@ -35,9 +35,6 @@ class RicNewSummaryCurveFeature : public caf::CmdFeature CAF_CMD_HEADER_INIT; public: - static RimSummaryCurve* addCurveToPlot(RimSummaryPlot* plot, RimSummaryCase* summaryCase); - static void ensureAtLeastOnePlot(RimSummaryPlotCollection* summaryPlotCollection, RimSummaryCase* summaryCase); - static void createNewPlot(RimSummaryPlotCollection* summaryPlotCollection, RimSummaryCase* summaryCase); protected: // Overrides diff --git a/ApplicationCode/Commands/SummaryPlotCommands/RicNewSummaryPlotFeature.cpp b/ApplicationCode/Commands/SummaryPlotCommands/RicNewSummaryPlotFeature.cpp index 66d9baa6bb..598a390376 100644 --- a/ApplicationCode/Commands/SummaryPlotCommands/RicNewSummaryPlotFeature.cpp +++ b/ApplicationCode/Commands/SummaryPlotCommands/RicNewSummaryPlotFeature.cpp @@ -145,11 +145,16 @@ void RicNewSummaryPlotFeature::setupActionLook(QAction* actionToSetup) actionToSetup->setIcon(QIcon(":/SummaryPlotLight16x16.png")); } +//================================================================================================== +/// +//================================================================================================== + #include "RiuPlotMainWindowTools.h" #include "RicNewSummaryCurveFeature.h" #include "RimMainPlotCollection.h" +#include "RicSummaryPlotFeatureImpl.h" -CAF_CMD_SOURCE_INIT(RicNewSummaryPlotDirectFeature, "RicNewSummaryPlotDirectFeature"); +CAF_CMD_SOURCE_INIT(RicNewDefaultSummaryPlotFeature, "RicNewDefaultSummaryPlotFeature"); std::pair> extractSumPlotCollectionOrSelectedSumCasesFromSelection() @@ -177,7 +182,7 @@ std::pair> extractSumPlo //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool RicNewSummaryPlotDirectFeature::isCommandEnabled() +bool RicNewDefaultSummaryPlotFeature::isCommandEnabled() { auto sumPlotSumCasesPair = extractSumPlotCollectionOrSelectedSumCasesFromSelection(); @@ -187,7 +192,7 @@ bool RicNewSummaryPlotDirectFeature::isCommandEnabled() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicNewSummaryPlotDirectFeature::onActionTriggered(bool isChecked) +void RicNewDefaultSummaryPlotFeature::onActionTriggered(bool isChecked) { auto sumPlotSumCasesPair = extractSumPlotCollectionOrSelectedSumCasesFromSelection(); @@ -203,7 +208,7 @@ void RicNewSummaryPlotDirectFeature::onActionTriggered(bool isChecked) if (sumCaseVector.size()) { - RicNewSummaryCurveFeature::addCurveToPlot(newPlot, sumCaseVector[0]); + RicSummaryPlotFeatureImpl::addDefaultCurveToPlot(newPlot, sumCaseVector[0]); } } else if (sumPlotSumCasesPair.second.size()) @@ -212,7 +217,7 @@ void RicNewSummaryPlotDirectFeature::onActionTriggered(bool isChecked) for (RimSummaryCase* sumCase : sumPlotSumCasesPair.second) { - RicNewSummaryCurveFeature::addCurveToPlot(newPlot, sumCase); + RicSummaryPlotFeatureImpl::addDefaultCurveToPlot(newPlot, sumCase); } } @@ -230,7 +235,7 @@ void RicNewSummaryPlotDirectFeature::onActionTriggered(bool isChecked) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicNewSummaryPlotDirectFeature::setupActionLook(QAction* actionToSetup) +void RicNewDefaultSummaryPlotFeature::setupActionLook(QAction* actionToSetup) { actionToSetup->setText("New Summary Plot"); actionToSetup->setIcon(QIcon(":/SummaryPlotLight16x16.png")); diff --git a/ApplicationCode/Commands/SummaryPlotCommands/RicNewSummaryPlotFeature.h b/ApplicationCode/Commands/SummaryPlotCommands/RicNewSummaryPlotFeature.h index 3ae0904059..a47954bde5 100644 --- a/ApplicationCode/Commands/SummaryPlotCommands/RicNewSummaryPlotFeature.h +++ b/ApplicationCode/Commands/SummaryPlotCommands/RicNewSummaryPlotFeature.h @@ -41,7 +41,7 @@ protected: //================================================================================================== /// //================================================================================================== -class RicNewSummaryPlotDirectFeature : public caf::CmdFeature +class RicNewDefaultSummaryPlotFeature : public caf::CmdFeature { CAF_CMD_HEADER_INIT; diff --git a/ApplicationCode/Commands/SummaryPlotCommands/RicSummaryPlotFeatureImpl.cpp b/ApplicationCode/Commands/SummaryPlotCommands/RicSummaryPlotFeatureImpl.cpp new file mode 100644 index 0000000000..7a76685789 --- /dev/null +++ b/ApplicationCode/Commands/SummaryPlotCommands/RicSummaryPlotFeatureImpl.cpp @@ -0,0 +1,95 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 "RicSummaryPlotFeatureImpl.h" + +#include "RimSummaryCurve.h" +#include "RimSummaryPlot.h" +#include "RimSummaryPlotCollection.h" +#include "RimProject.h" +#include "RimMainPlotCollection.h" + +#include "RiuPlotMainWindowTools.h" + +#include "RiaApplication.h" +#include "RiaColorTables.h" + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimSummaryCurve* RicSummaryPlotFeatureImpl::addDefaultCurveToPlot(RimSummaryPlot* plot, RimSummaryCase* summaryCase) +{ + if (plot) + { + RimSummaryCurve* newCurve = new RimSummaryCurve(); + + // Use same counting as RicNewSummaryEnsembleCurveSetFeature::onActionTriggered + cvf::Color3f curveColor = RiaColorTables::summaryCurveDefaultPaletteColors().cycledColor3f(plot->singleColorCurveCount()); + newCurve->setColor(curveColor); + + plot->addCurveNoUpdate(newCurve); + + if (summaryCase) + { + newCurve->setSummaryCaseY(summaryCase); + } + + newCurve->setSummaryAddressYAndApplyInterpolation(RifEclipseSummaryAddress::fieldAddress("FOPT")); + + return newCurve; + } + + return nullptr; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicSummaryPlotFeatureImpl::ensureAtLeastOnePlot(RimSummaryPlotCollection* summaryPlotCollection, RimSummaryCase* summaryCase) +{ + if (summaryPlotCollection && summaryCase) + { + if (summaryPlotCollection->summaryPlots.empty()) + { + createDefaultSummaryPlot(summaryCase); + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicSummaryPlotFeatureImpl::createDefaultSummaryPlot( RimSummaryCase* summaryCase) +{ + RimSummaryPlotCollection* summaryPlotCollection = RiaApplication::instance()->project()->mainPlotCollection->summaryPlotCollection(); + + if (summaryPlotCollection && summaryCase) + { + auto plot = summaryPlotCollection->createSummaryPlotWithAutoTitle(); + + auto curve = RicSummaryPlotFeatureImpl::addDefaultCurveToPlot(plot, summaryCase); + plot->loadDataAndUpdate(); + + summaryPlotCollection->updateConnectedEditors(); + + RiuPlotMainWindowTools::setExpanded(curve); + RiuPlotMainWindowTools::selectAsCurrentItem(curve); + } +} + + diff --git a/ApplicationCode/Commands/SummaryPlotCommands/RicSummaryPlotFeatureImpl.h b/ApplicationCode/Commands/SummaryPlotCommands/RicSummaryPlotFeatureImpl.h new file mode 100644 index 0000000000..fc22b87a82 --- /dev/null +++ b/ApplicationCode/Commands/SummaryPlotCommands/RicSummaryPlotFeatureImpl.h @@ -0,0 +1,33 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 + +class RimSummaryCurve; +class RimSummaryPlot; +class RimSummaryCase; +class RimSummaryPlotCollection; + +class RicSummaryPlotFeatureImpl +{ +public: + static RimSummaryCurve* addDefaultCurveToPlot(RimSummaryPlot* plot, RimSummaryCase* summaryCase); + static void ensureAtLeastOnePlot(RimSummaryPlotCollection* summaryPlotCollection, RimSummaryCase* summaryCase); + static void createDefaultSummaryPlot(RimSummaryCase* summaryCase); + +}; + diff --git a/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp b/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp index 7795866a05..1fe447a880 100644 --- a/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp +++ b/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp @@ -477,7 +477,7 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection() menuBuilder << "RicPasteAsciiDataToSummaryPlotFeature"; menuBuilder << "Separator"; menuBuilder << "RicNewSummaryPlotFeature"; - menuBuilder << "RicNewSummaryPlotDirectFeature"; + menuBuilder << "RicNewDefaultSummaryPlotFeature"; menuBuilder << "Separator"; menuBuilder << "RicShowSummaryCurveCalculatorFeature"; } @@ -543,7 +543,7 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection() menuBuilder << "Separator"; menuBuilder << "RicEditSummaryPlotFeature"; menuBuilder << "RicNewSummaryPlotFeature"; - menuBuilder << "RicNewSummaryPlotDirectFeature"; + menuBuilder << "RicNewDefaultSummaryPlotFeature"; menuBuilder << "RicDuplicateSummaryPlotFeature"; menuBuilder << "RicNewSummaryCurveFeature"; menuBuilder << "RicNewSummaryEnsembleCurveSetFeature"; @@ -623,7 +623,7 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection() menuBuilder.addSeparator(); menuBuilder << "RicNewDerivedEnsembleFeature"; menuBuilder << "RicNewSummaryPlotFeature"; - menuBuilder << "RicNewSummaryPlotDirectFeature"; + menuBuilder << "RicNewDefaultSummaryPlotFeature"; menuBuilder << "RicNewSummaryCrossPlotFeature"; menuBuilder.addSeparator(); menuBuilder << "RicConvertGroupToEnsembleFeature"; @@ -639,7 +639,7 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection() menuBuilder.subMenuEnd(); menuBuilder.addSeparator(); menuBuilder << "RicNewSummaryPlotFeature"; - menuBuilder << "RicNewSummaryPlotDirectFeature"; + menuBuilder << "RicNewDefaultSummaryPlotFeature"; menuBuilder << "RicNewSummaryCrossPlotFeature"; menuBuilder.addSeparator(); @@ -824,7 +824,7 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection() menuBuilder << "RicNewDerivedEnsembleFeature"; menuBuilder << "RicNewSummaryPlotFeature"; - menuBuilder << "RicNewSummaryPlotDirectFeature"; + menuBuilder << "RicNewDefaultSummaryPlotFeature"; menuBuilder << "RicNewSummaryCrossPlotFeature"; menuBuilder << "RicSummaryCurveSwitchAxisFeature"; menuBuilder.addSeparator(); From 0bb84b22a5b1dbdcc45ce2ad5646b09e2e08baa8 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 9 Aug 2019 10:48:07 +0200 Subject: [PATCH 305/396] #4540 : Include full path when working with extensions --- ApplicationCode/Application/RiaEclipseFileNameTools.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ApplicationCode/Application/RiaEclipseFileNameTools.cpp b/ApplicationCode/Application/RiaEclipseFileNameTools.cpp index 4a6078d83a..c9789c01a5 100644 --- a/ApplicationCode/Application/RiaEclipseFileNameTools.cpp +++ b/ApplicationCode/Application/RiaEclipseFileNameTools.cpp @@ -42,7 +42,9 @@ void caf::AppEnum::setUp() //-------------------------------------------------------------------------------------------------- RiaEclipseFileNameTools::RiaEclipseFileNameTools(const QString& inputFilePath) { - m_baseName = findBaseName(inputFilePath); + QFileInfo fi(inputFilePath); + + m_baseName = fi.absolutePath() + "/" + fi.baseName(); } //-------------------------------------------------------------------------------------------------- From 31f44531359df239b99dd1ac66e37fcb1a9dafeb Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 9 Aug 2019 10:48:58 +0200 Subject: [PATCH 306/396] #4540 Command line : Fix option --case without file extension --- .../Application/RiaConsoleApplication.cpp | 4 +- .../Application/RiaGuiApplication.cpp | 5 +- .../Application/Tools/RiaArgumentParser.cpp | 1 - .../Commands/RicImportGeneralDataFeature.cpp | 46 +++++++++++++++---- .../Commands/RicImportGeneralDataFeature.h | 1 + 5 files changed, 42 insertions(+), 15 deletions(-) diff --git a/ApplicationCode/Application/RiaConsoleApplication.cpp b/ApplicationCode/Application/RiaConsoleApplication.cpp index a93e12fd4a..8d3687a126 100644 --- a/ApplicationCode/Application/RiaConsoleApplication.cpp +++ b/ApplicationCode/Application/RiaConsoleApplication.cpp @@ -257,9 +257,9 @@ RiaApplication::ApplicationStatus RiaConsoleApplication::handleArguments(cvf::Pr if (cvf::Option o = progOpt->option("case")) { - QStringList caseNames = cvfqt::Utils::toQStringList(o.values()); + QStringList fileNames = RicImportGeneralDataFeature::fileNamesFromCaseNames(cvfqt::Utils::toQStringList(o.values())); RicImportGeneralDataFeature::OpenCaseResults results = - RicImportGeneralDataFeature::openEclipseFilesFromFileNames(caseNames); + RicImportGeneralDataFeature::openEclipseFilesFromFileNames(fileNames); } if (cvf::Option o = progOpt->option("commandFile")) diff --git a/ApplicationCode/Application/RiaGuiApplication.cpp b/ApplicationCode/Application/RiaGuiApplication.cpp index adcbf82629..6725c0bfa7 100644 --- a/ApplicationCode/Application/RiaGuiApplication.cpp +++ b/ApplicationCode/Application/RiaGuiApplication.cpp @@ -774,9 +774,10 @@ RiaApplication::ApplicationStatus RiaGuiApplication::handleArguments(cvf::Progra if (cvf::Option o = progOpt->option("case")) { - QStringList caseNames = cvfqt::Utils::toQStringList(o.values()); + QStringList fileNames = RicImportGeneralDataFeature::fileNamesFromCaseNames(cvfqt::Utils::toQStringList(o.values())); + RicImportGeneralDataFeature::OpenCaseResults results = - RicImportGeneralDataFeature::openEclipseFilesFromFileNames(caseNames); + RicImportGeneralDataFeature::openEclipseFilesFromFileNames(fileNames); if (results && !results.eclipseSummaryFiles.empty()) { getOrCreateAndShowMainPlotWindow(); diff --git a/ApplicationCode/Application/Tools/RiaArgumentParser.cpp b/ApplicationCode/Application/Tools/RiaArgumentParser.cpp index 938c777650..6361f7cc3f 100644 --- a/ApplicationCode/Application/Tools/RiaArgumentParser.cpp +++ b/ApplicationCode/Application/Tools/RiaArgumentParser.cpp @@ -19,7 +19,6 @@ #include "RiaArgumentParser.h" #include "RiaApplication.h" #include "RiaBaseDefs.h" -#include "RiaEclipseFileNameTools.h" #include "RiaImportEclipseCaseTools.h" #include "RiaLogging.h" #include "RiaPreferences.h" diff --git a/ApplicationCode/Commands/RicImportGeneralDataFeature.cpp b/ApplicationCode/Commands/RicImportGeneralDataFeature.cpp index 18405e67b7..a85267cfcf 100644 --- a/ApplicationCode/Commands/RicImportGeneralDataFeature.cpp +++ b/ApplicationCode/Commands/RicImportGeneralDataFeature.cpp @@ -19,6 +19,7 @@ #include "RiaApplication.h" #include "RiaDefines.h" +#include "RiaEclipseFileNameTools.h" #include "RiaImportEclipseCaseTools.h" #include "RiaLogging.h" @@ -40,7 +41,8 @@ CAF_CMD_SOURCE_INIT(RicImportGeneralDataFeature, "RicImportGeneralDataFeature"); //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RicImportGeneralDataFeature::OpenCaseResults RicImportGeneralDataFeature::openEclipseFilesFromFileNames(const QStringList& fileNames) +RicImportGeneralDataFeature::OpenCaseResults + RicImportGeneralDataFeature::openEclipseFilesFromFileNames(const QStringList& fileNames) { CVF_ASSERT(!fileNames.empty()); @@ -74,7 +76,7 @@ RicImportGeneralDataFeature::OpenCaseResults RicImportGeneralDataFeature::openEc return OpenCaseResults(); } results.eclipseCaseFiles = eclipseCaseFiles; - RiaApplication::instance()->setLastUsedDialogDirectory(defaultDirectoryLabel(ECLIPSE_EGRID_FILE), defaultDir); + RiaApplication::instance()->setLastUsedDialogDirectory(defaultDirectoryLabel(ECLIPSE_EGRID_FILE), defaultDir); } if (!eclipseInputFiles.empty()) { @@ -83,7 +85,7 @@ RicImportGeneralDataFeature::OpenCaseResults RicImportGeneralDataFeature::openEc return OpenCaseResults(); } results.eclipseInputFiles = eclipseInputFiles; - RiaApplication::instance()->setLastUsedDialogDirectory(defaultDirectoryLabel(ECLIPSE_INPUT_FILE), defaultDir); + RiaApplication::instance()->setLastUsedDialogDirectory(defaultDirectoryLabel(ECLIPSE_INPUT_FILE), defaultDir); } if (!eclipseSummaryFiles.empty()) { @@ -97,6 +99,30 @@ RicImportGeneralDataFeature::OpenCaseResults RicImportGeneralDataFeature::openEc return results; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QStringList RicImportGeneralDataFeature::fileNamesFromCaseNames(const QStringList& caseNames) +{ + QStringList fileNames; + { + for (const auto& caseName : caseNames) + { + if (caseName.lastIndexOf(".") != -1) + { + fileNames.push_back(caseName); + } + else + { + RiaEclipseFileNameTools nameTool(caseName); + QString filenameWithExtension = nameTool.findRelatedGridFile(); + fileNames.push_back(filenameWithExtension); + } + } + } + + return fileNames; +} //-------------------------------------------------------------------------------------------------- /// @@ -127,7 +153,7 @@ void RicImportGeneralDataFeature::setupActionLook(QAction* actionToSetup) /// //-------------------------------------------------------------------------------------------------- void RicImportGeneralDataFeature::openFileDialog(ImportFileType fileTypes) -{ +{ QString eclipseGridFilePattern("*.GRID"); QString eclipseEGridFilePattern("*.EGRID"); QString eclipseInputFilePattern("*.GRDECL"); @@ -137,10 +163,10 @@ void RicImportGeneralDataFeature::openFileDialog(ImportFileType fileTypes) if (fileTypes == ANY_ECLIPSE_FILE) { filePatternTexts += QString("Eclipse Files (%1 %2 %3 %4)") - .arg(eclipseGridFilePattern) - .arg(eclipseEGridFilePattern) - .arg(eclipseInputFilePattern) - .arg(eclipseSummaryFilePattern); + .arg(eclipseGridFilePattern) + .arg(eclipseEGridFilePattern) + .arg(eclipseInputFilePattern) + .arg(eclipseSummaryFilePattern); } if (fileTypes & ECLIPSE_GRID_FILE) { @@ -160,7 +186,7 @@ void RicImportGeneralDataFeature::openFileDialog(ImportFileType fileTypes) } QString fullPattern = filePatternTexts.join(";;"); - + QString defaultDir = RiaApplication::instance()->lastUsedDialogDirectory(defaultDirectoryLabel(fileTypes)); QStringList fileNames = @@ -172,7 +198,7 @@ void RicImportGeneralDataFeature::openFileDialog(ImportFileType fileTypes) { RiaApplication::instance()->setLastUsedDialogDirectory(defaultDirectoryLabel(ANY_ECLIPSE_FILE), fileNames.front()); } - + if (!openEclipseFilesFromFileNames(fileNames)) { RiaLogging::error(QString("Failed to open file names: %1").arg(fileNames.join(", "))); diff --git a/ApplicationCode/Commands/RicImportGeneralDataFeature.h b/ApplicationCode/Commands/RicImportGeneralDataFeature.h index 5211b60ceb..7a8b095f8b 100644 --- a/ApplicationCode/Commands/RicImportGeneralDataFeature.h +++ b/ApplicationCode/Commands/RicImportGeneralDataFeature.h @@ -47,6 +47,7 @@ public: }; static OpenCaseResults openEclipseFilesFromFileNames(const QStringList& fileNames); + static QStringList fileNamesFromCaseNames(const QStringList& caseNames); protected: From 93b41018318f37656d76d820ef596d6638283565 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Fri, 9 Aug 2019 13:15:32 +0200 Subject: [PATCH 307/396] #4003 Use the preferences settings when creating default summary plots. Refactored to make assigning default curve appearance easier. --- .../RicNewSummaryCurveFeature.cpp | 1 + .../RicNewSummaryPlotFeature.cpp | 26 +++---- .../RicSummaryCurveCreator.cpp | 74 ++---------------- .../RicSummaryCurveCreator.h | 3 - .../RicSummaryPlotFeatureImpl.cpp | 76 ++++++++++++++++++- .../RicSummaryPlotFeatureImpl.h | 4 + .../RifEclipseSummaryAddress.cpp | 18 +++++ .../FileInterface/RifEclipseSummaryAddress.h | 3 +- .../RimSummaryCurveAppearanceCalculator.cpp | 61 ++++++++++++++- .../RimSummaryCurveAppearanceCalculator.h | 7 +- .../Summary/RimSummaryFilter.cpp | 2 +- .../Summary/RimSummaryPlot.cpp | 41 ++++++++++ .../ProjectDataModel/Summary/RimSummaryPlot.h | 3 + 13 files changed, 222 insertions(+), 97 deletions(-) diff --git a/ApplicationCode/Commands/SummaryPlotCommands/RicNewSummaryCurveFeature.cpp b/ApplicationCode/Commands/SummaryPlotCommands/RicNewSummaryCurveFeature.cpp index 65b5b5c459..b7a7ba156a 100644 --- a/ApplicationCode/Commands/SummaryPlotCommands/RicNewSummaryCurveFeature.cpp +++ b/ApplicationCode/Commands/SummaryPlotCommands/RicNewSummaryCurveFeature.cpp @@ -71,6 +71,7 @@ void RicNewSummaryCurveFeature::onActionTriggered(bool isChecked) RimSummaryCurve* newCurve = RicSummaryPlotFeatureImpl::addDefaultCurveToPlot(plot, defaultCase); + plot->applyDefaultCurveAppearances(); plot->loadDataAndUpdate(); plot->updateConnectedEditors(); diff --git a/ApplicationCode/Commands/SummaryPlotCommands/RicNewSummaryPlotFeature.cpp b/ApplicationCode/Commands/SummaryPlotCommands/RicNewSummaryPlotFeature.cpp index 598a390376..af43fce428 100644 --- a/ApplicationCode/Commands/SummaryPlotCommands/RicNewSummaryPlotFeature.cpp +++ b/ApplicationCode/Commands/SummaryPlotCommands/RicNewSummaryPlotFeature.cpp @@ -196,33 +196,33 @@ void RicNewDefaultSummaryPlotFeature::onActionTriggered(bool isChecked) { auto sumPlotSumCasesPair = extractSumPlotCollectionOrSelectedSumCasesFromSelection(); - RimSummaryPlotCollection* sumPlotColl = RiaApplication::instance()->project()->mainPlotCollection()->summaryPlotCollection(); - - RimSummaryPlot* newPlot = nullptr; + std::vector summaryCasesToUse; if (sumPlotSumCasesPair.first) { auto sumCaseVector = RiaApplication::instance()->project()->allSummaryCases(); - newPlot = sumPlotColl->createSummaryPlotWithAutoTitle(); - if (sumCaseVector.size()) { - RicSummaryPlotFeatureImpl::addDefaultCurveToPlot(newPlot, sumCaseVector[0]); + summaryCasesToUse.push_back(sumCaseVector[0]); } } else if (sumPlotSumCasesPair.second.size()) { - newPlot = sumPlotColl->createSummaryPlotWithAutoTitle(); - - for (RimSummaryCase* sumCase : sumPlotSumCasesPair.second) - { - RicSummaryPlotFeatureImpl::addDefaultCurveToPlot(newPlot, sumCase); - } + summaryCasesToUse = sumPlotSumCasesPair.second; } - if ( newPlot ) + if ( summaryCasesToUse.size() ) { + RimSummaryPlotCollection* sumPlotColl = RiaApplication::instance()->project()->mainPlotCollection()->summaryPlotCollection(); + RimSummaryPlot* newPlot = sumPlotColl->createSummaryPlotWithAutoTitle(); + + for (RimSummaryCase* sumCase : summaryCasesToUse) + { + RicSummaryPlotFeatureImpl::addDefaultCurvesToPlot(newPlot, sumCase); + } + + newPlot->applyDefaultCurveAppearances(); newPlot->loadDataAndUpdate(); sumPlotColl->updateConnectedEditors(); diff --git a/ApplicationCode/Commands/SummaryPlotCommands/RicSummaryCurveCreator.cpp b/ApplicationCode/Commands/SummaryPlotCommands/RicSummaryCurveCreator.cpp index c703834067..2e0dcba7fc 100644 --- a/ApplicationCode/Commands/SummaryPlotCommands/RicSummaryCurveCreator.cpp +++ b/ApplicationCode/Commands/SummaryPlotCommands/RicSummaryCurveCreator.cpp @@ -441,8 +441,7 @@ void RicSummaryCurveCreator::updatePreviewCurvesFromCurveDefinitions( if (!def.isEnsembleCurve()) summaryCurveDefsToDisplay.insert(def); } - RimSummaryCurveAppearanceCalculator curveLookCalc( - summaryCurveDefsToDisplay, getAllSummaryCaseNames(), getAllSummaryWellNames()); + RimSummaryCurveAppearanceCalculator curveLookCalc(summaryCurveDefsToDisplay); initCurveAppearanceCalculator(curveLookCalc); // Delete curves @@ -528,55 +527,6 @@ void RicSummaryCurveCreator::updatePreviewCurvesFromCurveDefinitions( m_previewPlot->summaryCurveCollection()->updateConnectedEditors(); } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -std::set RicSummaryCurveCreator::getAllSummaryCaseNames() -{ - std::set summaryCaseHashes; - RimProject* proj = RiaApplication::instance()->project(); - - std::vector cases = proj->allSummaryCases(); - for (RimSummaryCase* rimCase : cases) - { - summaryCaseHashes.insert(rimCase->summaryHeaderFilename().toUtf8().constData()); - } - - return summaryCaseHashes; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -std::set RicSummaryCurveCreator::getAllSummaryWellNames() -{ - std::set summaryWellNames; - RimProject* proj = RiaApplication::instance()->project(); - - std::vector cases = proj->allSummaryCases(); - for (RimSummaryCase* rimCase : cases) - { - RifSummaryReaderInterface* reader = nullptr; - if (rimCase) - { - reader = rimCase->summaryReader(); - } - - if (reader) - { - const std::set allAddresses = reader->allResultAddresses(); - - for (auto& address : allAddresses) - { - if (address.category() == RifEclipseSummaryAddress::SUMMARY_WELL) - { - summaryWellNames.insert(address.wellName()); - } - } - } - } - return summaryWellNames; -} //-------------------------------------------------------------------------------------------------- /// @@ -816,9 +766,9 @@ void RicSummaryCurveCreator::initCurveAppearanceCalculator(RimSummaryCurveAppear //-------------------------------------------------------------------------------------------------- void RicSummaryCurveCreator::applyAppearanceToAllPreviewCurves() { - std::set allCurveDefs = allPreviewCurveDefs(); + std::set allCurveDefs = m_previewPlot->summaryAndEnsembleCurveDefinitions(); - RimSummaryCurveAppearanceCalculator curveLookCalc(allCurveDefs, getAllSummaryCaseNames(), getAllSummaryWellNames()); + RimSummaryCurveAppearanceCalculator curveLookCalc(allCurveDefs); initCurveAppearanceCalculator(curveLookCalc); // Summary curves @@ -842,26 +792,12 @@ void RicSummaryCurveCreator::applyAppearanceToAllPreviewCurves() //-------------------------------------------------------------------------------------------------- void RicSummaryCurveCreator::updateAppearanceEditor() { - std::set allCurveDefs = allPreviewCurveDefs(); + std::set allCurveDefs = m_previewPlot->summaryAndEnsembleCurveDefinitions(); - RimSummaryCurveAppearanceCalculator curveLookCalc(allCurveDefs, getAllSummaryCaseNames(), getAllSummaryWellNames()); + RimSummaryCurveAppearanceCalculator curveLookCalc(allCurveDefs); initCurveAppearanceCalculator(curveLookCalc); } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -std::set RicSummaryCurveCreator::allPreviewCurveDefs() const -{ - std::set allCurveDefs; - - for (const auto& curve : m_previewPlot->summaryAndEnsembleCurves()) - { - allCurveDefs.insert(RiaSummaryCurveDefinition(curve->summaryCaseY(), curve->summaryAddressY())); - } - return allCurveDefs; -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/Commands/SummaryPlotCommands/RicSummaryCurveCreator.h b/ApplicationCode/Commands/SummaryPlotCommands/RicSummaryCurveCreator.h index 7c065dda8e..c58de47861 100644 --- a/ApplicationCode/Commands/SummaryPlotCommands/RicSummaryCurveCreator.h +++ b/ApplicationCode/Commands/SummaryPlotCommands/RicSummaryCurveCreator.h @@ -89,8 +89,6 @@ private: const std::set& curveDefsToAdd, const std::set& curvesToDelete, const std::set& curveSetsToDelete); - std::set getAllSummaryCaseNames(); - std::set getAllSummaryWellNames(); void populateCurveCreator(const RimSummaryPlot& sourceSummaryPlot); void updateTargetPlot(); @@ -102,7 +100,6 @@ private: void initCurveAppearanceCalculator(RimSummaryCurveAppearanceCalculator& curveAppearanceCalc); void applyAppearanceToAllPreviewCurves(); void updateAppearanceEditor(); - std::set allPreviewCurveDefs() const; void createNewPlot(); bool isObservedData(RimSummaryCase *sumCase) const; diff --git a/ApplicationCode/Commands/SummaryPlotCommands/RicSummaryPlotFeatureImpl.cpp b/ApplicationCode/Commands/SummaryPlotCommands/RicSummaryPlotFeatureImpl.cpp index 7a76685789..11811f7424 100644 --- a/ApplicationCode/Commands/SummaryPlotCommands/RicSummaryPlotFeatureImpl.cpp +++ b/ApplicationCode/Commands/SummaryPlotCommands/RicSummaryPlotFeatureImpl.cpp @@ -28,6 +28,9 @@ #include "RiaApplication.h" #include "RiaColorTables.h" +#include "RiaPreferences.h" +#include "RifSummaryReaderInterface.h" +#include "RimSummaryCase.h" //-------------------------------------------------------------------------------------------------- /// @@ -36,6 +39,27 @@ RimSummaryCurve* RicSummaryPlotFeatureImpl::addDefaultCurveToPlot(RimSummaryPlot { if (plot) { + RifEclipseSummaryAddress defaultAddressToUse; + + QString curvesTextFilter = RiaApplication::instance()->preferences()->defaultSummaryCurvesTextFilter; + QStringList curveFilters = curvesTextFilter.split(";", QString::SkipEmptyParts); + + if ( curveFilters.size() ) + { + const std::set& addrs = summaryCase->summaryReader()->allResultAddresses(); + + for ( const auto & addr : addrs ) + { + const QString& filter = curveFilters[0]; + { + if ( addr.isUiTextMatchingFilterText(filter) ) + { + defaultAddressToUse = addr; + } + } + } + } + RimSummaryCurve* newCurve = new RimSummaryCurve(); // Use same counting as RicNewSummaryEnsembleCurveSetFeature::onActionTriggered @@ -49,7 +73,7 @@ RimSummaryCurve* RicSummaryPlotFeatureImpl::addDefaultCurveToPlot(RimSummaryPlot newCurve->setSummaryCaseY(summaryCase); } - newCurve->setSummaryAddressYAndApplyInterpolation(RifEclipseSummaryAddress::fieldAddress("FOPT")); + newCurve->setSummaryAddressYAndApplyInterpolation(defaultAddressToUse); return newCurve; } @@ -57,6 +81,45 @@ RimSummaryCurve* RicSummaryPlotFeatureImpl::addDefaultCurveToPlot(RimSummaryPlot return nullptr; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RicSummaryPlotFeatureImpl::addDefaultCurvesToPlot(RimSummaryPlot* plot, RimSummaryCase* summaryCase) +{ + std::vector defaultCurves; + + QString curvesTextFilter = RiaApplication::instance()->preferences()->defaultSummaryCurvesTextFilter; + QStringList curveFilters = curvesTextFilter.split(";", QString::SkipEmptyParts); + + const std::set& addrs = summaryCase->summaryReader()->allResultAddresses(); + std::vector curveAddressesToUse; + + for (const auto & addr : addrs) + { + for (const QString& filter: curveFilters) + { + if ( addr.isUiTextMatchingFilterText(filter) ) + { + curveAddressesToUse.push_back(addr); + } + } + } + + for (const auto & addr : curveAddressesToUse) + { + RimSummaryCurve* newCurve = new RimSummaryCurve(); + plot->addCurveNoUpdate(newCurve); + if (summaryCase) + { + newCurve->setSummaryCaseY(summaryCase); + } + newCurve->setSummaryAddressYAndApplyInterpolation(addr); + defaultCurves.push_back(newCurve); + } + + return defaultCurves; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -82,13 +145,18 @@ void RicSummaryPlotFeatureImpl::createDefaultSummaryPlot( RimSummaryCase* summar { auto plot = summaryPlotCollection->createSummaryPlotWithAutoTitle(); - auto curve = RicSummaryPlotFeatureImpl::addDefaultCurveToPlot(plot, summaryCase); + std::vector curves = RicSummaryPlotFeatureImpl::addDefaultCurvesToPlot(plot, summaryCase); + + plot->applyDefaultCurveAppearances(); plot->loadDataAndUpdate(); summaryPlotCollection->updateConnectedEditors(); - RiuPlotMainWindowTools::setExpanded(curve); - RiuPlotMainWindowTools::selectAsCurrentItem(curve); + caf::PdmObject* itemToSelect = plot; + if (curves.size()) itemToSelect = curves[0]; + + RiuPlotMainWindowTools::setExpanded(itemToSelect); + RiuPlotMainWindowTools::selectAsCurrentItem(itemToSelect); } } diff --git a/ApplicationCode/Commands/SummaryPlotCommands/RicSummaryPlotFeatureImpl.h b/ApplicationCode/Commands/SummaryPlotCommands/RicSummaryPlotFeatureImpl.h index fc22b87a82..3ddd497fd0 100644 --- a/ApplicationCode/Commands/SummaryPlotCommands/RicSummaryPlotFeatureImpl.h +++ b/ApplicationCode/Commands/SummaryPlotCommands/RicSummaryPlotFeatureImpl.h @@ -22,12 +22,16 @@ class RimSummaryPlot; class RimSummaryCase; class RimSummaryPlotCollection; +#include + class RicSummaryPlotFeatureImpl { public: static RimSummaryCurve* addDefaultCurveToPlot(RimSummaryPlot* plot, RimSummaryCase* summaryCase); + static std::vector addDefaultCurvesToPlot(RimSummaryPlot* plot, RimSummaryCase* summaryCase); static void ensureAtLeastOnePlot(RimSummaryPlotCollection* summaryPlotCollection, RimSummaryCase* summaryCase); static void createDefaultSummaryPlot(RimSummaryCase* summaryCase); + }; diff --git a/ApplicationCode/FileInterface/RifEclipseSummaryAddress.cpp b/ApplicationCode/FileInterface/RifEclipseSummaryAddress.cpp index d1bdd2a451..6169b39bf9 100644 --- a/ApplicationCode/FileInterface/RifEclipseSummaryAddress.cpp +++ b/ApplicationCode/FileInterface/RifEclipseSummaryAddress.cpp @@ -644,6 +644,24 @@ std::string RifEclipseSummaryAddress::uiText(RifEclipseSummaryAddress::SummaryId return ""; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RifEclipseSummaryAddress::isUiTextMatchingFilterText(const QString& filterString) const +{ + std::string value = uiText(); + if(filterString.isEmpty()) return true; + if(filterString.trimmed() == "*") + { + if(!value.empty()) return true; + else return false; + } + + QRegExp searcher(filterString, Qt::CaseInsensitive, QRegExp::WildcardUnix); + QString qstrValue = QString::fromStdString(value); + return searcher.exactMatch(qstrValue); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/FileInterface/RifEclipseSummaryAddress.h b/ApplicationCode/FileInterface/RifEclipseSummaryAddress.h index 8635f029da..2a017cb7c2 100644 --- a/ApplicationCode/FileInterface/RifEclipseSummaryAddress.h +++ b/ApplicationCode/FileInterface/RifEclipseSummaryAddress.h @@ -23,7 +23,7 @@ #include class QTextStream; - +class QString; #define ENSEMBLE_STAT_P10_QUANTITY_NAME "P10" #define ENSEMBLE_STAT_P50_QUANTITY_NAME "P50" @@ -170,6 +170,7 @@ public: std::string uiText() const; std::string uiText(RifEclipseSummaryAddress::SummaryIdentifierType itemTypeInput) const; + bool isUiTextMatchingFilterText(const QString& filterString) const; bool isValid() const; void setQuantityName(const std::string& quantity) { m_quantityName = quantity; } diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurveAppearanceCalculator.cpp b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurveAppearanceCalculator.cpp index 270c76b6e2..d0a99f3ab4 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurveAppearanceCalculator.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurveAppearanceCalculator.cpp @@ -20,10 +20,15 @@ #include "RiaColorTables.h" #include "RiaSummaryCurveDefinition.h" +#include "RiaApplication.h" + #include "RiuQwtPlotCurve.h" #include "RimSummaryCurve.h" #include "RimSummaryCase.h" +#include "RimProject.h" + +#include "RifSummaryReaderInterface.h" #include "cvfVector3.h" @@ -61,10 +66,10 @@ bool isExcplicitHandled(char secondChar) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RimSummaryCurveAppearanceCalculator::RimSummaryCurveAppearanceCalculator(const std::set& curveDefinitions, const std::set& allSummaryCaseNames, const std::set& allSummaryWellNames) +RimSummaryCurveAppearanceCalculator::RimSummaryCurveAppearanceCalculator(const std::set& curveDefinitions) { - m_allSummaryCaseNames = allSummaryCaseNames; - m_allSummaryWellNames = allSummaryWellNames; + m_allSummaryCaseNames = getAllSummaryCaseNames(); + m_allSummaryWellNames = getAllSummaryWellNames(); for(const RiaSummaryCurveDefinition& curveDef : curveDefinitions) { @@ -517,3 +522,53 @@ cvf::Color3f RimSummaryCurveAppearanceCalculator::gradeColor(const cvf::Color3f& return cvf::Color3f(newColor[0], newColor[1], newColor[2]); } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::set RimSummaryCurveAppearanceCalculator::getAllSummaryCaseNames() +{ + std::set summaryCaseHashes; + RimProject* proj = RiaApplication::instance()->project(); + + std::vector cases = proj->allSummaryCases(); + for (RimSummaryCase* rimCase : cases) + { + summaryCaseHashes.insert(rimCase->summaryHeaderFilename().toUtf8().constData()); + } + + return summaryCaseHashes; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::set RimSummaryCurveAppearanceCalculator::getAllSummaryWellNames() +{ + std::set summaryWellNames; + RimProject* proj = RiaApplication::instance()->project(); + + std::vector cases = proj->allSummaryCases(); + for (RimSummaryCase* rimCase : cases) + { + RifSummaryReaderInterface* reader = nullptr; + if (rimCase) + { + reader = rimCase->summaryReader(); + } + + if (reader) + { + const std::set allAddresses = reader->allResultAddresses(); + + for (auto& address : allAddresses) + { + if (address.category() == RifEclipseSummaryAddress::SUMMARY_WELL) + { + summaryWellNames.insert(address.wellName()); + } + } + } + } + return summaryWellNames; +} diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurveAppearanceCalculator.h b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurveAppearanceCalculator.h index 0b5ff28430..158b65cb18 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurveAppearanceCalculator.h +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurveAppearanceCalculator.h @@ -32,9 +32,7 @@ class RiaSummaryCurveDefinition; class RimSummaryCurveAppearanceCalculator { public: - explicit RimSummaryCurveAppearanceCalculator(const std::set& curveDefinitions, - const std::set& allSummaryCaseNames, - const std::set& allSummaryWellNames); + explicit RimSummaryCurveAppearanceCalculator(const std::set& curveDefinitions); enum CurveAppearanceType { NONE, @@ -80,6 +78,9 @@ private: cvf::Color3f gradeColor(const cvf::Color3f& color , float factor); + static std::set getAllSummaryCaseNames(); + static std::set getAllSummaryWellNames(); + cvf::Color3f m_currentCurveBaseColor; float m_currentCurveGradient; diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryFilter.cpp b/ApplicationCode/ProjectDataModel/Summary/RimSummaryFilter.cpp index 2ae8ad6411..71640f0e7d 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryFilter.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryFilter.cpp @@ -240,7 +240,7 @@ bool RimSummaryFilter::isIncludedByFilter(const RifEclipseSummaryAddress& addr) if(m_filterType() == SUM_FILTER_VAR_STRING) { - return isStringMatch(m_completeVarStringFilter(), addr.uiText()); + return addr.isUiTextMatchingFilterText(m_completeVarStringFilter()); } if(!isStringMatch(m_filterQuantityName(), addr.quantityName())) return false; diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlot.cpp b/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlot.cpp index 4e6181107c..485ef6a2e5 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlot.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlot.cpp @@ -63,6 +63,8 @@ #include #include #include +#include "RiaSummaryCurveDefinition.h" +#include "RiaColorTables.h" CAF_PDM_SOURCE_INIT(RimSummaryPlot, "SummaryPlot"); @@ -342,6 +344,20 @@ std::vector RimSummaryPlot::summaryAndEnsembleCurves() const return curves; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::set RimSummaryPlot::summaryAndEnsembleCurveDefinitions() const +{ + std::set allCurveDefs; + + for (const auto& curve : this->summaryAndEnsembleCurves()) + { + allCurveDefs.insert(RiaSummaryCurveDefinition(curve->summaryCaseY(), curve->summaryAddressY())); + } + return allCurveDefs; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -539,6 +555,31 @@ size_t RimSummaryPlot::singleColorCurveCount() const return colorIndex; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimSummaryPlot::applyDefaultCurveAppearances() +{ + std::set allCurveDefs = this->summaryAndEnsembleCurveDefinitions(); + + RimSummaryCurveAppearanceCalculator curveLookCalc(allCurveDefs); + + // Summary curves + for (auto& curve : this->summaryCurves()) + { + curve->resetAppearance(); + curveLookCalc.setupCurveLook(curve); + } + + // Ensemble curve sets + int colorIndex = 0; + for (auto& curveSet : this->ensembleCurveSetCollection()->curveSets()) + { + if (curveSet->colorMode() != RimEnsembleCurveSet::SINGLE_COLOR) continue; + curveSet->setColor(RiaColorTables::summaryCurveDefaultPaletteColors().cycledColor3f(colorIndex++)); + } +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlot.h b/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlot.h index e833dc7b3d..7a51c40c60 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlot.h +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlot.h @@ -23,6 +23,7 @@ #include "RiaDefines.h" #include "RiaQDateTimeTools.h" +#include "RiaSummaryCurveDefinition.h" #include "RifEclipseSummaryAddress.h" @@ -107,6 +108,7 @@ public: QString asciiDataForPlotExport(DateTimePeriod resamplingPeriod = DateTimePeriod::NONE) const; std::vector summaryAndEnsembleCurves() const; + std::set summaryAndEnsembleCurveDefinitions() const; std::vector summaryCurves() const; void deleteAllSummaryCurves(); RimSummaryCurveCollection* summaryCurveCollection() const; @@ -132,6 +134,7 @@ public: bool containsResamplableCurves() const; size_t singleColorCurveCount() const; + void applyDefaultCurveAppearances(); bool hasCustomFontSizes(RiaDefines::FontSettingType fontSettingType, int defaultFontSize) const override; From 08e966e4d71d1fa874cf5b353d257522ad1c8cb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Fri, 9 Aug 2019 14:04:54 +0200 Subject: [PATCH 308/396] Removed issue templates --- .github/ISSUE_TEMPLATE/bug_report.md | 14 -------------- .github/ISSUE_TEMPLATE/enhancement.md | 10 ---------- .github/ISSUE_TEMPLATE/feature_request.md | 20 -------------------- 3 files changed, 44 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/bug_report.md delete mode 100644 .github/ISSUE_TEMPLATE/enhancement.md delete mode 100644 .github/ISSUE_TEMPLATE/feature_request.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index 29c9a309b7..0000000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -name: Bug report -about: Create a report to help us improve -title: '' -labels: Bug -assignees: '' - ---- - -**Describe the bug** - -**To Reproduce** - -**Screenshots** diff --git a/.github/ISSUE_TEMPLATE/enhancement.md b/.github/ISSUE_TEMPLATE/enhancement.md deleted file mode 100644 index c121801e24..0000000000 --- a/.github/ISSUE_TEMPLATE/enhancement.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -name: Enhancement -about: Describe enhancement. -title: 'Context : EnhancementName' -labels: Enhancement -assignees: '' - ---- - - diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index b80a526ea0..0000000000 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -name: Feature request -about: Suggest an idea for this project -title: '' -labels: FeatureRequest -assignees: '' - ---- - -**Is your feature request related to a problem? Please describe.** -A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] - -**Describe the solution you'd like** -A clear and concise description of what you want to happen. - -**Describe alternatives you've considered** -A clear and concise description of any alternative solutions or features you've considered. - -**Additional context** -Add any other context or screenshots about the feature request here. From 02107a7a93e604ab78e32bdf8c81d95e84844e34 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Sun, 11 Aug 2019 14:50:38 +0200 Subject: [PATCH 309/396] Remove all sys.path.inserts from Python examples. --- .../GrpcInterface/Python/rips/examples/AllCases.py | 4 ---- .../GrpcInterface/Python/rips/examples/AppInfo.py | 4 ---- .../Python/rips/examples/CaseGridGroup.py | 7 ++----- .../Python/rips/examples/CaseInfoStreamingExample.py | 3 --- .../Python/rips/examples/CommandExample.py | 2 -- .../Python/rips/examples/GridInformation.py | 4 ---- .../Python/rips/examples/InputPropTestAsync.py | 4 ---- .../Python/rips/examples/InputPropTestSync.py | 4 ---- .../Python/rips/examples/InstanceExample.py | 8 +++----- .../Python/rips/examples/SelectedCases.py | 4 ---- .../Python/rips/examples/SetFlowDiagnosticsResult.py | 12 ++++++------ .../Python/rips/examples/SetGridProperties.py | 3 --- .../Python/rips/examples/SoilAverageAsync.py | 3 --- .../Python/rips/examples/SoilAverageSync.py | 5 ++--- .../Python/rips/examples/SoilPorvAsync.py | 3 --- .../Python/rips/examples/SoilPorvSync.py | 3 --- 16 files changed, 13 insertions(+), 60 deletions(-) diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/AllCases.py b/ApplicationCode/GrpcInterface/Python/rips/examples/AllCases.py index acbe3745bd..1064eb8545 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/examples/AllCases.py +++ b/ApplicationCode/GrpcInterface/Python/rips/examples/AllCases.py @@ -1,7 +1,3 @@ -import sys -import os - -sys.path.insert(1, os.path.join(sys.path[0], '../../')) import rips resInsight = rips.Instance.find() diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/AppInfo.py b/ApplicationCode/GrpcInterface/Python/rips/examples/AppInfo.py index d8d71d340e..4a003cc324 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/examples/AppInfo.py +++ b/ApplicationCode/GrpcInterface/Python/rips/examples/AppInfo.py @@ -1,7 +1,3 @@ -import sys -import os - -sys.path.insert(1, os.path.join(sys.path[0], '../../')) import rips resInsight = rips.Instance.find() diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/CaseGridGroup.py b/ApplicationCode/GrpcInterface/Python/rips/examples/CaseGridGroup.py index fa834c8026..afe8470d17 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/examples/CaseGridGroup.py +++ b/ApplicationCode/GrpcInterface/Python/rips/examples/CaseGridGroup.py @@ -1,14 +1,11 @@ -import sys import os - -sys.path.insert(1, os.path.join(sys.path[0], '../../')) import rips resInsight = rips.Instance.find() casePaths = [] -casePaths.append("C:/Users/lindkvis/Projects/ResInsight/TestModels/Case_with_10_timesteps/Real0/BRUGGE_0000.EGRID") -casePaths.append("C:/Users/lindkvis/Projects/ResInsight/TestModels/Case_with_10_timesteps/Real10/BRUGGE_0010.EGRID") +casePaths.append("C:/Users/lindk/source/repos/ResInsight/TestModels/Case_with_10_timesteps/Real0/BRUGGE_0000.EGRID") +casePaths.append("C:/Users/lindk/source/repos/ResInsight/TestModels/Case_with_10_timesteps/Real10/BRUGGE_0010.EGRID") for casePath in casePaths: assert os.path.exists(casePath), "You need to set valid case paths for this script to work" diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/CaseInfoStreamingExample.py b/ApplicationCode/GrpcInterface/Python/rips/examples/CaseInfoStreamingExample.py index 409a75f9ac..b0457173ea 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/examples/CaseInfoStreamingExample.py +++ b/ApplicationCode/GrpcInterface/Python/rips/examples/CaseInfoStreamingExample.py @@ -1,6 +1,3 @@ -import sys -import os -sys.path.insert(1, os.path.join(sys.path[0], '../../')) import rips resInsight = rips.Instance.find() diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/CommandExample.py b/ApplicationCode/GrpcInterface/Python/rips/examples/CommandExample.py index 3fa9d48890..26f364eea3 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/examples/CommandExample.py +++ b/ApplicationCode/GrpcInterface/Python/rips/examples/CommandExample.py @@ -1,7 +1,5 @@ -import sys import os import tempfile -sys.path.insert(1, os.path.join(sys.path[0], '../../')) import rips # Load instance diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/GridInformation.py b/ApplicationCode/GrpcInterface/Python/rips/examples/GridInformation.py index 66e0bcbcd9..410a261efa 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/examples/GridInformation.py +++ b/ApplicationCode/GrpcInterface/Python/rips/examples/GridInformation.py @@ -1,7 +1,3 @@ -import sys -import os -sys.path.insert(1, os.path.join(sys.path[0], '../../')) - import rips resInsight = rips.Instance.find() diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/InputPropTestAsync.py b/ApplicationCode/GrpcInterface/Python/rips/examples/InputPropTestAsync.py index 335c97d306..afb56bc588 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/examples/InputPropTestAsync.py +++ b/ApplicationCode/GrpcInterface/Python/rips/examples/InputPropTestAsync.py @@ -1,7 +1,3 @@ -import sys -import os -sys.path.insert(1, os.path.join(sys.path[0], '../../')) - import rips import time diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/InputPropTestSync.py b/ApplicationCode/GrpcInterface/Python/rips/examples/InputPropTestSync.py index 5d7d862e03..c92327af28 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/examples/InputPropTestSync.py +++ b/ApplicationCode/GrpcInterface/Python/rips/examples/InputPropTestSync.py @@ -1,7 +1,3 @@ -import sys -import os -sys.path.insert(1, os.path.join(sys.path[0], '../../')) - import rips import time diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/InstanceExample.py b/ApplicationCode/GrpcInterface/Python/rips/examples/InstanceExample.py index 2b08f90d6c..fcc15a8679 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/examples/InstanceExample.py +++ b/ApplicationCode/GrpcInterface/Python/rips/examples/InstanceExample.py @@ -1,10 +1,8 @@ -import sys -import os - -sys.path.insert(1, os.path.join(sys.path[0], '../../')) import rips resInsight = rips.Instance.find() if resInsight is None: - print('ERROR: could not find ResInsight') \ No newline at end of file + print('ERROR: could not find ResInsight') +else: + print('Successfully connected to ResInsight') \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/SelectedCases.py b/ApplicationCode/GrpcInterface/Python/rips/examples/SelectedCases.py index de17ac08fb..38faffa089 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/examples/SelectedCases.py +++ b/ApplicationCode/GrpcInterface/Python/rips/examples/SelectedCases.py @@ -1,7 +1,3 @@ -import sys -import os -sys.path.insert(1, os.path.join(sys.path[0], '../../')) - import rips resInsight = rips.Instance.find() diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/SetFlowDiagnosticsResult.py b/ApplicationCode/GrpcInterface/Python/rips/examples/SetFlowDiagnosticsResult.py index 3e13e32dca..949dfb2358 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/examples/SetFlowDiagnosticsResult.py +++ b/ApplicationCode/GrpcInterface/Python/rips/examples/SetFlowDiagnosticsResult.py @@ -4,11 +4,11 @@ import rips resInsight = rips.Instance.find() view = resInsight.project.view(0) -view.applyFlowDiagnosticsCellResult(resultVariable='Fraction', - selectionMode='FLOW_TR_INJ_AND_PROD') +#view.applyFlowDiagnosticsCellResult(resultVariable='Fraction', +# selectionMode='FLOW_TR_INJ_AND_PROD') # Example of setting individual wells. Commented out because well names are case specific. -#view.applyFlowDiagnosticsCellResult(resultVariable='Fraction', -# selectionMode='FLOW_TR_BY_SELECTION', -# injectors = ['C-1H', 'C-2H', 'F-2H'], -# producers = ['B-1AH', 'B-3H', 'D-1H']) +view.applyFlowDiagnosticsCellResult(resultVariable='Fraction', + selectionMode='FLOW_TR_BY_SELECTION', + injectors = ['C-1H', 'C-2H', 'F-2H'], + producers = ['B-1AH', 'B-3H', 'D-1H']) diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/SetGridProperties.py b/ApplicationCode/GrpcInterface/Python/rips/examples/SetGridProperties.py index 23a51f5fa4..1cdec8eb51 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/examples/SetGridProperties.py +++ b/ApplicationCode/GrpcInterface/Python/rips/examples/SetGridProperties.py @@ -1,6 +1,3 @@ -import sys -import os -sys.path.insert(1, os.path.join(sys.path[0], '../../')) import rips resInsight = rips.Instance.find() diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/SoilAverageAsync.py b/ApplicationCode/GrpcInterface/Python/rips/examples/SoilAverageAsync.py index 6da3d6ee3b..126607dec3 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/examples/SoilAverageAsync.py +++ b/ApplicationCode/GrpcInterface/Python/rips/examples/SoilAverageAsync.py @@ -1,6 +1,3 @@ -import sys -import os -sys.path.insert(1, os.path.join(sys.path[0], '../../')) import rips import itertools import time diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/SoilAverageSync.py b/ApplicationCode/GrpcInterface/Python/rips/examples/SoilAverageSync.py index b644d7dc78..64da1939b4 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/examples/SoilAverageSync.py +++ b/ApplicationCode/GrpcInterface/Python/rips/examples/SoilAverageSync.py @@ -1,6 +1,3 @@ -import sys -import os -sys.path.insert(1, os.path.join(sys.path[0], '../../')) import rips import itertools import time @@ -14,8 +11,10 @@ grid = case.grid(index = 0) timeSteps = case.timeSteps() averages = [] +allResults = [] for i in range(0, len(timeSteps)): results = case.properties.activeCellProperty('DYNAMIC_NATIVE', 'SOIL', i) + allResults.append(results) mysum = sum(results) averages.append(mysum/len(results)) diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/SoilPorvAsync.py b/ApplicationCode/GrpcInterface/Python/rips/examples/SoilPorvAsync.py index e42b25a270..8620a25dae 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/examples/SoilPorvAsync.py +++ b/ApplicationCode/GrpcInterface/Python/rips/examples/SoilPorvAsync.py @@ -1,6 +1,3 @@ -import sys -import os -sys.path.insert(1, os.path.join(sys.path[0], '../../')) import rips def createResult(soilChunks, porvChunks): diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/SoilPorvSync.py b/ApplicationCode/GrpcInterface/Python/rips/examples/SoilPorvSync.py index 4500feaab1..f3f25313d7 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/examples/SoilPorvSync.py +++ b/ApplicationCode/GrpcInterface/Python/rips/examples/SoilPorvSync.py @@ -1,6 +1,3 @@ -import sys -import os -sys.path.insert(1, os.path.join(sys.path[0], '../../')) import rips resInsight = rips.Instance.find() From b5d9a47fdcf1241c96fc89817afbdd8be186b1bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Mon, 12 Aug 2019 08:34:08 +0200 Subject: [PATCH 310/396] #4556 Command Line Help: Improve help text Group options using newline Fix misleading --case description --- .../Application/Tools/RiaArgumentParser.cpp | 101 +++++++++--------- 1 file changed, 52 insertions(+), 49 deletions(-) diff --git a/ApplicationCode/Application/Tools/RiaArgumentParser.cpp b/ApplicationCode/Application/Tools/RiaArgumentParser.cpp index 6361f7cc3f..f4f7697a2b 100644 --- a/ApplicationCode/Application/Tools/RiaArgumentParser.cpp +++ b/ApplicationCode/Application/Tools/RiaArgumentParser.cpp @@ -55,61 +55,64 @@ bool RiaArgumentParser::parseArguments(cvf::ProgramOptions* progOpt) { CVF_ASSERT(progOpt); - progOpt->registerOption("grpcserver", "[]", "Run as a GRPC server. Default port is 50051", cvf::ProgramOptions::SINGLE_VALUE); - progOpt->registerOption("console", "", "Run as a console application without Graphics"); - progOpt->registerOption("last", "", "Open last used project."); - progOpt->registerOption("project", "", "Open project file .", cvf::ProgramOptions::SINGLE_VALUE); - progOpt->registerOption("case", - "", - "If case or grid filename, import simulation grid data. If summary file name, import summary data", - cvf::ProgramOptions::MULTI_VALUE); - progOpt->registerOption("startdir", "", "Set startup directory.", cvf::ProgramOptions::SINGLE_VALUE); - progOpt->registerOption("savesnapshots", - "all|views|plots", - "Save snapshot of all views or plots to project file location sub folder 'snapshots'. Option 'all' " - "will include both views and plots. Application closes after snapshots have been written.", - cvf::ProgramOptions::OPTIONAL_MULTI_VALUE); - progOpt->registerOption( - "size", " ", "Set size of the main application window.", cvf::ProgramOptions::MULTI_VALUE); - progOpt->registerOption( - "replaceCase", - "[] ", - "Replace grid in or first case with . Repeat parameter for multiple replace operations.", - cvf::ProgramOptions::MULTI_VALUE, - cvf::ProgramOptions::COMBINE_REPEATED); - progOpt->registerOption("replaceSourceCases", - "[] ", - "Replace source cases in or first grid case group with the grid files listed in the " - " file. Repeat parameter for multiple replace operations.", - cvf::ProgramOptions::MULTI_VALUE, - cvf::ProgramOptions::COMBINE_REPEATED); - progOpt->registerOption("replacePropertiesFolder", - "[] ", - "Replace the folder containing property files for an eclipse input case.", - cvf::ProgramOptions::MULTI_VALUE); - progOpt->registerOption("multiCaseSnapshots", - "", - "For each grid file listed in the file, replace the first case in the project and save " - "snapshot of all views.", - cvf::ProgramOptions::SINGLE_VALUE); - progOpt->registerOption("commandFile", "", "Execute the command file.", cvf::ProgramOptions::SINGLE_VALUE); - progOpt->registerOption( - "commandFileProject", - "", - "Project to use if performing case looping for command file. Used in conjunction with 'commandFileReplaceCases'.", - cvf::ProgramOptions::SINGLE_VALUE); - progOpt->registerOption("commandFileReplaceCases", - "[] ", - "Supply list of cases to replace in project, performing command file for each case.", - cvf::ProgramOptions::SINGLE_VALUE); progOpt->registerOption("help", "", "Displays help text and exits."); progOpt->registerOption("?", "", "Displays help text and exits."); - progOpt->registerOption("regressiontest", "", "System command", cvf::ProgramOptions::SINGLE_VALUE); + + progOpt->registerOption("project", "", "Open project file .", cvf::ProgramOptions::SINGLE_VALUE); + progOpt->registerOption("last", "", "Open last used project."); + progOpt->registerOption("case", + " [ ...]", + "Imports the Eclipse cases. is the filepath to the case without extension (.GRID/.EGRID)", + cvf::ProgramOptions::MULTI_VALUE); + progOpt->registerOption("size", " ", "Set size of the main application window.", cvf::ProgramOptions::MULTI_VALUE); + progOpt->registerOption("console", "", "Run as a console application without Graphics"); + progOpt->registerOption("grpcserver", "[]", "Run as a GRPC server. Default port is 50051", cvf::ProgramOptions::SINGLE_VALUE); + progOpt->registerOption("startdir", "", "Set startup directory.\n", cvf::ProgramOptions::SINGLE_VALUE); + + progOpt->registerOption("commandFile", "", "Execute the command file.", cvf::ProgramOptions::SINGLE_VALUE); + progOpt->registerOption("commandFileReplaceCases", + "[] ", + "Supply list of cases to replace in project, performing command file for each case.", + cvf::ProgramOptions::SINGLE_VALUE); + progOpt->registerOption("commandFileProject", + "", + "Project to use if performing case looping for command file. Used in conjunction with 'commandFileReplaceCases'.\n", + cvf::ProgramOptions::SINGLE_VALUE); + + progOpt->registerOption("savesnapshots", + "all|views|plots", + "Save snapshot of all views or plots to project file location sub folder 'snapshots'. Option 'all' " + "will include both views and plots. Application closes after snapshots have been written.", + cvf::ProgramOptions::OPTIONAL_MULTI_VALUE); + progOpt->registerOption("multiCaseSnapshots", + "", + "For each grid file listed in the file, replace the first case in the project and save " + "snapshots of all views.\n", + cvf::ProgramOptions::SINGLE_VALUE); + + progOpt->registerOption("replaceCase", + "[] ", + "Replace grid in or first case with . Repeat parameter for multiple replace operations.", + cvf::ProgramOptions::MULTI_VALUE, + cvf::ProgramOptions::COMBINE_REPEATED); + progOpt->registerOption("replaceSourceCases", + "[] ", + "Replace source cases in or first grid case group with the grid files listed in the " + " file. Repeat parameter for multiple replace operations.", + cvf::ProgramOptions::MULTI_VALUE, + cvf::ProgramOptions::COMBINE_REPEATED); + progOpt->registerOption("replacePropertiesFolder", + "[] ", + "Replace the folder containing property files for an eclipse input case.\n", + cvf::ProgramOptions::MULTI_VALUE); + + progOpt->registerOption("updateregressiontestbase", "", "System command", cvf::ProgramOptions::SINGLE_VALUE); + progOpt->registerOption("regressiontest", "", "System command", cvf::ProgramOptions::SINGLE_VALUE); #ifdef USE_UNIT_TESTS progOpt->registerOption("unittest", "", "System command"); #endif - progOpt->registerOption("ignoreArgs", "", "Ignore all arguments. Mostly for testing purposes"); + progOpt->registerOption("ignoreArgs", "", "System command. Ignore all arguments. Mostly for testing purposes"); progOpt->setOptionPrefix(cvf::ProgramOptions::DOUBLE_DASH); From b3c00c203823bed9b86c1dacc556224af192b512 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 12 Aug 2019 08:51:26 +0200 Subject: [PATCH 311/396] Mark several cmake options as advanced --- ApplicationCode/CMakeLists.txt | 3 +++ CMakeLists.txt | 3 +++ 2 files changed, 6 insertions(+) diff --git a/ApplicationCode/CMakeLists.txt b/ApplicationCode/CMakeLists.txt index 8a24b8225b..74d1ddec79 100644 --- a/ApplicationCode/CMakeLists.txt +++ b/ApplicationCode/CMakeLists.txt @@ -162,6 +162,7 @@ list( APPEND REFERENCED_CMAKE_FILES ) option (RESINSIGHT_INCLUDE_APPLICATION_UNIT_TESTS "Include ApplicationCode Unit Tests" OFF) +mark_as_advanced(FORCE RESINSIGHT_INCLUDE_APPLICATION_UNIT_TESTS) if (RESINSIGHT_INCLUDE_APPLICATION_UNIT_TESTS) add_definitions(-DUSE_UNIT_TESTS) @@ -685,6 +686,8 @@ if (RESINSIGHT_PRIVATE_INSTALL) # OpenSSL option(RESINSIGHT_BUNDLE_OPENSSL "Bundle the OpenSSL binary DLLs" OFF) + mark_as_advanced(FORCE RESINSIGHT_BUNDLE_OPENSSL) + if (RESINSIGHT_BUNDLE_OPENSSL) find_package(OpenSSL) if (OPENSSL_FOUND) diff --git a/CMakeLists.txt b/CMakeLists.txt index 387933f46f..727ede6cf5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -252,6 +252,7 @@ list(APPEND THIRD_PARTY_LIBRARIES # Qt ################################################################################ option(RESINSIGHT_BUILD_WITH_QT5 "Use Qt5" ON) +mark_as_advanced(FORCE RESINSIGHT_BUILD_WITH_QT5) if (RESINSIGHT_BUILD_WITH_QT5) find_package(Qt5 COMPONENTS REQUIRED Core Gui OpenGL Network Script ScriptTools Widgets) @@ -413,6 +414,8 @@ set_property(TARGET ) option (RESINSIGHT_INCLUDE_APPFWK_TESTS "Enable AppFwk Tests" OFF) +mark_as_advanced(FORCE RESINSIGHT_INCLUDE_APPFWK_TESTS) + if (RESINSIGHT_INCLUDE_APPFWK_TESTS) # Unit Tests add_subdirectory(Fwk/AppFwk/cafProjectDataModel/cafProjectDataModel_UnitTests) From e70cf3c73615635db72da99e625486a0c9213db3 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 12 Aug 2019 08:51:56 +0200 Subject: [PATCH 312/396] cmake : Rename to RESINSIGHT_GRPC_PYTHON_EXECUTABLE --- ApplicationCode/CMakeLists.txt | 13 ++++---- .../GrpcInterface/CMakeLists.cmake | 32 +++++++++---------- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/ApplicationCode/CMakeLists.txt b/ApplicationCode/CMakeLists.txt index 74d1ddec79..0eedabdb4b 100644 --- a/ApplicationCode/CMakeLists.txt +++ b/ApplicationCode/CMakeLists.txt @@ -549,8 +549,9 @@ endforeach() # Copy all grpc libraries and python files if (RESINSIGHT_ENABLE_GRPC) - if (PYTHON_EXECUTABLE) - if (EXISTS ${PYTHON_EXECUTABLE}) + set(RESINSIGHT_GRPC_PYTHON_EXECUTABLE "" CACHE PATH "gRPC : Path to Python 3 executable, required to build the Python client library") + if (RESINSIGHT_GRPC_PYTHON_EXECUTABLE) + if (EXISTS ${RESINSIGHT_GRPC_PYTHON_EXECUTABLE}) add_custom_target(GeneratedPythonSources DEPENDS ${GRPC_GENERATED_PYTHON_SOURCES}) add_dependencies(ResInsight GeneratedPythonSources) @@ -562,11 +563,11 @@ if (RESINSIGHT_ENABLE_GRPC) endif(EXISTS "${GRPC_PYTHON_SOURCE_PATH}/${PYTHON_SCRIPT}") endforeach(PYTHON_SCRIPT ${GRPC_PYTHON_SOURCES}) else() - message(STATUS "Error installing python code: PYTHON_EXECUTABLE set but ${PYTHON_EXECUTABLE} not found") - endif(EXISTS ${PYTHON_EXECUTABLE}) + message(STATUS "Error installing python code: RESINSIGHT_GRPC_PYTHON_EXECUTABLE set but ${RESINSIGHT_GRPC_PYTHON_EXECUTABLE} not found") + endif(EXISTS ${RESINSIGHT_GRPC_PYTHON_EXECUTABLE}) else() - message(STATUS "PYTHON_EXECUTABLE not specified. Will not install GRPC Python code.") - endif(PYTHON_EXECUTABLE) + message(STATUS "RESINSIGHT_GRPC_PYTHON_EXECUTABLE not specified. Will not install GRPC Python code.") + endif(RESINSIGHT_GRPC_PYTHON_EXECUTABLE) endif(RESINSIGHT_ENABLE_GRPC) ############################################################################# diff --git a/ApplicationCode/GrpcInterface/CMakeLists.cmake b/ApplicationCode/GrpcInterface/CMakeLists.cmake index 748d126b31..f71c526681 100644 --- a/ApplicationCode/GrpcInterface/CMakeLists.cmake +++ b/ApplicationCode/GrpcInterface/CMakeLists.cmake @@ -71,9 +71,9 @@ else() endif() # Cannot use the nice new FindPackage modules for python since that is CMake 3.12+ -if(PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) - message(STATUS "Using Python ${PYTHON_EXECUTABLE}") -endif(PYTHON_EXECUTABLE AND EXISTS ${PYTHON_EXECUTABLE}) +if(RESINSIGHT_GRPC_PYTHON_EXECUTABLE AND EXISTS ${RESINSIGHT_GRPC_PYTHON_EXECUTABLE}) + message(STATUS "Using Python ${RESINSIGHT_GRPC_PYTHON_EXECUTABLE}") +endif(RESINSIGHT_GRPC_PYTHON_EXECUTABLE AND EXISTS ${RESINSIGHT_GRPC_PYTHON_EXECUTABLE}) # Proto files set(PROTO_FILES @@ -112,14 +112,14 @@ foreach(proto_file ${PROTO_FILES}) DEPENDS "${rips_proto}" ) - if (PYTHON_EXECUTABLE) - if (EXISTS ${PYTHON_EXECUTABLE}) + if (RESINSIGHT_GRPC_PYTHON_EXECUTABLE) + if (EXISTS ${RESINSIGHT_GRPC_PYTHON_EXECUTABLE}) set(rips_proto_python "rips/generated/${proto_file}_pb2.py") set(rips_grpc_python "rips/generated/${proto_file}_pb2_grpc.py") add_custom_command( OUTPUT "${GRPC_PYTHON_SOURCE_PATH}/${rips_proto_python}" "${GRPC_PYTHON_SOURCE_PATH}/${rips_grpc_python}" - COMMAND ${PYTHON_EXECUTABLE} + COMMAND ${RESINSIGHT_GRPC_PYTHON_EXECUTABLE} ARGS -m grpc_tools.protoc -I "${rips_proto_path}" --python_out "${GRPC_PYTHON_SOURCE_PATH}/rips/generated" @@ -134,11 +134,11 @@ foreach(proto_file ${PROTO_FILES}) ${rips_grpc_python} ) else() - message(STATUS "Error generating Python for ${rips_proto}: PYTHON_EXECUTABLE set but ${PYTHON_EXECUTABLE} not found") - endif(EXISTS ${PYTHON_EXECUTABLE}) + message(STATUS "Error generating Python for ${rips_proto}: RESINSIGHT_GRPC_PYTHON_EXECUTABLE set but ${RESINSIGHT_GRPC_PYTHON_EXECUTABLE} not found") + endif(EXISTS ${RESINSIGHT_GRPC_PYTHON_EXECUTABLE}) else() - message(STATUS "PYTHON_EXECUTABLE not specified. Will not generate GRPC Python code.") - endif(PYTHON_EXECUTABLE) + message(STATUS "RESINSIGHT_GRPC_PYTHON_EXECUTABLE not specified. Will not generate GRPC Python code.") + endif(RESINSIGHT_GRPC_PYTHON_EXECUTABLE) list( APPEND GRPC_HEADER_FILES ${rips_proto_hdrs} @@ -152,8 +152,8 @@ foreach(proto_file ${PROTO_FILES}) endforeach(proto_file) -if (PYTHON_EXECUTABLE) - if (EXISTS ${PYTHON_EXECUTABLE}) +if (RESINSIGHT_GRPC_PYTHON_EXECUTABLE) + if (EXISTS ${RESINSIGHT_GRPC_PYTHON_EXECUTABLE}) list(APPEND GRPC_PYTHON_SOURCES ${GRPC_PYTHON_GENERATED_SOURCES} "rips/generated/RiaVersionInfo.py" @@ -205,11 +205,11 @@ if (PYTHON_EXECUTABLE) source_group(TREE ${GRPC_PYTHON_SOURCE_PATH} FILES ${GRPC_PYTHON_SOURCES_FULL_PATH} PREFIX "GrpcInterface\\Python") endif(MSVC) else() - message(STATUS "Error copying GRPC Python Code to build folder: PYTHON_EXECUTABLE set but ${PYTHON_EXECUTABLE} not found") - endif(EXISTS ${PYTHON_EXECUTABLE}) + message(STATUS "Error copying GRPC Python Code to build folder: RESINSIGHT_GRPC_PYTHON_EXECUTABLE set but ${RESINSIGHT_GRPC_PYTHON_EXECUTABLE} not found") + endif(EXISTS ${RESINSIGHT_GRPC_PYTHON_EXECUTABLE}) else() - message(STATUS "PYTHON_EXECUTABLE not specified. Will not copy grpc Python code to build folder") -endif(PYTHON_EXECUTABLE) + message(STATUS "RESINSIGHT_GRPC_PYTHON_EXECUTABLE not specified. Will not copy grpc Python code to build folder") +endif(RESINSIGHT_GRPC_PYTHON_EXECUTABLE) list ( APPEND GRPC_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES}) list ( APPEND GRPC_CPP_SOURCES ${SOURCE_GROUP_SOURCE_FILES}) From 3f7a5ff29c73b967236011948d9333705e5d389d Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 12 Aug 2019 09:08:27 +0200 Subject: [PATCH 313/396] cmake : Rename to RESINSIGHT_GRPC_INSTALL_PREFIX --- ApplicationCode/GrpcInterface/CMakeLists.cmake | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/ApplicationCode/GrpcInterface/CMakeLists.cmake b/ApplicationCode/GrpcInterface/CMakeLists.cmake index f71c526681..a888f57f0d 100644 --- a/ApplicationCode/GrpcInterface/CMakeLists.cmake +++ b/ApplicationCode/GrpcInterface/CMakeLists.cmake @@ -59,14 +59,15 @@ if (MSVC) ) else() - if (NOT DEFINED GRPC_INSTALL_PREFIX OR NOT EXISTS ${GRPC_INSTALL_PREFIX}) - message(FATAL_ERROR "You need a valid GRPC_INSTALL_PREFIX set to build with gRPC") + set(RESINSIGHT_GRPC_INSTALL_PREFIX "" CACHE PATH "gRPC : Install prefix for gRPC") + if (NOT DEFINED RESINSIGHT_GRPC_INSTALL_PREFIX OR NOT EXISTS ${RESINSIGHT_GRPC_INSTALL_PREFIX}) + message(FATAL_ERROR "You need a valid RESINSIGHT_GRPC_INSTALL_PREFIX set to build with gRPC") endif() - set(ENV{PKG_CONFIG_PATH} "${GRPC_INSTALL_PREFIX}/lib/pkgconfig") + set(ENV{PKG_CONFIG_PATH} "${RESINSIGHT_GRPC_INSTALL_PREFIX}/lib/pkgconfig") find_package(PkgConfig REQUIRED) pkg_check_modules(GRPC REQUIRED grpc++_unsecure>=1.20 grpc_unsecure gpr protobuf) - set(_PROTOBUF_PROTOC "${GRPC_INSTALL_PREFIX}/bin/protoc") - set(_GRPC_CPP_PLUGIN_EXECUTABLE "${GRPC_INSTALL_PREFIX}/bin/grpc_cpp_plugin") + set(_PROTOBUF_PROTOC "${RESINSIGHT_GRPC_INSTALL_PREFIX}/bin/protoc") + set(_GRPC_CPP_PLUGIN_EXECUTABLE "${RESINSIGHT_GRPC_INSTALL_PREFIX}/bin/grpc_cpp_plugin") include_directories(AFTER ${GRPC_INCLUDE_DIRS}) endif() From b0605635a0a5d948dc689bf3a4679f1e17e9938f Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 12 Aug 2019 09:16:31 +0200 Subject: [PATCH 314/396] Update build descriptions --- GRPC_install_instructions.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/GRPC_install_instructions.txt b/GRPC_install_instructions.txt index b0c7c33072..7a49039f90 100644 --- a/GRPC_install_instructions.txt +++ b/GRPC_install_instructions.txt @@ -15,11 +15,11 @@ git clone https://github.com/microsoft/vcpkg.git * Install Python 3 * Execute the following using Python3 python -m pip install grpcio-tools -* Make sure the python executable is found by setting -DPYTHON_EXECUTABLE=LOCATION_OF_PYTHON.EXE +* Make sure the python executable is found by setting -DRESINSIGHT_GRPC_PYTHON_EXECUTABLE=LOCATION_OF_PYTHON.EXE 5. Run cmake with the following statements: -DRESINSIGHT_ENABLE_GRPC=true --DPYTHON_EXECUTABLE=LOCATION_OF_PYTHON.EXE +-DRESINSIGHT_GRPC_PYTHON_EXECUTABLE=LOCATION_OF_PYTHON.EXE -DCMAKE_TOOLCHAIN_FILE=LOCATION_OF_VCPKG/scripts/buildsystems/vcpkg.cmake NOTE: When using the CMake gui, you need to select "Specify toolchain for cross-compiling" and enter the "LOCATION_OF_VCPKG/scripts/buildsystems/vcpkg.cmake" there. @@ -90,8 +90,8 @@ python -m pip install --user grpcio-tools ################################################################################# # 6. Building ResInsight with GRPC enabled: # Run cmake making sure of the following: -# * GRPC_INSTALL_PREFIX is set to the Grpc install folder, -# * PYTHON_EXECUTABLE set to a good python 3 # * RESINSIGHT_ENABLE_GRPC = true +# * RESINSIGHT_GRPC_INSTALL_PREFIX is set to the Grpc install folder +# * RESINSIGHT_GRPC_PYTHON_EXECUTABLE set to a good python 3 ################################ -See regular build instructions for the rest \ No newline at end of file +See regular build instructions for the rest From d2b6cb589c542b4be6f9e0d28044a45772a82326 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 13 Aug 2019 08:20:50 +0200 Subject: [PATCH 315/396] #4563 Summary : Fix import of summary file specified by casename.SMSPEC --- ApplicationCode/Commands/RicImportGeneralDataFeature.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ApplicationCode/Commands/RicImportGeneralDataFeature.cpp b/ApplicationCode/Commands/RicImportGeneralDataFeature.cpp index a85267cfcf..2620eece67 100644 --- a/ApplicationCode/Commands/RicImportGeneralDataFeature.cpp +++ b/ApplicationCode/Commands/RicImportGeneralDataFeature.cpp @@ -110,7 +110,8 @@ QStringList RicImportGeneralDataFeature::fileNamesFromCaseNames(const QStringLis { if (caseName.lastIndexOf(".") != -1) { - fileNames.push_back(caseName); + QFileInfo fi(caseName); + fileNames.push_back(fi.absoluteFilePath()); } else { From 94e71b900cc0c779c795c95219c9950fbaa0561d Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 13 Aug 2019 10:12:32 +0200 Subject: [PATCH 316/396] Improve help text --- ApplicationCode/Application/Tools/RiaArgumentParser.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ApplicationCode/Application/Tools/RiaArgumentParser.cpp b/ApplicationCode/Application/Tools/RiaArgumentParser.cpp index f4f7697a2b..1287cdad13 100644 --- a/ApplicationCode/Application/Tools/RiaArgumentParser.cpp +++ b/ApplicationCode/Application/Tools/RiaArgumentParser.cpp @@ -61,8 +61,11 @@ bool RiaArgumentParser::parseArguments(cvf::ProgramOptions* progOpt) progOpt->registerOption("project", "", "Open project file .", cvf::ProgramOptions::SINGLE_VALUE); progOpt->registerOption("last", "", "Open last used project."); progOpt->registerOption("case", - " [ ...]", - "Imports the Eclipse cases. is the filepath to the case without extension (.GRID/.EGRID)", + " [ ...]", + "Imports the Eclipse cases specified by case name with or without extension." + "If , import the corresponding grid file and summary file" + "If has extension .GRRID/.EGRID, import the grid file and corresponding summary file" + "If has extension .SMSPEC, import the summary file (does not open the corresponding grid file)", cvf::ProgramOptions::MULTI_VALUE); progOpt->registerOption("size", " ", "Set size of the main application window.", cvf::ProgramOptions::MULTI_VALUE); progOpt->registerOption("console", "", "Run as a console application without Graphics"); From 7b3155ab33ecb3c142deb644b40cc2d0a327261e Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 13 Aug 2019 10:16:31 +0200 Subject: [PATCH 317/396] Help text editor : Set text widget as read only --- ApplicationCode/Application/RiaGuiApplication.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/ApplicationCode/Application/RiaGuiApplication.cpp b/ApplicationCode/Application/RiaGuiApplication.cpp index 6725c0bfa7..9fbfad3d6c 100644 --- a/ApplicationCode/Application/RiaGuiApplication.cpp +++ b/ApplicationCode/Application/RiaGuiApplication.cpp @@ -1241,6 +1241,7 @@ void RiaGuiApplication::showFormattedTextInMessageBoxOrConsole(const QString& te formattedText = QString("
%1
").arg(formattedText); textEdit->setText(formattedText); + textEdit->setReadOnly(true); // Resize dialog to fit text etc. textEdit->document()->adjustSize(); From 10e318033274add00613edb730bf0d065fe4e1c5 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 13 Aug 2019 12:58:04 +0200 Subject: [PATCH 318/396] #4565 Highlight Curves : Clicking on curve causes access violation Create a copy of the item list before the loop to avoid invalidated iterators when iterating the list plotCurve->setZ() causes the ordering of items in the list to change --- ApplicationCode/UserInterface/RiuQwtPlot.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/ApplicationCode/UserInterface/RiuQwtPlot.cpp b/ApplicationCode/UserInterface/RiuQwtPlot.cpp index c8ccef6f6c..bebfbeeeae 100644 --- a/ApplicationCode/UserInterface/RiuQwtPlot.cpp +++ b/ApplicationCode/UserInterface/RiuQwtPlot.cpp @@ -244,7 +244,10 @@ void RiuQwtPlot::selectClosestCurve(const QPoint& pos) //-------------------------------------------------------------------------------------------------- void RiuQwtPlot::highlightCurve(const QwtPlotCurve* closestCurve) { - for (QwtPlotItem* plotItem : this->itemList()) + // NB! Create a copy of the item list before the loop to avoid invalidated iterators when iterating the list + // plotCurve->setZ() causes the ordering of items in the list to change + auto plotItemList = this->itemList(); + for (QwtPlotItem* plotItem : plotItemList) { QwtPlotCurve* plotCurve = dynamic_cast(plotItem); if (plotCurve) @@ -293,7 +296,10 @@ void RiuQwtPlot::highlightCurve(const QwtPlotCurve* closestCurve) //-------------------------------------------------------------------------------------------------- void RiuQwtPlot::resetCurveHighlighting() { - for (QwtPlotItem* plotItem : this->itemList()) + // NB! Create a copy of the item list before the loop to avoid invalidated iterators when iterating the list + // plotCurve->setZ() causes the ordering of items in the list to change + auto plotItemList = this->itemList(); + for (QwtPlotItem* plotItem : plotItemList) { QwtPlotCurve* plotCurve = dynamic_cast(plotItem); if (plotCurve && m_originalCurveColors.count(plotCurve)) From 499798abc5d363576885b3bfaaa0d38d3e972dce Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Tue, 13 Aug 2019 08:23:03 +0200 Subject: [PATCH 319/396] gRPC: Improve naming of streaming callbacks --- .../GrpcInterface/RiaGrpcCallbacks.h | 8 ++--- .../GrpcInterface/RiaGrpcCallbacks.inl | 32 +++++++++---------- .../GrpcInterface/RiaGrpcCaseService.cpp | 2 +- .../RiaGrpcPropertiesService.cpp | 8 ++--- 4 files changed, 25 insertions(+), 25 deletions(-) diff --git a/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.h b/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.h index 8367002f60..b009546053 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.h +++ b/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.h @@ -139,7 +139,7 @@ private: // //================================================================================================== template -class RiaGrpcServerStreamCallback : public RiaGrpcServiceCallback +class RiaGrpcServerToClientStreamCallback : public RiaGrpcServiceCallback { public: typedef ServerAsyncWriter ResponseWriterT; @@ -148,7 +148,7 @@ public: void(ServiceT&, ServerContext*, RequestT*, ResponseWriterT*, CompletionQueue*, ServerCompletionQueue*, void*)> MethodRequestT; - RiaGrpcServerStreamCallback(ServiceT* service, MethodImplT methodImpl, MethodRequestT methodRequest, StateHandlerT* stateHandler); + RiaGrpcServerToClientStreamCallback(ServiceT* service, MethodImplT methodImpl, MethodRequestT methodRequest, StateHandlerT* stateHandler); RiaGrpcCallbackInterface* createNewFromThis() const override; void createRequestHandler(ServerCompletionQueue* completionQueue) override; @@ -179,7 +179,7 @@ private: // //================================================================================================== template -class RiaGrpcClientStreamCallback : public RiaGrpcServiceCallback +class RiaGrpcClientToServerStreamCallback : public RiaGrpcServiceCallback { public: typedef ServerAsyncReader RequestReaderT; @@ -188,7 +188,7 @@ public: void(ServiceT&, ServerContext*, RequestReaderT*, CompletionQueue*, ServerCompletionQueue*, void*)> MethodRequestT; - RiaGrpcClientStreamCallback(ServiceT* service, MethodImplT methodImpl, MethodRequestT methodRequest, StateHandlerT* stateHandler); + RiaGrpcClientToServerStreamCallback(ServiceT* service, MethodImplT methodImpl, MethodRequestT methodRequest, StateHandlerT* stateHandler); RiaGrpcCallbackInterface* createNewFromThis() const override; void createRequestHandler(ServerCompletionQueue* completionQueue) override; diff --git a/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.inl b/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.inl index 90f9a11a78..f30e0113e5 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.inl +++ b/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.inl @@ -150,7 +150,7 @@ QString RiaGrpcUnaryCallback::methodType() const /// //-------------------------------------------------------------------------------------------------- template -RiaGrpcServerStreamCallback::RiaGrpcServerStreamCallback(ServiceT* service, +RiaGrpcServerToClientStreamCallback::RiaGrpcServerToClientStreamCallback(ServiceT* service, MethodImplT methodImpl, MethodRequestT methodRequest, StateHandlerT* stateHandler) @@ -166,9 +166,9 @@ RiaGrpcServerStreamCallback::RiaGrpcS /// //-------------------------------------------------------------------------------------------------- template -RiaGrpcCallbackInterface* RiaGrpcServerStreamCallback::createNewFromThis() const +RiaGrpcCallbackInterface* RiaGrpcServerToClientStreamCallback::createNewFromThis() const { - return new RiaGrpcServerStreamCallback( + return new RiaGrpcServerToClientStreamCallback( this->m_service, m_methodImpl, m_methodRequest, new StateHandlerT); } @@ -176,7 +176,7 @@ RiaGrpcCallbackInterface* RiaGrpcServerStreamCallback -void RiaGrpcServerStreamCallback::createRequestHandler( +void RiaGrpcServerToClientStreamCallback::createRequestHandler( ServerCompletionQueue* completionQueue) { // The Request-method is where the service gets registered to respond to a given request. @@ -190,7 +190,7 @@ void RiaGrpcServerStreamCallback::cre /// Perform initialisation tasks at the time of receiving a complete request //-------------------------------------------------------------------------------------------------- template -void RiaGrpcServerStreamCallback::onInitRequestCompleted() +void RiaGrpcServerToClientStreamCallback::onInitRequestCompleted() { // Initialise streaming state handler this->m_status = m_stateHandler->init(&this->m_request); @@ -213,7 +213,7 @@ void RiaGrpcServerStreamCallback::onI /// Process a streaming request and send one package //-------------------------------------------------------------------------------------------------- template -void RiaGrpcServerStreamCallback::onProcessRequest() +void RiaGrpcServerToClientStreamCallback::onProcessRequest() { this->m_reply = ReplyT(); // Make sure it is reset @@ -243,7 +243,7 @@ void RiaGrpcServerStreamCallback::onP /// //-------------------------------------------------------------------------------------------------- template -QString RiaGrpcServerStreamCallback::methodType() const +QString RiaGrpcServerToClientStreamCallback::methodType() const { return "StreamingMethod"; } @@ -253,7 +253,7 @@ QString RiaGrpcServerStreamCallback:: /// //-------------------------------------------------------------------------------------------------- template -RiaGrpcClientStreamCallback::RiaGrpcClientStreamCallback(ServiceT* service, +RiaGrpcClientToServerStreamCallback::RiaGrpcClientToServerStreamCallback(ServiceT* service, MethodImplT methodImpl, MethodRequestT methodRequest, StateHandlerT* stateHandler) @@ -269,9 +269,9 @@ RiaGrpcClientStreamCallback::RiaGrpcC /// //-------------------------------------------------------------------------------------------------- template -RiaGrpcCallbackInterface* RiaGrpcClientStreamCallback::createNewFromThis() const +RiaGrpcCallbackInterface* RiaGrpcClientToServerStreamCallback::createNewFromThis() const { - return new RiaGrpcClientStreamCallback( + return new RiaGrpcClientToServerStreamCallback( this->m_service, m_methodImpl, m_methodRequest, new StateHandlerT(true)); } @@ -279,7 +279,7 @@ RiaGrpcCallbackInterface* RiaGrpcClientStreamCallback -void RiaGrpcClientStreamCallback::createRequestHandler( +void RiaGrpcClientToServerStreamCallback::createRequestHandler( ServerCompletionQueue* completionQueue) { // The Request-method is where the service gets registered to respond to a given request. @@ -293,7 +293,7 @@ void RiaGrpcClientStreamCallback::cre /// //-------------------------------------------------------------------------------------------------- template -void RiaGrpcClientStreamCallback::onInitRequestStarted() +void RiaGrpcClientToServerStreamCallback::onInitRequestStarted() { this->setNextCallState(RiaGrpcCallbackInterface::INIT_REQUEST_COMPLETED); // The read call will start reading the request data and push this callback back onto the command queue @@ -305,7 +305,7 @@ void RiaGrpcClientStreamCallback::onI /// //-------------------------------------------------------------------------------------------------- template -void RiaGrpcClientStreamCallback::onInitRequestCompleted() +void RiaGrpcClientToServerStreamCallback::onInitRequestCompleted() { this->setNextCallState(RiaGrpcCallbackInterface::PROCESS_REQUEST); // Fully received the stream package so can now init @@ -327,7 +327,7 @@ void RiaGrpcClientStreamCallback::onI /// //-------------------------------------------------------------------------------------------------- template -void RiaGrpcClientStreamCallback::onProcessRequest() +void RiaGrpcClientToServerStreamCallback::onProcessRequest() { this->m_reply = ReplyT(); // Make sure it is reset @@ -356,7 +356,7 @@ void RiaGrpcClientStreamCallback::onP /// //-------------------------------------------------------------------------------------------------- template -void RiaGrpcClientStreamCallback::onFinishRequest() +void RiaGrpcClientToServerStreamCallback::onFinishRequest() { m_stateHandler->finish(); } @@ -365,7 +365,7 @@ void RiaGrpcClientStreamCallback::onF /// //-------------------------------------------------------------------------------------------------- template -QString RiaGrpcClientStreamCallback::methodType() const +QString RiaGrpcClientToServerStreamCallback::methodType() const { return "ClientStreamingMethod"; } diff --git a/ApplicationCode/GrpcInterface/RiaGrpcCaseService.cpp b/ApplicationCode/GrpcInterface/RiaGrpcCaseService.cpp index db238300e5..1740eccecd 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcCaseService.cpp +++ b/ApplicationCode/GrpcInterface/RiaGrpcCaseService.cpp @@ -373,7 +373,7 @@ std::vector RiaGrpcCaseService::createCallbacks() new RiaGrpcUnaryCallback(this, &Self::GetDaysSinceStart, &Self::RequestGetDaysSinceStart), new RiaGrpcUnaryCallback(this, &Self::GetCaseInfo, &Self::RequestGetCaseInfo), new RiaGrpcUnaryCallback(this, &Self::GetPdmObject, &Self::RequestGetPdmObject), - new RiaGrpcServerStreamCallback( + new RiaGrpcServerToClientStreamCallback( this, &Self::GetCellInfoForActiveCells, &Self::RequestGetCellInfoForActiveCells, new RiaActiveCellInfoStateHandler)}; } diff --git a/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp b/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp index 18d3767f08..0fb2264de0 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp +++ b/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp @@ -356,16 +356,16 @@ std::vector RiaGrpcPropertiesService::createCallbacks callbacks = { new RiaGrpcUnaryCallback( this, &Self::GetAvailableProperties, &Self::RequestGetAvailableProperties), - new RiaGrpcClientStreamCallback( + new RiaGrpcClientToServerStreamCallback( this, &Self::SetActiveCellProperty, &Self::RequestSetActiveCellProperty, new RiaActiveCellResultsStateHandler(true)), - new RiaGrpcClientStreamCallback( + new RiaGrpcClientToServerStreamCallback( this, &Self::SetGridProperty, &Self::RequestSetGridProperty, new RiaGridCellResultsStateHandler(true))}; for (int i = 0; i < NUM_CONCURRENT_SERVER_STREAMS; ++i) { - callbacks.push_back(new RiaGrpcServerStreamCallback( + callbacks.push_back(new RiaGrpcServerToClientStreamCallback( this, &Self::GetActiveCellProperty, &Self::RequestGetActiveCellProperty, new RiaActiveCellResultsStateHandler)); - callbacks.push_back(new RiaGrpcServerStreamCallback( + callbacks.push_back(new RiaGrpcServerToClientStreamCallback( this, &Self::GetGridProperty, &Self::RequestGetGridProperty, new RiaGridCellResultsStateHandler)); } return callbacks; From f3d8e3dbdc304d32b942dd3802f23664dd8389b0 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Tue, 13 Aug 2019 13:15:58 +0200 Subject: [PATCH 320/396] #4566 #4572 Python: improve behaviour when sending more data than expected in property streams --- .../GrpcInterface/CMakeLists.cmake | 2 +- .../GrpcInterface/GrpcProtos/App.proto | 2 +- .../GrpcInterface/GrpcProtos/Commands.proto | 2 +- .../GrpcProtos/Definitions.proto | 12 ++ .../GrpcInterface/GrpcProtos/Empty.proto | 7 -- .../GrpcInterface/GrpcProtos/PdmObject.proto | 2 +- .../GrpcInterface/GrpcProtos/Project.proto | 2 +- .../GrpcInterface/GrpcProtos/Properties.proto | 6 +- .../GrpcInterface/Python/rips/App.py | 2 +- .../GrpcInterface/Python/rips/Commands.py | 2 +- .../GrpcInterface/Python/rips/PdmObject.py | 2 +- .../GrpcInterface/Python/rips/Project.py | 2 +- .../GrpcInterface/Python/rips/Properties.py | 19 ++- .../GrpcInterface/RiaGrpcCallbacks.inl | 18 +-- .../RiaGrpcPropertiesService.cpp | 109 +++++++++++------- .../GrpcInterface/RiaGrpcPropertiesService.h | 20 ++-- 16 files changed, 127 insertions(+), 82 deletions(-) create mode 100644 ApplicationCode/GrpcInterface/GrpcProtos/Definitions.proto delete mode 100644 ApplicationCode/GrpcInterface/GrpcProtos/Empty.proto diff --git a/ApplicationCode/GrpcInterface/CMakeLists.cmake b/ApplicationCode/GrpcInterface/CMakeLists.cmake index a888f57f0d..b911d660b6 100644 --- a/ApplicationCode/GrpcInterface/CMakeLists.cmake +++ b/ApplicationCode/GrpcInterface/CMakeLists.cmake @@ -78,7 +78,7 @@ endif(RESINSIGHT_GRPC_PYTHON_EXECUTABLE AND EXISTS ${RESINSIGHT_GRPC_PYTHON_EXEC # Proto files set(PROTO_FILES - "Empty" + "Definitions" "PdmObject" "Case" "Project" diff --git a/ApplicationCode/GrpcInterface/GrpcProtos/App.proto b/ApplicationCode/GrpcInterface/GrpcProtos/App.proto index 6ab1ce3b68..2778ec5550 100644 --- a/ApplicationCode/GrpcInterface/GrpcProtos/App.proto +++ b/ApplicationCode/GrpcInterface/GrpcProtos/App.proto @@ -2,7 +2,7 @@ syntax = "proto3"; package rips; -import "Empty.proto"; +import "Definitions.proto"; service App { rpc GetVersion(Empty) returns (Version) {} diff --git a/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto b/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto index eaf7335da6..d5b531101d 100644 --- a/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto +++ b/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto @@ -1,7 +1,7 @@ syntax = "proto3"; import "Case.proto"; -import "Empty.proto"; +import "Definitions.proto"; package rips; diff --git a/ApplicationCode/GrpcInterface/GrpcProtos/Definitions.proto b/ApplicationCode/GrpcInterface/GrpcProtos/Definitions.proto new file mode 100644 index 0000000000..1f5df27d0a --- /dev/null +++ b/ApplicationCode/GrpcInterface/GrpcProtos/Definitions.proto @@ -0,0 +1,12 @@ +syntax = "proto3"; + +package rips; + +message Empty +{ +} + +message ClientToServerStreamReply +{ + int64 values_accepted = 1; +} \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/GrpcProtos/Empty.proto b/ApplicationCode/GrpcInterface/GrpcProtos/Empty.proto deleted file mode 100644 index 7fd46ac602..0000000000 --- a/ApplicationCode/GrpcInterface/GrpcProtos/Empty.proto +++ /dev/null @@ -1,7 +0,0 @@ -syntax = "proto3"; - -package rips; - -message Empty -{ -} diff --git a/ApplicationCode/GrpcInterface/GrpcProtos/PdmObject.proto b/ApplicationCode/GrpcInterface/GrpcProtos/PdmObject.proto index 6d9a8ad709..a89f640e98 100644 --- a/ApplicationCode/GrpcInterface/GrpcProtos/PdmObject.proto +++ b/ApplicationCode/GrpcInterface/GrpcProtos/PdmObject.proto @@ -1,6 +1,6 @@ syntax = "proto3"; -import "Empty.proto"; +import "Definitions.proto"; package rips; diff --git a/ApplicationCode/GrpcInterface/GrpcProtos/Project.proto b/ApplicationCode/GrpcInterface/GrpcProtos/Project.proto index 01b4f64a53..11dae96ef2 100644 --- a/ApplicationCode/GrpcInterface/GrpcProtos/Project.proto +++ b/ApplicationCode/GrpcInterface/GrpcProtos/Project.proto @@ -1,6 +1,6 @@ syntax = "proto3"; -import "Empty.proto"; +import "Definitions.proto"; import "Case.proto"; import "PdmObject.proto"; diff --git a/ApplicationCode/GrpcInterface/GrpcProtos/Properties.proto b/ApplicationCode/GrpcInterface/GrpcProtos/Properties.proto index 3484e32f83..dcec187961 100644 --- a/ApplicationCode/GrpcInterface/GrpcProtos/Properties.proto +++ b/ApplicationCode/GrpcInterface/GrpcProtos/Properties.proto @@ -1,6 +1,6 @@ syntax = "proto3"; -import "Empty.proto"; +import "Definitions.proto"; import "Case.proto"; package rips; @@ -10,8 +10,8 @@ service Properties rpc GetAvailableProperties(AvailablePropertiesRequest) returns (AvailableProperties) {} rpc GetActiveCellProperty(PropertyRequest) returns (stream PropertyChunk) {} rpc GetGridProperty(PropertyRequest) returns (stream PropertyChunk) {} - rpc SetActiveCellProperty(stream PropertyInputChunk) returns (Empty) {} - rpc SetGridProperty(stream PropertyInputChunk) returns (Empty) {} + rpc SetActiveCellProperty(stream PropertyInputChunk) returns (ClientToServerStreamReply) {} + rpc SetGridProperty(stream PropertyInputChunk) returns (ClientToServerStreamReply) {} } enum PropertyType diff --git a/ApplicationCode/GrpcInterface/Python/rips/App.py b/ApplicationCode/GrpcInterface/Python/rips/App.py index 2eed6c8abb..64b2596396 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/App.py +++ b/ApplicationCode/GrpcInterface/Python/rips/App.py @@ -4,7 +4,7 @@ import sys sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'generated')) -from Empty_pb2 import Empty +from Definitions_pb2 import Empty import App_pb2 import App_pb2_grpc diff --git a/ApplicationCode/GrpcInterface/Python/rips/Commands.py b/ApplicationCode/GrpcInterface/Python/rips/Commands.py index 5a385cf926..652740337f 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Commands.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Commands.py @@ -4,7 +4,7 @@ import sys sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'generated')) -from Empty_pb2 import Empty +from Definitions_pb2 import Empty import Commands_pb2 as Cmd import Commands_pb2_grpc as CmdRpc from .Case import Case diff --git a/ApplicationCode/GrpcInterface/Python/rips/PdmObject.py b/ApplicationCode/GrpcInterface/Python/rips/PdmObject.py index 64189b10ef..e3277e6ba5 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/PdmObject.py +++ b/ApplicationCode/GrpcInterface/Python/rips/PdmObject.py @@ -4,7 +4,7 @@ import sys sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'generated')) -from Empty_pb2 import Empty +from Definitions_pb2 import Empty import PdmObject_pb2 import PdmObject_pb2_grpc diff --git a/ApplicationCode/GrpcInterface/Python/rips/Project.py b/ApplicationCode/GrpcInterface/Python/rips/Project.py index 4cf10e7d31..42359f7a70 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Project.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Project.py @@ -10,7 +10,7 @@ from .View import View sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'generated')) -from Empty_pb2 import Empty +from Definitions_pb2 import Empty import Project_pb2 import Project_pb2_grpc diff --git a/ApplicationCode/GrpcInterface/Python/rips/Properties.py b/ApplicationCode/GrpcInterface/Python/rips/Properties.py index 301fed723c..1b2fd23f60 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Properties.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Properties.py @@ -8,6 +8,7 @@ import Properties_pb2 import Properties_pb2_grpc import Case_pb2 import Case_pb2_grpc +from Definitions_pb2 import ClientToServerStreamReply class Properties: """ Class for streaming properties to and from ResInsight @@ -35,13 +36,13 @@ class Properties: # Meaning ideal number of doubles would be 8192. # However we need overhead space, so if we choose 8160 in chunk size # We have 256B left for overhead which should be plenty - chunkSize = 8000 + chunkSize = 44431 index = -1 while index < len(array): chunk = Properties_pb2.PropertyInputChunk() if index is -1: chunk.params.CopyFrom(parameters) - index += 1; + index += 1 else: actualChunkSize = min(len(array) - index + 1, chunkSize) chunk.values.CopyFrom(Properties_pb2.PropertyChunk(values = array[index:index+actualChunkSize])) @@ -184,8 +185,8 @@ class Properties: time_step = timeStep, porosity_model = porosityModelEnum) try: - reply_iterator = self.__generatePropertyInputIterator(values_iterator, request) - self.propertiesStub.SetActiveCellProperty(reply_iterator) + request_iterator = self.__generatePropertyInputIterator(values_iterator, request) + self.propertiesStub.SetActiveCellProperty(request_iterator) except grpc.RpcError as e: if e.code() == grpc.StatusCode.NOT_FOUND: print("Command not found") @@ -211,7 +212,10 @@ class Properties: porosity_model = porosityModelEnum) try: request_iterator = self.__generatePropertyInputChunks(values, request) - self.propertiesStub.SetActiveCellProperty(request_iterator) + reply = self.propertiesStub.SetActiveCellProperty(request_iterator) + if reply.values_accepted != len(values): + print("ERROR: Attempted to write outside bounds of " + propertyName + " data storage"); + except grpc.RpcError as e: if e.code() == grpc.StatusCode.NOT_FOUND: print("Command not found") @@ -239,7 +243,10 @@ class Properties: porosity_model = porosityModelEnum) try: request_iterator = self.__generatePropertyInputChunks(values, request) - self.propertiesStub.SetGridProperty(request_iterator) + reply = self.propertiesStub.SetGridProperty(request_iterator) + if reply.values_accepted != len(values): + print("ERROR: Attempted to write outside bounds of " + propertyName + " data storage"); + except grpc.RpcError as e: if e.code() == grpc.StatusCode.NOT_FOUND: print("Command not found") diff --git a/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.inl b/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.inl index f30e0113e5..77c1353975 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.inl +++ b/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.inl @@ -333,23 +333,25 @@ void RiaGrpcClientToServerStreamCallbackm_status = m_methodImpl(*this->m_service, &m_context, &this->m_request, &this->m_reply, m_stateHandler.get()); - + if (!this->m_status.ok()) { this->setNextCallState(RiaGrpcCallbackInterface::FINISH_REQUEST); - if (this->m_status.error_code() == grpc::OUT_OF_RANGE) + m_reader.FinishWithError(this->m_status, this); + } + else + { + CAF_ASSERT(m_stateHandler->nrOfValuesReceived() <= m_stateHandler->cellCount()); + if (m_stateHandler->nrOfValuesReceived() == m_stateHandler->cellCount()) { + this->setNextCallState(RiaGrpcCallbackInterface::FINISH_REQUEST); m_reader.Finish(this->m_reply, grpc::Status::OK, this); } else { - m_reader.FinishWithError(this->m_status, this); + m_reader.Read(&this->m_request, this); } - } - else - { - m_reader.Read(&this->m_request, this); - } + } } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp b/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp index 0fb2264de0..9872111ec5 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp +++ b/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp @@ -38,7 +38,7 @@ using namespace rips; -#define NUM_CONCURRENT_SERVER_STREAMS 10 +#define NUM_CONCURRENT_CLIENT_TO_SERVER_STREAMS 10 //-------------------------------------------------------------------------------------------------- /// Abstract handler base class for streaming cell results to client @@ -56,12 +56,28 @@ public: RiaCellResultsStateHandler(bool clientStreamer = false) : m_request(nullptr) , m_eclipseCase(nullptr) - , m_currentCellIdx(0u) + , m_nrOfValuesReceived(0u) , m_cellCount(0u) , m_clientStreamer(clientStreamer) { } + //-------------------------------------------------------------------------------------------------- + /// + //-------------------------------------------------------------------------------------------------- + size_t cellCount() const + { + return m_cellCount; + } + + //-------------------------------------------------------------------------------------------------- + /// + //-------------------------------------------------------------------------------------------------- + size_t nrOfValuesReceived() const + { + return m_nrOfValuesReceived; + } + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -79,31 +95,32 @@ public: auto resultData = caseData->results(porosityModel); auto resultType = static_cast(request->property_type()); size_t timeStep = static_cast(request->time_step()); - RigEclipseResultAddress resAddr(resultType, QString::fromStdString(request->property_name())); + + m_resultAddress = RigEclipseResultAddress(resultType, QString::fromStdString(request->property_name())); - if (resultData->ensureKnownResultLoaded(resAddr)) + if (resultData->ensureKnownResultLoaded(m_resultAddress)) { - if (timeStep < resultData->timeStepCount(resAddr)) + if (timeStep < resultData->timeStepCount(m_resultAddress)) { - initResultAccess(caseData, request->grid_index(), porosityModel, timeStep, resAddr); + initResultAccess(caseData, request->grid_index(), porosityModel, timeStep, m_resultAddress); return grpc::Status::OK; } return grpc::Status(grpc::NOT_FOUND, "No such time step"); } else if (m_clientStreamer) { - resultData->createResultEntry(resAddr, true); + resultData->createResultEntry(m_resultAddress, true); RigEclipseResultAddress addrToMaxTimeStepCountResult; size_t timeStepCount = resultData->maxTimeStepCount(&addrToMaxTimeStepCountResult); const std::vector timeStepInfos = resultData->timeStepInfos(addrToMaxTimeStepCountResult); - resultData->setTimeStepInfos(resAddr, timeStepInfos); - auto scalarResultFrames = resultData->modifiableCellScalarResultTimesteps(resAddr); + resultData->setTimeStepInfos(m_resultAddress, timeStepInfos); + auto scalarResultFrames = resultData->modifiableCellScalarResultTimesteps(m_resultAddress); scalarResultFrames.resize(timeStepCount); - if (timeStep < resultData->timeStepCount(resAddr)) + if (timeStep < resultData->timeStepCount(m_resultAddress)) { - initResultAccess(caseData, request->grid_index(), porosityModel, timeStep, resAddr); + initResultAccess(caseData, request->grid_index(), porosityModel, timeStep, m_resultAddress); return grpc::Status::OK; } return grpc::Status(grpc::NOT_FOUND, "No such time step"); @@ -133,9 +150,9 @@ public: const size_t packageSize = RiaGrpcServiceInterface::numberOfMessagesForByteCount(sizeof(rips::PropertyChunk)); size_t packageIndex = 0u; reply->mutable_values()->Reserve((int)packageSize); - for (; packageIndex < packageSize && m_currentCellIdx < m_cellCount; ++packageIndex, ++m_currentCellIdx) + for (; packageIndex < packageSize && m_nrOfValuesReceived < m_cellCount; ++packageIndex, ++m_nrOfValuesReceived) { - reply->add_values(cellResult(m_currentCellIdx)); + reply->add_values(cellResult(m_nrOfValuesReceived)); } if (packageIndex > 0u) { @@ -148,23 +165,31 @@ public: //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- - Status receiveStreamRequest(const PropertyInputChunk* request) + Status receiveStreamRequest(const PropertyInputChunk* request, ClientToServerStreamReply* reply) { + CAF_ASSERT(!request->has_params()); if (request->has_values()) { auto values = request->values().values(); - for (int i = 0; i < values.size() && m_currentCellIdx < m_cellCount; ++i, ++m_currentCellIdx) - { - setCellResult(m_currentCellIdx, values[i]); - } - if (m_currentCellIdx >= m_cellCount - 1) - { - return grpc::Status(grpc::OUT_OF_RANGE, "All values have been written"); - } + if (!values.empty()) + { + size_t currentCellIdx = m_nrOfValuesReceived; + m_nrOfValuesReceived += values.size(); + + for (int i = 0; i < values.size() && currentCellIdx < m_cellCount; ++i, ++currentCellIdx) + { + setCellResult(currentCellIdx, values[i]); + } - return Status::OK; + if (m_nrOfValuesReceived > m_cellCount) + { + return grpc::Status(grpc::OUT_OF_RANGE, "Attempting to write out of bounds"); + } + reply->set_values_accepted(static_cast(currentCellIdx)); + return Status::OK; + } } - return grpc::Status(grpc::OUT_OF_RANGE, "No messages to write"); + return Status::OK; } //-------------------------------------------------------------------------------------------------- @@ -174,6 +199,11 @@ public: { if (m_eclipseCase) { + auto porosityModel = static_cast(m_request->porosity_model()); + auto caseData = m_eclipseCase->eclipseCaseData(); + auto resultData = caseData->results(porosityModel); + resultData->recalculateStatistics(m_resultAddress); + for (Rim3dView* view : m_eclipseCase->views()) { view->setCurrentTimeStepAndUpdate(view->currentTimeStep()); @@ -192,11 +222,12 @@ protected: virtual void setCellResult(size_t currentCellIndex, double value) = 0; protected: - const rips::PropertyRequest* m_request; - RimEclipseCase* m_eclipseCase; - size_t m_currentCellIdx; - size_t m_cellCount; - bool m_clientStreamer; + const rips::PropertyRequest* m_request; + RimEclipseCase* m_eclipseCase; + size_t m_nrOfValuesReceived; + size_t m_cellCount; + bool m_clientStreamer; + RigEclipseResultAddress m_resultAddress; }; class RiaActiveCellResultsStateHandler : public RiaCellResultsStateHandler @@ -328,22 +359,22 @@ grpc::Status RiaGrpcPropertiesService::GetGridProperty(grpc::ServerContext* //-------------------------------------------------------------------------------------------------- grpc::Status RiaGrpcPropertiesService::SetActiveCellProperty(grpc::ServerContext* context, const rips::PropertyInputChunk* request, - rips::Empty* reply, + rips::ClientToServerStreamReply* reply, RiaActiveCellResultsStateHandler* stateHandler) { - return stateHandler->receiveStreamRequest(request); + return stateHandler->receiveStreamRequest(request, reply); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -grpc::Status RiaGrpcPropertiesService::SetGridProperty(grpc::ServerContext* context, - const rips::PropertyInputChunk* request, - rips::Empty* reply, - RiaGridCellResultsStateHandler* stateHandler) +grpc::Status RiaGrpcPropertiesService::SetGridProperty(grpc::ServerContext* context, + const rips::PropertyInputChunk* request, + rips::ClientToServerStreamReply* reply, + RiaGridCellResultsStateHandler* stateHandler) { - return stateHandler->receiveStreamRequest(request); + return stateHandler->receiveStreamRequest(request, reply); } //-------------------------------------------------------------------------------------------------- /// @@ -356,12 +387,12 @@ std::vector RiaGrpcPropertiesService::createCallbacks callbacks = { new RiaGrpcUnaryCallback( this, &Self::GetAvailableProperties, &Self::RequestGetAvailableProperties), - new RiaGrpcClientToServerStreamCallback( + new RiaGrpcClientToServerStreamCallback( this, &Self::SetActiveCellProperty, &Self::RequestSetActiveCellProperty, new RiaActiveCellResultsStateHandler(true)), - new RiaGrpcClientToServerStreamCallback( + new RiaGrpcClientToServerStreamCallback( this, &Self::SetGridProperty, &Self::RequestSetGridProperty, new RiaGridCellResultsStateHandler(true))}; - for (int i = 0; i < NUM_CONCURRENT_SERVER_STREAMS; ++i) + for (int i = 0; i < NUM_CONCURRENT_CLIENT_TO_SERVER_STREAMS; ++i) { callbacks.push_back(new RiaGrpcServerToClientStreamCallback( this, &Self::GetActiveCellProperty, &Self::RequestGetActiveCellProperty, new RiaActiveCellResultsStateHandler)); diff --git a/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.h b/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.h index b918c82400..91f7c7f4c1 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.h +++ b/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.h @@ -38,21 +38,21 @@ public: const rips::AvailablePropertiesRequest* request, rips::AvailableProperties* reply) override; grpc::Status GetActiveCellProperty(grpc::ServerContext* context, - const rips::PropertyRequest* request, - rips::PropertyChunk* reply, + const rips::PropertyRequest* request, + rips::PropertyChunk* reply, RiaActiveCellResultsStateHandler* stateHandler); grpc::Status GetGridProperty(grpc::ServerContext* context, - const rips::PropertyRequest* request, - rips::PropertyChunk* reply, + const rips::PropertyRequest* request, + rips::PropertyChunk* reply, RiaGridCellResultsStateHandler* stateHandler); - grpc::Status SetActiveCellProperty(grpc::ServerContext* context, + grpc::Status SetActiveCellProperty(grpc::ServerContext* context, const rips::PropertyInputChunk* chunk, - rips::Empty* reply, + rips::ClientToServerStreamReply* reply, RiaActiveCellResultsStateHandler* stateHandler); - grpc::Status SetGridProperty(grpc::ServerContext* context, - const rips::PropertyInputChunk* chunk, - rips::Empty* reply, - RiaGridCellResultsStateHandler* stateHandler); + grpc::Status SetGridProperty(grpc::ServerContext* context, + const rips::PropertyInputChunk* chunk, + rips::ClientToServerStreamReply* reply, + RiaGridCellResultsStateHandler* stateHandler); std::vector createCallbacks() override; }; From 84495641f96d410fb437beecd4820db35e13bd65 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Wed, 14 Aug 2019 09:08:55 +0200 Subject: [PATCH 321/396] Fix problem with wrong return value for RiaImportEclipseCaseTools method --- ApplicationCode/Application/Tools/RiaImportEclipseCaseTools.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ApplicationCode/Application/Tools/RiaImportEclipseCaseTools.cpp b/ApplicationCode/Application/Tools/RiaImportEclipseCaseTools.cpp index a458e76082..f7b677c502 100644 --- a/ApplicationCode/Application/Tools/RiaImportEclipseCaseTools.cpp +++ b/ApplicationCode/Application/Tools/RiaImportEclipseCaseTools.cpp @@ -196,7 +196,7 @@ bool RiaImportEclipseCaseTools::openEclipseCasesFromFile(const QStringList& file //-------------------------------------------------------------------------------------------------- int RiaImportEclipseCaseTools::openEclipseCaseFromFile(const QString& fileName) { - if (!caf::Utils::fileExists(fileName)) return false; + if (!caf::Utils::fileExists(fileName)) return -1; return RiaImportEclipseCaseTools::openEclipseCaseShowTimeStepFilterImpl(fileName, false); } From 197279ccbf3a634ec2d72feceaf7e92620229b5c Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Wed, 14 Aug 2019 09:14:12 +0200 Subject: [PATCH 322/396] #4576 Python: Improve error handling and add example --- .../GrpcInterface/CMakeLists.cmake | 1 + .../GrpcProtos/Definitions.proto | 2 +- .../GrpcInterface/Python/rips/Commands.py | 16 +---- .../GrpcInterface/Python/rips/Properties.py | 63 ++++++++----------- .../Python/rips/examples/ErrorHandling.py | 52 +++++++++++++++ .../Python/rips/examples/InputPropTestSync.py | 7 ++- .../GrpcInterface/RiaGrpcCallbacks.inl | 4 +- .../RiaGrpcPropertiesService.cpp | 21 +++---- 8 files changed, 99 insertions(+), 67 deletions(-) create mode 100644 ApplicationCode/GrpcInterface/Python/rips/examples/ErrorHandling.py diff --git a/ApplicationCode/GrpcInterface/CMakeLists.cmake b/ApplicationCode/GrpcInterface/CMakeLists.cmake index b911d660b6..cd3a7258b3 100644 --- a/ApplicationCode/GrpcInterface/CMakeLists.cmake +++ b/ApplicationCode/GrpcInterface/CMakeLists.cmake @@ -173,6 +173,7 @@ if (RESINSIGHT_GRPC_PYTHON_EXECUTABLE) "rips/examples/CommandExample.py" "rips/examples/CaseGridGroup.py" "rips/examples/CaseInfoStreamingExample.py" + "rips/examples/ErrorHandling.py" "rips/examples/SoilPorvAsync.py" "rips/examples/SoilPorvSync.py" "rips/examples/SelectedCases.py" diff --git a/ApplicationCode/GrpcInterface/GrpcProtos/Definitions.proto b/ApplicationCode/GrpcInterface/GrpcProtos/Definitions.proto index 1f5df27d0a..dcdabb8310 100644 --- a/ApplicationCode/GrpcInterface/GrpcProtos/Definitions.proto +++ b/ApplicationCode/GrpcInterface/GrpcProtos/Definitions.proto @@ -8,5 +8,5 @@ message Empty message ClientToServerStreamReply { - int64 values_accepted = 1; + int64 accepted_value_count = 1; } \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/Python/rips/Commands.py b/ApplicationCode/GrpcInterface/Python/rips/Commands.py index 652740337f..063b92f081 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Commands.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Commands.py @@ -25,14 +25,8 @@ class Commands: self.commands = CmdRpc.CommandsStub(channel) def __execute(self, **commandParams): - try: - return self.commands.Execute(Cmd.CommandParams(**commandParams)) - except grpc.RpcError as e: - if e.code() == grpc.StatusCode.NOT_FOUND: - print("Command not found", commandParams.keys()) - else: - print("Other error", e) - + return self.commands.Execute(Cmd.CommandParams(**commandParams)) + ######################## # Case Control Commands ######################## @@ -71,8 +65,6 @@ class Commands: """ commandReply = self.__execute(loadCase=Cmd.FilePathRequest(path=path)) - assert(commandReply is not None) - assert(commandReply.HasField("loadCaseResult")) return Case(self.channel, commandReply.loadCaseResult.id) def replaceCase(self, newGridFile, caseId=0): @@ -107,14 +99,10 @@ class Commands: A case group id and name """ commandReply = self.__execute(createGridCaseGroup=Cmd.CreateGridCaseGroupRequest(casePaths=casePaths)) - assert(commandReply is not None) - assert(commandReply.HasField("createGridCaseGroupResult")) return (commandReply.createGridCaseGroupResult.groupId, commandReply.createGridCaseGroupResult.groupName) def createStatisticsCase(self, caseGroupId): commandReply = self.__execute(createStatisticsCase=Cmd.CreateStatisticsCaseRequest(caseGroupId=caseGroupId)) - assert(commandReply is not None) - assert(commandReply.HasField("createStatisticsCaseResult")) return commandReply.createStatisticsCaseResult.caseId; ################## diff --git a/ApplicationCode/GrpcInterface/Python/rips/Properties.py b/ApplicationCode/GrpcInterface/Python/rips/Properties.py index 1b2fd23f60..8b25d29033 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Properties.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Properties.py @@ -12,7 +12,14 @@ from Definitions_pb2 import ClientToServerStreamReply class Properties: """ Class for streaming properties to and from ResInsight - """ + + Attributes: + chunkSize(int): The size of each chunk during value streaming. + A good chunk size is 64KiB = 65536B. + Meaning the ideal number of doubles would be 8192. + However we need overhead space, so the default is 8160. + This leaves 256B for overhead. + """ def __init__(self, case): """ Arguments: @@ -20,6 +27,8 @@ class Properties: """ self.case = case self.propertiesStub = Properties_pb2_grpc.PropertiesStub(self.case.channel) + self.chunkSize = 8160 + def __generatePropertyInputIterator(self, values_iterator, parameters): chunk = Properties_pb2.PropertyInputChunk() @@ -32,11 +41,7 @@ class Properties: yield chunk def __generatePropertyInputChunks(self, array, parameters): - # Each double is 8 bytes. A good chunk size is 64KiB = 65536B - # Meaning ideal number of doubles would be 8192. - # However we need overhead space, so if we choose 8160 in chunk size - # We have 256B left for overhead which should be plenty - chunkSize = 44431 + index = -1 while index < len(array): chunk = Properties_pb2.PropertyInputChunk() @@ -44,7 +49,7 @@ class Properties: chunk.params.CopyFrom(parameters) index += 1 else: - actualChunkSize = min(len(array) - index + 1, chunkSize) + actualChunkSize = min(len(array) - index + 1, self.chunkSize) chunk.values.CopyFrom(Properties_pb2.PropertyChunk(values = array[index:index+actualChunkSize])) index += actualChunkSize @@ -184,15 +189,10 @@ class Properties: property_name = propertyName, time_step = timeStep, porosity_model = porosityModelEnum) - try: - request_iterator = self.__generatePropertyInputIterator(values_iterator, request) - self.propertiesStub.SetActiveCellProperty(request_iterator) - except grpc.RpcError as e: - if e.code() == grpc.StatusCode.NOT_FOUND: - print("Command not found") - else: - print("Other error", e) - + + request_iterator = self.__generatePropertyInputIterator(values_iterator, request) + self.propertiesStub.SetActiveCellProperty(request_iterator) + def setActiveCellProperty(self, values, propertyType, propertyName, timeStep, porosityModel = 'MATRIX_MODEL'): """Set a cell property for all active cells. @@ -210,17 +210,10 @@ class Properties: property_name = propertyName, time_step = timeStep, porosity_model = porosityModelEnum) - try: - request_iterator = self.__generatePropertyInputChunks(values, request) - reply = self.propertiesStub.SetActiveCellProperty(request_iterator) - if reply.values_accepted != len(values): - print("ERROR: Attempted to write outside bounds of " + propertyName + " data storage"); - - except grpc.RpcError as e: - if e.code() == grpc.StatusCode.NOT_FOUND: - print("Command not found") - else: - print("Other error", e) + request_iterator = self.__generatePropertyInputChunks(values, request) + reply = self.propertiesStub.SetActiveCellProperty(request_iterator) + if reply.accepted_value_count < len(values): + raise IndexError def setGridProperty(self, values, propertyType, propertyName, timeStep, gridIndex = 0, porosityModel = 'MATRIX_MODEL'): """Set a cell property for all grid cells. @@ -241,14 +234,8 @@ class Properties: time_step = timeStep, grid_index = gridIndex, porosity_model = porosityModelEnum) - try: - request_iterator = self.__generatePropertyInputChunks(values, request) - reply = self.propertiesStub.SetGridProperty(request_iterator) - if reply.values_accepted != len(values): - print("ERROR: Attempted to write outside bounds of " + propertyName + " data storage"); - - except grpc.RpcError as e: - if e.code() == grpc.StatusCode.NOT_FOUND: - print("Command not found") - else: - print("Other error", e) + request_iterator = self.__generatePropertyInputChunks(values, request) + reply = self.propertiesStub.SetGridProperty(request_iterator) + if reply.accepted_value_count < len(values): + raise IndexError + \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/ErrorHandling.py b/ApplicationCode/GrpcInterface/Python/rips/examples/ErrorHandling.py new file mode 100644 index 0000000000..dacccaed71 --- /dev/null +++ b/ApplicationCode/GrpcInterface/Python/rips/examples/ErrorHandling.py @@ -0,0 +1,52 @@ +import rips +import grpc + +resInsight = rips.Instance.find() + +case = None + +# Try loading a non-existing case. We should get a grpc.RpcError exception from the server +try: + case = resInsight.project.loadCase("Nonsense") +except grpc.RpcError as e: + print("Expected Server Exception Received: ", e) + +case = resInsight.project.case(id=0) +if case is not None: + results = case.properties.activeCellProperty('STATIC_NATIVE', 'PORO', 0) + activeCellCount = len(results) + + # Send the results back to ResInsight inside try / except construct + try: + case.properties.setActiveCellProperty(results, 'GENERATED', 'POROAPPENDED', 0) + print("Everything went well as expected") + except: # Match any exception, but it should not happen + print("Ooops!") + + # Add another value, so this is outside the bounds of the active cell result storage + results.append(1.0) + + # This time we should get a grpc.RpcError exception, which is a server side error. + try: + case.properties.setActiveCellProperty(results, 'GENERATED', 'POROAPPENDED', 0) + print("Everything went well??") + except grpc.RpcError as e: + print("Expected Server Exception Received: ", e) + except IndexError: + print ("Got index out of bounds error. This shouldn't happen here") + + # With a chunk size exactly matching the active cell count the server will not + # be able to see any error as it will successfully close the stream after receiving + # the correct number of values, even if the python client has more chunks to send + case.properties.chunkSize = activeCellCount + + try: + case.properties.setActiveCellProperty(results, 'GENERATED', 'POROAPPENDED', 0) + print("Everything went well??") + except grpc.RpcError as e: + print("Got unexpected server exception", e, "This should not happen now") + except IndexError: + print ("Got expected index out of bounds error on client side") + + + diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/InputPropTestSync.py b/ApplicationCode/GrpcInterface/Python/rips/examples/InputPropTestSync.py index c92327af28..7354fc2ced 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/examples/InputPropTestSync.py +++ b/ApplicationCode/GrpcInterface/Python/rips/examples/InputPropTestSync.py @@ -1,5 +1,6 @@ import rips import time +import grpc resInsight = rips.Instance.find() start = time.time() @@ -12,7 +13,11 @@ results = [] for (poro, permx) in zip(poroResults, permxResults): results.append(poro * permx) -case.properties.setActiveCellProperty(results, 'GENERATED', 'POROPERMXSY', 0) +try: + case.properties.setActiveCellProperty(results, 'GENERATED', 'POROPERMXSY', 0) +except grpc.RpcError as e: + print("Exception Received: ", e) + end = time.time() print("Time elapsed: ", end - start) diff --git a/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.inl b/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.inl index 77c1353975..5e96997cd2 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.inl +++ b/ApplicationCode/GrpcInterface/RiaGrpcCallbacks.inl @@ -341,8 +341,8 @@ void RiaGrpcClientToServerStreamCallbacknrOfValuesReceived() <= m_stateHandler->cellCount()); - if (m_stateHandler->nrOfValuesReceived() == m_stateHandler->cellCount()) + CAF_ASSERT(m_stateHandler->streamedValueCount() <= m_stateHandler->cellCount()); + if (m_stateHandler->streamedValueCount() == m_stateHandler->cellCount()) { this->setNextCallState(RiaGrpcCallbackInterface::FINISH_REQUEST); m_reader.Finish(this->m_reply, grpc::Status::OK, this); diff --git a/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp b/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp index 9872111ec5..e97fe9454d 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp +++ b/ApplicationCode/GrpcInterface/RiaGrpcPropertiesService.cpp @@ -56,7 +56,7 @@ public: RiaCellResultsStateHandler(bool clientStreamer = false) : m_request(nullptr) , m_eclipseCase(nullptr) - , m_nrOfValuesReceived(0u) + , m_streamedValueCount(0u) , m_cellCount(0u) , m_clientStreamer(clientStreamer) { @@ -73,9 +73,9 @@ public: //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- - size_t nrOfValuesReceived() const + size_t streamedValueCount() const { - return m_nrOfValuesReceived; + return m_streamedValueCount; } //-------------------------------------------------------------------------------------------------- @@ -150,9 +150,9 @@ public: const size_t packageSize = RiaGrpcServiceInterface::numberOfMessagesForByteCount(sizeof(rips::PropertyChunk)); size_t packageIndex = 0u; reply->mutable_values()->Reserve((int)packageSize); - for (; packageIndex < packageSize && m_nrOfValuesReceived < m_cellCount; ++packageIndex, ++m_nrOfValuesReceived) + for (; packageIndex < packageSize && m_streamedValueCount < m_cellCount; ++packageIndex, ++m_streamedValueCount) { - reply->add_values(cellResult(m_nrOfValuesReceived)); + reply->add_values(cellResult(m_streamedValueCount)); } if (packageIndex > 0u) { @@ -167,25 +167,24 @@ public: //-------------------------------------------------------------------------------------------------- Status receiveStreamRequest(const PropertyInputChunk* request, ClientToServerStreamReply* reply) { - CAF_ASSERT(!request->has_params()); if (request->has_values()) { auto values = request->values().values(); if (!values.empty()) { - size_t currentCellIdx = m_nrOfValuesReceived; - m_nrOfValuesReceived += values.size(); + size_t currentCellIdx = m_streamedValueCount; + m_streamedValueCount += values.size(); for (int i = 0; i < values.size() && currentCellIdx < m_cellCount; ++i, ++currentCellIdx) { setCellResult(currentCellIdx, values[i]); } - if (m_nrOfValuesReceived > m_cellCount) + if (m_streamedValueCount > m_cellCount) { return grpc::Status(grpc::OUT_OF_RANGE, "Attempting to write out of bounds"); } - reply->set_values_accepted(static_cast(currentCellIdx)); + reply->set_accepted_value_count(static_cast(currentCellIdx)); return Status::OK; } } @@ -224,7 +223,7 @@ protected: protected: const rips::PropertyRequest* m_request; RimEclipseCase* m_eclipseCase; - size_t m_nrOfValuesReceived; + size_t m_streamedValueCount; size_t m_cellCount; bool m_clientStreamer; RigEclipseResultAddress m_resultAddress; From 7afeae144a7a028b23136248e7c403948d7c2529 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Wed, 14 Aug 2019 09:23:14 +0200 Subject: [PATCH 323/396] Python CMake: change RESINSIGHT_GRPC_PYTHON_EXECUTABLE to be FILEPATH instead of PATH --- ApplicationCode/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ApplicationCode/CMakeLists.txt b/ApplicationCode/CMakeLists.txt index 0eedabdb4b..7477a051ee 100644 --- a/ApplicationCode/CMakeLists.txt +++ b/ApplicationCode/CMakeLists.txt @@ -549,7 +549,7 @@ endforeach() # Copy all grpc libraries and python files if (RESINSIGHT_ENABLE_GRPC) - set(RESINSIGHT_GRPC_PYTHON_EXECUTABLE "" CACHE PATH "gRPC : Path to Python 3 executable, required to build the Python client library") + set(RESINSIGHT_GRPC_PYTHON_EXECUTABLE "" CACHE FILEPATH "gRPC : Path to Python 3 executable, required to build the Python client library") if (RESINSIGHT_GRPC_PYTHON_EXECUTABLE) if (EXISTS ${RESINSIGHT_GRPC_PYTHON_EXECUTABLE}) add_custom_target(GeneratedPythonSources DEPENDS ${GRPC_GENERATED_PYTHON_SOURCES}) From 071bb42101441e827dfdcf590898c35d529b14cb Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Wed, 14 Aug 2019 09:43:44 +0200 Subject: [PATCH 324/396] #4576 Python: Add tests to check for expected exceptions --- .../Python/rips/tests/test_commands.py | 8 +++++- .../Python/rips/tests/test_properties.py | 27 +++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/ApplicationCode/GrpcInterface/Python/rips/tests/test_commands.py b/ApplicationCode/GrpcInterface/Python/rips/tests/test_commands.py index c5f88482fe..a5aafd798b 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/tests/test_commands.py +++ b/ApplicationCode/GrpcInterface/Python/rips/tests/test_commands.py @@ -2,6 +2,7 @@ import sys import os import tempfile import pytest +import grpc sys.path.insert(1, os.path.join(sys.path[0], '../../')) import rips @@ -49,4 +50,9 @@ def test_exportFlowCharacteristics(rips_instance, initializeTest): with tempfile.TemporaryDirectory(prefix="rips") as tmpdirname: print("Temporary folder: ", tmpdirname) fileName = tmpdirname + "/exportFlowChar.txt" - rips_instance.commands.exportFlowCharacteristics(caseId=0, timeSteps=8, producers=[], injectors = "I01", fileName = fileName) \ No newline at end of file + rips_instance.commands.exportFlowCharacteristics(caseId=0, timeSteps=8, producers=[], injectors = "I01", fileName = fileName) + +def test_loadNonExistingCase(rips_instance, initializeTest): + casePath = "Nonsense/Nonsense/Nonsense" + with pytest.raises(grpc.RpcError): + assert rips_instance.project.loadCase(casePath) diff --git a/ApplicationCode/GrpcInterface/Python/rips/tests/test_properties.py b/ApplicationCode/GrpcInterface/Python/rips/tests/test_properties.py index a363d74f3b..fba9d6c125 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/tests/test_properties.py +++ b/ApplicationCode/GrpcInterface/Python/rips/tests/test_properties.py @@ -1,5 +1,6 @@ import sys import os +import grpc import pytest sys.path.insert(1, os.path.join(sys.path[0], '../../')) @@ -33,6 +34,32 @@ def test_10kSync(rips_instance, initializeTest): assert(average != pytest.approx(0.0158893, abs=0.0000001)) assert(average == pytest.approx(0.0558893, abs=0.0000001)) +def test_10k_set(rips_instance, initializeTest): + casePath = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID" + case = rips_instance.project.loadCase(path=casePath) + + results = case.properties.activeCellProperty('DYNAMIC_NATIVE', 'SOIL', 1) + case.properties.setActiveCellProperty(results, 'GENERATED', 'SOIL', 1) + +def test_10k_set_out_of_bounds(rips_instance, initializeTest): + casePath = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID" + case = rips_instance.project.loadCase(path=casePath) + + results = case.properties.activeCellProperty('DYNAMIC_NATIVE', 'SOIL', 1) + results.append(5.0) + with pytest.raises(grpc.RpcError): + assert case.properties.setActiveCellProperty(results, 'GENERATED', 'SOIL', 1) + +def test_10k_set_out_of_bounds_client(rips_instance, initializeTest): + casePath = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID" + case = rips_instance.project.loadCase(path=casePath) + + results = case.properties.activeCellProperty('DYNAMIC_NATIVE', 'SOIL', 1) + case.properties.chunkSize = len(results) + results.append(5.0) + with pytest.raises(IndexError): + assert case.properties.setActiveCellProperty(results, 'GENERATED', 'SOIL', 1) + def createResult(poroChunks, permxChunks): for (poroChunk, permxChunk) in zip(poroChunks, permxChunks): resultChunk = [] From 25ad832ab0d691e09b401ff17f9ae41a0aa7b3c5 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 14 Aug 2019 17:00:39 +0200 Subject: [PATCH 325/396] Upped to 2019.04.0-dev.05 --- ResInsightVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ResInsightVersion.cmake b/ResInsightVersion.cmake index 18fea3e40e..56fdcd72a0 100644 --- a/ResInsightVersion.cmake +++ b/ResInsightVersion.cmake @@ -10,7 +10,7 @@ set(RESINSIGHT_VERSION_TEXT "-dev") # 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 ".04") +set(RESINSIGHT_DEV_VERSION ".05") # https://github.com/CRAVA/crava/tree/master/libs/nrlib set(NRLIB_GITHUB_SHA "ba35d4359882f1c6f5e9dc30eb95fe52af50fd6f") From 010c9a539fe0d54030f06f03dce7c5ea3e719a84 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 15 Aug 2019 10:08:19 +0200 Subject: [PATCH 326/396] #4579 Countour Map : Fix missing data for Eclipse cases Introduction of checkable sub grids caused contour maps to display nothing. The problematic code was m_gridCollection->setActive(false); Changes in update logic based on checked state of visible grids triggered new computation of visible cells. In this case, all grids where marked as invisible due to the disabled grid collection. --- ApplicationCode/ProjectDataModel/RimEclipseContourMapView.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimEclipseContourMapView.cpp b/ApplicationCode/ProjectDataModel/RimEclipseContourMapView.cpp index adeba1b849..44bfb6acce 100644 --- a/ApplicationCode/ProjectDataModel/RimEclipseContourMapView.cpp +++ b/ApplicationCode/ProjectDataModel/RimEclipseContourMapView.cpp @@ -62,7 +62,6 @@ RimEclipseContourMapView::RimEclipseContourMapView() CAF_PDM_InitField(&m_showAxisLines, "ShowAxisLines", true, "Show Axis Lines", "", "", ""); CAF_PDM_InitField(&m_showScaleLegend, "ShowScaleLegend", true, "Show Scale Legend", "", "", ""); - m_gridCollection->setActive(false); // This is also not added to the tree view, so cannot be enabled. setFaultVisParameters(); setDefaultCustomName(); @@ -164,7 +163,6 @@ void RimEclipseContourMapView::updateCurrentTimeStepAndRedraw() //-------------------------------------------------------------------------------------------------- void RimEclipseContourMapView::initAfterRead() { - m_gridCollection->setActive(false); // This is also not added to the tree view, so cannot be enabled. disablePerspectiveProjectionField(); setShowGridBox(false); meshMode.setValue(RiaDefines::NO_MESH); From f3c0c4ff82053cd4230836143022dc41cfd3378b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Wed, 14 Aug 2019 16:42:02 +0200 Subject: [PATCH 327/396] #4554 Harmonized path separator direction in hierarchy file dialog on windows --- ApplicationCode/Commands/RicFileHierarchyDialog.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ApplicationCode/Commands/RicFileHierarchyDialog.cpp b/ApplicationCode/Commands/RicFileHierarchyDialog.cpp index 1b3f8bc671..e1bf6a4f14 100644 --- a/ApplicationCode/Commands/RicFileHierarchyDialog.cpp +++ b/ApplicationCode/Commands/RicFileHierarchyDialog.cpp @@ -283,7 +283,7 @@ void RicFileHierarchyDialog::appendToFileList(const QString& fileName) { QString itemText = fileName; itemText.remove(0, rootDir().size()); - QListWidgetItem* item = new QListWidgetItem(itemText, m_fileList); + QListWidgetItem* item = new QListWidgetItem(QDir::toNativeSeparators(itemText), m_fileList); item->setFlags(item->flags() | Qt::ItemIsUserCheckable); item->setCheckState(Qt::Checked); } @@ -715,7 +715,7 @@ void RicFileHierarchyDialog::slotDialogOkClicked() const QListWidgetItem* item = m_fileList->item(i); if ((item->flags() & Qt::ItemIsUserCheckable) != 0 && item->checkState()) { - m_files.push_back(rootDir() + item->text()); + m_files.push_back(rootDir() + RiaFilePathTools::toInternalSeparator(item->text())); } } accept(); @@ -737,7 +737,7 @@ void RicFileHierarchyDialog::slotDialogCancelClicked() void RicFileHierarchyDialog::slotBrowseButtonClicked() { QString folder = QFileDialog::getExistingDirectory(this, "Select root folder", m_rootDir->text()); - if(!folder.isEmpty()) m_rootDir->setText(folder); + if(!folder.isEmpty()) m_rootDir->setText(QDir::toNativeSeparators(folder)); } From e1c061fd15ac99fde7481366884ea9bf18d2137a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Thu, 15 Aug 2019 14:18:46 +0200 Subject: [PATCH 328/396] #4554 Use "..." in display of effective filter as notion of recursive search Fix display of multiple extensions Replace "**" with * in path text --- .../Commands/RicFileHierarchyDialog.cpp | 42 +++++++++---------- .../Commands/RicFileHierarchyDialog.h | 3 +- 2 files changed, 21 insertions(+), 24 deletions(-) diff --git a/ApplicationCode/Commands/RicFileHierarchyDialog.cpp b/ApplicationCode/Commands/RicFileHierarchyDialog.cpp index e1bf6a4f14..928361e8a1 100644 --- a/ApplicationCode/Commands/RicFileHierarchyDialog.cpp +++ b/ApplicationCode/Commands/RicFileHierarchyDialog.cpp @@ -71,7 +71,6 @@ static const QChar SEPARATOR = RiaFilePathTools::SEPARATOR; static QStringList prefixStrings(const QStringList& strings, const QString& prefix); static QStringList trimLeftStrings(const QStringList& strings, const QString& trimText); static void sortStringsByLength(QStringList& strings, bool ascending = true); -static QString effectivePathFilter(const QString& enteredPathFilter); //-------------------------------------------------------------------------------------------------- /// @@ -216,7 +215,7 @@ QString RicFileHierarchyDialog::rootDir() const //-------------------------------------------------------------------------------------------------- QString RicFileHierarchyDialog::pathFilter() const { - return RiaFilePathTools::toInternalSeparator(m_pathFilter->text().trimmed()); + return RiaFilePathTools::toInternalSeparator(m_pathFilter->text().trimmed()).replace(QString("**"), QString("*")); } //-------------------------------------------------------------------------------------------------- @@ -477,7 +476,7 @@ void RicFileHierarchyDialog::buildDirectoryListRecursiveSimple(const QString& cu QStringList RicFileHierarchyDialog::findFilesInDirs(const QStringList& dirs) { QStringList allFiles; - QStringList filters = createNameFilterList(fileNameFilter(), fileExtensions()); + QStringList filters = createFileNameFilterList(); for (const auto& dir : dirs) { @@ -501,8 +500,11 @@ QStringList RicFileHierarchyDialog::findFilesInDirs(const QStringList& dirs) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QStringList RicFileHierarchyDialog::createNameFilterList(const QString &fileNameFilter, const QStringList &fileExtensions) +QStringList RicFileHierarchyDialog::createFileNameFilterList() { + QString fileNameFilter = this->fileNameFilter(); + QStringList fileExtensions = this->fileExtensions(); + QStringList nameFilter; QString effectiveFileNameFilter = !fileNameFilter.isEmpty() ? fileNameFilter : "*"; @@ -536,24 +538,28 @@ bool RicFileHierarchyDialog::pathFilterMatch(const QString& pathFilter, const QS //-------------------------------------------------------------------------------------------------- void RicFileHierarchyDialog::updateEffectiveFilter() { - QString effFilter = QString("%1/%2/%3%4") - .arg(m_rootDir->text()) - .arg(effectivePathFilter(m_pathFilter->text())) - .arg(fileNameFilter()) - .arg(fileExtensionsText()); + QString pathFilterText = pathFilter(); + if (pathFilterText == "*" || pathFilterText.endsWith(QString(SEPARATOR) + "*")) + { + pathFilterText.chop(1); + pathFilterText = pathFilterText + "..."; + } - QString internalFilter(RiaFilePathTools::toInternalSeparator(effFilter)); + QString effFilterText = QString("%1/%2/%3") + .arg(rootDir()) + .arg(pathFilterText) + .arg(createFileNameFilterList().join("|")); // Remove duplicate separators int len; do { - len = internalFilter.size(); - internalFilter.replace(QString("%1%1").arg(SEPARATOR), SEPARATOR); - } while (internalFilter.size() != len); + len = effFilterText.size(); + effFilterText.replace(QString("%1%1").arg(SEPARATOR), SEPARATOR); + } while (effFilterText.size() != len); // Present native separators to the user - m_effectiveFilter->setText(QDir::toNativeSeparators(internalFilter)); + m_effectiveFilter->setText(QDir::toNativeSeparators(effFilterText)); } //-------------------------------------------------------------------------------------------------- @@ -811,11 +817,3 @@ void sortStringsByLength(QStringList& strings, bool ascending /*= true*/) } -QString effectivePathFilter(const QString& enteredPathFilter) -{ - QString p = RiaFilePathTools::toInternalSeparator(enteredPathFilter); - - if (p == "*" || p.endsWith(QString(SEPARATOR) + "*")) return p + "*"; - else return p; -} - diff --git a/ApplicationCode/Commands/RicFileHierarchyDialog.h b/ApplicationCode/Commands/RicFileHierarchyDialog.h index e0052e801a..a48f3fe918 100644 --- a/ApplicationCode/Commands/RicFileHierarchyDialog.h +++ b/ApplicationCode/Commands/RicFileHierarchyDialog.h @@ -77,8 +77,7 @@ private: QStringList findFilesInDirs(const QStringList& dirs); - QStringList createNameFilterList(const QString& fileNameFilter, - const QStringList& fileExtensions); + QStringList createFileNameFilterList(); bool pathFilterMatch(const QString& pathFilter, const QString& relPath); From cd5943a39c8de9545a067acef9019a899d9ae284 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Thu, 15 Aug 2019 16:08:38 +0200 Subject: [PATCH 329/396] #4555 Fix errors in filter behavior. Handle double separators Handle */ pathfilter correctly (no recursive search) --- .../Application/Tools/RiaFilePathTools.cpp | 16 +++++ .../Application/Tools/RiaFilePathTools.h | 1 + .../Commands/RicFileHierarchyDialog.cpp | 58 +++++++++---------- .../Commands/RicFileHierarchyDialog.h | 2 +- 4 files changed, 47 insertions(+), 30 deletions(-) diff --git a/ApplicationCode/Application/Tools/RiaFilePathTools.cpp b/ApplicationCode/Application/Tools/RiaFilePathTools.cpp index 0baf49d767..75db3144d9 100644 --- a/ApplicationCode/Application/Tools/RiaFilePathTools.cpp +++ b/ApplicationCode/Application/Tools/RiaFilePathTools.cpp @@ -112,3 +112,19 @@ std::pair RiaFilePathTools::toFolderAndFileName(const QString& return std::make_pair("", absFN); } } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RiaFilePathTools::removeDuplicatePathSeparators(const QString& path) +{ + QString correctedPath = path; + int len; + do + { + len = correctedPath.size(); + correctedPath.replace(QString("%1%1").arg(SEPARATOR), SEPARATOR); + } while (correctedPath.size() != len); + + return correctedPath; +} diff --git a/ApplicationCode/Application/Tools/RiaFilePathTools.h b/ApplicationCode/Application/Tools/RiaFilePathTools.h index e0fd937749..3384fa29e6 100644 --- a/ApplicationCode/Application/Tools/RiaFilePathTools.h +++ b/ApplicationCode/Application/Tools/RiaFilePathTools.h @@ -40,4 +40,5 @@ public: static bool equalPaths(const QString& path1, const QString& path2); static QString canonicalPath(const QString& path); static std::pair toFolderAndFileName(const QString& absFileName); + static QString removeDuplicatePathSeparators(const QString& path); }; diff --git a/ApplicationCode/Commands/RicFileHierarchyDialog.cpp b/ApplicationCode/Commands/RicFileHierarchyDialog.cpp index 928361e8a1..07de5d434a 100644 --- a/ApplicationCode/Commands/RicFileHierarchyDialog.cpp +++ b/ApplicationCode/Commands/RicFileHierarchyDialog.cpp @@ -190,7 +190,7 @@ RicFileHierarchyDialogResult RicFileHierarchyDialog::runRecursiveSearchDialog(QW dialog.resize(DEFAULT_DIALOG_WIDTH, DEFAULT_DIALOG_INIT_HEIGHT); dialog.exec(); - return RicFileHierarchyDialogResult(dialog.result() == QDialog::Accepted, dialog.files(), dialog.rootDir(), dialog.pathFilter(), dialog.fileNameFilter()); + return RicFileHierarchyDialogResult(dialog.result() == QDialog::Accepted, dialog.files(), dialog.rootDirWithEndSeparator(), dialog.pathFilter(), dialog.fileNameFilter()); } //-------------------------------------------------------------------------------------------------- @@ -204,9 +204,10 @@ QStringList RicFileHierarchyDialog::files() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QString RicFileHierarchyDialog::rootDir() const +QString RicFileHierarchyDialog::rootDirWithEndSeparator() const { QString rootDir = RiaFilePathTools::toInternalSeparator(m_rootDir->text().trimmed()); + rootDir = RiaFilePathTools::removeDuplicatePathSeparators(rootDir); return RiaFilePathTools::appendSeparatorIfNo(rootDir); } @@ -215,7 +216,10 @@ QString RicFileHierarchyDialog::rootDir() const //-------------------------------------------------------------------------------------------------- QString RicFileHierarchyDialog::pathFilter() const { - return RiaFilePathTools::toInternalSeparator(m_pathFilter->text().trimmed()).replace(QString("**"), QString("*")); + QString pathFilter = m_pathFilter->text().trimmed(); + pathFilter = RiaFilePathTools::toInternalSeparator(pathFilter); + pathFilter.replace(QString("**"), QString("*")); + return RiaFilePathTools::removeDuplicatePathSeparators(pathFilter); } //-------------------------------------------------------------------------------------------------- @@ -281,7 +285,7 @@ bool RicFileHierarchyDialog::cancelPressed() const void RicFileHierarchyDialog::appendToFileList(const QString& fileName) { QString itemText = fileName; - itemText.remove(0, rootDir().size()); + itemText.remove(0, rootDirWithEndSeparator().size()); QListWidgetItem* item = new QListWidgetItem(QDir::toNativeSeparators(itemText), m_fileList); item->setFlags(item->flags() | Qt::ItemIsUserCheckable); item->setCheckState(Qt::Checked); @@ -350,7 +354,12 @@ QStringList RicFileHierarchyDialog::findMatchingFiles() QStringList dirs; - buildDirectoryListRecursiveSimple(this->rootDir(), this->pathFilter(), &dirs); + QString pathFilter = this->pathFilter(); + if (pathFilter.startsWith(SEPARATOR)) pathFilter.remove(0, 1); + QString rootDir = this->rootDirWithEndSeparator(); + if (rootDir.endsWith(SEPARATOR)) rootDir.chop(1); + + buildDirectoryListRecursiveSimple(rootDir, pathFilter, &dirs); const QStringList& files = findFilesInDirs(dirs); @@ -390,7 +399,7 @@ QStringList RicFileHierarchyDialog::buildDirectoryListRecursive(const QString& c } } - QString currRelPath = RiaFilePathTools::relativePath(rootDir(), currentDir); + QString currRelPath = RiaFilePathTools::relativePath(rootDirWithEndSeparator(), currentDir); if (pathFilterMatch(currPathFilter, currRelPath)) { allDirs.push_back(currentDir); @@ -415,15 +424,12 @@ QStringList RicFileHierarchyDialog::buildDirectoryListRecursive(const QString& c //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicFileHierarchyDialog::buildDirectoryListRecursiveSimple(const QString& currentDir, - const QString& currentPathFilter, +void RicFileHierarchyDialog::buildDirectoryListRecursiveSimple(const QString& currentDirFullPathNoEndSeparator, + const QString& currentPathFilterNoEndSeparator, QStringList* accumulatedDirs) { - QString currDir = currentDir; - QString pathFilter = currentPathFilter; - if (pathFilter.startsWith(SEPARATOR)) pathFilter.remove(0, 1); - if (pathFilter.endsWith(SEPARATOR)) pathFilter.chop(1); - if (currDir.endsWith(SEPARATOR)) currDir.chop(1); + QString currDir = currentDirFullPathNoEndSeparator; + QString pathFilter = currentPathFilterNoEndSeparator; if (cancelPressed()) { @@ -436,15 +442,15 @@ void RicFileHierarchyDialog::buildDirectoryListRecursiveSimple(const QString& cu if (pathFilter.isEmpty()) { - accumulatedDirs->push_back(currentDir); + accumulatedDirs->push_back(currentDirFullPathNoEndSeparator); return; } - QStringList pathFilters = pathFilter.split(SEPARATOR); - QDir qdir(currDir, pathFilters[0], QDir::NoSort, QDir::Dirs | QDir::NoDotAndDotDot); + QStringList pathFilterPartList = pathFilter.split(SEPARATOR); + QDir qdir(currDir, pathFilterPartList[0], QDir::NoSort, QDir::Dirs | QDir::NoDotAndDotDot); QStringList subDirs = qdir.entryList(); - if (pathFilters.size() == 1 && pathFilters[0] == "*") + if (pathFilterPartList.size() == 1 && pathFilterPartList[0] == "*") { accumulatedDirs->push_back(currDir); } @@ -454,13 +460,13 @@ void RicFileHierarchyDialog::buildDirectoryListRecursiveSimple(const QString& cu QString fullPath = qdir.absoluteFilePath(subDir); QString nextPathFilter; - if (pathFilters.size() == 1 && pathFilters[0] == "*") + if (pathFilterPartList.size() == 1 && pathFilterPartList[0] == "*") { nextPathFilter = "*"; } else { - auto pf = pathFilters; + auto pf = pathFilterPartList; pf.removeFirst(); nextPathFilter = pf.join(SEPARATOR); } @@ -545,18 +551,12 @@ void RicFileHierarchyDialog::updateEffectiveFilter() pathFilterText = pathFilterText + "..."; } - QString effFilterText = QString("%1/%2/%3") - .arg(rootDir()) + QString effFilterText = QString("%1%2/%3") + .arg(rootDirWithEndSeparator()) .arg(pathFilterText) .arg(createFileNameFilterList().join("|")); - // Remove duplicate separators - int len; - do - { - len = effFilterText.size(); - effFilterText.replace(QString("%1%1").arg(SEPARATOR), SEPARATOR); - } while (effFilterText.size() != len); + effFilterText = RiaFilePathTools::removeDuplicatePathSeparators(effFilterText); // Present native separators to the user m_effectiveFilter->setText(QDir::toNativeSeparators(effFilterText)); @@ -721,7 +721,7 @@ void RicFileHierarchyDialog::slotDialogOkClicked() const QListWidgetItem* item = m_fileList->item(i); if ((item->flags() & Qt::ItemIsUserCheckable) != 0 && item->checkState()) { - m_files.push_back(rootDir() + RiaFilePathTools::toInternalSeparator(item->text())); + m_files.push_back(rootDirWithEndSeparator() + RiaFilePathTools::toInternalSeparator(item->text())); } } accept(); diff --git a/ApplicationCode/Commands/RicFileHierarchyDialog.h b/ApplicationCode/Commands/RicFileHierarchyDialog.h index a48f3fe918..0732e23bd3 100644 --- a/ApplicationCode/Commands/RicFileHierarchyDialog.h +++ b/ApplicationCode/Commands/RicFileHierarchyDialog.h @@ -55,7 +55,7 @@ public: private: QStringList files() const; - QString rootDir() const; + QString rootDirWithEndSeparator() const; QString pathFilter() const; QString fileNameFilter() const; QStringList fileExtensions() const; From b4285d619d6c972b6b21f0a0728d06d323a80211 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Fri, 16 Aug 2019 10:07:39 +0200 Subject: [PATCH 330/396] #4585 Add Copy-command in the file list --- .../Commands/RicFileHierarchyDialog.cpp | 28 +++++++++++++++++-- .../Commands/RicFileHierarchyDialog.h | 3 ++ 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/ApplicationCode/Commands/RicFileHierarchyDialog.cpp b/ApplicationCode/Commands/RicFileHierarchyDialog.cpp index 07de5d434a..e7728c37cb 100644 --- a/ApplicationCode/Commands/RicFileHierarchyDialog.cpp +++ b/ApplicationCode/Commands/RicFileHierarchyDialog.cpp @@ -21,7 +21,7 @@ #include "ExportCommands/RicSnapshotViewToFileFeature.h" #include "ExportCommands/RicSnapshotFilenameGenerator.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RiaFilePathTools.h" #include "RimEclipseView.h" @@ -45,6 +45,7 @@ #include #include #include +#include #include #include @@ -179,7 +180,7 @@ RicFileHierarchyDialogResult RicFileHierarchyDialog::runRecursiveSearchDialog(QW dialog.setWindowTitle(caption); dialog.m_rootDir->setText(QDir::toNativeSeparators(dir)); - dialog.m_pathFilter->setText(pathFilter); + dialog.m_pathFilter->setText(QDir::toNativeSeparators(pathFilter)); dialog.m_fileFilter->setText(fileNameFilter); dialog.m_fileExtensions = trimLeftStrings(fileExtensions, "."); @@ -190,7 +191,11 @@ RicFileHierarchyDialogResult RicFileHierarchyDialog::runRecursiveSearchDialog(QW dialog.resize(DEFAULT_DIALOG_WIDTH, DEFAULT_DIALOG_INIT_HEIGHT); dialog.exec(); - return RicFileHierarchyDialogResult(dialog.result() == QDialog::Accepted, dialog.files(), dialog.rootDirWithEndSeparator(), dialog.pathFilter(), dialog.fileNameFilter()); + return RicFileHierarchyDialogResult(dialog.result() == QDialog::Accepted, + dialog.files(), + dialog.rootDirWithEndSeparator(), + dialog.pathFilter(), + dialog.fileNameFilter()); } //-------------------------------------------------------------------------------------------------- @@ -605,6 +610,11 @@ void RicFileHierarchyDialog::slotFileListCustomMenuRequested(const QPoint& point QPoint globalPoint = point; QAction* action; + action = new QAction(QIcon(":/Copy.png"), "&Copy", this); + connect(action, SIGNAL(triggered()), SLOT(slotCopyFileItemText())); + menu.addAction(action); + menu.addSeparator(); + action = new QAction("On", this); connect(action, SIGNAL(triggered()), SLOT(slotTurnOnFileListItems())); menu.addAction(action); @@ -663,6 +673,18 @@ void RicFileHierarchyDialog::slotTurnOnFileListItems() } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicFileHierarchyDialog::slotCopyFileItemText() +{ + if (m_fileList->currentItem()) + { + QString relativePathText = m_fileList->currentItem()->text(); + RiaGuiApplication::instance()->clipboard()->setText(relativePathText); + } +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/Commands/RicFileHierarchyDialog.h b/ApplicationCode/Commands/RicFileHierarchyDialog.h index 0732e23bd3..0c6cb0243b 100644 --- a/ApplicationCode/Commands/RicFileHierarchyDialog.h +++ b/ApplicationCode/Commands/RicFileHierarchyDialog.h @@ -89,10 +89,13 @@ private: private slots: void slotFilterChanged(const QString& text); + void slotFileListCustomMenuRequested(const QPoint& point); void slotToggleFileListItems(); void slotTurnOffFileListItems(); void slotTurnOnFileListItems(); + void slotCopyFileItemText(); + void slotFindOrCancelButtonClicked(); void slotDialogOkClicked(); void slotDialogCancelClicked(); From 5179f840b849db4878359fcc675a0e876eed4c7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Fri, 16 Aug 2019 10:53:25 +0200 Subject: [PATCH 331/396] #4586 Add describing tooltips to the dialog --- .../Commands/RicFileHierarchyDialog.cpp | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/ApplicationCode/Commands/RicFileHierarchyDialog.cpp b/ApplicationCode/Commands/RicFileHierarchyDialog.cpp index e7728c37cb..9190c5cceb 100644 --- a/ApplicationCode/Commands/RicFileHierarchyDialog.cpp +++ b/ApplicationCode/Commands/RicFileHierarchyDialog.cpp @@ -110,6 +110,7 @@ RicFileHierarchyDialog::RicFileHierarchyDialog(QWidget* parent) // Set widget properties m_rootDirLabel->setText("Root folder"); m_pathFilterLabel->setText("Path pattern"); + m_fileFilterLabel->setText("File pattern"); m_effectiveFilterLabel->setText("Effective filter"); m_effectiveFilter->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); @@ -155,6 +156,33 @@ RicFileHierarchyDialog::RicFileHierarchyDialog(QWidget* parent) dialogLayout->addWidget(m_buttons); setLayout(dialogLayout); + + QString pathFilterHelpText = + "The path filter uses normal wildcard file globbing, like in any unix shell. \n" + "\n" + "An asterix \"*\" matches any number of any characters, except the path separator.\n" + "A question mark \"?\" matches any single character, except the path separator.\n" + "\n" + "When the filter ends with a single \"*\", however, ResInsight will \n" + "search recursively in all subdirectories from that point.\n" + "This is indicated by \"...\" in the Effective Filter label below."; + + m_pathFilterLabel->setToolTip(pathFilterHelpText); + m_pathFilter->setToolTip(pathFilterHelpText); + + QString fileFilterHelpText = + "The file filter uses normal wildcards, but is not allowed to contain path separators. "; + + m_fileFilterLabel->setToolTip(fileFilterHelpText); + m_fileFilter->setToolTip(fileFilterHelpText); + + QString effectiveFilterHelpText = + "This label displays the complete filter that is being applied. \n" + "The possible \"...\" indicates a complete recursive directory search."; + + m_effectiveFilterLabel->setToolTip(effectiveFilterHelpText); + m_effectiveFilter->setToolTip(effectiveFilterHelpText); + } //-------------------------------------------------------------------------------------------------- From f2e5ccc60df44c50fc6d85975ab42976bb1d0e70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Fri, 16 Aug 2019 11:36:37 +0200 Subject: [PATCH 332/396] #4588 Recursive import Dialog: Fixed tab order, default button, and avoid deleting the result list when editing the filters --- ApplicationCode/Commands/RicFileHierarchyDialog.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ApplicationCode/Commands/RicFileHierarchyDialog.cpp b/ApplicationCode/Commands/RicFileHierarchyDialog.cpp index 9190c5cceb..c031b6c7d5 100644 --- a/ApplicationCode/Commands/RicFileHierarchyDialog.cpp +++ b/ApplicationCode/Commands/RicFileHierarchyDialog.cpp @@ -90,9 +90,9 @@ RicFileHierarchyDialog::RicFileHierarchyDialog(QWidget* parent) m_fileExtensionLabel = new QLabel(); m_effectiveFilterLabel = new QLabel(); m_effectiveFilter = new QLabel(); + m_findOrCancelButton = new QPushButton(); m_fileListLabel = new QLabel(); m_fileList = new QListWidget(); - m_findOrCancelButton = new QPushButton(); m_buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); @@ -126,6 +126,7 @@ RicFileHierarchyDialog::RicFileHierarchyDialog(QWidget* parent) m_browseButton->setFixedWidth(25); m_findOrCancelButton->setText(FIND_BUTTON_FIND_TEXT); m_findOrCancelButton->setFixedWidth(75); + m_findOrCancelButton->setDefault(true); // Define layout QVBoxLayout* dialogLayout = new QVBoxLayout(); @@ -624,9 +625,9 @@ void RicFileHierarchyDialog::warningIfInvalidCharacters() //-------------------------------------------------------------------------------------------------- void RicFileHierarchyDialog::slotFilterChanged(const QString& text) { - clearFileList(); updateEffectiveFilter(); warningIfInvalidCharacters(); + m_findOrCancelButton->setDefault(true); } //-------------------------------------------------------------------------------------------------- @@ -751,6 +752,7 @@ void RicFileHierarchyDialog::slotFindOrCancelButtonClicked() } setOkButtonEnabled(!m_files.isEmpty()); + m_buttons->button(QDialogButtonBox::Ok)->setDefault(true); } else { From 0dde46e4fe3bc6213f73c8aa09e34261c5ae30a1 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 16 Aug 2019 10:52:32 +0200 Subject: [PATCH 333/396] #4575 Summary Plot: Increase minimum zoom window before accepting zoom action --- .../UserInterface/RiuQwtPlotZoomer.h | 30 ++++++++++++++----- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/ApplicationCode/UserInterface/RiuQwtPlotZoomer.h b/ApplicationCode/UserInterface/RiuQwtPlotZoomer.h index 690adc976a..80c80c60a6 100644 --- a/ApplicationCode/UserInterface/RiuQwtPlotZoomer.h +++ b/ApplicationCode/UserInterface/RiuQwtPlotZoomer.h @@ -1,17 +1,17 @@ ///////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2017- Statoil ASA -// +// // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// +// // ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. -// -// See the GNU General Public License at +// +// See the GNU General Public License at // for more details. // ///////////////////////////////////////////////////////////////////////////////// @@ -22,14 +22,28 @@ class RiuQwtPlotZoomer : public QwtPlotZoomer { public: - RiuQwtPlotZoomer(QWidget * canvas, bool doReplot=true) : QwtPlotZoomer(canvas, doReplot) {} + RiuQwtPlotZoomer(QWidget* canvas, bool doReplot = true) + : QwtPlotZoomer(canvas, doReplot) + { + } protected: QSizeF minZoomSize() const override { return QwtPlotZoomer::minZoomSize() / 10.0e6; } + + bool accept(QPolygon& pa) const override + { + if (pa.count() < 2) return false; + + QRect rect = QRect(pa[0], pa[int(pa.count()) - 1]); + rect = rect.normalized(); + + // This size is larger than the minSize value in the base class + const int minSize = 10; + if (rect.width() < minSize && rect.height() < minSize) return false; + + return QwtPlotZoomer::accept(pa); + } }; - - - From 7295ba85337a5466b75d07d0701e09a127b3d5cc Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 16 Aug 2019 12:54:21 +0200 Subject: [PATCH 334/396] #4567 Summary Plot: Set quantity plot title only WOPT and WOPTH --- .../Summary/RimSummaryCurveAutoName.cpp | 4 ++-- .../Summary/RimSummaryPlotNameHelper.cpp | 10 +++------- .../Summary/RimSummaryPlotNameHelper.h | 2 +- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurveAutoName.cpp b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurveAutoName.cpp index b94b181d27..2cd03a7725 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurveAutoName.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurveAutoName.cpp @@ -70,7 +70,7 @@ QString RimSummaryCurveAutoName::curveNameY(const RifEclipseSummaryAddress& summ if (m_vectorName) { - bool skipSubString = nameHelper && nameHelper->isQuantityInTitle(); + bool skipSubString = nameHelper && nameHelper->isPlotDisplayingSingleQuantity(); if (!skipSubString) { text += summaryAddress.quantityName(); @@ -132,7 +132,7 @@ QString RimSummaryCurveAutoName::curveNameX(const RifEclipseSummaryAddress& summ if (m_vectorName) { - bool skipSubString = nameHelper && nameHelper->isQuantityInTitle(); + bool skipSubString = nameHelper && nameHelper->isPlotDisplayingSingleQuantity(); if (!skipSubString) { text += summaryAddress.quantityName(); diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlotNameHelper.cpp b/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlotNameHelper.cpp index e20b651947..ef8f462c80 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlotNameHelper.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlotNameHelper.cpp @@ -152,9 +152,9 @@ QString RimSummaryPlotNameHelper::plotTitle() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool RimSummaryPlotNameHelper::isQuantityInTitle() const +bool RimSummaryPlotNameHelper::isPlotDisplayingSingleQuantity() const { - return !m_titleQuantity.empty(); + return m_analyzer.quantities().size() == 1; } //-------------------------------------------------------------------------------------------------- @@ -236,7 +236,6 @@ void RimSummaryPlotNameHelper::extractPlotTitleSubStrings() { clearTitleSubStrings(); - auto quantities = m_analyzer.quantities(); auto wellNames = m_analyzer.wellNames(); auto wellGroupNames = m_analyzer.wellGroupNames(); auto regions = m_analyzer.regionNumbers(); @@ -245,10 +244,7 @@ void RimSummaryPlotNameHelper::extractPlotTitleSubStrings() if (categories.size() == 1) { - if (quantities.size() == 1) - { - m_titleQuantity = *(quantities.begin()); - } + m_titleQuantity = m_analyzer.quantityNameForTitle(); if (wellNames.size() == 1) { diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlotNameHelper.h b/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlotNameHelper.h index b9c5d372d9..f8148dcdf4 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlotNameHelper.h +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlotNameHelper.h @@ -49,7 +49,7 @@ public: QString plotTitle() const; - bool isQuantityInTitle() const; + bool isPlotDisplayingSingleQuantity() const; bool isWellNameInTitle() const; bool isWellGroupNameInTitle() const; bool isRegionInTitle() const; From c78b435864561c515a187747075857e5e32dfea0 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 16 Aug 2019 14:02:16 +0200 Subject: [PATCH 335/396] #4574 Summary Plot: Do not modify highlight curve change when zooming --- ApplicationCode/UserInterface/RiuQwtPlot.cpp | 17 ++++++++++++++++- ApplicationCode/UserInterface/RiuQwtPlot.h | 7 ++++--- .../UserInterface/RiuQwtPlotZoomer.h | 8 ++++++++ 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/ApplicationCode/UserInterface/RiuQwtPlot.cpp b/ApplicationCode/UserInterface/RiuQwtPlot.cpp index bebfbeeeae..c33e82c0ee 100644 --- a/ApplicationCode/UserInterface/RiuQwtPlot.cpp +++ b/ApplicationCode/UserInterface/RiuQwtPlot.cpp @@ -174,7 +174,22 @@ bool RiuQwtPlot::eventFilter(QObject* watched, QEvent* event) { if(mouseEvent->button() == Qt::LeftButton && mouseEvent->type() == QMouseEvent::MouseButtonRelease) { - selectClosestCurve(mouseEvent->pos()); + bool anyZoomingActive = false; + + if (m_zoomerLeft && m_zoomerLeft->isActiveAndValid()) + { + anyZoomingActive = true; + } + + if (m_zoomerRight && m_zoomerRight->isActiveAndValid()) + { + anyZoomingActive = true; + } + + if (!anyZoomingActive) + { + selectClosestCurve(mouseEvent->pos()); + } } } } diff --git a/ApplicationCode/UserInterface/RiuQwtPlot.h b/ApplicationCode/UserInterface/RiuQwtPlot.h index 065963219f..d19e66e19a 100644 --- a/ApplicationCode/UserInterface/RiuQwtPlot.h +++ b/ApplicationCode/UserInterface/RiuQwtPlot.h @@ -28,9 +28,10 @@ #include +class RiuQwtPlotZoomer; + class QwtPlotCurve; class QwtPlotGrid; -class QwtPlotZoomer; class QwtInterval; class QwtPicker; class QwtPlotMarker; @@ -82,8 +83,8 @@ private: }; caf::PdmPointer m_ownerViewWindow; - QPointer m_zoomerLeft; - QPointer m_zoomerRight; + QPointer m_zoomerLeft; + QPointer m_zoomerRight; std::map m_originalCurveColors; std::map m_originalZValues; diff --git a/ApplicationCode/UserInterface/RiuQwtPlotZoomer.h b/ApplicationCode/UserInterface/RiuQwtPlotZoomer.h index 80c80c60a6..983211b52e 100644 --- a/ApplicationCode/UserInterface/RiuQwtPlotZoomer.h +++ b/ApplicationCode/UserInterface/RiuQwtPlotZoomer.h @@ -27,6 +27,14 @@ public: { } + bool isActiveAndValid() const + { + if (!isActive()) return false; + + auto currentSelection = selection(); + return accept(currentSelection); + } + protected: QSizeF minZoomSize() const override { From c5542463aa165485c451ca35ebcdbccfcb99c960 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 16 Aug 2019 14:37:34 +0200 Subject: [PATCH 336/396] #4581 Summary Plot: Add isHistoryQuantity --- .../FileInterface/RifEclipseSummaryAddress.cpp | 10 ++++++++++ .../FileInterface/RifEclipseSummaryAddress.h | 1 + .../Summary/RimEnsembleCurveSetCollection.cpp | 5 ++--- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/ApplicationCode/FileInterface/RifEclipseSummaryAddress.cpp b/ApplicationCode/FileInterface/RifEclipseSummaryAddress.cpp index 6169b39bf9..c0a2670f5c 100644 --- a/ApplicationCode/FileInterface/RifEclipseSummaryAddress.cpp +++ b/ApplicationCode/FileInterface/RifEclipseSummaryAddress.cpp @@ -537,6 +537,16 @@ bool RifEclipseSummaryAddress::isDependentOnWellName(SummaryVarCategory category return false; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RifEclipseSummaryAddress::isHistoryQuantity() const +{ + const std::string historyIdentifier = "H"; + + return RiaStdStringTools::endsWith(m_quantityName, historyIdentifier); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/FileInterface/RifEclipseSummaryAddress.h b/ApplicationCode/FileInterface/RifEclipseSummaryAddress.h index 2a017cb7c2..2a5db418bb 100644 --- a/ApplicationCode/FileInterface/RifEclipseSummaryAddress.h +++ b/ApplicationCode/FileInterface/RifEclipseSummaryAddress.h @@ -150,6 +150,7 @@ public: SummaryVarCategory category() const { return m_variableCategory; } const std::string& quantityName() const { return m_quantityName; } + bool isHistoryQuantity() const; int regionNumber() const { return m_regionNumber; } int regionNumber2() const { return m_regionNumber2; } diff --git a/ApplicationCode/ProjectDataModel/Summary/RimEnsembleCurveSetCollection.cpp b/ApplicationCode/ProjectDataModel/Summary/RimEnsembleCurveSetCollection.cpp index 0d6fbd62a7..2dab623ca0 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimEnsembleCurveSetCollection.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimEnsembleCurveSetCollection.cpp @@ -245,18 +245,17 @@ std::vector RimEnsembleCurveSetCollection::curveSetsForSou { // Add corresponding history/summary curve with or without H - const std::string historyIdentifier = "H"; std::string quantity = m_curveSetForSourceStepping->summaryAddress().quantityName(); std::string candidateName; - if (RiaStdStringTools::endsWith(quantity, historyIdentifier)) + if (m_curveSetForSourceStepping->summaryAddress().isHistoryQuantity()) { candidateName = quantity.substr(0, quantity.size() - 1); } else { - candidateName = quantity + historyIdentifier; + candidateName = quantity + "H"; } for (const auto& c : curveSets()) From c30b34511b45b149d4a5b2a26eb56995a2674f9b Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 16 Aug 2019 14:40:12 +0200 Subject: [PATCH 337/396] #4581 Summary Plot: Rename to setCurveAppearanceFromCaseType() --- .../ProjectDataModel/Summary/RimSummaryCurve.cpp | 9 +++------ .../ProjectDataModel/Summary/RimSummaryCurve.h | 2 +- .../Summary/RimSummaryCurveAppearanceCalculator.cpp | 5 +---- .../Summary/RimSummaryPlotSourceStepping.cpp | 3 +-- 4 files changed, 6 insertions(+), 13 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurve.cpp b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurve.cpp index 9b07f1e12b..a2b8bd674a 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurve.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurve.cpp @@ -799,7 +799,7 @@ QString RimSummaryCurve::curveExportDescription(const RifEclipseSummaryAddress& //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimSummaryCurve::forceUpdateCurveAppearanceFromCaseType() +void RimSummaryCurve::setCurveAppearanceFromCaseType() { if (m_yValuesSummaryCase) { @@ -811,11 +811,8 @@ void RimSummaryCurve::forceUpdateCurveAppearanceFromCaseType() { setSymbol(RiuQwtSymbol::SYMBOL_XCROSS); } - } - else - { - setLineStyle(RiuQwtPlotCurve::STYLE_SOLID); - setSymbol(RiuQwtSymbol::SYMBOL_NONE); + + return; } } } diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurve.h b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurve.h index b919d22b3e..3360e4af95 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurve.h +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurve.h @@ -79,7 +79,7 @@ public: void applyCurveAutoNameSettings(const RimSummaryCurveAutoName& autoNameSettings); QString curveExportDescription(const RifEclipseSummaryAddress& address = RifEclipseSummaryAddress()) const override; - void forceUpdateCurveAppearanceFromCaseType(); + void setCurveAppearanceFromCaseType(); void markCachedDataForPurge(); diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurveAppearanceCalculator.cpp b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurveAppearanceCalculator.cpp index d0a99f3ab4..c5c2dfad16 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurveAppearanceCalculator.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurveAppearanceCalculator.cpp @@ -357,10 +357,7 @@ void RimSummaryCurveAppearanceCalculator::setupCurveLook(RimSummaryCurve* curve) curve->setColor(gradeColor(m_currentCurveBaseColor, m_currentCurveGradient)); - if ( curve->summaryCaseY()->isObservedData() ) - { - curve->forceUpdateCurveAppearanceFromCaseType(); - } + curve->setCurveAppearanceFromCaseType(); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlotSourceStepping.cpp b/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlotSourceStepping.cpp index 62fc50d1f1..ed6410a891 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlotSourceStepping.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlotSourceStepping.cpp @@ -402,9 +402,8 @@ void RimSummaryPlotSourceStepping::fieldChangedByUi(const caf::PdmFieldHandle* c { if (previousCase == curve->summaryCaseY()) { - bool doSetAppearance = curve->summaryCaseY()->isObservedData() != m_summaryCase->isObservedData(); curve->setSummaryCaseY(m_summaryCase); - if (doSetAppearance) curve->forceUpdateCurveAppearanceFromCaseType(); + curve->setCurveAppearanceFromCaseType(); } } From dab424ace3c89652aa4df2ef6babf5ba91177eee Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 16 Aug 2019 15:10:32 +0200 Subject: [PATCH 338/396] #4590 Preferences : Improve definition and use of tab names in dialog --- .../Application/RiaPreferences.cpp | 82 +++++++++++++++---- ApplicationCode/Application/RiaPreferences.h | 10 ++- 2 files changed, 75 insertions(+), 17 deletions(-) diff --git a/ApplicationCode/Application/RiaPreferences.cpp b/ApplicationCode/Application/RiaPreferences.cpp index cd9bab914e..3c5dfb4a82 100644 --- a/ApplicationCode/Application/RiaPreferences.cpp +++ b/ApplicationCode/Application/RiaPreferences.cpp @@ -157,15 +157,6 @@ RiaPreferences::RiaPreferences(void) CAF_PDM_InitFieldNoDefault(&m_readerSettings, "readerSettings", "Reader Settings", "", "", ""); m_readerSettings = new RifReaderSettings; - - m_tabNames << "General"; - m_tabNames << "Eclipse"; - m_tabNames << "Scripting"; - m_tabNames << "Export"; - if (RiaApplication::enableDevelopmentFeatures()) - { - m_tabNames << "System"; - } } //-------------------------------------------------------------------------------------------------- @@ -233,7 +224,7 @@ void RiaPreferences::defineEditorAttribute(const caf::PdmFieldHandle* field, QSt //-------------------------------------------------------------------------------------------------- void RiaPreferences::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) { - if (uiConfigName == m_tabNames[0]) + if (uiConfigName == RiaPreferences::tabNameGeneral()) { caf::PdmUiGroup* colorGroup = uiOrdering.addNewGroup("Default Colors"); colorGroup->add(&defaultViewerBackgroundColor); @@ -260,7 +251,7 @@ void RiaPreferences::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& otherGroup->add(&showLasCurveWithoutTvdWarning); otherGroup->add(&holoLensDisableCertificateVerification); } - else if (uiConfigName == m_tabNames[1]) + else if (uiConfigName == RiaPreferences::tabNameEclipse()) { caf::PdmUiGroup* newCaseBehaviourGroup = uiOrdering.addNewGroup("Behavior When Loading Data"); newCaseBehaviourGroup->add(&autocomputeDepthRelatedProperties); @@ -291,7 +282,7 @@ void RiaPreferences::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& summaryPlotsGroup->add(&defaultSummaryCurvesTextFilter); } } - else if (uiConfigName == m_tabNames[2]) + else if (uiConfigName == RiaPreferences::tabNameScripting()) { caf::PdmUiGroup* octaveGroup = uiOrdering.addNewGroup("Octave"); octaveGroup->add(&octaveExecutable); @@ -307,11 +298,11 @@ void RiaPreferences::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& scriptGroup->add(&scriptDirectories); scriptGroup->add(&scriptEditorExecutable); } - else if (uiConfigName == m_tabNames[3]) + else if (uiConfigName == RiaPreferences::tabNameExport()) { uiOrdering.add(&csvTextExportFieldSeparator); } - else if (RiaApplication::enableDevelopmentFeatures() && uiConfigName == m_tabNames[4]) + else if (RiaApplication::enableDevelopmentFeatures() && uiConfigName == RiaPreferences::tabNameSystem()) { uiOrdering.add(&m_appendClassNameToUiText); uiOrdering.add(&m_appendFieldKeywordToToolTipText); @@ -369,12 +360,73 @@ void RiaPreferences::initAfterRead() } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RiaPreferences::tabNameGeneral() +{ + return "General"; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RiaPreferences::tabNameEclipse() +{ + return "Eclipse"; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RiaPreferences::tabNameEclipseSummary() +{ + return "Summary"; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RiaPreferences::tabNameScripting() +{ + return "Scripting"; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RiaPreferences::tabNameExport() +{ + return "Export"; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RiaPreferences::tabNameSystem() +{ + return "System"; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QStringList RiaPreferences::tabNames() { - return m_tabNames; + QStringList names; + + names << tabNameGeneral(); + names << tabNameEclipse(); + names << tabNameEclipseSummary(); + names << tabNameScripting(); + names << tabNameExport(); + + if (RiaApplication::enableDevelopmentFeatures()) + { + names << tabNameSystem(); + } + + return names; } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/Application/RiaPreferences.h b/ApplicationCode/Application/RiaPreferences.h index 7a412e2439..254b7d1866 100644 --- a/ApplicationCode/Application/RiaPreferences.h +++ b/ApplicationCode/Application/RiaPreferences.h @@ -121,6 +121,14 @@ protected: QList calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool * useOptionsOnly) override; void initAfterRead() override; +private: + static QString tabNameGeneral(); + static QString tabNameEclipse(); + static QString tabNameEclipseSummary(); + static QString tabNameScripting(); + static QString tabNameExport(); + static QString tabNameSystem(); + private: caf::PdmChildField m_readerSettings; caf::PdmField m_appendClassNameToUiText; @@ -131,6 +139,4 @@ private: caf::PdmField m_showTestToolbar; caf::PdmField m_includeFractureDebugInfoFile; caf::PdmField m_holoLensExportFolder; - QStringList m_tabNames; - }; From 4cb1c9facafa976a2e508d22aa0f046d0f87253e Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 16 Aug 2019 15:41:58 +0200 Subject: [PATCH 339/396] #4581 Summary Plot: Add default curve style to preferences for history curves --- .../Application/RiaPreferences.cpp | 22 ++++++++---- ApplicationCode/Application/RiaPreferences.h | 11 +++++- .../Summary/RimSummaryCurve.cpp | 35 ++++++++++++++----- 3 files changed, 53 insertions(+), 15 deletions(-) diff --git a/ApplicationCode/Application/RiaPreferences.cpp b/ApplicationCode/Application/RiaPreferences.cpp index 3c5dfb4a82..7e1b2cd605 100644 --- a/ApplicationCode/Application/RiaPreferences.cpp +++ b/ApplicationCode/Application/RiaPreferences.cpp @@ -44,7 +44,16 @@ namespace caf addItem(RiaPreferences::NOT_IMPORT, "NOT_IMPORT", "Skip"); setDefault(RiaPreferences::IMPORT); } -} + + template<> + void RiaPreferences::SummaryHistoryCurveStyleModeType::setUp() + { + addItem(RiaPreferences::SYMBOLS, "SYMBOLS", "Symbols"); + addItem(RiaPreferences::LINES, "LINES", "Lines"); + addItem(RiaPreferences::SYMBOLS_AND_LINES, "SYMBOLS_AND_LINES", "Symbols and Lines"); + setDefault(RiaPreferences::SYMBOLS); + } + } CAF_PDM_SOURCE_INIT(RiaPreferences, "RiaPreferences"); @@ -141,6 +150,7 @@ RiaPreferences::RiaPreferences(void) CAF_PDM_InitField(&gridImportMode, "gridImportMode", SummaryRestartFilesImportModeType(RiaPreferences::NOT_IMPORT), "Default Grid Import Option", "", "", ""); CAF_PDM_InitField(&summaryEnsembleImportMode, "summaryEnsembleImportMode", SummaryRestartFilesImportModeType(RiaPreferences::IMPORT), "Default Ensemble Summary Import Option", "", "", ""); + CAF_PDM_InitField(&defaultSummaryHistoryCurveStyle, "defaultSummaryHistoryCurveStyle", SummaryHistoryCurveStyleModeType(RiaPreferences::SYMBOLS), "Default Curve Style for History Vectors", "", "", ""); CAF_PDM_InitField(&defaultSummaryCurvesTextFilter, "defaultSummaryCurvesTextFilter", QString("FOPT"), "Default Summary Curves", "", "Semicolon separated list of filters used to create curves in new summary plots", ""); CAF_PDM_InitFieldNoDefault(&m_holoLensExportFolder, "holoLensExportFolder", "HoloLens Export Folder", "", "", ""); @@ -276,11 +286,11 @@ void RiaPreferences::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& caf::PdmUiGroup* group = restartBehaviourGroup->addNewGroup("Origin Ensemble Summary Files"); group->add(&summaryEnsembleImportMode); } - - { - caf::PdmUiGroup* summaryPlotsGroup = uiOrdering.addNewGroup("Summary Plots"); - summaryPlotsGroup->add(&defaultSummaryCurvesTextFilter); - } + } + else if (uiConfigName == RiaPreferences::tabNameEclipseSummary()) + { + uiOrdering.add(&defaultSummaryCurvesTextFilter); + uiOrdering.add(&defaultSummaryHistoryCurveStyle); } else if (uiConfigName == RiaPreferences::tabNameScripting()) { diff --git a/ApplicationCode/Application/RiaPreferences.h b/ApplicationCode/Application/RiaPreferences.h index 254b7d1866..8677be6a10 100644 --- a/ApplicationCode/Application/RiaPreferences.h +++ b/ApplicationCode/Application/RiaPreferences.h @@ -48,6 +48,14 @@ public: typedef caf::AppEnum SummaryRestartFilesImportModeType; typedef RiaFontCache::FontSizeType FontSizeType; + enum SummaryHistoryCurveStyleMode + { + SYMBOLS, + LINES, + SYMBOLS_AND_LINES + }; + typedef caf::AppEnum SummaryHistoryCurveStyleModeType; + RiaPreferences(void); ~RiaPreferences(void) override; @@ -110,7 +118,8 @@ public: // Pdm Fields caf::PdmField gridImportMode; caf::PdmField summaryEnsembleImportMode; - caf::PdmField defaultSummaryCurvesTextFilter; + caf::PdmField defaultSummaryCurvesTextFilter; + caf::PdmField defaultSummaryHistoryCurveStyle; caf::PdmField holoLensDisableCertificateVerification; caf::PdmField csvTextExportFieldSeparator; diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurve.cpp b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurve.cpp index a2b8bd674a..155b0c7c7d 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurve.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurve.cpp @@ -18,13 +18,13 @@ #include "RimSummaryCurve.h" -#include "RiaGuiApplication.h" #include "RiaDefines.h" +#include "RiaGuiApplication.h" +#include "RiaPreferences.h" +#include "RiaTimeHistoryCurveMerger.h" #include "RifReaderEclipseSummary.h" -#include "RiaTimeHistoryCurveMerger.h" - #include "RimEclipseResultCase.h" #include "RimEnsembleCurveSet.h" #include "RimEnsembleCurveSetCollection.h" @@ -806,15 +806,34 @@ void RimSummaryCurve::setCurveAppearanceFromCaseType() if (m_yValuesSummaryCase->isObservedData()) { setLineStyle(RiuQwtPlotCurve::STYLE_NONE); - - if (symbol() == RiuQwtSymbol::SYMBOL_NONE) - { - setSymbol(RiuQwtSymbol::SYMBOL_XCROSS); - } + setSymbol(RiuQwtSymbol::SYMBOL_XCROSS); return; } } + + if (m_yValuesCurveVariable && m_yValuesCurveVariable->address().isHistoryQuantity()) + { + RiaPreferences* prefs = RiaApplication::instance()->preferences(); + + if (prefs->defaultSummaryHistoryCurveStyle() == RiaPreferences::SYMBOLS) + { + setSymbol(RiuQwtSymbol::SYMBOL_XCROSS); + setLineStyle(RiuQwtPlotCurve::STYLE_NONE); + } + else if (prefs->defaultSummaryHistoryCurveStyle() == RiaPreferences::SYMBOLS_AND_LINES) + { + setSymbol(RiuQwtSymbol::SYMBOL_XCROSS); + setLineStyle(RiuQwtPlotCurve::STYLE_SOLID); + } + else if (prefs->defaultSummaryHistoryCurveStyle() == RiaPreferences::LINES) + { + setSymbol(RiuQwtSymbol::SYMBOL_NONE); + setLineStyle(RiuQwtPlotCurve::STYLE_SOLID); + } + + return; + } } //-------------------------------------------------------------------------------------------------- From 4d8ce1e399e2d6ef77cd2da9aaad1d5633e76083 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 19 Aug 2019 07:56:43 +0200 Subject: [PATCH 340/396] #4483 Summary Plot Stepping: Hide not relevant controls from property editor --- .../Summary/RimSummaryPlotSourceStepping.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlotSourceStepping.cpp b/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlotSourceStepping.cpp index ed6410a891..402f93bbf0 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlotSourceStepping.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlotSourceStepping.cpp @@ -729,6 +729,7 @@ std::set RimSummaryPlotSourceStepping::summaryCasesCurveCollect //-------------------------------------------------------------------------------------------------- std::vector RimSummaryPlotSourceStepping::computeVisibleFieldsAndSetFieldVisibility() { + // Required to set all stepping controls hidden, as they show up in the property editor when selecting a plot m_summaryCase.uiCapability()->setUiHidden(true); m_includeEnsembleCasesForCaseStepping.uiCapability()->setUiHidden(true); m_wellName.uiCapability()->setUiHidden(true); @@ -736,6 +737,9 @@ std::vector RimSummaryPlotSourceStepping::computeVisibleFi m_region.uiCapability()->setUiHidden(true); m_quantity.uiCapability()->setUiHidden(true); m_ensemble.uiCapability()->setUiHidden(true); + m_cellBlock.uiCapability()->setUiHidden(true); + m_segment.uiCapability()->setUiHidden(true); + m_completion.uiCapability()->setUiHidden(true); std::vector fields; @@ -834,6 +838,7 @@ std::vector RimSummaryPlotSourceStepping::computeVisibleFi { QString txt = QString::number(*(analyzer.wellSegmentNumbers(m_wellName().toStdString()).begin())); m_segment = txt; + m_segment.uiCapability()->setUiHidden(false); fieldsCommonForAllCurves.push_back(&m_segment); } @@ -842,6 +847,7 @@ std::vector RimSummaryPlotSourceStepping::computeVisibleFi { QString txt = QString::fromStdString(*(analyzer.blocks().begin())); m_cellBlock = txt; + m_cellBlock.uiCapability()->setUiHidden(false); fieldsCommonForAllCurves.push_back(&m_cellBlock); } @@ -850,6 +856,7 @@ std::vector RimSummaryPlotSourceStepping::computeVisibleFi { QString txt = QString::fromStdString(*(analyzer.wellCompletions(m_wellName().toStdString()).begin())); m_completion = txt; + m_completion.uiCapability()->setUiHidden(false); fieldsCommonForAllCurves.push_back(&m_completion); } From 824ec5cef6bbab6c32d896ef7e4008aab34ff485 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Thu, 15 Aug 2019 08:07:43 +0200 Subject: [PATCH 341/396] Python: Rename example directory to PythonExamples * This is so that when we add the folder to the Script Path it will look more sensible to the user. --- .../GrpcInterface/CMakeLists.cmake | 36 +++++++++---------- .../{examples => PythonExamples}/AllCases.py | 0 .../{examples => PythonExamples}/AppInfo.py | 0 .../CaseGridGroup.py | 0 .../CaseInfoStreamingExample.py | 0 .../CommandExample.py | 0 .../ErrorHandling.py | 0 .../GridInformation.py | 0 .../InputPropTestAsync.py | 0 .../InputPropTestSync.py | 0 .../InstanceExample.py | 0 .../SelectedCases.py | 0 .../SetCellResult.py | 0 .../SetFlowDiagnosticsResult.py | 0 .../SetGridProperties.py | 0 .../SoilAverageAsync.py | 0 .../SoilAverageNoComm.py | 0 .../SoilAverageSync.py | 0 .../SoilPorvAsync.py | 14 +++++--- .../SoilPorvSync.py | 6 ++++ 20 files changed, 33 insertions(+), 23 deletions(-) rename ApplicationCode/GrpcInterface/Python/rips/{examples => PythonExamples}/AllCases.py (100%) rename ApplicationCode/GrpcInterface/Python/rips/{examples => PythonExamples}/AppInfo.py (100%) rename ApplicationCode/GrpcInterface/Python/rips/{examples => PythonExamples}/CaseGridGroup.py (100%) rename ApplicationCode/GrpcInterface/Python/rips/{examples => PythonExamples}/CaseInfoStreamingExample.py (100%) rename ApplicationCode/GrpcInterface/Python/rips/{examples => PythonExamples}/CommandExample.py (100%) rename ApplicationCode/GrpcInterface/Python/rips/{examples => PythonExamples}/ErrorHandling.py (100%) rename ApplicationCode/GrpcInterface/Python/rips/{examples => PythonExamples}/GridInformation.py (100%) rename ApplicationCode/GrpcInterface/Python/rips/{examples => PythonExamples}/InputPropTestAsync.py (100%) rename ApplicationCode/GrpcInterface/Python/rips/{examples => PythonExamples}/InputPropTestSync.py (100%) rename ApplicationCode/GrpcInterface/Python/rips/{examples => PythonExamples}/InstanceExample.py (100%) rename ApplicationCode/GrpcInterface/Python/rips/{examples => PythonExamples}/SelectedCases.py (100%) rename ApplicationCode/GrpcInterface/Python/rips/{examples => PythonExamples}/SetCellResult.py (100%) rename ApplicationCode/GrpcInterface/Python/rips/{examples => PythonExamples}/SetFlowDiagnosticsResult.py (100%) rename ApplicationCode/GrpcInterface/Python/rips/{examples => PythonExamples}/SetGridProperties.py (100%) rename ApplicationCode/GrpcInterface/Python/rips/{examples => PythonExamples}/SoilAverageAsync.py (100%) rename ApplicationCode/GrpcInterface/Python/rips/{examples => PythonExamples}/SoilAverageNoComm.py (100%) rename ApplicationCode/GrpcInterface/Python/rips/{examples => PythonExamples}/SoilAverageSync.py (100%) rename ApplicationCode/GrpcInterface/Python/rips/{examples => PythonExamples}/SoilPorvAsync.py (71%) rename ApplicationCode/GrpcInterface/Python/rips/{examples => PythonExamples}/SoilPorvSync.py (80%) diff --git a/ApplicationCode/GrpcInterface/CMakeLists.cmake b/ApplicationCode/GrpcInterface/CMakeLists.cmake index cd3a7258b3..89d6ab410a 100644 --- a/ApplicationCode/GrpcInterface/CMakeLists.cmake +++ b/ApplicationCode/GrpcInterface/CMakeLists.cmake @@ -169,24 +169,24 @@ if (RESINSIGHT_GRPC_PYTHON_EXECUTABLE) "rips/Instance.py" "rips/PdmObject.py" "rips/View.py" - "rips/examples/InstanceExample.py" - "rips/examples/CommandExample.py" - "rips/examples/CaseGridGroup.py" - "rips/examples/CaseInfoStreamingExample.py" - "rips/examples/ErrorHandling.py" - "rips/examples/SoilPorvAsync.py" - "rips/examples/SoilPorvSync.py" - "rips/examples/SelectedCases.py" - "rips/examples/AllCases.py" - "rips/examples/SetGridProperties.py" - "rips/examples/SetCellResult.py" - "rips/examples/SetFlowDiagnosticsResult.py" - "rips/examples/GridInformation.py" - "rips/examples/InputPropTestSync.py" - "rips/examples/InputPropTestAsync.py" - "rips/examples/SoilAverageAsync.py" - "rips/examples/SoilAverageSync.py" - "rips/examples/SoilAverageNoComm.py" + "rips/PythonExamples/InstanceExample.py" + "rips/PythonExamples/CommandExample.py" + "rips/PythonExamples/CaseGridGroup.py" + "rips/PythonExamples/CaseInfoStreamingExample.py" + "rips/PythonExamples/ErrorHandling.py" + "rips/PythonExamples/SoilPorvAsync.py" + "rips/PythonExamples/SoilPorvSync.py" + "rips/PythonExamples/SelectedCases.py" + "rips/PythonExamples/AllCases.py" + "rips/PythonExamples/SetGridProperties.py" + "rips/PythonExamples/SetCellResult.py" + "rips/PythonExamples/SetFlowDiagnosticsResult.py" + "rips/PythonExamples/GridInformation.py" + "rips/PythonExamples/InputPropTestSync.py" + "rips/PythonExamples/InputPropTestAsync.py" + "rips/PythonExamples/SoilAverageAsync.py" + "rips/PythonExamples/SoilAverageSync.py" + "rips/PythonExamples/SoilAverageNoComm.py" "rips/tests/test_cases.py" "rips/tests/test_commands.py" "rips/tests/test_grids.py" diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/AllCases.py b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/AllCases.py similarity index 100% rename from ApplicationCode/GrpcInterface/Python/rips/examples/AllCases.py rename to ApplicationCode/GrpcInterface/Python/rips/PythonExamples/AllCases.py diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/AppInfo.py b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/AppInfo.py similarity index 100% rename from ApplicationCode/GrpcInterface/Python/rips/examples/AppInfo.py rename to ApplicationCode/GrpcInterface/Python/rips/PythonExamples/AppInfo.py diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/CaseGridGroup.py b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/CaseGridGroup.py similarity index 100% rename from ApplicationCode/GrpcInterface/Python/rips/examples/CaseGridGroup.py rename to ApplicationCode/GrpcInterface/Python/rips/PythonExamples/CaseGridGroup.py diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/CaseInfoStreamingExample.py b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/CaseInfoStreamingExample.py similarity index 100% rename from ApplicationCode/GrpcInterface/Python/rips/examples/CaseInfoStreamingExample.py rename to ApplicationCode/GrpcInterface/Python/rips/PythonExamples/CaseInfoStreamingExample.py diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/CommandExample.py b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/CommandExample.py similarity index 100% rename from ApplicationCode/GrpcInterface/Python/rips/examples/CommandExample.py rename to ApplicationCode/GrpcInterface/Python/rips/PythonExamples/CommandExample.py diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/ErrorHandling.py b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/ErrorHandling.py similarity index 100% rename from ApplicationCode/GrpcInterface/Python/rips/examples/ErrorHandling.py rename to ApplicationCode/GrpcInterface/Python/rips/PythonExamples/ErrorHandling.py diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/GridInformation.py b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/GridInformation.py similarity index 100% rename from ApplicationCode/GrpcInterface/Python/rips/examples/GridInformation.py rename to ApplicationCode/GrpcInterface/Python/rips/PythonExamples/GridInformation.py diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/InputPropTestAsync.py b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/InputPropTestAsync.py similarity index 100% rename from ApplicationCode/GrpcInterface/Python/rips/examples/InputPropTestAsync.py rename to ApplicationCode/GrpcInterface/Python/rips/PythonExamples/InputPropTestAsync.py diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/InputPropTestSync.py b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/InputPropTestSync.py similarity index 100% rename from ApplicationCode/GrpcInterface/Python/rips/examples/InputPropTestSync.py rename to ApplicationCode/GrpcInterface/Python/rips/PythonExamples/InputPropTestSync.py diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/InstanceExample.py b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/InstanceExample.py similarity index 100% rename from ApplicationCode/GrpcInterface/Python/rips/examples/InstanceExample.py rename to ApplicationCode/GrpcInterface/Python/rips/PythonExamples/InstanceExample.py diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/SelectedCases.py b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/SelectedCases.py similarity index 100% rename from ApplicationCode/GrpcInterface/Python/rips/examples/SelectedCases.py rename to ApplicationCode/GrpcInterface/Python/rips/PythonExamples/SelectedCases.py diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/SetCellResult.py b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/SetCellResult.py similarity index 100% rename from ApplicationCode/GrpcInterface/Python/rips/examples/SetCellResult.py rename to ApplicationCode/GrpcInterface/Python/rips/PythonExamples/SetCellResult.py diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/SetFlowDiagnosticsResult.py b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/SetFlowDiagnosticsResult.py similarity index 100% rename from ApplicationCode/GrpcInterface/Python/rips/examples/SetFlowDiagnosticsResult.py rename to ApplicationCode/GrpcInterface/Python/rips/PythonExamples/SetFlowDiagnosticsResult.py diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/SetGridProperties.py b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/SetGridProperties.py similarity index 100% rename from ApplicationCode/GrpcInterface/Python/rips/examples/SetGridProperties.py rename to ApplicationCode/GrpcInterface/Python/rips/PythonExamples/SetGridProperties.py diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/SoilAverageAsync.py b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/SoilAverageAsync.py similarity index 100% rename from ApplicationCode/GrpcInterface/Python/rips/examples/SoilAverageAsync.py rename to ApplicationCode/GrpcInterface/Python/rips/PythonExamples/SoilAverageAsync.py diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/SoilAverageNoComm.py b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/SoilAverageNoComm.py similarity index 100% rename from ApplicationCode/GrpcInterface/Python/rips/examples/SoilAverageNoComm.py rename to ApplicationCode/GrpcInterface/Python/rips/PythonExamples/SoilAverageNoComm.py diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/SoilAverageSync.py b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/SoilAverageSync.py similarity index 100% rename from ApplicationCode/GrpcInterface/Python/rips/examples/SoilAverageSync.py rename to ApplicationCode/GrpcInterface/Python/rips/PythonExamples/SoilAverageSync.py diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/SoilPorvAsync.py b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/SoilPorvAsync.py similarity index 71% rename from ApplicationCode/GrpcInterface/Python/rips/examples/SoilPorvAsync.py rename to ApplicationCode/GrpcInterface/Python/rips/PythonExamples/SoilPorvAsync.py index 8620a25dae..c9ba4b9e18 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/examples/SoilPorvAsync.py +++ b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/SoilPorvAsync.py @@ -1,17 +1,18 @@ import rips +import time +import numpy as np def createResult(soilChunks, porvChunks): for (soilChunk, porvChunk) in zip(soilChunks, porvChunks): resultChunk = [] number = 0 - for (soil, porv) in zip(soilChunk.values, porvChunk.values): - resultChunk.append(soil * porv) - number += 1 - yield resultChunk - + npSoilChunk = np.array(soilChunk.values) + npPorvChunk = np.array(porvChunk.values) + yield npSoilChunk + npPorvChunk resInsight = rips.Instance.find() +start = time.time() case = resInsight.project.case(id=0) timeStepInfo = case.timeSteps() @@ -25,4 +26,7 @@ for i in range (0, len(timeStepInfo)): input_iterator = createResult(soilChunks, iter(porvArray)) case.properties.setActiveCellPropertyAsync(input_iterator, 'GENERATED', 'SOILPORVAsync', i) +end = time.time() +print("Time elapsed: ", end - start) + print("Transferred all results back") \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/Python/rips/examples/SoilPorvSync.py b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/SoilPorvSync.py similarity index 80% rename from ApplicationCode/GrpcInterface/Python/rips/examples/SoilPorvSync.py rename to ApplicationCode/GrpcInterface/Python/rips/PythonExamples/SoilPorvSync.py index f3f25313d7..859a4f92bc 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/examples/SoilPorvSync.py +++ b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/SoilPorvSync.py @@ -1,6 +1,8 @@ import rips +import time resInsight = rips.Instance.find() +start = time.time() case = resInsight.project.case(id=0) porvResults = case.properties.activeCellProperty('STATIC_NATIVE', 'PORV', 0) @@ -13,4 +15,8 @@ for i in range (0, len(timeStepInfo)): results.append(soil * porv) case.properties.setActiveCellProperty(results, 'GENERATED', 'SOILPORVSync', i) + +end = time.time() +print("Time elapsed: ", end - start) + print("Transferred all results back") \ No newline at end of file From e58da136e3e616a18774c2dc05ba2ea95b7b93e8 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Mon, 19 Aug 2019 09:37:42 +0200 Subject: [PATCH 342/396] #2082 Support custom date time format (#4594) * #2082 Support custom date time format * Clang-format --- .../Application/RiaPreferences.cpp | 53 +++ ApplicationCode/Application/RiaPreferences.h | 9 +- .../Application/Tools/RiaQDateTimeTools.cpp | 76 ++++ .../Application/Tools/RiaQDateTimeTools.h | 30 ++ .../Summary/RimSummaryPlot.cpp | 5 +- .../Summary/RimSummaryTimeAxisProperties.cpp | 396 +++++++++++++----- .../Summary/RimSummaryTimeAxisProperties.h | 31 +- .../RiuFlowCharacteristicsPlot.cpp | 6 +- .../UserInterface/RiuQwtPlotTools.cpp | 71 +++- .../UserInterface/RiuQwtPlotTools.h | 9 +- .../UserInterface/RiuResultQwtPlot.cpp | 5 +- .../UserInterface/RiuSummaryQwtPlot.cpp | 13 +- .../UserInterface/RiuSummaryQwtPlot.h | 3 +- .../cafInternalPdmStreamOperators.cpp | 38 ++ .../cafPdmXml/cafInternalPdmStreamOperators.h | 16 + Fwk/AppFwk/cafUserInterface/CMakeLists.txt | 3 + .../cafUserInterface/cafPdmUiDateEditor.cpp | 5 +- .../cafUserInterface/cafPdmUiDateEditor.h | 4 +- .../cafPdmUiDefaultObjectEditor.cpp | 2 + .../cafUserInterface/cafPdmUiTimeEditor.cpp | 121 ++++++ .../cafUserInterface/cafPdmUiTimeEditor.h | 93 ++++ 21 files changed, 855 insertions(+), 134 deletions(-) create mode 100644 Fwk/AppFwk/cafUserInterface/cafPdmUiTimeEditor.cpp create mode 100644 Fwk/AppFwk/cafUserInterface/cafPdmUiTimeEditor.h diff --git a/ApplicationCode/Application/RiaPreferences.cpp b/ApplicationCode/Application/RiaPreferences.cpp index 7e1b2cd605..e80bb6b8d6 100644 --- a/ApplicationCode/Application/RiaPreferences.cpp +++ b/ApplicationCode/Application/RiaPreferences.cpp @@ -22,6 +22,7 @@ #include "RiaPreferences.h" #include "RiaColorTables.h" +#include "RiaQDateTimeTools.h" #include "RifReaderSettings.h" #include "cafPdmFieldCvfColor.h" @@ -30,6 +31,9 @@ #include "cafPdmUiFieldHandle.h" #include "cafPdmUiFilePathEditor.h" +#include +#include + #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) #include #endif @@ -167,6 +171,13 @@ RiaPreferences::RiaPreferences(void) CAF_PDM_InitFieldNoDefault(&m_readerSettings, "readerSettings", "Reader Settings", "", "", ""); m_readerSettings = new RifReaderSettings; + CAF_PDM_InitFieldNoDefault(&m_dateFormat, "dateFormat", "Date Format", "", "", ""); + m_dateFormat.uiCapability()->setUiEditorTypeName(caf::PdmUiComboBoxEditor::uiEditorTypeName()); + m_dateFormat = RiaQDateTimeTools::supportedDateFormats().front(); + + CAF_PDM_InitFieldNoDefault(&m_timeFormat, "timeFormat", "Time Format", "", "", ""); + m_timeFormat.uiCapability()->setUiEditorTypeName(caf::PdmUiComboBoxEditor::uiEditorTypeName()); + m_timeFormat = RiaQDateTimeTools::supportedTimeFormats().front(); } //-------------------------------------------------------------------------------------------------- @@ -257,6 +268,8 @@ void RiaPreferences::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& viewsGroup->add(&showHud); caf::PdmUiGroup* otherGroup = uiOrdering.addNewGroup("Other"); + otherGroup->add(&m_dateFormat); + otherGroup->add(&m_timeFormat); otherGroup->add(&ssihubAddress); otherGroup->add(&showLasCurveWithoutTvdWarning); otherGroup->add(&holoLensDisableCertificateVerification); @@ -353,6 +366,30 @@ QList RiaPreferences::calculateValueOptions(const caf::P options.push_back(caf::PdmOptionItemInfo(skip.uiText(), RiaPreferences::NOT_IMPORT)); options.push_back(caf::PdmOptionItemInfo(allowImport.uiText(), RiaPreferences::IMPORT)); } + else if (fieldNeedingOptions == &m_dateFormat) + { + for (auto dateFormat : RiaQDateTimeTools::supportedDateFormats()) + { + QDate exampleDate = QDate(2019, 8, 16); + QString fullDateFormat = + RiaQDateTimeTools::dateFormatString(dateFormat, RiaQDateTimeTools::DATE_FORMAT_YEAR_MONTH_DAY); + QString uiText = QString("%1 (%2)").arg(fullDateFormat).arg(exampleDate.toString(fullDateFormat)); + uiText.replace("AP", "AM/PM"); + options.push_back(caf::PdmOptionItemInfo(uiText, QVariant::fromValue(dateFormat))); + } + } + else if (fieldNeedingOptions == &m_timeFormat) + { + for (auto timeFormat : RiaQDateTimeTools::supportedTimeFormats()) + { + QTime exampleTime = QTime(15, 48, 22); + QString timeFormatString = + RiaQDateTimeTools::timeFormatString(timeFormat, RiaQDateTimeTools::TIME_FORMAT_HOUR_MINUTE_SECOND); + QString uiText = QString("%1 (%2)").arg(timeFormatString).arg(exampleTime.toString(timeFormatString)); + uiText.replace("AP", "AM/PM"); + options.push_back(caf::PdmOptionItemInfo(uiText, QVariant::fromValue(timeFormat))); + } + } return options; } @@ -500,6 +537,22 @@ QString RiaPreferences::holoLensExportFolder() const return m_holoLensExportFolder(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +const QString& RiaPreferences::dateFormat() const +{ + return m_dateFormat(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +const QString& RiaPreferences::timeFormat() const +{ + return m_timeFormat(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/Application/RiaPreferences.h b/ApplicationCode/Application/RiaPreferences.h index 8677be6a10..63bd50d498 100644 --- a/ApplicationCode/Application/RiaPreferences.h +++ b/ApplicationCode/Application/RiaPreferences.h @@ -25,7 +25,7 @@ #include "RiaGuiApplication.h" #include "RiaDefines.h" #include "RiaFontCache.h" - +#include "RiaQDateTimeTools.h" #include "cafAppEnum.h" #include "cafPdmChildField.h" @@ -71,6 +71,9 @@ public: bool showProjectChangedDialog() const; QString holoLensExportFolder() const; + const QString& dateFormat() const; + const QString& timeFormat() const; + std::map defaultFontSizes() const; public: // Pdm Fields @@ -129,7 +132,6 @@ protected: void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) override; QList calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool * useOptionsOnly) override; void initAfterRead() override; - private: static QString tabNameGeneral(); static QString tabNameEclipse(); @@ -148,4 +150,7 @@ private: caf::PdmField m_showTestToolbar; caf::PdmField m_includeFractureDebugInfoFile; caf::PdmField m_holoLensExportFolder; + caf::PdmField m_dateFormat; + caf::PdmField m_timeFormat; + QStringList m_tabNames; }; diff --git a/ApplicationCode/Application/Tools/RiaQDateTimeTools.cpp b/ApplicationCode/Application/Tools/RiaQDateTimeTools.cpp index 4c02eb49ae..23662cdfca 100644 --- a/ApplicationCode/Application/Tools/RiaQDateTimeTools.cpp +++ b/ApplicationCode/Application/Tools/RiaQDateTimeTools.cpp @@ -392,4 +392,80 @@ QString RiaQDateTimeTools::createTimeFormatStringFromDates(const std::vector RiaQDateTimeTools::supportedDateFormats() +{ + std::vector dateFormats; + + // See enum DateFormatComponents in header + // The semi-colon separated components are: + // DATE_FORMAT_YEAR, ..YEAR_MONTH, ..YEAR_MONTH_DAY + dateFormats.push_back("yyyy;yyyy-MM;yyyy-MM-dd"); + dateFormats.push_back("yyyy;MMM yyyy;dd. MMM yyyy"); + dateFormats.push_back("yyyy;MMM yyyy;MMM dd. yyyy"); + dateFormats.push_back("yyyy;MM/yyyy;dd/MM/yyyy"); + dateFormats.push_back("yyyy;M/yyyy;d/M/yyyy"); + dateFormats.push_back("yyyy;M/yyyy;M/d/yyyy"); + dateFormats.push_back("yy;M/yy;d/M/yy"); + dateFormats.push_back("yy;M/yy;M/d/yy"); + dateFormats.push_back("yyyy;MM-yyyy;dd-MM-yyyy"); + dateFormats.push_back("yyyy;MM-yyyy;MM-dd-yyyy"); + dateFormats.push_back("yy;MM-yy;dd-MM-yy"); + dateFormats.push_back("yy;MM-yy;MM-dd-yy"); + + return dateFormats; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RiaQDateTimeTools::supportedTimeFormats() +{ + std::vector timeFormats; + + // See enum TimeFormatComponents in header + // The semi-colon separated components are: + // TIME_FORMAT_HOUR, ..HOUR_MINUTE, ..HOUR_MINUTE_SECOND and ..HOUR_MINUTE_MILLISECOND + timeFormats.push_back("HH;HH:mm;HH:mm:ss;HH:mm:ss.zzz"); + timeFormats.push_back("H;H:mm;H:mm:ss;H:mm:ss.zzz"); + timeFormats.push_back("hh AP;hh:mm AP;hh:mm:ss AP;hh:mm:ss.zzz AP"); + timeFormats.push_back("h AP;h:mm AP;h:mm:ss AP;h:mm:ss.zzz AP"); + + return timeFormats; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RiaQDateTimeTools::dateFormatString(const QString& fullDateFormat, DateFormatComponents dateComponents) +{ + if (dateComponents == DATE_FORMAT_NONE) return ""; + + QStringList allVariants = fullDateFormat.split(";"); + if (static_cast(dateComponents) < allVariants.size()) + { + return allVariants[dateComponents]; + } + CVF_ASSERT(false && "Date format string is malformed"); + return ""; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RiaQDateTimeTools::timeFormatString(const QString& fullTimeFormat, TimeFormatComponents timeComponents) +{ + if (timeComponents == TIME_FORMAT_NONE) return ""; + + QStringList allVariants = fullTimeFormat.split(";"); + if (static_cast(timeComponents) < allVariants.size()) + { + return allVariants[timeComponents]; + } + CVF_ASSERT(false && "Time format string is malformed"); + return ""; } \ No newline at end of file diff --git a/ApplicationCode/Application/Tools/RiaQDateTimeTools.h b/ApplicationCode/Application/Tools/RiaQDateTimeTools.h index 9dffa4de32..eab75707ea 100644 --- a/ApplicationCode/Application/Tools/RiaQDateTimeTools.h +++ b/ApplicationCode/Application/Tools/RiaQDateTimeTools.h @@ -22,7 +22,11 @@ #include #include +#include +#include +#include +#include #include #include @@ -60,6 +64,25 @@ class RiaQDateTimeTools static const DateTimeSpan TIMESPAN_DECADE; public: + enum DateFormatComponents + { + DATE_FORMAT_NONE = -1, + DATE_FORMAT_YEAR = 0, + DATE_FORMAT_YEAR_MONTH, + DATE_FORMAT_YEAR_MONTH_DAY, + DATE_FORMAT_SIZE + }; + + enum TimeFormatComponents + { + TIME_FORMAT_NONE = -1, + TIME_FORMAT_HOUR, + TIME_FORMAT_HOUR_MINUTE, + TIME_FORMAT_HOUR_MINUTE_SECOND, + TIME_FORMAT_HOUR_MINUTE_SECOND_MILLISECOND, + TIME_FORMAT_SIZE + }; + static const QString TIMESPAN_DAY_NAME; static const QString TIMESPAN_WEEK_NAME; static const QString TIMESPAN_MONTH_NAME; @@ -104,9 +127,16 @@ public: static QString createTimeFormatStringFromDates(const std::vector& dates); static QString dateFormatString(); + static std::vector supportedDateFormats(); + static std::vector supportedTimeFormats(); + + static QString dateFormatString(const QString& fullDateFormat, DateFormatComponents dateComponents); + static QString timeFormatString(const QString& fullTimeFormat, TimeFormatComponents timeComponents); + private: static quint64 secondsInDay(); static quint64 secondsInYear(); + }; //================================================================================================== diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlot.cpp b/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlot.cpp index 485ef6a2e5..8b791a5c58 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlot.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlot.cpp @@ -926,7 +926,10 @@ void RimSummaryPlot::updateTimeAxis() if (m_timeAxisProperties->timeMode() == RimSummaryTimeAxisProperties::DATE) { - m_qwtPlot->useDateBasedTimeAxis(); + QString dateFormat = m_timeAxisProperties->dateFormat(); + QString timeFormat = m_timeAxisProperties->timeFormat(); + + m_qwtPlot->useDateBasedTimeAxis(dateFormat, timeFormat); } else { diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryTimeAxisProperties.cpp b/ApplicationCode/ProjectDataModel/Summary/RimSummaryTimeAxisProperties.cpp index 0b44863edb..49ba10be3d 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryTimeAxisProperties.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryTimeAxisProperties.cpp @@ -1,17 +1,17 @@ ///////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2016 Statoil ASA -// +// // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// +// // ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. -// -// See the GNU General Public License at +// +// See the GNU General Public License at // for more details. // ///////////////////////////////////////////////////////////////////////////////// @@ -24,16 +24,17 @@ #include "RimSummaryPlot.h" +#include "cafPdmUiComboBoxEditor.h" +#include "cafPdmUiDateEditor.h" #include "cafPdmUiLineEditor.h" - -#include "qwt_date.h" +#include "cafPdmUiTimeEditor.h" #include "cvfAssert.h" - +#include "qwt_date.h" namespace caf { template<> -void caf::AppEnum< RimSummaryTimeAxisProperties::TimeModeType >::setUp() +void caf::AppEnum::setUp() { addItem(RimSummaryTimeAxisProperties::DATE, "DATE", "Date"); addItem(RimSummaryTimeAxisProperties::TIME_FROM_SIMULATION_START, "TIME_FROM_SIMULATION_START", "Time From Simulation Start"); @@ -42,26 +43,23 @@ void caf::AppEnum< RimSummaryTimeAxisProperties::TimeModeType >::setUp() } template<> -void caf::AppEnum< RimSummaryTimeAxisProperties::TimeUnitType >::setUp() +void caf::AppEnum::setUp() { addItem(RimSummaryTimeAxisProperties::SECONDS, "SECONDS", "Seconds"); addItem(RimSummaryTimeAxisProperties::MINUTES, "MINUTES", "Minutes"); addItem(RimSummaryTimeAxisProperties::HOURS, "HOURS", "Hours"); - addItem(RimSummaryTimeAxisProperties::DAYS, "DAYS ", "Days"); + addItem(RimSummaryTimeAxisProperties::DAYS, "DAYS ", "Days"); addItem(RimSummaryTimeAxisProperties::YEARS, "YEARS", "Years"); setDefault(RimSummaryTimeAxisProperties::YEARS); } -} - - +} // namespace caf CAF_PDM_SOURCE_INIT(RimSummaryTimeAxisProperties, "SummaryTimeAxisProperties"); - //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- RimSummaryTimeAxisProperties::RimSummaryTimeAxisProperties() { @@ -77,17 +75,24 @@ RimSummaryTimeAxisProperties::RimSummaryTimeAxisProperties() CAF_PDM_InitFieldNoDefault(&m_timeMode, "TimeMode", "Time Mode", "", "", ""); CAF_PDM_InitFieldNoDefault(&m_timeUnit, "TimeUnit", "Time Unit", "", "", ""); - CAF_PDM_InitFieldNoDefault(&m_visibleDateRangeMax, "VisibleRangeMax", "Max", "", "", ""); - m_visibleDateRangeMax.uiCapability()->setUiEditorTypeName(caf::PdmUiLineEditor::uiEditorTypeName()); + CAF_PDM_InitFieldNoDefault(&m_visibleDateRangeMax, "VisibleDateRangeMax", "Max Date", "", "", ""); + m_visibleDateRangeMax.uiCapability()->setUiEditorTypeName(caf::PdmUiDateEditor::uiEditorTypeName()); + CAF_PDM_InitFieldNoDefault(&m_visibleDateRangeMin, "VisibleDateRangeMin", "Min Date", "", "", ""); + m_visibleDateRangeMin.uiCapability()->setUiEditorTypeName(caf::PdmUiDateEditor::uiEditorTypeName()); - CAF_PDM_InitFieldNoDefault(&m_visibleDateRangeMin, "VisibleRangeMin", "Min", "", "", ""); - m_visibleDateRangeMin.uiCapability()->setUiEditorTypeName(caf::PdmUiLineEditor::uiEditorTypeName()); + CAF_PDM_InitFieldNoDefault(&m_visibleTimeRangeMax, "VisibleTimeRangeMax", "MaxTime", "", "", ""); + m_visibleTimeRangeMax.uiCapability()->setUiEditorTypeName(caf::PdmUiTimeEditor::uiEditorTypeName()); + m_visibleTimeRangeMax.uiCapability()->setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN); - CAF_PDM_InitFieldNoDefault(&m_visibleTimeRangeMax, "VisibleTimeModeRangeMax", "Max", "", "", ""); - m_visibleDateRangeMax.uiCapability()->setUiEditorTypeName(caf::PdmUiLineEditor::uiEditorTypeName()); + CAF_PDM_InitFieldNoDefault(&m_visibleTimeRangeMin, "VisibleTimeRangeMin", "Min Time", "", "", ""); + m_visibleTimeRangeMin.uiCapability()->setUiEditorTypeName(caf::PdmUiTimeEditor::uiEditorTypeName()); + m_visibleTimeRangeMin.uiCapability()->setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN); - CAF_PDM_InitFieldNoDefault(&m_visibleTimeRangeMin, "VisibleTimeModeRangeMin", "Min", "", "", ""); - m_visibleDateRangeMin.uiCapability()->setUiEditorTypeName(caf::PdmUiLineEditor::uiEditorTypeName()); + CAF_PDM_InitFieldNoDefault(&m_visibleTimeSinceStartRangeMax, "VisibleTimeModeRangeMax", "Max", "", "", ""); + m_visibleTimeSinceStartRangeMax.uiCapability()->setUiEditorTypeName(caf::PdmUiLineEditor::uiEditorTypeName()); + + CAF_PDM_InitFieldNoDefault(&m_visibleTimeSinceStartRangeMin, "VisibleTimeModeRangeMin", "Min", "", "", ""); + m_visibleTimeSinceStartRangeMin.uiCapability()->setUiEditorTypeName(caf::PdmUiLineEditor::uiEditorTypeName()); CAF_PDM_InitFieldNoDefault(&m_titlePositionEnum, "TitlePosition", "Title Position", "", "", ""); CAF_PDM_InitField(&m_titleFontSize, "FontSize", 10, "Font Size", "", "", ""); @@ -95,6 +100,19 @@ RimSummaryTimeAxisProperties::RimSummaryTimeAxisProperties() CAF_PDM_InitField(&m_valuesFontSize, "ValuesFontSize", 10, "Font Size", "", "", ""); m_valuesFontSize = RiaFontCache::pointSizeFromFontSizeEnum(RiaApplication::instance()->preferences()->defaultPlotFontSize()); + CAF_PDM_InitFieldNoDefault(&m_dateFormat, "DateFormat", "Date Format", "", "", ""); + m_dateFormat.uiCapability()->setUiEditorTypeName(caf::PdmUiComboBoxEditor::uiEditorTypeName()); + m_dateFormat = RiaApplication::instance()->preferences()->dateFormat(); + + CAF_PDM_InitFieldNoDefault(&m_timeFormat, "TimeFormat", "Time Format", "", "", ""); + m_timeFormat.uiCapability()->setUiEditorTypeName(caf::PdmUiComboBoxEditor::uiEditorTypeName()); + m_timeFormat = RiaApplication::instance()->preferences()->timeFormat(); + + CAF_PDM_InitFieldNoDefault(&m_visibleDateTimeRangeMax_OBSOLETE, "VisibleRangeMax", "Max", "", "", ""); + m_visibleDateTimeRangeMax_OBSOLETE.uiCapability()->setUiEditorTypeName(caf::PdmUiLineEditor::uiEditorTypeName()); + + CAF_PDM_InitFieldNoDefault(&m_visibleDateTimeRangeMin_OBSOLETE, "VisibleRangeMin", "Min", "", "", ""); + m_visibleDateTimeRangeMin_OBSOLETE.uiCapability()->setUiEditorTypeName(caf::PdmUiLineEditor::uiEditorTypeName()); } //-------------------------------------------------------------------------------------------------- @@ -138,66 +156,71 @@ void RimSummaryTimeAxisProperties::setValuesFontSize(int fontSize) } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- double RimSummaryTimeAxisProperties::visibleRangeMin() const { - if ( m_timeMode() == DATE ) - return QwtDate::toDouble(m_visibleDateRangeMin()); + if (m_timeMode() == DATE) + { + return QwtDate::toDouble(visibleDateTimeMin()); + } else - return m_visibleTimeRangeMin(); + return m_visibleTimeSinceStartRangeMin(); } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- double RimSummaryTimeAxisProperties::visibleRangeMax() const { - if ( m_timeMode() == DATE ) - return QwtDate::toDouble(m_visibleDateRangeMax()); + if (m_timeMode() == DATE) + { + return QwtDate::toDouble(visibleDateTimeMax()); + } else - return m_visibleTimeRangeMax(); + return m_visibleTimeSinceStartRangeMax(); } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- void RimSummaryTimeAxisProperties::setVisibleRangeMin(double value) { - if ( m_timeMode() == DATE ) + if (m_timeMode() == DATE) { - m_visibleDateRangeMin = QwtDate::toDateTime(value); - m_visibleTimeRangeMin = fromDateToDisplayTime(m_visibleDateRangeMin()); + QDateTime dateTime = QwtDate::toDateTime(value); + m_visibleTimeSinceStartRangeMin = fromDateToDisplayTime(dateTime); + setVisibleDateTimeMin(dateTime); } else { - m_visibleTimeRangeMin = value; - m_visibleDateRangeMin = fromDisplayTimeToDate(value); + m_visibleTimeSinceStartRangeMin = value; + QDateTime dateTime = fromDisplayTimeToDate(value); + setVisibleDateTimeMin(dateTime); } - auto s = m_visibleDateRangeMin().toString(); } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- void RimSummaryTimeAxisProperties::setVisibleRangeMax(double value) { - if ( m_timeMode() == DATE ) + if (m_timeMode() == DATE) { - m_visibleDateRangeMax = QwtDate::toDateTime(value); - m_visibleTimeRangeMax = fromDateToDisplayTime(m_visibleDateRangeMax()); - + QDateTime dateTime = QwtDate::toDateTime(value); + m_visibleTimeSinceStartRangeMax = fromDateToDisplayTime(dateTime); + setVisibleDateTimeMax(dateTime); } else { - m_visibleTimeRangeMax = value; - m_visibleDateRangeMax = fromDisplayTimeToDate(value); + m_visibleTimeSinceStartRangeMax = value; + QDateTime dateTime = fromDisplayTimeToDate(value); + setVisibleDateTimeMax(dateTime); } - auto s = m_visibleDateRangeMax().toString(); } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- bool RimSummaryTimeAxisProperties::isAutoZoom() const { @@ -205,7 +228,7 @@ bool RimSummaryTimeAxisProperties::isAutoZoom() const } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- void RimSummaryTimeAxisProperties::setAutoZoom(bool enableAutoZoom) { @@ -213,25 +236,25 @@ void RimSummaryTimeAxisProperties::setAutoZoom(bool enableAutoZoom) } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- void RimSummaryTimeAxisProperties::updateTimeVisibleRange() { - m_visibleTimeRangeMax = fromDateToDisplayTime(m_visibleDateRangeMax()); - m_visibleTimeRangeMin = fromDateToDisplayTime(m_visibleDateRangeMin()); + m_visibleTimeSinceStartRangeMax = fromDateToDisplayTime(visibleDateTimeMax()); + m_visibleTimeSinceStartRangeMin = fromDateToDisplayTime(visibleDateTimeMin()); } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- void RimSummaryTimeAxisProperties::updateDateVisibleRange() { - m_visibleDateRangeMin = fromDisplayTimeToDate(m_visibleTimeRangeMin()); - m_visibleDateRangeMax = fromDisplayTimeToDate(m_visibleTimeRangeMax()); + setVisibleDateTimeMin(fromDisplayTimeToDate(m_visibleTimeSinceStartRangeMin())); + setVisibleDateTimeMax(fromDisplayTimeToDate(m_visibleTimeSinceStartRangeMax())); } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- QDateTime RimSummaryTimeAxisProperties::fromDisplayTimeToDate(double displayTime) { @@ -239,7 +262,7 @@ QDateTime RimSummaryTimeAxisProperties::fromDisplayTimeToDate(double displayTime this->firstAncestorOrThisOfType(rimSummaryPlot); time_t startOfSimulation = rimSummaryPlot->firstTimeStepOfFirstCurve(); - time_t secsSinceSimulationStart = displayTime/fromTimeTToDisplayUnitScale(); + time_t secsSinceSimulationStart = displayTime / fromTimeTToDisplayUnitScale(); QDateTime date; date.setTime_t(startOfSimulation + secsSinceSimulationStart); @@ -247,7 +270,7 @@ QDateTime RimSummaryTimeAxisProperties::fromDisplayTimeToDate(double displayTime } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- double RimSummaryTimeAxisProperties::fromDateToDisplayTime(const QDateTime& displayTime) { @@ -257,12 +280,11 @@ double RimSummaryTimeAxisProperties::fromDateToDisplayTime(const QDateTime& disp this->firstAncestorOrThisOfType(rimSummaryPlot); time_t startOfSimulation = rimSummaryPlot->firstTimeStepOfFirstCurve(); - return fromTimeTToDisplayUnitScale()*(secsSinceEpoc - startOfSimulation); + return fromTimeTToDisplayUnitScale() * (secsSinceEpoc - startOfSimulation); } - //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- bool RimSummaryTimeAxisProperties::isActive() const { @@ -270,15 +292,51 @@ bool RimSummaryTimeAxisProperties::isActive() const } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- -QList RimSummaryTimeAxisProperties::calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool * useOptionsOnly) +QDateTime RimSummaryTimeAxisProperties::visibleDateTimeMin() const +{ + QDateTime fullMin(m_visibleDateRangeMin(), m_visibleTimeRangeMin()); + return fullMin; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QDateTime RimSummaryTimeAxisProperties::visibleDateTimeMax() const +{ + QDateTime fullMax(m_visibleDateRangeMax(), m_visibleTimeRangeMax()); + return fullMax; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimSummaryTimeAxisProperties::setVisibleDateTimeMin(const QDateTime& dateTime) +{ + m_visibleDateRangeMin = dateTime.date(); + m_visibleTimeRangeMin = dateTime.time(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimSummaryTimeAxisProperties::setVisibleDateTimeMax(const QDateTime& dateTime) +{ + m_visibleDateRangeMax = dateTime.date(); + m_visibleTimeRangeMax = dateTime.time(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QList RimSummaryTimeAxisProperties::calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, + bool* useOptionsOnly) { QList options; *useOptionsOnly = true; - if (&m_titleFontSize == fieldNeedingOptions || - &m_valuesFontSize == fieldNeedingOptions) + if (&m_titleFontSize == fieldNeedingOptions || &m_valuesFontSize == fieldNeedingOptions) { std::vector fontSizes; fontSizes.push_back(8); @@ -297,12 +355,35 @@ QList RimSummaryTimeAxisProperties::calculateValueOption options.push_back(caf::PdmOptionItemInfo(text, value)); } } - + else if (fieldNeedingOptions == &m_dateFormat) + { + for (auto dateFormat : RiaQDateTimeTools::supportedDateFormats()) + { + QDate exampleDate = QDate(2019, 8, 16); + QString fullDateFormat = + RiaQDateTimeTools::dateFormatString(dateFormat, RiaQDateTimeTools::DATE_FORMAT_YEAR_MONTH_DAY); + QString uiText = QString("%1 (%2)").arg(fullDateFormat).arg(exampleDate.toString(fullDateFormat)); + uiText.replace("AP", "AM/PM"); + options.push_back(caf::PdmOptionItemInfo(uiText, QVariant::fromValue(dateFormat))); + } + } + else if (fieldNeedingOptions == &m_timeFormat) + { + for (auto timeFormat : RiaQDateTimeTools::supportedTimeFormats()) + { + QTime exampleTime = QTime(15, 48, 22); + QString timeFormatString = + RiaQDateTimeTools::timeFormatString(timeFormat, RiaQDateTimeTools::TIME_FORMAT_HOUR_MINUTE_SECOND); + QString uiText = QString("%1 (%2)").arg(timeFormatString).arg(exampleTime.toString(timeFormatString)); + uiText.replace("AP", "AM/PM"); + options.push_back(caf::PdmOptionItemInfo(uiText, QVariant::fromValue(timeFormat))); + } + } return options; } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- caf::PdmFieldHandle* RimSummaryTimeAxisProperties::objectToggleField() { @@ -326,7 +407,7 @@ void RimSummaryTimeAxisProperties::setTimeMode(TimeModeType val) } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- double RimSummaryTimeAxisProperties::fromTimeTToDisplayUnitScale() { @@ -334,59 +415,75 @@ double RimSummaryTimeAxisProperties::fromTimeTToDisplayUnitScale() switch (m_timeUnit()) { case SECONDS: - break; + break; case MINUTES: - scale = 1.0/60.0; - break; + scale = 1.0 / 60.0; + break; case HOURS: - scale = 1.0/(60.0*60.0); - break; + scale = 1.0 / (60.0 * 60.0); + break; case DAYS: - scale = 1.0/(60.0*60.0*24.0); - break; + scale = 1.0 / (60.0 * 60.0 * 24.0); + break; case YEARS: - scale = 1.0/31556952.0; - break; + scale = 1.0 / 31556952.0; + break; default: - CVF_ASSERT(false); - break; + CVF_ASSERT(false); + break; } return scale; } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- double RimSummaryTimeAxisProperties::fromDaysToDisplayUnitScale() { double scale = 1.0; switch (m_timeUnit()) { - case SECONDS: - scale = 60.0 * 60.0 * 24.0; - break; - case MINUTES: - scale = 60.0 * 24.0; - break; - case HOURS: - scale = 24.0; - break; - case DAYS: - break; - case YEARS: - scale = 1.0/365.2425; - break; - default: - CVF_ASSERT(false); - break; + case SECONDS: + scale = 60.0 * 60.0 * 24.0; + break; + case MINUTES: + scale = 60.0 * 24.0; + break; + case HOURS: + scale = 24.0; + break; + case DAYS: + break; + case YEARS: + scale = 1.0 / 365.2425; + break; + default: + CVF_ASSERT(false); + break; } return scale; } //-------------------------------------------------------------------------------------------------- -/// +/// +//-------------------------------------------------------------------------------------------------- +const QString& RimSummaryTimeAxisProperties::dateFormat() const +{ + return m_dateFormat(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +const QString& RimSummaryTimeAxisProperties::timeFormat() const +{ + return m_timeFormat(); +} + +//-------------------------------------------------------------------------------------------------- +/// //-------------------------------------------------------------------------------------------------- void RimSummaryTimeAxisProperties::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) { @@ -396,18 +493,22 @@ void RimSummaryTimeAxisProperties::defineUiOrdering(QString uiConfigName, caf::P titleGroup.add(&m_titlePositionEnum); titleGroup.add(&m_titleFontSize); - caf::PdmUiGroup* timeGroup = uiOrdering.addNewGroup("Time Values"); + caf::PdmUiGroup* timeGroup = uiOrdering.addNewGroup("Time Values"); timeGroup->add(&m_timeMode); if (m_timeMode() == DATE) { - timeGroup->add( &m_visibleDateRangeMax); - timeGroup->add(&m_visibleDateRangeMin); + timeGroup->add(&m_visibleDateRangeMax, true); + timeGroup->add(&m_visibleTimeRangeMax, false); + timeGroup->add(&m_visibleDateRangeMin, true); + timeGroup->add(&m_visibleTimeRangeMin, false); + timeGroup->add(&m_dateFormat); + timeGroup->add(&m_timeFormat); } else { - timeGroup->add(&m_timeUnit); - timeGroup->add(&m_visibleTimeRangeMax); - timeGroup->add(&m_visibleTimeRangeMin); + timeGroup->add(&m_timeUnit); + timeGroup->add(&m_visibleTimeSinceStartRangeMax); + timeGroup->add(&m_visibleTimeSinceStartRangeMin); } timeGroup->add(&m_valuesFontSize); @@ -415,9 +516,11 @@ void RimSummaryTimeAxisProperties::defineUiOrdering(QString uiConfigName, caf::P } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- -void RimSummaryTimeAxisProperties::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) +void RimSummaryTimeAxisProperties::fieldChangedByUi(const caf::PdmFieldHandle* changedField, + const QVariant& oldValue, + const QVariant& newValue) { RimSummaryPlot* rimSummaryPlot = nullptr; this->firstAncestorOrThisOfType(rimSummaryPlot); @@ -425,10 +528,21 @@ void RimSummaryTimeAxisProperties::fieldChangedByUi(const caf::PdmFieldHandle* c if (changedField == &m_visibleDateRangeMax) { - QDateTime test = newValue.toDateTime(); + QDate test = newValue.toDate(); if (!test.isValid()) { - m_visibleDateRangeMax = oldValue.toDateTime(); + m_visibleDateRangeMax = oldValue.toDate(); + } + + updateTimeVisibleRange(); + m_isAutoZoom = false; + } + else if (changedField == &m_visibleTimeRangeMax) + { + QTime test = newValue.toTime(); + if (!test.isValid()) + { + m_visibleTimeRangeMax = oldValue.toTime(); } updateTimeVisibleRange(); @@ -436,16 +550,27 @@ void RimSummaryTimeAxisProperties::fieldChangedByUi(const caf::PdmFieldHandle* c } else if (changedField == &m_visibleDateRangeMin) { - QDateTime test = newValue.toDateTime(); + QDate test = newValue.toDate(); if (!test.isValid()) { - m_visibleDateRangeMin = oldValue.toDateTime(); + m_visibleDateRangeMin = oldValue.toDate(); } updateTimeVisibleRange(); m_isAutoZoom = false; } - else if (changedField == &m_visibleTimeRangeMin || changedField == &m_visibleTimeRangeMax) + else if (changedField == &m_visibleTimeRangeMin) + { + QTime test = newValue.toTime(); + if (!test.isValid()) + { + m_visibleTimeRangeMin = oldValue.toTime(); + } + + updateTimeVisibleRange(); + m_isAutoZoom = false; + } + else if (changedField == &m_visibleTimeSinceStartRangeMin || changedField == &m_visibleTimeSinceStartRangeMax) { updateDateVisibleRange(); m_isAutoZoom = false; @@ -460,7 +585,58 @@ void RimSummaryTimeAxisProperties::fieldChangedByUi(const caf::PdmFieldHandle* c rimSummaryPlot->loadDataAndUpdate(); updateDateVisibleRange(); } + else if (changedField == &m_dateFormat || changedField == &m_timeFormat) + { + updateTimeVisibleRange(); // Use the stored max min dates to update the visible time range to new unit + rimSummaryPlot->loadDataAndUpdate(); + updateDateVisibleRange(); + } rimSummaryPlot->updateAxes(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimSummaryTimeAxisProperties::initAfterRead() +{ + QDateTime maxDateTime = m_visibleDateTimeRangeMax_OBSOLETE(); + QDateTime minDateTime = m_visibleDateTimeRangeMin_OBSOLETE(); + if (maxDateTime.isValid()) + { + m_visibleDateRangeMax = maxDateTime.date(); + m_visibleTimeRangeMax = maxDateTime.time(); + } + if (minDateTime.isValid()) + { + m_visibleDateRangeMin = minDateTime.date(); + m_visibleTimeRangeMin = minDateTime.time(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimSummaryTimeAxisProperties::defineEditorAttribute(const caf::PdmFieldHandle* field, + QString uiConfigName, + caf::PdmUiEditorAttribute* attribute) +{ + if (field == &m_visibleDateRangeMin || field == &m_visibleDateRangeMax) + { + auto dateAttrib = dynamic_cast(attribute); + if (dateAttrib) + { + dateAttrib->dateFormat = + RiaQDateTimeTools::dateFormatString(m_dateFormat(), RiaQDateTimeTools::DATE_FORMAT_YEAR_MONTH_DAY); + } + } + else if (field == &m_visibleTimeRangeMin || field == &m_visibleTimeRangeMax) + { + auto timeAttrib = dynamic_cast(attribute); + if (timeAttrib) + { + timeAttrib->timeFormat = + RiaQDateTimeTools::timeFormatString(m_timeFormat(), RiaQDateTimeTools::TIME_FORMAT_HOUR_MINUTE_SECOND); + } + } +} diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryTimeAxisProperties.h b/ApplicationCode/ProjectDataModel/Summary/RimSummaryTimeAxisProperties.h index bc8c018078..09d286cfe0 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryTimeAxisProperties.h +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryTimeAxisProperties.h @@ -19,6 +19,7 @@ #pragma once +#include "RiaQDateTimeTools.h" #include "RimPlotAxisPropertiesInterface.h" #include "cafPdmObject.h" @@ -70,6 +71,9 @@ public: double fromTimeTToDisplayUnitScale(); double fromDaysToDisplayUnitScale(); + const QString& dateFormat() const; + const QString& timeFormat() const; + double visibleRangeMin() const; double visibleRangeMax() const; @@ -81,30 +85,49 @@ public: bool isActive() const; + QDateTime visibleDateTimeMin() const; + QDateTime visibleDateTimeMax() const; + + void setVisibleDateTimeMin(const QDateTime& dateTime); + void setVisibleDateTimeMax(const QDateTime& dateTime); + protected: void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override; QList calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool * useOptionsOnly) override; caf::PdmFieldHandle* objectToggleField() override; void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) override; + void initAfterRead() override; + void defineEditorAttribute(const caf::PdmFieldHandle* field, + QString uiConfigName, + caf::PdmUiEditorAttribute* attribute) override; double fromDateToDisplayTime(const QDateTime& displayTime); QDateTime fromDisplayTimeToDate(double displayTime); void updateTimeVisibleRange(); void updateDateVisibleRange(); + + private: caf::PdmField< caf::AppEnum< TimeModeType > > m_timeMode; caf::PdmField< caf::AppEnum< TimeUnitType > > m_timeUnit; caf::PdmField m_isActive; - caf::PdmField m_visibleDateRangeMin; - caf::PdmField m_visibleDateRangeMax; - caf::PdmField m_visibleTimeRangeMin; - caf::PdmField m_visibleTimeRangeMax; + caf::PdmField m_visibleDateRangeMin; + caf::PdmField m_visibleDateRangeMax; + caf::PdmField m_visibleTimeRangeMin; + caf::PdmField m_visibleTimeRangeMax; + + caf::PdmField m_visibleTimeSinceStartRangeMin; + caf::PdmField m_visibleTimeSinceStartRangeMax; caf::PdmField m_isAutoZoom; caf::PdmField m_titleFontSize; caf::PdmField> m_titlePositionEnum; caf::PdmField m_valuesFontSize; + caf::PdmField m_dateFormat; + caf::PdmField m_timeFormat; + caf::PdmField m_visibleDateTimeRangeMin_OBSOLETE; + caf::PdmField m_visibleDateTimeRangeMax_OBSOLETE; }; diff --git a/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.cpp b/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.cpp index e47ea231b8..f52c904dbc 100644 --- a/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.cpp +++ b/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.cpp @@ -82,7 +82,11 @@ RiuFlowCharacteristicsPlot::RiuFlowCharacteristicsPlot(RimFlowCharacteristicsPlo RiuQwtPlotTools::setCommonPlotBehaviour(m_lorenzPlot); new RiuQwtPlotWheelZoomer(m_lorenzPlot); addWindowZoom(m_lorenzPlot); - RiuQwtPlotTools::enableDateBasedBottomXAxis(m_lorenzPlot); + + QString dateFormat = RiaApplication::instance()->preferences()->dateFormat(); + QString timeFormat = RiaApplication::instance()->preferences()->timeFormat(); + + RiuQwtPlotTools::enableDateBasedBottomXAxis(m_lorenzPlot, dateFormat, timeFormat); m_lorenzPlot->setTitle("Lorenz Coefficient"); RiuQwtPlotTools::setCommonPlotBehaviour(m_sweepEffPlot); diff --git a/ApplicationCode/UserInterface/RiuQwtPlotTools.cpp b/ApplicationCode/UserInterface/RiuQwtPlotTools.cpp index 35de490a1c..ed32ed0003 100644 --- a/ApplicationCode/UserInterface/RiuQwtPlotTools.cpp +++ b/ApplicationCode/UserInterface/RiuQwtPlotTools.cpp @@ -17,12 +17,16 @@ ///////////////////////////////////////////////////////////////////////////////// #include "RiuQwtPlotTools.h" +#include "RiaApplication.h" +#include "RiaPreferences.h" + #include "qwt_date_scale_draw.h" #include "qwt_date_scale_engine.h" #include "qwt_plot.h" #include "qwt_plot_grid.h" #include "qwt_plot_layout.h" +#include #include //-------------------------------------------------------------------------------------------------- @@ -63,8 +67,8 @@ void RiuQwtPlotTools::setCommonPlotBehaviour(QwtPlot* plot) plot->setAxisFont(QwtPlot::yRight, axisFont); // Axis title font - std::vector axes = { QwtPlot::xBottom, QwtPlot::xTop, QwtPlot::yLeft, QwtPlot::yRight }; - + std::vector axes = {QwtPlot::xBottom, QwtPlot::xTop, QwtPlot::yLeft, QwtPlot::yRight}; + for (QwtPlot::Axis axis : axes) { QwtText axisTitle = plot->axisTitle(axis); @@ -108,12 +112,69 @@ void RiuQwtPlotTools::setDefaultAxes(QwtPlot* plot) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RiuQwtPlotTools::enableDateBasedBottomXAxis(QwtPlot* plot) +void RiuQwtPlotTools::enableDateBasedBottomXAxis(QwtPlot* plot, + const QString& dateFormat, + const QString& timeFormat) { QwtDateScaleDraw* scaleDraw = new QwtDateScaleDraw(Qt::UTC); - scaleDraw->setDateFormat(QwtDate::Year, QString("dd-MM-yyyy")); + + std::set intervals = {QwtDate::Year, + QwtDate::Month, + QwtDate::Week, + QwtDate::Day, + QwtDate::Hour, + QwtDate::Minute, + QwtDate::Second, + QwtDate::Millisecond}; + + for (QwtDate::IntervalType interval : intervals) + { + scaleDraw->setDateFormat(interval, dateTimeFormatForInterval(interval, dateFormat, timeFormat)); + } QwtDateScaleEngine* scaleEngine = new QwtDateScaleEngine(Qt::UTC); plot->setAxisScaleEngine(QwtPlot::xBottom, scaleEngine); plot->setAxisScaleDraw(QwtPlot::xBottom, scaleDraw); -} \ No newline at end of file +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RiuQwtPlotTools::dateTimeFormatForInterval(QwtDate::IntervalType interval, + const QString& dateFormat, + const QString& timeFormat) +{ + switch (interval) + { + case QwtDate::Millisecond: + return RiaQDateTimeTools::timeFormatString(timeFormat, RiaQDateTimeTools::TIME_FORMAT_HOUR_MINUTE_SECOND_MILLISECOND); + case QwtDate::Second: + return RiaQDateTimeTools::timeFormatString(timeFormat, RiaQDateTimeTools::TIME_FORMAT_HOUR_MINUTE_SECOND); + case QwtDate::Minute: { + QString fullFormat = RiaQDateTimeTools::timeFormatString(timeFormat, RiaQDateTimeTools::TIME_FORMAT_HOUR_MINUTE); + fullFormat += "\n"; + fullFormat += RiaQDateTimeTools::dateFormatString(dateFormat, RiaQDateTimeTools::DATE_FORMAT_YEAR_MONTH_DAY); + return fullFormat; + } + case QwtDate::Hour: { + QString fullFormat = RiaQDateTimeTools::timeFormatString(timeFormat, RiaQDateTimeTools::TIME_FORMAT_HOUR); + if (!fullFormat.endsWith("AP")) + { + fullFormat += ":00"; + } + fullFormat += "\n"; + fullFormat += RiaQDateTimeTools::dateFormatString(dateFormat, RiaQDateTimeTools::DATE_FORMAT_YEAR_MONTH_DAY); + return fullFormat; + } + case QwtDate::Day: + return RiaQDateTimeTools::dateFormatString(dateFormat, RiaQDateTimeTools::DATE_FORMAT_YEAR_MONTH_DAY); + case QwtDate::Week: + return RiaQDateTimeTools::dateFormatString(dateFormat, RiaQDateTimeTools::DATE_FORMAT_YEAR_MONTH); + case QwtDate::Month: + return RiaQDateTimeTools::dateFormatString(dateFormat, RiaQDateTimeTools::DATE_FORMAT_YEAR_MONTH); + case QwtDate::Year: + return RiaQDateTimeTools::dateFormatString(dateFormat, RiaQDateTimeTools::DATE_FORMAT_YEAR); + default: + return RiaQDateTimeTools::dateFormatString(dateFormat, RiaQDateTimeTools::DATE_FORMAT_YEAR_MONTH_DAY); + } +} diff --git a/ApplicationCode/UserInterface/RiuQwtPlotTools.h b/ApplicationCode/UserInterface/RiuQwtPlotTools.h index a54578dfd7..cb53693405 100644 --- a/ApplicationCode/UserInterface/RiuQwtPlotTools.h +++ b/ApplicationCode/UserInterface/RiuQwtPlotTools.h @@ -17,6 +17,9 @@ ///////////////////////////////////////////////////////////////////////////////// #pragma once +#include "RiaQDateTimeTools.h" +#include + class QwtPlot; class RiuQwtPlotTools @@ -24,6 +27,8 @@ class RiuQwtPlotTools public: static void setCommonPlotBehaviour(QwtPlot* plot); static void setDefaultAxes(QwtPlot* plot); - static void enableDateBasedBottomXAxis(QwtPlot* plot); -}; + static void enableDateBasedBottomXAxis(QwtPlot* plot, const QString& dateFormat, const QString& timeFormat); + static QString + dateTimeFormatForInterval(QwtDate::IntervalType interval, const QString& dateFormat, const QString& timeFormat); +}; diff --git a/ApplicationCode/UserInterface/RiuResultQwtPlot.cpp b/ApplicationCode/UserInterface/RiuResultQwtPlot.cpp index 13e36fdd35..45d3a9d0ae 100644 --- a/ApplicationCode/UserInterface/RiuResultQwtPlot.cpp +++ b/ApplicationCode/UserInterface/RiuResultQwtPlot.cpp @@ -183,7 +183,10 @@ void RiuResultQwtPlot::setDefaults() enableAxis(QwtPlot::xTop, false); enableAxis(QwtPlot::yRight, false); - RiuQwtPlotTools::enableDateBasedBottomXAxis(this); + QString dateFormat = RiaApplication::instance()->preferences()->dateFormat(); + QString timeFormat = RiaApplication::instance()->preferences()->timeFormat(); + + RiuQwtPlotTools::enableDateBasedBottomXAxis(this, dateFormat, timeFormat); setAxisMaxMinor(QwtPlot::xBottom, 2); setAxisMaxMinor(QwtPlot::yLeft, 3); diff --git a/ApplicationCode/UserInterface/RiuSummaryQwtPlot.cpp b/ApplicationCode/UserInterface/RiuSummaryQwtPlot.cpp index 53939532e8..022e81c7bf 100644 --- a/ApplicationCode/UserInterface/RiuSummaryQwtPlot.cpp +++ b/ApplicationCode/UserInterface/RiuSummaryQwtPlot.cpp @@ -17,6 +17,9 @@ ///////////////////////////////////////////////////////////////////////////////// #include "RiuSummaryQwtPlot.h" +#include "RiaApplication.h" +#include "RiaPreferences.h" + #include "RimEnsembleCurveSet.h" #include "RimEnsembleCurveSetCollection.h" #include "RimMainPlotCollection.h" @@ -98,9 +101,10 @@ RiuSummaryQwtPlot::RiuSummaryQwtPlot(RimViewWindow* viewWindow, QWidget* parent //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RiuSummaryQwtPlot::useDateBasedTimeAxis() +void RiuSummaryQwtPlot::useDateBasedTimeAxis(const QString& dateFormat, + const QString& timeFormat) { - RiuQwtPlotTools::enableDateBasedBottomXAxis(this); + RiuQwtPlotTools::enableDateBasedBottomXAxis(this, dateFormat, timeFormat); } //-------------------------------------------------------------------------------------------------- @@ -198,7 +202,10 @@ void RiuSummaryQwtPlot::contextMenuEvent(QContextMenuEvent* event) //-------------------------------------------------------------------------------------------------- void RiuSummaryQwtPlot::setDefaults() { - useDateBasedTimeAxis(); + QString dateFormat = RiaApplication::instance()->preferences()->dateFormat(); + QString timeFormat = RiaApplication::instance()->preferences()->timeFormat(); + + useDateBasedTimeAxis(dateFormat, timeFormat); // The legend will be deleted in the destructor of the plot or when // another legend is inserted. diff --git a/ApplicationCode/UserInterface/RiuSummaryQwtPlot.h b/ApplicationCode/UserInterface/RiuSummaryQwtPlot.h index a70d9c068f..fd5b084646 100644 --- a/ApplicationCode/UserInterface/RiuSummaryQwtPlot.h +++ b/ApplicationCode/UserInterface/RiuSummaryQwtPlot.h @@ -18,6 +18,7 @@ #pragma once +#include "RiaQDateTimeTools.h" #include "RiuInterfaceToViewWindow.h" #include "RiuQwtPlot.h" @@ -40,7 +41,7 @@ class RiuSummaryQwtPlot : public RiuQwtPlot public: RiuSummaryQwtPlot(RimViewWindow* ownerViewWindow, QWidget* parent = nullptr); - void useDateBasedTimeAxis(); + void useDateBasedTimeAxis(const QString& dateFormat, const QString& timeFormat); void useTimeBasedTimeAxis(); void addOrUpdateEnsembleCurveSetLegend(RimEnsembleCurveSet* curveSetToShowLegendFor); diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmXml/cafInternalPdmStreamOperators.cpp b/Fwk/AppFwk/cafProjectDataModel/cafPdmXml/cafInternalPdmStreamOperators.cpp index 1e8b9155c7..1303000155 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmXml/cafInternalPdmStreamOperators.cpp +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmXml/cafInternalPdmStreamOperators.cpp @@ -41,3 +41,41 @@ QTextStream& operator << (QTextStream& str, const QDateTime& value) str << text; return str; } + +//-------------------------------------------------------------------------------------------------- +/// Specialized read operation for QDates +//-------------------------------------------------------------------------------------------------- +#include +QTextStream& operator >> (QTextStream& str, QDate& value) +{ + QString text; + str >> text; + value = QDate::fromString(text, "yyyy_MM_dd"); + return str; +} + +QTextStream& operator << (QTextStream& str, const QDate& value) +{ + QString text = value.toString("yyyy_MM_dd"); + str << text; + return str; +} + +//-------------------------------------------------------------------------------------------------- +/// Specialized read operation for QTimes +//-------------------------------------------------------------------------------------------------- +#include +QTextStream& operator >> (QTextStream& str, QTime& value) +{ + QString text; + str >> text; + value = QTime::fromString(text, "HH:mm:ss"); + return str; +} + +QTextStream& operator << (QTextStream& str, const QTime& value) +{ + QString text = value.toString("HH:mm:ss"); + str << text; + return str; +} diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmXml/cafInternalPdmStreamOperators.h b/Fwk/AppFwk/cafProjectDataModel/cafPdmXml/cafInternalPdmStreamOperators.h index 7d211ee841..ce4ffa9295 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmXml/cafInternalPdmStreamOperators.h +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmXml/cafInternalPdmStreamOperators.h @@ -19,6 +19,22 @@ QTextStream& operator << (QTextStream& str, const bool& value); QTextStream& operator >> (QTextStream& str, QDateTime& value); QTextStream& operator << (QTextStream& str, const QDateTime& value); +//================================================================================================== +/// QTextStream Stream operator overloading for QDates +/// +//================================================================================================== +//class QDate; +QTextStream& operator >> (QTextStream& str, QDate& value); +QTextStream& operator << (QTextStream& str, const QDate& value); + +//================================================================================================== +/// QTextStream Stream operator overloading for QTimes +/// +//================================================================================================== +//class QTime; +QTextStream& operator >> (QTextStream& str, QTime& value); +QTextStream& operator << (QTextStream& str, const QTime& value); + //================================================================================================== /// QTextStream Stream operator overloading for std::vector of things. diff --git a/Fwk/AppFwk/cafUserInterface/CMakeLists.txt b/Fwk/AppFwk/cafUserInterface/CMakeLists.txt index 247e12db1d..c2cdfe5763 100644 --- a/Fwk/AppFwk/cafUserInterface/CMakeLists.txt +++ b/Fwk/AppFwk/cafUserInterface/CMakeLists.txt @@ -15,6 +15,7 @@ set (MOC_HEADER_FILES cafPdmUiColorEditor.h cafPdmUiComboBoxEditor.h cafPdmUiDateEditor.h + cafPdmUiTimeEditor.h cafPdmUiDefaultObjectEditor.h cafPdmUiDoubleSliderEditor.h cafPdmUiFilePathEditor.h @@ -71,6 +72,8 @@ set( PROJECT_FILES cafPdmUiComboBoxEditor.h cafPdmUiDateEditor.cpp cafPdmUiDateEditor.h + cafPdmUiTimeEditor.cpp + cafPdmUiTimeEditor.h cafPdmUiDoubleSliderEditor.cpp cafPdmUiDoubleSliderEditor.h cafPdmUiDragDropInterface.h diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiDateEditor.cpp b/Fwk/AppFwk/cafUserInterface/cafPdmUiDateEditor.cpp index a4c719df53..ecbf6a7d94 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiDateEditor.cpp +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiDateEditor.cpp @@ -88,6 +88,7 @@ void PdmUiDateEditor::configureAndUpdateUi(const QString& uiConfigName) } m_dateEdit->setDate(uiField()->uiValue().toDate()); + m_dateEdit->setTime(uiField()->uiValue().toTime()); } @@ -96,7 +97,7 @@ void PdmUiDateEditor::configureAndUpdateUi(const QString& uiConfigName) //-------------------------------------------------------------------------------------------------- QWidget* PdmUiDateEditor::createEditorWidget(QWidget* parent) { - m_dateEdit = new QDateEdit(parent); + m_dateEdit = new QDateTimeEdit(parent); m_dateEdit->setCalendarPopup(true); connect(m_dateEdit, SIGNAL(editingFinished()), this, SLOT(slotEditingFinished())); return m_dateEdit; @@ -116,7 +117,7 @@ QWidget* PdmUiDateEditor::createLabelWidget(QWidget* parent) //-------------------------------------------------------------------------------------------------- void PdmUiDateEditor::slotEditingFinished() { - this->setValueToField(m_dateEdit->date()); + this->setValueToField(m_dateEdit->dateTime()); } } // end namespace caf diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiDateEditor.h b/Fwk/AppFwk/cafUserInterface/cafPdmUiDateEditor.h index 303876cd18..ab206a0653 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiDateEditor.h +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiDateEditor.h @@ -39,7 +39,7 @@ #include "cafPdmUiFieldEditorHandle.h" -#include +#include #include #include #include @@ -83,7 +83,7 @@ protected slots: void slotEditingFinished(); private: - QPointer m_dateEdit; + QPointer m_dateEdit; QPointer m_label; PdmUiDateEditorAttribute m_attributes; diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiDefaultObjectEditor.cpp b/Fwk/AppFwk/cafUserInterface/cafPdmUiDefaultObjectEditor.cpp index 033744442f..8865b5a066 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiDefaultObjectEditor.cpp +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiDefaultObjectEditor.cpp @@ -41,6 +41,7 @@ #include "cafPdmProxyValueField.h" #include "cafPdmUiCheckBoxEditor.h" #include "cafPdmUiDateEditor.h" +#include "cafPdmUiTimeEditor.h" #include "cafPdmUiFieldEditorHandle.h" #include "cafPdmUiFilePathEditor.h" #include "cafPdmUiLineEditor.h" @@ -57,6 +58,7 @@ CAF_PDM_UI_REGISTER_DEFAULT_FIELD_EDITOR(PdmUiCheckBoxEditor, bool); CAF_PDM_UI_REGISTER_DEFAULT_FIELD_EDITOR(PdmUiLineEditor, QString); CAF_PDM_UI_REGISTER_DEFAULT_FIELD_EDITOR(PdmUiDateEditor, QDate); CAF_PDM_UI_REGISTER_DEFAULT_FIELD_EDITOR(PdmUiDateEditor, QDateTime); +CAF_PDM_UI_REGISTER_DEFAULT_FIELD_EDITOR(PdmUiTimeEditor, QTime); CAF_PDM_UI_REGISTER_DEFAULT_FIELD_EDITOR(PdmUiLineEditor, int); CAF_PDM_UI_REGISTER_DEFAULT_FIELD_EDITOR(PdmUiLineEditor, double); CAF_PDM_UI_REGISTER_DEFAULT_FIELD_EDITOR(PdmUiLineEditor, float); diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiTimeEditor.cpp b/Fwk/AppFwk/cafUserInterface/cafPdmUiTimeEditor.cpp new file mode 100644 index 0000000000..ef3c333389 --- /dev/null +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiTimeEditor.cpp @@ -0,0 +1,121 @@ +//################################################################################################## +// +// Custom Visualization Core library +// Copyright (C) 2017 Ceetron Solutions AS +// +// This library may be used under the terms of either the GNU General Public License or +// the GNU Lesser General Public License as follows: +// +// GNU General Public License Usage +// This library 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. +// +// This library 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. +// +// GNU Lesser General Public License Usage +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This library 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 Lesser General Public License at <> +// for more details. +// +//################################################################################################## + + +#include "cafPdmUiTimeEditor.h" + +#include "cafFactory.h" +#include "cafPdmField.h" +#include "cafPdmObject.h" +#include "cafPdmUiDefaultObjectEditor.h" +#include "cafPdmUiFieldEditorHandle.h" +#include "cafPdmUiOrdering.h" +#include "cafSelectionManager.h" +#include "cafQShortenedLabel.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace caf +{ + + CAF_PDM_UI_FIELD_EDITOR_SOURCE_INIT(PdmUiTimeEditor); + + + //-------------------------------------------------------------------------------------------------- + /// + //-------------------------------------------------------------------------------------------------- + void PdmUiTimeEditor::configureAndUpdateUi(const QString& uiConfigName) + { + CAF_ASSERT(!m_timeEdit.isNull()); + + PdmUiFieldEditorHandle::updateLabelFromField(m_label, uiConfigName); + + m_timeEdit->setEnabled(!uiField()->isUiReadOnly(uiConfigName)); + + caf::PdmUiObjectHandle* uiObject = uiObj(uiField()->fieldHandle()->ownerObject()); + if (uiObject) + { + uiObject->editorAttribute(uiField()->fieldHandle(), uiConfigName, &m_attributes); + } + + if (!m_attributes.timeFormat.isEmpty()) + { + m_timeEdit->setDisplayFormat(m_attributes.timeFormat); + } + + m_timeEdit->setDate(uiField()->uiValue().toDate()); + } + + + //-------------------------------------------------------------------------------------------------- + /// + //-------------------------------------------------------------------------------------------------- + QWidget* PdmUiTimeEditor::createEditorWidget(QWidget* parent) + { + m_timeEdit = new QTimeEdit(parent); + connect(m_timeEdit, SIGNAL(editingFinished()), this, SLOT(slotEditingFinished())); + return m_timeEdit; + } + + //-------------------------------------------------------------------------------------------------- + /// + //-------------------------------------------------------------------------------------------------- + QWidget* PdmUiTimeEditor::createLabelWidget(QWidget* parent) + { + m_label = new QShortenedLabel(parent); + return m_label; + } + + //-------------------------------------------------------------------------------------------------- + /// + //-------------------------------------------------------------------------------------------------- + void PdmUiTimeEditor::slotEditingFinished() + { + this->setValueToField(m_timeEdit->date()); + } + +} // end namespace caf diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiTimeEditor.h b/Fwk/AppFwk/cafUserInterface/cafPdmUiTimeEditor.h new file mode 100644 index 0000000000..2e97b347d5 --- /dev/null +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiTimeEditor.h @@ -0,0 +1,93 @@ +//################################################################################################## +// +// Custom Visualization Core library +// Copyright (C) 2019- Ceetron Solutions AS +// +// This library may be used under the terms of either the GNU General Public License or +// the GNU Lesser General Public License as follows: +// +// GNU General Public License Usage +// This library 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. +// +// This library 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. +// +// GNU Lesser General Public License Usage +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This library 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 Lesser General Public License at <> +// for more details. +// +//################################################################################################## + + +#pragma once + +#include "cafPdmUiFieldEditorHandle.h" + +#include +#include +#include +#include +#include + +namespace caf +{ + + //================================================================================================== + /// + //================================================================================================== + class PdmUiTimeEditorAttribute : public PdmUiEditorAttribute + { + public: + QString timeFormat; + + public: + PdmUiTimeEditorAttribute() + { + } + }; + + //-------------------------------------------------------------------------------------------------- + /// + //-------------------------------------------------------------------------------------------------- + class PdmUiTimeEditor : public PdmUiFieldEditorHandle + { + Q_OBJECT + CAF_PDM_UI_FIELD_EDITOR_HEADER_INIT; + + public: + PdmUiTimeEditor() {} + ~PdmUiTimeEditor() override {} + + protected: + QWidget* createEditorWidget(QWidget * parent) override; + QWidget* createLabelWidget(QWidget * parent) override; + void configureAndUpdateUi(const QString& uiConfigName) override; + + protected slots: + void slotEditingFinished(); + + private: + QPointer m_timeEdit; + QPointer m_label; + + PdmUiTimeEditorAttribute m_attributes; + }; + + +} // end namespace caf From 17876c76ae6b6c5108385773ca3a84e98234af6f Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 19 Aug 2019 10:10:22 +0200 Subject: [PATCH 343/396] #4562 Summary : Group LGR categories at bottom of list --- .../RiuSummaryCurveDefSelection.cpp | 29 +++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/ApplicationCode/UserInterface/RiuSummaryCurveDefSelection.cpp b/ApplicationCode/UserInterface/RiuSummaryCurveDefSelection.cpp index d41a0d46fa..be1b2935ec 100644 --- a/ApplicationCode/UserInterface/RiuSummaryCurveDefSelection.cpp +++ b/ApplicationCode/UserInterface/RiuSummaryCurveDefSelection.cpp @@ -651,12 +651,31 @@ QList RiuSummaryCurveDefSelection::calculateValueOptions } else if (fieldNeedingOptions == &m_selectedSummaryCategories) { - for (size_t i = 0; i < caf::AppEnum::size(); ++i) - { - if (caf::AppEnum::fromIndex(i) == RifEclipseSummaryAddress::SUMMARY_ENSEMBLE_STATISTICS) continue; + std::vector sortedCategoriesForUi; - options.push_back(caf::PdmOptionItemInfo(caf::AppEnum::uiTextFromIndex(i), - caf::AppEnum::fromIndex(i))); + sortedCategoriesForUi.push_back(RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_FIELD); + sortedCategoriesForUi.push_back(RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_AQUIFER); + sortedCategoriesForUi.push_back(RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_NETWORK); + sortedCategoriesForUi.push_back(RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_MISC); + sortedCategoriesForUi.push_back(RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_REGION); + sortedCategoriesForUi.push_back(RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_REGION_2_REGION); + sortedCategoriesForUi.push_back(RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_WELL_GROUP); + sortedCategoriesForUi.push_back(RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_WELL); + sortedCategoriesForUi.push_back(RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_WELL_COMPLETION); + sortedCategoriesForUi.push_back(RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_WELL_SEGMENT); + sortedCategoriesForUi.push_back(RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_BLOCK); + sortedCategoriesForUi.push_back(RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_WELL_LGR); + sortedCategoriesForUi.push_back(RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_WELL_COMPLETION_LGR); + sortedCategoriesForUi.push_back(RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_BLOCK_LGR); + sortedCategoriesForUi.push_back(RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_CALCULATED); + sortedCategoriesForUi.push_back(RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_IMPORTED); + // NB SUMMARY_ENSEMBLE_STATISTICS is intentionally excluded + //categoriesForUiDisplay.push_back(RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_ENSEMBLE_STATISTICS); + + for (auto category : sortedCategoriesForUi) + { + auto uiText = caf::AppEnum::uiText(category); + options.push_back(caf::PdmOptionItemInfo(uiText, category)); } } else From 9a21ceb74fa2413483c466e645c82ab88db66bf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Fri, 16 Aug 2019 13:51:26 +0200 Subject: [PATCH 344/396] #4589 Recursive Import Dialog: Rename widgets to distinguish them from data --- .../Commands/RicFileHierarchyDialog.cpp | 122 +++++++++--------- .../Commands/RicFileHierarchyDialog.h | 14 +- 2 files changed, 68 insertions(+), 68 deletions(-) diff --git a/ApplicationCode/Commands/RicFileHierarchyDialog.cpp b/ApplicationCode/Commands/RicFileHierarchyDialog.cpp index c031b6c7d5..efa17e0a61 100644 --- a/ApplicationCode/Commands/RicFileHierarchyDialog.cpp +++ b/ApplicationCode/Commands/RicFileHierarchyDialog.cpp @@ -81,26 +81,26 @@ RicFileHierarchyDialog::RicFileHierarchyDialog(QWidget* parent) { // Create widgets m_rootDirLabel = new QLabel(); - m_rootDir = new QLineEdit(); + m_rootDirField = new QLineEdit(); m_browseButton = new QPushButton(); m_pathFilterLabel = new QLabel(); - m_pathFilter = new QLineEdit(); + m_pathFilterField = new QLineEdit(); m_fileFilterLabel = new QLabel(); - m_fileFilter = new QLineEdit(); - m_fileExtensionLabel = new QLabel(); + m_fileFilterField = new QLineEdit(); + //m_fileExtensionLabel = new QLabel(); m_effectiveFilterLabel = new QLabel(); - m_effectiveFilter = new QLabel(); + m_effectiveFilterContentLabel = new QLabel(); m_findOrCancelButton = new QPushButton(); m_fileListLabel = new QLabel(); - m_fileList = new QListWidget(); + m_fileListWidget = new QListWidget(); m_buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); // Connect to signals - connect(m_rootDir, SIGNAL(textChanged(const QString&)), this, SLOT(slotFilterChanged(const QString&))); - connect(m_pathFilter, SIGNAL(textChanged(const QString&)), this, SLOT(slotFilterChanged(const QString&))); - connect(m_fileFilter, SIGNAL(textChanged(const QString&)), this, SLOT(slotFilterChanged(const QString&))); - connect(m_fileList, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(slotFileListCustomMenuRequested(const QPoint&))); + connect(m_rootDirField, SIGNAL(textChanged(const QString&)), this, SLOT(slotFilterChanged(const QString&))); + connect(m_pathFilterField, SIGNAL(textChanged(const QString&)), this, SLOT(slotFilterChanged(const QString&))); + connect(m_fileFilterField, SIGNAL(textChanged(const QString&)), this, SLOT(slotFilterChanged(const QString&))); + connect(m_fileListWidget, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(slotFileListCustomMenuRequested(const QPoint&))); connect(m_findOrCancelButton, SIGNAL(clicked()), this, SLOT(slotFindOrCancelButtonClicked())); connect(m_buttons, SIGNAL(accepted()), this, SLOT(slotDialogOkClicked())); @@ -113,14 +113,14 @@ RicFileHierarchyDialog::RicFileHierarchyDialog(QWidget* parent) m_fileFilterLabel->setText("File pattern"); m_effectiveFilterLabel->setText("Effective filter"); - m_effectiveFilter->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); + m_effectiveFilterContentLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); m_fileListLabel->setText("Files found"); m_fileListLabel->setVisible(false); - m_fileList->setSelectionMode(QAbstractItemView::ExtendedSelection); - m_fileList->setVisible(false); - m_fileList->setContextMenuPolicy(Qt::CustomContextMenu); - m_fileList->setSortingEnabled(true); + m_fileListWidget->setSelectionMode(QAbstractItemView::ExtendedSelection); + m_fileListWidget->setVisible(false); + m_fileListWidget->setContextMenuPolicy(Qt::CustomContextMenu); + m_fileListWidget->setSortingEnabled(true); m_browseButton->setText("..."); m_browseButton->setFixedWidth(25); @@ -134,22 +134,22 @@ RicFileHierarchyDialog::RicFileHierarchyDialog(QWidget* parent) QGroupBox* inputGroup = new QGroupBox("Filter"); QGridLayout* inputGridLayout = new QGridLayout(); inputGridLayout->addWidget(m_rootDirLabel, 0, 0); - inputGridLayout->addWidget(m_rootDir, 0, 1); + inputGridLayout->addWidget(m_rootDirField, 0, 1); inputGridLayout->addWidget(m_browseButton, 0, 2); inputGridLayout->addWidget(m_pathFilterLabel, 1, 0); - inputGridLayout->addWidget(m_pathFilter, 1, 1); + inputGridLayout->addWidget(m_pathFilterField, 1, 1); inputGridLayout->addWidget(m_fileFilterLabel, 2, 0); - inputGridLayout->addWidget(m_fileFilter, 2, 1); - inputGridLayout->addWidget(m_fileExtensionLabel, 2, 2); + inputGridLayout->addWidget(m_fileFilterField, 2, 1); + //inputGridLayout->addWidget(m_fileExtensionLabel, 2, 2); inputGroup->setLayout(inputGridLayout); QGroupBox* outputGroup = new QGroupBox("Files"); QGridLayout* outputGridLayout = new QGridLayout(); outputGridLayout->addWidget(m_effectiveFilterLabel, 0, 0); - outputGridLayout->addWidget(m_effectiveFilter, 0, 1); + outputGridLayout->addWidget(m_effectiveFilterContentLabel, 0, 1); outputGridLayout->addWidget(m_findOrCancelButton, 0, 2); outputGridLayout->addWidget(m_fileListLabel, 1, 0); - outputGridLayout->addWidget(m_fileList, 1, 1, 1, 2); + outputGridLayout->addWidget(m_fileListWidget, 1, 1, 1, 2); outputGroup->setLayout(outputGridLayout); dialogLayout->addWidget(inputGroup); @@ -169,20 +169,20 @@ RicFileHierarchyDialog::RicFileHierarchyDialog(QWidget* parent) "This is indicated by \"...\" in the Effective Filter label below."; m_pathFilterLabel->setToolTip(pathFilterHelpText); - m_pathFilter->setToolTip(pathFilterHelpText); + m_pathFilterField->setToolTip(pathFilterHelpText); QString fileFilterHelpText = "The file filter uses normal wildcards, but is not allowed to contain path separators. "; m_fileFilterLabel->setToolTip(fileFilterHelpText); - m_fileFilter->setToolTip(fileFilterHelpText); + m_fileFilterField->setToolTip(fileFilterHelpText); QString effectiveFilterHelpText = "This label displays the complete filter that is being applied. \n" "The possible \"...\" indicates a complete recursive directory search."; m_effectiveFilterLabel->setToolTip(effectiveFilterHelpText); - m_effectiveFilter->setToolTip(effectiveFilterHelpText); + m_effectiveFilterContentLabel->setToolTip(effectiveFilterHelpText); } @@ -208,9 +208,9 @@ RicFileHierarchyDialogResult RicFileHierarchyDialog::runRecursiveSearchDialog(QW dialog.setWindowTitle(caption); - dialog.m_rootDir->setText(QDir::toNativeSeparators(dir)); - dialog.m_pathFilter->setText(QDir::toNativeSeparators(pathFilter)); - dialog.m_fileFilter->setText(fileNameFilter); + dialog.m_rootDirField->setText(QDir::toNativeSeparators(dir)); + dialog.m_pathFilterField->setText(QDir::toNativeSeparators(pathFilter)); + dialog.m_fileFilterField->setText(fileNameFilter); dialog.m_fileExtensions = trimLeftStrings(fileExtensions, "."); dialog.updateEffectiveFilter(); @@ -232,7 +232,7 @@ RicFileHierarchyDialogResult RicFileHierarchyDialog::runRecursiveSearchDialog(QW //-------------------------------------------------------------------------------------------------- QStringList RicFileHierarchyDialog::files() const { - return m_files; + return m_foundFiles; } //-------------------------------------------------------------------------------------------------- @@ -240,7 +240,7 @@ QStringList RicFileHierarchyDialog::files() const //-------------------------------------------------------------------------------------------------- QString RicFileHierarchyDialog::rootDirWithEndSeparator() const { - QString rootDir = RiaFilePathTools::toInternalSeparator(m_rootDir->text().trimmed()); + QString rootDir = RiaFilePathTools::toInternalSeparator(m_rootDirField->text().trimmed()); rootDir = RiaFilePathTools::removeDuplicatePathSeparators(rootDir); return RiaFilePathTools::appendSeparatorIfNo(rootDir); } @@ -250,7 +250,7 @@ QString RicFileHierarchyDialog::rootDirWithEndSeparator() const //-------------------------------------------------------------------------------------------------- QString RicFileHierarchyDialog::pathFilter() const { - QString pathFilter = m_pathFilter->text().trimmed(); + QString pathFilter = m_pathFilterField->text().trimmed(); pathFilter = RiaFilePathTools::toInternalSeparator(pathFilter); pathFilter.replace(QString("**"), QString("*")); return RiaFilePathTools::removeDuplicatePathSeparators(pathFilter); @@ -261,7 +261,7 @@ QString RicFileHierarchyDialog::pathFilter() const //-------------------------------------------------------------------------------------------------- QString RicFileHierarchyDialog::fileNameFilter() const { - return m_fileFilter->text().trimmed(); + return m_fileFilterField->text().trimmed(); } //-------------------------------------------------------------------------------------------------- @@ -297,7 +297,7 @@ QString RicFileHierarchyDialog::extensionFromFileNameFilter() const { for (const QString& ext : m_fileExtensions) { - if (m_fileFilter->text().endsWith(ext, Qt::CaseInsensitive)) + if (m_fileFilterField->text().endsWith(ext, Qt::CaseInsensitive)) { return ext; } @@ -320,7 +320,7 @@ void RicFileHierarchyDialog::appendToFileList(const QString& fileName) { QString itemText = fileName; itemText.remove(0, rootDirWithEndSeparator().size()); - QListWidgetItem* item = new QListWidgetItem(QDir::toNativeSeparators(itemText), m_fileList); + QListWidgetItem* item = new QListWidgetItem(QDir::toNativeSeparators(itemText), m_fileListWidget); item->setFlags(item->flags() | Qt::ItemIsUserCheckable); item->setCheckState(Qt::Checked); } @@ -330,8 +330,8 @@ void RicFileHierarchyDialog::appendToFileList(const QString& fileName) //-------------------------------------------------------------------------------------------------- void RicFileHierarchyDialog::clearFileList() { - m_files.clear(); - m_fileList->clear(); + m_foundFiles.clear(); + m_fileListWidget->clear(); m_fileListLabel->setText(FILES_FOUND_TEXT); setOkButtonEnabled(false); } @@ -373,8 +373,8 @@ void RicFileHierarchyDialog::updateStatus(Status status, const QString& extraTex lastStatusUpdate = now; - m_fileList->clear(); - new QListWidgetItem(newStatus, m_fileList); + m_fileListWidget->clear(); + new QListWidgetItem(newStatus, m_fileListWidget); } //-------------------------------------------------------------------------------------------------- @@ -382,7 +382,7 @@ void RicFileHierarchyDialog::updateStatus(Status status, const QString& extraTex //-------------------------------------------------------------------------------------------------- QStringList RicFileHierarchyDialog::findMatchingFiles() { - if (m_rootDir->text().isEmpty()) return QStringList(); + if (m_rootDirField->text().isEmpty()) return QStringList(); //const QStringList& dirs = buildDirectoryListRecursive(rootDir()); @@ -593,7 +593,7 @@ void RicFileHierarchyDialog::updateEffectiveFilter() effFilterText = RiaFilePathTools::removeDuplicatePathSeparators(effFilterText); // Present native separators to the user - m_effectiveFilter->setText(QDir::toNativeSeparators(effFilterText)); + m_effectiveFilterContentLabel->setText(QDir::toNativeSeparators(effFilterText)); } //-------------------------------------------------------------------------------------------------- @@ -609,10 +609,10 @@ void RicFileHierarchyDialog::setOkButtonEnabled(bool enabled) //-------------------------------------------------------------------------------------------------- void RicFileHierarchyDialog::warningIfInvalidCharacters() { - if (m_fileFilter->text().contains(QRegExp("[\\\\/:]"))) + if (m_fileFilterField->text().contains(QRegExp("[\\\\/:]"))) { - QToolTip::showText(m_fileFilter->mapToGlobal(QPoint(0, 0)), "File pattern contains invalid characters"); - m_effectiveFilter->setText("(Invalid filter)"); + QToolTip::showText(m_fileFilterField->mapToGlobal(QPoint(0, 0)), "File pattern contains invalid characters"); + m_effectiveFilterContentLabel->setText("(Invalid filter)"); } else { @@ -656,7 +656,7 @@ void RicFileHierarchyDialog::slotFileListCustomMenuRequested(const QPoint& point connect(action, SIGNAL(triggered()), SLOT(slotToggleFileListItems())); menu.addAction(action); - globalPoint = m_fileList->mapToGlobal(point); + globalPoint = m_fileListWidget->mapToGlobal(point); menu.exec(globalPoint); } @@ -665,7 +665,7 @@ void RicFileHierarchyDialog::slotFileListCustomMenuRequested(const QPoint& point //-------------------------------------------------------------------------------------------------- void RicFileHierarchyDialog::slotToggleFileListItems() { - for (auto& item : m_fileList->selectedItems()) + for (auto& item : m_fileListWidget->selectedItems()) { if ((item->flags() & Qt::ItemIsUserCheckable) != 0) { @@ -679,7 +679,7 @@ void RicFileHierarchyDialog::slotToggleFileListItems() //-------------------------------------------------------------------------------------------------- void RicFileHierarchyDialog::slotTurnOffFileListItems() { - for (auto& item : m_fileList->selectedItems()) + for (auto& item : m_fileListWidget->selectedItems()) { if ((item->flags() & Qt::ItemIsUserCheckable) != 0) { @@ -693,7 +693,7 @@ void RicFileHierarchyDialog::slotTurnOffFileListItems() //-------------------------------------------------------------------------------------------------- void RicFileHierarchyDialog::slotTurnOnFileListItems() { - for (auto& item : m_fileList->selectedItems()) + for (auto& item : m_fileListWidget->selectedItems()) { if ((item->flags() & Qt::ItemIsUserCheckable) != 0) { @@ -707,9 +707,9 @@ void RicFileHierarchyDialog::slotTurnOnFileListItems() //-------------------------------------------------------------------------------------------------- void RicFileHierarchyDialog::slotCopyFileItemText() { - if (m_fileList->currentItem()) + if (m_fileListWidget->currentItem()) { - QString relativePathText = m_fileList->currentItem()->text(); + QString relativePathText = m_fileListWidget->currentItem()->text(); RiaGuiApplication::instance()->clipboard()->setText(relativePathText); } } @@ -723,10 +723,10 @@ void RicFileHierarchyDialog::slotFindOrCancelButtonClicked() { clearFileList(); - if(!m_fileList->isVisible()) + if(!m_fileListWidget->isVisible()) { m_fileListLabel->setVisible(true); - m_fileList->setVisible(true); + m_fileListWidget->setVisible(true); if(height() < DEFAULT_DIALOG_FIND_HEIGHT) resize(width(), DEFAULT_DIALOG_FIND_HEIGHT); } @@ -734,7 +734,7 @@ void RicFileHierarchyDialog::slotFindOrCancelButtonClicked() m_findOrCancelButton->setText(FIND_BUTTON_CANCEL_TEXT); m_cancelPressed = false; - m_files = findMatchingFiles(); + m_foundFiles = findMatchingFiles(); m_findOrCancelButton->setText(FIND_BUTTON_FIND_TEXT); @@ -742,16 +742,16 @@ void RicFileHierarchyDialog::slotFindOrCancelButtonClicked() { clearFileList(); } - else if(m_files.isEmpty()) + else if(m_foundFiles.isEmpty()) { updateStatus(NO_FILES_FOUND); } else { - m_fileListLabel->setText(QString("%1\n(%2)").arg(FILES_FOUND_TEXT).arg(m_files.size())); + m_fileListLabel->setText(QString("%1\n(%2)").arg(FILES_FOUND_TEXT).arg(m_foundFiles.size())); } - setOkButtonEnabled(!m_files.isEmpty()); + setOkButtonEnabled(!m_foundFiles.isEmpty()); m_buttons->button(QDialogButtonBox::Ok)->setDefault(true); } else @@ -765,15 +765,15 @@ void RicFileHierarchyDialog::slotFindOrCancelButtonClicked() //-------------------------------------------------------------------------------------------------- void RicFileHierarchyDialog::slotDialogOkClicked() { - m_files.clear(); + m_foundFiles.clear(); - int itemCount = m_fileList->count(); + int itemCount = m_fileListWidget->count(); for (int i = 0; i < itemCount; i++) { - const QListWidgetItem* item = m_fileList->item(i); + const QListWidgetItem* item = m_fileListWidget->item(i); if ((item->flags() & Qt::ItemIsUserCheckable) != 0 && item->checkState()) { - m_files.push_back(rootDirWithEndSeparator() + RiaFilePathTools::toInternalSeparator(item->text())); + m_foundFiles.push_back(rootDirWithEndSeparator() + RiaFilePathTools::toInternalSeparator(item->text())); } } accept(); @@ -784,7 +784,7 @@ void RicFileHierarchyDialog::slotDialogOkClicked() //-------------------------------------------------------------------------------------------------- void RicFileHierarchyDialog::slotDialogCancelClicked() { - m_files = QStringList(); + m_foundFiles = QStringList(); m_cancelPressed = true; reject(); } @@ -794,8 +794,8 @@ void RicFileHierarchyDialog::slotDialogCancelClicked() //-------------------------------------------------------------------------------------------------- void RicFileHierarchyDialog::slotBrowseButtonClicked() { - QString folder = QFileDialog::getExistingDirectory(this, "Select root folder", m_rootDir->text()); - if(!folder.isEmpty()) m_rootDir->setText(QDir::toNativeSeparators(folder)); + QString folder = QFileDialog::getExistingDirectory(this, "Select root folder", m_rootDirField->text()); + if(!folder.isEmpty()) m_rootDirField->setText(QDir::toNativeSeparators(folder)); } diff --git a/ApplicationCode/Commands/RicFileHierarchyDialog.h b/ApplicationCode/Commands/RicFileHierarchyDialog.h index 0c6cb0243b..7a9c5c6c27 100644 --- a/ApplicationCode/Commands/RicFileHierarchyDialog.h +++ b/ApplicationCode/Commands/RicFileHierarchyDialog.h @@ -103,26 +103,26 @@ private slots: private: QLabel* m_rootDirLabel; - QLineEdit* m_rootDir; + QLineEdit* m_rootDirField; QPushButton* m_browseButton; QLabel* m_pathFilterLabel; - QLineEdit* m_pathFilter; + QLineEdit* m_pathFilterField; QLabel* m_fileFilterLabel; - QLineEdit* m_fileFilter; - QLabel* m_fileExtensionLabel; + QLineEdit* m_fileFilterField; + //QLabel* m_fileExtensionLabel; QLabel* m_effectiveFilterLabel; - QLabel* m_effectiveFilter; + QLabel* m_effectiveFilterContentLabel; QLabel* m_fileListLabel; - QListWidget* m_fileList; + QListWidget* m_fileListWidget; QPushButton* m_findOrCancelButton; QDialogButtonBox* m_buttons; - QStringList m_files; + QStringList m_foundFiles; QStringList m_fileExtensions; bool m_cancelPressed; From 19126d96ecadfb11069a5e9e55e89533744cde69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Fri, 16 Aug 2019 13:54:10 +0200 Subject: [PATCH 345/396] #4589 Recursive Import Dialog: Add a method to extract the root path from a search path string. Also added unit test for this --- .../Application/Tools/RiaFilePathTools.cpp | 34 ++++++++ .../Application/Tools/RiaFilePathTools.h | 1 + .../UnitTests/CMakeLists_files.cmake | 1 + .../UnitTests/RiaFilePathTools-Test.cpp | 85 +++++++++++++++++++ 4 files changed, 121 insertions(+) create mode 100644 ApplicationCode/UnitTests/RiaFilePathTools-Test.cpp diff --git a/ApplicationCode/Application/Tools/RiaFilePathTools.cpp b/ApplicationCode/Application/Tools/RiaFilePathTools.cpp index 75db3144d9..859b1951ab 100644 --- a/ApplicationCode/Application/Tools/RiaFilePathTools.cpp +++ b/ApplicationCode/Application/Tools/RiaFilePathTools.cpp @@ -20,6 +20,7 @@ #include "RiaFilePathTools.h" #include +#include //-------------------------------------------------------------------------------------------------- @@ -128,3 +129,36 @@ QString RiaFilePathTools::removeDuplicatePathSeparators(const QString& path) return correctedPath; } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RiaFilePathTools::rootSearchPathFromSearchFilter(const QString& searchFilter) +{ + std::set globStartCharacters = {'*', '?', '['}; // ']' not needed + + QStringList pathPartList = searchFilter.split(SEPARATOR); + + QStringList::iterator pathPartIt= pathPartList.begin(); + + for ( ; pathPartIt != pathPartList.end(); ++pathPartIt) + { + QString pathPart = *pathPartIt; + + // Remove allowed escaping of wildcards + + pathPart.replace("[[]", ""); + pathPart.replace("[]]", ""); + pathPart.replace("[?]", ""); + pathPart.replace("[*]", ""); + + if (pathPart.contains("*")) break; + if (pathPart.contains("?")) break; + if (pathPart.contains("[")) break; + + } + + pathPartList.erase(pathPartIt, pathPartList.end()); + + return pathPartList.join(SEPARATOR); +} diff --git a/ApplicationCode/Application/Tools/RiaFilePathTools.h b/ApplicationCode/Application/Tools/RiaFilePathTools.h index 3384fa29e6..c9fa71a1ab 100644 --- a/ApplicationCode/Application/Tools/RiaFilePathTools.h +++ b/ApplicationCode/Application/Tools/RiaFilePathTools.h @@ -41,4 +41,5 @@ public: static QString canonicalPath(const QString& path); static std::pair toFolderAndFileName(const QString& absFileName); static QString removeDuplicatePathSeparators(const QString& path); + static QString rootSearchPathFromSearchFilter(const QString& searchFilter); }; diff --git a/ApplicationCode/UnitTests/CMakeLists_files.cmake b/ApplicationCode/UnitTests/CMakeLists_files.cmake index 7f7dec4dcb..6b60930eee 100644 --- a/ApplicationCode/UnitTests/CMakeLists_files.cmake +++ b/ApplicationCode/UnitTests/CMakeLists_files.cmake @@ -51,6 +51,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RiaWeightedMean-Test.cpp ${CMAKE_CURRENT_LIST_DIR}/RiaWeightedGeometricMeanCalculator-Test.cpp ${CMAKE_CURRENT_LIST_DIR}/RiaWeightedHarmonicMeanCalculator-Test.cpp ${CMAKE_CURRENT_LIST_DIR}/RiaCellDividingTools-Test.cpp +${CMAKE_CURRENT_LIST_DIR}/RiaFilePathTools-Test.cpp ${CMAKE_CURRENT_LIST_DIR}/Intersect-Test.cpp ${CMAKE_CURRENT_LIST_DIR}/RifPerforationIntervalReader-Test.cpp ${CMAKE_CURRENT_LIST_DIR}/RimWellPathCompletions-Test.cpp diff --git a/ApplicationCode/UnitTests/RiaFilePathTools-Test.cpp b/ApplicationCode/UnitTests/RiaFilePathTools-Test.cpp new file mode 100644 index 0000000000..af7a91d979 --- /dev/null +++ b/ApplicationCode/UnitTests/RiaFilePathTools-Test.cpp @@ -0,0 +1,85 @@ +#include "gtest/gtest.h" + +#include "RiaFilePathTools.h" + +#include + +std::ostream& operator<< (std::ostream& out, const QString & text) +{ + out << text.toStdString(); + return out; +} + +//-------------------------------------------------------------------------------------------------- +TEST(RiaFilePathTools, rootSearchPathFromSearchFilter) +{ + { + QString testPath(""); + QString resultRootPath = RiaFilePathTools::rootSearchPathFromSearchFilter(testPath); + EXPECT_EQ(QString(""), resultRootPath); + } + + { + QString testPath("D:/"); + QString resultRootPath = RiaFilePathTools::rootSearchPathFromSearchFilter(testPath); + EXPECT_EQ(QString("D:/"), resultRootPath); + } + { + QString testPath("D:/A"); + QString resultRootPath = RiaFilePathTools::rootSearchPathFromSearchFilter(testPath); + EXPECT_EQ(QString("D:/A"), resultRootPath); + } + + { + QString testPath("D:/A/B[cd]/E"); + QString resultRootPath = RiaFilePathTools::rootSearchPathFromSearchFilter(testPath); + EXPECT_EQ(QString("D:/A"), resultRootPath); + } + { + QString testPath("/A/B[cd]/E"); + QString resultRootPath = RiaFilePathTools::rootSearchPathFromSearchFilter(testPath); + EXPECT_EQ(QString("/A"), resultRootPath); + } + { + QString testPath("/A/B?/E"); + QString resultRootPath = RiaFilePathTools::rootSearchPathFromSearchFilter(testPath); + EXPECT_EQ(QString("/A"), resultRootPath); + } + { + QString testPath("//A/B/E*"); + QString resultRootPath = RiaFilePathTools::rootSearchPathFromSearchFilter(testPath); + EXPECT_EQ(QString("//A/B"), resultRootPath); + } + { + QString testPath("//A/B/E"); + QString resultRootPath = RiaFilePathTools::rootSearchPathFromSearchFilter(testPath); + EXPECT_EQ(QString("//A/B/E"), resultRootPath); + } + { + QString testPath("//A/B/E/"); + QString resultRootPath = RiaFilePathTools::rootSearchPathFromSearchFilter(testPath); + EXPECT_EQ(QString("//A/B/E/"), resultRootPath); + } + + { + QString testPath("//A/B[[]/E/"); + QString resultRootPath = RiaFilePathTools::rootSearchPathFromSearchFilter(testPath); + EXPECT_EQ(QString("//A/B[[]/E/"), resultRootPath); + } + { + QString testPath("//A/B[]]/E/"); + QString resultRootPath = RiaFilePathTools::rootSearchPathFromSearchFilter(testPath); + EXPECT_EQ(QString("//A/B[]]/E/"), resultRootPath); + } + { + QString testPath("//A/B[*]/E/"); + QString resultRootPath = RiaFilePathTools::rootSearchPathFromSearchFilter(testPath); + EXPECT_EQ(QString("//A/B[*]/E/"), resultRootPath); + } + { + QString testPath("//A/B[?]/E/"); + QString resultRootPath = RiaFilePathTools::rootSearchPathFromSearchFilter(testPath); + EXPECT_EQ(QString("//A/B[?]/E/"), resultRootPath); + } + +} \ No newline at end of file From 7939e457f82a3df0baae980ed86447d6ca44c053 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Fri, 16 Aug 2019 14:10:45 +0200 Subject: [PATCH 346/396] #4589 Recursive Import Dialog: Rename to RicRecursiveFileSearchDialog --- .../Commands/CMakeLists_files.cmake | 6 +- ...RicCreateGridCaseGroupFromFilesFeature.cpp | 4 +- .../RicImportEclipseCasesFeature.cpp | 4 +- .../Commands/RicImportSummaryCasesFeature.cpp | 4 +- ...g.cpp => RicRecursiveFileSearchDialog.cpp} | 72 +++++++++---------- ...ialog.h => RicRecursiveFileSearchDialog.h} | 14 ++-- 6 files changed, 52 insertions(+), 52 deletions(-) rename ApplicationCode/Commands/{RicFileHierarchyDialog.cpp => RicRecursiveFileSearchDialog.cpp} (92%) rename ApplicationCode/Commands/{RicFileHierarchyDialog.h => RicRecursiveFileSearchDialog.h} (93%) diff --git a/ApplicationCode/Commands/CMakeLists_files.cmake b/ApplicationCode/Commands/CMakeLists_files.cmake index bbabfd08b5..86cac752e3 100644 --- a/ApplicationCode/Commands/CMakeLists_files.cmake +++ b/ApplicationCode/Commands/CMakeLists_files.cmake @@ -71,7 +71,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RicFlyToObjectFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicGridStatisticsDialog.h ${CMAKE_CURRENT_LIST_DIR}/RicShowGridStatisticsFeature.h -${CMAKE_CURRENT_LIST_DIR}/RicFileHierarchyDialog.h +${CMAKE_CURRENT_LIST_DIR}/RicRecursiveFileSearchDialog.h ${CMAKE_CURRENT_LIST_DIR}/RicSummaryCaseRestartDialog.h ${CMAKE_CURRENT_LIST_DIR}/RicImportEnsembleFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicImportSummaryGroupFeature.h @@ -148,7 +148,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RicFlyToObjectFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicGridStatisticsDialog.cpp ${CMAKE_CURRENT_LIST_DIR}/RicShowGridStatisticsFeature.cpp -${CMAKE_CURRENT_LIST_DIR}/RicFileHierarchyDialog.cpp +${CMAKE_CURRENT_LIST_DIR}/RicRecursiveFileSearchDialog.cpp ${CMAKE_CURRENT_LIST_DIR}/RicSummaryCaseRestartDialog.cpp ${CMAKE_CURRENT_LIST_DIR}/RicImportEnsembleFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicImportSummaryGroupFeature.cpp @@ -169,7 +169,7 @@ ${SOURCE_GROUP_SOURCE_FILES} list(APPEND QT_MOC_HEADERS ${CMAKE_CURRENT_LIST_DIR}/RicGridStatisticsDialog.h -${CMAKE_CURRENT_LIST_DIR}/RicFileHierarchyDialog.h +${CMAKE_CURRENT_LIST_DIR}/RicRecursiveFileSearchDialog.h ${CMAKE_CURRENT_LIST_DIR}/RicSummaryCaseRestartDialog.h ${CMAKE_CURRENT_LIST_DIR}/RicResampleDialog.h ) diff --git a/ApplicationCode/Commands/EclipseCommands/RicCreateGridCaseGroupFromFilesFeature.cpp b/ApplicationCode/Commands/EclipseCommands/RicCreateGridCaseGroupFromFilesFeature.cpp index 567ae6c791..47ddd2edfa 100644 --- a/ApplicationCode/Commands/EclipseCommands/RicCreateGridCaseGroupFromFilesFeature.cpp +++ b/ApplicationCode/Commands/EclipseCommands/RicCreateGridCaseGroupFromFilesFeature.cpp @@ -22,7 +22,7 @@ #include "RiaApplication.h" #include "RiaImportEclipseCaseTools.h" -#include "RicFileHierarchyDialog.h" +#include "RicRecursiveFileSearchDialog.h" #include "RimEclipseCaseCollection.h" #include "RiuMultiCaseImportDialog.h" @@ -50,7 +50,7 @@ void RicCreateGridCaseGroupFromFilesFeature::onActionTriggered(bool isChecked) RiaApplication* app = RiaApplication::instance(); QString defaultDir = app->lastUsedDialogDirectory("INPUT_FILES"); - RicFileHierarchyDialogResult result = RicFileHierarchyDialog::runRecursiveSearchDialog(nullptr, + RicRecursiveFileSearchDialogResult result = RicRecursiveFileSearchDialog::runRecursiveSearchDialog(nullptr, "Create Grid Case Group from Files", defaultDir, m_pathFilter, diff --git a/ApplicationCode/Commands/EclipseCommands/RicImportEclipseCasesFeature.cpp b/ApplicationCode/Commands/EclipseCommands/RicImportEclipseCasesFeature.cpp index 9bd97423a1..e229eda01b 100644 --- a/ApplicationCode/Commands/EclipseCommands/RicImportEclipseCasesFeature.cpp +++ b/ApplicationCode/Commands/EclipseCommands/RicImportEclipseCasesFeature.cpp @@ -23,7 +23,7 @@ #include "RiaApplication.h" -#include "RicFileHierarchyDialog.h" +#include "RicRecursiveFileSearchDialog.h" #include "RimEclipseCaseCollection.h" @@ -52,7 +52,7 @@ void RicImportEclipseCasesFeature::onActionTriggered(bool isChecked) RiaApplication* app = RiaApplication::instance(); QString defaultDir = app->lastUsedDialogDirectory("BINARY_GRID"); - RicFileHierarchyDialogResult result = RicFileHierarchyDialog::runRecursiveSearchDialog(nullptr, + RicRecursiveFileSearchDialogResult result = RicRecursiveFileSearchDialog::runRecursiveSearchDialog(nullptr, "Import Eclipse Cases", defaultDir, m_pathFilter, diff --git a/ApplicationCode/Commands/RicImportSummaryCasesFeature.cpp b/ApplicationCode/Commands/RicImportSummaryCasesFeature.cpp index 9730dfa701..f0bf868874 100644 --- a/ApplicationCode/Commands/RicImportSummaryCasesFeature.cpp +++ b/ApplicationCode/Commands/RicImportSummaryCasesFeature.cpp @@ -24,7 +24,7 @@ #include "RiaLogging.h" #include "RiaPreferences.h" -#include "RicFileHierarchyDialog.h" +#include "RicRecursiveFileSearchDialog.h" #include "RifSummaryCaseRestartSelector.h" @@ -242,7 +242,7 @@ QStringList RicImportSummaryCasesFeature::runRecursiveSummaryCaseFileSearchDialo RiaApplication* app = RiaApplication::instance(); QString defaultDir = app->lastUsedDialogDirectory(pathCacheName); - RicFileHierarchyDialogResult result = RicFileHierarchyDialog::runRecursiveSearchDialog( + RicRecursiveFileSearchDialogResult result = RicRecursiveFileSearchDialog::runRecursiveSearchDialog( nullptr, dialogTitle, defaultDir, m_pathFilter, m_fileNameFilter, QStringList(".SMSPEC")); // Remember filters diff --git a/ApplicationCode/Commands/RicFileHierarchyDialog.cpp b/ApplicationCode/Commands/RicRecursiveFileSearchDialog.cpp similarity index 92% rename from ApplicationCode/Commands/RicFileHierarchyDialog.cpp rename to ApplicationCode/Commands/RicRecursiveFileSearchDialog.cpp index efa17e0a61..5f5d779731 100644 --- a/ApplicationCode/Commands/RicFileHierarchyDialog.cpp +++ b/ApplicationCode/Commands/RicRecursiveFileSearchDialog.cpp @@ -16,7 +16,7 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RicFileHierarchyDialog.h" +#include "RicRecursiveFileSearchDialog.h" #include "ExportCommands/RicSnapshotViewToClipboardFeature.h" #include "ExportCommands/RicSnapshotViewToFileFeature.h" #include "ExportCommands/RicSnapshotFilenameGenerator.h" @@ -76,7 +76,7 @@ static void sortStringsByLength(QStringList& strings, bool ascending = t //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RicFileHierarchyDialog::RicFileHierarchyDialog(QWidget* parent) +RicRecursiveFileSearchDialog::RicRecursiveFileSearchDialog(QWidget* parent) : QDialog(parent, RiuTools::defaultDialogFlags()) { // Create widgets @@ -189,14 +189,14 @@ RicFileHierarchyDialog::RicFileHierarchyDialog(QWidget* parent) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RicFileHierarchyDialog::~RicFileHierarchyDialog() +RicRecursiveFileSearchDialog::~RicRecursiveFileSearchDialog() { } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RicFileHierarchyDialogResult RicFileHierarchyDialog::runRecursiveSearchDialog(QWidget *parent /*= 0*/, +RicRecursiveFileSearchDialogResult RicRecursiveFileSearchDialog::runRecursiveSearchDialog(QWidget *parent /*= 0*/, const QString &caption /*= QString()*/, const QString &dir /*= QString()*/, const QString &pathFilter /*= QString()*/, @@ -204,7 +204,7 @@ RicFileHierarchyDialogResult RicFileHierarchyDialog::runRecursiveSearchDialog(QW const QStringList &fileExtensions /*= QStringList()*/) { QStringList files; - RicFileHierarchyDialog dialog(parent); + RicRecursiveFileSearchDialog dialog(parent); dialog.setWindowTitle(caption); @@ -220,7 +220,7 @@ RicFileHierarchyDialogResult RicFileHierarchyDialog::runRecursiveSearchDialog(QW dialog.resize(DEFAULT_DIALOG_WIDTH, DEFAULT_DIALOG_INIT_HEIGHT); dialog.exec(); - return RicFileHierarchyDialogResult(dialog.result() == QDialog::Accepted, + return RicRecursiveFileSearchDialogResult(dialog.result() == QDialog::Accepted, dialog.files(), dialog.rootDirWithEndSeparator(), dialog.pathFilter(), @@ -230,7 +230,7 @@ RicFileHierarchyDialogResult RicFileHierarchyDialog::runRecursiveSearchDialog(QW //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QStringList RicFileHierarchyDialog::files() const +QStringList RicRecursiveFileSearchDialog::files() const { return m_foundFiles; } @@ -238,7 +238,7 @@ QStringList RicFileHierarchyDialog::files() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QString RicFileHierarchyDialog::rootDirWithEndSeparator() const +QString RicRecursiveFileSearchDialog::rootDirWithEndSeparator() const { QString rootDir = RiaFilePathTools::toInternalSeparator(m_rootDirField->text().trimmed()); rootDir = RiaFilePathTools::removeDuplicatePathSeparators(rootDir); @@ -248,7 +248,7 @@ QString RicFileHierarchyDialog::rootDirWithEndSeparator() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QString RicFileHierarchyDialog::pathFilter() const +QString RicRecursiveFileSearchDialog::pathFilter() const { QString pathFilter = m_pathFilterField->text().trimmed(); pathFilter = RiaFilePathTools::toInternalSeparator(pathFilter); @@ -259,7 +259,7 @@ QString RicFileHierarchyDialog::pathFilter() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QString RicFileHierarchyDialog::fileNameFilter() const +QString RicRecursiveFileSearchDialog::fileNameFilter() const { return m_fileFilterField->text().trimmed(); } @@ -267,7 +267,7 @@ QString RicFileHierarchyDialog::fileNameFilter() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QStringList RicFileHierarchyDialog::fileExtensions() const +QStringList RicRecursiveFileSearchDialog::fileExtensions() const { QString extFromFilter = extensionFromFileNameFilter(); if (!extFromFilter.isEmpty()) @@ -283,7 +283,7 @@ QStringList RicFileHierarchyDialog::fileExtensions() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QString RicFileHierarchyDialog::fileExtensionsText() const +QString RicRecursiveFileSearchDialog::fileExtensionsText() const { QString extFromFilter = extensionFromFileNameFilter(); if (!extFromFilter.isEmpty()) return ""; @@ -293,7 +293,7 @@ QString RicFileHierarchyDialog::fileExtensionsText() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QString RicFileHierarchyDialog::extensionFromFileNameFilter() const +QString RicRecursiveFileSearchDialog::extensionFromFileNameFilter() const { for (const QString& ext : m_fileExtensions) { @@ -308,7 +308,7 @@ QString RicFileHierarchyDialog::extensionFromFileNameFilter() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool RicFileHierarchyDialog::cancelPressed() const +bool RicRecursiveFileSearchDialog::cancelPressed() const { return m_cancelPressed; } @@ -316,7 +316,7 @@ bool RicFileHierarchyDialog::cancelPressed() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicFileHierarchyDialog::appendToFileList(const QString& fileName) +void RicRecursiveFileSearchDialog::appendToFileList(const QString& fileName) { QString itemText = fileName; itemText.remove(0, rootDirWithEndSeparator().size()); @@ -328,7 +328,7 @@ void RicFileHierarchyDialog::appendToFileList(const QString& fileName) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicFileHierarchyDialog::clearFileList() +void RicRecursiveFileSearchDialog::clearFileList() { m_foundFiles.clear(); m_fileListWidget->clear(); @@ -339,7 +339,7 @@ void RicFileHierarchyDialog::clearFileList() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicFileHierarchyDialog::updateStatus(Status status, const QString& extraText) +void RicRecursiveFileSearchDialog::updateStatus(Status status, const QString& extraText) { static int progressLoopStep = 0; static QTime lastStatusUpdate; @@ -380,7 +380,7 @@ void RicFileHierarchyDialog::updateStatus(Status status, const QString& extraTex //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QStringList RicFileHierarchyDialog::findMatchingFiles() +QStringList RicRecursiveFileSearchDialog::findMatchingFiles() { if (m_rootDirField->text().isEmpty()) return QStringList(); @@ -409,7 +409,7 @@ QStringList RicFileHierarchyDialog::findMatchingFiles() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QStringList RicFileHierarchyDialog::buildDirectoryListRecursive(const QString& currentDir, int level) +QStringList RicRecursiveFileSearchDialog::buildDirectoryListRecursive(const QString& currentDir, int level) { QStringList allDirs; @@ -458,7 +458,7 @@ QStringList RicFileHierarchyDialog::buildDirectoryListRecursive(const QString& c //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicFileHierarchyDialog::buildDirectoryListRecursiveSimple(const QString& currentDirFullPathNoEndSeparator, +void RicRecursiveFileSearchDialog::buildDirectoryListRecursiveSimple(const QString& currentDirFullPathNoEndSeparator, const QString& currentPathFilterNoEndSeparator, QStringList* accumulatedDirs) { @@ -513,7 +513,7 @@ void RicFileHierarchyDialog::buildDirectoryListRecursiveSimple(const QString& cu //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QStringList RicFileHierarchyDialog::findFilesInDirs(const QStringList& dirs) +QStringList RicRecursiveFileSearchDialog::findFilesInDirs(const QStringList& dirs) { QStringList allFiles; QStringList filters = createFileNameFilterList(); @@ -540,7 +540,7 @@ QStringList RicFileHierarchyDialog::findFilesInDirs(const QStringList& dirs) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QStringList RicFileHierarchyDialog::createFileNameFilterList() +QStringList RicRecursiveFileSearchDialog::createFileNameFilterList() { QString fileNameFilter = this->fileNameFilter(); QStringList fileExtensions = this->fileExtensions(); @@ -565,7 +565,7 @@ QStringList RicFileHierarchyDialog::createFileNameFilterList() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool RicFileHierarchyDialog::pathFilterMatch(const QString& pathFilter, const QString& relPath) +bool RicRecursiveFileSearchDialog::pathFilterMatch(const QString& pathFilter, const QString& relPath) { QString pattern = pathFilter; if (relPath.endsWith(SEPARATOR) && !pathFilter.endsWith(SEPARATOR)) pattern += SEPARATOR; @@ -576,7 +576,7 @@ bool RicFileHierarchyDialog::pathFilterMatch(const QString& pathFilter, const QS //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicFileHierarchyDialog::updateEffectiveFilter() +void RicRecursiveFileSearchDialog::updateEffectiveFilter() { QString pathFilterText = pathFilter(); if (pathFilterText == "*" || pathFilterText.endsWith(QString(SEPARATOR) + "*")) @@ -599,7 +599,7 @@ void RicFileHierarchyDialog::updateEffectiveFilter() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicFileHierarchyDialog::setOkButtonEnabled(bool enabled) +void RicRecursiveFileSearchDialog::setOkButtonEnabled(bool enabled) { m_buttons->button(QDialogButtonBox::Ok)->setEnabled(enabled); } @@ -607,7 +607,7 @@ void RicFileHierarchyDialog::setOkButtonEnabled(bool enabled) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicFileHierarchyDialog::warningIfInvalidCharacters() +void RicRecursiveFileSearchDialog::warningIfInvalidCharacters() { if (m_fileFilterField->text().contains(QRegExp("[\\\\/:]"))) { @@ -623,7 +623,7 @@ void RicFileHierarchyDialog::warningIfInvalidCharacters() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicFileHierarchyDialog::slotFilterChanged(const QString& text) +void RicRecursiveFileSearchDialog::slotFilterChanged(const QString& text) { updateEffectiveFilter(); warningIfInvalidCharacters(); @@ -633,7 +633,7 @@ void RicFileHierarchyDialog::slotFilterChanged(const QString& text) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicFileHierarchyDialog::slotFileListCustomMenuRequested(const QPoint& point) +void RicRecursiveFileSearchDialog::slotFileListCustomMenuRequested(const QPoint& point) { QMenu menu; QPoint globalPoint = point; @@ -663,7 +663,7 @@ void RicFileHierarchyDialog::slotFileListCustomMenuRequested(const QPoint& point //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicFileHierarchyDialog::slotToggleFileListItems() +void RicRecursiveFileSearchDialog::slotToggleFileListItems() { for (auto& item : m_fileListWidget->selectedItems()) { @@ -677,7 +677,7 @@ void RicFileHierarchyDialog::slotToggleFileListItems() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicFileHierarchyDialog::slotTurnOffFileListItems() +void RicRecursiveFileSearchDialog::slotTurnOffFileListItems() { for (auto& item : m_fileListWidget->selectedItems()) { @@ -691,7 +691,7 @@ void RicFileHierarchyDialog::slotTurnOffFileListItems() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicFileHierarchyDialog::slotTurnOnFileListItems() +void RicRecursiveFileSearchDialog::slotTurnOnFileListItems() { for (auto& item : m_fileListWidget->selectedItems()) { @@ -705,7 +705,7 @@ void RicFileHierarchyDialog::slotTurnOnFileListItems() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicFileHierarchyDialog::slotCopyFileItemText() +void RicRecursiveFileSearchDialog::slotCopyFileItemText() { if (m_fileListWidget->currentItem()) { @@ -717,7 +717,7 @@ void RicFileHierarchyDialog::slotCopyFileItemText() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicFileHierarchyDialog::slotFindOrCancelButtonClicked() +void RicRecursiveFileSearchDialog::slotFindOrCancelButtonClicked() { if (m_findOrCancelButton->text() == FIND_BUTTON_FIND_TEXT) { @@ -763,7 +763,7 @@ void RicFileHierarchyDialog::slotFindOrCancelButtonClicked() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicFileHierarchyDialog::slotDialogOkClicked() +void RicRecursiveFileSearchDialog::slotDialogOkClicked() { m_foundFiles.clear(); @@ -782,7 +782,7 @@ void RicFileHierarchyDialog::slotDialogOkClicked() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicFileHierarchyDialog::slotDialogCancelClicked() +void RicRecursiveFileSearchDialog::slotDialogCancelClicked() { m_foundFiles = QStringList(); m_cancelPressed = true; @@ -792,7 +792,7 @@ void RicFileHierarchyDialog::slotDialogCancelClicked() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicFileHierarchyDialog::slotBrowseButtonClicked() +void RicRecursiveFileSearchDialog::slotBrowseButtonClicked() { QString folder = QFileDialog::getExistingDirectory(this, "Select root folder", m_rootDirField->text()); if(!folder.isEmpty()) m_rootDirField->setText(QDir::toNativeSeparators(folder)); diff --git a/ApplicationCode/Commands/RicFileHierarchyDialog.h b/ApplicationCode/Commands/RicRecursiveFileSearchDialog.h similarity index 93% rename from ApplicationCode/Commands/RicFileHierarchyDialog.h rename to ApplicationCode/Commands/RicRecursiveFileSearchDialog.h index 7a9c5c6c27..5b243a7bc4 100644 --- a/ApplicationCode/Commands/RicFileHierarchyDialog.h +++ b/ApplicationCode/Commands/RicRecursiveFileSearchDialog.h @@ -31,22 +31,22 @@ class QDialogButtonBox; class QPushButton; class QMainWindow; class QListWidget; -class RicFileHierarchyDialogResult; +class RicRecursiveFileSearchDialogResult; //================================================================================================== /// //================================================================================================== -class RicFileHierarchyDialog : public QDialog +class RicRecursiveFileSearchDialog : public QDialog { Q_OBJECT enum Status {SEARCHING_FOR_DIRS, SEARCHING_FOR_FILES, NO_FILES_FOUND}; public: - RicFileHierarchyDialog(QWidget* parent); - ~RicFileHierarchyDialog() override; + RicRecursiveFileSearchDialog(QWidget* parent); + ~RicRecursiveFileSearchDialog() override; - static RicFileHierarchyDialogResult runRecursiveSearchDialog(QWidget *parent = nullptr, + static RicRecursiveFileSearchDialogResult runRecursiveSearchDialog(QWidget *parent = nullptr, const QString& caption = QString(), const QString& dir = QString(), const QString& pathFilter = QString(), @@ -132,10 +132,10 @@ private: //================================================================================================== /// //================================================================================================== -class RicFileHierarchyDialogResult +class RicRecursiveFileSearchDialogResult { public: - RicFileHierarchyDialogResult(bool ok, + RicRecursiveFileSearchDialogResult(bool ok, const QStringList& files, const QString& rootDir, const QString& pathFilter, From 8c144dce7f641e5d988b79a814da3b5898599044 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Mon, 19 Aug 2019 09:43:58 +0200 Subject: [PATCH 347/396] #4589 Recursive Import Dialog: Merged Root and path filter into one field Add "Root" label to show the root of the found files --- .../Commands/RicRecursiveFileSearchDialog.cpp | 238 +++++++++--------- .../Commands/RicRecursiveFileSearchDialog.h | 17 +- 2 files changed, 126 insertions(+), 129 deletions(-) diff --git a/ApplicationCode/Commands/RicRecursiveFileSearchDialog.cpp b/ApplicationCode/Commands/RicRecursiveFileSearchDialog.cpp index 5f5d779731..e32009a299 100644 --- a/ApplicationCode/Commands/RicRecursiveFileSearchDialog.cpp +++ b/ApplicationCode/Commands/RicRecursiveFileSearchDialog.cpp @@ -17,17 +17,10 @@ ///////////////////////////////////////////////////////////////////////////////// #include "RicRecursiveFileSearchDialog.h" -#include "ExportCommands/RicSnapshotViewToClipboardFeature.h" -#include "ExportCommands/RicSnapshotViewToFileFeature.h" -#include "ExportCommands/RicSnapshotFilenameGenerator.h" #include "RiaGuiApplication.h" #include "RiaFilePathTools.h" -#include "RimEclipseView.h" -#include "Rim3dOverlayInfoConfig.h" - -#include "RiuPlotMainWindow.h" #include "RiuTools.h" #include @@ -48,17 +41,9 @@ #include #include -#include -#include -#define DEFAULT_DIALOG_WIDTH 750 -#define DEFAULT_DIALOG_INIT_HEIGHT 150 #define DEFAULT_DIALOG_FIND_HEIGHT 350 #define FIND_BUTTON_FIND_TEXT "Find" -#define FIND_BUTTON_CANCEL_TEXT "Cancel" -#define NO_FILES_FOUND_TEXT "No files found" -#define SCANNING_DIRS_TEXT "Scanning Directories" -#define FINDING_FILES_TEXT "Finding Files" #define FILES_FOUND_TEXT "Files found" //-------------------------------------------------------------------------------------------------- @@ -80,43 +65,48 @@ RicRecursiveFileSearchDialog::RicRecursiveFileSearchDialog(QWidget* parent) : QDialog(parent, RiuTools::defaultDialogFlags()) { // Create widgets - m_rootDirLabel = new QLabel(); - m_rootDirField = new QLineEdit(); - m_browseButton = new QPushButton(); - m_pathFilterLabel = new QLabel(); - m_pathFilterField = new QLineEdit(); - m_fileFilterLabel = new QLabel(); - m_fileFilterField = new QLineEdit(); - //m_fileExtensionLabel = new QLabel(); - m_effectiveFilterLabel = new QLabel(); + m_browseButton = new QPushButton(); + m_pathFilterLabel = new QLabel(); + m_pathFilterField = new QLineEdit(); + m_fileFilterLabel = new QLabel(); + m_fileFilterField = new QLineEdit(); + m_effectiveFilterLabel = new QLabel(); m_effectiveFilterContentLabel = new QLabel(); - m_findOrCancelButton = new QPushButton(); - m_fileListLabel = new QLabel(); - m_fileListWidget = new QListWidget(); + m_searchRootLabel = new QLabel(); + m_searchRootContentLabel = new QLabel(); + m_findOrCancelButton = new QPushButton(); + m_fileListLabel = new QLabel(); + m_fileListWidget = new QListWidget(); m_buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); // Connect to signals - connect(m_rootDirField, SIGNAL(textChanged(const QString&)), this, SLOT(slotFilterChanged(const QString&))); connect(m_pathFilterField, SIGNAL(textChanged(const QString&)), this, SLOT(slotFilterChanged(const QString&))); connect(m_fileFilterField, SIGNAL(textChanged(const QString&)), this, SLOT(slotFilterChanged(const QString&))); + connect(m_fileListWidget, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(slotFileListCustomMenuRequested(const QPoint&))); + connect(m_browseButton, SIGNAL(clicked()), this, SLOT(slotBrowseButtonClicked())); + connect(m_findOrCancelButton, SIGNAL(clicked()), this, SLOT(slotFindOrCancelButtonClicked())); + connect(m_buttons, SIGNAL(accepted()), this, SLOT(slotDialogOkClicked())); connect(m_buttons, SIGNAL(rejected()), this, SLOT(slotDialogCancelClicked())); - connect(m_browseButton, SIGNAL(clicked()), this, SLOT(slotBrowseButtonClicked())); // Set widget properties - m_rootDirLabel->setText("Root folder"); m_pathFilterLabel->setText("Path pattern"); - m_fileFilterLabel->setText("File pattern"); m_effectiveFilterLabel->setText("Effective filter"); - m_effectiveFilterContentLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); + m_searchRootLabel->setText("Root"); + m_searchRootLabel->setVisible(false); + m_fileListLabel->setText("Files found"); m_fileListLabel->setVisible(false); - + + m_effectiveFilterContentLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); + m_searchRootContentLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); + m_searchRootContentLabel->setVisible(false); + m_fileListWidget->setSelectionMode(QAbstractItemView::ExtendedSelection); m_fileListWidget->setVisible(false); m_fileListWidget->setContextMenuPolicy(Qt::CustomContextMenu); @@ -124,6 +114,7 @@ RicRecursiveFileSearchDialog::RicRecursiveFileSearchDialog(QWidget* parent) m_browseButton->setText("..."); m_browseButton->setFixedWidth(25); + m_findOrCancelButton->setText(FIND_BUTTON_FIND_TEXT); m_findOrCancelButton->setFixedWidth(75); m_findOrCancelButton->setDefault(true); @@ -133,23 +124,24 @@ RicRecursiveFileSearchDialog::RicRecursiveFileSearchDialog(QWidget* parent) QGroupBox* inputGroup = new QGroupBox("Filter"); QGridLayout* inputGridLayout = new QGridLayout(); - inputGridLayout->addWidget(m_rootDirLabel, 0, 0); - inputGridLayout->addWidget(m_rootDirField, 0, 1); + inputGridLayout->addWidget(m_pathFilterLabel, 0, 0); + inputGridLayout->addWidget(m_pathFilterField, 0, 1); inputGridLayout->addWidget(m_browseButton, 0, 2); - inputGridLayout->addWidget(m_pathFilterLabel, 1, 0); - inputGridLayout->addWidget(m_pathFilterField, 1, 1); - inputGridLayout->addWidget(m_fileFilterLabel, 2, 0); - inputGridLayout->addWidget(m_fileFilterField, 2, 1); - //inputGridLayout->addWidget(m_fileExtensionLabel, 2, 2); + inputGridLayout->addWidget(m_fileFilterLabel, 1, 0); + inputGridLayout->addWidget(m_fileFilterField, 1, 1); + inputGroup->setLayout(inputGridLayout); QGroupBox* outputGroup = new QGroupBox("Files"); QGridLayout* outputGridLayout = new QGridLayout(); outputGridLayout->addWidget(m_effectiveFilterLabel, 0, 0); outputGridLayout->addWidget(m_effectiveFilterContentLabel, 0, 1); + outputGridLayout->addWidget(m_searchRootLabel, 1, 0); + outputGridLayout->addWidget(m_searchRootContentLabel, 1, 1); + outputGridLayout->addWidget(m_findOrCancelButton, 0, 2); - outputGridLayout->addWidget(m_fileListLabel, 1, 0); - outputGridLayout->addWidget(m_fileListWidget, 1, 1, 1, 2); + outputGridLayout->addWidget(m_fileListLabel, 2, 0); + outputGridLayout->addWidget(m_fileListWidget, 2, 1, 1, 2); outputGroup->setLayout(outputGridLayout); dialogLayout->addWidget(inputGroup); @@ -160,13 +152,17 @@ RicRecursiveFileSearchDialog::RicRecursiveFileSearchDialog(QWidget* parent) QString pathFilterHelpText = "The path filter uses normal wildcard file globbing, like in any unix shell. \n" + "When the filter ends with a single \"*\", however, ResInsight will \n" + "search recursively in all subdirectories from that point.\n" + "This is indicated by \"...\" in the Effective Filter label below." "\n" "An asterix \"*\" matches any number of any characters, except the path separator.\n" "A question mark \"?\" matches any single character, except the path separator.\n" - "\n" - "When the filter ends with a single \"*\", however, ResInsight will \n" - "search recursively in all subdirectories from that point.\n" - "This is indicated by \"...\" in the Effective Filter label below."; + "Square brackets \"[]\" encloses a list of characters and matches one of the enclosed characters.\n" + "they are also used to escape the characters *,? and []"; + + + // https://doc.qt.io/qt-5/qregularexpression.html#wildcardToRegularExpression m_pathFilterLabel->setToolTip(pathFilterHelpText); m_pathFilterField->setToolTip(pathFilterHelpText); @@ -196,20 +192,21 @@ RicRecursiveFileSearchDialog::~RicRecursiveFileSearchDialog() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RicRecursiveFileSearchDialogResult RicRecursiveFileSearchDialog::runRecursiveSearchDialog(QWidget *parent /*= 0*/, - const QString &caption /*= QString()*/, - const QString &dir /*= QString()*/, - const QString &pathFilter /*= QString()*/, - const QString &fileNameFilter /*= QString()*/, - const QStringList &fileExtensions /*= QStringList()*/) +RicRecursiveFileSearchDialogResult RicRecursiveFileSearchDialog::runRecursiveSearchDialog(QWidget *parent, + const QString &caption, + const QString &dir, + const QString &pathFilter , + const QString &fileNameFilter, + const QStringList &fileExtensions) { - QStringList files; RicRecursiveFileSearchDialog dialog(parent); dialog.setWindowTitle(caption); - dialog.m_rootDirField->setText(QDir::toNativeSeparators(dir)); - dialog.m_pathFilterField->setText(QDir::toNativeSeparators(pathFilter)); + QString pathFilterText = dir; + RiaFilePathTools::appendSeparatorIfNo(pathFilterText); + pathFilterText += pathFilter; + dialog.m_pathFilterField->setText(QDir::toNativeSeparators(pathFilterText)); dialog.m_fileFilterField->setText(fileNameFilter); dialog.m_fileExtensions = trimLeftStrings(fileExtensions, "."); @@ -217,22 +214,23 @@ RicRecursiveFileSearchDialogResult RicRecursiveFileSearchDialog::runRecursiveSea dialog.clearFileList(); dialog.setOkButtonEnabled(false); - dialog.resize(DEFAULT_DIALOG_WIDTH, DEFAULT_DIALOG_INIT_HEIGHT); + dialog.resize(750, 150); dialog.exec(); - return RicRecursiveFileSearchDialogResult(dialog.result() == QDialog::Accepted, - dialog.files(), - dialog.rootDirWithEndSeparator(), - dialog.pathFilter(), - dialog.fileNameFilter()); + return RicRecursiveFileSearchDialogResult(dialog.result() == QDialog::Accepted, + dialog.m_foundFiles, + dialog.rootDirWithEndSeparator(), + dialog.pathFilterWithoutStartSeparator(), + dialog.fileNameFilter()); } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -QStringList RicRecursiveFileSearchDialog::files() const +QString RicRecursiveFileSearchDialog::cleanTextFromPathFilterField() const { - return m_foundFiles; + QString pathFilterText = m_pathFilterField->text().trimmed(); + pathFilterText = RiaFilePathTools::toInternalSeparator(pathFilterText); + pathFilterText = RiaFilePathTools::removeDuplicatePathSeparators(pathFilterText); + pathFilterText.replace(QString("**"), QString("*")); + return pathFilterText; } //-------------------------------------------------------------------------------------------------- @@ -240,20 +238,22 @@ QStringList RicRecursiveFileSearchDialog::files() const //-------------------------------------------------------------------------------------------------- QString RicRecursiveFileSearchDialog::rootDirWithEndSeparator() const { - QString rootDir = RiaFilePathTools::toInternalSeparator(m_rootDirField->text().trimmed()); - rootDir = RiaFilePathTools::removeDuplicatePathSeparators(rootDir); + QString rootDir = this->cleanTextFromPathFilterField(); + rootDir = RiaFilePathTools::rootSearchPathFromSearchFilter(rootDir); return RiaFilePathTools::appendSeparatorIfNo(rootDir); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QString RicRecursiveFileSearchDialog::pathFilter() const +QString RicRecursiveFileSearchDialog::pathFilterWithoutStartSeparator() const { - QString pathFilter = m_pathFilterField->text().trimmed(); - pathFilter = RiaFilePathTools::toInternalSeparator(pathFilter); - pathFilter.replace(QString("**"), QString("*")); - return RiaFilePathTools::removeDuplicatePathSeparators(pathFilter); + QString pathFilter = this->cleanTextFromPathFilterField(); + QString rootDir = RiaFilePathTools::rootSearchPathFromSearchFilter(pathFilter); + + pathFilter.remove(0, rootDir.size()); + if (pathFilter.startsWith(SEPARATOR)) pathFilter.remove(0, 1); + return pathFilter; } //-------------------------------------------------------------------------------------------------- @@ -308,21 +308,22 @@ QString RicRecursiveFileSearchDialog::extensionFromFileNameFilter() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool RicRecursiveFileSearchDialog::cancelPressed() const +void RicRecursiveFileSearchDialog::updateFileListWidget() { - return m_cancelPressed; -} + m_fileListWidget->clear(); + m_fileListLabel->setText(FILES_FOUND_TEXT); -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RicRecursiveFileSearchDialog::appendToFileList(const QString& fileName) -{ - QString itemText = fileName; - itemText.remove(0, rootDirWithEndSeparator().size()); - QListWidgetItem* item = new QListWidgetItem(QDir::toNativeSeparators(itemText), m_fileListWidget); - item->setFlags(item->flags() | Qt::ItemIsUserCheckable); - item->setCheckState(Qt::Checked); + + int rootSearchPathLenght = rootDirWithEndSeparator().size(); + + for (const auto& fileName : m_foundFiles) + { + QString itemText = fileName; + itemText.remove(0, rootSearchPathLenght); + QListWidgetItem* item = new QListWidgetItem(QDir::toNativeSeparators(itemText), m_fileListWidget); + item->setFlags(item->flags() | Qt::ItemIsUserCheckable); + item->setCheckState(Qt::Checked); + } } //-------------------------------------------------------------------------------------------------- @@ -353,8 +354,8 @@ void RicRecursiveFileSearchDialog::updateStatus(Status status, const QString& ex { switch ( status ) { - case SEARCHING_FOR_DIRS: newStatus = SCANNING_DIRS_TEXT; break; - case SEARCHING_FOR_FILES: newStatus = FINDING_FILES_TEXT; break; + case SEARCHING_FOR_DIRS: newStatus = "Scanning Directories"; break; + case SEARCHING_FOR_FILES: newStatus = "Finding Files"; break; } for (int progress = 0; progress < progressLoopStep; ++progress) @@ -368,7 +369,7 @@ void RicRecursiveFileSearchDialog::updateStatus(Status status, const QString& ex } else if (status == NO_FILES_FOUND) { - newStatus = NO_FILES_FOUND_TEXT; + newStatus = "No files found"; } lastStatusUpdate = now; @@ -382,28 +383,18 @@ void RicRecursiveFileSearchDialog::updateStatus(Status status, const QString& ex //-------------------------------------------------------------------------------------------------- QStringList RicRecursiveFileSearchDialog::findMatchingFiles() { - if (m_rootDirField->text().isEmpty()) return QStringList(); - - //const QStringList& dirs = buildDirectoryListRecursive(rootDir()); + if (cleanTextFromPathFilterField().isEmpty()) return QStringList(); QStringList dirs; - QString pathFilter = this->pathFilter(); - if (pathFilter.startsWith(SEPARATOR)) pathFilter.remove(0, 1); + QString pathFilter = this->pathFilterWithoutStartSeparator(); QString rootDir = this->rootDirWithEndSeparator(); if (rootDir.endsWith(SEPARATOR)) rootDir.chop(1); buildDirectoryListRecursiveSimple(rootDir, pathFilter, &dirs); + - const QStringList& files = findFilesInDirs(dirs); - - this->clearFileList(); - - for (const auto& file : files) - { - appendToFileList(file); - } - return files; + return findFilesInDirs(dirs); } //-------------------------------------------------------------------------------------------------- @@ -413,15 +404,15 @@ QStringList RicRecursiveFileSearchDialog::buildDirectoryListRecursive(const QStr { QStringList allDirs; - if (cancelPressed()) return allDirs; + if (m_isCancelPressed) return allDirs; - QString currPathFilter = pathFilter(); + QString currPathFilter = pathFilterWithoutStartSeparator(); bool subStringFilter = false; // Optimizing for speed by a refined match at first directory level if (level == 1) { - QString pathFilter = this->pathFilter(); + QString pathFilter = this->pathFilterWithoutStartSeparator(); if (!pathFilter.startsWith("*")) { int wildcardIndex = pathFilter.indexOf(QRegExp(QString("[*%1]").arg(SEPARATOR))); @@ -452,20 +443,20 @@ QStringList RicRecursiveFileSearchDialog::buildDirectoryListRecursive(const QStr QApplication::processEvents(); allDirs += buildDirectoryListRecursive(subDirFullPath, level + 1); } - return cancelPressed() ? QStringList() : allDirs; + return m_isCancelPressed ? QStringList() : allDirs; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RicRecursiveFileSearchDialog::buildDirectoryListRecursiveSimple(const QString& currentDirFullPathNoEndSeparator, - const QString& currentPathFilterNoEndSeparator, - QStringList* accumulatedDirs) + const QString& currentPathFilterNoEndSeparator, + QStringList* accumulatedDirs) { QString currDir = currentDirFullPathNoEndSeparator; QString pathFilter = currentPathFilterNoEndSeparator; - if (cancelPressed()) + if (m_isCancelPressed) { accumulatedDirs->clear(); return; @@ -523,7 +514,7 @@ QStringList RicRecursiveFileSearchDialog::findFilesInDirs(const QStringList& dir QDir qdir(dir); QStringList files = qdir.entryList(filters, QDir::Files); - if (cancelPressed()) return QStringList(); + if (m_isCancelPressed) return QStringList(); updateStatus(SEARCHING_FOR_FILES, qdir.absolutePath()); QApplication::processEvents(); @@ -578,7 +569,7 @@ bool RicRecursiveFileSearchDialog::pathFilterMatch(const QString& pathFilter, co //-------------------------------------------------------------------------------------------------- void RicRecursiveFileSearchDialog::updateEffectiveFilter() { - QString pathFilterText = pathFilter(); + QString pathFilterText = pathFilterWithoutStartSeparator(); if (pathFilterText == "*" || pathFilterText.endsWith(QString(SEPARATOR) + "*")) { pathFilterText.chop(1); @@ -594,6 +585,7 @@ void RicRecursiveFileSearchDialog::updateEffectiveFilter() // Present native separators to the user m_effectiveFilterContentLabel->setText(QDir::toNativeSeparators(effFilterText)); + m_searchRootContentLabel->setText(QDir::toNativeSeparators(rootDirWithEndSeparator())); } //-------------------------------------------------------------------------------------------------- @@ -609,10 +601,11 @@ void RicRecursiveFileSearchDialog::setOkButtonEnabled(bool enabled) //-------------------------------------------------------------------------------------------------- void RicRecursiveFileSearchDialog::warningIfInvalidCharacters() { - if (m_fileFilterField->text().contains(QRegExp("[\\\\/:]"))) + if (fileNameFilter().contains(QRegExp("[\\\\/:]"))) { QToolTip::showText(m_fileFilterField->mapToGlobal(QPoint(0, 0)), "File pattern contains invalid characters"); m_effectiveFilterContentLabel->setText("(Invalid filter)"); + m_searchRootContentLabel->setText(""); } else { @@ -727,18 +720,21 @@ void RicRecursiveFileSearchDialog::slotFindOrCancelButtonClicked() { m_fileListLabel->setVisible(true); m_fileListWidget->setVisible(true); + m_searchRootLabel->setVisible(true); + m_searchRootContentLabel->setVisible(true); if(height() < DEFAULT_DIALOG_FIND_HEIGHT) resize(width(), DEFAULT_DIALOG_FIND_HEIGHT); } - m_findOrCancelButton->setText(FIND_BUTTON_CANCEL_TEXT); + m_findOrCancelButton->setText("Cancel"); - m_cancelPressed = false; + m_isCancelPressed = false; m_foundFiles = findMatchingFiles(); + this->updateFileListWidget(); m_findOrCancelButton->setText(FIND_BUTTON_FIND_TEXT); - if (m_cancelPressed) + if (m_isCancelPressed) { clearFileList(); } @@ -756,7 +752,7 @@ void RicRecursiveFileSearchDialog::slotFindOrCancelButtonClicked() } else { - m_cancelPressed = true; + m_isCancelPressed = true; } } @@ -785,7 +781,7 @@ void RicRecursiveFileSearchDialog::slotDialogOkClicked() void RicRecursiveFileSearchDialog::slotDialogCancelClicked() { m_foundFiles = QStringList(); - m_cancelPressed = true; + m_isCancelPressed = true; reject(); } @@ -794,8 +790,10 @@ void RicRecursiveFileSearchDialog::slotDialogCancelClicked() //-------------------------------------------------------------------------------------------------- void RicRecursiveFileSearchDialog::slotBrowseButtonClicked() { - QString folder = QFileDialog::getExistingDirectory(this, "Select root folder", m_rootDirField->text()); - if(!folder.isEmpty()) m_rootDirField->setText(QDir::toNativeSeparators(folder)); + QString folder = QFileDialog::getExistingDirectory(this, "Select folder", rootDirWithEndSeparator()); + RiaFilePathTools::appendSeparatorIfNo(folder); + folder += "*"; + if(!folder.isEmpty()) m_pathFilterField->setText(QDir::toNativeSeparators(folder)); } diff --git a/ApplicationCode/Commands/RicRecursiveFileSearchDialog.h b/ApplicationCode/Commands/RicRecursiveFileSearchDialog.h index 5b243a7bc4..c5d4d6e779 100644 --- a/ApplicationCode/Commands/RicRecursiveFileSearchDialog.h +++ b/ApplicationCode/Commands/RicRecursiveFileSearchDialog.h @@ -54,16 +54,15 @@ public: const QStringList& fileExtensions = QStringList()); private: - QStringList files() const; + QString cleanTextFromPathFilterField() const; QString rootDirWithEndSeparator() const; - QString pathFilter() const; + QString pathFilterWithoutStartSeparator() const; QString fileNameFilter() const; QStringList fileExtensions() const; QString fileExtensionsText() const; QString extensionFromFileNameFilter() const; - bool cancelPressed() const; - void appendToFileList(const QString& fileName); + void updateFileListWidget(); void clearFileList(); void updateStatus(Status status, const QString& extraText = ""); @@ -102,20 +101,20 @@ private slots: void slotBrowseButtonClicked(); private: - QLabel* m_rootDirLabel; - QLineEdit* m_rootDirField; - QPushButton* m_browseButton; QLabel* m_pathFilterLabel; QLineEdit* m_pathFilterField; + QPushButton* m_browseButton; QLabel* m_fileFilterLabel; QLineEdit* m_fileFilterField; - //QLabel* m_fileExtensionLabel; QLabel* m_effectiveFilterLabel; QLabel* m_effectiveFilterContentLabel; + QLabel* m_searchRootLabel; + QLabel* m_searchRootContentLabel; + QLabel* m_fileListLabel; QListWidget* m_fileListWidget; @@ -125,7 +124,7 @@ private: QStringList m_foundFiles; QStringList m_fileExtensions; - bool m_cancelPressed; + bool m_isCancelPressed; }; From f6ae265b38a9d372186257cc44f66c7a3b1d12f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Mon, 19 Aug 2019 10:30:20 +0200 Subject: [PATCH 348/396] Recursive import Dialog: Fix missing progress info at certain times --- ApplicationCode/Commands/RicRecursiveFileSearchDialog.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ApplicationCode/Commands/RicRecursiveFileSearchDialog.cpp b/ApplicationCode/Commands/RicRecursiveFileSearchDialog.cpp index e32009a299..f73837a8e2 100644 --- a/ApplicationCode/Commands/RicRecursiveFileSearchDialog.cpp +++ b/ApplicationCode/Commands/RicRecursiveFileSearchDialog.cpp @@ -343,11 +343,11 @@ void RicRecursiveFileSearchDialog::clearFileList() void RicRecursiveFileSearchDialog::updateStatus(Status status, const QString& extraText) { static int progressLoopStep = 0; - static QTime lastStatusUpdate; + static QTime lastStatusUpdate = QTime::currentTime(); QTime now = QTime::currentTime(); // Do not update dialog more often than twice per second to avoid text update from slowing down search progress - if (status != NO_FILES_FOUND && lastStatusUpdate.msecsTo(now) < 500) return; + if (status != NO_FILES_FOUND && lastStatusUpdate.msecsTo(now) < 250) return; QString newStatus; if (status == SEARCHING_FOR_DIRS || status == SEARCHING_FOR_FILES ) From 3d9ed39795270963ea0974fe6e14c22a30593198 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Mon, 19 Aug 2019 11:09:59 +0200 Subject: [PATCH 349/396] Recursive Import Dialog: Fixed "/*" not working on linux. Layout changes: Removed Files Found label. Moved Effective Filter and Find button into the Filter group Higher minimumsize for result list --- .../Commands/RicRecursiveFileSearchDialog.cpp | 44 ++++++++----------- .../Commands/RicRecursiveFileSearchDialog.h | 3 ++ 2 files changed, 22 insertions(+), 25 deletions(-) diff --git a/ApplicationCode/Commands/RicRecursiveFileSearchDialog.cpp b/ApplicationCode/Commands/RicRecursiveFileSearchDialog.cpp index f73837a8e2..c3fcea7e6e 100644 --- a/ApplicationCode/Commands/RicRecursiveFileSearchDialog.cpp +++ b/ApplicationCode/Commands/RicRecursiveFileSearchDialog.cpp @@ -44,7 +44,7 @@ #define DEFAULT_DIALOG_FIND_HEIGHT 350 #define FIND_BUTTON_FIND_TEXT "Find" -#define FILES_FOUND_TEXT "Files found" +#define FILES_FOUND_TEXT "Files Found" //-------------------------------------------------------------------------------------------------- /// Internal variables @@ -75,7 +75,6 @@ RicRecursiveFileSearchDialog::RicRecursiveFileSearchDialog(QWidget* parent) m_searchRootLabel = new QLabel(); m_searchRootContentLabel = new QLabel(); m_findOrCancelButton = new QPushButton(); - m_fileListLabel = new QLabel(); m_fileListWidget = new QListWidget(); m_buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); @@ -100,9 +99,6 @@ RicRecursiveFileSearchDialog::RicRecursiveFileSearchDialog(QWidget* parent) m_searchRootLabel->setText("Root"); m_searchRootLabel->setVisible(false); - m_fileListLabel->setText("Files found"); - m_fileListLabel->setVisible(false); - m_effectiveFilterContentLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); m_searchRootContentLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); m_searchRootContentLabel->setVisible(false); @@ -111,6 +107,7 @@ RicRecursiveFileSearchDialog::RicRecursiveFileSearchDialog(QWidget* parent) m_fileListWidget->setVisible(false); m_fileListWidget->setContextMenuPolicy(Qt::CustomContextMenu); m_fileListWidget->setSortingEnabled(true); + m_fileListWidget->setMinimumHeight(350); m_browseButton->setText("..."); m_browseButton->setFixedWidth(25); @@ -125,36 +122,36 @@ RicRecursiveFileSearchDialog::RicRecursiveFileSearchDialog(QWidget* parent) QGroupBox* inputGroup = new QGroupBox("Filter"); QGridLayout* inputGridLayout = new QGridLayout(); inputGridLayout->addWidget(m_pathFilterLabel, 0, 0); - inputGridLayout->addWidget(m_pathFilterField, 0, 1); - inputGridLayout->addWidget(m_browseButton, 0, 2); + inputGridLayout->addWidget(m_pathFilterField, 0, 1, 1, 2); + inputGridLayout->addWidget(m_browseButton, 0, 3); inputGridLayout->addWidget(m_fileFilterLabel, 1, 0); - inputGridLayout->addWidget(m_fileFilterField, 1, 1); + inputGridLayout->addWidget(m_fileFilterField, 1, 1, 1, 2); + inputGridLayout->addWidget(m_effectiveFilterLabel, 2, 0); + inputGridLayout->addWidget(m_effectiveFilterContentLabel, 2, 1); + inputGridLayout->addWidget(m_findOrCancelButton, 2, 2, 1, 2); inputGroup->setLayout(inputGridLayout); - QGroupBox* outputGroup = new QGroupBox("Files"); + m_outputGroup = new QGroupBox("Files Found"); QGridLayout* outputGridLayout = new QGridLayout(); - outputGridLayout->addWidget(m_effectiveFilterLabel, 0, 0); - outputGridLayout->addWidget(m_effectiveFilterContentLabel, 0, 1); outputGridLayout->addWidget(m_searchRootLabel, 1, 0); outputGridLayout->addWidget(m_searchRootContentLabel, 1, 1); - outputGridLayout->addWidget(m_findOrCancelButton, 0, 2); - outputGridLayout->addWidget(m_fileListLabel, 2, 0); - outputGridLayout->addWidget(m_fileListWidget, 2, 1, 1, 2); - outputGroup->setLayout(outputGridLayout); + //outputGridLayout->addWidget(m_fileListLabel, 2, 0); + outputGridLayout->addWidget(m_fileListWidget, 2, 0, 1, 3); + m_outputGroup->setLayout(outputGridLayout); dialogLayout->addWidget(inputGroup); - dialogLayout->addWidget(outputGroup); + dialogLayout->addWidget(m_outputGroup); dialogLayout->addWidget(m_buttons); setLayout(dialogLayout); QString pathFilterHelpText = "The path filter uses normal wildcard file globbing, like in any unix shell. \n" - "When the filter ends with a single \"*\", however, ResInsight will \n" + "When the filter ends with a single \"*\" (eg. \"/home/*\"), however, ResInsight will \n" "search recursively in all subdirectories from that point.\n" - "This is indicated by \"...\" in the Effective Filter label below." + "This is indicated by \"...\" in the Effective Filter label below.\n" "\n" "An asterix \"*\" matches any number of any characters, except the path separator.\n" "A question mark \"?\" matches any single character, except the path separator.\n" @@ -214,7 +211,7 @@ RicRecursiveFileSearchDialogResult RicRecursiveFileSearchDialog::runRecursiveSea dialog.clearFileList(); dialog.setOkButtonEnabled(false); - dialog.resize(750, 150); + dialog.resize(800, 150); dialog.exec(); return RicRecursiveFileSearchDialogResult(dialog.result() == QDialog::Accepted, @@ -311,8 +308,6 @@ QString RicRecursiveFileSearchDialog::extensionFromFileNameFilter() const void RicRecursiveFileSearchDialog::updateFileListWidget() { m_fileListWidget->clear(); - m_fileListLabel->setText(FILES_FOUND_TEXT); - int rootSearchPathLenght = rootDirWithEndSeparator().size(); @@ -333,7 +328,7 @@ void RicRecursiveFileSearchDialog::clearFileList() { m_foundFiles.clear(); m_fileListWidget->clear(); - m_fileListLabel->setText(FILES_FOUND_TEXT); + m_outputGroup->setTitle(FILES_FOUND_TEXT); setOkButtonEnabled(false); } @@ -389,7 +384,7 @@ QStringList RicRecursiveFileSearchDialog::findMatchingFiles() QString pathFilter = this->pathFilterWithoutStartSeparator(); QString rootDir = this->rootDirWithEndSeparator(); - if (rootDir.endsWith(SEPARATOR)) rootDir.chop(1); + if (rootDir.size() > 1 && rootDir.endsWith(SEPARATOR)) rootDir.chop(1); buildDirectoryListRecursiveSimple(rootDir, pathFilter, &dirs); @@ -718,7 +713,6 @@ void RicRecursiveFileSearchDialog::slotFindOrCancelButtonClicked() if(!m_fileListWidget->isVisible()) { - m_fileListLabel->setVisible(true); m_fileListWidget->setVisible(true); m_searchRootLabel->setVisible(true); m_searchRootContentLabel->setVisible(true); @@ -744,7 +738,7 @@ void RicRecursiveFileSearchDialog::slotFindOrCancelButtonClicked() } else { - m_fileListLabel->setText(QString("%1\n(%2)").arg(FILES_FOUND_TEXT).arg(m_foundFiles.size())); + m_outputGroup->setTitle(QString("%1 (%2)").arg(FILES_FOUND_TEXT).arg(m_foundFiles.size())); } setOkButtonEnabled(!m_foundFiles.isEmpty()); diff --git a/ApplicationCode/Commands/RicRecursiveFileSearchDialog.h b/ApplicationCode/Commands/RicRecursiveFileSearchDialog.h index c5d4d6e779..6e86dfe173 100644 --- a/ApplicationCode/Commands/RicRecursiveFileSearchDialog.h +++ b/ApplicationCode/Commands/RicRecursiveFileSearchDialog.h @@ -31,6 +31,8 @@ class QDialogButtonBox; class QPushButton; class QMainWindow; class QListWidget; +class QGroupBox; + class RicRecursiveFileSearchDialogResult; //================================================================================================== @@ -112,6 +114,7 @@ private: QLabel* m_effectiveFilterLabel; QLabel* m_effectiveFilterContentLabel; + QGroupBox* m_outputGroup; QLabel* m_searchRootLabel; QLabel* m_searchRootContentLabel; From 2d2ecc30310f7619e1f55e6b92f981463e6e46cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Mon, 19 Aug 2019 11:44:19 +0200 Subject: [PATCH 350/396] Recursive Import Dialog: Cleaned up code --- .../Commands/RicRecursiveFileSearchDialog.cpp | 222 ++++++++---------- .../Commands/RicRecursiveFileSearchDialog.h | 43 ++-- 2 files changed, 117 insertions(+), 148 deletions(-) diff --git a/ApplicationCode/Commands/RicRecursiveFileSearchDialog.cpp b/ApplicationCode/Commands/RicRecursiveFileSearchDialog.cpp index c3fcea7e6e..e5b80b3ea5 100644 --- a/ApplicationCode/Commands/RicRecursiveFileSearchDialog.cpp +++ b/ApplicationCode/Commands/RicRecursiveFileSearchDialog.cpp @@ -42,7 +42,7 @@ #include -#define DEFAULT_DIALOG_FIND_HEIGHT 350 +#define RECURSIVE_FILESEARCH_DEFAULT_DIALOG_HEIGHT 350 #define FIND_BUTTON_FIND_TEXT "Find" #define FILES_FOUND_TEXT "Files Found" @@ -54,10 +54,44 @@ static const QChar SEPARATOR = RiaFilePathTools::SEPARATOR; //-------------------------------------------------------------------------------------------------- /// Internal functions //-------------------------------------------------------------------------------------------------- -static QStringList prefixStrings(const QStringList& strings, const QString& prefix); static QStringList trimLeftStrings(const QStringList& strings, const QString& trimText); static void sortStringsByLength(QStringList& strings, bool ascending = true); +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RicRecursiveFileSearchDialogResult RicRecursiveFileSearchDialog::runRecursiveSearchDialog(QWidget *parent, + const QString &caption, + const QString &dir, + const QString &pathFilter , + const QString &fileNameFilter, + const QStringList &fileExtensions) +{ + RicRecursiveFileSearchDialog dialog(parent); + + dialog.setWindowTitle(caption); + + QString pathFilterText = dir; + RiaFilePathTools::appendSeparatorIfNo(pathFilterText); + pathFilterText += pathFilter; + dialog.m_pathFilterField->setText(QDir::toNativeSeparators(pathFilterText)); + dialog.m_fileFilterField->setText(fileNameFilter); + dialog.m_fileExtensions = trimLeftStrings(fileExtensions, "."); + + dialog.updateEffectiveFilter(); + dialog.clearFileList(); + dialog.setOkButtonEnabled(false); + + dialog.resize(800, 150); + dialog.exec(); + + return RicRecursiveFileSearchDialogResult(dialog.result() == QDialog::Accepted, + dialog.m_foundFiles, + dialog.rootDirWithEndSeparator(), + dialog.pathFilterWithoutStartSeparator(), + dialog.fileNameFilter()); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -189,38 +223,6 @@ RicRecursiveFileSearchDialog::~RicRecursiveFileSearchDialog() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RicRecursiveFileSearchDialogResult RicRecursiveFileSearchDialog::runRecursiveSearchDialog(QWidget *parent, - const QString &caption, - const QString &dir, - const QString &pathFilter , - const QString &fileNameFilter, - const QStringList &fileExtensions) -{ - RicRecursiveFileSearchDialog dialog(parent); - - dialog.setWindowTitle(caption); - - QString pathFilterText = dir; - RiaFilePathTools::appendSeparatorIfNo(pathFilterText); - pathFilterText += pathFilter; - dialog.m_pathFilterField->setText(QDir::toNativeSeparators(pathFilterText)); - dialog.m_fileFilterField->setText(fileNameFilter); - dialog.m_fileExtensions = trimLeftStrings(fileExtensions, "."); - - dialog.updateEffectiveFilter(); - dialog.clearFileList(); - dialog.setOkButtonEnabled(false); - - dialog.resize(800, 150); - dialog.exec(); - - return RicRecursiveFileSearchDialogResult(dialog.result() == QDialog::Accepted, - dialog.m_foundFiles, - dialog.rootDirWithEndSeparator(), - dialog.pathFilterWithoutStartSeparator(), - dialog.fileNameFilter()); -} - QString RicRecursiveFileSearchDialog::cleanTextFromPathFilterField() const { QString pathFilterText = m_pathFilterField->text().trimmed(); @@ -277,16 +279,6 @@ QStringList RicRecursiveFileSearchDialog::fileExtensions() const return exts; } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -QString RicRecursiveFileSearchDialog::fileExtensionsText() const -{ - QString extFromFilter = extensionFromFileNameFilter(); - if (!extFromFilter.isEmpty()) return ""; - else return prefixStrings(fileExtensions(), ".").join(" | "); -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -392,55 +384,6 @@ QStringList RicRecursiveFileSearchDialog::findMatchingFiles() return findFilesInDirs(dirs); } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -QStringList RicRecursiveFileSearchDialog::buildDirectoryListRecursive(const QString& currentDir, int level) -{ - QStringList allDirs; - - if (m_isCancelPressed) return allDirs; - - QString currPathFilter = pathFilterWithoutStartSeparator(); - bool subStringFilter = false; - - // Optimizing for speed by a refined match at first directory level - if (level == 1) - { - QString pathFilter = this->pathFilterWithoutStartSeparator(); - if (!pathFilter.startsWith("*")) - { - int wildcardIndex = pathFilter.indexOf(QRegExp(QString("[*%1]").arg(SEPARATOR))); - if (wildcardIndex >= 0) - { - currPathFilter = pathFilter.left(wildcardIndex + 1); - subStringFilter = true; - } - } - } - - QString currRelPath = RiaFilePathTools::relativePath(rootDirWithEndSeparator(), currentDir); - if (pathFilterMatch(currPathFilter, currRelPath)) - { - allDirs.push_back(currentDir); - } - else if(level == 1 && subStringFilter) - { - return QStringList(); - } - - QDir qdir(currentDir); - QStringList subDirs = qdir.entryList(QDir::Dirs | QDir::NoDotAndDotDot); - for (QString subDir : subDirs) - { - QString subDirFullPath = qdir.absoluteFilePath(subDir); - updateStatus(SEARCHING_FOR_DIRS, subDirFullPath); - QApplication::processEvents(); - allDirs += buildDirectoryListRecursive(subDirFullPath, level + 1); - } - return m_isCancelPressed ? QStringList() : allDirs; -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -548,17 +491,6 @@ QStringList RicRecursiveFileSearchDialog::createFileNameFilterList() return nameFilter; } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool RicRecursiveFileSearchDialog::pathFilterMatch(const QString& pathFilter, const QString& relPath) -{ - QString pattern = pathFilter; - if (relPath.endsWith(SEPARATOR) && !pathFilter.endsWith(SEPARATOR)) pattern += SEPARATOR; - QRegExp regexp(pattern, Qt::CaseInsensitive, QRegExp::Wildcard); - return regexp.exactMatch(relPath); -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -717,7 +649,7 @@ void RicRecursiveFileSearchDialog::slotFindOrCancelButtonClicked() m_searchRootLabel->setVisible(true); m_searchRootContentLabel->setVisible(true); - if(height() < DEFAULT_DIALOG_FIND_HEIGHT) resize(width(), DEFAULT_DIALOG_FIND_HEIGHT); + if(height() < RECURSIVE_FILESEARCH_DEFAULT_DIALOG_HEIGHT) resize(width(), RECURSIVE_FILESEARCH_DEFAULT_DIALOG_HEIGHT); } m_findOrCancelButton->setText("Cancel"); @@ -795,26 +727,6 @@ void RicRecursiveFileSearchDialog::slotBrowseButtonClicked() /// Internal functions //-------------------------------------------------------------------------------------------------- -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -QStringList prefixStrings(const QStringList& strings, const QString& prefix) -{ - QStringList prefixedStrings; - for (auto string : strings) - { - if (!string.startsWith(prefix)) - { - prefixedStrings.append(prefix + string); - } - else - { - prefixedStrings.append(string); - } - } - return prefixedStrings; -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -861,3 +773,63 @@ void sortStringsByLength(QStringList& strings, bool ascending /*= true*/) } + +//-------------------------------------------------------------------------------------------------- +/// Obsolete +//-------------------------------------------------------------------------------------------------- +QStringList RicRecursiveFileSearchDialog::buildDirectoryListRecursive(const QString& currentDir, int level) +{ + QStringList allDirs; + + if (m_isCancelPressed) return allDirs; + + QString currPathFilter = pathFilterWithoutStartSeparator(); + bool subStringFilter = false; + + // Optimizing for speed by a refined match at first directory level + if (level == 1) + { + QString pathFilter = this->pathFilterWithoutStartSeparator(); + if (!pathFilter.startsWith("*")) + { + int wildcardIndex = pathFilter.indexOf(QRegExp(QString("[*%1]").arg(SEPARATOR))); + if (wildcardIndex >= 0) + { + currPathFilter = pathFilter.left(wildcardIndex + 1); + subStringFilter = true; + } + } + } + + QString currRelPath = RiaFilePathTools::relativePath(rootDirWithEndSeparator(), currentDir); + if (pathFilterMatch(currPathFilter, currRelPath)) + { + allDirs.push_back(currentDir); + } + else if(level == 1 && subStringFilter) + { + return QStringList(); + } + + QDir qdir(currentDir); + QStringList subDirs = qdir.entryList(QDir::Dirs | QDir::NoDotAndDotDot); + for (QString subDir : subDirs) + { + QString subDirFullPath = qdir.absoluteFilePath(subDir); + updateStatus(SEARCHING_FOR_DIRS, subDirFullPath); + QApplication::processEvents(); + allDirs += buildDirectoryListRecursive(subDirFullPath, level + 1); + } + return m_isCancelPressed ? QStringList() : allDirs; +} + +//-------------------------------------------------------------------------------------------------- +/// Obsolete +//-------------------------------------------------------------------------------------------------- +bool RicRecursiveFileSearchDialog::pathFilterMatch(const QString& pathFilter, const QString& relPath) +{ + QString pattern = pathFilter; + if (relPath.endsWith(SEPARATOR) && !pathFilter.endsWith(SEPARATOR)) pattern += SEPARATOR; + QRegExp regexp(pattern, Qt::CaseInsensitive, QRegExp::Wildcard); + return regexp.exactMatch(relPath); +} diff --git a/ApplicationCode/Commands/RicRecursiveFileSearchDialog.h b/ApplicationCode/Commands/RicRecursiveFileSearchDialog.h index 6e86dfe173..9ad73e72e4 100644 --- a/ApplicationCode/Commands/RicRecursiveFileSearchDialog.h +++ b/ApplicationCode/Commands/RicRecursiveFileSearchDialog.h @@ -45,8 +45,6 @@ class RicRecursiveFileSearchDialog : public QDialog enum Status {SEARCHING_FOR_DIRS, SEARCHING_FOR_FILES, NO_FILES_FOUND}; public: - RicRecursiveFileSearchDialog(QWidget* parent); - ~RicRecursiveFileSearchDialog() override; static RicRecursiveFileSearchDialogResult runRecursiveSearchDialog(QWidget *parent = nullptr, const QString& caption = QString(), @@ -56,51 +54,47 @@ public: const QStringList& fileExtensions = QStringList()); private: + RicRecursiveFileSearchDialog(QWidget* parent); + ~RicRecursiveFileSearchDialog() override; + QString cleanTextFromPathFilterField() const; QString rootDirWithEndSeparator() const; QString pathFilterWithoutStartSeparator() const; QString fileNameFilter() const; + QStringList fileExtensions() const; - QString fileExtensionsText() const; QString extensionFromFileNameFilter() const; + void setOkButtonEnabled(bool enabled); + void warningIfInvalidCharacters(); + void updateEffectiveFilter(); + void updateStatus(Status status, const QString& extraText = ""); + void updateFileListWidget(); void clearFileList(); - void updateStatus(Status status, const QString& extraText = ""); + + // File search methods QStringList findMatchingFiles(); - - QStringList buildDirectoryListRecursive(const QString& currentDir, int level = 0); - void buildDirectoryListRecursiveSimple(const QString& currentDir, const QString& currentPathFilter, QStringList* accumulatedDirs); - QStringList findFilesInDirs(const QStringList& dirs); - QStringList createFileNameFilterList(); - bool pathFilterMatch(const QString& pathFilter, const QString& relPath); - - void updateEffectiveFilter(); - - void setOkButtonEnabled(bool enabled); - - void warningIfInvalidCharacters(); - private slots: void slotFilterChanged(const QString& text); + void slotBrowseButtonClicked(); + void slotFindOrCancelButtonClicked(); void slotFileListCustomMenuRequested(const QPoint& point); + void slotCopyFileItemText(); void slotToggleFileListItems(); void slotTurnOffFileListItems(); void slotTurnOnFileListItems(); - void slotCopyFileItemText(); - void slotFindOrCancelButtonClicked(); void slotDialogOkClicked(); void slotDialogCancelClicked(); - void slotBrowseButtonClicked(); private: @@ -113,21 +107,24 @@ private: QLabel* m_effectiveFilterLabel; QLabel* m_effectiveFilterContentLabel; + QPushButton* m_findOrCancelButton; QGroupBox* m_outputGroup; QLabel* m_searchRootLabel; QLabel* m_searchRootContentLabel; - - QLabel* m_fileListLabel; QListWidget* m_fileListWidget; - QPushButton* m_findOrCancelButton; QDialogButtonBox* m_buttons; QStringList m_foundFiles; QStringList m_fileExtensions; bool m_isCancelPressed; + + // Obsolete. Here for reference if this search mode is needed later + QStringList buildDirectoryListRecursive(const QString& currentDir, int level = 0); + bool pathFilterMatch(const QString& pathFilter, const QString& relPath); + }; From 68d3ffdbb2640d09093cf330f094bf534c230f76 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Mon, 19 Aug 2019 11:47:53 +0200 Subject: [PATCH 351/396] #4596 fix applyCellResult legend range --- ApplicationCode/GrpcInterface/RiaGrpcPdmObjectService.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/ApplicationCode/GrpcInterface/RiaGrpcPdmObjectService.cpp b/ApplicationCode/GrpcInterface/RiaGrpcPdmObjectService.cpp index 1048b26947..7ea2416e78 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcPdmObjectService.cpp +++ b/ApplicationCode/GrpcInterface/RiaGrpcPdmObjectService.cpp @@ -169,6 +169,7 @@ grpc::Status RiaGrpcPdmObjectService::UpdateExistingPdmObject(grpc::ServerContex if (resultDefinition) { resultDefinition->updateUiFieldsFromActiveResult(); + resultDefinition->loadResult(); } matchingObject->updateAllRequiredEditors(); From edfb39c9b7346f073b5617f13812eb17c9ad2d19 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Mon, 19 Aug 2019 11:49:00 +0200 Subject: [PATCH 352/396] #4596 Python: Add gridPath method to Case and add simpler activeCellInfo method --- .../GrpcInterface/Python/rips/Case.py | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/ApplicationCode/GrpcInterface/Python/rips/Case.py b/ApplicationCode/GrpcInterface/Python/rips/Case.py index 3b6bb7ec49..dde1466455 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Case.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Case.py @@ -46,6 +46,9 @@ class Case (PdmObject): print("ERROR: ", e) return 0 + def gridPath(self): + return self.getValue("CaseFileName") + def grid(self, index): """Get Grid of a given index. Returns a rips Grid object @@ -80,7 +83,7 @@ class Case (PdmObject): porosity_model=porosityModel) return self.stub.GetCellCount(request) - def cellInfoForActiveCells(self, porosityModel='MATRIX_MODEL'): + def cellInfoForActiveCellsAsync(self, porosityModel='MATRIX_MODEL'): """Get Stream of cell info objects for current case Arguments: @@ -101,6 +104,28 @@ class Case (PdmObject): porosity_model=porosityModel) return self.stub.GetCellInfoForActiveCells(request) + def cellInfoForActiveCells(self, porosityModel='MATRIX_MODEL'): + """Get list of cell info objects for current case + + Arguments: + porosityModel(str): String representing an enum. + must be 'MATRIX_MODEL' or 'FRACTURE_MODEL'. + + Returns: + List of cell info objects with the following attributes: + grid_index(int): grid the cell belongs to + parent_grid_index(int): parent of the grid the cell belongs to + coarsening_box_index(int): the coarsening box index + local_ijk(Vec3i: i(int), j(int), k(int)): local cell index in i, j, k directions. + parent_ijk(Vec3i: i(int), j(int), k(int)): cell index in parent grid in i, j, k. + """ + activeCellInfoChunks = self.cellInfoForActiveCellsAsync() + receivedActiveCells = [] + for activeCellChunk in activeCellInfoChunks: + for activeCell in activeCellChunk.data: + receivedActiveCells.append(activeCell) + return receivedActiveCells + def timeSteps(self): """Get a list containing time step strings for all time steps""" return self.stub.GetTimeSteps(self.request).dates From 6c0e2bb3ad54542d4e30720d193bbd9bdde8e23f Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Mon, 19 Aug 2019 13:46:14 +0200 Subject: [PATCH 353/396] #4597 Python: add exportSnapshots example and more comments in examples --- .../GrpcInterface/CMakeLists.cmake | 3 +- .../Python/rips/PythonExamples/AllCases.py | 16 ++++--- .../CaseInfoStreamingExample.py | 25 ++++++----- .../rips/PythonExamples/CommandExample.py | 20 ++++++++- .../rips/PythonExamples/ErrorHandling.py | 5 +++ .../rips/PythonExamples/ExportSnapshots.py | 43 +++++++++++++++++++ .../rips/PythonExamples/GridInformation.py | 5 +++ .../rips/PythonExamples/InputPropTestAsync.py | 18 +++++++- .../rips/PythonExamples/InputPropTestSync.py | 15 ++++++- .../rips/PythonExamples/InstanceExample.py | 3 ++ .../rips/PythonExamples/SelectedCases.py | 7 +++ .../rips/PythonExamples/SetCellResult.py | 3 ++ .../SetFlowDiagnosticsResult.py | 4 ++ .../rips/PythonExamples/SetGridProperties.py | 3 ++ .../rips/PythonExamples/SoilAverageAsync.py | 15 ++++++- .../rips/PythonExamples/SoilAverageNoComm.py | 16 ------- .../rips/PythonExamples/SoilAverageSync.py | 11 +++-- .../rips/PythonExamples/SoilPorvAsync.py | 33 ++++++++++---- .../rips/PythonExamples/SoilPorvSync.py | 13 +++++- .../Python/rips/PythonExamples/ViewExample.py | 21 +++++++++ 20 files changed, 226 insertions(+), 53 deletions(-) create mode 100644 ApplicationCode/GrpcInterface/Python/rips/PythonExamples/ExportSnapshots.py delete mode 100644 ApplicationCode/GrpcInterface/Python/rips/PythonExamples/SoilAverageNoComm.py create mode 100644 ApplicationCode/GrpcInterface/Python/rips/PythonExamples/ViewExample.py diff --git a/ApplicationCode/GrpcInterface/CMakeLists.cmake b/ApplicationCode/GrpcInterface/CMakeLists.cmake index 89d6ab410a..1e6000dcb6 100644 --- a/ApplicationCode/GrpcInterface/CMakeLists.cmake +++ b/ApplicationCode/GrpcInterface/CMakeLists.cmake @@ -173,6 +173,7 @@ if (RESINSIGHT_GRPC_PYTHON_EXECUTABLE) "rips/PythonExamples/CommandExample.py" "rips/PythonExamples/CaseGridGroup.py" "rips/PythonExamples/CaseInfoStreamingExample.py" + "rips/PythonExamples/ExportSnapshots.py" "rips/PythonExamples/ErrorHandling.py" "rips/PythonExamples/SoilPorvAsync.py" "rips/PythonExamples/SoilPorvSync.py" @@ -186,7 +187,7 @@ if (RESINSIGHT_GRPC_PYTHON_EXECUTABLE) "rips/PythonExamples/InputPropTestAsync.py" "rips/PythonExamples/SoilAverageAsync.py" "rips/PythonExamples/SoilAverageSync.py" - "rips/PythonExamples/SoilAverageNoComm.py" + "rips/PythonExamples/ViewExample.py" "rips/tests/test_cases.py" "rips/tests/test_commands.py" "rips/tests/test_grids.py" diff --git a/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/AllCases.py b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/AllCases.py index 1064eb8545..f54195c1ff 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/AllCases.py +++ b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/AllCases.py @@ -1,14 +1,18 @@ +################################################################################### +# This example will connect to ResInsight, retrieve a list of cases and print info +################################################################################### + +# Import the ResInsight Processing Server Module import rips +# Connect to ResInsight resInsight = rips.Instance.find() if resInsight is not None: + # Get a list of all cases cases = resInsight.project.cases() print ("Got " + str(len(cases)) + " cases: ") for case in cases: - print(case.name) - views = case.views() - for view in views: - view.setShowGridBox(not view.showGridBox()) - view.setBackgroundColor("#3388AA") - view.update() + print("Case name: " + case.name) + print("Case grid path: " + case.gridPath()) + diff --git a/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/CaseInfoStreamingExample.py b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/CaseInfoStreamingExample.py index b0457173ea..6f81aa0693 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/CaseInfoStreamingExample.py +++ b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/CaseInfoStreamingExample.py @@ -1,22 +1,27 @@ +############################################################################### +# This example will get the cell info for the active cells for the first case +############################################################################### + +# Import the ResInsight Processing Server Module import rips +# Connect to ResInsight resInsight = rips.Instance.find() +# Get the case with id == 0. This will fail if your project doesn't have a case with id == 0 case = resInsight.project.case(id = 0) +# Get the cell count object cellCounts = case.cellCount() print("Number of active cells: " + str(cellCounts.active_cell_count)) +print("Total number of reservoir cells: " + str(cellCounts.reservoir_cell_count)) -activeCellInfoChunks = case.cellInfoForActiveCells() +# Get information for all active cells +activeCellInfos = case.cellInfoForActiveCells() -#print("Number of grids: " + str(gridCount)) -#print(gridDimensions) +# A simple check on the size of the cell info +assert(cellCounts.active_cell_count == len(activeCellInfos)) -receivedActiveCells = [] -for activeCellChunk in activeCellInfoChunks: - for activeCell in activeCellChunk.data: - receivedActiveCells.append(activeCell) - -assert(cellCounts.active_cell_count == len(receivedActiveCells)) +# Print information for the first active cell print("First active cell: ") -print(receivedActiveCells[0]) +print(activeCellInfos[0]) diff --git a/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/CommandExample.py b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/CommandExample.py index 26f364eea3..a32760a367 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/CommandExample.py +++ b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/CommandExample.py @@ -1,3 +1,8 @@ +############################################################################### +# This example will run a few ResInsight command file commands +# .. which are exposed in the Python interface. +# Including setting time step, window size and export snapshots and properties +############################################################################### import os import tempfile import rips @@ -8,16 +13,29 @@ resInsight = rips.Instance.find() # Run a couple of commands resInsight.commands.setTimeStep(caseId=0, timeStep=3) resInsight.commands.setMainWindowSize(width=800, height=500) -#resInsight.commands.exportWellPaths() + +# Create a temporary directory which will disappear at the end of this script +# If you want to keep the files, provide a good path name instead of tmpdirname with tempfile.TemporaryDirectory(prefix="rips") as tmpdirname: print("Temporary folder: ", tmpdirname) + + # Set export folder for snapshots and properties resInsight.commands.setExportFolder(type='SNAPSHOTS', path=tmpdirname) resInsight.commands.setExportFolder(type='PROPERTIES', path=tmpdirname) + + # Export snapshots resInsight.commands.exportSnapshots() + + # Print contents of temporary folder print(os.listdir(tmpdirname)) + assert(len(os.listdir(tmpdirname)) > 0) case = resInsight.project.case(id=0) + + # Export properties in the view resInsight.commands.exportPropertyInViews(0, "3D View", 0) + + # Check that the exported file exists expectedFileName = case.name + "-" + str("3D_View") + "-" + "T3" + "-SOIL" fullPath = tmpdirname + "/" + expectedFileName assert(os.path.exists(fullPath)) diff --git a/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/ErrorHandling.py b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/ErrorHandling.py index dacccaed71..d36d99f923 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/ErrorHandling.py +++ b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/ErrorHandling.py @@ -1,3 +1,8 @@ +################################################################### +# This example demonstrates the use of ResInsight exceptions +# for proper error handling +################################################################### + import rips import grpc diff --git a/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/ExportSnapshots.py b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/ExportSnapshots.py new file mode 100644 index 0000000000..8a5ef4cbc7 --- /dev/null +++ b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/ExportSnapshots.py @@ -0,0 +1,43 @@ +############################################################################ +# This script will export snapshots for two properties in every loaded case +# And put them in a snapshots folder in the same folder as the case grid +############################################################################ +import os +import rips + +# Load instance +resInsight = rips.Instance.find() +cases = resInsight.project.cases() + +# Set main window size +resInsight.commands.setMainWindowSize(width=800, height=500) + +n = 5 # every n-th timestep for snapshot +property_list = ['SOIL', 'PRESSURE'] # list of parameter for snapshot + +print ("Looping through cases") +for case in cases: + # Get grid path and its folder name + casepath = case.gridPath() + foldername = os.path.dirname(casepath) + + # create a folder to hold the snapshots + dirname = os.path.join(foldername, 'snapshots') + + if os.path.exists(dirname) is False: + os.mkdir(dirname) + + print ("Exporting to folder: " + dirname) + resInsight.commands.setExportFolder(type='SNAPSHOTS', path=dirname) + + timeSteps = case.timeSteps() + tss_snapshot = range(0, len(timeSteps), n) + print(case.name, case.id, 'Number of timesteps: ' + str(len(timeSteps))) + print('Number of timesteps for snapshoting: ' + str(len(tss_snapshot))) + + view = case.view(id = 0) + for property in property_list: + view.applyCellResult(resultType='DYNAMIC_NATIVE', resultVariable=property) + for ts_snapshot in tss_snapshot: + resInsight.commands.setTimeStep(caseId = case.id, timeStep = ts_snapshot) + resInsight.commands.exportSnapshots('VIEWS') # ‘ALL’, ‘VIEWS’ or ‘PLOTS’ default is 'ALL' diff --git a/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/GridInformation.py b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/GridInformation.py index 410a261efa..52ec8c3fca 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/GridInformation.py +++ b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/GridInformation.py @@ -1,6 +1,11 @@ +###################################################################################### +# This example prints information about the grids of all cases in the current project +###################################################################################### + import rips resInsight = rips.Instance.find() + cases = resInsight.project.cases() print("Number of cases found: ", len(cases)) for case in cases: diff --git a/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/InputPropTestAsync.py b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/InputPropTestAsync.py index afb56bc588..2db56bbf81 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/InputPropTestAsync.py +++ b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/InputPropTestAsync.py @@ -1,24 +1,38 @@ +######################################################################################## +# This example generates a derived property in an asynchronous manner +# Meaning it does not wait for all the data for each stage to be read before proceeding +######################################################################################## import rips import time +# Internal function for creating a result from a small chunk of poro and permx results +# The return value of the function is a generator for the results rather than the result itself. def createResult(poroChunks, permxChunks): + # Loop through all the chunks of poro and permx in order for (poroChunk, permxChunk) in zip(poroChunks, permxChunks): resultChunk = [] + # Loop through all the values inside the chunks, in order for (poro, permx) in zip(poroChunk.values, permxChunk.values): resultChunk.append(poro * permx) + # Return a generator object that behaves like a Python iterator yield resultChunk resInsight = rips.Instance.find() start = time.time() case = resInsight.project.case(id=0) +# Get a generator for the poro results. The generator will provide a chunk each time it is iterated poroChunks = case.properties.activeCellPropertyAsync('STATIC_NATIVE', 'PORO', 0) +# Get a generator for the permx results. The generator will provide a chunk each time it is iterated permxChunks = case.properties.activeCellPropertyAsync('STATIC_NATIVE', 'PERMX', 0) +# Send back the result with the result provided by a generator object. +# Iterating the result generator will cause the script to read from the poro and permx generators +# And return the result of each iteration case.properties.setActiveCellPropertyAsync(createResult(poroChunks, permxChunks), 'GENERATED', 'POROPERMXAS', 0) end = time.time() print("Time elapsed: ", end - start) - -print("Transferred all results back") \ No newline at end of file +print("Transferred all results back") +view = case.views()[0].applyCellResult('GENERATED', 'POROPERMXAS') \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/InputPropTestSync.py b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/InputPropTestSync.py index 7354fc2ced..577880a1d6 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/InputPropTestSync.py +++ b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/InputPropTestSync.py @@ -1,3 +1,8 @@ +######################################################################################## +# This example generates a derived property in an synchronous manner +# Meaning it completes reading each result before calculating the derived result +# See InputPropTestAsync for how to do this asynchronously instead. +######################################################################################## import rips import time import grpc @@ -6,14 +11,18 @@ resInsight = rips.Instance.find() start = time.time() case = resInsight.project.case(id=0) +# Read poro result into list poroResults = case.properties.activeCellProperty('STATIC_NATIVE', 'PORO', 0) +# Read permx result into list permxResults = case.properties.activeCellProperty('STATIC_NATIVE', 'PERMX', 0) +# Generate output result results = [] for (poro, permx) in zip(poroResults, permxResults): results.append(poro * permx) -try: +try: + # Send back output result case.properties.setActiveCellProperty(results, 'GENERATED', 'POROPERMXSY', 0) except grpc.RpcError as e: print("Exception Received: ", e) @@ -21,4 +30,6 @@ except grpc.RpcError as e: end = time.time() print("Time elapsed: ", end - start) -print("Transferred all results back") \ No newline at end of file +print("Transferred all results back") + +view = case.views()[0].applyCellResult('GENERATED', 'POROPERMXSY') \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/InstanceExample.py b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/InstanceExample.py index fcc15a8679..bf72ff22b4 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/InstanceExample.py +++ b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/InstanceExample.py @@ -1,3 +1,6 @@ +####################################### +# This example connects to ResInsight +####################################### import rips resInsight = rips.Instance.find() diff --git a/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/SelectedCases.py b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/SelectedCases.py index 38faffa089..80fc48d35b 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/SelectedCases.py +++ b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/SelectedCases.py @@ -1,3 +1,10 @@ +############################################################################ +# This example returns the currently selected cases in ResInsight +# Because running this script in the GUI takes away the selection +# This script does not run successfully from within the ResInsight GUI +# And will need to be run from the command line separately from ResInsight +############################################################################ + import rips resInsight = rips.Instance.find() diff --git a/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/SetCellResult.py b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/SetCellResult.py index de0b3e31b1..5eea3d07f9 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/SetCellResult.py +++ b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/SetCellResult.py @@ -1,3 +1,6 @@ +###################################################################### +# This script applies a cell result to the first view in the project +###################################################################### import rips resInsight = rips.Instance.find() diff --git a/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/SetFlowDiagnosticsResult.py b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/SetFlowDiagnosticsResult.py index 949dfb2358..9e3523f44e 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/SetFlowDiagnosticsResult.py +++ b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/SetFlowDiagnosticsResult.py @@ -1,3 +1,7 @@ +###################################################################### +# This script applies a flow diagnostics cell result to the first view in the project +###################################################################### + # Load ResInsight Processing Server Client Library import rips # Connect to ResInsight instance diff --git a/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/SetGridProperties.py b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/SetGridProperties.py index 1cdec8eb51..a7f8f7878b 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/SetGridProperties.py +++ b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/SetGridProperties.py @@ -1,3 +1,6 @@ +###################################################################### +# This script sets values for SOIL for all grid cells in the first case in the project +###################################################################### import rips resInsight = rips.Instance.find() diff --git a/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/SoilAverageAsync.py b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/SoilAverageAsync.py index 126607dec3..b6eccc186d 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/SoilAverageAsync.py +++ b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/SoilAverageAsync.py @@ -1,3 +1,7 @@ +########################################################################################### +# This example will asynchronously calculate the average value for SOIL for all time steps +########################################################################################### + import rips import itertools import time @@ -5,16 +9,23 @@ import time resInsight = rips.Instance.find() start = time.time() -case = resInsight.project.case(id=0) -grid = case.grid(index = 0) +# Get the case with case id 0 +case = resInsight.project.case(id=0) + +# Get a list of all time steps timeSteps = case.timeSteps() averages = [] for i in range(0, len(timeSteps)): + # Get the results from time step i asynchronously + # It actually returns a generator object almost immediately resultChunks = case.properties.activeCellPropertyAsync('DYNAMIC_NATIVE', 'SOIL', i) mysum = 0.0 count = 0 + # Loop through and append the average. each time we loop resultChunks + # We will trigger a read of the input data, meaning the script will start + # Calculating averages before the whole resultValue for this time step has been received for chunk in resultChunks: mysum += sum(chunk.values) count += len(chunk.values) diff --git a/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/SoilAverageNoComm.py b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/SoilAverageNoComm.py deleted file mode 100644 index 06b12c79d0..0000000000 --- a/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/SoilAverageNoComm.py +++ /dev/null @@ -1,16 +0,0 @@ -import sys -import os - -averages = [] -for i in range(0, 10): - values = [] - - sum = 0.0 - count = 0 - for j in range(0, 1199516): - sum += j - count += 1 - - averages.append(sum / count) - -print (averages) diff --git a/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/SoilAverageSync.py b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/SoilAverageSync.py index 64da1939b4..7b3b879689 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/SoilAverageSync.py +++ b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/SoilAverageSync.py @@ -1,3 +1,6 @@ +########################################################################################### +# This example will synchronously calculate the average value for SOIL for all time steps +########################################################################################### import rips import itertools import time @@ -6,15 +9,17 @@ resInsight = rips.Instance.find() start = time.time() case = resInsight.project.case(id=0) -grid = case.grid(index = 0) +# Get the case with case id 0 +case = resInsight.project.case(id=0) + +# Get a list of all time steps timeSteps = case.timeSteps() averages = [] -allResults = [] for i in range(0, len(timeSteps)): + # Get a list of all the results for time step i results = case.properties.activeCellProperty('DYNAMIC_NATIVE', 'SOIL', i) - allResults.append(results) mysum = sum(results) averages.append(mysum/len(results)) diff --git a/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/SoilPorvAsync.py b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/SoilPorvAsync.py index c9ba4b9e18..2c8bd954de 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/SoilPorvAsync.py +++ b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/SoilPorvAsync.py @@ -1,32 +1,47 @@ +############################################################################## +# This example will create a derived result for each time step asynchronously +############################################################################## + import rips import time -import numpy as np +# Internal function for creating a result from a small chunk of soil and porv results +# The return value of the function is a generator for the results rather than the result itself. def createResult(soilChunks, porvChunks): for (soilChunk, porvChunk) in zip(soilChunks, porvChunks): resultChunk = [] number = 0 - npSoilChunk = np.array(soilChunk.values) - npPorvChunk = np.array(porvChunk.values) - yield npSoilChunk + npPorvChunk - + for (soilValue, porvValue) in zip(soilChunk.values, porvChunk.values): + resultChunk.append(soilValue * porvValue) + # Return a Python generator + yield resultChunk resInsight = rips.Instance.find() -start = time.time() +start = time.time() case = resInsight.project.case(id=0) timeStepInfo = case.timeSteps() +# Get a generator for the porv results. The generator will provide a chunk each time it is iterated porvChunks = case.properties.activeCellPropertyAsync('STATIC_NATIVE', 'PORV', 0) + +# Read the static result into an array, so we don't have to transfer it for each iteration +# Note we use the async method even if we synchronise here, because we need the values chunked +# ... to match the soil chunks porvArray = [] for porvChunk in porvChunks: porvArray.append(porvChunk) for i in range (0, len(timeStepInfo)): + # Get a generator object for the SOIL property for time step i soilChunks = case.properties.activeCellPropertyAsync('DYNAMIC_NATIVE', 'SOIL', i) - input_iterator = createResult(soilChunks, iter(porvArray)) - case.properties.setActiveCellPropertyAsync(input_iterator, 'GENERATED', 'SOILPORVAsync', i) + # Create the generator object for the SOIL * PORV derived result + result_generator = createResult(soilChunks, iter(porvArray)) + # Send back the result asynchronously with a generator object + case.properties.setActiveCellPropertyAsync(result_generator, 'GENERATED', 'SOILPORVAsync', i) end = time.time() print("Time elapsed: ", end - start) -print("Transferred all results back") \ No newline at end of file +print("Transferred all results back") + +view = case.views()[0].applyCellResult('GENERATED', 'SOILPORVAsync') \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/SoilPorvSync.py b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/SoilPorvSync.py index 859a4f92bc..53684a211b 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/SoilPorvSync.py +++ b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/SoilPorvSync.py @@ -1,3 +1,7 @@ +############################################################################## +# This example will create a derived result for each time step synchronously +############################################################################## + import rips import time @@ -5,18 +9,25 @@ resInsight = rips.Instance.find() start = time.time() case = resInsight.project.case(id=0) +# Read the full porv result porvResults = case.properties.activeCellProperty('STATIC_NATIVE', 'PORV', 0) timeStepInfo = case.timeSteps() for i in range (0, len(timeStepInfo)): + # Read the full SOIl result for time step i soilResults = case.properties.activeCellProperty('DYNAMIC_NATIVE', 'SOIL', i) + + # Generate the result by looping through both lists in order results = [] for (soil, porv) in zip(soilResults, porvResults): results.append(soil * porv) + # Send back result case.properties.setActiveCellProperty(results, 'GENERATED', 'SOILPORVSync', i) end = time.time() print("Time elapsed: ", end - start) -print("Transferred all results back") \ No newline at end of file +print("Transferred all results back") + +view = case.views()[0].applyCellResult('GENERATED', 'SOILPORVSync') \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/ViewExample.py b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/ViewExample.py new file mode 100644 index 0000000000..63d70a76d5 --- /dev/null +++ b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/ViewExample.py @@ -0,0 +1,21 @@ +############################################################# +# This example will alter the views of all cases +# By setting the background color and toggle the grid box +############################################################# +import rips +# Connect to ResInsight instance +resInsight = rips.Instance.find() + +# Check if connection worked +if resInsight is not None: + # Get a list of all cases + cases = resInsight.project.cases() + for case in cases: + # Get a list of all views + views = case.views() + for view in views: + # Set some parameters for the view + view.setShowGridBox(not view.showGridBox()) + view.setBackgroundColor("#3388AA") + # Update the view in ResInsight + view.update() \ No newline at end of file From 97c795cda4a58054866ee585728b1246ed4f2a9d Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 19 Aug 2019 21:07:35 +0200 Subject: [PATCH 354/396] Remove duplicate function hiding base class implementation --- ApplicationCode/UserInterface/RiuMainWindow.cpp | 8 -------- ApplicationCode/UserInterface/RiuMainWindow.h | 2 -- 2 files changed, 10 deletions(-) diff --git a/ApplicationCode/UserInterface/RiuMainWindow.cpp b/ApplicationCode/UserInterface/RiuMainWindow.cpp index 11bb59b6b4..f581892150 100644 --- a/ApplicationCode/UserInterface/RiuMainWindow.cpp +++ b/ApplicationCode/UserInterface/RiuMainWindow.cpp @@ -1909,14 +1909,6 @@ void RiuMainWindow::slotShowWellCellsAction(bool doAdd) } } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuMainWindow::setExpanded(const caf::PdmUiItem* uiItem, bool expanded) -{ - m_projectTreeView->setExpanded(uiItem, expanded); -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/UserInterface/RiuMainWindow.h b/ApplicationCode/UserInterface/RiuMainWindow.h index 472b6ef297..5e8e5c235b 100644 --- a/ApplicationCode/UserInterface/RiuMainWindow.h +++ b/ApplicationCode/UserInterface/RiuMainWindow.h @@ -105,8 +105,6 @@ public: void refreshDrawStyleActions(); - void setExpanded(const caf::PdmUiItem* uiItem, bool expanded = true); - void tileSubWindows() override; void storeSubWindowTiling(bool tiled) override; void clearWindowTiling() override; From d0650145712e7ca3e6570b6be21f3dbe77ceab1c Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 20 Aug 2019 10:35:30 +0200 Subject: [PATCH 355/396] #4599 AppFwk : Do not scroll to item when item is collapsed --- Fwk/AppFwk/cafUserInterface/cafPdmUiTreeViewEditor.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeViewEditor.cpp b/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeViewEditor.cpp index 919ae9aa2a..1ce4905e01 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeViewEditor.cpp +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeViewEditor.cpp @@ -332,7 +332,11 @@ void PdmUiTreeViewEditor::setExpanded(const PdmUiItem* uiItem, bool doExpand) co { QModelIndex index = m_treeViewModel->findModelIndex(uiItem); m_treeView->setExpanded(index, doExpand); - m_treeView->scrollTo(index); + + if (doExpand) + { + m_treeView->scrollTo(index); + } } //-------------------------------------------------------------------------------------------------- From d86a53f732926fbc1e851e92cf46e2364ed40b97 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 20 Aug 2019 10:39:23 +0200 Subject: [PATCH 356/396] #4599 Add "Collapse Others Views/Plots" to context menu of views and plots --- .../ToggleCommands/CMakeLists_files.cmake | 2 + .../RicCollapseSiblingsFeature.cpp | 85 +++++++++++++++++++ .../RicCollapseSiblingsFeature.h | 34 ++++++++ .../RimContextCommandBuilder.cpp | 5 ++ .../UserInterface/CMakeLists_files.cmake | 2 + .../UserInterface/RiuMainWindowTools.cpp | 85 +++++++++++++++++++ .../UserInterface/RiuMainWindowTools.h | 30 +++++++ 7 files changed, 243 insertions(+) create mode 100644 ApplicationCode/Commands/ToggleCommands/RicCollapseSiblingsFeature.cpp create mode 100644 ApplicationCode/Commands/ToggleCommands/RicCollapseSiblingsFeature.h create mode 100644 ApplicationCode/UserInterface/RiuMainWindowTools.cpp create mode 100644 ApplicationCode/UserInterface/RiuMainWindowTools.h diff --git a/ApplicationCode/Commands/ToggleCommands/CMakeLists_files.cmake b/ApplicationCode/Commands/ToggleCommands/CMakeLists_files.cmake index ce811d143d..347670701c 100644 --- a/ApplicationCode/Commands/ToggleCommands/CMakeLists_files.cmake +++ b/ApplicationCode/Commands/ToggleCommands/CMakeLists_files.cmake @@ -5,6 +5,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RicToggleItemsOnFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicToggleItemsOffFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicToggleItemsFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicToggleItemsOnOthersOffFeature.h +${CMAKE_CURRENT_LIST_DIR}/RicCollapseSiblingsFeature.h ) set (SOURCE_GROUP_SOURCE_FILES @@ -13,6 +14,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RicToggleItemsOnFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicToggleItemsOffFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicToggleItemsFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicToggleItemsOnOthersOffFeature.cpp +${CMAKE_CURRENT_LIST_DIR}/RicCollapseSiblingsFeature.cpp ) list(APPEND CODE_HEADER_FILES diff --git a/ApplicationCode/Commands/ToggleCommands/RicCollapseSiblingsFeature.cpp b/ApplicationCode/Commands/ToggleCommands/RicCollapseSiblingsFeature.cpp new file mode 100644 index 0000000000..a198737ca2 --- /dev/null +++ b/ApplicationCode/Commands/ToggleCommands/RicCollapseSiblingsFeature.cpp @@ -0,0 +1,85 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 "RicCollapseSiblingsFeature.h" + +#include "Rim3dView.h" +#include "RimSummaryPlot.h" + +#include "RiuMainWindowTools.h" + +#include "cafSelectionManager.h" + +#include + +CAF_CMD_SOURCE_INIT(RicCollapseSiblingsFeature, "RicCollapseSiblingsFeature"); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RicCollapseSiblingsFeature::isCommandEnabled() +{ + { + auto selectedItem = dynamic_cast(caf::SelectionManager::instance()->selectedItem()); + if (selectedItem) return true; + } + + { + auto selectedItem = dynamic_cast(caf::SelectionManager::instance()->selectedItem()); + if (selectedItem) return true; + } + + return false; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicCollapseSiblingsFeature::onActionTriggered(bool isChecked) +{ + auto selectedItem = caf::SelectionManager::instance()->selectedItem(); + + RiuMainWindowTools::collapseSiblings(selectedItem); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicCollapseSiblingsFeature::setupActionLook(QAction* actionToSetup) +{ + QString objectName = "Items"; + + { + auto selectedItem = dynamic_cast(caf::SelectionManager::instance()->selectedItem()); + if (selectedItem) + { + objectName = "Views"; + } + } + + { + auto selectedItem = dynamic_cast(caf::SelectionManager::instance()->selectedItem()); + if (selectedItem) + { + objectName = "Plots"; + } + } + + actionToSetup->setText("Collapse Other " + objectName); + // actionToSetup->setIcon(QIcon(":/ToggleOn16x16.png")); +} diff --git a/ApplicationCode/Commands/ToggleCommands/RicCollapseSiblingsFeature.h b/ApplicationCode/Commands/ToggleCommands/RicCollapseSiblingsFeature.h new file mode 100644 index 0000000000..23ae4f326f --- /dev/null +++ b/ApplicationCode/Commands/ToggleCommands/RicCollapseSiblingsFeature.h @@ -0,0 +1,34 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 RicCollapseSiblingsFeature : public caf::CmdFeature +{ + CAF_CMD_HEADER_INIT; + +protected: + bool isCommandEnabled() override; + void onActionTriggered( bool isChecked ) override; + void setupActionLook( QAction* actionToSetup ) override; +}; diff --git a/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp b/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp index 1fe447a880..cd719000fc 100644 --- a/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp +++ b/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp @@ -930,6 +930,11 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection() menuBuilder.addSeparator(); } menuBuilder << "RicToggleItemsOnOthersOffFeature"; + + if (RicToggleItemsFeatureImpl::isToggleCommandsAvailable()) + { + menuBuilder << "RicCollapseSiblingsFeature"; + } } if ( caf::CmdFeatureManager::instance()->getCommandFeature("RicDeleteItemFeature")->canFeatureBeExecuted() ) diff --git a/ApplicationCode/UserInterface/CMakeLists_files.cmake b/ApplicationCode/UserInterface/CMakeLists_files.cmake index 7e4b0ae1b7..794e74a228 100644 --- a/ApplicationCode/UserInterface/CMakeLists_files.cmake +++ b/ApplicationCode/UserInterface/CMakeLists_files.cmake @@ -84,6 +84,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RiuWellPathComponentPlotItem.h ${CMAKE_CURRENT_LIST_DIR}/RiuMeasurementViewEventFilter.h ${CMAKE_CURRENT_LIST_DIR}/RiuDraggableOverlayFrame.h ${CMAKE_CURRENT_LIST_DIR}/RiuMdiMaximizeWindowGuard.h +${CMAKE_CURRENT_LIST_DIR}/RiuMainWindowTools.h ) set (SOURCE_GROUP_SOURCE_FILES @@ -167,6 +168,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RiuQwtPlotTools.cpp ${CMAKE_CURRENT_LIST_DIR}/RiuWellPathComponentPlotItem.cpp ${CMAKE_CURRENT_LIST_DIR}/RiuDraggableOverlayFrame.cpp ${CMAKE_CURRENT_LIST_DIR}/RiuMdiMaximizeWindowGuard.cpp +${CMAKE_CURRENT_LIST_DIR}/RiuMainWindowTools.cpp ) list(APPEND CODE_HEADER_FILES diff --git a/ApplicationCode/UserInterface/RiuMainWindowTools.cpp b/ApplicationCode/UserInterface/RiuMainWindowTools.cpp new file mode 100644 index 0000000000..d1c11dd446 --- /dev/null +++ b/ApplicationCode/UserInterface/RiuMainWindowTools.cpp @@ -0,0 +1,85 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2018- 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 "RiuMainWindowTools.h" + +#include "RiaGuiApplication.h" + +#include "RiuMainWindow.h" +#include "RiuPlotMainWindow.h" + +#include "cafPdmUiTreeOrdering.h" +#include "cafPdmUiTreeView.h" + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuMainWindowTools::collapseSiblings(const caf::PdmUiItem* sourceUiItem) +{ + if (!sourceUiItem) return; + + if (!RiaGuiApplication::isRunning()) return; + + { + caf::PdmUiTreeView* sourceTreeView = nullptr; + caf::PdmUiTreeOrdering* sourceTreeOrderingItem = nullptr; + + { + QModelIndex modIndex; + + if (RiuMainWindow::instance()) + { + modIndex = RiuMainWindow::instance()->projectTreeView()->findModelIndex(sourceUiItem); + } + + if (modIndex.isValid()) + { + sourceTreeView = RiuMainWindow::instance()->projectTreeView(); + } + else + { + RiuPlotMainWindow* mpw = RiaGuiApplication::instance()->mainPlotWindow(); + if (mpw) + { + modIndex = mpw->projectTreeView()->findModelIndex(sourceUiItem); + if (modIndex.isValid()) + { + sourceTreeView = mpw->projectTreeView(); + } + } + } + + if (!modIndex.isValid()) return; + + sourceTreeOrderingItem = static_cast(modIndex.internalPointer()); + } + + if (sourceTreeView && sourceTreeOrderingItem && sourceTreeOrderingItem->parent()) + { + for (int i = 0; i < sourceTreeOrderingItem->parent()->childCount(); i++) + { + auto siblingTreeOrderingItem = sourceTreeOrderingItem->parent()->child(i); + if (siblingTreeOrderingItem != sourceTreeOrderingItem) + { + sourceTreeView->setExpanded(siblingTreeOrderingItem->activeItem(), false); + } + } + } + } +} diff --git a/ApplicationCode/UserInterface/RiuMainWindowTools.h b/ApplicationCode/UserInterface/RiuMainWindowTools.h new file mode 100644 index 0000000000..5b4ae606e5 --- /dev/null +++ b/ApplicationCode/UserInterface/RiuMainWindowTools.h @@ -0,0 +1,30 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2018- 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 + +namespace caf +{ +class PdmUiItem; +} // namespace caf + +class RiuMainWindowTools +{ +public: + static void collapseSiblings(const caf::PdmUiItem* uiItem); +}; From fee9a2de1991c17423b98356825adb0f8fb063bf Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 21 Aug 2019 07:25:17 +0200 Subject: [PATCH 357/396] #4600 Dual porosity: Apply matrix/fracture change immediately --- .../ProjectDataModel/RimEclipseResultDefinition.cpp | 7 +++++++ .../ProjectDataModel/RimEclipseResultDefinition.h | 3 +++ 2 files changed, 10 insertions(+) diff --git a/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.cpp b/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.cpp index 76a2a903ba..94f50131a4 100644 --- a/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.cpp +++ b/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.cpp @@ -279,6 +279,13 @@ void RimEclipseResultDefinition::fieldChangedByUi(const caf::PdmFieldHandle* cha loadDataAndUpdate(); } + if (&m_porosityModelUiField == changedField) + { + m_porosityModel = m_porosityModelUiField; + m_resultVariableUiField = resultVariable(); + loadDataAndUpdate(); + } + if (&m_differenceCase == changedField) { m_timeLapseBaseTimestep = RigEclipseResultAddress::noTimeLapseValue(); diff --git a/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.h b/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.h index c44f741fb2..2f7dc83962 100644 --- a/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.h +++ b/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.h @@ -164,7 +164,10 @@ protected: // User interface only fields, to support "filtering"-like behaviour etc. caf::PdmField< caf::AppEnum< RiaDefines::ResultCatType > > m_resultTypeUiField; + + // TODO: Remove Ui field, as behavior is similar to time difference fields caf::PdmField< caf::AppEnum< RiaDefines::PorosityModelType > > m_porosityModelUiField; + caf::PdmField m_resultVariableUiField; caf::PdmField< caf::AppEnum< FlowTracerSelectionType > > m_flowTracerSelectionMode; From a97066b2f211e9fd530da91fa5f27e0a93368d93 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 21 Aug 2019 08:10:48 +0200 Subject: [PATCH 358/396] Show saturation pressure plot command on context menu of Eclipse view --- ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp b/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp index cd719000fc..8ebb7aad62 100644 --- a/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp +++ b/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp @@ -182,6 +182,7 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection() menuBuilder << "RicNewViewFeature"; menuBuilder << "RicNewContourMapViewFeature"; menuBuilder << "RicCreateGridCrossPlotFeature"; + menuBuilder << "RicCreateSaturationPressurePlotsFeature"; menuBuilder << "Separator"; menuBuilder << "RicCopyReferencesToClipboardFeature"; menuBuilder << "RicExportEclipseInputGridFeature"; From 7bfe4f4bfe5758c4155c0b0f71361087ab18d849 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Wed, 21 Aug 2019 15:11:29 +0200 Subject: [PATCH 359/396] #4603 Python: add case Id to exportSnapshots (#4604) * #4603 Python: add case Id to exportSnapshots * Fixup after review --- .../CommandFileInterface/RicfExportSnapshots.cpp | 3 ++- ApplicationCode/CommandFileInterface/RicfExportSnapshots.h | 1 + .../ExportCommands/RicSnapshotAllViewsToFileFeature.cpp | 7 +++++-- .../ExportCommands/RicSnapshotAllViewsToFileFeature.h | 2 +- ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto | 1 + ApplicationCode/GrpcInterface/Python/rips/Commands.py | 6 ++++-- .../Python/rips/PythonExamples/ExportSnapshots.py | 4 ++-- 7 files changed, 16 insertions(+), 8 deletions(-) diff --git a/ApplicationCode/CommandFileInterface/RicfExportSnapshots.cpp b/ApplicationCode/CommandFileInterface/RicfExportSnapshots.cpp index 97bd0b507d..ee272ec0a1 100644 --- a/ApplicationCode/CommandFileInterface/RicfExportSnapshots.cpp +++ b/ApplicationCode/CommandFileInterface/RicfExportSnapshots.cpp @@ -51,6 +51,7 @@ RicfExportSnapshots::RicfExportSnapshots() { RICF_InitField(&m_type, "type", RicfExportSnapshots::SnapshotsTypeEnum(), "Type", "", "", ""); RICF_InitField(&m_prefix, "prefix", QString(), "Prefix", "", "", ""); + RICF_InitField(&m_caseId, "caseId", -1, "Case Id", "", "", ""); } //-------------------------------------------------------------------------------------------------- @@ -77,7 +78,7 @@ RicfCommandResponse RicfExportSnapshots::execute() } if (m_type == RicfExportSnapshots::VIEWS || m_type == RicfExportSnapshots::ALL) { - RicSnapshotAllViewsToFileFeature::exportSnapshotOfAllViewsIntoFolder(absolutePathToSnapshotDir, m_prefix); + RicSnapshotAllViewsToFileFeature::exportSnapshotOfAllViewsIntoFolder(absolutePathToSnapshotDir, m_prefix, m_caseId()); } if (m_type == RicfExportSnapshots::PLOTS || m_type == RicfExportSnapshots::ALL) { diff --git a/ApplicationCode/CommandFileInterface/RicfExportSnapshots.h b/ApplicationCode/CommandFileInterface/RicfExportSnapshots.h index 2d2a706043..47aa2123fa 100644 --- a/ApplicationCode/CommandFileInterface/RicfExportSnapshots.h +++ b/ApplicationCode/CommandFileInterface/RicfExportSnapshots.h @@ -50,4 +50,5 @@ public: private: caf::PdmField m_type; caf::PdmField m_prefix; + caf::PdmField m_caseId; }; diff --git a/ApplicationCode/Commands/ExportCommands/RicSnapshotAllViewsToFileFeature.cpp b/ApplicationCode/Commands/ExportCommands/RicSnapshotAllViewsToFileFeature.cpp index ceac51fa33..6fe37816fd 100644 --- a/ApplicationCode/Commands/ExportCommands/RicSnapshotAllViewsToFileFeature.cpp +++ b/ApplicationCode/Commands/ExportCommands/RicSnapshotAllViewsToFileFeature.cpp @@ -68,9 +68,9 @@ void RicSnapshotAllViewsToFileFeature::saveAllViews() } //-------------------------------------------------------------------------------------------------- -/// +/// Export all snapshots of a given case (or caseId == -1 for all cases) //-------------------------------------------------------------------------------------------------- -void RicSnapshotAllViewsToFileFeature::exportSnapshotOfAllViewsIntoFolder(const QString& snapshotFolderName, const QString& prefix) +void RicSnapshotAllViewsToFileFeature::exportSnapshotOfAllViewsIntoFolder(const QString& snapshotFolderName, const QString& prefix /*= ""*/, int caseId /*= -1*/) { RimProject* project = RiaApplication::instance()->project(); @@ -94,6 +94,9 @@ void RicSnapshotAllViewsToFileFeature::exportSnapshotOfAllViewsIntoFolder(const RimCase* cas = projectCases[i]; if (!cas) continue; + bool matchingCaseId = caseId == -1 || caseId == cas->caseId(); + if (!matchingCaseId) continue; + std::vector views = cas->views(); for (size_t j = 0; j < views.size(); j++) diff --git a/ApplicationCode/Commands/ExportCommands/RicSnapshotAllViewsToFileFeature.h b/ApplicationCode/Commands/ExportCommands/RicSnapshotAllViewsToFileFeature.h index e8d664f36b..705566be1f 100644 --- a/ApplicationCode/Commands/ExportCommands/RicSnapshotAllViewsToFileFeature.h +++ b/ApplicationCode/Commands/ExportCommands/RicSnapshotAllViewsToFileFeature.h @@ -32,7 +32,7 @@ class RicSnapshotAllViewsToFileFeature : public caf::CmdFeature public: static void saveAllViews(); - static void exportSnapshotOfAllViewsIntoFolder(const QString& snapshotFolderName, const QString& prefix = ""); + static void exportSnapshotOfAllViewsIntoFolder(const QString& snapshotFolderName, const QString& prefix = "", int caseId = -1); protected: // Overrides diff --git a/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto b/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto index d5b531101d..970139eefe 100644 --- a/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto +++ b/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto @@ -52,6 +52,7 @@ message ExportSnapshotsRequest { SnapshotType type = 1; string prefix = 2; + int32 caseId = 3; } message ExportPropertyRequest diff --git a/ApplicationCode/GrpcInterface/Python/rips/Commands.py b/ApplicationCode/GrpcInterface/Python/rips/Commands.py index 063b92f081..d07ba51327 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Commands.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Commands.py @@ -118,16 +118,18 @@ class Commands: """ return self.__execute(exportMultiCaseSnapshot=Cmd.ExportMultiCaseRequest(gridListFile=gridListFile)) - def exportSnapshots(self, type = 'ALL', prefix=''): + def exportSnapshots(self, type = 'ALL', prefix='', caseId = -1): """ Export snapshots of a given type Arguments: type (str): Enum string ('ALL', 'VIEWS' or 'PLOTS') prefix (str): Exported file name prefix + caseId (int): the case Id to export for. The default of -1 will export all cases """ return self.__execute(exportSnapshots=Cmd.ExportSnapshotsRequest(type=type, - prefix=prefix)) + prefix=prefix, + caseId=caseId)) def exportProperty(self, caseId, timeStep, property, eclipseKeyword=property, undefinedValue=0.0, exportFile=property): """ Export an Eclipse property diff --git a/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/ExportSnapshots.py b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/ExportSnapshots.py index 8a5ef4cbc7..69f71f80cc 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/ExportSnapshots.py +++ b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/ExportSnapshots.py @@ -35,9 +35,9 @@ for case in cases: print(case.name, case.id, 'Number of timesteps: ' + str(len(timeSteps))) print('Number of timesteps for snapshoting: ' + str(len(tss_snapshot))) - view = case.view(id = 0) + view = case.views()[0] for property in property_list: view.applyCellResult(resultType='DYNAMIC_NATIVE', resultVariable=property) for ts_snapshot in tss_snapshot: resInsight.commands.setTimeStep(caseId = case.id, timeStep = ts_snapshot) - resInsight.commands.exportSnapshots('VIEWS') # ‘ALL’, ‘VIEWS’ or ‘PLOTS’ default is 'ALL' + resInsight.commands.exportSnapshots(type='VIEWS', caseId=case.id) # ‘ALL’, ‘VIEWS’ or ‘PLOTS’ default is 'ALL' From 4af1963ac07e915e18ab6b715a8f68b3235a5ab9 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Wed, 21 Aug 2019 15:29:25 +0200 Subject: [PATCH 360/396] #4551 Optionally Bundle grpcio Python module and dependencies (#4602) * #4551 Optionally Bundle grpcio Python module and dependencies * More status messages --- ApplicationCode/CMakeLists.txt | 28 +++++++++++-------- .../GrpcInterface/CMakeLists.cmake | 14 ++++++---- 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/ApplicationCode/CMakeLists.txt b/ApplicationCode/CMakeLists.txt index 7477a051ee..7d21500c50 100644 --- a/ApplicationCode/CMakeLists.txt +++ b/ApplicationCode/CMakeLists.txt @@ -6,6 +6,8 @@ project (ApplicationCode) find_package( OpenGL ) option(RESINSIGHT_ENABLE_GRPC "Enable the gRPC scripting framework" OFF) +option(RESINSIGHT_GRPC_BUNDLE_PYTHON_MODULE "Bundle the gRPC python modules into the install folder" OFF) + if (RESINSIGHT_BUILD_WITH_QT5) find_package(Qt5 COMPONENTS Core QUIET) endif(RESINSIGHT_BUILD_WITH_QT5) @@ -547,21 +549,13 @@ foreach (FILE_TO_COPY ${RI_DLL_FILENAMES}) endif() endforeach() -# Copy all grpc libraries and python files +# Make sure we perform the Python code generation by having a target which ResInsight depends on if (RESINSIGHT_ENABLE_GRPC) set(RESINSIGHT_GRPC_PYTHON_EXECUTABLE "" CACHE FILEPATH "gRPC : Path to Python 3 executable, required to build the Python client library") if (RESINSIGHT_GRPC_PYTHON_EXECUTABLE) if (EXISTS ${RESINSIGHT_GRPC_PYTHON_EXECUTABLE}) add_custom_target(GeneratedPythonSources DEPENDS ${GRPC_GENERATED_PYTHON_SOURCES}) add_dependencies(ResInsight GeneratedPythonSources) - - foreach (PYTHON_SCRIPT ${GRPC_PYTHON_SOURCES}) - if (EXISTS "${GRPC_PYTHON_SOURCE_PATH}/${PYTHON_SCRIPT}") - configure_file("${GRPC_PYTHON_SOURCE_PATH}/${PYTHON_SCRIPT}" - "${GRPC_PYTHON_DEST_PATH}/${PYTHON_SCRIPT}" - COPYONLY) - endif(EXISTS "${GRPC_PYTHON_SOURCE_PATH}/${PYTHON_SCRIPT}") - endforeach(PYTHON_SCRIPT ${GRPC_PYTHON_SOURCES}) else() message(STATUS "Error installing python code: RESINSIGHT_GRPC_PYTHON_EXECUTABLE set but ${RESINSIGHT_GRPC_PYTHON_EXECUTABLE} not found") endif(EXISTS ${RESINSIGHT_GRPC_PYTHON_EXECUTABLE}) @@ -581,7 +575,6 @@ set (RESINSIGHT_LICENSE_FILES # bundle libraries together with private installation if (RESINSIGHT_PRIVATE_INSTALL) - if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") # tell binary to first attempt to load libraries from its own directory set(RESINSIGHT_INSTALL_RPATH "\$ORIGIN") @@ -710,11 +703,22 @@ if (RESINSIGHT_PRIVATE_INSTALL) endif() - # install gRPC Python files if (RESINSIGHT_ENABLE_GRPC) - install(DIRECTORY ${GRPC_PYTHON_SOURCE_PATH} DESTINATION ${RESINSIGHT_INSTALL_FOLDER} FILES_MATCHING PATTERN "*.py") + message(STATUS "GRPC enabled") + if (RESINSIGHT_GRPC_PYTHON_EXECUTABLE) + message(STATUS "Python found") + if (RESINSIGHT_GRPC_BUNDLE_PYTHON_MODULE) + message(STATUS "Bundling Python GRPC modules") + add_custom_command( + TARGET ResInsight + POST_BUILD + COMMAND ${RESINSIGHT_GRPC_PYTHON_EXECUTABLE} -m pip install --target=${CMAKE_BINARY_DIR}/Python grpcio + ) + endif() + endif() endif() + install(DIRECTORY ${CMAKE_BINARY_DIR}/Python/ DESTINATION ${RESINSIGHT_INSTALL_FOLDER}/Python) set (RESINSIGHT_FILES ${RESINSIGHT_FILES} ${RESINSIGHT_LICENSE_FILES}) diff --git a/ApplicationCode/GrpcInterface/CMakeLists.cmake b/ApplicationCode/GrpcInterface/CMakeLists.cmake index 1e6000dcb6..1d10dac6a9 100644 --- a/ApplicationCode/GrpcInterface/CMakeLists.cmake +++ b/ApplicationCode/GrpcInterface/CMakeLists.cmake @@ -89,9 +89,8 @@ set(PROTO_FILES ) set(GRPC_PYTHON_SOURCE_PATH "${CMAKE_CURRENT_LIST_DIR}/Python") -set(GRPC_PYTHON_DEST_PATH "${CMAKE_BINARY_DIR}/Python") -foreach(proto_file ${PROTO_FILES}) +foreach(proto_file ${PROTO_FILES}) get_filename_component(rips_proto "${CMAKE_CURRENT_LIST_DIR}/GrpcProtos/${proto_file}.proto" ABSOLUTE) get_filename_component(rips_proto_path "${rips_proto}" PATH) @@ -155,6 +154,12 @@ endforeach(proto_file) if (RESINSIGHT_GRPC_PYTHON_EXECUTABLE) if (EXISTS ${RESINSIGHT_GRPC_PYTHON_EXECUTABLE}) + foreach(PYTHON_SCRIPT ${GRPC_PYTHON_SOURCES}) + list(APPEND GRPC_PYTHON_SOURCES_FULL_PATH "${GRPC_PYTHON_SOURCE_PATH}/${PYTHON_SCRIPT}") + # Copy into build folder so the python code is present for debugging + configure_file("${GRPC_PYTHON_SOURCE_PATH}/${PYTHON_SCRIPT}" "${CMAKE_BINARY_DIR}/Python/${PYTHON_SCRIPT}") + endforeach() + list(APPEND GRPC_PYTHON_SOURCES ${GRPC_PYTHON_GENERATED_SOURCES} "rips/generated/RiaVersionInfo.py" @@ -196,14 +201,11 @@ if (RESINSIGHT_GRPC_PYTHON_EXECUTABLE) "rips/tests/conftest.py" "rips/tests/dataroot.py" "requirements.txt" - "setup.py.cmake" + "setup.py" "README.md" "LICENSE" ) - foreach(PYTHON_SCRIPT ${GRPC_PYTHON_SOURCES}) - list(APPEND GRPC_PYTHON_SOURCES_FULL_PATH "${GRPC_PYTHON_SOURCE_PATH}/${PYTHON_SCRIPT}") - endforeach() if (MSVC) source_group(TREE ${GRPC_PYTHON_SOURCE_PATH} FILES ${GRPC_PYTHON_SOURCES_FULL_PATH} PREFIX "GrpcInterface\\Python") endif(MSVC) From 9a2cf3d1ce3a3763e1e8ec4848e1608dc91a1758 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Thu, 22 Aug 2019 08:38:49 +0200 Subject: [PATCH 361/396] #4612 Fix build error without GRPC --- ApplicationCode/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ApplicationCode/CMakeLists.txt b/ApplicationCode/CMakeLists.txt index 7d21500c50..72e3cb4139 100644 --- a/ApplicationCode/CMakeLists.txt +++ b/ApplicationCode/CMakeLists.txt @@ -706,7 +706,7 @@ if (RESINSIGHT_PRIVATE_INSTALL) # install gRPC Python files if (RESINSIGHT_ENABLE_GRPC) message(STATUS "GRPC enabled") - if (RESINSIGHT_GRPC_PYTHON_EXECUTABLE) + if (RESINSIGHT_GRPC_PYTHON_EXECUTABLE AND EXISTS ${RESINSIGHT_GRPC_PYTHON_EXECUTABLE}) message(STATUS "Python found") if (RESINSIGHT_GRPC_BUNDLE_PYTHON_MODULE) message(STATUS "Bundling Python GRPC modules") @@ -716,9 +716,9 @@ if (RESINSIGHT_PRIVATE_INSTALL) COMMAND ${RESINSIGHT_GRPC_PYTHON_EXECUTABLE} -m pip install --target=${CMAKE_BINARY_DIR}/Python grpcio ) endif() + install(DIRECTORY ${CMAKE_BINARY_DIR}/Python/ DESTINATION ${RESINSIGHT_INSTALL_FOLDER}/Python) endif() endif() - install(DIRECTORY ${CMAKE_BINARY_DIR}/Python/ DESTINATION ${RESINSIGHT_INSTALL_FOLDER}/Python) set (RESINSIGHT_FILES ${RESINSIGHT_FILES} ${RESINSIGHT_LICENSE_FILES}) From 52c9830192761272832a29e2da8992a58a582ad6 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Thu, 22 Aug 2019 08:41:09 +0200 Subject: [PATCH 362/396] Python: remove text reference to GRPC from About dialog --- .../Commands/ApplicationCommands/RicHelpFeatures.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ApplicationCode/Commands/ApplicationCommands/RicHelpFeatures.cpp b/ApplicationCode/Commands/ApplicationCommands/RicHelpFeatures.cpp index 1786d04e65..b1330523c0 100644 --- a/ApplicationCode/Commands/ApplicationCommands/RicHelpFeatures.cpp +++ b/ApplicationCode/Commands/ApplicationCommands/RicHelpFeatures.cpp @@ -125,11 +125,11 @@ void RicHelpAboutFeature::onActionTriggered(bool isChecked) RiaGrpcServer* grpcServer = RiaApplication::instance()->grpcServer(); if (grpcServer && grpcServer->isRunning()) { - dlg.addVersionEntry(" ", QString(" gRPC available and running at port %1").arg(grpcServer->portNumber())); + dlg.addVersionEntry(" ", QString(" Python Script Server available and running at port %1").arg(grpcServer->portNumber())); } else { - dlg.addVersionEntry(" ", QString(" gRPC available but currently disabled in preferences")); + dlg.addVersionEntry(" ", QString(" Python Script Server available but currently disabled in preferences")); } #else dlg.addVersionEntry(" ", " gRPC disabled"); From 28bb8641d2c4d235d9b97236f1d483f3abd59343 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Thu, 22 Aug 2019 10:42:55 +0200 Subject: [PATCH 363/396] #4615 Make Python code show up in Visual Studio project --- ApplicationCode/GrpcInterface/CMakeLists.cmake | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/ApplicationCode/GrpcInterface/CMakeLists.cmake b/ApplicationCode/GrpcInterface/CMakeLists.cmake index 1d10dac6a9..70c586dfa9 100644 --- a/ApplicationCode/GrpcInterface/CMakeLists.cmake +++ b/ApplicationCode/GrpcInterface/CMakeLists.cmake @@ -154,12 +154,6 @@ endforeach(proto_file) if (RESINSIGHT_GRPC_PYTHON_EXECUTABLE) if (EXISTS ${RESINSIGHT_GRPC_PYTHON_EXECUTABLE}) - foreach(PYTHON_SCRIPT ${GRPC_PYTHON_SOURCES}) - list(APPEND GRPC_PYTHON_SOURCES_FULL_PATH "${GRPC_PYTHON_SOURCE_PATH}/${PYTHON_SCRIPT}") - # Copy into build folder so the python code is present for debugging - configure_file("${GRPC_PYTHON_SOURCE_PATH}/${PYTHON_SCRIPT}" "${CMAKE_BINARY_DIR}/Python/${PYTHON_SCRIPT}") - endforeach() - list(APPEND GRPC_PYTHON_SOURCES ${GRPC_PYTHON_GENERATED_SOURCES} "rips/generated/RiaVersionInfo.py" @@ -205,6 +199,11 @@ if (RESINSIGHT_GRPC_PYTHON_EXECUTABLE) "README.md" "LICENSE" ) + foreach(PYTHON_SCRIPT ${GRPC_PYTHON_SOURCES}) + list(APPEND GRPC_PYTHON_SOURCES_FULL_PATH "${GRPC_PYTHON_SOURCE_PATH}/${PYTHON_SCRIPT}") + # Copy into build folder so the python code is present for debugging + configure_file("${GRPC_PYTHON_SOURCE_PATH}/${PYTHON_SCRIPT}" "${CMAKE_BINARY_DIR}/Python/${PYTHON_SCRIPT}" COPYONLY) + endforeach() if (MSVC) source_group(TREE ${GRPC_PYTHON_SOURCE_PATH} FILES ${GRPC_PYTHON_SOURCES_FULL_PATH} PREFIX "GrpcInterface\\Python") From 07cb9e52cbd8a8f5028555925d5b28cf26ec928c Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Thu, 22 Aug 2019 11:11:16 +0200 Subject: [PATCH 364/396] #4611 Merge python classes App and Instance --- .../GrpcInterface/CMakeLists.cmake | 1 - .../GrpcInterface/Python/rips/Instance.py | 43 ++++++++++++++++--- .../Python/rips/tests/conftest.py | 2 +- .../Python/rips/tests/test_commands.py | 2 +- 4 files changed, 40 insertions(+), 8 deletions(-) diff --git a/ApplicationCode/GrpcInterface/CMakeLists.cmake b/ApplicationCode/GrpcInterface/CMakeLists.cmake index 1d10dac6a9..1a39a18a2e 100644 --- a/ApplicationCode/GrpcInterface/CMakeLists.cmake +++ b/ApplicationCode/GrpcInterface/CMakeLists.cmake @@ -164,7 +164,6 @@ if (RESINSIGHT_GRPC_PYTHON_EXECUTABLE) ${GRPC_PYTHON_GENERATED_SOURCES} "rips/generated/RiaVersionInfo.py" "rips/__init__.py" - "rips/App.py" "rips/Case.py" "rips/Commands.py" "rips/Grid.py" diff --git a/ApplicationCode/GrpcInterface/Python/rips/Instance.py b/ApplicationCode/GrpcInterface/Python/rips/Instance.py index db05e08044..5c1654900c 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Instance.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Instance.py @@ -6,10 +6,12 @@ import logging import time sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'generated')) +import App_pb2 +import App_pb2_grpc +from Definitions_pb2 import Empty import RiaVersionInfo -from .App import App from .Commands import Commands from .Project import Project @@ -19,7 +21,6 @@ class Instance: Attributes: launched (bool): Tells us whether the application was launched as a new process. If the application was launched we may need to close it when exiting the script. - app (App): Application information object. Set when creating an instance. commands (Commands): Command executor. Set when creating an instance. project (Project): Current project in ResInsight. Set when creating an instance and updated when opening/closing projects. @@ -99,8 +100,8 @@ class Instance: def __checkVersion(self): try: - majorVersionOk = self.app.majorVersion() == int(RiaVersionInfo.RESINSIGHT_MAJOR_VERSION) - minorVersionOk = self.app.minorVersion() == int(RiaVersionInfo.RESINSIGHT_MINOR_VERSION) + majorVersionOk = self.majorVersion() == int(RiaVersionInfo.RESINSIGHT_MAJOR_VERSION) + minorVersionOk = self.minorVersion() == int(RiaVersionInfo.RESINSIGHT_MINOR_VERSION) return True, majorVersionOk and minorVersionOk except grpc.RpcError as e: return False, False @@ -118,7 +119,7 @@ class Instance: self.launched = launched # Main version check package - self.app = App(self.channel) + self.app = self.app = App_pb2_grpc.AppStub(self.channel) connectionOk = False versionOk = False @@ -147,3 +148,35 @@ class Instance: path = os.getcwd() self.commands.setStartDir(path=path) + + def __versionMessage(self): + return self.app.GetVersion(Empty()) + + def majorVersion(self): + """Get an integer with the major version number""" + return self.__versionMessage().major_version + + def minorVersion(self): + """Get an integer with the minor version number""" + return self.__versionMessage().minor_version + + def patchVersion(self): + """Get an integer with the patch version number""" + return self.__versionMessage().patch_version + + def versionString(self): + """Get a full version string, i.e. 2019.04.01""" + return str(self.majorVersion()) + "." + str(self.minorVersion()) + "." + str(self.patchVersion()) + + def exit(self): + """Tell ResInsight instance to quit""" + print("Telling ResInsight to Exit") + return self.app.Exit(Empty()) + + def isConsole(self): + """Returns true if the connected ResInsight instance is a console app""" + return self.app.GetRuntimeInfo(Empty()).app_type == App_pb2.ApplicationTypeEnum.Value('CONSOLE_APPLICATION') + + def isGui(self): + """Returns true if the connected ResInsight instance is a GUI app""" + return self.app.GetRuntimeInfo(Empty()).app_type == App_pb2.ApplicationTypeEnum.Value('GUI_APPLICATION') diff --git a/ApplicationCode/GrpcInterface/Python/rips/tests/conftest.py b/ApplicationCode/GrpcInterface/Python/rips/tests/conftest.py index 14345eabd1..b9d1efb2f3 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/tests/conftest.py +++ b/ApplicationCode/GrpcInterface/Python/rips/tests/conftest.py @@ -38,4 +38,4 @@ def pytest_configure(config): def pytest_unconfigure(config): if not config.getoption('--existing'): - _rips_instance.app.exit() + _rips_instance.exit() diff --git a/ApplicationCode/GrpcInterface/Python/rips/tests/test_commands.py b/ApplicationCode/GrpcInterface/Python/rips/tests/test_commands.py index a5aafd798b..184b0e42e6 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/tests/test_commands.py +++ b/ApplicationCode/GrpcInterface/Python/rips/tests/test_commands.py @@ -10,7 +10,7 @@ import rips import dataroot def test_exportSnapshots(rips_instance, initializeTest): - if not rips_instance.app.isGui(): + if not rips_instance.isGui(): pytest.skip("Cannot run test without a GUI") casePath = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID" From e03b578075cd2474c9ee0ff8b9a9ca971989cd52 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Thu, 22 Aug 2019 12:49:33 +0200 Subject: [PATCH 365/396] Install from Python source directory and not binary directory --- ApplicationCode/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ApplicationCode/CMakeLists.txt b/ApplicationCode/CMakeLists.txt index 72e3cb4139..5a8704384b 100644 --- a/ApplicationCode/CMakeLists.txt +++ b/ApplicationCode/CMakeLists.txt @@ -716,7 +716,7 @@ if (RESINSIGHT_PRIVATE_INSTALL) COMMAND ${RESINSIGHT_GRPC_PYTHON_EXECUTABLE} -m pip install --target=${CMAKE_BINARY_DIR}/Python grpcio ) endif() - install(DIRECTORY ${CMAKE_BINARY_DIR}/Python/ DESTINATION ${RESINSIGHT_INSTALL_FOLDER}/Python) + install(DIRECTORY ${GRPC_PYTHON_SOURCE_PATH}/ DESTINATION ${RESINSIGHT_INSTALL_FOLDER}/Python) endif() endif() From 5b0d77f19ae3faa2093eba14a96f04f734f487a5 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Thu, 22 Aug 2019 12:52:09 +0200 Subject: [PATCH 366/396] Configure setup.py and RiaVersionInfo.py first --- ApplicationCode/GrpcInterface/CMakeLists.cmake | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/ApplicationCode/GrpcInterface/CMakeLists.cmake b/ApplicationCode/GrpcInterface/CMakeLists.cmake index 70c586dfa9..ab6131780a 100644 --- a/ApplicationCode/GrpcInterface/CMakeLists.cmake +++ b/ApplicationCode/GrpcInterface/CMakeLists.cmake @@ -154,6 +154,11 @@ endforeach(proto_file) if (RESINSIGHT_GRPC_PYTHON_EXECUTABLE) if (EXISTS ${RESINSIGHT_GRPC_PYTHON_EXECUTABLE}) + CONFIGURE_FILE( ${CMAKE_SOURCE_DIR}/ApplicationCode/Adm/RiaVersionInfo.py.cmake + ${GRPC_PYTHON_SOURCE_PATH}/rips/generated/RiaVersionInfo.py) + CONFIGURE_FILE( ${GRPC_PYTHON_SOURCE_PATH}/setup.py.cmake + ${GRPC_PYTHON_SOURCE_PATH}/setup.py) + list(APPEND GRPC_PYTHON_SOURCES ${GRPC_PYTHON_GENERATED_SOURCES} "rips/generated/RiaVersionInfo.py" @@ -218,12 +223,5 @@ endif(RESINSIGHT_GRPC_PYTHON_EXECUTABLE) list ( APPEND GRPC_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES}) list ( APPEND GRPC_CPP_SOURCES ${SOURCE_GROUP_SOURCE_FILES}) -CONFIGURE_FILE( ${CMAKE_SOURCE_DIR}/ApplicationCode/Adm/RiaVersionInfo.py.cmake - ${GRPC_PYTHON_SOURCE_PATH}/rips/generated/RiaVersionInfo.py -) -CONFIGURE_FILE( ${GRPC_PYTHON_SOURCE_PATH}/setup.py.cmake - ${GRPC_PYTHON_SOURCE_PATH}/setup.py -) - source_group( "GrpcInterface" FILES ${SOURCE_GROUP_HEADER_FILES} ${SOURCE_GROUP_SOURCE_FILES} ${CMAKE_CURRENT_LIST_DIR}/CMakeLists.cmake ) source_group( "GrpcInterface\\GrpcProtos" FILES ${GRPC_PROTO_FILES_FULL_PATH} ) \ No newline at end of file From 84c1442af7e6ecb8f935acd38665095b2d6cac1b Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Thu, 22 Aug 2019 13:05:39 +0200 Subject: [PATCH 367/396] #4617 Disallow creating ensemble curve sets if you have no ensemble --- .../RicNewSummaryEnsembleCurveSetFeature.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/ApplicationCode/Commands/SummaryPlotCommands/RicNewSummaryEnsembleCurveSetFeature.cpp b/ApplicationCode/Commands/SummaryPlotCommands/RicNewSummaryEnsembleCurveSetFeature.cpp index e9c3a40001..c698217a3b 100644 --- a/ApplicationCode/Commands/SummaryPlotCommands/RicNewSummaryEnsembleCurveSetFeature.cpp +++ b/ApplicationCode/Commands/SummaryPlotCommands/RicNewSummaryEnsembleCurveSetFeature.cpp @@ -78,7 +78,7 @@ RimEnsembleCurveSet* RicNewSummaryEnsembleCurveSetFeature::addDefaultCurveSet(Ri void RicNewSummaryEnsembleCurveSetFeature::createPlotForCurveSetAndUpdate(RimSummaryCaseCollection* ensemble) { RiaGuiApplication* app = RiaGuiApplication::instance(); - RimProject* proj = app->project(); + RimProject* proj = app->project(); RimSummaryPlotCollection* summaryPlotCollection = proj->mainPlotCollection->summaryPlotCollection(); RimSummaryPlot* plot = summaryPlotCollection->createSummaryPlotWithAutoTitle(); @@ -100,7 +100,17 @@ void RicNewSummaryEnsembleCurveSetFeature::createPlotForCurveSetAndUpdate(RimSum //-------------------------------------------------------------------------------------------------- bool RicNewSummaryEnsembleCurveSetFeature::isCommandEnabled() { - return (selectedSummaryPlot()); + bool summaryPlotSelected = selectedSummaryPlot(); + if (summaryPlotSelected) + { + RimProject* project = RiaApplication::instance()->project(); + CVF_ASSERT(project); + if (!project->summaryGroups().empty()) + { + return true; + } + } + return false; } //-------------------------------------------------------------------------------------------------- @@ -114,6 +124,7 @@ void RicNewSummaryEnsembleCurveSetFeature::onActionTriggered(bool isChecked) RimSummaryPlot* plot = selectedSummaryPlot(); if (plot) { + CVF_ASSERT(!project->summaryGroups().empty()); auto ensemble = project->summaryGroups().back(); RicNewSummaryEnsembleCurveSetFeature::createPlotForCurveSetAndUpdate(ensemble); From fb4aff48367c5b6d677884fe6aac0b0f4ced4f34 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Thu, 22 Aug 2019 13:32:25 +0200 Subject: [PATCH 368/396] GRPC Build issues: make sure we don't run configure_file on generated sources --- ApplicationCode/GrpcInterface/CMakeLists.cmake | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/ApplicationCode/GrpcInterface/CMakeLists.cmake b/ApplicationCode/GrpcInterface/CMakeLists.cmake index ab6131780a..b0f71dd987 100644 --- a/ApplicationCode/GrpcInterface/CMakeLists.cmake +++ b/ApplicationCode/GrpcInterface/CMakeLists.cmake @@ -160,7 +160,6 @@ if (RESINSIGHT_GRPC_PYTHON_EXECUTABLE) ${GRPC_PYTHON_SOURCE_PATH}/setup.py) list(APPEND GRPC_PYTHON_SOURCES - ${GRPC_PYTHON_GENERATED_SOURCES} "rips/generated/RiaVersionInfo.py" "rips/__init__.py" "rips/App.py" @@ -204,12 +203,18 @@ if (RESINSIGHT_GRPC_PYTHON_EXECUTABLE) "README.md" "LICENSE" ) + foreach(PYTHON_SCRIPT ${GRPC_PYTHON_SOURCES}) - list(APPEND GRPC_PYTHON_SOURCES_FULL_PATH "${GRPC_PYTHON_SOURCE_PATH}/${PYTHON_SCRIPT}") # Copy into build folder so the python code is present for debugging configure_file("${GRPC_PYTHON_SOURCE_PATH}/${PYTHON_SCRIPT}" "${CMAKE_BINARY_DIR}/Python/${PYTHON_SCRIPT}" COPYONLY) endforeach() + list(APPEND GRPC_PYTHON_SOURCES ${GRPC_PYTHON_GENERATED_SOURCES}) + + foreach(PYTHON_SCRIPT ${GRPC_PYTHON_SOURCES}) + list(APPEND GRPC_PYTHON_SOURCES_FULL_PATH "${GRPC_PYTHON_SOURCE_PATH}/${PYTHON_SCRIPT}") + endforeach() + if (MSVC) source_group(TREE ${GRPC_PYTHON_SOURCE_PATH} FILES ${GRPC_PYTHON_SOURCES_FULL_PATH} PREFIX "GrpcInterface\\Python") endif(MSVC) From 4afe159f91995595049971c570355e711912faf8 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Thu, 22 Aug 2019 14:16:46 +0200 Subject: [PATCH 369/396] #4611 Remove App.py --- .../GrpcInterface/Python/rips/App.py | 42 ------------------- 1 file changed, 42 deletions(-) delete mode 100644 ApplicationCode/GrpcInterface/Python/rips/App.py diff --git a/ApplicationCode/GrpcInterface/Python/rips/App.py b/ApplicationCode/GrpcInterface/Python/rips/App.py deleted file mode 100644 index 64b2596396..0000000000 --- a/ApplicationCode/GrpcInterface/Python/rips/App.py +++ /dev/null @@ -1,42 +0,0 @@ -import grpc -import os -import sys - -sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'generated')) - -from Definitions_pb2 import Empty - -import App_pb2 -import App_pb2_grpc - -class App: - """ResInsight application information and control. - Allows retrieving of information and controlling the running instance - Not meant to be constructed manually, but exists as part of the Instance method - """ - def __init__(self, channel): - self.app = App_pb2_grpc.AppStub(channel) - def __versionMessage(self): - return self.app.GetVersion(Empty()) - def majorVersion(self): - """Get an integer with the major version number""" - return self.__versionMessage().major_version - def minorVersion(self): - """Get an integer with the minor version number""" - return self.__versionMessage().minor_version - def patchVersion(self): - """Get an integer with the patch version number""" - return self.__versionMessage().patch_version - def versionString(self): - """Get a full version string, i.e. 2019.04.01""" - return str(self.majorVersion()) + "." + str(self.minorVersion()) + "." + str(self.patchVersion()) - def exit(self): - """Tell ResInsight instance to quit""" - print("Telling ResInsight to Exit") - return self.app.Exit(Empty()) - def isConsole(self): - """Returns true if the connected ResInsight instance is a console app""" - return self.app.GetRuntimeInfo(Empty()).app_type == App_pb2.ApplicationTypeEnum.Value('CONSOLE_APPLICATION') - def isGui(self): - """Returns true if the connected ResInsight instance is a GUI app""" - return self.app.GetRuntimeInfo(Empty()).app_type == App_pb2.ApplicationTypeEnum.Value('GUI_APPLICATION') From a86ae13bb74c0c40b3bcaa374af565f1d702853b Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 22 Aug 2019 14:41:51 +0200 Subject: [PATCH 370/396] Rename command line argument to --server --- ApplicationCode/Application/RiaApplication.cpp | 2 +- ApplicationCode/Application/Tools/RiaArgumentParser.cpp | 4 ++-- ApplicationCode/GrpcInterface/Python/rips/Instance.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ApplicationCode/Application/RiaApplication.cpp b/ApplicationCode/Application/RiaApplication.cpp index 1d3cbbf22e..d8772cdcfd 100644 --- a/ApplicationCode/Application/RiaApplication.cpp +++ b/ApplicationCode/Application/RiaApplication.cpp @@ -1379,7 +1379,7 @@ bool RiaApplication::initializeGrpcServer(const cvf::ProgramOptions& progOpt) int defaultPortNumber = m_preferences->defaultGrpcPortNumber(); bool fixedPort = false; - if (cvf::Option o = progOpt.option("grpcserver")) + if (cvf::Option o = progOpt.option("server")) { if (o.valueCount() == 1) { diff --git a/ApplicationCode/Application/Tools/RiaArgumentParser.cpp b/ApplicationCode/Application/Tools/RiaArgumentParser.cpp index 1287cdad13..5168ffcf71 100644 --- a/ApplicationCode/Application/Tools/RiaArgumentParser.cpp +++ b/ApplicationCode/Application/Tools/RiaArgumentParser.cpp @@ -68,8 +68,8 @@ bool RiaArgumentParser::parseArguments(cvf::ProgramOptions* progOpt) "If has extension .SMSPEC, import the summary file (does not open the corresponding grid file)", cvf::ProgramOptions::MULTI_VALUE); progOpt->registerOption("size", " ", "Set size of the main application window.", cvf::ProgramOptions::MULTI_VALUE); - progOpt->registerOption("console", "", "Run as a console application without Graphics"); - progOpt->registerOption("grpcserver", "[]", "Run as a GRPC server. Default port is 50051", cvf::ProgramOptions::SINGLE_VALUE); + progOpt->registerOption("console", "", "Launch as a console application without graphics"); + progOpt->registerOption("server", "[]", "Launch as a GRPC server. Default port is 50051", cvf::ProgramOptions::SINGLE_VALUE); progOpt->registerOption("startdir", "", "Set startup directory.\n", cvf::ProgramOptions::SINGLE_VALUE); progOpt->registerOption("commandFile", "", "Execute the command file.", cvf::ProgramOptions::SINGLE_VALUE); diff --git a/ApplicationCode/GrpcInterface/Python/rips/Instance.py b/ApplicationCode/GrpcInterface/Python/rips/Instance.py index 5c1654900c..d5b55b3ecd 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Instance.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Instance.py @@ -64,7 +64,7 @@ class Instance: print('Port ' + str(port)) print('Trying to launch', resInsightExecutable) - parameters = ["ResInsight", "--grpcserver", str(port)] + parameters = ["ResInsight", "--server", str(port)] if console: print("Launching as console app") parameters.append("--console") From 3f6d0db07a8e8dd9962962039b597573e8fe9e9e Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Thu, 22 Aug 2019 15:50:40 +0200 Subject: [PATCH 371/396] #4622 Make sure inverted axis values are assigned correctly in GridCrossPlot y-axis properties --- .../ProjectDataModel/GridCrossPlots/RimGridCrossPlot.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/GridCrossPlots/RimGridCrossPlot.cpp b/ApplicationCode/ProjectDataModel/GridCrossPlots/RimGridCrossPlot.cpp index 75fd58a8ff..736571b5ab 100644 --- a/ApplicationCode/ProjectDataModel/GridCrossPlots/RimGridCrossPlot.cpp +++ b/ApplicationCode/ProjectDataModel/GridCrossPlots/RimGridCrossPlot.cpp @@ -881,8 +881,8 @@ void RimGridCrossPlot::updateAxisFromQwt(RiaDefines::PlotAxis axisType) axisRange = yAxisRange; } - axisProperties->visibleRangeMin = axisRange.minValue(); - axisProperties->visibleRangeMax = axisRange.maxValue(); + axisProperties->visibleRangeMin = std::min(axisRange.minValue(), axisRange.maxValue()); + axisProperties->visibleRangeMax = std::max(axisRange.minValue(), axisRange.maxValue()); axisProperties->updateConnectedEditors(); } From 2e49670f4046723c7f572f7f15d15a9b8d316b7f Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Fri, 23 Aug 2019 11:25:00 +0200 Subject: [PATCH 372/396] #4578 Add commands for create and clone view --- .../CMakeLists_files.cmake | 4 + .../CommandFileInterface/RicfCloneView.cpp | 80 +++++++++++++++++ .../CommandFileInterface/RicfCloneView.h | 41 +++++++++ .../CommandFileInterface/RicfCreateView.cpp | 85 +++++++++++++++++++ .../CommandFileInterface/RicfCreateView.h | 52 ++++++++++++ .../CommandFileInterface/RicfLoadCase.cpp | 1 - .../GrpcInterface/GrpcProtos/Commands.proto | 20 ++++- .../GrpcInterface/Python/rips/Case.py | 14 ++- .../GrpcInterface/Python/rips/Commands.py | 10 ++- .../Python/rips/GridCaseGroup.py | 4 +- .../GrpcInterface/Python/rips/Instance.py | 4 +- .../GrpcInterface/Python/rips/Project.py | 10 +-- .../Python/rips/PythonExamples/AllCases.py | 4 + .../Python/rips/PythonExamples/ViewExample.py | 8 +- .../GrpcInterface/Python/rips/View.py | 20 ++++- .../GrpcInterface/Python/rips/__init__.py | 1 - .../ProjectDataModel/Rim3dView.cpp | 3 - .../ProjectDataModel/RimEclipseCase.cpp | 4 +- .../ProjectDataModel/RimGeoMechCase.cpp | 27 +++++- .../ProjectDataModel/RimGeoMechCase.h | 1 + .../ProjectDataModel/RimGeoMechView.cpp | 2 +- .../ProjectDataModel/RimGeoMechView.h | 2 +- 22 files changed, 368 insertions(+), 29 deletions(-) create mode 100644 ApplicationCode/CommandFileInterface/RicfCloneView.cpp create mode 100644 ApplicationCode/CommandFileInterface/RicfCloneView.h create mode 100644 ApplicationCode/CommandFileInterface/RicfCreateView.cpp create mode 100644 ApplicationCode/CommandFileInterface/RicfCreateView.h diff --git a/ApplicationCode/CommandFileInterface/CMakeLists_files.cmake b/ApplicationCode/CommandFileInterface/CMakeLists_files.cmake index 17f60f1f6e..933045014f 100644 --- a/ApplicationCode/CommandFileInterface/CMakeLists_files.cmake +++ b/ApplicationCode/CommandFileInterface/CMakeLists_files.cmake @@ -31,6 +31,8 @@ ${CMAKE_CURRENT_LIST_DIR}/RicfCreateSaturationPressurePlots.h ${CMAKE_CURRENT_LIST_DIR}/RicfExportFlowCharacteristics.h ${CMAKE_CURRENT_LIST_DIR}/RicfCreateGridCaseGroup.h ${CMAKE_CURRENT_LIST_DIR}/RicfCreateStatisticsCase.h +${CMAKE_CURRENT_LIST_DIR}/RicfCreateView.h +${CMAKE_CURRENT_LIST_DIR}/RicfCloneView.h ) set (SOURCE_GROUP_SOURCE_FILES @@ -65,6 +67,8 @@ ${CMAKE_CURRENT_LIST_DIR}/RicfCreateSaturationPressurePlots.cpp ${CMAKE_CURRENT_LIST_DIR}/RicfExportFlowCharacteristics.cpp ${CMAKE_CURRENT_LIST_DIR}/RicfCreateGridCaseGroup.cpp ${CMAKE_CURRENT_LIST_DIR}/RicfCreateStatisticsCase.cpp +${CMAKE_CURRENT_LIST_DIR}/RicfCreateView.cpp +${CMAKE_CURRENT_LIST_DIR}/RicfCloneView.cpp ) list(APPEND CODE_HEADER_FILES diff --git a/ApplicationCode/CommandFileInterface/RicfCloneView.cpp b/ApplicationCode/CommandFileInterface/RicfCloneView.cpp new file mode 100644 index 0000000000..ed78b7b359 --- /dev/null +++ b/ApplicationCode/CommandFileInterface/RicfCloneView.cpp @@ -0,0 +1,80 @@ +#include "RicfCloneView.h" + +#include "RiaApplication.h" +#include "RiaLogging.h" + +#include "RicfCreateView.h" + +#include "Rim3dView.h" +#include "RimEclipseCase.h" +#include "RimEclipseView.h" +#include "RimGeoMechCase.h" +#include "RimGeoMechView.h" +#include "RimProject.h" + +#include "Riu3DMainWindowTools.h" + +#include "cafSelectionManager.h" + +#include + +CAF_PDM_SOURCE_INIT(RicfCloneView, "cloneView"); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RicfCloneView::RicfCloneView() +{ + RICF_InitField(&m_viewId, "viewId", -1, "View Id", "", "", ""); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RicfCommandResponse RicfCloneView::execute() +{ + RimProject* project = RiaApplication::instance()->project(); + std::vector allViews; + project->descendantsIncludingThisOfType(allViews); + + for (Rim3dView* view : allViews) + { + if (view->id() == m_viewId()) + { + const RimEclipseView* eclipseView = dynamic_cast(view); + const RimGeoMechView* geoMechView = dynamic_cast(view); + + int newViewId = -1; + if (eclipseView) + { + RimEclipseCase* eclipseCase = eclipseView->eclipseCase(); + RimEclipseView* newEclipseView = eclipseCase->createCopyAndAddView(eclipseView); + newViewId = newEclipseView->id(); + newEclipseView->loadDataAndUpdate(); + eclipseCase->updateConnectedEditors(); + Riu3DMainWindowTools::setExpanded(newEclipseView); + } + else if (geoMechView) + { + RimGeoMechCase* geoMechCase = geoMechView->geoMechCase(); + RimGeoMechView* newGeoMechView = geoMechCase->createCopyAndAddView(geoMechView); + newViewId = newGeoMechView->id(); + view->loadDataAndUpdate(); + geoMechCase->updateConnectedEditors(); + Riu3DMainWindowTools::setExpanded(view); + } + + if (newViewId) + { + RicfCommandResponse response; + response.setResult(new RicfCreateViewResult(newViewId)); + return response; + + } + } + } + + QString error = QString("cloneView: Could not clone view with id %1").arg(m_viewId()); + RiaLogging::error(error); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, error); +} diff --git a/ApplicationCode/CommandFileInterface/RicfCloneView.h b/ApplicationCode/CommandFileInterface/RicfCloneView.h new file mode 100644 index 0000000000..64e96da95a --- /dev/null +++ b/ApplicationCode/CommandFileInterface/RicfCloneView.h @@ -0,0 +1,41 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 "RicfCommandObject.h" + +#include "cafPdmField.h" + +//================================================================================================== +// +// +// +//================================================================================================== +class RicfCloneView : public RicfCommandObject +{ + CAF_PDM_HEADER_INIT; + +public: + RicfCloneView(); + + RicfCommandResponse execute() override; + +private: + caf::PdmField m_viewId; +}; diff --git a/ApplicationCode/CommandFileInterface/RicfCreateView.cpp b/ApplicationCode/CommandFileInterface/RicfCreateView.cpp new file mode 100644 index 0000000000..51ed5117e7 --- /dev/null +++ b/ApplicationCode/CommandFileInterface/RicfCreateView.cpp @@ -0,0 +1,85 @@ +#include "RicfCreateView.h" + +#include "RiaApplication.h" +#include "RiaLogging.h" + +#include "Rim3dView.h" +#include "RimEclipseCase.h" +#include "RimEclipseView.h" +#include "RimGeoMechCase.h" +#include "RimGeoMechView.h" +#include "RimProject.h" + +#include "Riu3DMainWindowTools.h" + +#include "cafSelectionManager.h" + +#include + +CAF_PDM_SOURCE_INIT(RicfCreateViewResult, "createViewResult"); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RicfCreateViewResult::RicfCreateViewResult(int viewId /*= -1*/) +{ + CAF_PDM_InitObject("view_result", "", "", ""); + CAF_PDM_InitField(&this->viewId, "viewId", viewId, "", "", "", ""); +} + +CAF_PDM_SOURCE_INIT(RicfCreateView, "createView"); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RicfCreateView::RicfCreateView() +{ + RICF_InitField(&m_caseId, "caseId", -1, "Case Id", "", "", ""); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RicfCommandResponse RicfCreateView::execute() +{ + RimProject* project = RiaApplication::instance()->project(); + std::vector allCases; + project->allCases(allCases); + + for (RimCase* rimCase : allCases) + { + if (rimCase->caseId == m_caseId()) + { + int viewId = -1; + RimEclipseCase* eclipseCase = dynamic_cast(rimCase); + RimGeoMechCase* geoMechCase = dynamic_cast(rimCase); + if (eclipseCase) + { + RimEclipseView* view = eclipseCase->createAndAddReservoirView(); + viewId = view->id(); + view->loadDataAndUpdate(); + eclipseCase->updateConnectedEditors(); + Riu3DMainWindowTools::setExpanded(view); + } + else if (geoMechCase) + { + RimGeoMechView* view = geoMechCase->createAndAddReservoirView(); + viewId = view->id(); + view->loadDataAndUpdate(); + geoMechCase->updateConnectedEditors(); + Riu3DMainWindowTools::setExpanded(view); + } + + if (viewId >= 0) + { + RicfCommandResponse response; + response.setResult(new RicfCreateViewResult(viewId)); + return response; + } + } + } + + QString error = QString("createView: Could not create view for case id %1").arg(m_caseId()); + RiaLogging::error(error); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, error); +} diff --git a/ApplicationCode/CommandFileInterface/RicfCreateView.h b/ApplicationCode/CommandFileInterface/RicfCreateView.h new file mode 100644 index 0000000000..df9c809946 --- /dev/null +++ b/ApplicationCode/CommandFileInterface/RicfCreateView.h @@ -0,0 +1,52 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 "RicfCommandObject.h" + +#include "cafPdmField.h" + +class RicfCreateViewResult : public caf::PdmObject +{ + CAF_PDM_HEADER_INIT; + +public: + RicfCreateViewResult(int viewId = -1); + +public: + caf::PdmField viewId; +}; + +//================================================================================================== +// +// +// +//================================================================================================== +class RicfCreateView : public RicfCommandObject +{ + CAF_PDM_HEADER_INIT; + +public: + RicfCreateView(); + + RicfCommandResponse execute() override; + +private: + caf::PdmField m_caseId; +}; diff --git a/ApplicationCode/CommandFileInterface/RicfLoadCase.cpp b/ApplicationCode/CommandFileInterface/RicfLoadCase.cpp index a0ca993e00..bb03dfb341 100644 --- a/ApplicationCode/CommandFileInterface/RicfLoadCase.cpp +++ b/ApplicationCode/CommandFileInterface/RicfLoadCase.cpp @@ -70,7 +70,6 @@ RicfCommandResponse RicfLoadCase::execute() return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, error); } CAF_ASSERT(fileCaseIdMap.size() == 1u); - RicfLoadCaseResult result; RicfCommandResponse response; response.setResult(new RicfLoadCaseResult(fileCaseIdMap.begin()->second)); return response; diff --git a/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto b/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto index 970139eefe..8676996ecf 100644 --- a/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto +++ b/ApplicationCode/GrpcInterface/GrpcProtos/Commands.proto @@ -256,6 +256,16 @@ message ExportFlowInfoRequest double aquiferCellThreshold = 7; } +message CreateViewRequest +{ + int32 caseId = 1; +} + +message CloneViewRequest +{ + int32 viewId = 1; +} + /* CommandParams handles both command name and parameters in one. * The message type and content is used as parameters and * the name of the variable is used to find the command name. */ @@ -296,8 +306,8 @@ message CommandParams CreateGridCaseGroupRequest createGridCaseGroup = 27; CreateStatisticsCaseRequest createStatisticsCase = 28; ExportFlowInfoRequest exportFlowCharacteristics = 29; - - + CreateViewRequest createView = 30; + CloneViewRequest cloneView = 31; } } @@ -312,6 +322,11 @@ message CreateStatisticsCaseResult int32 caseId = 1; } +message CreateViewResult +{ + int32 viewId = 1; +} + /* Command reply handles the return values for the generic command * The name of the variable is used to map to the cafPdmObject classKeyword */ message CommandReply @@ -322,6 +337,7 @@ message CommandReply CaseRequest loadCaseResult = 2; GridCaseGroupResult createGridCaseGroupResult = 3; CreateStatisticsCaseResult createStatisticsCaseResult = 4; + CreateViewResult createViewResult = 5; } } diff --git a/ApplicationCode/GrpcInterface/Python/rips/Case.py b/ApplicationCode/GrpcInterface/Python/rips/Case.py index dde1466455..897bc68f95 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Case.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Case.py @@ -1,10 +1,11 @@ import grpc import os import sys -from .Grid import Grid -from .Properties import Properties -from .PdmObject import PdmObject -from .View import View +from rips.Commands import Commands +from rips.Grid import Grid +from rips.Properties import Properties +from rips.PdmObject import PdmObject +from rips.View import View sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'generated')) @@ -156,3 +157,8 @@ class Case (PdmObject): return viewObject return None + def createView(self): + """Create a new view in the current case""" + viewId = Commands(self.channel).createView(self.id) + return self.view(viewId) + diff --git a/ApplicationCode/GrpcInterface/Python/rips/Commands.py b/ApplicationCode/GrpcInterface/Python/rips/Commands.py index d07ba51327..ced55b5bfc 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Commands.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Commands.py @@ -7,7 +7,7 @@ sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'generated')) from Definitions_pb2 import Empty import Commands_pb2 as Cmd import Commands_pb2_grpc as CmdRpc -from .Case import Case +import rips.Case class Commands: """Command executor which can run ResInsight Command File commands nearly verbatim @@ -65,7 +65,7 @@ class Commands: """ commandReply = self.__execute(loadCase=Cmd.FilePathRequest(path=path)) - return Case(self.channel, commandReply.loadCaseResult.id) + return rips.Case(self.channel, commandReply.loadCaseResult.id) def replaceCase(self, newGridFile, caseId=0): """Replace the given case with a new case loaded from file @@ -276,3 +276,9 @@ class Commands: fileName=fileName, minimumCommunication = minimumCommunication, aquiferCellThreshold = aquiferCellThreshold)) + + def createView(self, caseId): + return self.__execute(createView=Cmd.CreateViewRequest(caseId=caseId)).createViewResult.viewId + + def cloneView(self, viewId): + return self.__execute(cloneView=Cmd.CloneViewRequest(viewId=viewId)).createViewResult.viewId \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/Python/rips/GridCaseGroup.py b/ApplicationCode/GrpcInterface/Python/rips/GridCaseGroup.py index 1f2802fb45..d00d2f9e40 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/GridCaseGroup.py +++ b/ApplicationCode/GrpcInterface/Python/rips/GridCaseGroup.py @@ -1,8 +1,8 @@ import grpc import os import sys -from .PdmObject import PdmObject -from .View import View +from rips.PdmObject import PdmObject +from rips.View import View sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'generated')) diff --git a/ApplicationCode/GrpcInterface/Python/rips/Instance.py b/ApplicationCode/GrpcInterface/Python/rips/Instance.py index d5b55b3ecd..55660ce274 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Instance.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Instance.py @@ -12,8 +12,8 @@ from Definitions_pb2 import Empty import RiaVersionInfo -from .Commands import Commands -from .Project import Project +from rips.Commands import Commands +from rips.Project import Project class Instance: """The ResInsight Instance class. Use to launch or find existing ResInsight instances diff --git a/ApplicationCode/GrpcInterface/Python/rips/Project.py b/ApplicationCode/GrpcInterface/Python/rips/Project.py index 42359f7a70..23c8e7ab2e 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Project.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Project.py @@ -2,11 +2,11 @@ import grpc import os import sys -from .Case import Case -from .Commands import Commands -from .GridCaseGroup import GridCaseGroup -from .PdmObject import PdmObject -from .View import View +from rips.Case import Case +from rips.Commands import Commands +from rips.GridCaseGroup import GridCaseGroup +from rips.PdmObject import PdmObject +from rips.View import View sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'generated')) diff --git a/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/AllCases.py b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/AllCases.py index f54195c1ff..91d2db22c3 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/AllCases.py +++ b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/AllCases.py @@ -1,5 +1,6 @@ ################################################################################### # This example will connect to ResInsight, retrieve a list of cases and print info +# Also creates a new view for all cases ################################################################################### # Import the ResInsight Processing Server Module @@ -15,4 +16,7 @@ if resInsight is not None: for case in cases: print("Case name: " + case.name) print("Case grid path: " + case.gridPath()) + # Create a new view + view = case.createView() + diff --git a/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/ViewExample.py b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/ViewExample.py index 63d70a76d5..3b03154125 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/ViewExample.py +++ b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/ViewExample.py @@ -1,6 +1,7 @@ ############################################################# # This example will alter the views of all cases # By setting the background color and toggle the grid box +# Also clones the first view ############################################################# import rips # Connect to ResInsight instance @@ -18,4 +19,9 @@ if resInsight is not None: view.setShowGridBox(not view.showGridBox()) view.setBackgroundColor("#3388AA") # Update the view in ResInsight - view.update() \ No newline at end of file + view.update() + # Clone the first view + newView = views[0].clone() + view.setShowGridBox(False) + newView.setBackgroundColor("#FFAA33") + newView.update() \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/Python/rips/View.py b/ApplicationCode/GrpcInterface/Python/rips/View.py index d895e1bf34..115bf05238 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/View.py +++ b/ApplicationCode/GrpcInterface/Python/rips/View.py @@ -1,4 +1,6 @@ -from .PdmObject import PdmObject +import rips.Case +from rips.Commands import Commands +from rips.PdmObject import PdmObject class View (PdmObject): """ResInsight view class @@ -74,4 +76,18 @@ class View (PdmObject): if selectionMode == 'FLOW_TR_BY_SELECTION': cellResult.setValue("SelectedInjectorTracers", injectors) cellResult.setValue("SelectedProducerTracers", producers) - cellResult.update() \ No newline at end of file + cellResult.update() + + def case(self): + """Get the case the view belongs to""" + pdmCase = self.ancestor("EclipseCase") + if pdmCase is None: + pdmCase = self.ancestor("ResInsightGeoMechCase") + if pdmCase is None: + return None + return rips.Case(self.channel, pdmCase.getValue("CaseId")) + + def clone(self): + """Clone the current view""" + viewId = Commands(self.channel).cloneView(self.id) + return self.case().view(viewId) \ No newline at end of file diff --git a/ApplicationCode/GrpcInterface/Python/rips/__init__.py b/ApplicationCode/GrpcInterface/Python/rips/__init__.py index 84a933e156..973283f882 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/__init__.py +++ b/ApplicationCode/GrpcInterface/Python/rips/__init__.py @@ -3,7 +3,6 @@ from .Case import Case from .Grid import Grid from .Properties import Properties from .Instance import Instance -from .App import App from .Commands import Commands from .PdmObject import PdmObject from .View import View diff --git a/ApplicationCode/ProjectDataModel/Rim3dView.cpp b/ApplicationCode/ProjectDataModel/Rim3dView.cpp index bb99f51c81..e98faaadee 100644 --- a/ApplicationCode/ProjectDataModel/Rim3dView.cpp +++ b/ApplicationCode/ProjectDataModel/Rim3dView.cpp @@ -141,9 +141,6 @@ Rim3dView::Rim3dView(void) m_measurementPartManager = new RivMeasurementPartMgr(this); this->setAs3DViewMdiWindow(); - - RimProject* proj = RiaApplication::instance()->project(); - proj->assignViewIdToView(this); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimEclipseCase.cpp b/ApplicationCode/ProjectDataModel/RimEclipseCase.cpp index e5b9acec89..8f9530d5bd 100644 --- a/ApplicationCode/ProjectDataModel/RimEclipseCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimEclipseCase.cpp @@ -271,6 +271,8 @@ void RimEclipseCase::initAfterRead() RimEclipseView* RimEclipseCase::createAndAddReservoirView() { RimEclipseView* rimEclipseView = new RimEclipseView(); + RiaApplication::instance()->project()->assignViewIdToView(rimEclipseView); + rimEclipseView->setEclipseCase(this); // Set default values @@ -306,7 +308,7 @@ RimEclipseView* RimEclipseCase::createCopyAndAddView(const RimEclipseView* sourc RimEclipseView* rimEclipseView = dynamic_cast( sourceView->xmlCapability()->copyByXmlSerialization(caf::PdmDefaultObjectFactory::instance())); CVF_ASSERT(rimEclipseView); - + RiaApplication::instance()->project()->assignViewIdToView(rimEclipseView); rimEclipseView->setEclipseCase(this); caf::PdmDocument::updateUiIconStateRecursively(rimEclipseView); diff --git a/ApplicationCode/ProjectDataModel/RimGeoMechCase.cpp b/ApplicationCode/ProjectDataModel/RimGeoMechCase.cpp index 9d1bde616e..4b1a3ab914 100644 --- a/ApplicationCode/ProjectDataModel/RimGeoMechCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimGeoMechCase.cpp @@ -181,13 +181,38 @@ void RimGeoMechCase::reloadDataAndUpdate() RimGeoMechView* RimGeoMechCase::createAndAddReservoirView() { RimGeoMechView* gmv = new RimGeoMechView(); - + RiaApplication::instance()->project()->assignViewIdToView(gmv); + gmv->setGeoMechCase(this); geoMechViews.push_back(gmv); return gmv; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimGeoMechView* RimGeoMechCase::createCopyAndAddView(const RimGeoMechView* sourceView) +{ + RimGeoMechView* rimGeoMechView = dynamic_cast( + sourceView->xmlCapability()->copyByXmlSerialization(caf::PdmDefaultObjectFactory::instance())); + CVF_ASSERT(rimGeoMechView); + + RiaApplication::instance()->project()->assignViewIdToView(rimGeoMechView); + rimGeoMechView->setGeoMechCase(this); + + caf::PdmDocument::updateUiIconStateRecursively(rimGeoMechView); + + geoMechViews.push_back(rimGeoMechView); + + // Resolve references after reservoir view has been inserted into Rim structures + rimGeoMechView->resolveReferencesRecursively(); + rimGeoMechView->initAfterReadRecursively(); + + return rimGeoMechView; + +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimGeoMechCase.h b/ApplicationCode/ProjectDataModel/RimGeoMechCase.h index e7fa9b3ae1..a7e1cf8a3f 100644 --- a/ApplicationCode/ProjectDataModel/RimGeoMechCase.h +++ b/ApplicationCode/ProjectDataModel/RimGeoMechCase.h @@ -67,6 +67,7 @@ public: void reloadDataAndUpdate(); RimGeoMechView* createAndAddReservoirView(); + RimGeoMechView* createCopyAndAddView(const RimGeoMechView* sourceView); void updateFilePathsFromProjectPath(const QString& projectPath, const QString& oldProjectPath) override; diff --git a/ApplicationCode/ProjectDataModel/RimGeoMechView.cpp b/ApplicationCode/ProjectDataModel/RimGeoMechView.cpp index d46cc390a5..8d2271de86 100644 --- a/ApplicationCode/ProjectDataModel/RimGeoMechView.cpp +++ b/ApplicationCode/ProjectDataModel/RimGeoMechView.cpp @@ -682,7 +682,7 @@ void RimGeoMechView::convertCameraPositionFromOldProjectFiles() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RimGeoMechCase* RimGeoMechView::geoMechCase() +RimGeoMechCase* RimGeoMechView::geoMechCase() const { return m_geomechCase; } diff --git a/ApplicationCode/ProjectDataModel/RimGeoMechView.h b/ApplicationCode/ProjectDataModel/RimGeoMechView.h index 1701031518..ba91d0d21a 100644 --- a/ApplicationCode/ProjectDataModel/RimGeoMechView.h +++ b/ApplicationCode/ProjectDataModel/RimGeoMechView.h @@ -64,7 +64,7 @@ public: ~RimGeoMechView(void) override; void setGeoMechCase(RimGeoMechCase* gmCase); - RimGeoMechCase* geoMechCase(); + RimGeoMechCase* geoMechCase() const; RimCase* ownerCase() const override; caf::PdmChildField cellResult; From 45b53af1be06fcb1cb1e4ef3e0a7c2ed928effc9 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 23 Aug 2019 11:03:18 +0200 Subject: [PATCH 373/396] #4611 Python : Remove reference do deleted module App --- ApplicationCode/GrpcInterface/Python/rips/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/ApplicationCode/GrpcInterface/Python/rips/__init__.py b/ApplicationCode/GrpcInterface/Python/rips/__init__.py index 84a933e156..973283f882 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/__init__.py +++ b/ApplicationCode/GrpcInterface/Python/rips/__init__.py @@ -3,7 +3,6 @@ from .Case import Case from .Grid import Grid from .Properties import Properties from .Instance import Instance -from .App import App from .Commands import Commands from .PdmObject import PdmObject from .View import View From d6c80f52a7680c34d0e56085a941760e9728bc5a Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 23 Aug 2019 11:42:10 +0200 Subject: [PATCH 374/396] Documentation updates --- .../GrpcInterface/Python/doc/source/rips.rst | 40 ++++++------------- .../GrpcInterface/Python/rips/Properties.py | 22 +++++----- .../GrpcInterface/Python/rips/View.py | 35 +++++++++------- 3 files changed, 44 insertions(+), 53 deletions(-) diff --git a/ApplicationCode/GrpcInterface/Python/doc/source/rips.rst b/ApplicationCode/GrpcInterface/Python/doc/source/rips.rst index f20e954542..6e5e14daa5 100644 --- a/ApplicationCode/GrpcInterface/Python/doc/source/rips.rst +++ b/ApplicationCode/GrpcInterface/Python/doc/source/rips.rst @@ -1,40 +1,26 @@ Instance Module -================ +=============== .. autoclass:: rips.Instance :members: Example --------- +------- -.. literalinclude:: ../../rips/examples/InstanceExample.py +.. literalinclude:: ../../rips/PythonExamples/InstanceExample.py :language: python :lines: 5- :emphasize-lines: 3 -App Module -=========== - -.. autoclass:: rips.App - :members: - -Example --------- - -.. literalinclude:: ../../rips/examples/AppInfo.py - :language: python - :lines: 5- - :emphasize-lines: 5 - Case Module -============ +=========== .. autoclass:: rips.Case :members: Example ------- -.. literalinclude:: ../../rips/examples/AllCases.py +.. literalinclude:: ../../rips/PythonExamples/AllCases.py :language: python :lines: 5- :emphasize-lines: 5 @@ -47,8 +33,8 @@ Commands Module :undoc-members: Example --------- -.. literalinclude:: ../../rips/examples/CommandExample.py +------- +.. literalinclude:: ../../rips/PythonExamples/CommandExample.py :language: python :lines: 5- @@ -72,7 +58,7 @@ Example print(dimensions.k) GridCaseGroup Module -=========== +==================== .. autoclass:: rips.GridCaseGroup :members: @@ -91,18 +77,18 @@ Properties Module :members: View Module -================= +=========== .. autoclass:: rips.View :members: - Synchronous Example --------------------- +Synchronous Example +------------------- Read two properties, multiply them together and push the results back to ResInsight in a naïve way, by reading PORO into a list, then reading PERMX into a list, then multiplying them both in a resulting list and finally transferring back the list. This is slow and inefficient, but works. -.. literalinclude:: ../../rips/examples/InputPropTestSync.py +.. literalinclude:: ../../rips/PythonExamples/InputPropTestSync.py :language: python :lines: 5- @@ -112,7 +98,7 @@ Read two properties at the same time chunk by chunk, multiply each chunk togethe This is far more efficient. -.. literalinclude:: ../../rips/examples/InputPropTestAsync.py +.. literalinclude:: ../../rips/PythonExamples/InputPropTestAsync.py :language: python :lines: 5- diff --git a/ApplicationCode/GrpcInterface/Python/rips/Properties.py b/ApplicationCode/GrpcInterface/Python/rips/Properties.py index 8b25d29033..38af187e25 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Properties.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Properties.py @@ -62,18 +62,16 @@ class Properties: """Get a list of available properties Arguments: - propertyType (str): string corresponding to propertyType enum. - - Can be one of the following: - - 'DYNAMIC_NATIVE' - 'STATIC_NATIVE' - 'SOURSIMRL' - 'GENERATED' - 'INPUT_PROPERTY' - 'FORMATION_NAMES' - 'FLOW_DIAGNOSTICS' - 'INJECTION_FLOODING' + propertyType (str): string corresponding to propertyType enum. Can be one of the following: + - DYNAMIC_NATIVE + - STATIC_NATIVE + - SOURSIMRL + - GENERATED + - INPUT_PROPERTY + - FORMATION_NAMES + - FLOW_DIAGNOSTICS + - INJECTION_FLOODING + porosityModel(str): 'MATRIX_MODEL' or 'FRACTURE_MODEL'. """ diff --git a/ApplicationCode/GrpcInterface/Python/rips/View.py b/ApplicationCode/GrpcInterface/Python/rips/View.py index d895e1bf34..91040bb6fa 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/View.py +++ b/ApplicationCode/GrpcInterface/Python/rips/View.py @@ -34,12 +34,18 @@ class View (PdmObject): def applyCellResult(self, resultType, resultVariable): """Apply a regular cell result + Arguments: - resultType [str]: String representing the result category - The valid values are: "DYNAMIC_NATIVE", "STATIC_NATIVE", "SOURSIMRL", - "GENERATED", "INPUT_PROPERTY", "FORMATION_NAMES", - "FLOW_DIAGNOSTICS" and "INJECTION_FLOODING" - resultVariable [str]: String representing the result value. + resultType (str): String representing the result category. The valid values are + - DYNAMIC_NATIVE + - STATIC_NATIVE + - SOURSIMRL + - GENERATED + - INPUT_PROPERTY + - FORMATION_NAMES + - FLOW_DIAGNOSTICS + - INJECTION_FLOODING + resultVariable (str): String representing the result variable. """ cellResult = self.cellResult() cellResult.setValue("ResultType", resultType) @@ -54,17 +60,18 @@ class View (PdmObject): """Apply a flow diagnostics cell result Arguments: - resultVariable [str]: String representing the result value + resultVariable (str): String representing the result value The valid values are 'TOF', 'Fraction', 'MaxFractionTracer' and 'Communication'. - selectionMode [str]: String specifying which tracers to select. - The valid values are FLOW_TR_INJ_AND_PROD (all injector and producer tracers) - FLOW_TR_PRODUCERS (all producers) - FLOW_TR_INJECTORS (all injectors) - FLOW_TR_BY_SELECTION (specify individual tracers in the - injectorTracers and producerTracers variables) - injectorTracers [list]: List of injector names (strings) to select. + selectionMode (str): String specifying which tracers to select. + The valid values are + - FLOW_TR_INJ_AND_PROD (all injector and producer tracers), + - FLOW_TR_PRODUCERS (all producers) + - FLOW_TR_INJECTORS (all injectors), + - FLOW_TR_BY_SELECTION (specify individual tracers in the + injectorTracers and producerTracers variables) + injectorTracers (list): List of injector names (strings) to select. Requires selectionMode to be 'FLOW_TR_BY_SELECTION'. - producerTracers [list]: List of producer tracers (strings) to select. + producerTracers (list): List of producer tracers (strings) to select. Requires selectionMode to be 'FLOW_TR_BY_SELECTION'. """ cellResult = self.cellResult() From d663ea2ae7bf6de38a914e2fde0cdf1d16e444fb Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 23 Aug 2019 11:42:10 +0200 Subject: [PATCH 375/396] Documentation updates --- ApplicationCode/GrpcInterface/Python/doc/source/header.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ApplicationCode/GrpcInterface/Python/doc/source/header.rst b/ApplicationCode/GrpcInterface/Python/doc/source/header.rst index c794ea15d6..aad05260d7 100644 --- a/ApplicationCode/GrpcInterface/Python/doc/source/header.rst +++ b/ApplicationCode/GrpcInterface/Python/doc/source/header.rst @@ -1,7 +1,7 @@ +++ title = "Python API - rips" published = true -weight = 20 +weight = 40 +++ From 529f181689d38ce0f2be4d750e435fd7cd260e1c Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 23 Aug 2019 14:01:01 +0200 Subject: [PATCH 376/396] #4601 Make sure 3D main window is focus window when opening grid --- ApplicationCode/Application/RiaGuiApplication.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/ApplicationCode/Application/RiaGuiApplication.cpp b/ApplicationCode/Application/RiaGuiApplication.cpp index 9fbfad3d6c..88eabb6d4c 100644 --- a/ApplicationCode/Application/RiaGuiApplication.cpp +++ b/ApplicationCode/Application/RiaGuiApplication.cpp @@ -1292,8 +1292,18 @@ void RiaGuiApplication::onFileSuccessfullyLoaded(const QString& fileName, RiaDef if (fileType & RiaDefines::ANY_ECLIPSE_FILE) { getOrCreateAndShowMainPlotWindow(); + + if (fileType != RiaDefines::ECLIPSE_SUMMARY_FILE) + { + if (mainWindow()) + { + mainWindow()->raise(); + } + } + auto plotWindow = getOrCreateMainPlotWindow(); + plotWindow->show(); } - + if (!RiaGuiApplication::hasValidProjectFileExtension(fileName)) { caf::PdmUiModelChangeDetector::instance()->setModelChanged(); From 79518997172641a2f52dab08b3c06f6e0469eee7 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Fri, 23 Aug 2019 14:13:13 +0200 Subject: [PATCH 377/396] #4624 Allow customization of date/time components in labels --- .../Application/Tools/RiaQDateTimeTools.cpp | 25 ++++++ .../Application/Tools/RiaQDateTimeTools.h | 2 + .../Summary/RimSummaryPlot.cpp | 5 +- .../Summary/RimSummaryTimeAxisProperties.cpp | 64 +++++++++++--- .../Summary/RimSummaryTimeAxisProperties.h | 12 ++- .../UserInterface/RiuQwtPlotTools.cpp | 86 +++++++++++-------- .../UserInterface/RiuQwtPlotTools.h | 13 ++- .../UserInterface/RiuSummaryQwtPlot.cpp | 6 +- .../UserInterface/RiuSummaryQwtPlot.h | 7 +- 9 files changed, 165 insertions(+), 55 deletions(-) diff --git a/ApplicationCode/Application/Tools/RiaQDateTimeTools.cpp b/ApplicationCode/Application/Tools/RiaQDateTimeTools.cpp index 23662cdfca..47ee6d9d78 100644 --- a/ApplicationCode/Application/Tools/RiaQDateTimeTools.cpp +++ b/ApplicationCode/Application/Tools/RiaQDateTimeTools.cpp @@ -22,6 +22,7 @@ #include #include +#include "cafAppEnum.h" #include #include @@ -47,6 +48,30 @@ const QString RiaQDateTimeTools::TIMESPAN_HALFYEAR_NAME = "Half Year"; const QString RiaQDateTimeTools::TIMESPAN_YEAR_NAME = "Year"; const QString RiaQDateTimeTools::TIMESPAN_DECADE_NAME = "Decade"; + +namespace caf +{ +template<> +void caf::AppEnum::setUp() +{ + addItem(RiaQDateTimeTools::DATE_FORMAT_NONE, "NO_DATE", "No Date"); + addItem(RiaQDateTimeTools::DATE_FORMAT_YEAR, "YEAR", "Year Only"); + addItem(RiaQDateTimeTools::DATE_FORMAT_YEAR_MONTH, "YEAR_MONTH", "Year and Month"); + addItem(RiaQDateTimeTools::DATE_FORMAT_YEAR_MONTH_DAY, "YEAR_MONTH_DAY", "Year, Month and Day"); + setDefault(RiaQDateTimeTools::DATE_FORMAT_YEAR_MONTH_DAY); +} + +template<> +void caf::AppEnum::setUp() +{ + addItem(RiaQDateTimeTools::TIME_FORMAT_NONE, "NO_TIME", "No Time of Day"); + addItem(RiaQDateTimeTools::TIME_FORMAT_HOUR, "HOUR", "Hour Only"); + addItem(RiaQDateTimeTools::TIME_FORMAT_HOUR_MINUTE, "HOUR_MINUTE", "Hour and Minute"); + addItem(RiaQDateTimeTools::TIME_FORMAT_HOUR_MINUTE_SECOND, "HOUR_MINUTE_SECONDS", "Hour, Minutes and Seconds"); + setDefault(RiaQDateTimeTools::TIME_FORMAT_NONE); +} +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/Application/Tools/RiaQDateTimeTools.h b/ApplicationCode/Application/Tools/RiaQDateTimeTools.h index eab75707ea..fc3a30bbc2 100644 --- a/ApplicationCode/Application/Tools/RiaQDateTimeTools.h +++ b/ApplicationCode/Application/Tools/RiaQDateTimeTools.h @@ -66,6 +66,7 @@ class RiaQDateTimeTools public: enum DateFormatComponents { + DATE_FORMAT_UNSPECIFIED = -2, DATE_FORMAT_NONE = -1, DATE_FORMAT_YEAR = 0, DATE_FORMAT_YEAR_MONTH, @@ -75,6 +76,7 @@ public: enum TimeFormatComponents { + TIME_FORMAT_UNSPECIFIED = -2, TIME_FORMAT_NONE = -1, TIME_FORMAT_HOUR, TIME_FORMAT_HOUR_MINUTE, diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlot.cpp b/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlot.cpp index 8b791a5c58..092e4a60ad 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlot.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlot.cpp @@ -926,10 +926,13 @@ void RimSummaryPlot::updateTimeAxis() if (m_timeAxisProperties->timeMode() == RimSummaryTimeAxisProperties::DATE) { + RiaQDateTimeTools::DateFormatComponents dateComponents = m_timeAxisProperties->dateComponents(); + RiaQDateTimeTools::TimeFormatComponents timeComponents = m_timeAxisProperties->timeComponents(); + QString dateFormat = m_timeAxisProperties->dateFormat(); QString timeFormat = m_timeAxisProperties->timeFormat(); - m_qwtPlot->useDateBasedTimeAxis(dateFormat, timeFormat); + m_qwtPlot->useDateBasedTimeAxis(dateFormat, timeFormat, dateComponents, timeComponents); } else { diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryTimeAxisProperties.cpp b/ApplicationCode/ProjectDataModel/Summary/RimSummaryTimeAxisProperties.cpp index 49ba10be3d..cf7fdf2982 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryTimeAxisProperties.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryTimeAxisProperties.cpp @@ -49,6 +49,7 @@ void caf::AppEnum::setUp() addItem(RimSummaryTimeAxisProperties::MINUTES, "MINUTES", "Minutes"); addItem(RimSummaryTimeAxisProperties::HOURS, "HOURS", "Hours"); addItem(RimSummaryTimeAxisProperties::DAYS, "DAYS ", "Days"); + addItem(RimSummaryTimeAxisProperties::MONTHS, "MONTHS", "Months"); addItem(RimSummaryTimeAxisProperties::YEARS, "YEARS", "Years"); setDefault(RimSummaryTimeAxisProperties::YEARS); @@ -68,8 +69,8 @@ RimSummaryTimeAxisProperties::RimSummaryTimeAxisProperties() CAF_PDM_InitField(&m_isActive, "Active", true, "Active", "", "", ""); m_isActive.uiCapability()->setUiHidden(true); - CAF_PDM_InitField(&showTitle, "ShowTitle", false, "Show Title", "", "", ""); - CAF_PDM_InitField(&title, "Title", QString("Time"), "Title", "", "", ""); + CAF_PDM_InitField(&showTitle, "ShowTitle", false, "Show Title ", "", "", ""); + CAF_PDM_InitField(&title, "Title", QString("Time"), "Title ", "", "", ""); CAF_PDM_InitField(&m_isAutoZoom, "AutoZoom", true, "Set Range Automatically", "", "", ""); CAF_PDM_InitFieldNoDefault(&m_timeMode, "TimeMode", "Time Mode", "", "", ""); @@ -99,12 +100,16 @@ RimSummaryTimeAxisProperties::RimSummaryTimeAxisProperties() m_titleFontSize = RiaFontCache::pointSizeFromFontSizeEnum(RiaApplication::instance()->preferences()->defaultPlotFontSize()); CAF_PDM_InitField(&m_valuesFontSize, "ValuesFontSize", 10, "Font Size", "", "", ""); m_valuesFontSize = RiaFontCache::pointSizeFromFontSizeEnum(RiaApplication::instance()->preferences()->defaultPlotFontSize()); + + CAF_PDM_InitField(&m_automaticDateComponents, "AutoDate", true, "Automatic Date/Time Labels", "", "", ""); + CAF_PDM_InitFieldNoDefault(&m_dateComponents, "DateComponents", "Set Date Label", "", "", ""); + CAF_PDM_InitFieldNoDefault(&m_timeComponents, "TimeComponents", "Set Time Label", "", "", ""); - CAF_PDM_InitFieldNoDefault(&m_dateFormat, "DateFormat", "Date Format", "", "", ""); + CAF_PDM_InitFieldNoDefault(&m_dateFormat, "DateFormat", "Date Label Format", "", "", ""); m_dateFormat.uiCapability()->setUiEditorTypeName(caf::PdmUiComboBoxEditor::uiEditorTypeName()); m_dateFormat = RiaApplication::instance()->preferences()->dateFormat(); - CAF_PDM_InitFieldNoDefault(&m_timeFormat, "TimeFormat", "Time Format", "", "", ""); + CAF_PDM_InitFieldNoDefault(&m_timeFormat, "TimeFormat", "Time Label Format", "", "", ""); m_timeFormat.uiCapability()->setUiEditorTypeName(caf::PdmUiComboBoxEditor::uiEditorTypeName()); m_timeFormat = RiaApplication::instance()->preferences()->timeFormat(); @@ -361,7 +366,7 @@ QList RimSummaryTimeAxisProperties::calculateValueOption { QDate exampleDate = QDate(2019, 8, 16); QString fullDateFormat = - RiaQDateTimeTools::dateFormatString(dateFormat, RiaQDateTimeTools::DATE_FORMAT_YEAR_MONTH_DAY); + RiaQDateTimeTools::dateFormatString(dateFormat, dateComponents(RiaQDateTimeTools::DATE_FORMAT_YEAR_MONTH_DAY)); QString uiText = QString("%1 (%2)").arg(fullDateFormat).arg(exampleDate.toString(fullDateFormat)); uiText.replace("AP", "AM/PM"); options.push_back(caf::PdmOptionItemInfo(uiText, QVariant::fromValue(dateFormat))); @@ -373,7 +378,7 @@ QList RimSummaryTimeAxisProperties::calculateValueOption { QTime exampleTime = QTime(15, 48, 22); QString timeFormatString = - RiaQDateTimeTools::timeFormatString(timeFormat, RiaQDateTimeTools::TIME_FORMAT_HOUR_MINUTE_SECOND); + RiaQDateTimeTools::timeFormatString(timeFormat, timeComponents(RiaQDateTimeTools::TIME_FORMAT_HOUR_MINUTE_SECOND)); QString uiText = QString("%1 (%2)").arg(timeFormatString).arg(exampleTime.toString(timeFormatString)); uiText.replace("AP", "AM/PM"); options.push_back(caf::PdmOptionItemInfo(uiText, QVariant::fromValue(timeFormat))); @@ -466,6 +471,22 @@ double RimSummaryTimeAxisProperties::fromDaysToDisplayUnitScale() return scale; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiaQDateTimeTools::DateFormatComponents RimSummaryTimeAxisProperties::dateComponents(RiaQDateTimeTools::DateFormatComponents fallback) const +{ + return m_automaticDateComponents() ? fallback : m_dateComponents(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiaQDateTimeTools::TimeFormatComponents RimSummaryTimeAxisProperties::timeComponents(RiaQDateTimeTools::TimeFormatComponents fallback) const +{ + return m_automaticDateComponents() ? fallback : m_timeComponents(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -489,9 +510,13 @@ void RimSummaryTimeAxisProperties::defineUiOrdering(QString uiConfigName, caf::P { caf::PdmUiGroup& titleGroup = *(uiOrdering.addNewGroup("Axis Title")); titleGroup.add(&showTitle); - titleGroup.add(&title); - titleGroup.add(&m_titlePositionEnum); - titleGroup.add(&m_titleFontSize); + titleGroup.add(&title); + title.uiCapability()->setUiReadOnly(!showTitle()); + if (showTitle()) + { + titleGroup.add(&m_titlePositionEnum); + titleGroup.add(&m_titleFontSize); + } caf::PdmUiGroup* timeGroup = uiOrdering.addNewGroup("Time Values"); timeGroup->add(&m_timeMode); @@ -501,8 +526,12 @@ void RimSummaryTimeAxisProperties::defineUiOrdering(QString uiConfigName, caf::P timeGroup->add(&m_visibleTimeRangeMax, false); timeGroup->add(&m_visibleDateRangeMin, true); timeGroup->add(&m_visibleTimeRangeMin, false); - timeGroup->add(&m_dateFormat); - timeGroup->add(&m_timeFormat); + timeGroup->add(&m_automaticDateComponents); + if (!m_automaticDateComponents()) + { + timeGroup->add(&m_dateComponents); + timeGroup->add(&m_timeComponents); + } } else { @@ -511,6 +540,19 @@ void RimSummaryTimeAxisProperties::defineUiOrdering(QString uiConfigName, caf::P timeGroup->add(&m_visibleTimeSinceStartRangeMin); } timeGroup->add(&m_valuesFontSize); + if (m_timeMode() == DATE) + { + caf::PdmUiGroup* advancedGroup = timeGroup->addNewGroup("Date/Time Label Format"); + advancedGroup->setCollapsedByDefault(true); + if (m_automaticDateComponents() || m_dateComponents() != RiaQDateTimeTools::DATE_FORMAT_NONE) + { + advancedGroup->add(&m_dateFormat); + } + if (m_automaticDateComponents() || m_timeComponents() != RiaQDateTimeTools::TIME_FORMAT_NONE) + { + advancedGroup->add(&m_timeFormat); + } + } uiOrdering.skipRemainingFields(true); } diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryTimeAxisProperties.h b/ApplicationCode/ProjectDataModel/Summary/RimSummaryTimeAxisProperties.h index 09d286cfe0..f98a18feb3 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryTimeAxisProperties.h +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryTimeAxisProperties.h @@ -50,10 +50,14 @@ public: SECONDS, MINUTES, HOURS, - DAYS, + DAYS, + MONTHS, YEARS }; + typedef caf::AppEnum DateFormatEnum; + typedef caf::AppEnum TimeFormatEnum; + public: RimSummaryTimeAxisProperties(); @@ -71,6 +75,9 @@ public: double fromTimeTToDisplayUnitScale(); double fromDaysToDisplayUnitScale(); + RiaQDateTimeTools::DateFormatComponents dateComponents(RiaQDateTimeTools::DateFormatComponents fallback = RiaQDateTimeTools::DATE_FORMAT_UNSPECIFIED) const; + RiaQDateTimeTools::TimeFormatComponents timeComponents(RiaQDateTimeTools::TimeFormatComponents fallback = RiaQDateTimeTools::TIME_FORMAT_UNSPECIFIED) const; + const QString& dateFormat() const; const QString& timeFormat() const; @@ -125,6 +132,9 @@ private: caf::PdmField m_titleFontSize; caf::PdmField> m_titlePositionEnum; caf::PdmField m_valuesFontSize; + caf::PdmField m_automaticDateComponents; + caf::PdmField m_dateComponents; + caf::PdmField m_timeComponents; caf::PdmField m_dateFormat; caf::PdmField m_timeFormat; diff --git a/ApplicationCode/UserInterface/RiuQwtPlotTools.cpp b/ApplicationCode/UserInterface/RiuQwtPlotTools.cpp index ed32ed0003..9032f8dbf9 100644 --- a/ApplicationCode/UserInterface/RiuQwtPlotTools.cpp +++ b/ApplicationCode/UserInterface/RiuQwtPlotTools.cpp @@ -114,7 +114,9 @@ void RiuQwtPlotTools::setDefaultAxes(QwtPlot* plot) //-------------------------------------------------------------------------------------------------- void RiuQwtPlotTools::enableDateBasedBottomXAxis(QwtPlot* plot, const QString& dateFormat, - const QString& timeFormat) + const QString& timeFormat, + RiaQDateTimeTools::DateFormatComponents dateComponents, + RiaQDateTimeTools::TimeFormatComponents timeComponents) { QwtDateScaleDraw* scaleDraw = new QwtDateScaleDraw(Qt::UTC); @@ -129,7 +131,7 @@ void RiuQwtPlotTools::enableDateBasedBottomXAxis(QwtPlot* plot, for (QwtDate::IntervalType interval : intervals) { - scaleDraw->setDateFormat(interval, dateTimeFormatForInterval(interval, dateFormat, timeFormat)); + scaleDraw->setDateFormat(interval, dateTimeFormatForInterval(interval, dateFormat, timeFormat, dateComponents, timeComponents)); } QwtDateScaleEngine* scaleEngine = new QwtDateScaleEngine(Qt::UTC); @@ -142,39 +144,51 @@ void RiuQwtPlotTools::enableDateBasedBottomXAxis(QwtPlot* plot, //-------------------------------------------------------------------------------------------------- QString RiuQwtPlotTools::dateTimeFormatForInterval(QwtDate::IntervalType interval, const QString& dateFormat, - const QString& timeFormat) + const QString& timeFormat, + RiaQDateTimeTools::DateFormatComponents dateComponents, + RiaQDateTimeTools::TimeFormatComponents timeComponents) { - switch (interval) - { - case QwtDate::Millisecond: - return RiaQDateTimeTools::timeFormatString(timeFormat, RiaQDateTimeTools::TIME_FORMAT_HOUR_MINUTE_SECOND_MILLISECOND); - case QwtDate::Second: - return RiaQDateTimeTools::timeFormatString(timeFormat, RiaQDateTimeTools::TIME_FORMAT_HOUR_MINUTE_SECOND); - case QwtDate::Minute: { - QString fullFormat = RiaQDateTimeTools::timeFormatString(timeFormat, RiaQDateTimeTools::TIME_FORMAT_HOUR_MINUTE); - fullFormat += "\n"; - fullFormat += RiaQDateTimeTools::dateFormatString(dateFormat, RiaQDateTimeTools::DATE_FORMAT_YEAR_MONTH_DAY); - return fullFormat; - } - case QwtDate::Hour: { - QString fullFormat = RiaQDateTimeTools::timeFormatString(timeFormat, RiaQDateTimeTools::TIME_FORMAT_HOUR); - if (!fullFormat.endsWith("AP")) - { - fullFormat += ":00"; - } - fullFormat += "\n"; - fullFormat += RiaQDateTimeTools::dateFormatString(dateFormat, RiaQDateTimeTools::DATE_FORMAT_YEAR_MONTH_DAY); - return fullFormat; - } - case QwtDate::Day: - return RiaQDateTimeTools::dateFormatString(dateFormat, RiaQDateTimeTools::DATE_FORMAT_YEAR_MONTH_DAY); - case QwtDate::Week: - return RiaQDateTimeTools::dateFormatString(dateFormat, RiaQDateTimeTools::DATE_FORMAT_YEAR_MONTH); - case QwtDate::Month: - return RiaQDateTimeTools::dateFormatString(dateFormat, RiaQDateTimeTools::DATE_FORMAT_YEAR_MONTH); - case QwtDate::Year: - return RiaQDateTimeTools::dateFormatString(dateFormat, RiaQDateTimeTools::DATE_FORMAT_YEAR); - default: - return RiaQDateTimeTools::dateFormatString(dateFormat, RiaQDateTimeTools::DATE_FORMAT_YEAR_MONTH_DAY); - } + if (dateComponents != RiaQDateTimeTools::DATE_FORMAT_UNSPECIFIED && timeComponents != RiaQDateTimeTools::TIME_FORMAT_UNSPECIFIED) + { + return RiaQDateTimeTools::dateFormatString(dateFormat, dateComponents) + "\n" + + RiaQDateTimeTools::timeFormatString(timeFormat, timeComponents); + } + else + { + switch (interval) + { + case QwtDate::Millisecond: + return RiaQDateTimeTools::timeFormatString(timeFormat, RiaQDateTimeTools::TIME_FORMAT_HOUR_MINUTE_SECOND_MILLISECOND); + case QwtDate::Second: + return RiaQDateTimeTools::timeFormatString(timeFormat, RiaQDateTimeTools::TIME_FORMAT_HOUR_MINUTE_SECOND); + case QwtDate::Minute: + { + QString fullFormat = RiaQDateTimeTools::timeFormatString(timeFormat, RiaQDateTimeTools::TIME_FORMAT_HOUR_MINUTE); + fullFormat += "\n"; + fullFormat += RiaQDateTimeTools::dateFormatString(dateFormat, RiaQDateTimeTools::DATE_FORMAT_YEAR_MONTH_DAY); + return fullFormat; + } + case QwtDate::Hour: + { + QString fullFormat = RiaQDateTimeTools::timeFormatString(timeFormat, RiaQDateTimeTools::TIME_FORMAT_HOUR); + if (!fullFormat.endsWith("AP")) + { + fullFormat += ":00"; + } + fullFormat += "\n"; + fullFormat += RiaQDateTimeTools::dateFormatString(dateFormat, RiaQDateTimeTools::DATE_FORMAT_YEAR_MONTH_DAY); + return fullFormat; + } + case QwtDate::Day: + return RiaQDateTimeTools::dateFormatString(dateFormat, RiaQDateTimeTools::DATE_FORMAT_YEAR_MONTH_DAY); + case QwtDate::Week: + return RiaQDateTimeTools::dateFormatString(dateFormat, RiaQDateTimeTools::DATE_FORMAT_YEAR_MONTH); + case QwtDate::Month: + return RiaQDateTimeTools::dateFormatString(dateFormat, RiaQDateTimeTools::DATE_FORMAT_YEAR_MONTH); + case QwtDate::Year: + return RiaQDateTimeTools::dateFormatString(dateFormat, RiaQDateTimeTools::DATE_FORMAT_YEAR); + default: + return RiaQDateTimeTools::dateFormatString(dateFormat, RiaQDateTimeTools::DATE_FORMAT_YEAR_MONTH_DAY); + } + } } diff --git a/ApplicationCode/UserInterface/RiuQwtPlotTools.h b/ApplicationCode/UserInterface/RiuQwtPlotTools.h index cb53693405..8e3fbdd30d 100644 --- a/ApplicationCode/UserInterface/RiuQwtPlotTools.h +++ b/ApplicationCode/UserInterface/RiuQwtPlotTools.h @@ -27,8 +27,15 @@ class RiuQwtPlotTools public: static void setCommonPlotBehaviour(QwtPlot* plot); static void setDefaultAxes(QwtPlot* plot); - static void enableDateBasedBottomXAxis(QwtPlot* plot, const QString& dateFormat, const QString& timeFormat); + static void enableDateBasedBottomXAxis(QwtPlot* plot, + const QString& dateFormat, + const QString& timeFormat, + RiaQDateTimeTools::DateFormatComponents dateComponents = RiaQDateTimeTools::DATE_FORMAT_UNSPECIFIED, + RiaQDateTimeTools::TimeFormatComponents timeComponents = RiaQDateTimeTools::TIME_FORMAT_UNSPECIFIED); - static QString - dateTimeFormatForInterval(QwtDate::IntervalType interval, const QString& dateFormat, const QString& timeFormat); + static QString dateTimeFormatForInterval(QwtDate::IntervalType interval, + const QString& dateFormat, + const QString& timeFormat, + RiaQDateTimeTools::DateFormatComponents dateComponents, + RiaQDateTimeTools::TimeFormatComponents timeComponents); }; diff --git a/ApplicationCode/UserInterface/RiuSummaryQwtPlot.cpp b/ApplicationCode/UserInterface/RiuSummaryQwtPlot.cpp index 022e81c7bf..edeb0f96fd 100644 --- a/ApplicationCode/UserInterface/RiuSummaryQwtPlot.cpp +++ b/ApplicationCode/UserInterface/RiuSummaryQwtPlot.cpp @@ -102,9 +102,11 @@ RiuSummaryQwtPlot::RiuSummaryQwtPlot(RimViewWindow* viewWindow, QWidget* parent /// //-------------------------------------------------------------------------------------------------- void RiuSummaryQwtPlot::useDateBasedTimeAxis(const QString& dateFormat, - const QString& timeFormat) + const QString& timeFormat, + RiaQDateTimeTools::DateFormatComponents dateComponents, + RiaQDateTimeTools::TimeFormatComponents timeComponents) { - RiuQwtPlotTools::enableDateBasedBottomXAxis(this, dateFormat, timeFormat); + RiuQwtPlotTools::enableDateBasedBottomXAxis(this, dateFormat, timeFormat, dateComponents, timeComponents); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/UserInterface/RiuSummaryQwtPlot.h b/ApplicationCode/UserInterface/RiuSummaryQwtPlot.h index fd5b084646..90012c67da 100644 --- a/ApplicationCode/UserInterface/RiuSummaryQwtPlot.h +++ b/ApplicationCode/UserInterface/RiuSummaryQwtPlot.h @@ -41,7 +41,12 @@ class RiuSummaryQwtPlot : public RiuQwtPlot public: RiuSummaryQwtPlot(RimViewWindow* ownerViewWindow, QWidget* parent = nullptr); - void useDateBasedTimeAxis(const QString& dateFormat, const QString& timeFormat); + void + useDateBasedTimeAxis(const QString& dateFormat, + const QString& timeFormat, + RiaQDateTimeTools::DateFormatComponents dateComponents = RiaQDateTimeTools::DATE_FORMAT_UNSPECIFIED, + RiaQDateTimeTools::TimeFormatComponents timeComponents = RiaQDateTimeTools::TIME_FORMAT_UNSPECIFIED); + void useTimeBasedTimeAxis(); void addOrUpdateEnsembleCurveSetLegend(RimEnsembleCurveSet* curveSetToShowLegendFor); From 72a954e9f76110ee37e369fb47b912d688434d70 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Fri, 23 Aug 2019 15:25:26 +0200 Subject: [PATCH 378/396] Python: Stop copying Python files to build folder. --- ApplicationCode/CMakeLists.txt | 2 +- ApplicationCode/GrpcInterface/CMakeLists.cmake | 7 +------ ApplicationCode/GrpcInterface/Python/.gitignore | 3 +++ 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/ApplicationCode/CMakeLists.txt b/ApplicationCode/CMakeLists.txt index 5a8704384b..01761782ed 100644 --- a/ApplicationCode/CMakeLists.txt +++ b/ApplicationCode/CMakeLists.txt @@ -713,7 +713,7 @@ if (RESINSIGHT_PRIVATE_INSTALL) add_custom_command( TARGET ResInsight POST_BUILD - COMMAND ${RESINSIGHT_GRPC_PYTHON_EXECUTABLE} -m pip install --target=${CMAKE_BINARY_DIR}/Python grpcio + COMMAND ${RESINSIGHT_GRPC_PYTHON_EXECUTABLE} -m pip install --target=${GRPC_PYTHON_SOURCE_PATH} grpcio ) endif() install(DIRECTORY ${GRPC_PYTHON_SOURCE_PATH}/ DESTINATION ${RESINSIGHT_INSTALL_FOLDER}/Python) diff --git a/ApplicationCode/GrpcInterface/CMakeLists.cmake b/ApplicationCode/GrpcInterface/CMakeLists.cmake index 4bd57c097b..6271a0ad20 100644 --- a/ApplicationCode/GrpcInterface/CMakeLists.cmake +++ b/ApplicationCode/GrpcInterface/CMakeLists.cmake @@ -202,12 +202,7 @@ if (RESINSIGHT_GRPC_PYTHON_EXECUTABLE) "README.md" "LICENSE" ) - - foreach(PYTHON_SCRIPT ${GRPC_PYTHON_SOURCES}) - # Copy into build folder so the python code is present for debugging - configure_file("${GRPC_PYTHON_SOURCE_PATH}/${PYTHON_SCRIPT}" "${CMAKE_BINARY_DIR}/Python/${PYTHON_SCRIPT}" COPYONLY) - endforeach() - + list(APPEND GRPC_PYTHON_SOURCES ${GRPC_PYTHON_GENERATED_SOURCES}) foreach(PYTHON_SCRIPT ${GRPC_PYTHON_SOURCES}) diff --git a/ApplicationCode/GrpcInterface/Python/.gitignore b/ApplicationCode/GrpcInterface/Python/.gitignore index b95f862edb..d740b896f4 100644 --- a/ApplicationCode/GrpcInterface/Python/.gitignore +++ b/ApplicationCode/GrpcInterface/Python/.gitignore @@ -5,3 +5,6 @@ dist build rips.egg-info setup.py +grpc +grpcio* +six* \ No newline at end of file From f279aeced70cc1a5e60325efdeba04e161d41441 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Fri, 23 Aug 2019 15:26:31 +0200 Subject: [PATCH 379/396] #4610 Enable command line options and port number in rips.Instance.launch() --- .../GrpcInterface/Python/rips/Instance.py | 18 ++++++++++++++++-- .../LaunchWithCommandLineOptions.py | 11 +++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 ApplicationCode/GrpcInterface/Python/rips/PythonExamples/LaunchWithCommandLineOptions.py diff --git a/ApplicationCode/GrpcInterface/Python/rips/Instance.py b/ApplicationCode/GrpcInterface/Python/rips/Instance.py index d5b55b3ecd..818fcd2039 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/Instance.py +++ b/ApplicationCode/GrpcInterface/Python/rips/Instance.py @@ -33,7 +33,7 @@ class Instance: return s.connect_ex(('localhost', port)) == 0 @staticmethod - def launch(resInsightExecutable = '', console = False): + def launch(resInsightExecutable = '', console = False, launchPort = -1, commandLineParameters=[]): """ Launch a new Instance of ResInsight. This requires the environment variable RESINSIGHT_EXECUTABLE to be set or the parameter resInsightExecutable to be provided. The RESINSIGHT_GRPC_PORT environment variable can be set to an alternative port number. @@ -43,6 +43,9 @@ class Instance: will take precedence over what is provided in the RESINSIGHT_EXECUTABLE environment variable. console (bool): If True, launch as console application, without GUI. + launchPort(int): If -1 will use the default port of 50051 or look for RESINSIGHT_GRPC_PORT + if anything else, ResInsight will try to launch with this port + commandLineParameters(list): Additional command line parameters as string entries in the list. Returns: Instance: an instance object if it worked. None if not. """ @@ -51,6 +54,8 @@ class Instance: portEnv = os.environ.get('RESINSIGHT_GRPC_PORT') if portEnv: port = int(portEnv) + if launchPort is not -1: + port = launchPort if not resInsightExecutable: resInsightExecutable = os.environ.get('RESINSIGHT_EXECUTABLE') @@ -64,10 +69,19 @@ class Instance: print('Port ' + str(port)) print('Trying to launch', resInsightExecutable) - parameters = ["ResInsight", "--server", str(port)] + + if isinstance(commandLineParameters, str): + commandLineParameters = [str] + + parameters = ["ResInsight", "--server", str(port)] + commandLineParameters if console: print("Launching as console app") parameters.append("--console") + + # Stringify all parameters + for i in range(0, len(parameters)): + parameters[i] = str(parameters[i]) + pid = os.spawnv(os.P_NOWAIT, resInsightExecutable, parameters) if pid: instance = Instance(port=port, launched=True) diff --git a/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/LaunchWithCommandLineOptions.py b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/LaunchWithCommandLineOptions.py new file mode 100644 index 0000000000..ae6975408e --- /dev/null +++ b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/LaunchWithCommandLineOptions.py @@ -0,0 +1,11 @@ +# Load ResInsight Processing Server Client Library +import rips +# Launch ResInsight with last project file and a Window size of 600x1000 pixels +resInsight = rips.Instance.launch(commandLineParameters=['--last', '--size', 600, 1000]) +# Get a list of all cases +cases = resInsight.project.cases() + +print ("Got " + str(len(cases)) + " cases: ") +for case in cases: + print("Case name: " + case.name) + print("Case grid path: " + case.gridPath()) From 94a967cea4dc8c9966034a9f93e9976b082950f0 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 23 Aug 2019 16:23:07 +0200 Subject: [PATCH 380/396] #4624 Customization of date format: Make sure time is reported above date --- ApplicationCode/UserInterface/RiuQwtPlotTools.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ApplicationCode/UserInterface/RiuQwtPlotTools.cpp b/ApplicationCode/UserInterface/RiuQwtPlotTools.cpp index 9032f8dbf9..f879fdace3 100644 --- a/ApplicationCode/UserInterface/RiuQwtPlotTools.cpp +++ b/ApplicationCode/UserInterface/RiuQwtPlotTools.cpp @@ -150,9 +150,9 @@ QString RiuQwtPlotTools::dateTimeFormatForInterval(QwtDate::IntervalType interva { if (dateComponents != RiaQDateTimeTools::DATE_FORMAT_UNSPECIFIED && timeComponents != RiaQDateTimeTools::TIME_FORMAT_UNSPECIFIED) { - return RiaQDateTimeTools::dateFormatString(dateFormat, dateComponents) + "\n" + - RiaQDateTimeTools::timeFormatString(timeFormat, timeComponents); - } + return RiaQDateTimeTools::timeFormatString(timeFormat, timeComponents) + "\n" + + RiaQDateTimeTools::dateFormatString(dateFormat, dateComponents); + } else { switch (interval) From cae2d13aeb9d570eb9e0236de8739d9e2fb6a98a Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 23 Aug 2019 16:41:53 +0200 Subject: [PATCH 381/396] Fix implicit type conversion issues --- .../Summary/RimSummaryTimeAxisProperties.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryTimeAxisProperties.cpp b/ApplicationCode/ProjectDataModel/Summary/RimSummaryTimeAxisProperties.cpp index cf7fdf2982..09e21a0715 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryTimeAxisProperties.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryTimeAxisProperties.cpp @@ -476,7 +476,11 @@ double RimSummaryTimeAxisProperties::fromDaysToDisplayUnitScale() //-------------------------------------------------------------------------------------------------- RiaQDateTimeTools::DateFormatComponents RimSummaryTimeAxisProperties::dateComponents(RiaQDateTimeTools::DateFormatComponents fallback) const { - return m_automaticDateComponents() ? fallback : m_dateComponents(); + if (m_automaticDateComponents()) return fallback; + + RiaQDateTimeTools::DateFormatComponents components = m_dateComponents(); + + return components; } //-------------------------------------------------------------------------------------------------- @@ -484,7 +488,11 @@ RiaQDateTimeTools::DateFormatComponents RimSummaryTimeAxisProperties::dateCompon //-------------------------------------------------------------------------------------------------- RiaQDateTimeTools::TimeFormatComponents RimSummaryTimeAxisProperties::timeComponents(RiaQDateTimeTools::TimeFormatComponents fallback) const { - return m_automaticDateComponents() ? fallback : m_timeComponents(); + if (m_automaticDateComponents()) return fallback; + + RiaQDateTimeTools::TimeFormatComponents components = m_timeComponents(); + + return components; } //-------------------------------------------------------------------------------------------------- From afc2b21708b3433e5d5c42e05ed06bffbd4dd8c6 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 26 Aug 2019 09:56:17 +0200 Subject: [PATCH 382/396] Add more data format variants --- ApplicationCode/Application/Tools/RiaQDateTimeTools.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ApplicationCode/Application/Tools/RiaQDateTimeTools.cpp b/ApplicationCode/Application/Tools/RiaQDateTimeTools.cpp index 47ee6d9d78..3998316ed7 100644 --- a/ApplicationCode/Application/Tools/RiaQDateTimeTools.cpp +++ b/ApplicationCode/Application/Tools/RiaQDateTimeTools.cpp @@ -438,7 +438,9 @@ std::vector RiaQDateTimeTools::supportedDateFormats() dateFormats.push_back("yy;M/yy;d/M/yy"); dateFormats.push_back("yy;M/yy;M/d/yy"); dateFormats.push_back("yyyy;MM-yyyy;dd-MM-yyyy"); + dateFormats.push_back("yyyy;MM.yyyy;dd.MM.yyyy"); dateFormats.push_back("yyyy;MM-yyyy;MM-dd-yyyy"); + dateFormats.push_back("yyyy;MM.yyyy;MM.dd.yyyy"); dateFormats.push_back("yy;MM-yy;dd-MM-yy"); dateFormats.push_back("yy;MM-yy;MM-dd-yy"); From e7f90c0ecfa79748e90a57e7d736b04dbc28d622 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Mon, 26 Aug 2019 09:57:50 +0200 Subject: [PATCH 383/396] Clang-format --- .../CommandFileInterface/RicfCloneView.cpp | 49 +++++++------ .../CommandFileInterface/RicfCreateView.cpp | 70 +++++++++---------- .../ProjectDataModel/RimEclipseCase.cpp | 2 +- .../ProjectDataModel/RimGeoMechCase.cpp | 7 +- 4 files changed, 63 insertions(+), 65 deletions(-) diff --git a/ApplicationCode/CommandFileInterface/RicfCloneView.cpp b/ApplicationCode/CommandFileInterface/RicfCloneView.cpp index ed78b7b359..ddc039ac9b 100644 --- a/ApplicationCode/CommandFileInterface/RicfCloneView.cpp +++ b/ApplicationCode/CommandFileInterface/RicfCloneView.cpp @@ -33,45 +33,44 @@ RicfCloneView::RicfCloneView() //-------------------------------------------------------------------------------------------------- RicfCommandResponse RicfCloneView::execute() { - RimProject* project = RiaApplication::instance()->project(); - std::vector allViews; - project->descendantsIncludingThisOfType(allViews); + RimProject* project = RiaApplication::instance()->project(); + std::vector allViews; + project->descendantsIncludingThisOfType(allViews); for (Rim3dView* view : allViews) { - if (view->id() == m_viewId()) - { - const RimEclipseView* eclipseView = dynamic_cast(view); - const RimGeoMechView* geoMechView = dynamic_cast(view); + if (view->id() == m_viewId()) + { + const RimEclipseView* eclipseView = dynamic_cast(view); + const RimGeoMechView* geoMechView = dynamic_cast(view); - int newViewId = -1; - if (eclipseView) - { - RimEclipseCase* eclipseCase = eclipseView->eclipseCase(); - RimEclipseView* newEclipseView = eclipseCase->createCopyAndAddView(eclipseView); - newViewId = newEclipseView->id(); + int newViewId = -1; + if (eclipseView) + { + RimEclipseCase* eclipseCase = eclipseView->eclipseCase(); + RimEclipseView* newEclipseView = eclipseCase->createCopyAndAddView(eclipseView); + newViewId = newEclipseView->id(); newEclipseView->loadDataAndUpdate(); eclipseCase->updateConnectedEditors(); Riu3DMainWindowTools::setExpanded(newEclipseView); - } - else if (geoMechView) - { - RimGeoMechCase* geoMechCase = geoMechView->geoMechCase(); - RimGeoMechView* newGeoMechView = geoMechCase->createCopyAndAddView(geoMechView); - newViewId = newGeoMechView->id(); + } + else if (geoMechView) + { + RimGeoMechCase* geoMechCase = geoMechView->geoMechCase(); + RimGeoMechView* newGeoMechView = geoMechCase->createCopyAndAddView(geoMechView); + newViewId = newGeoMechView->id(); view->loadDataAndUpdate(); geoMechCase->updateConnectedEditors(); Riu3DMainWindowTools::setExpanded(view); - } + } - if (newViewId) - { + if (newViewId) + { RicfCommandResponse response; response.setResult(new RicfCreateViewResult(newViewId)); return response; - - } - } + } + } } QString error = QString("cloneView: Could not clone view with id %1").arg(m_viewId()); diff --git a/ApplicationCode/CommandFileInterface/RicfCreateView.cpp b/ApplicationCode/CommandFileInterface/RicfCreateView.cpp index 51ed5117e7..c393519975 100644 --- a/ApplicationCode/CommandFileInterface/RicfCreateView.cpp +++ b/ApplicationCode/CommandFileInterface/RicfCreateView.cpp @@ -42,44 +42,44 @@ RicfCreateView::RicfCreateView() //-------------------------------------------------------------------------------------------------- RicfCommandResponse RicfCreateView::execute() { - RimProject* project = RiaApplication::instance()->project(); - std::vector allCases; - project->allCases(allCases); + RimProject* project = RiaApplication::instance()->project(); + std::vector allCases; + project->allCases(allCases); - for (RimCase* rimCase : allCases) - { - if (rimCase->caseId == m_caseId()) - { - int viewId = -1; - RimEclipseCase* eclipseCase = dynamic_cast(rimCase); - RimGeoMechCase* geoMechCase = dynamic_cast(rimCase); - if (eclipseCase) - { - RimEclipseView* view = eclipseCase->createAndAddReservoirView(); - viewId = view->id(); - view->loadDataAndUpdate(); - eclipseCase->updateConnectedEditors(); - Riu3DMainWindowTools::setExpanded(view); - } - else if (geoMechCase) - { - RimGeoMechView* view = geoMechCase->createAndAddReservoirView(); - viewId = view->id(); - view->loadDataAndUpdate(); - geoMechCase->updateConnectedEditors(); - Riu3DMainWindowTools::setExpanded(view); - } + for (RimCase* rimCase : allCases) + { + if (rimCase->caseId == m_caseId()) + { + int viewId = -1; + RimEclipseCase* eclipseCase = dynamic_cast(rimCase); + RimGeoMechCase* geoMechCase = dynamic_cast(rimCase); + if (eclipseCase) + { + RimEclipseView* view = eclipseCase->createAndAddReservoirView(); + viewId = view->id(); + view->loadDataAndUpdate(); + eclipseCase->updateConnectedEditors(); + Riu3DMainWindowTools::setExpanded(view); + } + else if (geoMechCase) + { + RimGeoMechView* view = geoMechCase->createAndAddReservoirView(); + viewId = view->id(); + view->loadDataAndUpdate(); + geoMechCase->updateConnectedEditors(); + Riu3DMainWindowTools::setExpanded(view); + } - if (viewId >= 0) - { - RicfCommandResponse response; - response.setResult(new RicfCreateViewResult(viewId)); - return response; - } - } - } + if (viewId >= 0) + { + RicfCommandResponse response; + response.setResult(new RicfCreateViewResult(viewId)); + return response; + } + } + } QString error = QString("createView: Could not create view for case id %1").arg(m_caseId()); RiaLogging::error(error); - return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, error); + return RicfCommandResponse(RicfCommandResponse::COMMAND_ERROR, error); } diff --git a/ApplicationCode/ProjectDataModel/RimEclipseCase.cpp b/ApplicationCode/ProjectDataModel/RimEclipseCase.cpp index 8f9530d5bd..7fa68fd72e 100644 --- a/ApplicationCode/ProjectDataModel/RimEclipseCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimEclipseCase.cpp @@ -308,7 +308,7 @@ RimEclipseView* RimEclipseCase::createCopyAndAddView(const RimEclipseView* sourc RimEclipseView* rimEclipseView = dynamic_cast( sourceView->xmlCapability()->copyByXmlSerialization(caf::PdmDefaultObjectFactory::instance())); CVF_ASSERT(rimEclipseView); - RiaApplication::instance()->project()->assignViewIdToView(rimEclipseView); + RiaApplication::instance()->project()->assignViewIdToView(rimEclipseView); rimEclipseView->setEclipseCase(this); caf::PdmDocument::updateUiIconStateRecursively(rimEclipseView); diff --git a/ApplicationCode/ProjectDataModel/RimGeoMechCase.cpp b/ApplicationCode/ProjectDataModel/RimGeoMechCase.cpp index 4b1a3ab914..c76c134b7c 100644 --- a/ApplicationCode/ProjectDataModel/RimGeoMechCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimGeoMechCase.cpp @@ -198,8 +198,8 @@ RimGeoMechView* RimGeoMechCase::createCopyAndAddView(const RimGeoMechView* sourc sourceView->xmlCapability()->copyByXmlSerialization(caf::PdmDefaultObjectFactory::instance())); CVF_ASSERT(rimGeoMechView); - RiaApplication::instance()->project()->assignViewIdToView(rimGeoMechView); - rimGeoMechView->setGeoMechCase(this); + RiaApplication::instance()->project()->assignViewIdToView(rimGeoMechView); + rimGeoMechView->setGeoMechCase(this); caf::PdmDocument::updateUiIconStateRecursively(rimGeoMechView); @@ -209,8 +209,7 @@ RimGeoMechView* RimGeoMechCase::createCopyAndAddView(const RimGeoMechView* sourc rimGeoMechView->resolveReferencesRecursively(); rimGeoMechView->initAfterReadRecursively(); - return rimGeoMechView; - + return rimGeoMechView; } //-------------------------------------------------------------------------------------------------- From 88ca2c558d3f5a54868b9f59101f4f7c368b5b47 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 26 Aug 2019 10:00:13 +0200 Subject: [PATCH 384/396] Move data and time format to plotting --- ApplicationCode/Application/RiaPreferences.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ApplicationCode/Application/RiaPreferences.cpp b/ApplicationCode/Application/RiaPreferences.cpp index e80bb6b8d6..cf11363f41 100644 --- a/ApplicationCode/Application/RiaPreferences.cpp +++ b/ApplicationCode/Application/RiaPreferences.cpp @@ -268,8 +268,6 @@ void RiaPreferences::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& viewsGroup->add(&showHud); caf::PdmUiGroup* otherGroup = uiOrdering.addNewGroup("Other"); - otherGroup->add(&m_dateFormat); - otherGroup->add(&m_timeFormat); otherGroup->add(&ssihubAddress); otherGroup->add(&showLasCurveWithoutTvdWarning); otherGroup->add(&holoLensDisableCertificateVerification); @@ -304,6 +302,8 @@ void RiaPreferences::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& { uiOrdering.add(&defaultSummaryCurvesTextFilter); uiOrdering.add(&defaultSummaryHistoryCurveStyle); + uiOrdering.add(&m_dateFormat); + uiOrdering.add(&m_timeFormat); } else if (uiConfigName == RiaPreferences::tabNameScripting()) { From 51793ea7b3485f93d6363d018ecfb8e0362dc2ca Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Mon, 26 Aug 2019 10:01:40 +0200 Subject: [PATCH 385/396] Fix error in CloneView result --- ApplicationCode/CommandFileInterface/RicfCloneView.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ApplicationCode/CommandFileInterface/RicfCloneView.cpp b/ApplicationCode/CommandFileInterface/RicfCloneView.cpp index ddc039ac9b..f682f47f44 100644 --- a/ApplicationCode/CommandFileInterface/RicfCloneView.cpp +++ b/ApplicationCode/CommandFileInterface/RicfCloneView.cpp @@ -64,7 +64,7 @@ RicfCommandResponse RicfCloneView::execute() Riu3DMainWindowTools::setExpanded(view); } - if (newViewId) + if (newViewId >= 0) { RicfCommandResponse response; response.setResult(new RicfCreateViewResult(newViewId)); From 896d086d0da0ab2af5c3b9bb66777cd4f60b0262 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 26 Aug 2019 10:02:02 +0200 Subject: [PATCH 386/396] Rename tab name to Plotting --- ApplicationCode/Application/RiaPreferences.cpp | 8 ++++---- ApplicationCode/Application/RiaPreferences.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ApplicationCode/Application/RiaPreferences.cpp b/ApplicationCode/Application/RiaPreferences.cpp index cf11363f41..51ec810c8d 100644 --- a/ApplicationCode/Application/RiaPreferences.cpp +++ b/ApplicationCode/Application/RiaPreferences.cpp @@ -298,7 +298,7 @@ void RiaPreferences::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& group->add(&summaryEnsembleImportMode); } } - else if (uiConfigName == RiaPreferences::tabNameEclipseSummary()) + else if (uiConfigName == RiaPreferences::tabNamePlotting()) { uiOrdering.add(&defaultSummaryCurvesTextFilter); uiOrdering.add(&defaultSummaryHistoryCurveStyle); @@ -426,9 +426,9 @@ QString RiaPreferences::tabNameEclipse() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QString RiaPreferences::tabNameEclipseSummary() +QString RiaPreferences::tabNamePlotting() { - return "Summary"; + return "Plotting"; } //-------------------------------------------------------------------------------------------------- @@ -464,7 +464,7 @@ QStringList RiaPreferences::tabNames() names << tabNameGeneral(); names << tabNameEclipse(); - names << tabNameEclipseSummary(); + names << tabNamePlotting(); names << tabNameScripting(); names << tabNameExport(); diff --git a/ApplicationCode/Application/RiaPreferences.h b/ApplicationCode/Application/RiaPreferences.h index 63bd50d498..08598df29b 100644 --- a/ApplicationCode/Application/RiaPreferences.h +++ b/ApplicationCode/Application/RiaPreferences.h @@ -135,7 +135,7 @@ protected: private: static QString tabNameGeneral(); static QString tabNameEclipse(); - static QString tabNameEclipseSummary(); + static QString tabNamePlotting(); static QString tabNameScripting(); static QString tabNameExport(); static QString tabNameSystem(); From a1f9c4c1cdf8f35e21e56d3b00d34018599e6161 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Mon, 26 Aug 2019 10:03:56 +0200 Subject: [PATCH 387/396] Comment for circular import of Python module --- ApplicationCode/GrpcInterface/Python/rips/View.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ApplicationCode/GrpcInterface/Python/rips/View.py b/ApplicationCode/GrpcInterface/Python/rips/View.py index 115bf05238..1c4f34b6fa 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/View.py +++ b/ApplicationCode/GrpcInterface/Python/rips/View.py @@ -1,4 +1,4 @@ -import rips.Case +import rips.Case # Circular import of Case, which already imports View. Use full name. from rips.Commands import Commands from rips.PdmObject import PdmObject From 95602c78e1b02b64b21cbdf7878a2fa987e23ac8 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 26 Aug 2019 10:32:14 +0200 Subject: [PATCH 388/396] Add support for Travis (#4631) --- .travis.yml | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000000..a78690e48b --- /dev/null +++ b/.travis.yml @@ -0,0 +1,37 @@ +dist: xenial # For 18.04, use bionic + +language: cpp + +compiler: + - gcc + +addons: + apt: + sources: + packages: + - cmake + - cmake-data + - libqt5opengl5 + - qt5-qmake + - qt5-default + - libqt5opengl5-dev + - qtbase5-dev + - qtscript5-dev + +before_script: + - git clone https://github.com/OPM/ResInsight.git + +script: + ############################################################################ + # Build main and tests + ############################################################################ + - mkdir -p build + - cd build + + - cmake -DRESINSIGHT_ENABLE_COTIRE=true .. + + # Build the default target + #- make -j8 + + # Build the target produced by Cotire + - make -j8 ResInsight_unity From 7d5df167fd403bb6ea16add4f6d79778375f2a11 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 26 Aug 2019 11:00:09 +0200 Subject: [PATCH 389/396] Make sure all plot windows are resized to predefined size --- .../Tools/RiaRegressionTestRunner.cpp | 27 ++++++++----------- .../Tools/RiaRegressionTestRunner.h | 2 +- 2 files changed, 12 insertions(+), 17 deletions(-) diff --git a/ApplicationCode/Application/Tools/RiaRegressionTestRunner.cpp b/ApplicationCode/Application/Tools/RiaRegressionTestRunner.cpp index 26e344fee8..29ad82e2b3 100644 --- a/ApplicationCode/Application/Tools/RiaRegressionTestRunner.cpp +++ b/ApplicationCode/Application/Tools/RiaRegressionTestRunner.cpp @@ -18,8 +18,8 @@ #include "RiaRegressionTestRunner.h" -#include "RiaGuiApplication.h" #include "RiaGitDiff.h" +#include "RiaGuiApplication.h" #include "RiaImageCompareReporter.h" #include "RiaImageFileCompare.h" #include "RiaLogging.h" @@ -199,7 +199,7 @@ void RiaRegressionTestRunner::runRegressionTest() regressionTestConfigureProject(); - resizeMaximizedPlotWindows(); + resizePlotWindows(); QString fullPathGeneratedFolder = testCaseFolder.absoluteFilePath(generatedFolderName); RicSnapshotAllViewsToFileFeature::exportSnapshotOfAllViewsIntoFolder(fullPathGeneratedFolder); @@ -499,7 +499,7 @@ void RiaRegressionTestRunner::regressionTestConfigureProject() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RiaRegressionTestRunner::resizeMaximizedPlotWindows() +void RiaRegressionTestRunner::resizePlotWindows() { RimProject* proj = RiaApplication::instance()->project(); if (!proj) return; @@ -515,20 +515,16 @@ void RiaRegressionTestRunner::resizeMaximizedPlotWindows() { if (viewWindow->isMdiWindow()) { - RimMdiWindowGeometry wndGeo = viewWindow->mdiWindowGeometry(); - if (wndGeo.isMaximized) + QWidget* viewWidget = viewWindow->viewWidget(); + + if (viewWidget) { - QWidget* viewWidget = viewWindow->viewWidget(); - - if (viewWidget) + QMdiSubWindow* mdiWindow = plotMainWindow->findMdiSubWindow(viewWidget); + if (mdiWindow) { - QMdiSubWindow* mdiWindow = plotMainWindow->findMdiSubWindow(viewWidget); - if (mdiWindow) - { - mdiWindow->showNormal(); + mdiWindow->showNormal(); - viewWidget->resize(RiaRegressionTestRunner::regressionDefaultImageSize()); - } + viewWidget->resize(RiaRegressionTestRunner::regressionDefaultImageSize()); } } } @@ -603,8 +599,7 @@ QFileInfoList RiaRegressionTestRunner::subDirectoriesForTestExecution(const QDir for (const auto& s : m_testFilter) { QString trimmed = s.trimmed(); - if ((m_appendAllTestsAfterLastItemInFilter && anyMatchFound) || - baseName.contains(trimmed, Qt::CaseInsensitive)) + if ((m_appendAllTestsAfterLastItemInFilter && anyMatchFound) || baseName.contains(trimmed, Qt::CaseInsensitive)) { foldersMatchingTestFilter.push_back(fi); anyMatchFound = true; diff --git a/ApplicationCode/Application/Tools/RiaRegressionTestRunner.h b/ApplicationCode/Application/Tools/RiaRegressionTestRunner.h index 4a5edf2817..1b19b300dc 100644 --- a/ApplicationCode/Application/Tools/RiaRegressionTestRunner.h +++ b/ApplicationCode/Application/Tools/RiaRegressionTestRunner.h @@ -60,7 +60,7 @@ private: const QDir& testDir); static void removeDirectoryWithContent(QDir& dirToDelete); - static void resizeMaximizedPlotWindows(); + static void resizePlotWindows(); static QSize regressionDefaultImageSize(); static QString diff2htmlHeaderText(const QString& testRootPath); QFileInfoList subDirectoriesForTestExecution(const QDir& directory); From 1009f1ff45bc6664a8ede497e0cf58bf3be7db22 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Mon, 26 Aug 2019 11:17:20 +0200 Subject: [PATCH 390/396] #4629 Fix setting and reading of summary time values --- .../Summary/RimSummaryTimeAxisProperties.cpp | 6 ++---- .../cafUserInterface/cafPdmUiTimeEditor.cpp | 16 ++++++++++++---- Fwk/AppFwk/cafUserInterface/cafPdmUiTimeEditor.h | 1 + 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryTimeAxisProperties.cpp b/ApplicationCode/ProjectDataModel/Summary/RimSummaryTimeAxisProperties.cpp index 09e21a0715..b8961df29a 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryTimeAxisProperties.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryTimeAxisProperties.cpp @@ -301,8 +301,7 @@ bool RimSummaryTimeAxisProperties::isActive() const //-------------------------------------------------------------------------------------------------- QDateTime RimSummaryTimeAxisProperties::visibleDateTimeMin() const { - QDateTime fullMin(m_visibleDateRangeMin(), m_visibleTimeRangeMin()); - return fullMin; + return RiaQDateTimeTools::createUtcDateTime(m_visibleDateRangeMin(), m_visibleTimeRangeMin()); } //-------------------------------------------------------------------------------------------------- @@ -310,8 +309,7 @@ QDateTime RimSummaryTimeAxisProperties::visibleDateTimeMin() const //-------------------------------------------------------------------------------------------------- QDateTime RimSummaryTimeAxisProperties::visibleDateTimeMax() const { - QDateTime fullMax(m_visibleDateRangeMax(), m_visibleTimeRangeMax()); - return fullMax; + return RiaQDateTimeTools::createUtcDateTime(m_visibleDateRangeMax(), m_visibleTimeRangeMax()); } //-------------------------------------------------------------------------------------------------- diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiTimeEditor.cpp b/Fwk/AppFwk/cafUserInterface/cafPdmUiTimeEditor.cpp index ef3c333389..e317479228 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiTimeEditor.cpp +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiTimeEditor.cpp @@ -47,7 +47,6 @@ #include "cafQShortenedLabel.h" #include -#include #include #include #include @@ -87,7 +86,7 @@ namespace caf m_timeEdit->setDisplayFormat(m_attributes.timeFormat); } - m_timeEdit->setDate(uiField()->uiValue().toDate()); + m_timeEdit->setTime(uiField()->uiValue().toTime()); } @@ -98,9 +97,10 @@ namespace caf { m_timeEdit = new QTimeEdit(parent); connect(m_timeEdit, SIGNAL(editingFinished()), this, SLOT(slotEditingFinished())); + connect(m_timeEdit, SIGNAL(timeChanged(QTime)), this, SLOT(slotTimeChanged(QTime))); return m_timeEdit; } - + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -115,7 +115,15 @@ namespace caf //-------------------------------------------------------------------------------------------------- void PdmUiTimeEditor::slotEditingFinished() { - this->setValueToField(m_timeEdit->date()); + this->setValueToField(m_timeEdit->time()); } + //-------------------------------------------------------------------------------------------------- + /// + //-------------------------------------------------------------------------------------------------- + void PdmUiTimeEditor::slotTimeChanged(const QTime& time) + { + this->setValueToField(m_timeEdit->time()); + } + } // end namespace caf diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiTimeEditor.h b/Fwk/AppFwk/cafUserInterface/cafPdmUiTimeEditor.h index 2e97b347d5..657939e2df 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiTimeEditor.h +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiTimeEditor.h @@ -81,6 +81,7 @@ namespace caf protected slots: void slotEditingFinished(); + void slotTimeChanged(const QTime& time); private: QPointer m_timeEdit; From f1ccf4550fc29066a65da93e0d62309b6a8b4f2b Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Mon, 26 Aug 2019 08:46:16 +0200 Subject: [PATCH 391/396] #4535 Add default script path with Python examples --- ApplicationCode/Application/RiaPreferences.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ApplicationCode/Application/RiaPreferences.cpp b/ApplicationCode/Application/RiaPreferences.cpp index e80bb6b8d6..9bbb5ce340 100644 --- a/ApplicationCode/Application/RiaPreferences.cpp +++ b/ApplicationCode/Application/RiaPreferences.cpp @@ -32,6 +32,7 @@ #include "cafPdmUiFilePathEditor.h" #include +#include #include #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) @@ -74,7 +75,10 @@ RiaPreferences::RiaPreferences(void) CAF_PDM_InitFieldNoDefault(&scriptDirectories, "scriptDirectory", "Shared Script Folder(s)", "", "", ""); scriptDirectories.uiCapability()->setUiEditorTypeName(caf::PdmUiFilePathEditor::uiEditorTypeName()); - QString defaultTextEditor; + // TODO: This only currently works for installed ResInsight. + scriptDirectories = QCoreApplication::applicationDirPath() + "/Python/rips/PythonExamples"; + + QString defaultTextEditor; #ifdef WIN32 defaultTextEditor = QString("notepad.exe"); #else From d93b43afbe376f7c6375ab16474ba6709b50da6e Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Mon, 26 Aug 2019 12:26:47 +0200 Subject: [PATCH 392/396] Clang-format --- .../cafUserInterface/cafPdmUiTimeEditor.cpp | 146 +++++++++--------- .../cafUserInterface/cafPdmUiTimeEditor.h | 95 ++++++------ 2 files changed, 113 insertions(+), 128 deletions(-) diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiTimeEditor.cpp b/Fwk/AppFwk/cafUserInterface/cafPdmUiTimeEditor.cpp index e317479228..4910815e21 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiTimeEditor.cpp +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiTimeEditor.cpp @@ -3,8 +3,8 @@ // Custom Visualization Core library // Copyright (C) 2017 Ceetron Solutions AS // -// This library may be used under the terms of either the GNU General Public License or -// the GNU Lesser General Public License as follows: +// This library may be used under the terms of either the GNU General Public +// License or the GNU Lesser General Public License as follows: // // GNU General Public License Usage // This library is free software: you can redistribute it and/or modify @@ -12,12 +12,12 @@ // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // -// This library is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// This library 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. +// See the GNU General Public License at +// <> for more details. // // GNU Lesser General Public License Usage // This library is free software; you can redistribute it and/or modify @@ -25,27 +25,17 @@ // the Free Software Foundation; either version 2.1 of the License, or // (at your option) any later version. // -// This library is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// This library 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 Lesser General Public License at <> -// for more details. +// See the GNU Lesser General Public License at +// <> for more details. // //################################################################################################## - #include "cafPdmUiTimeEditor.h" -#include "cafFactory.h" -#include "cafPdmField.h" -#include "cafPdmObject.h" -#include "cafPdmUiDefaultObjectEditor.h" -#include "cafPdmUiFieldEditorHandle.h" -#include "cafPdmUiOrdering.h" -#include "cafSelectionManager.h" -#include "cafQShortenedLabel.h" - #include #include #include @@ -57,73 +47,75 @@ #include #include +#include "cafFactory.h" +#include "cafPdmField.h" +#include "cafPdmObject.h" +#include "cafPdmUiDefaultObjectEditor.h" +#include "cafPdmUiFieldEditorHandle.h" +#include "cafPdmUiOrdering.h" +#include "cafQShortenedLabel.h" +#include "cafSelectionManager.h" -namespace caf -{ +namespace caf { - CAF_PDM_UI_FIELD_EDITOR_SOURCE_INIT(PdmUiTimeEditor); +CAF_PDM_UI_FIELD_EDITOR_SOURCE_INIT(PdmUiTimeEditor); +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void PdmUiTimeEditor::configureAndUpdateUi(const QString& uiConfigName) { + CAF_ASSERT(!m_timeEdit.isNull()); - //-------------------------------------------------------------------------------------------------- - /// - //-------------------------------------------------------------------------------------------------- - void PdmUiTimeEditor::configureAndUpdateUi(const QString& uiConfigName) - { - CAF_ASSERT(!m_timeEdit.isNull()); + PdmUiFieldEditorHandle::updateLabelFromField(m_label, uiConfigName); - PdmUiFieldEditorHandle::updateLabelFromField(m_label, uiConfigName); + m_timeEdit->setEnabled(!uiField()->isUiReadOnly(uiConfigName)); - m_timeEdit->setEnabled(!uiField()->isUiReadOnly(uiConfigName)); + caf::PdmUiObjectHandle* uiObject = + uiObj(uiField()->fieldHandle()->ownerObject()); + if (uiObject) { + uiObject->editorAttribute(uiField()->fieldHandle(), uiConfigName, + &m_attributes); + } - caf::PdmUiObjectHandle* uiObject = uiObj(uiField()->fieldHandle()->ownerObject()); - if (uiObject) - { - uiObject->editorAttribute(uiField()->fieldHandle(), uiConfigName, &m_attributes); - } + if (!m_attributes.timeFormat.isEmpty()) { + m_timeEdit->setDisplayFormat(m_attributes.timeFormat); + } - if (!m_attributes.timeFormat.isEmpty()) - { - m_timeEdit->setDisplayFormat(m_attributes.timeFormat); - } + m_timeEdit->setTime(uiField()->uiValue().toTime()); +} - m_timeEdit->setTime(uiField()->uiValue().toTime()); - } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QWidget* PdmUiTimeEditor::createEditorWidget(QWidget* parent) { + m_timeEdit = new QTimeEdit(parent); + connect(m_timeEdit, SIGNAL(editingFinished()), this, + SLOT(slotEditingFinished())); + connect(m_timeEdit, SIGNAL(timeChanged(QTime)), this, + SLOT(slotTimeChanged(QTime))); + return m_timeEdit; +} +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QWidget* PdmUiTimeEditor::createLabelWidget(QWidget* parent) { + m_label = new QShortenedLabel(parent); + return m_label; +} - //-------------------------------------------------------------------------------------------------- - /// - //-------------------------------------------------------------------------------------------------- - QWidget* PdmUiTimeEditor::createEditorWidget(QWidget* parent) - { - m_timeEdit = new QTimeEdit(parent); - connect(m_timeEdit, SIGNAL(editingFinished()), this, SLOT(slotEditingFinished())); - connect(m_timeEdit, SIGNAL(timeChanged(QTime)), this, SLOT(slotTimeChanged(QTime))); - return m_timeEdit; - } - - //-------------------------------------------------------------------------------------------------- - /// - //-------------------------------------------------------------------------------------------------- - QWidget* PdmUiTimeEditor::createLabelWidget(QWidget* parent) - { - m_label = new QShortenedLabel(parent); - return m_label; - } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void PdmUiTimeEditor::slotEditingFinished() { + this->setValueToField(m_timeEdit->time()); +} - //-------------------------------------------------------------------------------------------------- - /// - //-------------------------------------------------------------------------------------------------- - void PdmUiTimeEditor::slotEditingFinished() - { - this->setValueToField(m_timeEdit->time()); - } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void PdmUiTimeEditor::slotTimeChanged(const QTime& time) { + this->setValueToField(m_timeEdit->time()); +} - //-------------------------------------------------------------------------------------------------- - /// - //-------------------------------------------------------------------------------------------------- - void PdmUiTimeEditor::slotTimeChanged(const QTime& time) - { - this->setValueToField(m_timeEdit->time()); - } - -} // end namespace caf +} // end namespace caf diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiTimeEditor.h b/Fwk/AppFwk/cafUserInterface/cafPdmUiTimeEditor.h index 657939e2df..47042defb2 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiTimeEditor.h +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiTimeEditor.h @@ -3,8 +3,8 @@ // Custom Visualization Core library // Copyright (C) 2019- Ceetron Solutions AS // -// This library may be used under the terms of either the GNU General Public License or -// the GNU Lesser General Public License as follows: +// This library may be used under the terms of either the GNU General Public +// License or the GNU Lesser General Public License as follows: // // GNU General Public License Usage // This library is free software: you can redistribute it and/or modify @@ -12,12 +12,12 @@ // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // -// This library is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// This library 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. +// See the GNU General Public License at +// <> for more details. // // GNU Lesser General Public License Usage // This library is free software; you can redistribute it and/or modify @@ -25,70 +25,63 @@ // the Free Software Foundation; either version 2.1 of the License, or // (at your option) any later version. // -// This library is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// This library 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 Lesser General Public License at <> -// for more details. +// See the GNU Lesser General Public License at +// <> for more details. // //################################################################################################## - #pragma once -#include "cafPdmUiFieldEditorHandle.h" - -#include #include #include #include +#include #include -namespace caf -{ +#include "cafPdmUiFieldEditorHandle.h" - //================================================================================================== - /// - //================================================================================================== - class PdmUiTimeEditorAttribute : public PdmUiEditorAttribute - { - public: - QString timeFormat; +namespace caf { - public: - PdmUiTimeEditorAttribute() - { - } - }; +//================================================================================================== +/// +//================================================================================================== +class PdmUiTimeEditorAttribute : public PdmUiEditorAttribute { + public: + QString timeFormat; - //-------------------------------------------------------------------------------------------------- - /// - //-------------------------------------------------------------------------------------------------- - class PdmUiTimeEditor : public PdmUiFieldEditorHandle - { - Q_OBJECT - CAF_PDM_UI_FIELD_EDITOR_HEADER_INIT; + public: + PdmUiTimeEditorAttribute() {} +}; - public: - PdmUiTimeEditor() {} - ~PdmUiTimeEditor() override {} +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +class PdmUiTimeEditor : public PdmUiFieldEditorHandle { + Q_OBJECT + CAF_PDM_UI_FIELD_EDITOR_HEADER_INIT; - protected: - QWidget* createEditorWidget(QWidget * parent) override; - QWidget* createLabelWidget(QWidget * parent) override; - void configureAndUpdateUi(const QString& uiConfigName) override; + public: + PdmUiTimeEditor() {} + ~PdmUiTimeEditor() override {} - protected slots: - void slotEditingFinished(); - void slotTimeChanged(const QTime& time); + protected: + QWidget* createEditorWidget(QWidget* parent) override; + QWidget* createLabelWidget(QWidget* parent) override; + void configureAndUpdateUi(const QString& uiConfigName) override; - private: - QPointer m_timeEdit; - QPointer m_label; + protected slots: + void slotEditingFinished(); + void slotTimeChanged(const QTime& time); - PdmUiTimeEditorAttribute m_attributes; - }; + private: + QPointer m_timeEdit; + QPointer m_label; + PdmUiTimeEditorAttribute m_attributes; +}; -} // end namespace caf +} // end namespace caf From 245d3ad2870d222ff99bcc1c5d72370f3633d9cb Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Mon, 26 Aug 2019 12:33:38 +0200 Subject: [PATCH 393/396] Fixed clang-format with proper definition file --- .../cafUserInterface/cafPdmUiTimeEditor.cpp | 103 +++++++++--------- .../cafUserInterface/cafPdmUiTimeEditor.h | 76 ++++++------- 2 files changed, 92 insertions(+), 87 deletions(-) diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiTimeEditor.cpp b/Fwk/AppFwk/cafUserInterface/cafPdmUiTimeEditor.cpp index 4910815e21..8008abacec 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiTimeEditor.cpp +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiTimeEditor.cpp @@ -3,8 +3,8 @@ // Custom Visualization Core library // Copyright (C) 2017 Ceetron Solutions AS // -// This library may be used under the terms of either the GNU General Public -// License or the GNU Lesser General Public License as follows: +// This library may be used under the terms of either the GNU General Public License or +// the GNU Lesser General Public License as follows: // // GNU General Public License Usage // This library is free software: you can redistribute it and/or modify @@ -12,12 +12,12 @@ // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // -// This library is distributed in the hope that it will be useful, but WITHOUT -// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// This library 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. +// See the GNU General Public License at <> +// for more details. // // GNU Lesser General Public License Usage // This library is free software; you can redistribute it and/or modify @@ -25,17 +25,26 @@ // the Free Software Foundation; either version 2.1 of the License, or // (at your option) any later version. // -// This library is distributed in the hope that it will be useful, but WITHOUT -// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// This library 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 Lesser General Public License at -// <> for more details. +// See the GNU Lesser General Public License at <> +// for more details. // //################################################################################################## #include "cafPdmUiTimeEditor.h" +#include "cafFactory.h" +#include "cafPdmField.h" +#include "cafPdmObject.h" +#include "cafPdmUiDefaultObjectEditor.h" +#include "cafPdmUiFieldEditorHandle.h" +#include "cafPdmUiOrdering.h" +#include "cafQShortenedLabel.h" +#include "cafSelectionManager.h" + #include #include #include @@ -47,75 +56,69 @@ #include #include -#include "cafFactory.h" -#include "cafPdmField.h" -#include "cafPdmObject.h" -#include "cafPdmUiDefaultObjectEditor.h" -#include "cafPdmUiFieldEditorHandle.h" -#include "cafPdmUiOrdering.h" -#include "cafQShortenedLabel.h" -#include "cafSelectionManager.h" - -namespace caf { - +namespace caf +{ CAF_PDM_UI_FIELD_EDITOR_SOURCE_INIT(PdmUiTimeEditor); //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void PdmUiTimeEditor::configureAndUpdateUi(const QString& uiConfigName) { - CAF_ASSERT(!m_timeEdit.isNull()); +void PdmUiTimeEditor::configureAndUpdateUi(const QString& uiConfigName) +{ + CAF_ASSERT(!m_timeEdit.isNull()); - PdmUiFieldEditorHandle::updateLabelFromField(m_label, uiConfigName); + PdmUiFieldEditorHandle::updateLabelFromField(m_label, uiConfigName); - m_timeEdit->setEnabled(!uiField()->isUiReadOnly(uiConfigName)); + m_timeEdit->setEnabled(!uiField()->isUiReadOnly(uiConfigName)); - caf::PdmUiObjectHandle* uiObject = - uiObj(uiField()->fieldHandle()->ownerObject()); - if (uiObject) { - uiObject->editorAttribute(uiField()->fieldHandle(), uiConfigName, - &m_attributes); - } + caf::PdmUiObjectHandle* uiObject = uiObj(uiField()->fieldHandle()->ownerObject()); + if (uiObject) + { + uiObject->editorAttribute(uiField()->fieldHandle(), uiConfigName, &m_attributes); + } - if (!m_attributes.timeFormat.isEmpty()) { - m_timeEdit->setDisplayFormat(m_attributes.timeFormat); - } + if (!m_attributes.timeFormat.isEmpty()) + { + m_timeEdit->setDisplayFormat(m_attributes.timeFormat); + } - m_timeEdit->setTime(uiField()->uiValue().toTime()); + m_timeEdit->setTime(uiField()->uiValue().toTime()); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QWidget* PdmUiTimeEditor::createEditorWidget(QWidget* parent) { - m_timeEdit = new QTimeEdit(parent); - connect(m_timeEdit, SIGNAL(editingFinished()), this, - SLOT(slotEditingFinished())); - connect(m_timeEdit, SIGNAL(timeChanged(QTime)), this, - SLOT(slotTimeChanged(QTime))); - return m_timeEdit; +QWidget* PdmUiTimeEditor::createEditorWidget(QWidget* parent) +{ + m_timeEdit = new QTimeEdit(parent); + connect(m_timeEdit, SIGNAL(editingFinished()), this, SLOT(slotEditingFinished())); + connect(m_timeEdit, SIGNAL(timeChanged(QTime)), this, SLOT(slotTimeChanged(QTime))); + return m_timeEdit; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QWidget* PdmUiTimeEditor::createLabelWidget(QWidget* parent) { - m_label = new QShortenedLabel(parent); - return m_label; +QWidget* PdmUiTimeEditor::createLabelWidget(QWidget* parent) +{ + m_label = new QShortenedLabel(parent); + return m_label; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void PdmUiTimeEditor::slotEditingFinished() { - this->setValueToField(m_timeEdit->time()); +void PdmUiTimeEditor::slotEditingFinished() +{ + this->setValueToField(m_timeEdit->time()); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void PdmUiTimeEditor::slotTimeChanged(const QTime& time) { - this->setValueToField(m_timeEdit->time()); +void PdmUiTimeEditor::slotTimeChanged(const QTime& time) +{ + this->setValueToField(m_timeEdit->time()); } -} // end namespace caf +} // end namespace caf diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiTimeEditor.h b/Fwk/AppFwk/cafUserInterface/cafPdmUiTimeEditor.h index 47042defb2..2aa8865b4d 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiTimeEditor.h +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiTimeEditor.h @@ -3,8 +3,8 @@ // Custom Visualization Core library // Copyright (C) 2019- Ceetron Solutions AS // -// This library may be used under the terms of either the GNU General Public -// License or the GNU Lesser General Public License as follows: +// This library may be used under the terms of either the GNU General Public License or +// the GNU Lesser General Public License as follows: // // GNU General Public License Usage // This library is free software: you can redistribute it and/or modify @@ -12,12 +12,12 @@ // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // -// This library is distributed in the hope that it will be useful, but WITHOUT -// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// This library 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. +// See the GNU General Public License at <> +// for more details. // // GNU Lesser General Public License Usage // This library is free software; you can redistribute it and/or modify @@ -25,63 +25,65 @@ // the Free Software Foundation; either version 2.1 of the License, or // (at your option) any later version. // -// This library is distributed in the hope that it will be useful, but WITHOUT -// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// This library 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 Lesser General Public License at -// <> for more details. +// See the GNU Lesser General Public License at <> +// for more details. // //################################################################################################## #pragma once +#include "cafPdmUiFieldEditorHandle.h" + #include #include #include #include #include -#include "cafPdmUiFieldEditorHandle.h" - -namespace caf { - +namespace caf +{ //================================================================================================== /// //================================================================================================== -class PdmUiTimeEditorAttribute : public PdmUiEditorAttribute { - public: - QString timeFormat; +class PdmUiTimeEditorAttribute : public PdmUiEditorAttribute +{ +public: + QString timeFormat; - public: - PdmUiTimeEditorAttribute() {} +public: + PdmUiTimeEditorAttribute() {} }; //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -class PdmUiTimeEditor : public PdmUiFieldEditorHandle { - Q_OBJECT - CAF_PDM_UI_FIELD_EDITOR_HEADER_INIT; +class PdmUiTimeEditor : public PdmUiFieldEditorHandle +{ + Q_OBJECT + CAF_PDM_UI_FIELD_EDITOR_HEADER_INIT; - public: - PdmUiTimeEditor() {} - ~PdmUiTimeEditor() override {} +public: + PdmUiTimeEditor() {} + ~PdmUiTimeEditor() override {} - protected: - QWidget* createEditorWidget(QWidget* parent) override; - QWidget* createLabelWidget(QWidget* parent) override; - void configureAndUpdateUi(const QString& uiConfigName) override; +protected: + QWidget* createEditorWidget(QWidget* parent) override; + QWidget* createLabelWidget(QWidget* parent) override; + void configureAndUpdateUi(const QString& uiConfigName) override; - protected slots: - void slotEditingFinished(); - void slotTimeChanged(const QTime& time); +protected slots: + void slotEditingFinished(); + void slotTimeChanged(const QTime& time); - private: - QPointer m_timeEdit; - QPointer m_label; +private: + QPointer m_timeEdit; + QPointer m_label; - PdmUiTimeEditorAttribute m_attributes; + PdmUiTimeEditorAttribute m_attributes; }; -} // end namespace caf +} // end namespace caf From a5b2a2e439f14aebcbd58559676e47b816c5de20 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 26 Aug 2019 13:19:07 +0200 Subject: [PATCH 394/396] Set version to 2019.8.0 --- ResInsightVersion.cmake | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ResInsightVersion.cmake b/ResInsightVersion.cmake index 56fdcd72a0..caf6d777e5 100644 --- a/ResInsightVersion.cmake +++ b/ResInsightVersion.cmake @@ -1,16 +1,16 @@ set(RESINSIGHT_MAJOR_VERSION 2019) -set(RESINSIGHT_MINOR_VERSION 04) +set(RESINSIGHT_MINOR_VERSION 8) set(RESINSIGHT_PATCH_VERSION 0) # Opional text with no restrictions -set(RESINSIGHT_VERSION_TEXT "-dev") +#set(RESINSIGHT_VERSION_TEXT "-dev") # 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 ".05") +#set(RESINSIGHT_DEV_VERSION ".05") # https://github.com/CRAVA/crava/tree/master/libs/nrlib set(NRLIB_GITHUB_SHA "ba35d4359882f1c6f5e9dc30eb95fe52af50fd6f") From 7b9e6677fffeff5e57b13f5a8bc75274d2bc0c7e Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Mon, 26 Aug 2019 15:48:20 +0200 Subject: [PATCH 395/396] GRPC: Move to version strings rather than int to avoid octal numbers --- ApplicationCode/Adm/RiaVersionInfo.h.cmake | 6 +++--- ApplicationCode/GrpcInterface/RiaGrpcAppService.cpp | 6 +++--- ResInsightVersion.cmake | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/ApplicationCode/Adm/RiaVersionInfo.h.cmake b/ApplicationCode/Adm/RiaVersionInfo.h.cmake index befafb8ef0..f3825c0350 100644 --- a/ApplicationCode/Adm/RiaVersionInfo.h.cmake +++ b/ApplicationCode/Adm/RiaVersionInfo.h.cmake @@ -27,8 +27,8 @@ #define PRODUCTVER "@PRODUCTVER@" #define STRPRODUCTVER "@STRPRODUCTVER@" -#define RESINSIGHT_MAJOR_VERSION @RESINSIGHT_MAJOR_VERSION@ -#define RESINSIGHT_MINOR_VERSION @RESINSIGHT_MINOR_VERSION@ -#define RESINSIGHT_PATCH_VERSION @RESINSIGHT_PATCH_VERSION@ +#define RESINSIGHT_MAJOR_VERSION "@RESINSIGHT_MAJOR_VERSION@" +#define RESINSIGHT_MINOR_VERSION "@RESINSIGHT_MINOR_VERSION@" +#define RESINSIGHT_PATCH_VERSION "@RESINSIGHT_PATCH_VERSION@" #define RESINSIGHT_OCTAVE_VERSION "@OCTAVE_VERSION_STRING@" diff --git a/ApplicationCode/GrpcInterface/RiaGrpcAppService.cpp b/ApplicationCode/GrpcInterface/RiaGrpcAppService.cpp index 8224ce9e62..4c907bdd55 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcAppService.cpp +++ b/ApplicationCode/GrpcInterface/RiaGrpcAppService.cpp @@ -27,9 +27,9 @@ //-------------------------------------------------------------------------------------------------- grpc::Status RiaGrpcAppService::GetVersion(grpc::ServerContext* context, const rips::Empty* request, rips::Version* reply) { - reply->set_major_version(RESINSIGHT_MAJOR_VERSION); - reply->set_minor_version(RESINSIGHT_MINOR_VERSION); - reply->set_patch_version(RESINSIGHT_PATCH_VERSION); + reply->set_major_version(QString(RESINSIGHT_MAJOR_VERSION).toInt()); + reply->set_minor_version(QString(RESINSIGHT_MINOR_VERSION).toInt()); + reply->set_patch_version(QString(RESINSIGHT_PATCH_VERSION).toInt()); return grpc::Status::OK; } diff --git a/ResInsightVersion.cmake b/ResInsightVersion.cmake index caf6d777e5..6d7d158be3 100644 --- a/ResInsightVersion.cmake +++ b/ResInsightVersion.cmake @@ -1,6 +1,6 @@ set(RESINSIGHT_MAJOR_VERSION 2019) -set(RESINSIGHT_MINOR_VERSION 8) +set(RESINSIGHT_MINOR_VERSION 08) set(RESINSIGHT_PATCH_VERSION 0) # Opional text with no restrictions From 1f903234627ee827b3502f7ef936e079529aa592 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 27 Aug 2019 07:35:35 +0200 Subject: [PATCH 396/396] #4636 Curve Data Export : Use correct column header for P10/P90 --- .../ProjectDataModel/Summary/RimSummaryCurve.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurve.cpp b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurve.cpp index 155b0c7c7d..9ae2c362b2 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurve.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurve.cpp @@ -21,6 +21,7 @@ #include "RiaDefines.h" #include "RiaGuiApplication.h" #include "RiaPreferences.h" +#include "RiaStatisticsTools.h" #include "RiaTimeHistoryCurveMerger.h" #include "RifReaderEclipseSummary.h" @@ -781,17 +782,24 @@ QString RimSummaryCurve::curveExportDescription(const RifEclipseSummaryAddress& auto curveSet = coll ? coll->findRimCurveSetFromQwtCurve(m_qwtPlotCurve) : nullptr; auto group = curveSet ? curveSet->summaryCaseCollection() : nullptr; + auto addressUiText = addr.uiText(); + if (addr.category() == RifEclipseSummaryAddress::SUMMARY_ENSEMBLE_STATISTICS) + { + addressUiText = RiaStatisticsTools::replacePercentileByPValueText(QString::fromStdString(addressUiText)).toStdString(); + + } + if (group && group->isEnsemble()) { return QString("%1.%2.%3") - .arg(QString::fromStdString(addr.uiText())) + .arg(QString::fromStdString(addressUiText)) .arg(m_yValuesSummaryCase->caseName()) .arg(group->name()); } else { return QString("%1.%2") - .arg(QString::fromStdString(addr.uiText())) + .arg(QString::fromStdString(addressUiText)) .arg(m_yValuesSummaryCase->caseName()); } }