hotstart.c
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | //----------------------------------------------------------------------------- | ||
| 2 | // hotstart.c | ||
| 3 | // | ||
| 4 | // Project: EPA SWMM5 | ||
| 5 | // Version: 5.2 | ||
| 6 | // Date: 11/01/21 (Build 5.2.0) | ||
| 7 | // Author: L. Rossman | ||
| 8 | // | ||
| 9 | // Hot Start file functions. | ||
| 10 | // | ||
| 11 | // A SWMM hot start file contains the state of a SWMM project after | ||
| 12 | // a simulation has been run, allowing it to be used to initialize | ||
| 13 | // a subsequent simulation that picks up where the previous run ended. | ||
| 14 | // | ||
| 15 | // An abridged version of the hot start file (version 2) is available | ||
| 16 | // that contains only variables that appear in the binary output file | ||
| 17 | // (groundwater upper moisture and water table elevation, node depth, | ||
| 18 | // lateral inflow, and quality, and link flow, depth, setting and quality). | ||
| 19 | // | ||
| 20 | // When reading a previously saved hot start file checks are made to | ||
| 21 | // insure the the current SWMM project has the same number of major | ||
| 22 | // components (subcatchments, land uses, nodes, links, and pollutants) | ||
| 23 | // and unit system as does the hot start file. No test is made to | ||
| 24 | // insure that these components are of the same sub-type and maintain | ||
| 25 | // the same order as when the hot start file was created. | ||
| 26 | // | ||
| 27 | // Update History | ||
| 28 | // ============== | ||
| 29 | // Build 5.1.008: | ||
| 30 | // - Storage node hydraulic residence time (HRT) was added to the file. | ||
| 31 | // - Link control settings are now applied when reading a hot start file. | ||
| 32 | // - Runoff read from file assigned to newRunoff property instead of oldRunoff. | ||
| 33 | // - Array indexing bug when reading snowpack state from file fixed. | ||
| 34 | // Build 5.1.011: | ||
| 35 | // - Link control setting bug when reading a hot start file fixed. | ||
| 36 | // Build 5.1.015: | ||
| 37 | // - Support added for multiple infiltration methods within a project. | ||
| 38 | // Build 5.2.5: | ||
| 39 | // - Fixed bug in fwrite count argument when writing of pollutant build-up. | ||
| 40 | //----------------------------------------------------------------------------- | ||
| 41 | #define _CRT_SECURE_NO_DEPRECATE | ||
| 42 | |||
| 43 | #include <stdio.h> | ||
| 44 | #include <stdlib.h> | ||
| 45 | #include <string.h> | ||
| 46 | #include <math.h> | ||
| 47 | #include "headers.h" | ||
| 48 | |||
| 49 | //----------------------------------------------------------------------------- | ||
| 50 | // Local Variables | ||
| 51 | //----------------------------------------------------------------------------- | ||
| 52 | static int fileVersion; | ||
| 53 | |||
| 54 | //----------------------------------------------------------------------------- | ||
| 55 | // External functions (declared in funcs.h) | ||
| 56 | //----------------------------------------------------------------------------- | ||
| 57 | // hotstart_open (called by swmm_start in swmm5.c) | ||
| 58 | // hotstart_close (called by swmm_end in swmm5.c) | ||
| 59 | |||
| 60 | //----------------------------------------------------------------------------- | ||
| 61 | // Function declarations | ||
| 62 | //----------------------------------------------------------------------------- | ||
| 63 | static int openHotstartFile1(void); | ||
| 64 | static int openHotstartFile2(void); | ||
| 65 | static void readRunoff(void); | ||
| 66 | static void saveRunoff(void); | ||
| 67 | static void readRouting(void); | ||
| 68 | static void saveRouting(void); | ||
| 69 | static int readFloat(float *x, FILE* f); | ||
| 70 | static int readDouble(double* x, FILE* f); | ||
| 71 | |||
| 72 | //============================================================================= | ||
| 73 | |||
| 74 | 58 | int hotstart_open() | |
| 75 | { | ||
| 76 | // --- open hot start files | ||
| 77 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 58 times.
|
58 | if ( !openHotstartFile1() ) return FALSE; //input hot start file |
| 78 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 58 times.
|
58 | if ( !openHotstartFile2() ) return FALSE; //output hot start file |
| 79 | 58 | return TRUE; | |
| 80 | } | ||
| 81 | |||
| 82 | //============================================================================= | ||
| 83 | |||
| 84 | 58 | void hotstart_close() | |
| 85 | { | ||
| 86 |
2/2✓ Branch 0 taken 1 time.
✓ Branch 1 taken 57 times.
|
58 | if ( Fhotstart2.file ) |
| 87 | { | ||
| 88 | 1 | saveRunoff(); | |
| 89 | 1 | saveRouting(); | |
| 90 | 1 | fclose(Fhotstart2.file); | |
| 91 | } | ||
| 92 | 58 | } | |
| 93 | |||
| 94 | //============================================================================= | ||
| 95 | |||
| 96 | 58 | int openHotstartFile1() | |
| 97 | // | ||
| 98 | // Input: none | ||
| 99 | // Output: none | ||
| 100 | // Purpose: opens a previously saved routing hotstart file. | ||
| 101 | // | ||
| 102 | { | ||
| 103 | int nSubcatch; | ||
| 104 | int nNodes; | ||
| 105 | int nLinks; | ||
| 106 | int nPollut; | ||
| 107 | int nLandUses; | ||
| 108 | int flowUnits; | ||
| 109 | 58 | char fStamp[] = "SWMM5-HOTSTART"; | |
| 110 | 58 | char fileStamp[] = "SWMM5-HOTSTART"; | |
| 111 | 58 | char fStampx[] = "SWMM5-HOTSTARTx"; | |
| 112 | 58 | char fileStamp2[] = "SWMM5-HOTSTART2"; | |
| 113 | 58 | char fileStamp3[] = "SWMM5-HOTSTART3"; | |
| 114 | 58 | char fileStamp4[] = "SWMM5-HOTSTART4"; | |
| 115 | |||
| 116 | // --- try to open the file | ||
| 117 |
2/2✓ Branch 0 taken 57 times.
✓ Branch 1 taken 1 time.
|
58 | if ( Fhotstart1.mode != USE_FILE ) return TRUE; |
| 118 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
|
1 | if ( (Fhotstart1.file = fopen(Fhotstart1.name, "r+b")) == NULL) |
| 119 | { | ||
| 120 | ✗ | report_writeErrorMsg(ERR_HOTSTART_FILE_OPEN, Fhotstart1.name); | |
| 121 | ✗ | return FALSE; | |
| 122 | } | ||
| 123 | |||
| 124 | // --- check that file contains proper header records | ||
| 125 | 1 | fread(fStampx, sizeof(char), strlen(fileStamp2), Fhotstart1.file); | |
| 126 |
1/2✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
|
1 | if ( strcmp(fStampx, fileStamp4) == 0 ) fileVersion = 4; |
| 127 | ✗ | else if ( strcmp(fStampx, fileStamp3) == 0 ) fileVersion = 3; | |
| 128 | ✗ | else if ( strcmp(fStampx, fileStamp2) == 0 ) fileVersion = 2; | |
| 129 | else | ||
| 130 | { | ||
| 131 | ✗ | rewind(Fhotstart1.file); | |
| 132 | ✗ | fread(fStamp, sizeof(char), strlen(fileStamp), Fhotstart1.file); | |
| 133 | ✗ | if ( strcmp(fStamp, fileStamp) != 0 ) | |
| 134 | { | ||
| 135 | ✗ | report_writeErrorMsg(ERR_HOTSTART_FILE_FORMAT, ""); | |
| 136 | ✗ | return FALSE; | |
| 137 | } | ||
| 138 | ✗ | fileVersion = 1; | |
| 139 | } | ||
| 140 | |||
| 141 | 1 | nSubcatch = -1; | |
| 142 | 1 | nNodes = -1; | |
| 143 | 1 | nLinks = -1; | |
| 144 | 1 | nPollut = -1; | |
| 145 | 1 | nLandUses = -1; | |
| 146 | 1 | flowUnits = -1; | |
| 147 |
1/2✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
|
1 | if ( fileVersion >= 2 ) |
| 148 | { | ||
| 149 | 1 | fread(&nSubcatch, sizeof(int), 1, Fhotstart1.file); | |
| 150 | } | ||
| 151 | ✗ | else nSubcatch = Nobjects[SUBCATCH]; | |
| 152 |
1/2✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
|
1 | if ( fileVersion >= 3 ) |
| 153 | { | ||
| 154 | 1 | fread(&nLandUses, sizeof(int), 1, Fhotstart1.file); | |
| 155 | } | ||
| 156 | ✗ | else nLandUses = Nobjects[LANDUSE]; | |
| 157 | 1 | fread(&nNodes, sizeof(int), 1, Fhotstart1.file); | |
| 158 | 1 | fread(&nLinks, sizeof(int), 1, Fhotstart1.file); | |
| 159 | 1 | fread(&nPollut, sizeof(int), 1, Fhotstart1.file); | |
| 160 | 1 | fread(&flowUnits, sizeof(int), 1, Fhotstart1.file); | |
| 161 |
1/2✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
|
1 | if ( nSubcatch != Nobjects[SUBCATCH] |
| 162 |
1/2✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
|
1 | || nLandUses != Nobjects[LANDUSE] |
| 163 |
1/2✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
|
1 | || nNodes != Nobjects[NODE] |
| 164 |
1/2✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
|
1 | || nLinks != Nobjects[LINK] |
| 165 |
1/2✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
|
1 | || nPollut != Nobjects[POLLUT] |
| 166 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
|
1 | || flowUnits != FlowUnits ) |
| 167 | { | ||
| 168 | ✗ | report_writeErrorMsg(ERR_HOTSTART_FILE_FORMAT, ""); | |
| 169 | ✗ | return FALSE; | |
| 170 | } | ||
| 171 | |||
| 172 | // --- read contents of the file and close it | ||
| 173 |
1/2✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
|
1 | if ( fileVersion >= 3 ) readRunoff(); |
| 174 | 1 | readRouting(); | |
| 175 | 1 | fclose(Fhotstart1.file); | |
| 176 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
|
1 | if ( ErrorCode ) return FALSE; |
| 177 | 1 | else return TRUE; | |
| 178 | } | ||
| 179 | |||
| 180 | //============================================================================= | ||
| 181 | |||
| 182 | 58 | int openHotstartFile2() | |
| 183 | // | ||
| 184 | // Input: none | ||
| 185 | // Output: none | ||
| 186 | // Purpose: opens a new routing hotstart file to save results to. | ||
| 187 | // | ||
| 188 | { | ||
| 189 | int nSubcatch; | ||
| 190 | int nLandUses; | ||
| 191 | int nNodes; | ||
| 192 | int nLinks; | ||
| 193 | int nPollut; | ||
| 194 | int flowUnits; | ||
| 195 | 58 | char fileStamp[] = "SWMM5-HOTSTART4"; | |
| 196 | |||
| 197 | // --- try to open file | ||
| 198 |
2/2✓ Branch 0 taken 57 times.
✓ Branch 1 taken 1 time.
|
58 | if ( Fhotstart2.mode != SAVE_FILE ) return TRUE; |
| 199 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
|
1 | if ( (Fhotstart2.file = fopen(Fhotstart2.name, "w+b")) == NULL) |
| 200 | { | ||
| 201 | ✗ | report_writeErrorMsg(ERR_HOTSTART_FILE_OPEN, Fhotstart2.name); | |
| 202 | ✗ | return FALSE; | |
| 203 | } | ||
| 204 | |||
| 205 | // --- write file stamp & number of objects to file | ||
| 206 | 1 | nSubcatch = Nobjects[SUBCATCH]; | |
| 207 | 1 | nLandUses = Nobjects[LANDUSE]; | |
| 208 | 1 | nNodes = Nobjects[NODE]; | |
| 209 | 1 | nLinks = Nobjects[LINK]; | |
| 210 | 1 | nPollut = Nobjects[POLLUT]; | |
| 211 | 1 | flowUnits = FlowUnits; | |
| 212 | 1 | fwrite(fileStamp, sizeof(char), strlen(fileStamp), Fhotstart2.file); | |
| 213 | 1 | fwrite(&nSubcatch, sizeof(int), 1, Fhotstart2.file); | |
| 214 | 1 | fwrite(&nLandUses, sizeof(int), 1, Fhotstart2.file); | |
| 215 | 1 | fwrite(&nNodes, sizeof(int), 1, Fhotstart2.file); | |
| 216 | 1 | fwrite(&nLinks, sizeof(int), 1, Fhotstart2.file); | |
| 217 | 1 | fwrite(&nPollut, sizeof(int), 1, Fhotstart2.file); | |
| 218 | 1 | fwrite(&flowUnits, sizeof(int), 1, Fhotstart2.file); | |
| 219 | 1 | return TRUE; | |
| 220 | } | ||
| 221 | |||
| 222 | //============================================================================= | ||
| 223 | |||
| 224 | 1 | void saveRouting() | |
| 225 | // | ||
| 226 | // Input: none | ||
| 227 | // Output: none | ||
| 228 | // Purpose: saves current state of all nodes and links to hotstart file. | ||
| 229 | // | ||
| 230 | { | ||
| 231 | int i, j; | ||
| 232 | float x[3]; | ||
| 233 | |||
| 234 |
2/2✓ Branch 0 taken 916 times.
✓ Branch 1 taken 1 time.
|
917 | for (i = 0; i < Nobjects[NODE]; i++) |
| 235 | { | ||
| 236 | 916 | x[0] = (float)Node[i].newDepth; | |
| 237 | 916 | x[1] = (float)Node[i].newLatFlow; | |
| 238 | 916 | fwrite(x, sizeof(float), 2, Fhotstart2.file); | |
| 239 | |||
| 240 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 904 times.
|
916 | if ( Node[i].type == STORAGE ) |
| 241 | { | ||
| 242 | 12 | j = Node[i].subIndex; | |
| 243 | 12 | x[0] = (float)Storage[j].hrt; | |
| 244 | 12 | fwrite(&x[0], sizeof(float), 1, Fhotstart2.file); | |
| 245 | } | ||
| 246 | |||
| 247 |
2/2✓ Branch 0 taken 3664 times.
✓ Branch 1 taken 916 times.
|
4580 | for (j = 0; j < Nobjects[POLLUT]; j++) |
| 248 | { | ||
| 249 | 3664 | x[0] = (float)Node[i].newQual[j]; | |
| 250 | 3664 | fwrite(&x[0], sizeof(float), 1, Fhotstart2.file); | |
| 251 | } | ||
| 252 | } | ||
| 253 |
2/2✓ Branch 0 taken 967 times.
✓ Branch 1 taken 1 time.
|
968 | for (i = 0; i < Nobjects[LINK]; i++) |
| 254 | { | ||
| 255 | 967 | x[0] = (float)Link[i].newFlow; | |
| 256 | 967 | x[1] = (float)Link[i].newDepth; | |
| 257 | 967 | x[2] = (float)Link[i].setting; | |
| 258 | 967 | fwrite(x, sizeof(float), 3, Fhotstart2.file); | |
| 259 |
2/2✓ Branch 0 taken 3868 times.
✓ Branch 1 taken 967 times.
|
4835 | for (j = 0; j < Nobjects[POLLUT]; j++) |
| 260 | { | ||
| 261 | 3868 | x[0] = (float)Link[i].newQual[j]; | |
| 262 | 3868 | fwrite(&x[0], sizeof(float), 1, Fhotstart2.file); | |
| 263 | } | ||
| 264 | } | ||
| 265 | 1 | } | |
| 266 | |||
| 267 | //============================================================================= | ||
| 268 | |||
| 269 | 1 | void readRouting() | |
| 270 | // | ||
| 271 | // Input: none | ||
| 272 | // Output: none | ||
| 273 | // Purpose: reads initial state of all nodes, links and groundwater objects | ||
| 274 | // from hotstart file. | ||
| 275 | // | ||
| 276 | { | ||
| 277 | int i, j; | ||
| 278 | float x; | ||
| 279 | double xgw[4]; | ||
| 280 | 1 | FILE* f = Fhotstart1.file; | |
| 281 | |||
| 282 | // --- for file format 2, assign GW moisture content and lower depth | ||
| 283 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
|
1 | if ( fileVersion == 2 ) |
| 284 | { | ||
| 285 | // --- flow and available upper zone volume not used | ||
| 286 | ✗ | xgw[2] = 0.0; | |
| 287 | ✗ | xgw[3] = MISSING; | |
| 288 | ✗ | for (i = 0; i < Nobjects[SUBCATCH]; i++) | |
| 289 | { | ||
| 290 | // --- read moisture content and water table elevation as floats | ||
| 291 | ✗ | if ( !readFloat(&x, f) ) return; | |
| 292 | ✗ | xgw[0] = x; | |
| 293 | ✗ | if ( !readFloat(&x, f) ) return; | |
| 294 | ✗ | xgw[1] = x; | |
| 295 | |||
| 296 | // --- set GW state | ||
| 297 | ✗ | if ( Subcatch[i].groundwater != NULL ) gwater_setState(i, xgw); | |
| 298 | } | ||
| 299 | } | ||
| 300 | |||
| 301 | // --- read node states | ||
| 302 |
2/2✓ Branch 0 taken 916 times.
✓ Branch 1 taken 1 time.
|
917 | for (i = 0; i < Nobjects[NODE]; i++) |
| 303 | { | ||
| 304 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 916 times.
|
916 | if ( !readFloat(&x, f) ) return; |
| 305 | 916 | Node[i].newDepth = x; | |
| 306 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 916 times.
|
916 | if ( !readFloat(&x, f) ) return; |
| 307 | 916 | Node[i].newLatFlow = x; | |
| 308 | |||
| 309 |
3/4✓ Branch 0 taken 916 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 904 times.
|
916 | if ( fileVersion >= 4 && Node[i].type == STORAGE ) |
| 310 | { | ||
| 311 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
|
12 | if ( !readFloat(&x, f) ) return; |
| 312 | 12 | j = Node[i].subIndex; | |
| 313 | 12 | Storage[j].hrt = x; | |
| 314 | } | ||
| 315 | |||
| 316 |
2/2✓ Branch 0 taken 3664 times.
✓ Branch 1 taken 916 times.
|
4580 | for (j = 0; j < Nobjects[POLLUT]; j++) |
| 317 | { | ||
| 318 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3664 times.
|
3664 | if ( !readFloat(&x, f) ) return; |
| 319 | 3664 | Node[i].newQual[j] = x; | |
| 320 | } | ||
| 321 | |||
| 322 | // --- read in zeros here for backwards compatibility | ||
| 323 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 916 times.
|
916 | if ( fileVersion <= 2 ) |
| 324 | { | ||
| 325 | ✗ | for (j = 0; j < Nobjects[POLLUT]; j++) | |
| 326 | { | ||
| 327 | ✗ | if ( !readFloat(&x, f) ) return; | |
| 328 | } | ||
| 329 | } | ||
| 330 | } | ||
| 331 | |||
| 332 | // --- read link states | ||
| 333 |
2/2✓ Branch 0 taken 967 times.
✓ Branch 1 taken 1 time.
|
968 | for (i = 0; i < Nobjects[LINK]; i++) |
| 334 | { | ||
| 335 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 967 times.
|
967 | if ( !readFloat(&x, f) ) return; |
| 336 | 967 | Link[i].newFlow = x; | |
| 337 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 967 times.
|
967 | if ( !readFloat(&x, f) ) return; |
| 338 | 967 | Link[i].newDepth = x; | |
| 339 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 967 times.
|
967 | if ( !readFloat(&x, f) ) return; |
| 340 | 967 | Link[i].setting = x; | |
| 341 | |||
| 342 | // --- set link's target setting to saved setting | ||
| 343 | 967 | Link[i].targetSetting = x; | |
| 344 | 967 | link_setTargetSetting(i); | |
| 345 | 967 | link_setSetting(i, 0.0); | |
| 346 | |||
| 347 |
2/2✓ Branch 0 taken 3868 times.
✓ Branch 1 taken 967 times.
|
4835 | for (j = 0; j < Nobjects[POLLUT]; j++) |
| 348 | { | ||
| 349 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3868 times.
|
3868 | if ( !readFloat(&x, f) ) return; |
| 350 | 3868 | Link[i].newQual[j] = x; | |
| 351 | } | ||
| 352 | |||
| 353 | } | ||
| 354 | } | ||
| 355 | |||
| 356 | //============================================================================= | ||
| 357 | |||
| 358 | 1 | void saveRunoff(void) | |
| 359 | // | ||
| 360 | // Input: none | ||
| 361 | // Output: none | ||
| 362 | // Purpose: saves current state of all subcatchments to hotstart file. | ||
| 363 | // | ||
| 364 | { | ||
| 365 | int i, j, k; | ||
| 366 | double x[6]; | ||
| 367 | 1 | FILE* f = Fhotstart2.file; | |
| 368 | |||
| 369 |
2/2✓ Branch 0 taken 329 times.
✓ Branch 1 taken 1 time.
|
330 | for (i = 0; i < Nobjects[SUBCATCH]; i++) |
| 370 | { | ||
| 371 | // Ponded depths for each sub-area & total runoff (4 elements) | ||
| 372 |
2/2✓ Branch 0 taken 987 times.
✓ Branch 1 taken 329 times.
|
1316 | for (j = 0; j < 3; j++) x[j] = Subcatch[i].subArea[j].depth; |
| 373 | 329 | x[3] = Subcatch[i].newRunoff; | |
| 374 | 329 | fwrite(x, sizeof(double), 4, f); | |
| 375 | |||
| 376 | // Infiltration state (max. of 6 elements) | ||
| 377 |
2/2✓ Branch 0 taken 1974 times.
✓ Branch 1 taken 329 times.
|
2303 | for (j=0; j<6; j++) x[j] = 0.0; |
| 378 | 329 | infil_getState(i, x); | |
| 379 | 329 | fwrite(x, sizeof(double), 6, f); | |
| 380 | |||
| 381 | // Groundwater state (4 elements) | ||
| 382 |
2/2✓ Branch 0 taken 319 times.
✓ Branch 1 taken 10 times.
|
329 | if ( Subcatch[i].groundwater != NULL ) |
| 383 | { | ||
| 384 | 319 | gwater_getState(i, x); | |
| 385 | 319 | fwrite(x, sizeof(double), 4, f); | |
| 386 | } | ||
| 387 | |||
| 388 | // Snowpack state (5 elements for each of 3 snow surfaces) | ||
| 389 |
1/2✓ Branch 0 taken 329 times.
✗ Branch 1 not taken.
|
329 | if ( Subcatch[i].snowpack != NULL ) |
| 390 | { | ||
| 391 |
2/2✓ Branch 0 taken 987 times.
✓ Branch 1 taken 329 times.
|
1316 | for (j=0; j<3; j++) |
| 392 | { | ||
| 393 | 987 | snow_getState(i, j, x); | |
| 394 | 987 | fwrite(x, sizeof(double), 5, f); | |
| 395 | } | ||
| 396 | } | ||
| 397 | |||
| 398 | // Water quality | ||
| 399 |
1/2✓ Branch 0 taken 329 times.
✗ Branch 1 not taken.
|
329 | if ( Nobjects[POLLUT] > 0 ) |
| 400 | { | ||
| 401 | // Runoff quality | ||
| 402 |
2/2✓ Branch 0 taken 1316 times.
✓ Branch 1 taken 329 times.
|
1645 | for (j=0; j<Nobjects[POLLUT]; j++) |
| 403 | { | ||
| 404 | 1316 | x[0] = Subcatch[i].newQual[j]; | |
| 405 | 1316 | fwrite(x, sizeof(double), 1, f); | |
| 406 | } | ||
| 407 | |||
| 408 | // Ponded quality | ||
| 409 |
2/2✓ Branch 0 taken 1316 times.
✓ Branch 1 taken 329 times.
|
1645 | for (j=0; j<Nobjects[POLLUT]; j++) |
| 410 | { | ||
| 411 | 1316 | x[0] = Subcatch[i].pondedQual[j]; | |
| 412 | 1316 | fwrite(x, sizeof(double), 1, f); | |
| 413 | } | ||
| 414 | |||
| 415 | // Buildup and when streets were last swept | ||
| 416 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 329 times.
|
329 | for (k=0; k<Nobjects[LANDUSE]; k++) |
| 417 | { | ||
| 418 | ✗ | for (j=0; j<Nobjects[POLLUT]; j++) | |
| 419 | { | ||
| 420 | ✗ | x[0] = Subcatch[i].landFactor[k].buildup[j]; | |
| 421 | ✗ | fwrite(x, sizeof(double), 1, f); | |
| 422 | } | ||
| 423 | ✗ | x[0] = Subcatch[i].landFactor[k].lastSwept; | |
| 424 | ✗ | fwrite(x, sizeof(double), 1, f); | |
| 425 | } | ||
| 426 | } | ||
| 427 | } | ||
| 428 | 1 | } | |
| 429 | |||
| 430 | //============================================================================= | ||
| 431 | |||
| 432 | 1 | void readRunoff() | |
| 433 | // | ||
| 434 | // Input: none | ||
| 435 | // Output: none | ||
| 436 | // Purpose: reads saved state of all subcatchments from a hot start file. | ||
| 437 | // | ||
| 438 | { | ||
| 439 | int i, j, k; | ||
| 440 | double x[6]; | ||
| 441 | 1 | FILE* f = Fhotstart1.file; | |
| 442 | |||
| 443 |
2/2✓ Branch 0 taken 329 times.
✓ Branch 1 taken 1 time.
|
330 | for (i = 0; i < Nobjects[SUBCATCH]; i++) |
| 444 | { | ||
| 445 | // Ponded depths & runoff (4 elements) | ||
| 446 |
2/2✓ Branch 0 taken 987 times.
✓ Branch 1 taken 329 times.
|
1316 | for (j = 0; j < 3; j++) |
| 447 | { | ||
| 448 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 987 times.
|
987 | if ( !readDouble(&Subcatch[i].subArea[j].depth, f) ) return; |
| 449 | } | ||
| 450 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 329 times.
|
329 | if ( !readDouble(&Subcatch[i].newRunoff, f) ) return; |
| 451 | |||
| 452 | // Infiltration state (max. of 6 elements) | ||
| 453 |
3/4✗ Branch 1 not taken.
✓ Branch 2 taken 1974 times.
✓ Branch 3 taken 1974 times.
✓ Branch 4 taken 329 times.
|
2303 | for (j=0; j<6; j++) if ( !readDouble(&x[j], f) ) return; |
| 454 | 329 | infil_setState(i, x); | |
| 455 | |||
| 456 | // Groundwater state (4 elements) | ||
| 457 |
2/2✓ Branch 0 taken 319 times.
✓ Branch 1 taken 10 times.
|
329 | if ( Subcatch[i].groundwater != NULL ) |
| 458 | { | ||
| 459 |
3/4✗ Branch 1 not taken.
✓ Branch 2 taken 1276 times.
✓ Branch 3 taken 1276 times.
✓ Branch 4 taken 319 times.
|
1595 | for (j=0; j<4; j++) if ( !readDouble(&x[j], f) ) return; |
| 460 | 319 | gwater_setState(i, x); | |
| 461 | } | ||
| 462 | |||
| 463 | // Snowpack state (5 elements for each of 3 snow surfaces) | ||
| 464 |
1/2✓ Branch 0 taken 329 times.
✗ Branch 1 not taken.
|
329 | if ( Subcatch[i].snowpack != NULL ) |
| 465 | { | ||
| 466 |
2/2✓ Branch 0 taken 987 times.
✓ Branch 1 taken 329 times.
|
1316 | for (j=0; j<3; j++) |
| 467 | { | ||
| 468 |
3/4✗ Branch 1 not taken.
✓ Branch 2 taken 4935 times.
✓ Branch 3 taken 4935 times.
✓ Branch 4 taken 987 times.
|
5922 | for (k=0; k<5; k++) if ( !readDouble(&x[k], f) ) return; |
| 469 | 987 | snow_setState(i, j, x); | |
| 470 | } | ||
| 471 | } | ||
| 472 | |||
| 473 | // Water quality | ||
| 474 |
1/2✓ Branch 0 taken 329 times.
✗ Branch 1 not taken.
|
329 | if ( Nobjects[POLLUT] > 0 ) |
| 475 | { | ||
| 476 | // Runoff quality | ||
| 477 |
2/2✓ Branch 0 taken 1316 times.
✓ Branch 1 taken 329 times.
|
1645 | for (j=0; j<Nobjects[POLLUT]; j++) |
| 478 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1316 times.
|
1316 | if ( ! readDouble(&Subcatch[i].newQual[j], f) ) return; |
| 479 | |||
| 480 | // Ponded quality | ||
| 481 |
2/2✓ Branch 0 taken 1316 times.
✓ Branch 1 taken 329 times.
|
1645 | for (j=0; j<Nobjects[POLLUT]; j++) |
| 482 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1316 times.
|
1316 | if ( !readDouble(&Subcatch[i].pondedQual[j], f) ) return; |
| 483 | |||
| 484 | // Buildup and when streets were last swept | ||
| 485 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 329 times.
|
329 | for (k=0; k<Nobjects[LANDUSE]; k++) |
| 486 | { | ||
| 487 | ✗ | for (j=0; j<Nobjects[POLLUT]; j++) | |
| 488 | { | ||
| 489 | ✗ | if ( !readDouble( | |
| 490 | ✗ | &Subcatch[i].landFactor[k].buildup[j], f) ) return; | |
| 491 | } | ||
| 492 | ✗ | if ( !readDouble(&Subcatch[i].landFactor[k].lastSwept, f) ) | |
| 493 | ✗ | return; | |
| 494 | } | ||
| 495 | } | ||
| 496 | } | ||
| 497 | } | ||
| 498 | |||
| 499 | //============================================================================= | ||
| 500 | |||
| 501 | 12277 | int readFloat(float *x, FILE* f) | |
| 502 | // | ||
| 503 | // Input: none | ||
| 504 | // Output: x = pointer to a float variable | ||
| 505 | // Purpose: reads a floating point value from a hot start file | ||
| 506 | // | ||
| 507 | { | ||
| 508 | // --- read a value from the file | ||
| 509 | 12277 | fread(x, sizeof(float), 1, f); | |
| 510 | |||
| 511 | // --- test if the value is NaN (not a number) | ||
| 512 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12277 times.
|
12277 | if ( *(x) != *(x) ) |
| 513 | { | ||
| 514 | ✗ | report_writeErrorMsg(ERR_HOTSTART_FILE_READ, ""); | |
| 515 | ✗ | *(x) = 0.0; | |
| 516 | ✗ | return FALSE; | |
| 517 | } | ||
| 518 | 12277 | return TRUE; | |
| 519 | } | ||
| 520 | |||
| 521 | //============================================================================= | ||
| 522 | |||
| 523 | 12133 | int readDouble(double* x, FILE* f) | |
| 524 | // | ||
| 525 | // Input: none | ||
| 526 | // Output: x = pointer to a double variable | ||
| 527 | // Purpose: reads a floating point value from a hot start file | ||
| 528 | // | ||
| 529 | { | ||
| 530 | // --- read a value from the file | ||
| 531 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 12133 times.
|
12133 | if ( feof(f) ) |
| 532 | { | ||
| 533 | ✗ | *(x) = 0.0; | |
| 534 | ✗ | report_writeErrorMsg(ERR_HOTSTART_FILE_READ, ""); | |
| 535 | ✗ | return FALSE; | |
| 536 | } | ||
| 537 | 12133 | fread(x, sizeof(double), 1, f); | |
| 538 | |||
| 539 | // --- test if the value is NaN (not a number) | ||
| 540 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12133 times.
|
12133 | if ( *(x) != *(x) ) |
| 541 | { | ||
| 542 | ✗ | *(x) = 0.0; | |
| 543 | ✗ | return FALSE; | |
| 544 | } | ||
| 545 | 12133 | return TRUE; | |
| 546 | } | ||
| 547 |