From b318fc9daa25f321ae957645e259bc9f28b53681 Mon Sep 17 00:00:00 2001 From: vcloarec Date: Wed, 1 Mar 2023 07:50:56 -0400 Subject: [PATCH 1/4] start implementation --- .../simulationEngines/hecras/test_hecras.cpp | 5 +- src/dataProviders/hec-dss/CMakeLists.txt | 2 + src/dataProviders/hec-dss/reosdsswatcher.cpp | 8 ++ src/dataProviders/hec-dss/reosdsswatcher.h | 124 ++++++++++++++++++ .../hecras/reoshecrascontroller.cpp | 70 +++++++++- .../hecras/reoshecrascontroller.h | 68 +++++++--- .../hecras/reoshecrassimulation.cpp | 45 ++----- 7 files changed, 262 insertions(+), 60 deletions(-) create mode 100644 src/dataProviders/hec-dss/reosdsswatcher.cpp create mode 100644 src/dataProviders/hec-dss/reosdsswatcher.h diff --git a/Tests/simulationEngines/hecras/test_hecras.cpp b/Tests/simulationEngines/hecras/test_hecras.cpp index e9d4a4df9..73b24d06b 100644 --- a/Tests/simulationEngines/hecras/test_hecras.cpp +++ b/Tests/simulationEngines/hecras/test_hecras.cpp @@ -917,6 +917,7 @@ void ReosHecrasTesting::importAndLaunchStructure() if ( !versions.isEmpty() ) { ReosHecRasController controller( versions.last() ); + controller.initialize(); QVERIFY( controller.isValid() ); @@ -928,8 +929,8 @@ void ReosHecrasTesting::importAndLaunchStructure() QCOMPARE( plans.at( 0 ), QStringLiteral( "plan_test" ) ); QCOMPARE( plans.at( 1 ), QStringLiteral( "plan_test_2" ) ); - QVERIFY( controller.setCurrentPlan( plans.at( 1 ) ) ); - QVERIFY( controller.setCurrentPlan( plans.at( 0 ) ) ); + QVERIFY( controller.setCurrentPlanPrivate( plans.at( 1 ) ) ); + QVERIFY( controller.setCurrentPlanPrivate( plans.at( 0 ) ) ); QVERIFY( !controller.computeCurrentPlan().isEmpty() ); } diff --git a/src/dataProviders/hec-dss/CMakeLists.txt b/src/dataProviders/hec-dss/CMakeLists.txt index 41ad882ab..1efa190a0 100644 --- a/src/dataProviders/hec-dss/CMakeLists.txt +++ b/src/dataProviders/hec-dss/CMakeLists.txt @@ -4,11 +4,13 @@ SET(REOS_HEC_DSS_SOURCES reosdssutils.cpp reosdssfile.cpp + reosdsswatcher.cpp ) SET(REOS_HEC_DSS_HEADERS reosdssutils.h reosdssfile.h + reosdsswatcher.h ) SET(REOS_PROVIDER_HEC_DSS_SOURCES diff --git a/src/dataProviders/hec-dss/reosdsswatcher.cpp b/src/dataProviders/hec-dss/reosdsswatcher.cpp new file mode 100644 index 000000000..d1881c79f --- /dev/null +++ b/src/dataProviders/hec-dss/reosdsswatcher.cpp @@ -0,0 +1,8 @@ +#include "reosdsswatcher.h" + + + +void ReosDssWatcher::setTimeWatchingTimeWindow( const ReosTimeWindow &timeWatchingTimeWindow ) +{ + mTimeWatchingTimeWindow = timeWatchingTimeWindow; +} diff --git a/src/dataProviders/hec-dss/reosdsswatcher.h b/src/dataProviders/hec-dss/reosdsswatcher.h new file mode 100644 index 000000000..03cf197d4 --- /dev/null +++ b/src/dataProviders/hec-dss/reosdsswatcher.h @@ -0,0 +1,124 @@ +#ifndef REOSDSSWATCHER_H +#define REOSDSSWATCHER_H + +#include +#include +#include + +#include "reosdssfile.h" + +class ReosDssWatcher : public QObject +{ + Q_OBJECT + public: + ReosDssWatcher( const QString &filePath ) + : mFilePath( filePath ) + { + connect( &mTimer, &QTimer::timeout, this, &ReosDssWatcher::watch ); + } + + void startWatch() + { + mFile.reset( new ReosDssFile( mFilePath ) ); + if ( !mFile->isValid() ) + return; + mTimer.start( mWatchInterval ); + } + + void setTimeWatchingTimeWindow( const ReosTimeWindow &newTimeWatchingTimeWindow ); + + signals: + void sendValues( QString path, QList values, qint64 timeStepMillisec ); + + private slots: + void watch() + { + + } + + private: + QString mFilePath; + std::unique_ptr mFile; + ReosTimeWindow mTimeWatchingTimeWindow; + QList mPaths; + QTimer mTimer; + int mWatchInterval = 500; + + QHash mLastObtainedTime; + + void watchForTimeSerie( const ReosDssPath &path ) + { + QVector values; + ReosDuration timeStep; + QDateTime startTime; + mFile->getSeries( path, mTimeWatchingTimeWindow, values, timeStep, startTime ); + + if ( values.count() > 0 ) + { + const QDateTime lastTimeRecorded = mLastObtainedTime.value( path.string() ); + const QDateTime lastTimeValue = startTime.addMSecs( ( values.count() - 1 ) * timeStep.valueMilliSecond() ); + if ( !lastTimeRecorded.isValid() || lastTimeValue > lastTimeRecorded ) + { + int timeStepCount; + if ( lastTimeRecorded.isValid() ) + { + timeStepCount = values.count(); + } + else + { + timeStepCount = lastTimeRecorded.msecsTo( lastTimeValue ) / timeStep.valueMilliSecond(); + } + + mLastObtainedTime.insert( path.string(), lastTimeValue ); + + QList valuesToSend; + valuesToSend.reserve( timeStepCount ); + for ( int i = values.count() - timeStepCount; i < values.count(); ++i ) + { + valuesToSend.append( values.at( i ) ); + } + + emit sendValues( path.string(), valuesToSend, timeStep.valueMilliSecond() ); + } + } + } + +}; + +class ReosDssWatcherControler : public QObject +{ + Q_OBJECT + public: + ReosDssWatcherControler( const QString &dssFilePath ) + : mFilePath( dssFilePath ) + { + + } + + ~ReosDssWatcherControler() + { + mThread.quit(); + mThread.wait(); + mWatcher->deleteLater(); + } + + void startWatching() + { + mWatcher = new ReosDssWatcher( mFilePath ); + QObject::connect( &mThread, &QThread::started, mWatcher, &ReosDssWatcher::startWatch ); + mWatcher->moveToThread( &mThread ); + } + + private slots: + void receiveFlowValues( QString &path, QList values, qint64 timeStepMillisec ) + { + + } + + private: + QThread mThread; + QString mFilePath; + ReosDssWatcher *mWatcher = nullptr; +}; + +#endif // REOSDSSWATCHER_H diff --git a/src/simulationEngines/hecras/reoshecrascontroller.cpp b/src/simulationEngines/hecras/reoshecrascontroller.cpp index 3e4235ac4..186e5071c 100644 --- a/src/simulationEngines/hecras/reoshecrascontroller.cpp +++ b/src/simulationEngines/hecras/reoshecrascontroller.cpp @@ -136,15 +136,14 @@ QStringList ReosHecRasController::availableVersion() return ret; } -ReosHecRasController::ReosHecRasController( const QString &version ) - : mVersion( version ) +void ReosHecRasController::initialize() { #ifdef _WIN32 if ( !SUCCEEDED( CoInitializeEx( nullptr, COINIT_APARTMENTTHREADED ) ) ) return; CLSID ClassID; - QString controllerName = version + QStringLiteral( ".HECRASController" ); + QString controllerName = mVersion + QStringLiteral( ".HECRASController" ); std::wstring controllerString = qStringToWideString( controllerName ); @@ -196,6 +195,10 @@ ReosHecRasController::ReosHecRasController( const QString &version ) #endif } +ReosHecRasController::ReosHecRasController( const QString &version ) + : mVersion( version ) +{} + ReosHecRasController::~ReosHecRasController() { #ifdef _WIN32 @@ -340,7 +343,12 @@ QStringList ReosHecRasController::planNames() const return ret; } -bool ReosHecRasController::setCurrentPlan( const QString &planName ) +void ReosHecRasController::setCurrentPlan( const QString ¤tPlan ) +{ + mCurrentPlan = currentPlan; +} + +bool ReosHecRasController::setCurrentPlanPrivate( const QString &planName ) { bool ok = false; #ifdef _WIN32 @@ -376,6 +384,8 @@ bool ReosHecRasController::setCurrentPlan( const QString &planName ) QStringList ReosHecRasController::computeCurrentPlan() { + setCurrentPlanPrivate( mCurrentPlan ); + QStringList ret; #ifdef _WIN32 DISPID id = mFunctionNames.value( QStringLiteral( "Compute_CurrentPlan" ) ); @@ -671,3 +681,55 @@ bool ReosHecRasController::hideComputationWindow() const #endif return false; } + +void ReosHecRasController::setProjectFileName( const QString &newProjectFileName ) +{ + mProjectFileName = newProjectFileName; +} + +void ReosHecRasController::startComputation() +{ + initialize(); + + if ( !isValid() ) + { + emit sendInformation( tr( "Controller of HEC-RAS found is not valid.\nCalculation cancelled." ) ); + return; + } + + if ( !openHecrasProject( mProjectFileName ) ) + { + emit sendInformation( tr( "UNable to open HEC-RAS project file \"%1\".\nCalculation cancelled." ).arg( mProjectFileName ) ); + return; + } + + QStringList plans = planNames(); + + if ( !plans.contains( mCurrentPlan ) ) + { + emit sendInformation( tr( "Plan \"%1\" not found.\nCalculation cancelled." ).arg( mCurrentPlan ) ); + return; + } + + if ( !setCurrentPlanPrivate( mCurrentPlan ) ) + { + emit sendInformation( tr( "Unable to set plan \"%1\" as current plan.\nCalculation cancelled." ).arg( mCurrentPlan ) ); + return; + } + + showComputationWindow(); + + const QStringList returnedMessages = computeCurrentPlan(); + + for ( const QString &mes : returnedMessages ) + { + emit sendInformation( mes ); + } + + mIsSuccessful = !returnedMessages.isEmpty() && returnedMessages.last() == QStringLiteral( "Computations Completed" ); +} + +bool ReosHecRasController::isSuccessful() const +{ + return mIsSuccessful; +} diff --git a/src/simulationEngines/hecras/reoshecrascontroller.h b/src/simulationEngines/hecras/reoshecrascontroller.h index c19288d4b..fa1f5dcd0 100644 --- a/src/simulationEngines/hecras/reoshecrascontroller.h +++ b/src/simulationEngines/hecras/reoshecrascontroller.h @@ -24,9 +24,12 @@ #include #include +#include -class ReosHecRasController + +class ReosHecRasController : public QObject { + Q_OBJECT public: //! Constructor with \a version of HecRas, \see availableVersion() explicit ReosHecRasController( const QString &version ); @@ -38,42 +41,65 @@ class ReosHecRasController //! Returns whether the controller is valid bool isValid() const; - //! Returns the user-friendly string of the controller version of this instance - QString version() const; + //! Sets the current plan + void setCurrentPlan( const QString ¤tPlan ); - //! Opens a project with path \a projFileName - bool openHecrasProject( const QString &projFileName ); + //! Sets the current project file name + void setProjectFileName( const QString &newProjectFileName ); - //! Returns the plan names of the currently opened project - QStringList planNames() const; + bool isSuccessful() const; - //! Set the current plan - bool setCurrentPlan( const QString &planName ); +public slots: + void startComputation(); - //! Starts computation of the current plan - QStringList computeCurrentPlan(); + signals: + void sendInformation( const QString &info ); - //! Returns the flow 2D area names of the currently opened project - QStringList flowAreas2D() const; + private: + + QString mVersion; + QString mProjectFileName; + QString mCurrentPlan; + bool mIsValid = false; + bool mIsSuccessful = false; +#ifdef _WIN32 + IDispatch *mDispatch = nullptr; + QMap mFunctionNames; +#endif + + bool exitRas() const; + + bool setCurrentPlanPrivate( const QString &planName ); + + //! Initializes the controller before using it. ONce initialized, the controller must be used in the thread where is has been initializd. + void initialize(); //! Returns the domain of the flow area with \a areaName QPolygonF flow2DAreasDomain( const QString &areaName ) const; + //! Returns the flow 2D area names of the currently opened project + QStringList flowAreas2D() const; + + //! Returns the plan names of the currently opened project + QStringList planNames() const; + + //! Returns the user-friendly string of the controller version of this instance + QString version() const; + + //! Opens a project with path \a projFileName + bool openHecrasProject( const QString &projFileName ); + + //! Starts computation of the current plan + QStringList computeCurrentPlan(); + bool showRas() const; bool showComputationWindow() const; bool hideComputationWindow() const; - private: - QString mVersion; - bool mIsValid = false; -#ifdef _WIN32 - IDispatch *mDispatch = nullptr; - QMap mFunctionNames; -#endif + friend class ReosHecrasTesting; - bool exitRas() const; }; diff --git a/src/simulationEngines/hecras/reoshecrassimulation.cpp b/src/simulationEngines/hecras/reoshecrassimulation.cpp index 042f520f3..3964b9f10 100644 --- a/src/simulationEngines/hecras/reoshecrassimulation.cpp +++ b/src/simulationEngines/hecras/reoshecrassimulation.cpp @@ -28,6 +28,7 @@ #include "reosdssprovider.h" #include +#include REOSEXTERN ReosSimulationEngineFactory *engineSimulationFactory() { @@ -1022,16 +1023,6 @@ void ReosHecRasSimulationProcess::start() return; } - std::unique_ptr controller( new ReosHecRasController( mControllerVersion ) ); - - if ( !controller->isValid() ) - { - emit sendInformation( tr( "Controller of HEC-RAS found is not valid.\nCalculation cancelled." ) ); - return; - } - - emit sendInformation( tr( "Start HEC-RAS model calculation with %1." ).arg( controller->version() ) ); - QFileInfo fileProjectInfo( mProject.fileName() ); if ( !fileProjectInfo.exists() ) { @@ -1039,36 +1030,24 @@ void ReosHecRasSimulationProcess::start() return; } - if ( !controller->openHecrasProject( mProject.fileName() ) ) - { - emit sendInformation( tr( "UNable to open HEC-RAS project file \"%1\".\nCalculation cancelled." ).arg( mProject.fileName() ) ); - return; - } + QThread thread; + std::unique_ptr controller( new ReosHecRasController( mControllerVersion ) ); + controller->setCurrentPlan( mPlan.title() ); - QStringList plans = controller->planNames(); + controller->moveToThread( &thread ); - if ( !plans.contains( mPlan.title() ) ) - { - emit sendInformation( tr( "Plan \"%1\" not found.\nCalculation cancelled." ).arg( mPlan.title() ) ); - return; - } + connect( &thread, &QThread::started, controller.get(), &ReosHecRasController::startComputation ); - if ( !controller->setCurrentPlan( mPlan.title() ) ) - { - emit sendInformation( tr( "Unable to set plan \"%1\" as current plan.\nCalculation cancelled." ).arg( mPlan.title() ) ); - return; - } + QEventLoop loop; + connect( &thread, &QThread::finished, &loop, &QEventLoop::quit ); - controller->showComputationWindow(); + thread.start(); - const QStringList returnedMessages = controller->computeCurrentPlan(); + if ( thread.isRunning() ) + loop.exec(); - for ( const QString &mes : returnedMessages ) - { - emit sendInformation( mes ); - } + mIsSuccessful = controller->isSuccessful(); - mIsSuccessful = !returnedMessages.isEmpty() && returnedMessages.last() == QStringLiteral( "Computations Completed" ); } ReosHecRasStructureImporterSource::ReosHecRasStructureImporterSource( const QString &file, const ReosHydraulicNetworkContext &context ) From 962e0da4b2ae2902a0892dfbe6d2b15fd848e134 Mon Sep 17 00:00:00 2001 From: vcloarec Date: Wed, 1 Mar 2023 08:35:46 -0400 Subject: [PATCH 2/4] fix test --- Tests/simulationEngines/hecras/test_hecras.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Tests/simulationEngines/hecras/test_hecras.cpp b/Tests/simulationEngines/hecras/test_hecras.cpp index 73b24d06b..8968fcd77 100644 --- a/Tests/simulationEngines/hecras/test_hecras.cpp +++ b/Tests/simulationEngines/hecras/test_hecras.cpp @@ -155,8 +155,8 @@ void ReosHecrasTesting::getControllerPlans() QCOMPARE( plans.at( 0 ), QStringLiteral( "plan_test" ) ); QCOMPARE( plans.at( 1 ), QStringLiteral( "plan_test_2" ) ); - QVERIFY( controller.setCurrentPlan( plans.at( 1 ) ) ); - QVERIFY( controller.setCurrentPlan( plans.at( 0 ) ) ); + QVERIFY( controller.setCurrentPlanPrivate( plans.at( 1 ) ) ); + QVERIFY( controller.setCurrentPlanPrivate( plans.at( 0 ) ) ); QVERIFY( !controller.computeCurrentPlan().isEmpty() ); } @@ -495,7 +495,9 @@ void ReosHecrasTesting::createAndWriteGridFromScratch() QDateTime( QDate( 2005, 05, 01 ), QTime( 12, 35, 0 ), Qt::UTC ) ); ReosRasterMemory frame2( 30, 30 ); - frame2.reserveMemory(); + frame2.reserveMemory + + (); frame2.fill( 0 ); for ( int i = 5; i < 25; ++i ) for ( int j = 5; j < 25; j++ ) From 3a0cfa1f4b3a6c9672f8b9aaa659e4338bdad0b1 Mon Sep 17 00:00:00 2001 From: vcloarec Date: Wed, 1 Mar 2023 18:10:11 -0400 Subject: [PATCH 3/4] try --- .../simulation/reoshydraulicsimulation.cpp | 26 +++++++--- .../simulation/reoshydraulicsimulation.h | 10 ++-- src/dataProviders/hec-dss/reosdssfile.h | 9 +++- src/dataProviders/hec-dss/reosdsswatcher.h | 51 +++++++++++-------- .../hecras/reoshecrasproject.cpp | 45 ++++++++++++++++ .../hecras/reoshecrasproject.h | 26 ++++------ .../hecras/reoshecrassimulation.cpp | 45 ++++++++++++---- .../hecras/reoshecrassimulation.h | 7 +++ .../hecras/reoshecrassimulationresults.cpp | 10 +--- .../telemac/reostelemac2dsimulation.cpp | 3 +- 10 files changed, 165 insertions(+), 67 deletions(-) diff --git a/src/core/hydraulicNetwork/simulation/reoshydraulicsimulation.cpp b/src/core/hydraulicNetwork/simulation/reoshydraulicsimulation.cpp index b346ef363..2c013fd9d 100644 --- a/src/core/hydraulicNetwork/simulation/reoshydraulicsimulation.cpp +++ b/src/core/hydraulicNetwork/simulation/reoshydraulicsimulation.cpp @@ -255,15 +255,13 @@ void ReosSimulationPreparationProcess::start() } } - QEventLoop *eventLoop = new QEventLoop; - connect( this, &ReosSimulationPreparationProcess::allBoundariesUpdated, eventLoop, &QEventLoop::quit ); + QEventLoop eventLoop; + connect( this, &ReosSimulationPreparationProcess::allBoundariesUpdated, &eventLoop, &QEventLoop::quit ); emit sendInformation( tr( "Wait for %n boundary condition", nullptr, mWaitedBoundaryId.count() ) ); setCurrentProgression( mBoundaryCount - mWaitedBoundaryId.count() ); if ( !mWaitedBoundaryId.isEmpty() ) - eventLoop->exec(); - - eventLoop->deleteLater(); + eventLoop.exec(); mContext.setTimeWindow( mStructure->timeWindow() ); @@ -321,10 +319,10 @@ ReosSimulationProcess::ReosSimulationProcess( } qRegisterMetaType< QList >( "QList" ); - connect( this, &ReosSimulationProcess::sendBoundaryFlow, this, &ReosSimulationProcess::onReceiveFlow ); + connect( this, &ReosSimulationProcess::sendBoundariesFlow, this, &ReosSimulationProcess::onReceiveFlowValueFromBoundaries ); } -void ReosSimulationProcess::onReceiveFlow( QDateTime time, QStringList boundaryIds, QList values ) +void ReosSimulationProcess::onReceiveFlowValueFromBoundaries( const QDateTime &time, const QStringList &boundaryIds, const QList &values ) { for ( int i = 0; i < boundaryIds.count(); ++i ) { @@ -335,6 +333,20 @@ void ReosSimulationProcess::onReceiveFlow( QDateTime time, QStringList boundaryI } } +void ReosSimulationProcess::onReceiveFlowValuesFromBoundary( const QString &boundaryId, const QList ×, const QList &values ) +{ + if ( times.count() != values.count() ) + return; + + ReosHydrograph *hyd = mOutputHydrographs.value( boundaryId ); + if ( !hyd ) + return; + + for ( int i = 0; i < times.count(); ++i ) + hyd->setValue( times.at( i ), values.at( i ) ); +} + + QMap ReosSimulationProcess::outputHydrographs() const { return mOutputHydrographs; diff --git a/src/core/hydraulicNetwork/simulation/reoshydraulicsimulation.h b/src/core/hydraulicNetwork/simulation/reoshydraulicsimulation.h index 5536d7559..0eaaeea2f 100644 --- a/src/core/hydraulicNetwork/simulation/reoshydraulicsimulation.h +++ b/src/core/hydraulicNetwork/simulation/reoshydraulicsimulation.h @@ -106,10 +106,14 @@ class REOSCORE_EXPORT ReosSimulationProcess : public ReosProcess ReosTimeWindow timeWindow() const; signals: - void sendBoundaryFlow( QDateTime time, QStringList boundaryIds, QList values ); + void sendBoundariesFlow( const QDateTime &time, const QStringList &boundaryIds, const QList &values ); - private slots: - void onReceiveFlow( QDateTime time, QStringList boundaryIds, QList values ); + protected slots: + //! Receives flows from runing simumation for n boundaryIds, with one value per boundary + void onReceiveFlowValueFromBoundaries( const QDateTime &time, const QStringList &boundaryIds, const QList &values ); + + //! Receives flow from runing simumation for one boundaryId, with several values + void onReceiveFlowValuesFromBoundary(const QString &boundaryId, const QList ×, const QList &values ); private: QMap mOutputHydrographs; diff --git a/src/dataProviders/hec-dss/reosdssfile.h b/src/dataProviders/hec-dss/reosdssfile.h index f371496fd..35c17ecc7 100644 --- a/src/dataProviders/hec-dss/reosdssfile.h +++ b/src/dataProviders/hec-dss/reosdssfile.h @@ -104,7 +104,14 @@ class REOSDSS_EXPORT ReosDssFile bool pathExist( const ReosDssPath &path, bool considerInterval ) const; bool getSeries( const ReosDssPath &path, QVector &values, ReosDuration &timeStep, QDateTime &startTime ) const; - bool getSeries(const ReosDssPath &path, const ReosTimeWindow &timeWindow, QVector &values, ReosDuration &timeStep, QDateTime &startTime ) const; + + /** + * Gets a DSS time series corresponding to \a path and a \a timeWindow + * \a values will contains the values + * \a timeStep will be the time step of the series + * \a startTime will be the effective start time of the series + */ + bool getSeries( const ReosDssPath &path, const ReosTimeWindow &timeWindow, QVector &values, ReosDuration &timeStep, QDateTime &startTime ) const; bool gridMinMax( const ReosDssPath &path, double &min, double &max ) const; diff --git a/src/dataProviders/hec-dss/reosdsswatcher.h b/src/dataProviders/hec-dss/reosdsswatcher.h index 03cf197d4..653852c5c 100644 --- a/src/dataProviders/hec-dss/reosdsswatcher.h +++ b/src/dataProviders/hec-dss/reosdsswatcher.h @@ -11,8 +11,9 @@ class ReosDssWatcher : public QObject { Q_OBJECT public: - ReosDssWatcher( const QString &filePath ) + explicit ReosDssWatcher( const QString &filePath, const QList &pathes ) : mFilePath( filePath ) + , mPathes( pathes ) { connect( &mTimer, &QTimer::timeout, this, &ReosDssWatcher::watch ); } @@ -28,23 +29,24 @@ class ReosDssWatcher : public QObject void setTimeWatchingTimeWindow( const ReosTimeWindow &newTimeWatchingTimeWindow ); signals: - void sendValues( QString path, QList values, qint64 timeStepMillisec ); + void sendValues( const QString &path, const QDateTime &firstTime, const QList &values, qint64 timeStepMillisec ); private slots: void watch() { - + for ( const ReosDssPath &path : std::as_const( mPathes ) ) + watchForTimeSerie( path ); } private: QString mFilePath; std::unique_ptr mFile; ReosTimeWindow mTimeWatchingTimeWindow; - QList mPaths; + QList mPathes; QTimer mTimer; int mWatchInterval = 500; - QHash mLastObtainedTime; + mutable QHash mLastObtainedTime; void watchForTimeSerie( const ReosDssPath &path ) { @@ -60,13 +62,17 @@ class ReosDssWatcher : public QObject if ( !lastTimeRecorded.isValid() || lastTimeValue > lastTimeRecorded ) { int timeStepCount; + QDateTime firstTimeToSend; + if ( lastTimeRecorded.isValid() ) { timeStepCount = values.count(); + firstTimeToSend = startTime; } else { - timeStepCount = lastTimeRecorded.msecsTo( lastTimeValue ) / timeStep.valueMilliSecond(); + timeStepCount = static_cast( lastTimeRecorded.msecsTo( lastTimeValue ) / timeStep.valueMilliSecond() ); + firstTimeToSend = lastTimeRecorded.addMSecs( timeStep.valueMilliSecond() ); } mLastObtainedTime.insert( path.string(), lastTimeValue ); @@ -74,11 +80,9 @@ class ReosDssWatcher : public QObject QList valuesToSend; valuesToSend.reserve( timeStepCount ); for ( int i = values.count() - timeStepCount; i < values.count(); ++i ) - { valuesToSend.append( values.at( i ) ); - } - emit sendValues( path.string(), valuesToSend, timeStep.valueMilliSecond() ); + emit sendValues( path.string(), firstTimeToSend, valuesToSend, timeStep.valueMilliSecond() ); } } } @@ -89,11 +93,10 @@ class ReosDssWatcherControler : public QObject { Q_OBJECT public: - ReosDssWatcherControler( const QString &dssFilePath ) - : mFilePath( dssFilePath ) - { - - } + explicit ReosDssWatcherControler( const QString &dssFilePath, QObject *parent ) + : QObject( parent ) + , mFilePath( dssFilePath ) + {} ~ReosDssWatcherControler() { @@ -102,22 +105,28 @@ class ReosDssWatcherControler : public QObject mWatcher->deleteLater(); } - void startWatching() + void addPathToWatch( const ReosDssPath &path ) { - mWatcher = new ReosDssWatcher( mFilePath ); - QObject::connect( &mThread, &QThread::started, mWatcher, &ReosDssWatcher::startWatch ); - mWatcher->moveToThread( &mThread ); + mPathes.append( path ); } - private slots: - void receiveFlowValues( QString &path, QList values, qint64 timeStepMillisec ) + public slots: + void startWatching() { - + mWatcher = new ReosDssWatcher( mFilePath, mPathes ); + connect( mWatcher, &ReosDssWatcher::sendValues, this, &ReosDssWatcherControler::sendValues ); + connect( &mThread, &QThread::started, mWatcher, &ReosDssWatcher::startWatch ); + mWatcher->moveToThread( &mThread ); + mThread.start(); } + signals: + void sendValues( const QString &path, const QDateTime &firstime, const QList &values, qint64 timeStepMillisec ); + private: QThread mThread; QString mFilePath; + QList mPathes; ReosDssWatcher *mWatcher = nullptr; }; diff --git a/src/simulationEngines/hecras/reoshecrasproject.cpp b/src/simulationEngines/hecras/reoshecrasproject.cpp index 0a63d590b..d51d56745 100644 --- a/src/simulationEngines/hecras/reoshecrasproject.cpp +++ b/src/simulationEngines/hecras/reoshecrasproject.cpp @@ -1077,6 +1077,20 @@ bool ReosHecRasFlow::applyBoudaryFlow( const QList &flows ) return true; } +void ReosHecRasFlow::activeGriddedPrecipitation( const QString &dssFilePath, const ReosDssPath &dssPath ) +{ + mGriddedPrecipitationActivated = true; + mGriddedPrecipitationFile = dssFilePath; + mGriddedPrecipitationPath = dssPath; +} + +void ReosHecRasFlow::deactivateGriddedPrecipitation() +{ + mGriddedPrecipitationActivated = false; + mGriddedPrecipitationFile.clear(); + mGriddedPrecipitationPath = ReosDssPath(); +} + bool ReosHecRasFlow::isValid() const { return mIsValid; @@ -1315,6 +1329,18 @@ const QString &ReosHecRasBoundaryConditionId::location() const return mLocation; } +ReosDssPath ReosHecRasBoundaryConditionId::dssFlowPath( const ReosHecRasPlan &plan ) const +{ + ReosDssPath path; + path.setGroup( QStringLiteral( "BCLINE" ) ); + path.setVersion( plan.shortIdentifier() ); + path.setParameter( QStringLiteral( "FLOW" ) ); + path.setTimeInterval( plan.outputInterval() ); + path.setLocation( location() + QStringLiteral( ": " ) + name() ); + + return path; +} + const QString &ReosHecRasBoundaryConditionId::name() const { return mName; @@ -1344,6 +1370,20 @@ QString ReosHecRasFlow::BoundaryFlow::id() const return mId.id(); } +ReosDssPath ReosHecRasFlow::BoundaryFlow::buildDssFlowRatePath( const ReosHecRasPlan &plan ) const +{ + ReosDssPath path; + path.setGroup( QStringLiteral( "BCLINE" ) ); + path.setVersion( plan.shortIdentifier() ); + path.setParameter( QStringLiteral( "FLOW" ) ); + path.setTimeInterval( plan.outputInterval() ); + + const QString location = area() + QStringLiteral( ": " ) + boundaryConditionLine(); + path.setLocation( location ); + + return path; +} + ReosHecRasGeometry::BoundaryCondition::BoundaryCondition( const QString &area, const QString &name ) : mId( area, name ) {} @@ -1362,3 +1402,8 @@ QString ReosHecRasGeometry::BoundaryCondition::id() const { return mId.id(); } + +ReosHecRasBoundaryConditionId ReosHecRasGeometry::BoundaryCondition::bcId() const +{ + return mId; +} diff --git a/src/simulationEngines/hecras/reoshecrasproject.h b/src/simulationEngines/hecras/reoshecrasproject.h index d65f577bb..c573ebd86 100644 --- a/src/simulationEngines/hecras/reoshecrasproject.h +++ b/src/simulationEngines/hecras/reoshecrasproject.h @@ -18,6 +18,7 @@ class ReosHecRasSimulation; class ReosMesh; class ReosHydraulicStructure2D; class ReosHydraulicScheme; +class ReosHecRasPlan; struct ReosHydraulicNetworkElementCompatibilty; class ReosHecRasBoundaryConditionId @@ -31,6 +32,8 @@ class ReosHecRasBoundaryConditionId const QString &name() const; const QString &location() const; + ReosDssPath dssFlowPath( const ReosHecRasPlan &plan ) const; + private: QString mLocation; QString mName; @@ -54,6 +57,8 @@ class ReosHecRasGeometry QString name() const; QString id() const; + ReosHecRasBoundaryConditionId bcId() const; + QPointF middlePosition; private: @@ -187,9 +192,10 @@ class ReosHecRasFlow bool isDss = false; QString dssFile; QString dssPath; - QString id() const; + ReosDssPath buildDssFlowRatePath( const ReosHecRasPlan &plan ) const; + private: ReosHecRasBoundaryConditionId mId; }; @@ -211,23 +217,13 @@ class ReosHecRasFlow */ bool applyBoudaryFlow( const QList &flows ); - void activeGriddedPrecipitation( const QString &dssFilePath, const ReosDssPath &dssPath ) - { - mGriddedPrecipitationActivated = true; - mGriddedPrecipitationFile = dssFilePath; - mGriddedPrecipitationPath = dssPath; - } + void activeGriddedPrecipitation( const QString &dssFilePath, const ReosDssPath &dssPath ); - void deactivateGriddedPrecipitation() - { - mGriddedPrecipitationActivated = false; - mGriddedPrecipitationFile.clear(); - mGriddedPrecipitationPath = ReosDssPath(); - } + void deactivateGriddedPrecipitation(); bool isValid() const; -private: + private: QString mFileName; bool mIsValid = false; QString mTitle; @@ -292,7 +288,7 @@ class ReosHecRasProject bool isValid() const; -private: + private: QString mFileName; bool mIsValid = false; QMap mPlans; diff --git a/src/simulationEngines/hecras/reoshecrassimulation.cpp b/src/simulationEngines/hecras/reoshecrassimulation.cpp index 3964b9f10..dc87e70ad 100644 --- a/src/simulationEngines/hecras/reoshecrassimulation.cpp +++ b/src/simulationEngines/hecras/reoshecrassimulation.cpp @@ -15,6 +15,7 @@ ***************************************************************************/ #include "reoshecrassimulation.h" +#include "reosdsswatcher.h" #include "reoshydraulicstructureboundarycondition.h" #include "reoscore.h" #include "reosdssfile.h" @@ -990,15 +991,16 @@ void ReosHecRasSimulation::accordCurrentPlan() mProject->setCurrentPlan( mCurrentPlan ); } -ReosHecRasSimulationProcess::ReosHecRasSimulationProcess( const ReosHecRasProject &hecRasProject, - const QString &planId, - const ReosCalculationContext &context, - const QList &boundaries ) +ReosHecRasSimulationProcess::ReosHecRasSimulationProcess( + const ReosHecRasProject &hecRasProject, + const QString &planId, + const ReosCalculationContext &context, + const QList &boundaries ) : ReosSimulationProcess( context, boundaries ) , mProject( hecRasProject ) , mPlan( hecRasProject.plan( planId ) ) { - QStringList availableVersions = ReosHecRasController::availableVersion(); + const QStringList availableVersions = ReosHecRasController::availableVersion(); ReosSettings settings; if ( settings.contains( QStringLiteral( "/engine/hecras/version" ) ) ) { @@ -1009,6 +1011,17 @@ ReosHecRasSimulationProcess::ReosHecRasSimulationProcess( const ReosHecRasProjec if ( mControllerVersion.isEmpty() && !availableVersions.isEmpty() ) mControllerVersion = availableVersions.last(); + + mWatcher = new ReosDssWatcherControler( mProject.fileName(), this ); + + for ( const ReosHydraulicStructureBoundaryCondition *bc : boundaries ) + { + ReosHecRasBoundaryConditionId bcId( bc->boundaryConditionId() ); + ReosDssPath dssPath = bcId.dssFlowPath( mPlan ); + mBoundariesPathToBoundaryId.insert( dssPath.string(), bc->boundaryConditionId() ); + mWatcher->addPathToWatch( dssPath ); + } + } void ReosHecRasSimulationProcess::start() @@ -1030,19 +1043,17 @@ void ReosHecRasSimulationProcess::start() return; } + QEventLoop loop; QThread thread; std::unique_ptr controller( new ReosHecRasController( mControllerVersion ) ); controller->setCurrentPlan( mPlan.title() ); - controller->moveToThread( &thread ); - connect( &thread, &QThread::started, controller.get(), &ReosHecRasController::startComputation ); - - QEventLoop loop; connect( &thread, &QThread::finished, &loop, &QEventLoop::quit ); - thread.start(); + mWatcher->startWatching(); + if ( thread.isRunning() ) loop.exec(); @@ -1050,6 +1061,20 @@ void ReosHecRasSimulationProcess::start() } +void ReosHecRasSimulationProcess::receiveFlow( const QString &path, const QDateTime &firstTime, const QList &values, qint64 timeStep ) +{ + const QString bcId = mBoundariesPathToBoundaryId.value( path ); + if ( bcId.isEmpty() ) + return; + + QList times; + times.reserve( values.count() ); + for ( int i = 0; i < values.count(); ++i ) + times.append( firstTime.addMSecs( timeStep * i ) ); + + onReceiveFlowValuesFromBoundary( bcId, times, values ); +} + ReosHecRasStructureImporterSource::ReosHecRasStructureImporterSource( const QString &file, const ReosHydraulicNetworkContext &context ) : mHecRasProjectFile( file ) , mNetwork( context.network() ) diff --git a/src/simulationEngines/hecras/reoshecrassimulation.h b/src/simulationEngines/hecras/reoshecrassimulation.h index a509e8de9..b0506c1fa 100644 --- a/src/simulationEngines/hecras/reoshecrassimulation.h +++ b/src/simulationEngines/hecras/reoshecrassimulation.h @@ -24,6 +24,7 @@ class ReosDssPath; class ReosHecRasController; class ReosHecRasStructureImporterSource; +class ReosDssWatcherControler; class ReosHecRasSimulationProcess: public ReosSimulationProcess { @@ -37,10 +38,16 @@ class ReosHecRasSimulationProcess: public ReosSimulationProcess void start(); + private slots: + void receiveFlow( const QString &path, const QDateTime &firstTime, const QList &values, qint64 timeStep ); + private: QString mControllerVersion; ReosHecRasProject mProject; ReosHecRasPlan mPlan; + QMap mBoundariesPathToBoundaryId; + QMap mLastTimeReceived; + ReosDssWatcherControler *mWatcher = nullptr; }; class ReosHecRasSimulation : public ReosHydraulicSimulation diff --git a/src/simulationEngines/hecras/reoshecrassimulationresults.cpp b/src/simulationEngines/hecras/reoshecrassimulationresults.cpp index f348e50eb..05a128876 100644 --- a/src/simulationEngines/hecras/reoshecrassimulationresults.cpp +++ b/src/simulationEngines/hecras/reoshecrassimulationresults.cpp @@ -450,24 +450,16 @@ QMap ReosHecRasSimulationResults::outputHydrographs() QMap ret; - ReosDssPath path; - path.setGroup( QStringLiteral( "BCLINE" ) ); - path.setVersion( plan.shortIdentifier() ); - path.setParameter( QStringLiteral( "FLOW" ) ); - path.setTimeInterval( plan.outputInterval() ); - for ( int i = 0; i < flow.boundariesCount(); ++i ) { const ReosHecRasFlow::BoundaryFlow &hbc = flow.boundary( i ); - const QString location = hbc.area() + QStringLiteral( ": " ) + hbc.boundaryConditionLine(); - path.setLocation( location ); + const ReosDssPath path = hbc.buildDssFlowRatePath( plan ); ReosHydrograph *hyd = new ReosHydrograph( const_cast( this ), QStringLiteral( "dss" ), ReosDssUtils::uri( dssFile, path, ReosTimeWindow( plan.startTime(), plan.endTime() ) ) ); ret.insert( hbc.id(), hyd ); - } return ret; } diff --git a/src/simulationEngines/telemac/reostelemac2dsimulation.cpp b/src/simulationEngines/telemac/reostelemac2dsimulation.cpp index 122634fcc..2460eb5cb 100644 --- a/src/simulationEngines/telemac/reostelemac2dsimulation.cpp +++ b/src/simulationEngines/telemac/reostelemac2dsimulation.cpp @@ -1556,6 +1556,7 @@ void ReosTelemac2DSimulationProcess::extractInformation( const QRegularExpressi { case ReosHydraulicStructureBoundaryCondition::Type::NotDefined: case ReosHydraulicStructureBoundaryCondition::Type::InputFlow: + case ReosHydraulicStructureBoundaryCondition::Type:: DefinedExternally: break; case ReosHydraulicStructureBoundaryCondition::Type::OutputLevel: value = -value; @@ -1564,7 +1565,7 @@ void ReosTelemac2DSimulationProcess::extractInformation( const QRegularExpressi flows.append( value ); } - emit sendBoundaryFlow( mStartTime.addMSecs( qint64( time * 1000 ) ), ids, flows ); + emit sendBoundariesFlow( mStartTime.addMSecs( qint64( time * 1000 ) ), ids, flows ); setCurrentProgression( int( time * 100.0 / mTotalTime ) ); emit sendInformation( timeString ); From 4814b6806df018e0e5b7184ec02181310f6acfdf Mon Sep 17 00:00:00 2001 From: vcloarec Date: Wed, 1 Mar 2023 23:34:14 -0400 Subject: [PATCH 4/4] fix export win --- src/dataProviders/hec-dss/reosdsswatcher.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dataProviders/hec-dss/reosdsswatcher.h b/src/dataProviders/hec-dss/reosdsswatcher.h index 653852c5c..e060f0224 100644 --- a/src/dataProviders/hec-dss/reosdsswatcher.h +++ b/src/dataProviders/hec-dss/reosdsswatcher.h @@ -89,7 +89,7 @@ class ReosDssWatcher : public QObject }; -class ReosDssWatcherControler : public QObject +class REOSDSS_EXPORT ReosDssWatcherControler : public QObject { Q_OBJECT public: