Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

start implementation #114

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions Tests/simulationEngines/hecras/test_hecras.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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() );
}
Expand Down Expand Up @@ -495,7 +495,9 @@ void ReosHecrasTesting::createAndWriteGridFromScratch()
QDateTime( QDate( 2005, 05, 01 ), QTime( 12, 35, 0 ), Qt::UTC ) );

ReosRasterMemory<double> frame2( 30, 30 );
frame2.reserveMemory();
frame2.reserveMemory

();
frame2.fill( 0 );
for ( int i = 5; i < 25; ++i )
for ( int j = 5; j < 25; j++ )
Expand Down Expand Up @@ -917,6 +919,7 @@ void ReosHecrasTesting::importAndLaunchStructure()
if ( !versions.isEmpty() )
{
ReosHecRasController controller( versions.last() );
controller.initialize();

QVERIFY( controller.isValid() );

Expand All @@ -928,8 +931,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() );
}
Expand Down
26 changes: 19 additions & 7 deletions src/core/hydraulicNetwork/simulation/reoshydraulicsimulation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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() );

Expand Down Expand Up @@ -321,10 +319,10 @@ ReosSimulationProcess::ReosSimulationProcess(
}

qRegisterMetaType< QList<double> >( "QList<double>" );
connect( this, &ReosSimulationProcess::sendBoundaryFlow, this, &ReosSimulationProcess::onReceiveFlow );
connect( this, &ReosSimulationProcess::sendBoundariesFlow, this, &ReosSimulationProcess::onReceiveFlowValueFromBoundaries );
}

