16 const int rc = sqlite3_step(statement);
17 if (rc != SQLITE_DONE) {
18 const std::string error = sqlite3_errmsg(db);
19 sqlite3_reset(statement);
29 const std::string& simulation) {
30 exec(db,
"CREATE TABLE IF NOT EXISTS model_supplement (simulation_id TEXT PRIMARY KEY, "
31 "version INTEGER NOT NULL, sections TEXT NOT NULL)");
32 exec(db,
"CREATE TABLE IF NOT EXISTS model_properties (simulation_id TEXT NOT NULL, "
33 "scope TEXT NOT NULL, object_id TEXT NOT NULL, property TEXT NOT NULL, value TEXT NOT NULL, "
34 "PRIMARY KEY(simulation_id,scope,object_id,property))");
35 auto clear =
prepare(db,
"DELETE FROM model_properties WHERE simulation_id=?");
37 if (sqlite3_step(clear.get()) != SQLITE_DONE)
throw GpkgError(sqlite3_errmsg(db));
38 auto property =
prepare(db,
"INSERT INTO model_properties VALUES (?,?,?,?,?)");
39 auto put = [&](
const std::string& scope,
const std::string& id,
40 const std::string& key,
const auto& value) {
41 std::ostringstream out;
42 out << std::setprecision(17) << value;
43 sqlite3_reset(property.get());
47 if (sqlite3_step(property.get()) != SQLITE_DONE)
throw GpkgError(sqlite3_errmsg(db));
49 auto comments = [&](
const char* scope,
const auto& names,
const auto& values) {
50 for (
int i = 0; i < names.size(); ++i)
51 if (
static_cast<std::size_t
>(i) < values.size())
52 put(scope, names.name_of(i),
"comment", values[i]);
54 put(
"model",
"",
"title_count", ctx.
title_notes.size());
55 for (std::size_t i=0; i<ctx.
title_notes.size(); ++i)
56 put(
"title", std::to_string(i),
"line", ctx.
title_notes[i]);
62 for (
int i = 0; i < ctx.
n_tables(); ++i)
63 put(
"table", ctx.
tables[i].id,
"comment", ctx.
tables[i].comment);
69 std::string name = i < static_cast<int>(s.snowpack_name.size()) ? s.
snowpack_name[i] :
"";
70 if (i <
static_cast<int>(s.snowpack.size()) && s.snowpack[i] >= 0)
77 for (
int i = 0; i < ctx.
n_links(); ++i) {
79 if (row < 0)
continue;
82 put(
"weir",
id,
"cd2", w.cd2[row]);
83 put(
"weir",
id,
"end_contractions", w.end_contractions[row]);
84 put(
"weir",
id,
"can_surcharge",
int(w.can_surcharge[row]));
85 put(
"weir",
id,
"road_width", w.road_width[row]);
86 put(
"weir",
id,
"road_surface",
int(w.road_surface[row]));
87 put(
"weir",
id,
"cd_curve", w.cd_curve[row] >= 0 ? ctx.
tables[w.cd_curve[row]].id :
"");
91 put(
"component",
id,
"configuration", text);
93 std::set<std::string> options;
94 auto keys =
prepare(db,
"SELECT key FROM options WHERE simulation_id=?");
96 while (sqlite3_step(keys.get()) == SQLITE_ROW) options.insert(
column_text(keys.get(), 0));
98 const std::set<std::string> relational = {
99 "TITLE",
"EVAPORATION",
"ADJUSTMENTS",
"RAINGAGES",
"SUBCATCHMENTS",
"SUBAREAS",
"INFILTRATION",
100 "JUNCTIONS",
"VIRTUAL_JUNCTIONS",
"INLET_JUNCTIONS",
"OUTFALLS",
"DIVIDERS",
"STORAGE",
101 "CONDUITS",
"PUMPS",
"ORIFICES",
"WEIRS",
"OUTLETS",
"XSECTIONS",
"LOSSES",
102 "TRANSECTS",
"STREETS",
"INLETS",
"INLET_USAGE",
"2D_NODE_COUPLING",
103 "POLLUTANTS",
"LANDUSES",
"BUILDUP",
"WASHOFF",
"COVERAGES",
"LOADINGS",
"TREATMENT",
104 "INFLOWS",
"DWF",
"RDII",
"HYDROGRAPHS",
"PATTERNS",
"TIMESERIES",
"CURVES",
105 "CONTROLS",
"REPORT",
"MAP",
"COORDINATES",
"VERTICES",
"POLYGONS",
"SYMBOLS",
106 "LID_USAGE",
"LID_NODES",
"LID_NODE_OUTLETS",
"LID_LAYER_TREATMENT",
"LID_RICHARDS",
107 "2D_VERTICES",
"2D_TRIANGLES",
"2D_QUADS",
"2D_VERTEX_NODE_MAP",
"2D_TRIANGLE_NODE_MAP",
108 "2D_BOUNDARY_CONDITIONS",
"2D_EDGE_CONVEYANCE",
"FILES"};
109 const char* destination = sqlite3_db_filename(db,
"main");
111 std::string line, section, previous;
112 std::ostringstream extra;
113 while (std::getline(native, line)) {
114 if (!line.empty() && line.front() ==
'[') {
119 if (words.empty() || relational.contains(section))
continue;
120 if (section ==
"OPTIONS") {
121 const std::string key = words[0];
123 if (options.contains(key) || key ==
"FLOW_ROUTING" || key ==
"FORCE_MAIN_EQUATION" ||
124 key ==
"START_TIME" || key ==
"END_TIME" || key.starts_with(
"REPORT_START_"))
continue;
125 }
else if (section ==
"2D_OPTIONS") {
126 if (options.contains(
"2D_" + words[0]))
continue;
127 }
else if (section ==
"TEMPERATURE") {
128 if (words[0] ==
"TIMESERIES" || words[0] ==
"FILE" || words[0] ==
"WINDSPEED" ||
129 words[0] ==
"SNOWMELT" || words[0] ==
"ADC")
continue;
130 }
else if (section ==
"SNOWPACKS") {
131 if (words.size() < 2 || words[1] !=
"UEB")
continue;
132 }
else if (section ==
"LID_CONTROLS") {
133 if (words.size() < 2 || (words[1] !=
"REMOVALS" && words[1] !=
"DRAIN"))
continue;
135 if (section != previous) { extra <<
'\n' <<
'[' << section <<
"]\n"; previous = section; }
136 extra << line <<
'\n';
138 auto row =
prepare(db,
"INSERT OR REPLACE INTO model_supplement VALUES (?,1,?)");
140 if (sqlite3_step(row.get()) != SQLITE_DONE)
throw GpkgError(sqlite3_errmsg(db));
144 auto exists =
prepare(db,
"SELECT 1 FROM sqlite_master WHERE type='table' AND name='model_supplement'");
145 if (sqlite3_step(exists.get()) != SQLITE_ROW)
return false;
146 auto row =
prepare(db,
"SELECT 1 FROM model_supplement WHERE simulation_id=?");
148 return sqlite3_step(row.get()) == SQLITE_ROW;
152 const std::string& simulation) {
154 auto row =
prepare(db,
"SELECT version,sections FROM model_supplement WHERE simulation_id=?");
156 if (sqlite3_step(row.get()) != SQLITE_ROW)
return;
157 if (
column_int(row.get(), 0) != 1)
throw GpkgError(
"Unsupported model supplement version");
161 std::string line, section;
162 std::vector<std::string> body;
164 if (section.empty())
return;
174 ctx.
warnings.push_back(
"[2D_OPTIONS] ignored: no 2D options storage is attached");
175 else throw GpkgError(
"Unsupported saved model section: " + section);
178 while (std::getline(
input, line)) {
179 if (!line.empty() && line.front() ==
'[') {
180 flush(); section = line.substr(1, line.find(
']') - 1);
181 }
else body.push_back(line);
184 auto props =
prepare(db,
"SELECT scope,object_id,property,value FROM model_properties WHERE simulation_id=?");
186 auto comment = [](
auto& values,
int index,
const std::string& value) {
187 if (index >= 0) {
if (values.size() <= std::size_t(index)) values.resize(index + 1); values[index] = value; }
189 std::map<std::string, std::string> configs;
190 std::map<int, std::string> title;
191 bool hasTitle =
false;
192 while (sqlite3_step(props.get()) == SQLITE_ROW) {
195 if (scope ==
"model" && key ==
"title_count") hasTitle =
true;
196 else if (scope ==
"title") title[std::stoi(
id)] = value;
197 else if (scope ==
"component") { configs[id] = value; }
200 else if (scope ==
"table") {
int i = ctx.
find_table_any(
id);
if (i >= 0) ctx.
tables[i].comment = value; }
201 else if (scope ==
"gage") {
205 }
else if (scope ==
"subcatch") {
208 else if (key ==
"snowpack") {
212 }
else if (scope ==
"pollutant") {
215 else if (key ==
"mwt") ctx.
pollutants.
mwt[i] = std::stod(value);
216 }
else if (scope ==
"weir") {
220 if (key ==
"cd2") w.
cd2[r] = std::stod(value);
221 else if (key ==
"end_contractions") w.end_contractions[r] = std::stod(value);
222 else if (key ==
"can_surcharge") w.can_surcharge[r] = std::stoi(value);
223 else if (key ==
"road_width") w.road_width[r] = std::stod(value);
224 else if (key ==
"road_surface") w.road_surface[r] = std::stoi(value);
225 else if (key ==
"cd_curve") w.cd_curve[r] = ctx.
find_table_any(value);
230 for (
const auto& [index, line] : title) ctx.
title_notes.push_back(line);
RAII wrappers and utilities for SQLite operations in GeoPackage I/O.
Write a SimulationContext to a SWMM .inp file.
The central, reentrant simulation context for the new engine.
Multi-delimiter tokenizer for SWMM input files.
int size() const noexcept
Count names in the ordered vector.
Definition NameIndex.hpp:196
int find(std::string_view name) const noexcept
Look up a borrowed name without allocating a temporary key.
Definition NameIndex.hpp:136
const std::string & name_of(int idx) const
Borrow a registered name by its ordered index.
Definition NameIndex.hpp:186
Runtime-error carrier for owned GeoPackage/SQLite diagnostic text.
Definition GpkgUtils.hpp:45
Definition ExternalContentReader.cpp:50
void read_model_supplement(sqlite3 *db, SimulationContext &ctx, const std::string &simulation)
Definition ModelSupplement.hpp:151
void exec(sqlite3 *db, const std::string &sql)
Execute SQL text and discard all returned rows.
Definition GpkgUtils.hpp:198
bool has_model_supplement(sqlite3 *db, const std::string &simulation)
Definition ModelSupplement.hpp:143
StmtPtr prepare(sqlite3 *db, const std::string &sql)
Prepare the first SQL statement without stepping it.
Definition GpkgUtils.hpp:171
void checked_model_step(sqlite3 *db, sqlite3_stmt *statement)
Definition ModelSupplement.hpp:15
std::string column_text(sqlite3_stmt *stmt, int col)
Copy current-row text using NUL-terminated SQLite conversion.
Definition GpkgUtils.hpp:292
int column_int(sqlite3_stmt *stmt, int col)
Read current-row SQLite numeric conversion as int.
Definition GpkgUtils.hpp:318
void write_model_supplement(sqlite3 *db, const SimulationContext &ctx, const std::string &simulation)
Definition ModelSupplement.hpp:28
void bind_text(sqlite3_stmt *stmt, int col, const std::string &val)
Bind a copied SQL text parameter, discarding SQLite status.
Definition GpkgUtils.hpp:220
std::string modelText(const SimulationContext &ctx, const std::string &anchor, bool internal_units)
Definition InpWriter.cpp:5012
std::map< std::string, std::string > configurations(const SimulationContext &ctx)
Definition NativeModelBundle.hpp:12
void restoreConfigurations(SimulationContext &ctx, const std::map< std::string, std::string > &content)
Definition NativeModelBundle.hpp:32
std::vector< std::string > comments
Object comment from the INP file (';'-prefixed lines immediately above this gage's data row),...
Definition GageData.hpp:314
std::vector< double > scale_factor
Rainfall scaling factor (1.0 = no scaling).
Definition GageData.hpp:218
std::vector< std::string > comments
Object comment from the INP file (';'-prefixed lines immediately above this link's data row),...
Definition LinkData.hpp:432
WeirData weirs
Definition LinkSubtypes.hpp:685
int weir_row(int i) const noexcept
Resolve a base link key into the weir side table.
Definition LinkSubtypes.hpp:928
std::vector< std::string > comments
Object comment from the INP file (lines with a single ';' prefix immediately above this object's data...
Definition NodeData.hpp:592
std::vector< std::string > comments
Object comment from the INP file (';'-prefixed lines immediately above this pollutant's data row),...
Definition PollutantData.hpp:152
std::vector< double > mwt
Molecular weight (g/mol). Used for unit conversions.
Definition PollutantData.hpp:87
twoD::SolverOptions2D * options
Definition SimulationContext.hpp:1008
LinkSubtypes link_subtypes
Relational per-subtype link side-tables (Phase 6) — the link analogue of node_subtypes....
Definition SimulationContext.hpp:588
NameIndex subcatch_names
Subcatchment name → subcatchment index.
Definition SimulationContext.hpp:736
NameIndex node_names
Node name → node index.
Definition SimulationContext.hpp:724
NodeData nodes
All node state and properties.
Definition SimulationContext.hpp:563
TableData tables
All time series and rating curves.
Definition SimulationContext.hpp:714
NameIndex snowpack_names
Definition SimulationContext.hpp:864
GageData gages
All rain gage state and properties.
Definition SimulationContext.hpp:600
NameIndex gage_names
Rain gage name → gage index.
Definition SimulationContext.hpp:742
std::string inp_file_path
Path to the input .inp file (empty if not opened from a file).
Definition SimulationContext.hpp:2039
int n_tables() const noexcept
Number of tables (time series + curves).
Definition SimulationContext.hpp:2377
std::vector< std::string > title_notes
Project title and notes (from [TITLE] section).
Definition SimulationContext.hpp:425
std::vector< std::string > warnings
Accumulated warning messages written to report file.
Definition SimulationContext.hpp:1107
LinkData links
All link state and properties.
Definition SimulationContext.hpp:580
int n_pollutants() const noexcept
Number of pollutants.
Definition SimulationContext.hpp:2369
std::vector< std::pair< std::string, std::vector< std::string > > > embedded_component_sections
Embedded component sections found in the legacy .inp ([REACTION_*] today; other component families as...
Definition SimulationContext.hpp:964
int n_subcatches() const noexcept
Number of subcatchments.
Definition SimulationContext.hpp:2363
int n_links() const noexcept
Number of links.
Definition SimulationContext.hpp:2360
NameIndex link_names
Link name → link index.
Definition SimulationContext.hpp:730
struct openswmm::SimulationContext::TwoDModelIO twod_io
int find_table_any(std::string_view name) const noexcept
Find a named table with time-series precedence.
Definition SimulationContext.hpp:2419
NameIndex pollutant_names
Pollutant name → pollutant index.
Definition SimulationContext.hpp:748
SubcatchData subcatches
All subcatchment state and properties.
Definition SimulationContext.hpp:594
SimulationOptions options
Parsed simulation options (from [OPTIONS] section).
Definition SimulationContext.hpp:452
PollutantData pollutants
Pollutant definitions and per-object quality state.
Definition SimulationContext.hpp:606
double report_start
Report start date/time.
Definition SimulationOptions.hpp:192
std::vector< std::string > snowpack_name
Snow pack name string for deferred resolution.
Definition SubcatchData.hpp:91
std::vector< int > snowpack
Snowpack index for this subcatchment (-1 = none).
Definition SubcatchData.hpp:578
std::vector< std::string > comments
Object comment from the INP file (';'-prefixed lines immediately above this subcatchment's data row),...
Definition SubcatchData.hpp:466
std::vector< double > cd2
End-section discharge coeff (legacy cDisch2)
Definition LinkSubtypes.hpp:470
Central, reentrant simulation context.
Definition SimulationContext.hpp:390