From d13a52a8b439846acb7717c9d41e279ebf8a1dff Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Mon, 18 Jun 2018 14:17:13 +0200 Subject: [PATCH] #3058 Implement a memory cleanup dialog for GeoMech data. --- .../Application/CMakeLists_files.cmake | 2 + .../Application/RiaMemoryCleanup.cpp | 228 ++++++++++++++++++ .../Application/RiaMemoryCleanup.h | 55 +++++ .../CMakeLists_files.cmake | 2 + .../RicShowMemoryCleanupDialogFeature.cpp | 65 +++++ .../RicShowMemoryCleanupDialogFeature.h | 38 +++ .../GeoMech/GeoMechDataModel/CMakeLists.txt | 6 +- .../GeoMechDataModel/RigFemPartResults.cpp | 13 + .../GeoMechDataModel/RigFemPartResults.h | 7 +- .../RigFemPartResultsCollection.cpp | 85 ++++--- .../RigFemPartResultsCollection.h | 10 +- .../GeoMechDataModel/RimFemResultObserver.cpp | 4 + .../GeoMechDataModel/RimFemResultObserver.h | 32 +++ .../RimGeoMechResultDefinition.cpp | 34 ++- .../RimGeoMechResultDefinition.h | 12 +- .../ProjectDataModel/RimTensorResults.cpp | 12 + .../ProjectDataModel/RimTensorResults.h | 10 +- .../UserInterface/RiuMainWindow.cpp | 20 +- ApplicationCode/UserInterface/RiuMainWindow.h | 3 +- .../cafPdmUiTreeSelectionEditor.cpp | 13 +- .../cafPdmUiTreeSelectionQModel.cpp | 28 ++- .../cafPdmUiTreeSelectionQModel.h | 2 + 22 files changed, 622 insertions(+), 59 deletions(-) create mode 100644 ApplicationCode/Application/RiaMemoryCleanup.cpp create mode 100644 ApplicationCode/Application/RiaMemoryCleanup.h create mode 100644 ApplicationCode/Commands/ApplicationCommands/RicShowMemoryCleanupDialogFeature.cpp create mode 100644 ApplicationCode/Commands/ApplicationCommands/RicShowMemoryCleanupDialogFeature.h create mode 100644 ApplicationCode/GeoMech/GeoMechDataModel/RimFemResultObserver.cpp create mode 100644 ApplicationCode/GeoMech/GeoMechDataModel/RimFemResultObserver.h diff --git a/ApplicationCode/Application/CMakeLists_files.cmake b/ApplicationCode/Application/CMakeLists_files.cmake index 6e0a95b270..2fc2f0249b 100644 --- a/ApplicationCode/Application/CMakeLists_files.cmake +++ b/ApplicationCode/Application/CMakeLists_files.cmake @@ -9,6 +9,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RiaPorosityModel.h ${CMAKE_CURRENT_LIST_DIR}/RiaSummaryCurveDefinition.h ${CMAKE_CURRENT_LIST_DIR}/RiaRftPltCurveDefinition.h ${CMAKE_CURRENT_LIST_DIR}/RiaViewRedrawScheduler.h +${CMAKE_CURRENT_LIST_DIR}/RiaMemoryCleanup.h ) set (SOURCE_GROUP_SOURCE_FILES @@ -22,6 +23,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RiaPorosityModel.cpp ${CMAKE_CURRENT_LIST_DIR}/RiaSummaryCurveDefinition.cpp ${CMAKE_CURRENT_LIST_DIR}/RiaRftPltCurveDefinition.cpp ${CMAKE_CURRENT_LIST_DIR}/RiaViewRedrawScheduler.cpp +${CMAKE_CURRENT_LIST_DIR}/RiaMemoryCleanup.cpp ) list(APPEND CODE_HEADER_FILES diff --git a/ApplicationCode/Application/RiaMemoryCleanup.cpp b/ApplicationCode/Application/RiaMemoryCleanup.cpp new file mode 100644 index 0000000000..8adcb55a29 --- /dev/null +++ b/ApplicationCode/Application/RiaMemoryCleanup.cpp @@ -0,0 +1,228 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2018- Statoil ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RiaMemoryCleanup.h" + +#include "RiaApplication.h" +#include "RigFemPartResultsCollection.h" +#include "RigFemResultAddress.h" +#include "RigGeoMechCaseData.h" +#include "Rim3dView.h" +#include "RimGeoMechCase.h" +#include "RimGeoMechResultDefinition.h" +#include "RimProject.h" + +#include "cafPdmUiListEditor.h" +#include "cafPdmUiPushButtonEditor.h" +#include "cafPdmUiTreeSelectionEditor.h" + +//================================================================================================== +/// +/// +//================================================================================================== + +CAF_PDM_SOURCE_INIT(RiaMemoryCleanup, "RiaMemoryCleanup"); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiaMemoryCleanup::RiaMemoryCleanup() +{ + // clang-format off + CAF_PDM_InitFieldNoDefault(&m_case, "DataCase", "Case", "", "", ""); + m_case = nullptr; + + CAF_PDM_InitFieldNoDefault(&m_resultsToDelete, "ResultsToDelete", "Results In Memory", "", "", ""); + m_resultsToDelete.uiCapability()->setUiLabelPosition(caf::PdmUiItemInfo::TOP); + m_resultsToDelete.uiCapability()->setUiEditorTypeName(caf::PdmUiTreeSelectionEditor::uiEditorTypeName()); + + CAF_PDM_InitFieldNoDefault(&m_performDelete, "ClearSelectedData", "", "", "", ""); + caf::PdmUiPushButtonEditor::configureEditorForField(&m_performDelete); + // clang-format on +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaMemoryCleanup::setPropertiesFromView(Rim3dView* view) +{ + if (!view) return; + + m_case = view->ownerCase(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaMemoryCleanup::clearSelectedResultsFromMemory() +{ + RimGeoMechCase* geoMechCase = dynamic_cast(m_case()); + if (geoMechCase) + { + RigGeoMechCaseData* data = geoMechCase->geoMechData(); + if (data) + { + RigFemPartResultsCollection* resultsCollection = data->femPartResults(); + if (resultsCollection) + { + std::vector resultsToDelete = selectedGeoMechResults(); + for (RigFemResultAddress result : resultsToDelete) + { + resultsCollection->deleteResult(result); + } + } + } + } + m_resultsToDelete.v().clear(); + m_geomResultAddresses.clear(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RiaMemoryCleanup::selectedGeoMechResults() const +{ + std::vector results; + for (size_t index : m_resultsToDelete()) + { + results.push_back(m_geomResultAddresses[index]); + } + return results; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::set RiaMemoryCleanup::findGeoMechCaseResultsInUse() const +{ + std::set resultsInUse; + RimGeoMechCase* geoMechCase = dynamic_cast(m_case()); + if (geoMechCase) + { + std::vector geoMechResults; + geoMechCase->descendantsIncludingThisOfType(geoMechResults); + for (RimFemResultObserver* resultDef : geoMechResults) + { + caf::PdmField* field = dynamic_cast*>(resultDef->objectToggleField()); + if (!field || (*field)()) + { + std::vector required = resultDef->observedResults(); + resultsInUse.insert(required.begin(), required.end()); + } + } + } + return resultsInUse; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaMemoryCleanup::fieldChangedByUi(const caf::PdmFieldHandle* changedField, + const QVariant& oldValue, + const QVariant& newValue) +{ + if (changedField == &m_case) + { + m_resultsToDelete.uiCapability()->updateConnectedEditors(); + } + else if (changedField == &m_performDelete) + { + clearSelectedResultsFromMemory(); + m_resultsToDelete.uiCapability()->updateConnectedEditors(); + m_performDelete = false; + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QList RiaMemoryCleanup::calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, + bool* useOptionsOnly) +{ + QList options; + if (fieldNeedingOptions == &m_case) + { + RimProject* proj = RiaApplication::instance()->project(); + if (proj) + { + std::vector cases = proj->geoMechCases(); + + for (RimGeoMechCase* c : cases) + { + options.push_back(caf::PdmOptionItemInfo(c->caseUserDescription(), c, false, c->uiIcon())); + } + } + } + else if (fieldNeedingOptions == &m_resultsToDelete) + { + RimGeoMechCase* geoMechCase = dynamic_cast(m_case()); + if (geoMechCase) + { + std::set resultsInUse = findGeoMechCaseResultsInUse(); + RigGeoMechCaseData* caseData = geoMechCase->geoMechData(); + if (caseData) + { + RigFemPartResultsCollection* results = caseData->femPartResults(); + m_geomResultAddresses = results->loadedResults(); + + for (size_t i = 0; i < m_geomResultAddresses.size(); ++i) + { + const RigFemResultAddress& result = m_geomResultAddresses[i]; + bool inUse = resultsInUse.count(result); + QString posText = caf::AppEnum::uiTextFromIndex(result.resultPosType); + QString resultsText = QString("%1, %2").arg(posText).arg(QString::fromStdString(result.fieldName)); + if (!result.componentName.empty()) + { + resultsText += QString(", %1").arg(QString::fromStdString(result.componentName)); + } + if (inUse) + { + resultsText += QString(" [shown in view]"); + } + options.push_back(caf::PdmOptionItemInfo(resultsText, (qulonglong) i, inUse)); + } + } + } + } + return options; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaMemoryCleanup::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) +{ + uiOrdering.add(&m_case); + uiOrdering.add(&m_resultsToDelete); + uiOrdering.add(&m_performDelete); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaMemoryCleanup::defineEditorAttribute(const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute) +{ + if (field == &m_performDelete) + { + caf::PdmUiPushButtonEditorAttribute* attrib = dynamic_cast(attribute); + if (attrib) + { + attrib->m_buttonText = "Clear Checked Data From Memory"; + } + } +} diff --git a/ApplicationCode/Application/RiaMemoryCleanup.h b/ApplicationCode/Application/RiaMemoryCleanup.h new file mode 100644 index 0000000000..9842f9d9b2 --- /dev/null +++ b/ApplicationCode/Application/RiaMemoryCleanup.h @@ -0,0 +1,55 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2018- Statoil ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "RigFemResultAddress.h" + +#include "cafPdmField.h" +#include "cafPdmChildArrayField.h" +#include "cafPdmPtrField.h" +#include "cafPdmObject.h" +#include "cafPdmUiItem.h" + +class RimCase; +class Rim3dView; + +class RiaMemoryCleanup : public caf::PdmObject +{ + CAF_PDM_HEADER_INIT; +public: + RiaMemoryCleanup(); + + void setPropertiesFromView(Rim3dView* view); + void clearSelectedResultsFromMemory(); +protected: + virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override; +private: + std::vector selectedGeoMechResults() const; + std::set findGeoMechCaseResultsInUse() const; + + virtual QList calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, + bool* useOptionsOnly) override; + virtual void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) override; + virtual void defineEditorAttribute(const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute) override; +private: + caf::PdmPtrField m_case; + caf::PdmField> m_resultsToDelete; + std::vector m_geomResultAddresses; + caf::PdmField m_performDelete; +}; \ No newline at end of file diff --git a/ApplicationCode/Commands/ApplicationCommands/CMakeLists_files.cmake b/ApplicationCode/Commands/ApplicationCommands/CMakeLists_files.cmake index a104e060e6..503c54c485 100644 --- a/ApplicationCode/Commands/ApplicationCommands/CMakeLists_files.cmake +++ b/ApplicationCode/Commands/ApplicationCommands/CMakeLists_files.cmake @@ -15,6 +15,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RicEditPreferencesFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicShowPlotDataFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicLaunchRegressionTestsFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicRunCommandFileFeature.h +${CMAKE_CURRENT_LIST_DIR}/RicShowMemoryCleanupDialogFeature.h ) set (SOURCE_GROUP_SOURCE_FILES @@ -33,6 +34,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RicEditPreferencesFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicShowPlotDataFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicLaunchRegressionTestsFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicRunCommandFileFeature.cpp +${CMAKE_CURRENT_LIST_DIR}/RicShowMemoryCleanupDialogFeature.cpp ) list(APPEND CODE_HEADER_FILES diff --git a/ApplicationCode/Commands/ApplicationCommands/RicShowMemoryCleanupDialogFeature.cpp b/ApplicationCode/Commands/ApplicationCommands/RicShowMemoryCleanupDialogFeature.cpp new file mode 100644 index 0000000000..2c378f0ece --- /dev/null +++ b/ApplicationCode/Commands/ApplicationCommands/RicShowMemoryCleanupDialogFeature.cpp @@ -0,0 +1,65 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2016 Statoil ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RicShowMemoryCleanupDialogFeature.h" + +#include "RiaApplication.h" +#include "RiaMemoryCleanup.h" +#include "RiuMainWindow.h" + +#include "cafPdmUiPropertyViewDialog.h" + +#include + +CAF_CMD_SOURCE_INIT(RicShowMemoryCleanupDialogFeature, "RicShowMemoryCleanupDialogFeature"); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RicShowMemoryCleanupDialogFeature::isCommandEnabled() +{ + return true; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicShowMemoryCleanupDialogFeature::onActionTriggered(bool isChecked) +{ + RiaMemoryCleanup memoryCleanup; + Rim3dView* view = RiaApplication::instance()->activeReservoirView(); + if (view) + { + memoryCleanup.setPropertiesFromView(view); + } + + caf::PdmUiPropertyViewDialog dialog(RiuMainWindow::instance(), &memoryCleanup, "Clear Results From Memory", "", QDialogButtonBox::Close); + dialog.resize(QSize(400, 400)); + if (dialog.exec() == QDialog::Accepted) + { + memoryCleanup.clearSelectedResultsFromMemory(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicShowMemoryCleanupDialogFeature::setupActionLook(QAction* actionToSetup) +{ + actionToSetup->setText("&Memory Cleanup..."); +} diff --git a/ApplicationCode/Commands/ApplicationCommands/RicShowMemoryCleanupDialogFeature.h b/ApplicationCode/Commands/ApplicationCommands/RicShowMemoryCleanupDialogFeature.h new file mode 100644 index 0000000000..23dcdb532e --- /dev/null +++ b/ApplicationCode/Commands/ApplicationCommands/RicShowMemoryCleanupDialogFeature.h @@ -0,0 +1,38 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2018- Statoil ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cafCmdFeature.h" + + +//================================================================================================== +/// +//================================================================================================== +class RicShowMemoryCleanupDialogFeature : public caf::CmdFeature +{ + CAF_CMD_HEADER_INIT; + +protected: + // Overrides + virtual bool isCommandEnabled() override; + virtual void onActionTriggered( bool isChecked ) override; + virtual void setupActionLook( QAction* actionToSetup ) override; +}; + + diff --git a/ApplicationCode/GeoMech/GeoMechDataModel/CMakeLists.txt b/ApplicationCode/GeoMech/GeoMechDataModel/CMakeLists.txt index ed56edb9f3..c082dd9ac3 100644 --- a/ApplicationCode/GeoMech/GeoMechDataModel/CMakeLists.txt +++ b/ApplicationCode/GeoMech/GeoMechDataModel/CMakeLists.txt @@ -26,8 +26,10 @@ add_library( ${PROJECT_NAME} RigFemPartGrid.cpp RigFemResultAddress.h RigFemResultPosEnum.h - RimGeoMechGeometrySelectionItem.h - RimGeoMechGeometrySelectionItem.cpp + RimFemResultObserver.h + RimFemResultObserver.cpp + RimGeoMechGeometrySelectionItem.h + RimGeoMechGeometrySelectionItem.cpp ) target_include_directories(${PROJECT_NAME} diff --git a/ApplicationCode/GeoMech/GeoMechDataModel/RigFemPartResults.cpp b/ApplicationCode/GeoMech/GeoMechDataModel/RigFemPartResults.cpp index bf0ea0250d..3f518a9fac 100644 --- a/ApplicationCode/GeoMech/GeoMechDataModel/RigFemPartResults.cpp +++ b/ApplicationCode/GeoMech/GeoMechDataModel/RigFemPartResults.cpp @@ -92,3 +92,16 @@ void RigFemPartResults::deleteScalarResult(const RigFemResultAddress& resVarAddr } } } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RigFemPartResults::loadedResults() const +{ + std::vector currentResults; + for (const auto& result : resultSets) + { + currentResults.push_back(result.first); + } + return currentResults; +} diff --git a/ApplicationCode/GeoMech/GeoMechDataModel/RigFemPartResults.h b/ApplicationCode/GeoMech/GeoMechDataModel/RigFemPartResults.h index c193f0212f..5df61d0c19 100644 --- a/ApplicationCode/GeoMech/GeoMechDataModel/RigFemPartResults.h +++ b/ApplicationCode/GeoMech/GeoMechDataModel/RigFemPartResults.h @@ -39,9 +39,10 @@ public: void initResultSteps(const std::vector& stepNames); - RigFemScalarResultFrames* createScalarResult(const RigFemResultAddress& resVarAddr); - RigFemScalarResultFrames* findScalarResult(const RigFemResultAddress& resVarAddr); - void deleteScalarResult(const RigFemResultAddress& resVarAddr); + RigFemScalarResultFrames* createScalarResult(const RigFemResultAddress& resVarAddr); + RigFemScalarResultFrames* findScalarResult(const RigFemResultAddress& resVarAddr); + void deleteScalarResult(const RigFemResultAddress& resVarAddr); + std::vector loadedResults() const; private: diff --git a/ApplicationCode/GeoMech/GeoMechDataModel/RigFemPartResultsCollection.cpp b/ApplicationCode/GeoMech/GeoMechDataModel/RigFemPartResultsCollection.cpp index 82c052d080..994f93fb13 100644 --- a/ApplicationCode/GeoMech/GeoMechDataModel/RigFemPartResultsCollection.cpp +++ b/ApplicationCode/GeoMech/GeoMechDataModel/RigFemPartResultsCollection.cpp @@ -2243,6 +2243,20 @@ void RigFemPartResultsCollection::deleteResult(const RigFemResultAddress& resVar } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RigFemPartResultsCollection::loadedResults() const +{ + std::vector currentResults; + for (auto & femPartResult : m_femPartResults) + { + std::vector partResults = femPartResult->loadedResults(); + currentResults.insert(currentResults.end(), partResults.begin(), partResults.end()); + } + return currentResults; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -2263,40 +2277,19 @@ std::vector RigFemPartResultsCollection::tensors(const RigFemResultA std::vector outputTensors; - RigFemResultAddress address11(resVarAddr.resultPosType, resVarAddr.fieldName, ""); - RigFemResultAddress address22(resVarAddr.resultPosType, resVarAddr.fieldName, ""); - RigFemResultAddress address33(resVarAddr.resultPosType, resVarAddr.fieldName, ""); - RigFemResultAddress address12(resVarAddr.resultPosType, resVarAddr.fieldName, ""); - RigFemResultAddress address13(resVarAddr.resultPosType, resVarAddr.fieldName, ""); - RigFemResultAddress address23(resVarAddr.resultPosType, resVarAddr.fieldName, ""); + std::vector addresses = tensorComponentAddresses(resVarAddr); - if (resVarAddr.fieldName == "SE" || resVarAddr.fieldName == "ST") + if (addresses.empty()) { - address11.componentName = "S11"; - address22.componentName = "S22"; - address33.componentName = "S33"; - address12.componentName = "S12"; - address13.componentName = "S13"; - address23.componentName = "S23"; - } - else if (resVarAddr.fieldName == "NE") - { - address11.componentName = "E11"; - address22.componentName = "E22"; - address33.componentName = "E33"; - address12.componentName = "E12"; - address13.componentName = "E13"; - address23.componentName = "E23"; - } - else return outputTensors; + } - const std::vector& v11 = resultValues(address11, partIndex, frameIndex); - const std::vector& v22 = resultValues(address22, partIndex, frameIndex); - const std::vector& v33 = resultValues(address33, partIndex, frameIndex); - const std::vector& v12 = resultValues(address12, partIndex, frameIndex); - const std::vector& v13 = resultValues(address13, partIndex, frameIndex); - const std::vector& v23 = resultValues(address23, partIndex, frameIndex); + const std::vector& v11 = resultValues(addresses[caf::Ten3f::SXX], partIndex, frameIndex); + const std::vector& v22 = resultValues(addresses[caf::Ten3f::SYY], partIndex, frameIndex); + const std::vector& v33 = resultValues(addresses[caf::Ten3f::SZZ], partIndex, frameIndex); + const std::vector& v12 = resultValues(addresses[caf::Ten3f::SXY], partIndex, frameIndex); + const std::vector& v13 = resultValues(addresses[caf::Ten3f::SZX], partIndex, frameIndex); + const std::vector& v23 = resultValues(addresses[caf::Ten3f::SYZ], partIndex, frameIndex); size_t valCount = v11.size(); outputTensors.resize(valCount); @@ -2568,6 +2561,38 @@ void RigFemPartResultsCollection::posNegClosestToZeroOverAllTensorComponents(con *globalNegClosestToZero = currentNegClosestToZero; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RigFemPartResultsCollection::tensorComponentAddresses(const RigFemResultAddress& resVarAddr) +{ + std::vector addresses(6, RigFemResultAddress(resVarAddr.resultPosType, resVarAddr.fieldName, "")); + + if (resVarAddr.fieldName == "SE" || resVarAddr.fieldName == "ST") + { + addresses[caf::Ten3f::SXX].componentName = "S11"; + addresses[caf::Ten3f::SYY].componentName = "S22"; + addresses[caf::Ten3f::SZZ].componentName = "S33"; + addresses[caf::Ten3f::SXY].componentName = "S12"; + addresses[caf::Ten3f::SZX].componentName = "S13"; + addresses[caf::Ten3f::SYZ].componentName = "S23"; + } + else if (resVarAddr.fieldName == "NE") + { + addresses[caf::Ten3f::SXX].componentName = "E11"; + addresses[caf::Ten3f::SYY].componentName = "E22"; + addresses[caf::Ten3f::SZZ].componentName = "E33"; + addresses[caf::Ten3f::SXY].componentName = "E12"; + addresses[caf::Ten3f::SZX].componentName = "E13"; + addresses[caf::Ten3f::SYZ].componentName = "E23"; + } + else + { + return std::vector(); + } + return addresses; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/GeoMech/GeoMechDataModel/RigFemPartResultsCollection.h b/ApplicationCode/GeoMech/GeoMechDataModel/RigFemPartResultsCollection.h index 5a4ee4acd0..e939016d0e 100644 --- a/ApplicationCode/GeoMech/GeoMechDataModel/RigFemPartResultsCollection.h +++ b/ApplicationCode/GeoMech/GeoMechDataModel/RigFemPartResultsCollection.h @@ -68,6 +68,8 @@ public: bool assertResultsLoaded(const RigFemResultAddress& resVarAddr); void deleteResult(const RigFemResultAddress& resVarAddr); + std::vector loadedResults() const; + const std::vector& resultValues(const RigFemResultAddress& resVarAddr, int partIndex, int frameIndex); std::vector tensors(const RigFemResultAddress& resVarAddr, int partIndex, int frameIndex); int partCount() const; @@ -92,6 +94,10 @@ public: void minMaxScalarValuesOverAllTensorComponents(const RigFemResultAddress& resVarAddr, double* globalMin, double* globalMax); void posNegClosestToZeroOverAllTensorComponents(const RigFemResultAddress& resVarAddr, int frameIndex, double* localPosClosestToZero, double* localNegClosestToZero); void posNegClosestToZeroOverAllTensorComponents(const RigFemResultAddress& resVarAddr, double* globalPosClosestToZero, double* globalNegClosestToZero); + + static std::vector tensorComponentAddresses(const RigFemResultAddress& resVarAddr); + static std::vector tensorPrincipalComponentAdresses(const RigFemResultAddress& resVarAddr); + private: RigFemScalarResultFrames* findOrLoadScalarResult(int partIndex, const RigFemResultAddress& resVarAddr); @@ -127,9 +133,7 @@ private: RigFemScalarResultFrames* calculateST_12_13_23(int partIndex, const RigFemResultAddress &resVarAddr); RigFemScalarResultFrames* calculateGamma(int partIndex, const RigFemResultAddress &resVarAddr); RigFemScalarResultFrames* calculateFormationIndices(int partIndex, const RigFemResultAddress &resVarAddr); - - static std::vector tensorPrincipalComponentAdresses(const RigFemResultAddress& resVarAddr); - + private: cvf::Collection m_femPartResults; cvf::ref m_readerInterface; diff --git a/ApplicationCode/GeoMech/GeoMechDataModel/RimFemResultObserver.cpp b/ApplicationCode/GeoMech/GeoMechDataModel/RimFemResultObserver.cpp new file mode 100644 index 0000000000..48c6c33a3c --- /dev/null +++ b/ApplicationCode/GeoMech/GeoMechDataModel/RimFemResultObserver.cpp @@ -0,0 +1,4 @@ +#include "RimFemResultObserver.h" + +CAF_PDM_ABSTRACT_SOURCE_INIT(RimFemResultObserver, "RimFemResultObserver"); + diff --git a/ApplicationCode/GeoMech/GeoMechDataModel/RimFemResultObserver.h b/ApplicationCode/GeoMech/GeoMechDataModel/RimFemResultObserver.h new file mode 100644 index 0000000000..c91f3ce84d --- /dev/null +++ b/ApplicationCode/GeoMech/GeoMechDataModel/RimFemResultObserver.h @@ -0,0 +1,32 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2018- Statoil ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "RigFemResultAddress.h" + +#include "cafPdmObject.h" + +#include + +class RimFemResultObserver : public caf::PdmObject +{ + CAF_PDM_HEADER_INIT; +public: + virtual std::vector observedResults() const = 0; +}; \ No newline at end of file diff --git a/ApplicationCode/ProjectDataModel/RimGeoMechResultDefinition.cpp b/ApplicationCode/ProjectDataModel/RimGeoMechResultDefinition.cpp index 50080f9183..685d6fe793 100644 --- a/ApplicationCode/ProjectDataModel/RimGeoMechResultDefinition.cpp +++ b/ApplicationCode/ProjectDataModel/RimGeoMechResultDefinition.cpp @@ -509,7 +509,7 @@ void RimGeoMechResultDefinition::setAddWellPathDerivedResults(bool addWellPathDe //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RigFemResultAddress RimGeoMechResultDefinition::resultAddress() +RigFemResultAddress RimGeoMechResultDefinition::resultAddress() const { return RigFemResultAddress(resultPositionType(), resultFieldName().toStdString(), @@ -518,6 +518,38 @@ RigFemResultAddress RimGeoMechResultDefinition::resultAddress() resultFieldName().toStdString() == RigFemPartResultsCollection::FIELD_NAME_COMPACTION ? m_compactionRefLayer() : RigFemResultAddress::NO_COMPACTION); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RimGeoMechResultDefinition::observedResults() const +{ + return std::vector(1, resultAddress()); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RigFemResultPosEnum RimGeoMechResultDefinition::resultPositionType() const +{ + return m_resultPositionType(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RimGeoMechResultDefinition::resultFieldName() const +{ + return m_resultFieldName(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RimGeoMechResultDefinition::resultComponentName() const +{ + return m_resultComponentName(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimGeoMechResultDefinition.h b/ApplicationCode/ProjectDataModel/RimGeoMechResultDefinition.h index f3a2185499..250d916fd9 100644 --- a/ApplicationCode/ProjectDataModel/RimGeoMechResultDefinition.h +++ b/ApplicationCode/ProjectDataModel/RimGeoMechResultDefinition.h @@ -25,6 +25,7 @@ #include "cafAppEnum.h" #include "RigFemResultPosEnum.h" #include "RigFemResultAddress.h" +#include "RimFemResultObserver.h" class RimGeoMechView; class RimGeoMechPropertyFilter; @@ -36,7 +37,7 @@ class RimGeoMechCase; /// /// //================================================================================================== -class RimGeoMechResultDefinition : public caf::PdmObject +class RimGeoMechResultDefinition : public RimFemResultObserver { CAF_PDM_HEADER_INIT; public: @@ -50,11 +51,12 @@ public: void loadResult(); void setAddWellPathDerivedResults(bool addWellPathDerivedResults); - RigFemResultAddress resultAddress(); + RigFemResultAddress resultAddress() const; + virtual std::vector observedResults() const override; - RigFemResultPosEnum resultPositionType() { return m_resultPositionType();} - QString resultFieldName() { return m_resultFieldName();} - QString resultComponentName() { return m_resultComponentName();} + RigFemResultPosEnum resultPositionType() const; + QString resultFieldName() const; + QString resultComponentName() const; void setResultAddress(const RigFemResultAddress& resultAddress); QString resultFieldUiName(); diff --git a/ApplicationCode/ProjectDataModel/RimTensorResults.cpp b/ApplicationCode/ProjectDataModel/RimTensorResults.cpp index d2f05925a2..cc1d833961 100644 --- a/ApplicationCode/ProjectDataModel/RimTensorResults.cpp +++ b/ApplicationCode/ProjectDataModel/RimTensorResults.cpp @@ -214,6 +214,18 @@ void RimTensorResults::mappingRange(double* min, double* max) const } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RimTensorResults::observedResults() const +{ + RigFemResultAddress mainResult = selectedTensorResult(); + std::vector tensorComponents = RigFemPartResultsCollection::tensorComponentAddresses(mainResult); + std::vector principleComponents = RigFemPartResultsCollection::tensorPrincipalComponentAdresses(mainResult); + tensorComponents.insert(tensorComponents.end(), principleComponents.begin(), principleComponents.end()); + return tensorComponents; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimTensorResults.h b/ApplicationCode/ProjectDataModel/RimTensorResults.h index 18701d39f1..57e1663749 100644 --- a/ApplicationCode/ProjectDataModel/RimTensorResults.h +++ b/ApplicationCode/ProjectDataModel/RimTensorResults.h @@ -22,6 +22,7 @@ #include "cafPdmField.h" #include "cafPdmObject.h" +#include "RimFemResultObserver.h" #include "RigFemResultPosEnum.h" #include "RimRegularLegendConfig.h" @@ -36,7 +37,7 @@ class RimRegularLegendConfig; /// /// //================================================================================================== -class RimTensorResults : public caf::PdmObject +class RimTensorResults : public RimFemResultObserver { CAF_PDM_HEADER_INIT; @@ -72,9 +73,10 @@ public: void mappingRange(double *min, double* max) const; - static RigFemResultPosEnum resultPositionType(); - QString resultFieldName() const; - static QString uiFieldName(const QString& fieldName); + std::vector observedResults() const; + static RigFemResultPosEnum resultPositionType(); + QString resultFieldName() const; + static QString uiFieldName(const QString& fieldName); caf::PdmChildField arrowColorLegendConfig; diff --git a/ApplicationCode/UserInterface/RiuMainWindow.cpp b/ApplicationCode/UserInterface/RiuMainWindow.cpp index 603d2f364a..be48bcd6df 100644 --- a/ApplicationCode/UserInterface/RiuMainWindow.cpp +++ b/ApplicationCode/UserInterface/RiuMainWindow.cpp @@ -26,6 +26,10 @@ #include "RiaRegressionTest.h" #include "RiaRegressionTestRunner.h" +#include "RigFemPartCollection.h" +#include "RigFemPartResultsCollection.h" +#include "RigGeoMechCaseData.h" + #include "Rim2dIntersectionView.h" #include "Rim3dView.h" #include "RimCellEdgeColors.h" @@ -54,6 +58,7 @@ #include "RiuRelativePermeabilityPlotPanel.h" #include "RiuResultInfoPanel.h" #include "RiuResultQwtPlot.h" +#include "RiuTextDialog.h" #include "RiuToolTipMenu.h" #include "RiuTreeViewEventFilter.h" #include "RiuViewer.h" @@ -84,6 +89,7 @@ #include #include #include +#include #include #include #include @@ -145,13 +151,17 @@ RiuMainWindow::RiuMainWindow() //caf::CmdExecCommandManager::instance()->enableUndoCommandSystem(true); m_memoryCriticalWarning = new QLabel(""); - m_memoryUsedStatus = new QLabel(""); + m_memoryUsedButton = new QToolButton(nullptr); m_memoryTotalStatus = new QLabel(""); + m_memoryUsedButton->setDefaultAction(caf::CmdFeatureManager::instance()->action("RicShowMemoryCleanupDialogFeature")); + statusBar()->addPermanentWidget(m_memoryCriticalWarning); - statusBar()->addPermanentWidget(m_memoryUsedStatus); + statusBar()->addPermanentWidget(m_memoryUsedButton); statusBar()->addPermanentWidget(m_memoryTotalStatus); + + updateMemoryUsage(); m_memoryRefreshTimer = new QTimer(this); @@ -456,6 +466,8 @@ void RiuMainWindow::createMenus() QMenu* editMenu = menuBar()->addMenu("&Edit"); editMenu->addAction(cmdFeatureMgr->action("RicSnapshotViewToClipboardFeature")); editMenu->addSeparator(); + editMenu->addAction(cmdFeatureMgr->action("RicShowMemoryCleanupDialogFeature")); + editMenu->addSeparator(); editMenu->addAction(cmdFeatureMgr->action("RicEditPreferencesFeature")); connect(editMenu, SIGNAL(aboutToShow()), SLOT(slotRefreshEditActions())); @@ -1732,10 +1744,10 @@ void RiuMainWindow::updateMemoryUsage() m_memoryCriticalWarning->setText(QString("")); } - m_memoryUsedStatus->setText(QString("Physical Memory Used: %1 MiB").arg(currentUsage)); + m_memoryUsedButton->setText(QString("Memory Used: %1 MiB").arg(currentUsage)); m_memoryTotalStatus->setText(QString("Total Physical Memory: %1 MiB").arg(totalPhysicalMemory)); - m_memoryUsedStatus->setStyleSheet(QString("QLabel {color: %1; padding: 0px 5px 0px 0px;}").arg(usageColor.name())); + m_memoryUsedButton->setStyleSheet(QString("QLabel {color: %1; padding: 0px 5px 0px 0px;}").arg(usageColor.name())); m_memoryTotalStatus->setStyleSheet(QString("QLabel {padding: 0px 5px 0px 0px; }")); } diff --git a/ApplicationCode/UserInterface/RiuMainWindow.h b/ApplicationCode/UserInterface/RiuMainWindow.h index b77a0f42eb..d628e2975b 100644 --- a/ApplicationCode/UserInterface/RiuMainWindow.h +++ b/ApplicationCode/UserInterface/RiuMainWindow.h @@ -35,6 +35,7 @@ class QActionGroup; class QMdiSubWindow; +class QToolButton; class QSpinBox; class QTimer; class QUndoView; @@ -183,7 +184,7 @@ private: QMenu* m_windowMenu; QLabel* m_memoryCriticalWarning; - QLabel* m_memoryUsedStatus; + QToolButton* m_memoryUsedButton; QLabel* m_memoryTotalStatus; QTimer* m_memoryRefreshTimer; diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeSelectionEditor.cpp b/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeSelectionEditor.cpp index 2368619cd8..2abd733366 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeSelectionEditor.cpp +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeSelectionEditor.cpp @@ -314,15 +314,20 @@ void PdmUiTreeSelectionEditor::configureAndUpdateUi(const QString& uiConfigName) QModelIndexList indices = allVisibleSourceModelIndices(); if (indices.size() > 0) { - bool allItemsChecked = true; + size_t editableItems = 0u; + size_t checkedEditableItems = 0u; for (auto mi : indices) { - if (m_model->data(mi, Qt::CheckStateRole).toBool() == false) + if (!m_model->isReadOnly(mi)) { - allItemsChecked = false; + editableItems++; + if (m_model->isChecked(mi)) + { + checkedEditableItems++; + } } } - + bool allItemsChecked = (editableItems > 0u && checkedEditableItems == editableItems); m_toggleAllCheckBox->setChecked(allItemsChecked); } } diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeSelectionQModel.cpp b/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeSelectionQModel.cpp index 148aa126d4..96d991afee 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeSelectionQModel.cpp +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeSelectionQModel.cpp @@ -108,14 +108,22 @@ void caf::PdmUiTreeSelectionQModel::setCheckedStateForItems(const QModelIndexLis { for (auto mi : sourceModelIndices) { - selectedIndices.insert(static_cast(optionIndex(mi))); + const caf::PdmOptionItemInfo* optionItemInfo = optionItem(mi); + if (!optionItemInfo->isReadOnly()) + { + selectedIndices.insert(static_cast(optionIndex(mi))); + } } } else { for (auto mi : sourceModelIndices) { - selectedIndices.erase(static_cast(optionIndex(mi))); + const caf::PdmOptionItemInfo* optionItemInfo = optionItem(mi); + if (!optionItemInfo->isReadOnly()) + { + selectedIndices.erase(static_cast(optionIndex(mi))); + } } } @@ -194,6 +202,22 @@ void caf::PdmUiTreeSelectionQModel::resetUiValueCache() m_uiValueCache = nullptr; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool caf::PdmUiTreeSelectionQModel::isReadOnly(const QModelIndex& index) const +{ + return optionItem(index)->isReadOnly(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool caf::PdmUiTreeSelectionQModel::isChecked(const QModelIndex& index) const +{ + return data(index, Qt::CheckStateRole).toBool(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeSelectionQModel.h b/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeSelectionQModel.h index 9b4191a793..e0c80f3cd8 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeSelectionQModel.h +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeSelectionQModel.h @@ -71,6 +71,8 @@ public: void setOptions(caf::PdmUiFieldEditorHandle* field, const QList& options); void setUiValueCache(const QVariant* uiValuesCache ); void resetUiValueCache(); + bool isReadOnly(const QModelIndex& index) const; + bool isChecked(const QModelIndex& index) const; virtual Qt::ItemFlags flags(const QModelIndex &index) const override; virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;