void ReosSimulationProcess::onReceiveFlow( QDateTime time, QStringList boundaryIds, QList<double> values )
void ReosSimulationProcess::onReceiveFlowValueFromBoundaries( const QDateTime &time, const QStringList &boundaryIds, const QList<double> &values )
{
for ( int i = 0; i < boundaryIds.count(); ++i )
{
Expand All @@ -335,6 +333,20 @@ void ReosSimulationProcess::onReceiveFlow( QDateTime time, QStringList boundaryI
}
}

void ReosSimulationProcess::onReceiveFlowValuesFromBoundary( const QString &boundaryId, const QList<QDateTime> &times, const QList<double> &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<QString, ReosHydrograph *> ReosSimulationProcess::outputHydrographs() const
{
return mOutputHydrographs;
Expand Down
10 changes: 7 additions & 3 deletions src/core/hydraulicNetwork/simulation/reoshydraulicsimulation.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,14 @@ class REOSCORE_EXPORT ReosSimulationProcess : public ReosProcess
ReosTimeWindow timeWindow() const;

signals:
void sendBoundaryFlow( QDateTime time, QStringList boundaryIds, QList<double> values );
void sendBoundariesFlow( const QDateTime &time, const QStringList &boundaryIds, const QList<double> &values );

private slots:
void onReceiveFlow( QDateTime time, QStringList boundaryIds, QList<double> 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<double> &values );

//! Receives flow from runing simumation for one boundaryId, with several values
void onReceiveFlowValuesFromBoundary(const QString &boundaryId, const QList<QDateTime> &times, const QList<double> &values );

private:
QMap<QString, ReosHydrograph *> mOutputHydrographs;
Expand Down
2 changes: 2 additions & 0 deletions src/dataProviders/hec-dss/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 8 additions & 1 deletion src/dataProviders/hec-dss/reosdssfile.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,14 @@ class REOSDSS_EXPORT ReosDssFile
bool pathExist( const ReosDssPath &path, bool considerInterval ) const;

bool getSeries( const ReosDssPath &path, QVector<double> &values, ReosDuration &timeStep, QDateTime &startTime ) const;
bool getSeries(const ReosDssPath &path, const ReosTimeWindow &timeWindow, QVector<double> &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<double> &values, ReosDuration &timeStep, QDateTime &startTime ) const;

bool gridMinMax( const ReosDssPath &path, double &min, double &max ) const;

Expand Down
8 changes: 8 additions & 0 deletions src/dataProviders/hec-dss/reosdsswatcher.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#include "reosdsswatcher.h"



void ReosDssWatcher::setTimeWatchingTimeWindow( const ReosTimeWindow &timeWatchingTimeWindow )
{
mTimeWatchingTimeWindow = timeWatchingTimeWindow;
}
133 changes: 133 additions & 0 deletions src/dataProviders/hec-dss/reosdsswatcher.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
#ifndef REOSDSSWATCHER_H
#define REOSDSSWATCHER_H

#include <QObject>
#include <QThread>
#include <QTimer>

#include "reosdssfile.h"

class ReosDssWatcher : public QObject
{
Q_OBJECT
public:
explicit ReosDssWatcher( const QString &filePath, const QList<ReosDssPath> &pathes )
: mFilePath( filePath )
, mPathes( pathes )
{
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( const QString &path, const QDateTime &firstTime, const QList<double> &values, qint64 timeStepMillisec );

private slots:
void watch()
{
for ( const ReosDssPath &path : std::as_const( mPathes ) )
watchForTimeSerie( path );
}

private:
QString mFilePath;
std::unique_ptr<ReosDssFile> mFile;
ReosTimeWindow mTimeWatchingTimeWindow;
QList<ReosDssPath> mPathes;
QTimer mTimer;
int mWatchInterval = 500;

mutable QHash<QString, QDateTime> mLastObtainedTime;

void watchForTimeSerie( const ReosDssPath &path )
{
QVector<double> 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;
QDateTime firstTimeToSend;

if ( lastTimeRecorded.isValid() )
{
timeStepCount = values.count();
firstTimeToSend = startTime;
}
else
{
timeStepCount = static_cast<int>( lastTimeRecorded.msecsTo( lastTimeValue ) / timeStep.valueMilliSecond() );
firstTimeToSend = lastTimeRecorded.addMSecs( timeStep.valueMilliSecond() );
}

mLastObtainedTime.insert( path.string(), lastTimeValue );

QList<double> valuesToSend;
valuesToSend.reserve( timeStepCount );
for ( int i = values.count() - timeStepCount; i < values.count(); ++i )
valuesToSend.append( values.at( i ) );

emit sendValues( path.string(), firstTimeToSend, valuesToSend, timeStep.valueMilliSecond() );
}
}
}

};

class REOSDSS_EXPORT ReosDssWatcherControler : public QObject
{
Q_OBJECT
public:
explicit ReosDssWatcherControler( const QString &dssFilePath, QObject *parent )
: QObject( parent )
, mFilePath( dssFilePath )
{}

~ReosDssWatcherControler()
{
mThread.quit();
mThread.wait();
mWatcher->deleteLater();
}

void addPathToWatch( const ReosDssPath &path )
{
mPathes.append( path );
}

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<double> &values, qint64 timeStepMillisec );

private:
QThread mThread;
QString mFilePath;
QList<ReosDssPath> mPathes;
ReosDssWatcher *mWatcher = nullptr;
};

#endif // REOSDSSWATCHER_H
70 changes: 66 additions & 4 deletions src/simulationEngines/hecras/reoshecrascontroller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 );

Expand Down Expand Up @@ -196,6 +195,10 @@ ReosHecRasController::ReosHecRasController( const QString &version )
#endif
}

ReosHecRasController::ReosHecRasController( const QString &version )
: mVersion( version )
{}

ReosHecRasController::~ReosHecRasController()
{
#ifdef _WIN32
Expand Down Expand Up @@ -340,7 +343,12 @@ QStringList ReosHecRasController::planNames() const
return ret;
}

bool ReosHecRasController::setCurrentPlan( const QString &planName )
void ReosHecRasController::setCurrentPlan( const QString &currentPlan )
{
mCurrentPlan = currentPlan;
}

bool ReosHecRasController::setCurrentPlanPrivate( const QString &planName )
{
bool ok = false;
#ifdef _WIN32
Expand Down Expand Up @@ -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" ) );
Expand Down Expand Up @@ -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;
}
Loading