SWMMVis  6.0.0-alpha.4
Qt6/C++ GIS-based graphical user interface for the SWMMVis engine (6.0.0-alpha.4)
Loading...
Searching...
No Matches
simulationrunner.h
Go to the documentation of this file.
1
7#ifndef SIMULATIONRUNNER_H
8#define SIMULATIONRUNNER_H
9
10#include <QDateTime>
11#include <QObject>
12#include <QString>
13#include <QVector>
14#include <atomic>
15
30class SimulationRunner : public QObject
31{
32 Q_OBJECT
33
34public:
35 explicit SimulationRunner(int jobId,
36 const QString &instanceName,
37 const QString &inpPath,
38 const QString &rptPath,
39 const QString &outPath,
40 const QString &engineVersion = "6.0.0",
41 QObject *parent = nullptr);
42
44 void start();
45
53 void cancel();
54
57 void setPaused(bool paused);
58 bool isPaused() const { return m_paused.load(); }
59
60 int jobId() const { return m_jobId; }
61 QString outPath() const { return m_outPath; }
62 QString inpPath() const { return m_inpPath; }
63
76 [[nodiscard]] static QString parseTwoDOutputFile(const QString &inpPath);
77
86 [[nodiscard]] static QString parseTwoDOption(const QString &inpPath,
87 const QString &key);
88
89signals:
90 void started(int jobId);
91
98 void simulationDatesKnown(int jobId, QDateTime start, QDateTime end);
112 void progressChanged(int jobId, double fraction, QDateTime currentSimDate,
113 double runoffErrFrac, double routingErrFrac,
114 double avgTimestepSec, double twoDErrFrac);
115 void warningReceived(int jobId, int code, QString message);
122 void finished(int jobId, bool success, int errorCode, QString errorMessage,
123 double runoffErrFrac, double routingErrFrac,
124 double twoDErrFrac);
136 void twoDSolverStats(int jobId, QString backend, int momentum, int ltsTiers,
137 qint64 steps, QVector<qint64> tierCells);
138
139 // ── Slice CF.MVP — 2D inundation viz hooks ─────────────────────────────
140 //
141 // Emitted once the engine has initialised and 2D is active. Carries the
142 // mesh geometry queried via `swmm_2d_*` on the worker thread (read-only
143 // calls; safe to make there because the engine's 2D mesh is immutable
144 // after SurfaceRouter2D::initialize). The GUI builds an
145 // EngineMesh2DSource from these vectors and attaches a
146 // SWMM2DResultsLayer to the canvas.
147 //
148 // `cellFlat` is cell connectivity flattened to [v0,v1,v2,v3, v0,v1,v2,v3,
149 // …] — FOUR ints per cell (size = cellCount * 4), v3 = -1 for a triangle
150 // (mixed triangle/quad meshes, workplans/TRI_QUAD_MESHING_PLAN_2026-09-06.md)
151 // — so it ships as a single QVector<int> (a registered Qt metatype).
152 // Cells are in the engine's order (triangles first, then quads); a
153 // quad's vertices are in cyclic order.
154 void twoDInitialized(int jobId, QString h5Path,
155 QVector<double> vx,
156 QVector<double> vy,
157 QVector<double> vz,
158 QVector<int> cellFlat);
159
160 // Per-tick depth slice from swmm_2d_get_depths_bulk. Rate-limited to the
161 // existing kTickIntervalMs budget (≈ 1 Hz). The GUI pushes each slice
162 // into the active EngineMesh2DSource and refreshes the layer.
163 void twoDDepthsAvailable(int jobId, QVector<float> depths,
164 QDateTime simTime, double elapsedSec);
165
166 // ── Slice CF.2 — velocity vector overlay hooks ─────────────────────────
167 //
168 // Emitted once at twoDInitialized after the engine builds its mesh, this
169 // ships the time-invariant edge geometry (length + outward unit normal,
170 // both indexed [cell*4 + localEdge] = mesh::edgeSlot, sized
171 // mesh::edgeSlotCount(cellCount); the engine's own stride (3 or 4,
172 // swmm_2d_edge_stride) is repacked before emission — slot 3 of a
173 // triangle is 0). The GUI installs the arrays on the
174 // active EngineMesh2DSource so client-side RT0 reconstruction has
175 // everything it needs without re-deriving from vertex coords.
177 QVector<float> length,
178 QVector<float> nx,
179 QVector<float> ny);
180
181 // Per-tick signed edge flux from swmm_2d_get_edge_flux_bulk, repacked to
182 // the same [cell*4 + localEdge] layout as twoDEdgeGeometryAvailable. Same
183 // cadence as twoDDepthsAvailable; pushed into EngineMesh2DSource::pushFlux
184 // on the GUI thread, paired with the matching depth tick by elapsedSec.
185 void twoDFluxAvailable(int jobId, QVector<float> flux,
186 QDateTime simTime, double elapsedSec);
187
188 // Per-tick rainfall intensity (m/s) + cumulative rainfall volume (m³)
189 // per cell from swmm_2d_get_rainfall_bulk / swmm_2d_get_rain_volume_bulk.
190 // Same cadence/pairing as twoDFluxAvailable; pushed into
191 // EngineMesh2DSource::pushRainfall so the Rainfall / Rainfall volume
192 // cell series are plottable live.
193 void twoDRainfallAvailable(int jobId, QVector<float> rainfall,
194 QVector<float> rainCum,
195 QDateTime simTime, double elapsedSec);
196
197 // Per-tick SIGNED vertex render depths from
198 // swmm_2d_vertex_get_render_depths_bulk (the engine's wet-masked,
199 // depth-weighted η_v − z_v reconstruction — dry-cell bed elevations never
200 // contribute). Same cadence/pairing as twoDFluxAvailable; pushed into
201 // EngineMesh2DSource::pushVertexSignedDepths. Negative values carry the
202 // sub-cell shoreline intercept and must not be clamped.
203 void twoDVertexDepthsAvailable(int jobId, QVector<double> vdepths,
204 QDateTime simTime, double elapsedSec);
205
206 // Per-tick per-cell water-surface elevation (m) from
207 // swmm_2d_get_heads_bulk. Same cadence/pairing as twoDFluxAvailable;
208 // pushed into EngineMesh2DSource::pushHeads so a mid-run export writes
209 // the solver's head rather than a depth + bed approximation.
210 void twoDHeadsAvailable(int jobId, QVector<float> heads,
211 QDateTime simTime, double elapsedSec);
212
213 // Per-tick cumulative per-cell maxima (m, m/s) from
214 // swmm_2d_get_stat_max_depths / swmm_2d_get_stat_max_velocities — the
215 // live ENVELOPES. Monotone, so no time stamp: the receiver keeps the
216 // newest payload only (EngineMesh2DSource::setEnvelopes).
217 void twoDEnvelopesAvailable(int jobId, QVector<float> maxDepth,
218 QVector<float> maxVel);
219
220private:
221 // Warning callback — fires on the worker thread during engine
222 // open/initialize, posts back via QMetaObject::invokeMethod. The
223 // engine's progress callback is only invoked once (in initialize), so
224 // progress is polled inline in the step loop instead, not through a
225 // registered callback.
226 static void warningCallback(void* engine, int code, const char *msg, void *ud);
227
228 int m_jobId;
229 QString m_instanceName;
230 QString m_inpPath;
231 QString m_rptPath;
232 QString m_outPath;
233 QString m_engineVersion;
234
235 std::atomic<bool> m_cancel{false};
236 std::atomic<bool> m_paused{false};
237 // Back-pressure for the per-tick 2D payload bundle (depths, flux,
238 // rainfall, vertex depths — several MB per tick on a big mesh). Counts
239 // bundles posted to the GUI thread and not yet consumed; the worker
240 // skips a tick's bundle while two are still queued, so a GUI thread that
241 // falls behind never accumulates an unbounded event queue.
242 std::atomic<int> m_pending2DTicks{0};
243};
244
245#endif // SIMULATIONRUNNER_H
Runs a single SWMM simulation on a worker thread and emits live progress, warnings,...
Definition simulationrunner.h:31
void progressChanged(int jobId, double fraction, QDateTime currentSimDate, double runoffErrFrac, double routingErrFrac, double avgTimestepSec, double twoDErrFrac)
Per-tick progress signal emitted from the step loop.
int jobId() const
Definition simulationrunner.h:60
void setPaused(bool paused)
Definition simulationrunner.cpp:1185
void twoDEnvelopesAvailable(int jobId, QVector< float > maxDepth, QVector< float > maxVel)
static QString parseTwoDOption(const QString &inpPath, const QString &key)
Scan a .inp for a [2D_OPTIONS] key and return its value as a QString verbatim (empty when absent).
Definition simulationrunner.cpp:195
void twoDInitialized(int jobId, QString h5Path, QVector< double > vx, QVector< double > vy, QVector< double > vz, QVector< int > cellFlat)
void warningReceived(int jobId, int code, QString message)
void cancel()
Request early termination. Step-loop exits at the next iteration; swmm_engine_end + swmm_engine_repor...
Definition simulationrunner.cpp:1178
void twoDFluxAvailable(int jobId, QVector< float > flux, QDateTime simTime, double elapsedSec)
void finished(int jobId, bool success, int errorCode, QString errorMessage, double runoffErrFrac, double routingErrFrac, double twoDErrFrac)
void twoDSolverStats(int jobId, QString backend, int momentum, int ltsTiers, qint64 steps, QVector< qint64 > tierCells)
2D solver telemetry (swmm_2d_get_run_stats), emitted once after start and with every progress tick of...
static QString parseTwoDOutputFile(const QString &inpPath)
Scan a .inp for [2D_OPTIONS] OUTPUT_FILE and return the resolved absolute path of the 2D HDF5 output ...
Definition simulationrunner.cpp:223
void twoDEdgeGeometryAvailable(int jobId, QVector< float > length, QVector< float > nx, QVector< float > ny)
void twoDRainfallAvailable(int jobId, QVector< float > rainfall, QVector< float > rainCum, QDateTime simTime, double elapsedSec)
void twoDHeadsAvailable(int jobId, QVector< float > heads, QDateTime simTime, double elapsedSec)
void started(int jobId)
void start()
Definition simulationrunner.cpp:324
void simulationDatesKnown(int jobId, QDateTime start, QDateTime end)
Emitted once the engine is initialised and its OPTIONS section has been parsed. Carries the engine-si...
void twoDVertexDepthsAvailable(int jobId, QVector< double > vdepths, QDateTime simTime, double elapsedSec)
QString inpPath() const
Definition simulationrunner.h:62
bool isPaused() const
Definition simulationrunner.h:58
void twoDDepthsAvailable(int jobId, QVector< float > depths, QDateTime simTime, double elapsedSec)
QString outPath() const
Definition simulationrunner.h:61
int code
Definition heatconfigdialog.cpp:40
std::vector< double > nx
Definition mesh2dresultsexport.cpp:448
std::vector< double > ny
Definition mesh2dresultsexport.cpp:448
std::vector< std::vector< float > > steps
one per selected time step
Definition mesh2dresultsexport.cpp:295
const char * key
Definition meshcellparams.cpp:24
double length
Definition meshpatch.cpp:64
QVector< int > parent
union-find
Definition pslgminsize.cpp:176
QString message
Definition queryparser.cpp:150