Files
ResInsight/ApplicationLibCode/ProjectDataModel/RimRoffCaseSumo.h
T
Jørgen Herje 52f9cdf777 Add Polygons data from Cloud (#14811)
Add fetch og polygons from cloud using ri-cloud-api service as submodule

Current version of submodule fetches polygons from Sumo, prodviding polygons with standard results tag.
2026-09-30 18:16:00 +02:00

175 lines
8.0 KiB
C++

/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2024 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "RimEclipseCase.h"
#include "Cloud/RiaSumoGrid.h"
#include "cafPdmField.h"
#include "cafPdmPtrField.h"
#include "cvfObject.h"
#include <QPointer>
#include <QString>
#include <memory>
#include <optional>
#include <utility>
class RiaSumoConnector;
class RifReaderSumoGridProperty;
class RimSumoDataSource;
namespace caf
{
class ProgressInfo;
}
//==================================================================================================
//
// Eclipse grid case backed by a roff grid stored on Sumo. The grid geometry is downloaded as a
// blob through RiaSumoConnector and parsed in memory, so there is no grid file on disk.
//
//==================================================================================================
class RimRoffCaseSumo : public RimEclipseCase
{
CAF_PDM_HEADER_INIT;
public:
RimRoffCaseSumo();
~RimRoffCaseSumo() override;
// Create a grid case for a single realization of the given grid, linked back to the data source
// so the case can be updated when the data source realization filter changes.
static RimRoffCaseSumo* createFromDataSource( RimSumoDataSource* dataSource, const QString& gridName, int realization );
void setSumoDataSource( RimSumoDataSource* dataSource );
void setSumoCaseId( const QString& sumoCaseId );
void setEnsembleName( const QString& ensembleName );
void setGridName( const QString& gridName );
void setRealization( int realization );
QString gridName() const;
int realization() const;
// Data source this case was created from -- used to check whether a view's case belongs to
// the same Sumo case/ensemble before auto-following that view's realization. See
// RimPolygonCloudSource::resolveViewMatchingRealization.
RimSumoDataSource* dataSource() const;
bool openEclipseGridFile() override;
void closeReservoirCase() override;
// Aborts any transfers still in flight for this realization, without discarding already loaded grid and
// result data. Used when switching away from this case in a view while it may still be shown elsewhere,
// so a still loading realization does not keep competing for bandwidth with a newly selected one, while a
// fully loaded realization is not forced through a full reload if switched back to.
void cancelPendingTransfers();
// Fetches and stores exactly the given time steps of a dynamic property, in parallel, without pulling in
// the rest of the time series. See RifReaderSumoGridProperty::prefetchDynamicResult.
bool prefetchDynamicResult( const QString& resultName, const std::vector<size_t>& stepIndices ) override;
QString locationOnDisc() const override;
QString dataLoadingText() const override;
protected:
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
private:
// Download the roff grid blob for this realization and parse it into the case data.
bool downloadAndParseGrid();
// Register the results and attach the property reader. Shared by the two ways the grid can end up on
// this case: parsed and kept, or parsed and replaced by the grid shared with the other realizations.
void finalizeCaseSetup();
// Discover the available grid properties from Sumo, register them as cell results and attach a reader
// that fetches the property data on demand. Static properties only in this first version.
void registerSumoGridProperties();
// Start the transfer of the property time step about to be displayed. Called before the grid download so
// the two run in parallel; only the decode needs the grid.
//
// The values go to the reader, which does not exist yet at this point. That is safe: arrivals come through
// the event loop, and runOnTransferThreadBlocking holds the grid download on a semaphore without
// dispatching events, so nothing lands before the case is set up.
void startPropertyFetch();
// The property and time step a view of this case is about to show. False when no view has picked one yet,
// leaving the on demand path to fetch whatever is asked for.
bool propertyToFetch( QString& propertyName, size_t& stepIndex, QString& isoDateOrInterval ) const;
// Callbacks handed to m_propertyReader, so the reader itself stays free of GUI code. Shows the loading
// banner and status bar message, and redraws the views once a time step has arrived.
void onPropertyPendingChanged( const QString& message );
void onPropertyTimeStepArrived( const QString& propertyName, size_t stepIndex, bool ok );
// Turns the reader's plain completed/total/description numbers into an actual progress dialog: opens one
// the first time total is non-zero (or replaces it with a freshly-sized one if total grew while a dialog
// was already open - caf::ProgressInfo's maximum cannot change after construction), ticks it as completed
// grows, and closes it once total is reported back as 0.
void onPropertyBatchProgressChanged( size_t completed, size_t total, const QString& description );
// Redraw the views of this case, so arrived values become visible.
void scheduleRedrawOfViews();
private:
caf::PdmPtrField<RimSumoDataSource*> m_sumoDataSource;
caf::PdmField<QString> m_sumoCaseId;
caf::PdmField<QString> m_ensembleName;
caf::PdmField<QString> m_gridName;
caf::PdmField<int> m_realization;
QPointer<RiaSumoConnector> m_sumoConnector;
// The same reader the cell results hold, set in registerSumoGridProperties. Time steps fetched before it
// existed are handed to it.
cvf::ref<RifReaderSumoGridProperty> m_propertyReader;
// The properties Sumo reports for this realization. Fetched before the grid and reused when they are
// registered, so the request is made once.
std::vector<SumoGridPropertyInfo> m_propertyInfos;
// The time step startPropertyFetch put in flight, until the reader exists and takes it over. Handed to
// the reader as pending so it is reported to the user and not requested a second time.
std::optional<std::pair<QString, size_t>> m_fetchInFlight;
// Identifies the transfer startPropertyFetch issues before the reader (and its own lifetime token) exists,
// so it can still be cancelled from closeReservoirCase. Recreated on every close, so a transfer left over
// from a previous open is never cancelled by a later one.
std::shared_ptr<bool> m_lifetimeToken;
// A redraw can read another time step and arrive back here through the reader's callback. Coalesce
// rather than recurse.
bool m_isRedrawingViews = false;
bool m_hasMissedViewRedraw = false;
// One single dialog for however many time steps the reader currently has pending, so waiting for a run
// of single steps in a row does not pop open and close a new dialog for each one. Owned here rather than
// in the reader itself, which reports only plain numbers via onPropertyBatchProgressChanged - no GUI code
// lives in RifReaderSumoGridProperty. Null when nothing is pending.
std::unique_ptr<caf::ProgressInfo> m_batchProgress;
size_t m_batchProgressShownTotal = 0; // What m_batchProgress was actually constructed with.
};