CoastalME (Coastal Modelling Environment)
Simulates the long-term behaviour of complex coastlines
Loading...
Searching...
No Matches
read_input.cpp
Go to the documentation of this file.
1
12
13/* ==============================================================================================================================
14
15 This file is part of CoastalME, the Coastal Modelling Environment.
16
17 CoastalME is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22
23==============================================================================================================================*/
24#include <cstdio>
25
26#include <cctype>
27using std::isdigit;
28
29#include <cmath>
30using std::floor;
31
32#include <fstream>
33using std::ifstream;
34
35#include <iostream>
36using std::cerr;
37using std::cout;
38using std::endl;
39using std::ios;
40
41#include <string>
42using std::to_string;
43
44#include <algorithm>
45using std::find;
46using std::sort;
47
48#include <random>
49using std::random_device;
50
51#include "cme.h"
53#include "simulation.h"
54
55//===============================================================================================================================
57//===============================================================================================================================
59{
60 // Check if user has supplied home directory
61 if (m_strCMEIni.empty())
62 // if not use the cme executable directory to find cme.ini
64
65 else
66 {
67 // if user has supplied home directory replace cme run directory with user supplied dir
69 }
70
71 m_strCMEIni.append(CME_INI);
72
73 // The .ini file is assumed to be in the CoastalME executable's directory
74 string const strFilePathName(m_strCMEIni);
75
76 // Tell the user what is happening
77 cout << READING_FILE_LOCATIONS << strFilePathName << endl;
78
79 // Create an ifstream object
80 ifstream InStream;
81
82 // Try to open .ini file for input
83 InStream.open(strFilePathName.c_str(), ios::in);
84
85 // Did it open OK?
86 if (!InStream.is_open())
87 {
88 // Error: cannot open .ini file for input
89 cerr << ERR << "cannot open " << strFilePathName << " for input" << endl;
90 return false;
91 }
92
93 int nLine = 0;
94 int i = 0;
95 string strRec, strErr;
96
97 while (getline(InStream, strRec))
98 {
99 nLine++;
100
101 // Trim off leading and trailing whitespace
102 strRec = strTrim(&strRec);
103
104 // If it is a blank line or a comment then ignore it
105 if ((!strRec.empty()) && (strRec[0] != QUOTE1) && (strRec[0] != QUOTE2))
106 {
107 // It isn't so increment counter
108 i++;
109
110 // Find the colon: note that lines MUST have a colon separating data from leading description portion
111 size_t nPos = strRec.find(COLON);
112
113 if (nPos == string::npos)
114 {
115 // Error: badly formatted (no colon)
116 cerr << ERR << "on line " << nLine << ": badly formatted (no ':') in " << strFilePathName << endl
117 << "'" << strRec << "'" << endl;
118 return false;
119 }
120
121 if (nPos == strRec.size() - 1)
122 {
123 // Error: badly formatted (colon with nothing following)
124 cerr << ERR << "on line " << nLine << ": badly formatted (nothing following ':') in " << strFilePathName << endl
125 << "'" << strRec << "'" << endl;
126 return false;
127 }
128
129 // Strip off leading portion (the bit up to and including the colon)
130 string strRH = strRec.erase(0, nPos + 1);
131
132 // Remove leading whitespace
133 strRH = strTrimLeft(&strRH);
134
135 // Look for a trailing comment, if found then terminate string at that point and trim off any trailing whitespace
136 nPos = strRH.rfind(QUOTE1);
137
138 if (nPos != string::npos)
139 strRH.resize(nPos);
140
141 nPos = strRH.rfind(QUOTE2);
142
143 if (nPos != string::npos)
144 strRH.resize(nPos);
145
146 // Remove trailing whitespace
147 strRH = strTrimRight(&strRH);
148
149 switch (i)
150 {
151 case 1:
152 // The main input run-data filename
153 if (strRH.empty())
154 strErr = "line " + to_string(nLine) + ": path and name of main datafile";
155
156 else
157 {
158 // First check that we don't already have an input run-data filename, e.g. one entered on the command-line
159 if (m_strDataPathName.empty())
160 {
161 // We don't: so first check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
162 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
163 // It has an absolute path, so use it 'as is'
164 m_strDataPathName = strRH;
165
166 else
167 {
168 // It has a relative path, so prepend the CoastalME dir
170 m_strDataPathName.append(strRH);
171 }
172 }
173 }
174
175 break;
176
177 case 2:
178 // Path for CoastalME output
179 if (strRH.empty())
180 strErr = "line " + to_string(nLine) + ": path for CoastalME output";
181
182 else
183 {
184 // Check for trailing slash on CoastalME output directory name (is vital)
185 if (strRH[strRH.size() - 1] != PATH_SEPARATOR)
186 strRH.push_back(PATH_SEPARATOR);
187
188 // Now check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
189 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
190 // It is an absolute path, so use it 'as is'
191 m_strOutPath = strRH;
192
193 else
194 {
195 // It is a relative path, so prepend the CoastalME dir
197 m_strOutPath.append(strRH);
198 }
199 }
200
201 break;
202
203 case 3:
204 // Email address, only useful if running under Linux/Unix
205 if (!strRH.empty())
206 {
207 // Something was entered, do rudimentary check for valid email address
208 if (strRH.find('@') == string::npos)
209 strErr = "line " + to_string(nLine) + ": email address for messages";
210
211 else
212 m_strMailAddress = strRH;
213 }
214
215 break;
216 }
217
218 // Did an error occur?
219 if (!strErr.empty())
220 {
221 // Error in input to initialisation file
222 cerr << ERR << "reading " << strErr << " in " << strFilePathName << endl
223 << "'" << strRec << "'" << endl;
224 InStream.close();
225
226 return false;
227 }
228 }
229 }
230
231 InStream.close();
232 return true;
233}
234
235//===============================================================================================================================
237// TODO 000 Should user input be split in two main files: one for frequently-changed things, one for rarely-changed things? If so, what should go into each file ('testing only' OK, but what else?)
238//===============================================================================================================================
240{
241 // Create an ifstream object
242 ifstream InStream;
243
244 // Try to open run details file for input
245 InStream.open(m_strDataPathName.c_str(), ios::in);
246
247 // Did it open OK?
248 if (!InStream.is_open())
249 {
250 // Error: cannot open run details file for input
251 cerr << ERR << "cannot open " << m_strDataPathName << " for input" << endl;
252 return false;
253 }
254
255 int nLine = 0;
256 int i = 0;
257 size_t nPos;
258 string strRec, strErr;
259
260 while (getline(InStream, strRec))
261 {
262 nLine++;
263
264 // Trim off leading and trailing whitespace
265 strRec = strTrim(&strRec);
266
267 // If it is a blank line or a comment then ignore it
268 if ((!strRec.empty()) && (strRec[0] != QUOTE1) && (strRec[0] != QUOTE2))
269 {
270 // It isn't so increment counter
271 i++;
272
273 // Find the colon: note that lines MUST have a colon separating data from leading description portion
274 nPos = strRec.find(COLON);
275
276 if (nPos == string::npos)
277 {
278 // Error: badly formatted (no colon)
279 cerr << ERR << "on line " << to_string(nLine) << "badly formatted (no ':') in " << m_strDataPathName << endl
280 << strRec << endl;
281 return false;
282 }
283
284 // Strip off leading portion (the bit up to and including the colon)
285 string strRH = strRec.erase(0, nPos + 1);
286
287 // Remove leading whitespace after the colon
288 strRH = strTrimLeft(&strRH);
289
290 // Look for trailing comments, if found then terminate string at that point and trim off any trailing whitespace
291 bool bFound = true;
292
293 while (bFound)
294 {
295 bFound = false;
296
297 nPos = strRH.rfind(QUOTE1);
298
299 if (nPos != string::npos)
300 {
301 strRH.resize(nPos);
302 bFound = true;
303 }
304
305 nPos = strRH.rfind(QUOTE2);
306
307 if (nPos != string::npos)
308 {
309 strRH.resize(nPos);
310 bFound = true;
311 }
312
313 // Trim trailing spaces
314 strRH = strTrimRight(&strRH);
315 }
316
317#ifdef _WIN32
318 // For Windows, make sure has backslashes, not Unix-style slashes
319 strRH = pstrChangeToBackslash(&strRH);
320#endif
321 bool bFirst = true;
322 int nRet = 0;
323 int nHour = 0;
324 int nMin = 0;
325 int nSec = 0;
326 int nDay = 0;
327 int nMonth = 0;
328 int nYear = 0;
329 double dMult = 0;
330 string strTmp;
331 vector<string> VstrTmp;
332
333 switch (i)
334 {
335 // ---------------------------------------------- Run Information -----------------------------------------------------
336 case 1:
337 // Text output file names, don't change case
338 if (strRH.empty())
339 strErr = "line " + to_string(nLine) + ": output file names";
340
341 else
342 {
343 m_strRunName = strRH;
344
346 m_strOutFile.append(strRH);
347 m_strOutFile.append(OUTEXT);
348
350 m_strLogFile.append(strRH);
351 m_strLogFile.append(LOGEXT);
352 }
353
354 break;
355
356 case 2:
357 // Content of log file, 0 = no log file, 1 = least detail, 3 = most detail
358 if (!bIsStringValidInt(strRH))
359 {
360 strErr = "line " + to_string(nLine) + ": invalid integer for log file detail level '" + strRH + "' in " + m_strDataPathName;
361 break;
362 }
363
364 m_nLogFileDetail = stoi(strRH);
365
367 strErr = "line " + to_string(nLine) + ": log file detail level";
368
369 break;
370
371 case 3:
372 // Output per-timestep results in CSV format?
373 strRH = strToLower(&strRH);
374
376
377 if (strRH.find('y') != string::npos)
379
380 break;
381
382 case 4:
383 // Get the start date/time of the simulation, format is [hh-mm-ss dd/mm/yyyy]
384 VstrTmp = VstrSplit(&strRH, SPACE);
385
386 // Both date and time here?
387 if (VstrTmp.size() < 2)
388 {
389 strErr = "line " + to_string(nLine) + ": must have both date and time for simulation start in '" + m_strDataPathName + "'";
390 break;
391 }
392
393 // OK, first sort out the time
394 if (!bParseTime(&VstrTmp[0], nHour, nMin, nSec))
395 {
396 strErr = "line " + to_string(nLine) + ": could not understand simulation start time in '" + m_strDataPathName + "'";
397 break;
398 }
399
400 // Next sort out the date
401 if (!bParseDate(&VstrTmp[1], nDay, nMonth, nYear))
402 {
403 strErr = "line " + to_string(nLine) + ": could not understand simulation start date in '" + m_strDataPathName + "'";
404 break;
405 }
406
407 // Store simulation start time and date
408 m_nSimStartSec = nSec;
409 m_nSimStartMin = nMin;
410 m_nSimStartHour = nHour;
411 m_nSimStartDay = nDay;
412 m_nSimStartMonth = nMonth;
413 m_nSimStartYear = nYear;
414
415 break;
416
417 case 5:
418 // Duration of simulation (in hours, days, months, or years): sort out multiplier and user units, as used in the per-timestep output
419 strRH = strToLower(&strRH);
420
421 nRet = nDoSimulationTimeMultiplier(&strRH);
422
423 if (nRet != RTN_OK)
424 {
425 strErr = "line " + to_string(nLine) + ": units for duration of simulation";
426 break;
427 }
428
429 // And now calculate the duration of the simulation in hours: first find whitespace between the number and the unit
430 nPos = strRH.rfind(SPACE);
431
432 if (nPos == string::npos)
433 {
434 strErr = "line " + to_string(nLine) + ": format of duration simulation line";
435 break;
436 }
437
438 // Cut off rh bit of string
439 strRH.resize(nPos);
440
441 // Remove trailing spaces
442 strRH = strTrimRight(&strRH);
443
444 // Calculate the duration of the simulation in hours
445 m_dSimDuration = strtod(strRH.c_str(), NULL) * m_dDurationUnitsMult;
446
447 if (m_dSimDuration <= 0)
448 strErr = "line " + to_string(nLine) + ": duration of simulation must be > 0";
449
450 break;
451
452 case 6:
453 // Timestep of simulation (in hours or days)
454 strRH = strToLower(&strRH);
455
456 dMult = dGetTimeMultiplier(&strRH);
457
458 if (static_cast<int>(dMult) == TIME_UNKNOWN)
459 {
460 strErr = "line " + to_string(nLine) + ": units for simulation timestep";
461 break;
462 }
463
464 // we have the multiplier, now calculate the timestep in hours: look for the whitespace between the number and unit
465 nPos = strRH.rfind(SPACE);
466
467 if (nPos == string::npos)
468 {
469 strErr = "line " + to_string(nLine) + ": format of simulation timestep";
470 break;
471 }
472
473 // cut off rh bit of string
474 strRH.resize(nPos);
475
476 // remove trailing spaces
477 strRH = strTrimRight(&strRH);
478
479 // Check that this is a valid double
480 if (!bIsStringValidDouble(strRH))
481 {
482 strErr = "line " + to_string(nLine) + ": invalid floating point number for timestep '" + strRH + "' in " + m_strDataPathName;
483 break;
484 }
485
486 m_dTimeStep = strtod(strRH.c_str(), NULL) * dMult; // in hours
487
488 if (m_dTimeStep <= 0)
489 strErr = "line " + to_string(nLine) + ": timestep of simulation must be > 0";
490
492 strErr = "line " + to_string(nLine) + ": timestep of simulation must be < the duration of the simulation";
493
494 break;
495
496 case 7:
497 {
498 // Save interval(s) - can handle multiple groups with different units if groups are comma-separated e.g., "6 12 24 48 hours, 1 2 6 months, 1 years"
499 strRH = strToLower(&strRH);
500
501 // Split by commas to handle multiple unit groups
502 string const strOriginal = strRH;
503 size_t nCommaPos = 0;
504
505 m_bSaveRegular = false; // Start with assumption of multiple values
506
507 do
508 {
509 string strGroup;
510 size_t const nNextComma = strOriginal.find(',', nCommaPos);
511
512 if (nNextComma != string::npos)
513 {
514 strGroup = strOriginal.substr(nCommaPos, nNextComma - nCommaPos);
515 nCommaPos = nNextComma + 1;
516 }
517
518 else
519 {
520 strGroup = strOriginal.substr(nCommaPos);
521 nCommaPos = string::npos;
522 }
523
524 // Trim whitespace from group
525 strGroup = strTrimLeft(&strGroup);
526 strGroup = strTrimRight(&strGroup);
527
528 if (strGroup.empty())
529 continue;
530
531 // Get the multiplier for this group
532 dMult = dGetTimeMultiplier(&strGroup);
533
534 if (static_cast<int>(dMult) == TIME_UNKNOWN)
535 {
536 strErr = "line " + to_string(nLine) + ": units for save intervals in group '" + strGroup + "'";
537 break;
538 }
539
540 // Remove the unit text from the end
541 size_t const nLastSpace = strGroup.rfind(SPACE);
542
543 if (nLastSpace == string::npos)
544 {
545 strErr = "line " + to_string(nLine) + ": format of save times/intervals in group '" + strGroup + "'";
546 break;
547 }
548
549 string strNumbers = strGroup.substr(0, nLastSpace);
550 strNumbers = strTrimRight(&strNumbers);
551
552 // Parse numbers in this group
553 size_t nSpacePos = 0;
554 strNumbers += SPACE; // Add trailing space to help parsing
555
556 do
557 {
558 size_t const nNextSpace = strNumbers.find(SPACE, nSpacePos);
559
560 if (nNextSpace == string::npos)
561 break;
562
563 string const strNumber = strNumbers.substr(nSpacePos, nNextSpace - nSpacePos);
564
565 if (!strNumber.empty())
566 {
567 if (m_nUSave > static_cast<int>(SAVEMAX) - 1)
568 {
569 strErr = "line " + to_string(nLine) + ": too many save intervals";
570 break;
571 }
572
573 double const dValue = strtod(strNumber.c_str(), NULL) * dMult;
574 m_dUSaveTime[m_nUSave++] = dValue;
575 }
576
577 nSpacePos = nNextSpace + 1;
578 } while (nSpacePos < strNumbers.length());
579
580 if (!strErr.empty())
581 break;
582 } while (nCommaPos != string::npos);
583
584 if (!strErr.empty())
585 break;
586
587 // Check if we only have one value (making it a regular interval)
588 if (m_nUSave == 1)
589 {
590 m_bSaveRegular = true;
592
594 strErr = "line " + to_string(nLine) + ": save interval cannot be less than timestep";
595
596 else
598 }
599
600 else if (m_nUSave > 1)
601 {
602 // Multiple values - sort them and validate
604
605 if (m_dUSaveTime[0] < m_dTimeStep)
606 {
607 strErr = "line " + to_string(nLine) + ": first save time cannot be less than timestep";
608 break;
609 }
610
611 // Put a dummy save interval as the last entry in the array
613 }
614
615 else
616 {
617 strErr = "line " + to_string(nLine) + ": no save times specified";
618 }
619 }
620 break;
621
622 case 8:
623 // Random number seed(s)
624 if (strRH.empty())
625 {
626 // User didn't specify a random number seed, so seed with a real random value, if available
627 random_device rdev;
628 m_ulRandSeed[0] = rdev();
629
630 // Only one seed specified, so make all seeds the same
631 for (int n = 1; n < NUMBER_OF_RNGS; n++)
632 m_ulRandSeed[n] = m_ulRandSeed[n - 1];
633 }
634
635 else
636 {
637 // User did specify at least one random number seed. Next find out whether we're dealing with a single seed or more than one: check for a space
638 nPos = strRH.find(SPACE);
639
640 if (nPos == string::npos)
641 {
642 // No space, so we have just one one number
643 m_ulRandSeed[0] = atol(strRH.c_str());
644
645 // Only one seed specified, so make all seeds the same
646 for (int n = 1; n < NUMBER_OF_RNGS; n++)
647 m_ulRandSeed[n] = m_ulRandSeed[n - 1];
648 }
649
650 else
651 {
652 // The user has supplied more than one random number seed
653 int n = 0;
654
655 do
656 {
657 // Get LH bit
658 strTmp = strRH.substr(0, nPos);
659 m_ulRandSeed[n++] = atol(strTmp.c_str());
660
661 if (n == NUMBER_OF_RNGS)
662 // All random number seeds read
663 break;
664
665 // We need more seeds, so get the RH bit
666 strRH = strRH.substr(nPos, strRH.size() - nPos);
667 strRH = strTrimLeft(&strRH);
668
669 if (strRH.size() == 0)
670 // No more seeds left to read
671 break;
672 } while (true);
673
674 // If we haven't filled all random number seeds, make all the remainder the same as the last one read
675 if (n < NUMBER_OF_RNGS - 1)
676 {
677 for (int m = n; m < NUMBER_OF_RNGS; m++)
679 }
680 }
681 }
682
683 break;
684
685 case 9:
686 // Max save digits for GIS output file names
687 if (!bIsStringValidInt(strRH))
688 {
689 strErr = "line " + to_string(nLine) + ": invalid integer for max save digits for GIS output file names '" + strRH + "' in " + m_strDataPathName;
690 break;
691 }
692
693 m_nGISMaxSaveDigits = stoi(strRH);
694
695 if (m_nGISMaxSaveDigits < 2)
696 strErr = "line " + to_string(nLine) + ": max save digits for GIS output file names must be > 1";
697
698 break;
699
700 case 10:
701 // Save digits for GIS output sequential or iteration number? [s = sequential, i = iteration]: s
702 if (strRH.empty())
703 strErr = "line " + to_string(nLine) + ": must specify save digits for GIS output as sequential or as iteration number";
704
705 else
706 {
707 // Convert to lower case
708 strRH = strToLower(&strRH);
709
710 if (strRH.find('s') != string::npos)
711 {
712 // First look for 's'
714 }
715
716 else if (strRH.find('i') != string::npos)
717 {
718 // Now look for 'i'
720 }
721
722 else
723 {
724 strErr = "line ";
725 strErr += to_string(nLine);
726 strErr += ": invalid code for save digits for GIS output save number (must be s or i)";
727
728 break;
729 }
730 }
731
732 break;
733
734 case 11:
735 // Raster GIS files to output
736 if (strRH.empty())
737 {
738 strErr = "line ";
739 strErr += to_string(nLine);
740 strErr += ": must contain '";
741 strErr += RASTER_ALL_OUTPUT_CODE;
742 strErr += "', or '";
743 strErr += RASTER_USUAL_OUTPUT_CODE;
744 strErr += "', or at least one raster GIS output code";
745 }
746
747 else
748 {
749 // Convert to lower case
750 strRH = strToLower(&strRH);
751
752 if (strRH.find(RASTER_ALL_OUTPUT_CODE) != string::npos)
753 {
754 // Set switches for all GIS raster output. Some of these (e.g. all relating to fine sediment) are ignored if e.g. no fine sediment layers are read in
804 }
805
806 else if (strRH.find(RASTER_USUAL_OUTPUT_CODE) != string::npos)
807 {
808 // Set switches for usual GIS raster output. Again, some of these (e.g. all relating to fine sediment) are ignored if they are irrelevant
848
849 // TEST
852 }
853
854 else
855 {
856 // We are not outputting either the "usual" or the "all" collections of raster GIS files, so set switches (and remove strings) for those optional files for which the user specified the code
857 if (strRH.find(RASTER_SEDIMENT_TOP_CODE) != string::npos)
858 {
861 }
862
863 if (strRH.find(RASTER_TOP_CODE) != string::npos)
864 {
865 m_bTopSurfSave = true;
866 strRH = strRemoveSubstr(&strRH, &RASTER_TOP_CODE);
867 }
868
869 if (strRH.find(RASTER_SEA_DEPTH_CODE) != string::npos)
870 {
871 m_bSeaDepthSave = true;
872 strRH = strRemoveSubstr(&strRH, &RASTER_SEA_DEPTH_CODE);
873 }
874
875 if (strRH.find(RASTER_WAVE_HEIGHT_CODE) != string::npos)
876 {
877 m_bWaveHeightSave = true;
879 }
880
881 if (strRH.find(RASTER_WAVE_ORIENTATION_CODE) != string::npos)
882 {
883 m_bWaveAngleSave = true;
885 }
886
887 if (strRH.find(RASTER_WAVE_PERIOD_CODE) != string::npos)
888 {
891 }
892
893 if (strRH.find(RASTER_POTENTIAL_PLATFORM_EROSION_CODE) != string::npos)
894 {
897 }
898
899 if (strRH.find(RASTER_ACTUAL_PLATFORM_EROSION_CODE) != string::npos)
900 {
903 }
904
905 if (strRH.find(RASTER_TOTAL_POTENTIAL_PLATFORM_EROSION_CODE) != string::npos)
906 {
909 }
910
911 if (strRH.find(RASTER_TOTAL_ACTUAL_PLATFORM_EROSION_CODE) != string::npos)
912 {
915 }
916
917 if (strRH.find(RASTER_POTENTIAL_BEACH_EROSION_CODE) != string::npos)
918 {
921 }
922
923 if (strRH.find(RASTER_ACTUAL_BEACH_EROSION_CODE) != string::npos)
924 {
927 }
928
929 if (strRH.find(RASTER_TOTAL_POTENTIAL_BEACH_EROSION_CODE) != string::npos)
930 {
933 }
934
935 if (strRH.find(RASTER_TOTAL_ACTUAL_BEACH_EROSION_CODE) != string::npos)
936 {
939 }
940
941 if (strRH.find(RASTER_LANDFORM_CODE) != string::npos)
942 {
943 m_bLandformSave = true;
944 strRH = strRemoveSubstr(&strRH, &RASTER_LANDFORM_CODE);
945 }
946
947 if (strRH.find(RASTER_LOCAL_SLOPE_CODE) != string::npos)
948 {
949 m_bLocalSlopeSave = true;
951 }
952
953 if (strRH.find(RASTER_SLOPE_CODE) != string::npos)
954 {
955 m_bSlopeSave = true;
956 strRH = strRemoveSubstr(&strRH, &RASTER_SLOPE_CODE);
957 }
958
959 if (strRH.find(RASTER_CLIFF_CODE) != string::npos)
960 {
961 m_bCliffSave = true;
962 strRH = strRemoveSubstr(&strRH, &RASTER_CLIFF_CODE);
963 }
964
965 if (strRH.find(RASTER_AVG_SEA_DEPTH_CODE) != string::npos)
966 {
967 m_bAvgSeaDepthSave = true;
969 }
970
971 if (strRH.find(RASTER_AVG_WAVE_HEIGHT_CODE) != string::npos)
972 {
975 }
976
977 if (strRH.find(RASTER_AVG_WAVE_ORIENTATION_CODE) != string::npos)
978 {
979 m_bAvgWaveAngleSave = true;
981 }
982
983 if (strRH.find(RASTER_BEACH_PROTECTION_CODE) != string::npos)
984 {
987 }
988
989 if (strRH.find(RASTER_BASEMENT_ELEVATION_CODE) != string::npos)
990 {
991 m_bBasementElevSave = true;
993 }
994
995 if (strRH.find(RASTER_SUSP_SED_CODE) != string::npos)
996 {
997 m_bSuspSedSave = true;
998 strRH = strRemoveSubstr(&strRH, &RASTER_SUSP_SED_CODE);
999 }
1000
1001 if (strRH.find(RASTER_AVG_SUSP_SED_CODE) != string::npos)
1002 {
1003 m_bAvgSuspSedSave = true;
1004 strRH = strRemoveSubstr(&strRH, &RASTER_AVG_SUSP_SED_CODE);
1005 }
1006
1007 if (strRH.find(RASTER_FINE_UNCONS_CODE) != string::npos)
1008 {
1009 m_bFineUnconsSedSave = true;
1010 strRH = strRemoveSubstr(&strRH, &RASTER_FINE_UNCONS_CODE);
1011 }
1012
1013 if (strRH.find(RASTER_SAND_UNCONS_CODE) != string::npos)
1014 {
1015 m_bSandUnconsSedSave = true;
1016 strRH = strRemoveSubstr(&strRH, &RASTER_SAND_UNCONS_CODE);
1017 }
1018
1019 if (strRH.find(RASTER_COARSE_UNCONS_CODE) != string::npos)
1020 {
1023 }
1024
1025 if (strRH.find(RASTER_FINE_CONS_CODE) != string::npos)
1026 {
1027 m_bFineConsSedSave = true;
1028 strRH = strRemoveSubstr(&strRH, &RASTER_FINE_CONS_CODE);
1029 }
1030
1031 if (strRH.find(RASTER_SAND_CONS_CODE) != string::npos)
1032 {
1033 m_bSandConsSedSave = true;
1034 strRH = strRemoveSubstr(&strRH, &RASTER_SAND_CONS_CODE);
1035 }
1036
1037 if (strRH.find(RASTER_COARSE_CONS_CODE) != string::npos)
1038 {
1039 m_bCoarseConsSedSave = true;
1040 strRH = strRemoveSubstr(&strRH, &RASTER_COARSE_CONS_CODE);
1041 }
1042
1043 if (strRH.find(RASTER_COAST_CODE) != string::npos)
1044 {
1046 strRH = strRemoveSubstr(&strRH, &RASTER_COAST_CODE);
1047 }
1048
1049 if (strRH.find(RASTER_COAST_NORMAL_CODE) != string::npos)
1050 {
1052 strRH = strRemoveSubstr(&strRH, &RASTER_COAST_NORMAL_CODE);
1053 }
1054
1055 if (strRH.find(RASTER_ACTIVE_ZONE_CODE) != string::npos)
1056 {
1057 m_bActiveZoneSave = true;
1058 strRH = strRemoveSubstr(&strRH, &RASTER_ACTIVE_ZONE_CODE);
1059 }
1060
1061 if (strRH.find(RASTER_CLIFF_COLLAPSE_EROSION_FINE_CODE) != string::npos)
1062 {
1063 m_bCliffCollapseSave = true;
1065 }
1066
1067 if (strRH.find(RASTER_CLIFF_COLLAPSE_EROSION_SAND_CODE) != string::npos)
1068 {
1069 m_bCliffCollapseSave = true;
1071 }
1072
1073 if (strRH.find(RASTER_CLIFF_COLLAPSE_EROSION_COARSE_CODE) != string::npos)
1074 {
1075 m_bCliffCollapseSave = true;
1077 }
1078
1079 if (strRH.find(RASTER_TOTAL_CLIFF_COLLAPSE_EROSION_FINE_CODE) != string::npos)
1080 {
1083 }
1084
1085 if (strRH.find(RASTER_TOTAL_CLIFF_COLLAPSE_EROSION_SAND_CODE) != string::npos)
1086 {
1089 }
1090
1091 if (strRH.find(RASTER_TOTAL_CLIFF_COLLAPSE_EROSION_COARSE_CODE) != string::npos)
1092 {
1095 }
1096
1097 if (strRH.find(RASTER_CLIFF_COLLAPSE_DEPOSITION_SAND_CODE) != string::npos)
1098 {
1101 }
1102
1103 if (strRH.find(RASTER_CLIFF_COLLAPSE_DEPOSITION_COARSE_CODE) != string::npos)
1104 {
1107 }
1108
1109 if (strRH.find(RASTER_TOTAL_CLIFF_COLLAPSE_DEPOSITION_SAND_CODE) != string::npos)
1110 {
1113 }
1114
1115 if (strRH.find(RASTER_TOTAL_CLIFF_COLLAPSE_DEPOSITION_COARSE_CODE) != string::npos)
1116 {
1119 }
1120
1121 if (strRH.find(RASTER_POLYGON_CODE) != string::npos)
1122 {
1123 m_bRasterPolygonSave = true;
1124 strRH = strRemoveSubstr(&strRH, &RASTER_POLYGON_CODE);
1125 }
1126
1127 if (strRH.find(RASTER_POTENTIAL_PLATFORM_EROSION_MASK_CODE) != string::npos)
1128 {
1131 }
1132
1133 if (strRH.find(RASTER_INUNDATION_MASK_CODE) != string::npos)
1134 {
1135 m_bSeaMaskSave = true;
1137 }
1138
1139 if (strRH.find(RASTER_BEACH_MASK_CODE) != string::npos)
1140 {
1141 m_bBeachMaskSave = true;
1142 strRH = strRemoveSubstr(&strRH, &RASTER_BEACH_MASK_CODE);
1143 }
1144
1145 if (strRH.find(RASTER_INTERVENTION_CLASS_CODE) != string::npos)
1146 {
1149 }
1150
1151 if (strRH.find(RASTER_INTERVENTION_HEIGHT_CODE) != string::npos)
1152 {
1155 }
1156
1157 if (strRH.find(RASTER_SHADOW_ZONE_CODE) != string::npos)
1158 {
1160 strRH = strRemoveSubstr(&strRH, &RASTER_SHADOW_ZONE_CODE);
1161 }
1162
1163 if (strRH.find(RASTER_DEEP_WATER_WAVE_ORIENTATION_CODE) != string::npos)
1164 {
1167 }
1168
1169 if (strRH.find(RASTER_DEEP_WATER_WAVE_HEIGHT_CODE) != string::npos)
1170 {
1173 }
1174
1175 if (strRH.find(RASTER_DEEP_WATER_WAVE_PERIOD_CODE) != string::npos)
1176 {
1179 }
1180
1181 if (strRH.find(RASTER_POLYGON_UPDRIFT_OR_DOWNDRIFT_CODE) != string::npos)
1182 {
1185 }
1186
1187 if (strRH.find(RASTER_POLYGON_GAIN_OR_LOSS_CODE) != string::npos)
1188 {
1191 }
1192
1193 if (strRH.find(RASTER_BEACH_DEPOSITION_CODE) != string::npos)
1194 {
1197 }
1198
1199 if (strRH.find(RASTER_TOTAL_BEACH_DEPOSITION_CODE) != string::npos)
1200 {
1203 }
1204
1205 if (strRH.find(RASTER_SEDIMENT_INPUT_EVENT_CODE) != string::npos)
1206 {
1209 }
1210
1211 if (strRH.find(RASTER_SETUP_SURGE_FLOOD_MASK_CODE) != string::npos)
1212 {
1215 }
1216
1217 if (strRH.find(RASTER_SETUP_SURGE_RUNUP_FLOOD_MASK_CODE) != string::npos)
1218 {
1221 }
1222
1223 if (strRH.find(RASTER_WAVE_FLOOD_LINE_CODE) != string::npos)
1224 {
1227 }
1228
1229 // Check to see if all codes have been removed
1230 if (!strRH.empty())
1231 strErr = "line " + to_string(nLine) + ": unknown code '" + strRH + "' in list of codes for raster GIS output";
1232 }
1233 }
1234
1235 break;
1236
1237 case 12:
1238 // Raster GIS output format (note must retain original case). Blank means use same format as input DEM file (if possible)
1240
1241 // TODO 065 Remove this when GDAL gpkg raster output is working correctly
1242 if (strRH.find("gpkg") != string::npos)
1243 strErr = "GDAL gpkg raster create() is not yet working correctly. Please choose another output format.";
1244
1245 break;
1246
1247 case 13:
1248 // If needed, scale GIS raster output values
1249 strRH = strToLower(&strRH);
1250
1251 m_bScaleRasterOutput = false;
1252
1253 if (strRH.find('y') != string::npos)
1254 m_bScaleRasterOutput = true;
1255
1256 break;
1257
1258 case 14:
1259 // If needed, also output GIS raster world file
1260 strRH = strToLower(&strRH);
1261
1262 m_bWorldFile = false;
1263
1264 if (strRH.find('y') != string::npos)
1265 m_bWorldFile = true;
1266
1267 break;
1268
1269 case 15:
1270 // Elevations for raster slice output, if desired
1271 if (!strRH.empty())
1272 {
1273 m_bSliceSave = true;
1274
1275 // OK, so find out whether we're dealing with a single seed or more than one: check for a space
1276 nPos = strRH.find(SPACE);
1277
1278 if (nPos != string::npos)
1279 {
1280 // There's a space, so we must have more than one number
1281 do
1282 {
1283 // Get LH bit
1284 strTmp = strRH.substr(0, nPos);
1285 m_VdSliceElev.push_back(strtod(strTmp.c_str(), NULL));
1286
1287 // Get the RH bit
1288 strRH = strRH.substr(nPos, strRH.size() - nPos);
1289 strRH = strTrimLeft(&strRH);
1290
1291 // Now look for another space
1292 nPos = strRH.find(SPACE);
1293 } while (nPos != string::npos);
1294 }
1295
1296 // Read either the single number, or the left-over number
1297 m_VdSliceElev.push_back(strtod(strTmp.c_str(), NULL));
1298 }
1299
1300 break;
1301
1302 case 16:
1303 // Vector GIS files to output
1304 if (strRH.empty())
1305 {
1306 strErr = "line ";
1307 strErr += to_string(nLine);
1308 strErr += ": must contain '";
1309 strErr += VECTOR_ALL_OUTPUT_CODE;
1310 strErr += "', or '";
1311 strErr += VECTOR_USUAL_OUTPUT_CODE;
1312 strErr += "', or at least one vector GIS output code";
1313 }
1314
1315 else
1316 {
1317 strRH = strToLower(&strRH);
1318
1319 if (strRH.find(VECTOR_ALL_OUTPUT_CODE) != string::npos)
1320 {
1321 // Output all vector files
1322 m_bCoastSave =
1340 m_bRunUpSave =
1342 }
1343
1344 else if (strRH.find(VECTOR_USUAL_OUTPUT_CODE) != string::npos)
1345 {
1346 // Output the "usual" collection of vector output files
1347 m_bCoastSave =
1361 }
1362
1363 else
1364 {
1365 // Output only those vector files for which the user specified the code
1366 if (strRH.find(VECTOR_COAST_CODE) != string::npos)
1367 {
1368 m_bCoastSave = true;
1369 strRH = strRemoveSubstr(&strRH, &VECTOR_COAST_CODE);
1370 }
1371
1372 if (strRH.find(VECTOR_CLIFF_EDGE_CODE) != string::npos)
1373 {
1374 m_bCliffEdgeSave = true;
1375 strRH = strRemoveSubstr(&strRH, &VECTOR_CLIFF_EDGE_CODE);
1376 }
1377
1378 if (strRH.find(VECTOR_AVG_WAVE_ANGLE_AND_HEIGHT_CODE) != string::npos)
1379 {
1382 }
1383
1384 if (strRH.find(VECTOR_NORMALS_CODE) != string::npos)
1385 {
1386 m_bNormalsSave = true;
1387 strRH = strRemoveSubstr(&strRH, &VECTOR_NORMALS_CODE);
1388 }
1389
1390 if (strRH.find(VECTOR_INVALID_NORMALS_CODE) != string::npos)
1391 {
1392 m_bInvalidNormalsSave = true;
1394 }
1395
1396 if (strRH.find(VECTOR_AVG_WAVE_ANGLE_AND_HEIGHT_CODE) != string::npos)
1397 {
1400 }
1401
1402 if (strRH.find(VECTOR_COAST_CURVATURE_CODE) != string::npos)
1403 {
1404 m_bCoastCurvatureSave = true;
1406 }
1407
1408 if (strRH.find(VECTOR_WAVE_ENERGY_SINCE_COLLAPSE_CODE) != string::npos)
1409 {
1412 }
1413
1414 if (strRH.find(VECTOR_MEAN_WAVE_ENERGY_CODE) != string::npos)
1415 {
1416 m_bMeanWaveEnergySave = true;
1418 }
1419
1420 if (strRH.find(VECTOR_BREAKING_WAVE_HEIGHT_CODE) != string::npos)
1421 {
1424 }
1425
1426 if (strRH.find(VECTOR_POLYGON_NODE_CODE) != string::npos)
1427 {
1428 m_bPolygonNodeSave = true;
1429 strRH = strRemoveSubstr(&strRH, &VECTOR_POLYGON_NODE_CODE);
1430 }
1431
1432 if (strRH.find(VECTOR_POLYGON_BOUNDARY_CODE) != string::npos)
1433 {
1436 }
1437
1438 if (strRH.find(VECTOR_CLIFF_NOTCH_SIZE_CODE) != string::npos)
1439 {
1440 m_bCliffNotchSave = true;
1442 }
1443
1444 if (strRH.find(VECTOR_SHADOW_BOUNDARY_CODE) != string::npos)
1445 {
1446 m_bShadowBoundarySave = true;
1448 }
1449
1450 if (strRH.find(VECTOR_DOWNDRIFT_BOUNDARY_CODE) != string::npos)
1451 {
1454 }
1455
1456 if (strRH.find(VECTOR_DEEP_WATER_WAVE_ANGLE_AND_HEIGHT_CODE) != string::npos)
1457 {
1460 }
1461
1462 if (strRH.find(VECTOR_WAVE_SETUP_CODE) != string::npos)
1463 {
1464 m_bWaveSetupSave = true;
1465 strRH = strRemoveSubstr(&strRH, &VECTOR_WAVE_SETUP_CODE);
1466 }
1467
1468 if (strRH.find(VECTOR_STORM_SURGE_CODE) != string::npos)
1469 {
1470 m_bStormSurgeSave = true;
1471 strRH = strRemoveSubstr(&strRH, &VECTOR_STORM_SURGE_CODE);
1472 }
1473
1474 if (strRH.find(VECTOR_RUN_UP_CODE) != string::npos)
1475 {
1476 m_bRunUpSave = true;
1477 strRH = strRemoveSubstr(&strRH, &VECTOR_RUN_UP_CODE);
1478 }
1479
1480 if (strRH.find(VECTOR_FLOOD_LINE_CODE) != string::npos)
1481 {
1483 strRH = strRemoveSubstr(&strRH, &VECTOR_FLOOD_LINE_CODE);
1484 }
1485
1486 // Check to see if all codes have been removed
1487 if (!strRH.empty())
1488 strErr = "line " + to_string(nLine) + ": unknown code '" + strRH + "' in list of vector GIS output codes";
1489 }
1490 }
1491
1492 break;
1493
1494 case 17:
1495 // Vector GIS output format (note must retain original case)
1497
1498 if (strRH.empty())
1499 strErr = "line " + to_string(nLine) + ": vector GIS output format";
1500
1501 break;
1502
1503 case 18:
1504 // Time series files to output
1505 if (!strRH.empty())
1506 {
1507 strRH = strToLower(&strRH);
1508
1509 // First check for "all"
1510 if (strRH.find(RASTER_ALL_OUTPUT_CODE) != string::npos)
1511 {
1524 }
1525
1526 else
1527 {
1528 if (strRH.find(TIME_SERIES_SEA_AREA_CODE) != string::npos)
1529 {
1530 m_bSeaAreaTSSave = true;
1532 }
1533
1534 if (strRH.find(TIME_SERIES_STILL_WATER_LEVEL_CODE) != string::npos)
1535 {
1538 }
1539
1540 if (strRH.find(TIME_SERIES_PLATFORM_EROSION_CODE) != string::npos)
1541 {
1544 }
1545
1546 if (strRH.find(TIME_SERIES_CLIFF_COLLAPSE_EROSION_CODE) != string::npos)
1547 {
1550 }
1551
1552 if (strRH.find(TIME_SERIES_CLIFF_COLLAPSE_DEPOSITION_CODE) != string::npos)
1553 {
1556 }
1557
1558 if (strRH.find(TIME_SERIES_CLIFF_COLLAPSE_NET_CODE) != string::npos)
1559 {
1562 }
1563
1564 if (strRH.find(TIME_SERIES_BEACH_EROSION_CODE) != string::npos)
1565 {
1566 m_bBeachErosionTSSave = true;
1568 }
1569
1570 if (strRH.find(TIME_SERIES_BEACH_DEPOSITION_CODE) != string::npos)
1571 {
1574 }
1575
1576 if (strRH.find(TIME_SERIES_BEACH_CHANGE_NET_CODE) != string::npos)
1577 {
1580 }
1581
1582 if (strRH.find(TIME_SERIES_SUSPENDED_SEDIMENT_CODE) != string::npos)
1583 {
1584 m_bSuspSedTSSave = true;
1586 }
1587
1588 if (strRH.find(TIME_SERIES_FLOOD_SETUP_SURGE_CODE) != string::npos)
1589 {
1592 }
1593
1594 if (strRH.find(TIME_SERIES_FLOOD_SETUP_SURGE_RUNUP_CODE) != string::npos)
1595 {
1598 }
1599
1600 // Check to see if all codes have been removed
1601 if (!strRH.empty())
1602 strErr = "line " + to_string(nLine) + ": unknown code '" + strRH + "' in list of time series output files";
1603 }
1604 }
1605
1606 break;
1607
1608 case 19:
1609 // Vector coastline smoothing algorithm: 0 = none, 1 = running mean, 2 = Savitzky-Golay
1610 if (!bIsStringValidInt(strRH))
1611 {
1612 strErr = "line " + to_string(nLine) + ": invalid integer for coastline smoothing algorithm '" + strRH + "' in " + m_strDataPathName;
1613 break;
1614 }
1615
1616 m_nCoastSmooth = stoi(strRH);
1617
1619 strErr = "line " + to_string(nLine) + ": coastline vector smoothing algorithm";
1620
1621 break;
1622
1623 case 20:
1624 // Size of coastline smoothing window: must be odd
1625 if (!bIsStringValidInt(strRH))
1626 {
1627 strErr = "line " + to_string(nLine) + ": invalid integer for coastline smoothing window '" + strRH + "' in " + m_strDataPathName;
1628 break;
1629 }
1630
1631 m_nCoastSmoothingWindowSize = stoi(strRH);
1632
1634 strErr = "line " + to_string(nLine) + ": size of coastline vector smoothing window (must be > 0 and odd)";
1635
1636 break;
1637
1638 case 21:
1639 // Order of coastline profile smoothing polynomial for Savitzky-Golay: usually 2 or 4, max is 6
1640 if (!bIsStringValidInt(strRH))
1641 {
1642 strErr = "line " + to_string(nLine) + ": invalid integer for Savitzky-Golay polynomial for coastline smoothing '" + strRH + "' in " + m_strDataPathName;
1643 break;
1644 }
1645
1646 m_nSavGolCoastPoly = stoi(strRH);
1647
1648 if ((m_nSavGolCoastPoly <= 0) || (m_nSavGolCoastPoly > 6))
1649 strErr = "line " + to_string(nLine) + ": value of Savitzky-Golay polynomial for coastline smoothing (must be <= 6)";
1650
1651 break;
1652
1653 case 22:
1654 // Grid edge(s) to omit when searching for coastline [NSWE]
1655 strRH = strToLower(&strRH);
1656
1657 if (strRH.find('n') != string::npos)
1658 {
1660 }
1661
1662 if (strRH.find('s') != string::npos)
1663 {
1665 }
1666
1667 if (strRH.find('w') != string::npos)
1668 {
1669 m_bOmitSearchWestEdge = true;
1670 }
1671
1672 if (strRH.find('e') != string::npos)
1673 {
1674 m_bOmitSearchEastEdge = true;
1675 }
1676
1677 break;
1678
1679 case 23:
1680 // Profile slope running-mean smoothing window size: must be odd
1681 if (!bIsStringValidInt(strRH))
1682 {
1683 strErr = "line " + to_string(nLine) + ": invalid integer for size of coastline smoothing window '" + strRH + "' in " + m_strDataPathName;
1684 break;
1685 }
1686
1687 m_nProfileSmoothWindow = stoi(strRH);
1688
1690 strErr = "line " + to_string(nLine) + ": size of profile vector smoothing window (must be >= 0, if > 0 must be odd)";
1691
1692 break;
1693
1694 case 24:
1695 // Max local slope (m/m), first check that this is a valid double
1696 if (!bIsStringValidDouble(strRH))
1697 {
1698 strErr = "line " + to_string(nLine) + ": invalid floating point number for max local slope '" + strRH + "' in " + m_strDataPathName;
1699 break;
1700 }
1701
1702 m_dProfileMaxSlope = strtod(strRH.c_str(), NULL);
1703
1704 if (m_dProfileMaxSlope <= 0)
1705 strErr = "line " + to_string(nLine) + ": max local slope must be > 0";
1706
1707 break;
1708
1709 case 25:
1710 // Maximum elevation of beach above SWL, first check that this is a valid double
1711 if (!bIsStringValidDouble(strRH))
1712 {
1713 strErr = "line " + to_string(nLine) + ": invalid floating point number for maximum elevation of beach above SWL '" + strRH + "' in " + m_strDataPathName;
1714 break;
1715 }
1716
1717 m_dMaxBeachElevAboveSWL = strtod(strRH.c_str(), NULL);
1718
1720 strErr = "line " + to_string(nLine) + ": maximum elevation of beach above SWL must be >= 0";
1721
1722 break;
1723
1724 // ------------------------------------------------- Raster GIS layers ------------------------------------------------
1725 case 26:
1726 // Number of sediment layers
1727 if (!bIsStringValidInt(strRH))
1728 {
1729 strErr = "line " + to_string(nLine) + ": invalid integer for number of sediment layers '" + strRH + "' in " + m_strDataPathName;
1730 break;
1731 }
1732
1733 m_nLayers = stoi(strRH);
1734
1735 if (m_nLayers < 1)
1736 {
1737 strErr = "line " + to_string(nLine) + ": must be at least one sediment layer";
1738 break;
1739 }
1740
1741 // OK we know the number of layers, so add elements to these vectors
1742 for (int j = 0; j < m_nLayers; j++)
1743 {
1750 m_VstrGDALIUFDriverCode.push_back("");
1751 m_VstrGDALIUFDriverDesc.push_back("");
1752 m_VstrGDALIUFProjection.push_back("");
1753 m_VstrGDALIUFDataType.push_back("");
1754 m_VstrGDALIUSDriverCode.push_back("");
1755 m_VstrGDALIUSDriverDesc.push_back("");
1756 m_VstrGDALIUSProjection.push_back("");
1757 m_VstrGDALIUSDataType.push_back("");
1758 m_VstrGDALIUCDriverCode.push_back("");
1759 m_VstrGDALIUCDriverDesc.push_back("");
1760 m_VstrGDALIUCProjection.push_back("");
1761 m_VstrGDALIUCDataType.push_back("");
1762 m_VstrGDALICFDriverCode.push_back("");
1763 m_VstrGDALICFDriverDesc.push_back("");
1764 m_VstrGDALICFProjection.push_back("");
1765 m_VstrGDALICFDataType.push_back("");
1766 m_VstrGDALICSDriverCode.push_back("");
1767 m_VstrGDALICSDriverDesc.push_back("");
1768 m_VstrGDALICSProjection.push_back("");
1769 m_VstrGDALICSDataType.push_back("");
1770 m_VstrGDALICCDriverCode.push_back("");
1771 m_VstrGDALICCDriverDesc.push_back("");
1772 m_VstrGDALICCProjection.push_back("");
1773 m_VstrGDALICCDataType.push_back("");
1774 }
1775
1776 break;
1777
1778 case 27:
1779 // Basement DEM file (can be blank)
1780 if (!strRH.empty())
1781 {
1782#ifdef _WIN32
1783 // For Windows, make sure has backslashes, not Unix-style slashes
1784 strRH = pstrChangeToBackslash(&strRH);
1785#endif
1786
1787 // Now check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
1788 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
1789 // It has an absolute path, so use it 'as is'
1791
1792 else
1793 {
1794 // It has a relative path, so prepend the CoastalME dir
1796 m_strInitialBasementDEMFile.append(strRH);
1797 }
1798 }
1799
1800 break;
1801
1802 case 28:
1803 // Read 6 x sediment files for each layer
1804 for (int nLayer = 0; nLayer < m_nLayers; nLayer++)
1805 {
1806 for (int j = 1; j <= 6; j++)
1807 {
1808 if (! bFirst)
1809 {
1810 do
1811 {
1812 if (!getline(InStream, strRec))
1813 {
1814 cerr << ERR << "premature end of file in " << m_strDataPathName << endl;
1815 return false;
1816 }
1817
1818 nLine++;
1819
1820 // Trim off leading and trailing whitespace
1821 strRec = strTrim(&strRec);
1822 }
1823
1824 // If it is a blank line or a comment then ignore it
1825 while (strRec.empty() || (strRec[0] == QUOTE1) || (strRec[0] == QUOTE2));
1826
1827 // Not blank or a comment, so find the colon: lines MUST have a colon separating data from leading description portion
1828 nPos = strRec.find(COLON);
1829
1830 if (nPos == string::npos)
1831 {
1832 // Error: badly formatted (no colon)
1833 cerr << ERR << "on line " << to_string(nLine) << ": badly formatted (no ':') in " << m_strDataPathName << endl
1834 << strRec << endl;
1835 return false;
1836 }
1837
1838 // Strip off leading portion (the bit up to and including the colon)
1839 strRH = strRec.substr(nPos + 1);
1840 // ERROR strRH.resize(nPos);
1841
1842 // Remove leading whitespace after the colon
1843 strRH = strTrimLeft(&strRH);
1844
1845 // Look for a trailing comment, if found then terminate string at that point and trim off any trailing whitespace
1846 nPos = strRH.rfind(QUOTE1);
1847
1848 if (nPos != string::npos)
1849 strRH.resize(nPos);
1850
1851 nPos = strRH.rfind(QUOTE2);
1852
1853 if (nPos != string::npos)
1854 strRH.resize(nPos);
1855
1856 // Trim trailing spaces
1857 strRH = strTrimRight(&strRH);
1858
1859#ifdef _WIN32
1860 // For Windows, make sure has backslashes, not Unix-style slashes
1861 strRH = pstrChangeToBackslash(&strRH);
1862#endif
1863 }
1864
1865 bFirst = false;
1866
1867 switch (j)
1868 {
1869 case 1:
1870
1871 // Initial fine unconsolidated sediment depth GIS file (can be blank)
1872 if (!strRH.empty())
1873 {
1874 // Set switch
1875 m_bHaveFineSediment = true;
1876#ifdef _WIN32
1877 // For Windows, make sure has backslashes, not Unix-style slashes
1878 strRH = pstrChangeToBackslash(&strRH);
1879#endif
1880
1881 // Now check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
1882 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
1883 {
1884 // It has an absolute path, so use it 'as is'
1886 }
1887
1888 else
1889 {
1890 // It has a relative path, so prepend the CoastalME dir
1892 m_VstrInitialFineUnconsSedimentFile[nLayer].append(strRH);
1893 }
1894 }
1895
1896 break;
1897
1898 case 2:
1899 // Initial sand unconsolidated sediment depth GIS file (can be blank)
1900 if (!strRH.empty())
1901 {
1902 // Set switch
1903 m_bHaveSandSediment = true;
1904#ifdef _WIN32
1905 // For Windows, make sure has backslashes, not Unix-style slashes
1906 strRH = pstrChangeToBackslash(&strRH);
1907#endif
1908
1909 // Now check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
1910 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
1911 {
1912 // It has an absolute path, so use it 'as is'
1914 }
1915
1916 else
1917 {
1918 // It has a relative path, so prepend the CoastalME dir
1920 m_VstrInitialSandUnconsSedimentFile[nLayer].append(strRH);
1921 }
1922 }
1923
1924 break;
1925
1926 case 3:
1927 // Initial coarse unconsolidated sediment depth GIS file (can be blank)
1928 if (!strRH.empty())
1929 {
1930 // Set switch
1931 m_bHaveCoarseSediment = true;
1932#ifdef _WIN32
1933 // For Windows, make sure has backslashes, not Unix-style slashes
1934 strRH = pstrChangeToBackslash(&strRH);
1935#endif
1936
1937 // Now check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
1938 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
1939 {
1940 // It has an absolute path, so use it 'as is'
1942 }
1943
1944 else
1945 {
1946 // It has a relative path, so prepend the CoastalME dir
1948 m_VstrInitialCoarseUnconsSedimentFile[nLayer].append(strRH);
1949 }
1950 }
1951
1952 break;
1953
1954 case 4:
1955 // Initial fine consolidated sediment depth GIS file (can be blank)
1956 if (!strRH.empty())
1957 {
1958 // Set switches
1960 m_bHaveFineSediment = true;
1961#ifdef _WIN32
1962 // For Windows, make sure has backslashes, not Unix-style slashes
1963 strRH = pstrChangeToBackslash(&strRH);
1964#endif
1965
1966 // Now check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
1967 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
1968 {
1969 // It has an absolute path, so use it 'as is'
1970 m_VstrInitialFineConsSedimentFile[nLayer] = strRH;
1971 }
1972
1973 else
1974 {
1975 // It has a relative path, so prepend the CoastalME dir
1977 m_VstrInitialFineConsSedimentFile[nLayer].append(strRH);
1978 }
1979 }
1980
1981 break;
1982
1983 case 5:
1984 // Initial sand consolidated sediment depth GIS file (can be blank)
1985 if (!strRH.empty())
1986 {
1987 // Set switches
1989 m_bHaveSandSediment = true;
1990#ifdef _WIN32
1991 // For Windows, make sure has backslashes, not Unix-style slashes
1992 strRH = pstrChangeToBackslash(&strRH);
1993#endif
1994
1995 // Now check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
1996 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
1997 {
1998 // It has an absolute path, so use it 'as is'
1999 m_VstrInitialSandConsSedimentFile[nLayer] = strRH;
2000 }
2001
2002 else
2003 {
2004 // It has a relative path, so prepend the CoastalME dir
2006 m_VstrInitialSandConsSedimentFile[nLayer].append(strRH);
2007 }
2008 }
2009
2010 break;
2011
2012 case 6:
2013 // Initial coarse consolidated sediment depth GIS file (can be blank)
2014 if (!strRH.empty())
2015 {
2016 // Set switches
2018 m_bHaveCoarseSediment = true;
2019#ifdef _WIN32
2020 // For Windows, make sure has backslashes, not Unix-style slashes
2021 strRH = pstrChangeToBackslash(&strRH);
2022#endif
2023
2024 // Now check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
2025 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
2026 {
2027 // It has an absolute path, so use it 'as is'
2029 }
2030
2031 else
2032 {
2033 // It has a relative path, so prepend the CoastalME dir
2035 m_VstrInitialCoarseConsSedimentFile[nLayer].append(strRH);
2036 }
2037 }
2038
2039 break;
2040 }
2041
2042 // Did an error occur?
2043 if (!strErr.empty())
2044 {
2045 // Error in input to run details file
2046 cerr << ERR << "reading " << strErr << " in " << m_strDataPathName << endl
2047 << "'" << strRec << "'" << endl;
2048 InStream.close();
2049 return false;
2050 }
2051 }
2052 }
2053
2054 break;
2055
2056 case 29:
2057 // Initial suspended sediment depth GIS file (can be blank)
2058 if (!strRH.empty())
2059 {
2060 // Set switch
2061 m_bHaveFineSediment = true;
2062#ifdef _WIN32
2063 // For Windows, make sure has backslashes, not Unix-style slashes
2064 strRH = pstrChangeToBackslash(&strRH);
2065#endif
2066
2067 // Now check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
2068 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
2069 {
2070 // It has an absolute path, so use it 'as is'
2072 }
2073
2074 else
2075 {
2076 // It has a relative path, so prepend the CoastalME dir
2078 m_strInitialSuspSedimentFile.append(strRH);
2079 }
2080 }
2081
2082 break;
2083
2084 case 30:
2085 // Initial Landform class GIS file (can be blank)
2086 if (!strRH.empty())
2087 {
2088#ifdef _WIN32
2089 // For Windows, make sure has backslashes, not Unix-style slashes
2090 strRH = pstrChangeToBackslash(&strRH);
2091#endif
2092
2093 // Now check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
2094 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
2095 {
2096 // It has an absolute path, so use it 'as is'
2098 }
2099
2100 else
2101 {
2102 // It has a relative path, so prepend the CoastalME dir
2104 m_strInitialLandformFile.append(strRH);
2105 }
2106 }
2107
2108 break;
2109
2110 case 31:
2111 // Initial Intervention class GIS file (can be blank: if so then intervention height file must also be blank)
2112 if (!strRH.empty())
2113 {
2114#ifdef _WIN32
2115 // For Windows, make sure has backslashes, not Unix-style slashes
2116 strRH = pstrChangeToBackslash(&strRH);
2117#endif
2118
2119 // Now check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
2120 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
2121 {
2122 // It has an absolute path, so use it 'as is'
2124 }
2125
2126 else
2127 {
2128 // It has a relative path, so prepend the CoastalME dir
2130 m_strInterventionClassFile.append(strRH);
2131 }
2132
2133 // Set the save switches
2136 }
2137
2138 break;
2139
2140 case 32:
2141 // Initial Intervention height GIS file (can be blank: if so then intervention class file must also be blank)
2142 if (strRH.empty())
2143 {
2144 if (!m_strInterventionClassFile.empty())
2145 strErr = "line " + to_string(nLine) + ": must specify both intervention class and intervention height files";
2146
2147 break;
2148 }
2149
2150 else
2151 {
2152 if (m_strInterventionClassFile.empty())
2153 {
2154 strErr = "line " + to_string(nLine) + ": must specify both intervention class and intervention height files";
2155 break;
2156 }
2157
2158#ifdef _WIN32
2159 // For Windows, make sure has backslashes, not Unix-style slashes
2160 strRH = pstrChangeToBackslash(&strRH);
2161#endif
2162
2163 // Now check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
2164 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
2165 {
2166 // It has an absolute path, so use it 'as is'
2168 }
2169
2170 else
2171 {
2172 // It has a relative path, so prepend the CoastalME dir
2174 m_strInterventionHeightFile.append(strRH);
2175 }
2176 }
2177
2178 break;
2179
2180 // ---------------------------------------------------- Hydrology data ------------------------------------------------
2181 case 33:
2182 // Wave propagation model [0 = COVE, 1 = CShore]
2183 if (!bIsStringValidInt(strRH))
2184 {
2185 strErr = "line " + to_string(nLine) + ": invalid integer for wave propagation model '" + strRH + "' in " + m_strDataPathName;
2186 break;
2187 }
2188
2189 m_nWavePropagationModel = stoi(strRH);
2190
2192 strErr = "line " + to_string(nLine) + ": wave propagation model must be 0 or 1";
2193
2194 break;
2195
2196 case 34:
2197 // Density of sea water (kg/m3), first check that this is a valid double
2198 if (!bIsStringValidDouble(strRH))
2199 {
2200 strErr = "line " + to_string(nLine) + ": invalid floating point number for sea water density '" + strRH + "' in " + m_strDataPathName;
2201 break;
2202 }
2203
2204 m_dSeaWaterDensity = strtod(strRH.c_str(), NULL);
2205
2206 if (m_dSeaWaterDensity <= 0)
2207 strErr = "line " + to_string(nLine) + ": sea water density must be > 0";
2208
2209 break;
2210
2211 case 35:
2212 // Initial mean still water level (m), first check that this is a valid double TODO 041 Make this a per-timestep SWL file
2213 if (!bIsStringValidDouble(strRH))
2214 {
2215 strErr = "line " + to_string(nLine) + ": invalid floating point number for initial SWL '" + strRH + "' in " + m_strDataPathName;
2216 break;
2217 }
2218
2219 m_dInitialMeanSWL = strtod(strRH.c_str(), NULL);
2220 break;
2221
2222 case 36:
2223 // Final mean still water level (m) [blank = same as initial MSWL]
2224 if (strRH.empty())
2226
2227 else
2228 {
2229 // Check that this is a valid double
2230 if (!bIsStringValidDouble(strRH))
2231 {
2232 strErr = "line " + to_string(nLine) + ": invalid floating point number for final SWL '" + strRH + "' in " + m_strDataPathName;
2233 break;
2234 }
2235
2236 m_dFinalMeanSWL = strtod(strRH.c_str(), NULL);
2237 }
2238
2239 break;
2240
2241 case 37:
2242 // Deep water wave height (m) or a file of point vectors giving deep water wave height (m) and orientation (for units, see below)
2243 if (strRH.empty())
2244 strErr = "line " + to_string(nLine) + ": deep water wave height in " + m_strDataPathName + " must be either a number or a filename (filename must not start with a number)";
2245
2246 else
2247 {
2248 if (isdigit(strRH.at(0))) // If this starts with a number then is a single value, otherwise is a filename. Note that filename must not start with number
2249 {
2250 // Just one value of wave height for all deep water cells, first check that this is a valid double
2251 if (!bIsStringValidDouble(strRH))
2252 {
2253 strErr = "line " + to_string(nLine) + ": invalid floating point number for deep water wave height '" + strRH + "' in " + m_strDataPathName;
2254 break;
2255 }
2256
2258 m_bHaveWaveStationData = false;
2259
2260 m_dAllCellsDeepWaterWaveHeight = strtod(strRH.c_str(), NULL);
2261
2263 strErr = "line " + to_string(nLine) + ": deep water wave height must be > 0";
2264 }
2265
2266 else
2267 {
2268 // We are reading deep water wave height and deep water wave orientation from two files. This first file is a point shape file with the location of the buoys and integer ID for each one
2270#ifdef _WIN32
2271 // For Windows, make sure has backslashes, not Unix-style slashes
2272 strRH = pstrChangeToBackslash(&strRH);
2273#endif
2274
2275 // Now check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
2276 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
2277 {
2278 // It has an absolute path, so use it 'as is'
2280 }
2281
2282 else
2283 {
2284 // It has a relative path, so prepend the CoastalME dir
2287 }
2288 }
2289 }
2290
2291 break;
2292
2293 case 38:
2294 // Deep water wave height input file. Each point in m_strDeepWaterWavesInputFile is a triad of wave height, orientation and period for each time step
2296 {
2297 if (strRH.empty())
2298 {
2299 strErr = "line " + to_string(nLine) + ": filename missing for deep water wave height input";
2300 break;
2301 }
2302
2303#ifdef _WIN32
2304 // For Windows, make sure has backslashes, not Unix-style slashes
2305 strRH = pstrChangeToBackslash(&strRH);
2306#endif
2307
2308 // Now check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
2309 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
2310 {
2311 // It has an absolute path, so use it 'as is'
2313 }
2314
2315 else
2316 {
2317 // It has a relative path, so prepend the CoastalME dir
2319 m_strDeepWaterWavesInputFile.append(strRH);
2320 }
2321 }
2322
2323 break;
2324
2325 case 39:
2326 // Deep water wave orientation in input CRS: this is the oceanographic convention i.e. direction TOWARDS which the waves move (in degrees clockwise from north)
2328 {
2329 // Only read this if we have just a single value of wave height for all deep water cells. Check that this is a valid double
2330 if (!bIsStringValidDouble(strRH))
2331 {
2332 strErr = "line " + to_string(nLine) + ": invalid floating point number for deep water wave orientation '" + strRH + "' in " + m_strDataPathName;
2333 break;
2334 }
2335
2336 m_dAllCellsDeepWaterWaveAngle = strtod(strRH.c_str(), NULL);
2337
2339 strErr = "line " + to_string(nLine) + ": deep water wave orientation must be zero degrees or more";
2340
2341 else if (m_dAllCellsDeepWaterWaveAngle >= 360)
2342 strErr = "line " + to_string(nLine) + ": deep water wave orientation must be less than 360 degrees";
2343 }
2344
2345 break;
2346
2347 case 40:
2348 // Wave period (sec)
2350 {
2351 // Only read this if we also have just a single value of wave height for all deep water cells. Check that this is a valid double
2352 if (!bIsStringValidDouble(strRH))
2353 {
2354 strErr = "line " + to_string(nLine) + ": invalid floating point number for wave period '" + strRH + "' in " + m_strDataPathName;
2355 break;
2356 }
2357
2358 m_dAllCellsDeepWaterWavePeriod = strtod(strRH.c_str(), NULL);
2359
2361 strErr = "line " + to_string(nLine) + ": wave period must be > 0";
2362 }
2363
2364 break;
2365
2366 case 41:
2367 // Tide data file (can be blank). This is the change (m) from still water level for each timestep
2368 if (!strRH.empty())
2369 {
2370#ifdef _WIN32
2371 // For Windows, make sure has backslashes, not Unix-style slashes
2372 strRH = pstrChangeToBackslash(&strRH);
2373#endif
2374
2375 // Now check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
2376 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
2377 // It has an absolute path, so use it 'as is'
2378 m_strTideDataFile = strRH;
2379
2380 else
2381 {
2382 // It has a relative path, so prepend the CoastalME dir
2384 m_strTideDataFile.append(strRH);
2385 }
2386 }
2387
2388 break;
2389
2390 case 42:
2391 // Breaking wave height-to-depth ratio, check that this is a valid double
2392 if (!bIsStringValidDouble(strRH))
2393 {
2394 strErr = "line " + to_string(nLine) + ": invalid floating point number for breaking wave height to depth ratio '" + strRH + "' in " + m_strDataPathName;
2395 break;
2396 }
2397
2398 m_dBreakingWaveHeightDepthRatio = strtod(strRH.c_str(), NULL);
2399
2401 strErr = "line " + to_string(nLine) + ": breaking wave height to depth ratio must be > 0";
2402
2403 break;
2404
2405 // ----------------------------------------------------- Sediment data ------------------------------------------------
2406 case 43:
2407 // Simulate coast platform erosion?
2408 strRH = strToLower(&strRH);
2409
2410 if (strRH.find('y') != string::npos)
2412
2413 break;
2414
2415 case 44:
2416 // If simulating coast platform erosion, R (coast platform resistance to erosion) values along profile, see Walkden & Hall, 2011
2418 {
2419 // First check that this is a valid double
2420 if (!bIsStringValidDouble(strRH))
2421 {
2422 strErr = "line " + to_string(nLine) + ": invalid floating point number for R (coast platform resistance to erosion) '" + strRH + "' in " + m_strDataPathName;
2423 break;
2424 }
2425
2426 m_dR = strtod(strRH.c_str(), NULL);
2427
2428 if (m_dR <= 0)
2429 strErr = "line " + to_string(nLine) + ": R (coast platform resistance to erosion) value must be > 0";
2430 }
2431
2432 break;
2433
2434 case 45:
2435 // Simulate beach sediment transport?
2436 strRH = strToLower(&strRH);
2437
2439
2440 if (strRH.find('y') != string::npos)
2442
2443 break;
2444
2445 case 46:
2446 // If simulating beach sediment transport, beach sediment transport at grid edges [0 = closed, 1 = open, 2 = re-circulate]
2448 {
2449 if (!bIsStringValidInt(strRH))
2450 {
2451 strErr = "line " + to_string(nLine) + ": invalid integer for beach sediment transport at grid edges '" + strRH + "' in " + m_strDataPathName;
2452 break;
2453 }
2454
2456
2458 strErr = "line " + to_string(nLine) + ": switch for handling of beach sediment at grid edges must be 0, 1, or 2";
2459 }
2460
2461 break;
2462
2463 case 47:
2464 // If simulating beach sediment transport, beach erosion/deposition equation [0 = CERC, 1 = Kamphuis]
2466 {
2467 if (!bIsStringValidInt(strRH))
2468 {
2469 strErr = "line " + to_string(nLine) + ": invalid integer for beach erosion/deposition equation '" + strRH + "' in " + m_strDataPathName;
2470 break;
2471 }
2472
2474
2476 strErr = "line " + to_string(nLine) + ": switch for beach erosion/deposition equation must be 0 or 1";
2477 }
2478
2479 break;
2480
2481 case 48:
2482 // Median size of fine sediment (mm), always needed [0 = default, only for Kamphuis eqn]. First check that this is a valid double
2483 if (!bIsStringValidDouble(strRH))
2484 {
2485 strErr = "line " + to_string(nLine) + ": invalid floating point number for median particle size of fine sediment '" + strRH + "' in " + m_strDataPathName;
2486 break;
2487 }
2488
2489 m_dD50Fine = strtod(strRH.c_str(), NULL);
2490
2491 if (m_dD50Fine < 0)
2492 strErr = "line " + to_string(nLine) + ": median particle size of fine sediment must be > 0";
2493
2494 else if (bFPIsEqual(m_dD50Fine, 0.0, TOLERANCE))
2495 // Use default value
2497
2498 break;
2499
2500 case 49:
2501 // Median size of sand sediment (mm), always needed [0 = default, only for Kamphuis eqn]. First check that this is a valid double
2502 if (!bIsStringValidDouble(strRH))
2503 {
2504 strErr = "line " + to_string(nLine) + ": invalid floating point number for median particle size of sand sediment '" + strRH + "' in " + m_strDataPathName;
2505 break;
2506 }
2507
2508 m_dD50Sand = strtod(strRH.c_str(), NULL);
2509
2510 if (m_dD50Sand < 0)
2511 strErr = "line " + to_string(nLine) + ": median particle size of sand sediment must be > 0";
2512
2513 else if (bFPIsEqual(m_dD50Sand, 0.0, TOLERANCE))
2514 // Use default value
2516
2517 break;
2518
2519 case 50:
2520 // Median size of coarse sediment (mm), always needed [0 = default, only for Kamphuis eqn]. First check that this is a valid double
2521 if (!bIsStringValidDouble(strRH))
2522 {
2523 strErr = "line " + to_string(nLine) + ": invalid floating point number for median particle size of coarse sediment '" + strRH + "' in " + m_strDataPathName;
2524 break;
2525 }
2526
2527 m_dD50Coarse = strtod(strRH.c_str(), NULL);
2528
2529 if (m_dD50Coarse < 0)
2530 strErr = "line " + to_string(nLine) + ": median particle size of coarse sediment must be > 0";
2531
2532 else if (bFPIsEqual(m_dD50Coarse, 0.0, TOLERANCE))
2533 // Use default value
2535
2536 break;
2537
2538 case 51:
2539 // Density of unconsolidated beach sediment (kg/m3)
2541 {
2542 // First check that this is a valid double
2543 if (!bIsStringValidDouble(strRH))
2544 {
2545 strErr = "line " + to_string(nLine) + ": invalid floating point number for density of beach sediment '" + strRH + "' in " + m_strDataPathName;
2546 break;
2547 }
2548
2549 m_dBeachSedimentDensity = strtod(strRH.c_str(), NULL);
2550
2551 if (m_dBeachSedimentDensity <= 0)
2552 strErr = "line " + to_string(nLine) + ": density of beach sediment must be > 0";
2553 }
2554
2555 break;
2556
2557 case 52:
2558 // Beach sediment porosity
2560 {
2561 // First check that this is a valid double
2562 if (!bIsStringValidDouble(strRH))
2563 {
2564 strErr = "line " + to_string(nLine) + ": invalid floating point number for porosity of beach sediment '" + strRH + "' in " + m_strDataPathName;
2565 break;
2566 }
2567
2568 m_dBeachSedimentPorosity = strtod(strRH.c_str(), NULL);
2569
2570 if (m_dBeachSedimentPorosity <= 0)
2571 strErr = "line " + to_string(nLine) + ": porosity of beach sediment must be > 0";
2572 }
2573
2574 break;
2575
2576 case 53:
2577 // Relative erodibility (0 - 1) of fine-sized sediment, always needed. First check that this is a valid double
2578 if (!bIsStringValidDouble(strRH))
2579 {
2580 strErr = "line " + to_string(nLine) + ": invalid floating point number for erodibility of fine-sized sediment '" + strRH + "' in " + m_strDataPathName;
2581 break;
2582 }
2583
2584 m_dFineErodibility = strtod(strRH.c_str(), NULL);
2585
2586 if ((m_dFineErodibility < 0) || (m_dFineErodibility > 1))
2587 strErr = "line " + to_string(nLine) + ": relative erodibility of fine-sized sediment must be between 0 and 1";
2588
2589 break;
2590
2591 case 54:
2592 // Relative erodibility (0 - 1) of sand-sized sediment, always needed. First check that this is a valid double
2593 if (!bIsStringValidDouble(strRH))
2594 {
2595 strErr = "line " + to_string(nLine) + ": invalid floating point number for erodibility of sand-sized sediment '" + strRH + "' in " + m_strDataPathName;
2596 break;
2597 }
2598
2599 m_dSandErodibility = strtod(strRH.c_str(), NULL);
2600
2601 if ((m_dSandErodibility < 0) || (m_dSandErodibility > 1))
2602 strErr = "line " + to_string(nLine) + ": relative erodibility of sand-sized sediment must be between 0 and 1";
2603
2604 break;
2605
2606 case 55:
2607 // Relative erodibility (0 - 1) of coarse-sized sediment, always needed. First check that this is a valid double
2608 if (!bIsStringValidDouble(strRH))
2609 {
2610 strErr = "line " + to_string(nLine) + ": invalid floating point number for erodibility of coarse-sized sediment '" + strRH + "' in " + m_strDataPathName;
2611 break;
2612 }
2613
2614 m_dCoarseErodibility = strtod(strRH.c_str(), NULL);
2615
2616 if ((m_dCoarseErodibility < 0) || (m_dCoarseErodibility > 1))
2617 {
2618 strErr = "line " + to_string(nLine) + ": relative erodibility of coarse-sized sediment must be between 0 and 1";
2619 break;
2620 }
2621
2623 strErr = "line " + to_string(nLine) + ": must have at least one non-zero erodibility value";
2624
2625 break;
2626
2627 case 56:
2628 // Transport parameter KLS in CERC equation
2630 {
2631 // First check that this is a valid double
2632 if (!bIsStringValidDouble(strRH))
2633 {
2634 strErr = "line " + to_string(nLine) + ": invalid floating point number for transport parameter KLS of CERC equation '" + strRH + "' in " + m_strDataPathName;
2635 break;
2636 }
2637
2638 m_dKLS = strtod(strRH.c_str(), NULL);
2639
2640 // However, many sites do not have transport data available to calibrate K, and for design applications without calibration data the CERC formula provides only order-of-magnitude accuracy (Fowler et al., 1995; Wang et al., 1998). The recommended value of K = 0.39 has been commonly used to represent the potential longshore transport rate. However, Miller (1998) found that the CERC formula sometimes over and sometimes under predicted longshore transport rate for measurements during storms, indicating the value of K also can be higher than 0.39
2641 // TODO 042 Should this be a user input, or not? The comment above seems inconclusive
2642 // m_dKLS = tMin(m_dKLS, 0.39);
2643
2644 if (m_dKLS <= 0)
2645 strErr = "line " + to_string(nLine) + ": transport parameter KLS of CERC equation must be > 0";
2646 }
2647
2648 break;
2649
2650 case 57:
2651 // Transport parameter for Kamphuis equation
2653 {
2654 // First check that this is a valid double
2655 if (!bIsStringValidDouble(strRH))
2656 {
2657 strErr = "line " + to_string(nLine) + ": invalid floating point number for transport parameter of Kamphuis equation '" + strRH + "' in " + m_strDataPathName;
2658 break;
2659 }
2660
2661 m_dKamphuis = strtod(strRH.c_str(), NULL);
2662
2663 if (m_dKamphuis <= 0)
2664 strErr = "line " + to_string(nLine) + ": transport parameter of Kamphuis equation must be > 0";
2665 }
2666
2667 break;
2668
2669 case 58:
2670 // Berm height i.e. height above SWL of start of depositional Dean profile
2672 {
2673 // First check that this is a valid double
2674 if (!bIsStringValidDouble(strRH))
2675 {
2676 strErr = "line " + to_string(nLine) + ": invalid floating point number for Dean profile start height above SWL '" + strRH + "' in " + m_strDataPathName;
2677 break;
2678 }
2679
2680 m_dDeanProfileStartAboveSWL = strtod(strRH.c_str(), NULL);
2681
2683 strErr = "line " + to_string(nLine) + ": Berm height (Dean profile start height above SWL) must be >= 0";
2684 }
2685
2686 break;
2687
2688 // ------------------------------------------------ Cliff collapse data -----------------------------------------------
2689 case 59:
2690 // Simulate cliff collapse?
2692 {
2693 // Only consider cliff collapse if we have some consolidated sedimemt
2694 strRH = strToLower(&strRH);
2695
2696 if (strRH.find('y') != string::npos)
2697 m_bDoCliffCollapse = true;
2698 }
2699
2700 break;
2701
2702 case 60:
2703 // Cliff resistance to erosion
2705 {
2706 // First check that this is a valid double
2707 if (!bIsStringValidDouble(strRH))
2708 {
2709 strErr = "line " + to_string(nLine) + ": invalid floating point number for cliff resistance to erosion '" + strRH + "' in " + m_strDataPathName;
2710 break;
2711 }
2712
2713 m_dCliffErosionResistance = strtod(strRH.c_str(), NULL);
2714
2716 strErr = "line " + to_string(nLine) + ": cliff resistance to erosion must be > 0";
2717 }
2718
2719 break;
2720
2721 case 61:
2722 // Notch overhang at collapse (m)
2724 {
2725 // First check that this is a valid double
2726 if (!bIsStringValidDouble(strRH))
2727 {
2728 strErr = "line " + to_string(nLine) + ": invalid floating point number for cliff notch overhang at collapse '" + strRH + "' in " + m_strDataPathName;
2729 break;
2730 }
2731
2732 m_dNotchDepthAtCollapse = strtod(strRH.c_str(), NULL);
2733
2734 if (m_dNotchDepthAtCollapse <= 0)
2735 strErr = "line " + to_string(nLine) + ": cliff notch overhang at collapse must be > 0";
2736 }
2737
2738 break;
2739
2740 case 62:
2741 // Notch base below still water level (m)
2743 {
2744 m_dNotchBaseBelowSWL = strtod(strRH.c_str(), NULL);
2745
2746 if (m_dNotchBaseBelowSWL < 0)
2747 strErr = "line " + to_string(nLine) + ": cliff notch base below still water level must be > 0";
2748 }
2749
2750 break;
2751
2752 case 63:
2753 // Scale parameter A for cliff deposition (m^(1/3)) [0 = auto]
2755 {
2756 // First check that this is a valid double
2757 if (!bIsStringValidDouble(strRH))
2758 {
2759 strErr = "line " + to_string(nLine) + ": invalid floating point number for scale parameter A for cliff deposition '" + strRH + "' in " + m_strDataPathName;
2760 break;
2761 }
2762
2763 m_dCliffDepositionA = strtod(strRH.c_str(), NULL);
2764
2765 if (m_dCliffDepositionA < 0)
2766 strErr = "line " + to_string(nLine) + ": scale parameter A for cliff deposition must be 0 [= auto] or greater";
2767 }
2768
2769 break;
2770
2771 case 64:
2772 // Approximate planview width of cliff collapse talus (in m)
2774 {
2775 // First check that this is a valid double
2776 if (!bIsStringValidDouble(strRH))
2777 {
2778 strErr = "line " + to_string(nLine) + ": invalid floating point number for width of cliff collapse talus '" + strRH + "' in " + m_strDataPathName;
2779 break;
2780 }
2781
2782 m_dCliffDepositionPlanviewWidth = strtod(strRH.c_str(), NULL);
2783
2785 strErr = "line " + to_string(nLine) + ": planview width of cliff deposition must be > 0";
2786 }
2787
2788 break;
2789
2790 case 65:
2791 // Planview length of cliff deposition talus (m)
2793 {
2794 // First check that this is a valid double
2795 if (!bIsStringValidDouble(strRH))
2796 {
2797 strErr = "line " + to_string(nLine) + ": invalid floating point number for planview length of cliff deposition '" + strRH + "' in " + m_strDataPathName;
2798 break;
2799 }
2800
2801 m_dCliffTalusMinDepositionLength = strtod(strRH.c_str(), NULL);
2802
2804 strErr = "line " + to_string(nLine) + ": planview length of cliff deposition must be > 0";
2805 }
2806
2807 break;
2808
2809 case 66:
2810 // Minimum height of landward end of talus, as a fraction of cliff elevation
2812 {
2813 // First check that this is a valid double
2814 if (!bIsStringValidDouble(strRH))
2815 {
2816 strErr = "line " + to_string(nLine) + ": invalid floating point number for height of cliff collapse (as a fraction of cliff elevation) '" + strRH + "' in " + m_strDataPathName;
2817 break;
2818 }
2819
2820 m_dMinCliffTalusHeightFrac = strtod(strRH.c_str(), NULL);
2821
2823 strErr = "line " + to_string(nLine) + ": minimum height of cliff collapse (as a fraction of cliff elevation) must be >= 0";
2824 }
2825
2826 break;
2827
2828 // -------------------------------------------------- Input events data -----------------------------------------------
2829 case 67:
2830 // Simulate riverine flooding?
2831 strRH = strToLower(&strRH);
2832
2833 if (strRH.find('y') != string::npos)
2834 {
2835 m_bRiverineFlooding = true;
2839 }
2840
2841 break;
2842
2843 case 68:
2844 // Output riverine flooding vector files
2846 {
2847 if (!strRH.empty())
2848 {
2849 // Convert to lower case
2850 strRH = strToLower(&strRH);
2851
2852 // First look for "all"
2853 if (strRH.find(VECTOR_ALL_RIVER_FLOOD_OUTPUT_CODE) != string::npos)
2854 {
2858 }
2859
2860 else
2861 {
2862 // We are not outputting all vector flood GIS files, so set switches (and remove strings) for those optional files for which the user specified the code
2863 if (strRH.find(VECTOR_FLOOD_SWL_SETUP_LINE_CODE) != string::npos)
2864 {
2865 m_bFloodSWLSetupLine = true;
2867 }
2868
2869 if (strRH.find(VECTOR_FLOOD_SWL_SETUP_SURGE_LINE_CODE) != string::npos)
2870 {
2873 }
2874
2875 if (strRH.find(VECTOR_FLOOD_SWL_SETUP_SURGE_RUNUP_LINE_CODE) != string::npos)
2876 {
2879 }
2880
2881 // Check to see if all codes have been removed
2882 if (!strRH.empty())
2883 strErr = "line " + to_string(nLine) + ": unknown code '" + strRH + "' in list of riverine flooding output codes";
2884 }
2885 }
2886
2887 else
2888 strErr = "line " + to_string(nLine) + ": if simulating riverine flooding, must contain '" + VECTOR_ALL_RIVER_FLOOD_OUTPUT_CODE + "' or at least one vector GIS output code for riverine flooding";
2889 }
2890
2891 break;
2892
2893 case 69:
2895 {
2896 // Run-up equation?
2897 if (bIsStringValidInt(strRH))
2898 {
2899 m_nRunUpEquation = stoi(strRH);
2900 }
2901
2902 else
2903 strErr = "line " + to_string(nLine) + ": invalid code for run-up equation used in simulating floods";
2904 }
2905
2906 break;
2907
2908 case 70:
2910 {
2911 // Characteristic locations for flood?
2912 strRH = strToLower(&strRH);
2913
2914 m_bFloodLocation = false;
2915
2916 if (strRH.find('y') != string::npos)
2917 {
2918 m_bFloodLocation = true;
2919 }
2920 }
2921
2922 break;
2923
2924 case 71:
2926 {
2927 // Path of location points file
2928 if (!strRH.empty())
2929 {
2930#ifdef _WIN32
2931 // For Windows, make sure has backslashes, not Unix-style slashes
2932 strRH = pstrChangeToBackslash(&strRH);
2933#endif
2934
2935 // Now check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
2936 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
2937 // It has an absolute path, so use it 'as is'
2939
2940 else
2941 {
2942 // It has a relative path, so prepend the CoastalME dir
2944 m_strFloodLocationShapefile.append(strRH);
2945 }
2946
2947 // Set the switch
2948 m_bFloodLocation = true;
2949 }
2950
2951 else
2952 strErr = "line " + to_string(nLine) + ": path of location points file must not be empty if simulating floods";
2953 }
2954
2955 break;
2956
2957 case 72:
2958 // Simulate sediment input?
2959 strRH = strToLower(&strRH);
2960
2961 if (strRH.find('y') != string::npos)
2962 {
2963 m_bSedimentInput = true;
2965 }
2966
2967 break;
2968
2969 case 73:
2970 // Sediment input location (point or line shapefile)
2971 if (m_bSedimentInput)
2972 {
2973 if (!strRH.empty())
2974 {
2975#ifdef _WIN32
2976 // For Windows, make sure has backslashes, not Unix-style slashes
2977 strRH = pstrChangeToBackslash(&strRH);
2978#endif
2979
2980 // Now check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
2981 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
2982 // It has an absolute path, so use it 'as is'
2984
2985 else
2986 {
2987 // It has a relative path, so prepend the CoastalME dir
2990 }
2991 }
2992 }
2993
2994 break;
2995
2996 case 74:
2997 // Sediment input type: required if have shapefile [P = Point, C = coast block, L = line]
2998 if (m_bSedimentInput)
2999 {
3000 strRH = strToLower(&strRH);
3001
3002 if (strRH.find('p') != string::npos)
3004
3005 else if (strRH.find('c') != string::npos)
3007
3008 else if (strRH.find('l') != string::npos)
3010
3011 else
3012 strErr = "line " + to_string(nLine) + ": Sediment input type must be P, C, or L";
3013 }
3014
3015 break;
3016
3017 case 75:
3018 // Sediment input details file (required if have shapefile)
3019 if (m_bSedimentInput)
3020 {
3021 if (strRH.empty())
3022 {
3023 strErr = "line " + to_string(nLine) + ": filename missing for sediment input";
3024 break;
3025 }
3026
3027#ifdef _WIN32
3028 // For Windows, make sure has backslashes, not Unix-style slashes
3029 strRH = pstrChangeToBackslash(&strRH);
3030#endif
3031
3032 // Now check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
3033 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
3034 {
3035 // It has an absolute path, so use it 'as is'
3037 }
3038
3039 else
3040 {
3041 // It has a relative path, so prepend the CoastalME dir
3043 m_strSedimentInputEventFile.append(strRH);
3044 }
3045 }
3046
3047 break;
3048
3049 // ------------------------------------------------------ Other data --------------------------------------------------
3050 case 76:
3051 // Gravitational acceleration (m2/s). First check that this is a valid double
3052 if (!bIsStringValidDouble(strRH))
3053 {
3054 strErr = "line " + to_string(nLine) + ": invalid floating point number for gravitational acceleration '" + strRH + "' in " + m_strDataPathName;
3055 break;
3056 }
3057
3058 m_dG = strtod(strRH.c_str(), NULL);
3059
3060 if (m_dG <= 0)
3061 strErr = "line " + to_string(nLine) + ": gravitational acceleration must be > 0";
3062
3063 break;
3064
3065 case 77:
3066 // Spacing of coastline normals (m)
3067 m_dCoastNormalSpacing = strtod(strRH.c_str(), NULL);
3068
3070 m_nCoastNormalSpacing = DEFAULT_PROFILE_SPACING; // In cells, we will set m_dCoastNormalSpacing later when we know m_dCellSide
3071
3072 else if (m_dCoastNormalSpacing < 0)
3073 strErr = "line " + to_string(nLine) + ": spacing of coastline normals must be > 0";
3074
3075 break;
3076
3077 case 78:
3078 // Random factor for spacing of normals [0 to 1, 0 = deterministic], check that this is a valid double
3079 if (!bIsStringValidDouble(strRH))
3080 {
3081 strErr = "line " + to_string(nLine) + ": invalid floating point number for random factor for spacing of coastline normals '" + strRH + "' in " + m_strDataPathName;
3082 break;
3083 }
3084
3085 m_dCoastNormalRandSpacingFactor = strtod(strRH.c_str(), NULL);
3086
3088 strErr = "line " + to_string(nLine) + ": random factor for spacing of coastline normals must be >= 0";
3089
3091 strErr = "line " + to_string(nLine) + ": random factor for spacing of coastline normals must be < 1";
3092
3093 break;
3094
3095 case 79:
3096 // Length of coastline normals (m), check that this is a valid double
3097 if (!bIsStringValidDouble(strRH))
3098 {
3099 strErr = "line " + to_string(nLine) + ": invalid floating point number for length of coastline normals '" + strRH + "' in " + m_strDataPathName;
3100 break;
3101 }
3102
3103 m_dCoastNormalLength = strtod(strRH.c_str(), NULL);
3104
3105 if (m_dCoastNormalLength <= 0)
3106 strErr = "line " + to_string(nLine) + ": length of coastline normals must be > 0";
3107
3108 break;
3109
3110 case 80:
3111 // Start depth for wave calcs (ratio to deep water wave height), check that this is a valid double
3112 if (!bIsStringValidDouble(strRH))
3113 {
3114 strErr = "line " + to_string(nLine) + ": invalid floating point number for start depth for wave calcs '" + strRH + "' in " + m_strDataPathName;
3115 break;
3116 }
3117
3118 m_dWaveDepthRatioForWaveCalcs = strtod(strRH.c_str(), NULL);
3119
3121 strErr = "line " + to_string(nLine) + ": start depth for wave calcs must be > 0";
3122
3123 break;
3124
3125 // ----------------------------------------------------- Testing only -------------------------------------------------
3126 case 81:
3127 // Output profile data?
3128 strRH = strToLower(&strRH);
3129
3130 m_bOutputProfileData = false;
3131
3132 if (strRH.find('y') != string::npos)
3133 {
3134 m_bOutputProfileData = true;
3135
3137 {
3138 strErr = "line " + to_string(nLine) + ": cannot save profiile data if not simulating shore platform erosion";
3139 break;
3140 }
3141
3142 // TODO 043 What about randomness of profile spacing, since profile location is determined by curvature?
3143 }
3144
3145 break;
3146
3147 case 82:
3148 // Numbers of profiles to be saved
3150 {
3151 VstrTmp = VstrSplit(&strRH, SPACE);
3152
3153 for (unsigned int j = 0; j < VstrTmp.size(); j++)
3154 {
3155 VstrTmp[j] = strTrim(&VstrTmp[j]);
3156
3157 if (!bIsStringValidInt(VstrTmp[j]))
3158 {
3159 strErr = "line " + to_string(nLine) + ": invalid integer for profile to be saved '" + VstrTmp[j] + "' in " + m_strDataPathName;
3160 break;
3161 }
3162
3163 int const nTmp = stoi(VstrTmp[j]);
3164
3165 if (nTmp < 0)
3166 {
3167 strErr = "line " + to_string(nLine) + ": Profile number for saving must be >= 0";
3168 break;
3169 }
3170
3171 m_VnProfileToSave.push_back(nTmp);
3172 }
3173 }
3174
3175 break;
3176
3177 case 83:
3178 // Timesteps to save profiles
3180 {
3181 VstrTmp = VstrSplit(&strRH, SPACE);
3182
3183 for (unsigned int j = 0; j < VstrTmp.size(); j++)
3184 {
3185 VstrTmp[j] = strTrim(&VstrTmp[j]);
3186 unsigned long const ulTmp = atol(VstrTmp[j].c_str());
3187
3188 if (ulTmp < 1)
3189 {
3190 strErr = "line " + to_string(nLine) + ": Timestep for profile saves must >= 1";
3191 break;
3192 }
3193
3194 m_VulProfileTimestep.push_back(ulTmp);
3195 }
3196 }
3197
3198 break;
3199
3200 case 84:
3201 // Output parallel profile data?
3202 strRH = strToLower(&strRH);
3203
3205
3206 if (strRH.find('y') != string::npos)
3208
3209 break;
3210
3211 case 85:
3212 // Output erosion potential look-up data?
3213 strRH = strToLower(&strRH);
3214
3216
3217 if (strRH.find('y') != string::npos)
3219
3220 break;
3221
3222 case 86:
3223 // Size of moving window for coastline curvature calculation (must be odd)
3224 if (! bIsStringValidInt(strRH))
3225 {
3226 strErr = "line ";
3227 strErr += to_string(nLine);
3228 strErr += ": invalid integer for size of moving window for coastline curvature calculation '";
3229 strErr += strRH;
3230 strErr += "' in ";
3231 strErr += m_strDataPathName;
3232
3233 break;
3234 }
3235
3237
3239 {
3240 strErr = "line ";
3241 strErr += to_string(nLine);
3242 strErr += ": size of moving window for coastline curvature calculation (must be > 0 and odd)";
3243 }
3244
3245 break;
3246
3247 case 87:
3248 // Cliff edge smoothing algorithm: 0 = none, 1 = running mean, 2 = Savitzky-Golay
3249 if (! bIsStringValidInt(strRH))
3250 {
3251 strErr = "line ";
3252 strErr += to_string(nLine);
3253 strErr += ": invalid integer for cliff edge smoothing algorithm '";
3254 strErr += strRH;
3255 strErr += "' in " + m_strDataPathName;
3256
3257 break;
3258 }
3259
3260 m_nCliffEdgeSmooth = stoi(strRH);
3261
3264 strErr = "line " + to_string(nLine) +
3265 ": cliff edge smoothing algorithm";
3266
3267 break;
3268
3269 case 88:
3270 // Size of cliff edge smoothing window: must be odd
3271 if (! bIsStringValidInt(strRH))
3272 {
3273 strErr = "line " + to_string(nLine) +
3274 ": invalid integer for cliff edge smoothing window '" +
3275 strRH + "' in " + m_strDataPathName;
3276 break;
3277 }
3278
3279 m_nCliffEdgeSmoothWindow = stoi(strRH);
3280
3282 strErr = "line " + to_string(nLine) +
3283 ": size of cliff edge smoothing window (must be > 0 and odd)";
3284
3285 break;
3286
3287 case 89:
3288 // Order of cliff edge smoothing polynomial for Savitzky-Golay: usually 2 or 4, max is 6
3289 if (! bIsStringValidInt(strRH))
3290 {
3291 strErr = "line " + to_string(nLine) +
3292 ": invalid integer for Savitzky-Golay polynomial for cliff edge smoothing '" +
3293 strRH + "' in " + m_strDataPathName;
3294 break;
3295 }
3296
3297 m_nSavGolCliffEdgePoly = stoi(strRH);
3298
3301 strErr = "line " + to_string(nLine) + ": order of Savitzky-Golay polynomial for cliff edge smoothing (must be 2, 4 or 6)";
3302
3303 break;
3304
3305 case 90:
3306 // Cliff slope limit for cliff toe detection
3307 if (! bIsStringValidDouble(strRH))
3308 {
3309 strErr = "line " + to_string(nLine) + ": invalid number for cliff slope limit '" + strRH + "' in " + m_strDataPathName;
3310 break;
3311 }
3312
3313 m_dCliffSlopeLimit = stod(strRH);
3314
3315 if (m_dCliffSlopeLimit <= 0)
3316 strErr = "line " + to_string(nLine) +
3317 ": cliff slope limit must be > 0";
3318
3319 break;
3320 }
3321
3322 // Did an error occur?
3323 if (! strErr.empty())
3324 {
3325 // Error in input to run details file
3326 cerr << endl << ERR << strErr << ".\nPlease edit " << m_strDataPathName << " and change this line:" << endl;
3327 cerr << "'" << strRec << "'" << endl << endl;
3328 InStream.close();
3329 return false;
3330 }
3331 }
3332 }
3333
3334 // Close file
3335 InStream.close();
3336
3337 // Finally, need to check that we have at least one raster file, so that we know the grid size and units (and preferably also the projection)
3338 bool bNoRasterFiles = true;
3339
3340 if ((! m_strInitialBasementDEMFile.empty()) || (! m_strInitialSuspSedimentFile.empty()) || (! m_strInitialLandformFile.empty()) || (! m_strInterventionHeightFile.empty()))
3341 bNoRasterFiles = false;
3342
3343 for (int j = 0; j < m_nLayers; j++)
3344 {
3346 bNoRasterFiles = false;
3347 }
3348
3349 if (bNoRasterFiles)
3350 {
3351 // No raster files
3352 cerr << ERR << "at least one raster GIS file is needed" << endl;
3353 return false;
3354 }
3355
3356 return true;
3357}
3358
3359//===============================================================================================================================
3361//===============================================================================================================================
3363{
3364 // Create an ifstream object
3365 ifstream InStream;
3366
3367 // Try to open the file for input
3368 InStream.open(m_strTideDataFile.c_str(), ios::in);
3369
3370 // Did it open OK?
3371 if (! InStream.is_open())
3372 {
3373 // Error: cannot open tide data file for input
3374 cerr << ERR << "cannot open " << m_strTideDataFile << " for input" << endl;
3375 return RTN_ERR_TIDEDATAFILE;
3376 }
3377
3378 // Opened OK
3379 int nLine = 0;
3380 string strRec;
3381
3382 // Now read the data from the file
3383 while (getline(InStream, strRec))
3384 {
3385 nLine++;
3386
3387 // Trim off leading and trailing whitespace
3388 strRec = strTrim(&strRec);
3389
3390 // If it is a blank line or a comment then ignore it
3391 if ((strRec.empty()) || (strRec[0] == QUOTE1) || (strRec[0] == QUOTE2))
3392 continue;
3393
3394 // Check that this is a valid double
3395 if (! bIsStringValidDouble(strRec))
3396 {
3397 cerr << ERR << "invalid floating point number for tide data '" << strRec << "' on line " << nLine << " of " << m_strTideDataFile << endl;
3398 return RTN_ERR_TIDEDATAFILE;
3399 }
3400
3401 // Convert to double then append the value to the vector
3402 m_VdTideData.push_back(strtod(strRec.c_str(), NULL));
3403 }
3404
3405 // Close file
3406 InStream.close();
3407
3408 return RTN_OK;
3409}
3410
3411//===============================================================================================================================
3413//===============================================================================================================================
3415{
3416 // Sort out the path and filename
3420
3421 // Create an ifstream object
3422 ifstream InStream;
3423
3424 // Try to open the file for input
3425 InStream.open(m_strSCAPEShapeFunctionFile.c_str(), ios::in);
3426
3427 // Did it open OK?
3428 if (! InStream.is_open())
3429 {
3430 // Error: cannot open shape function file for input
3431 cerr << ERR << "cannot open " << m_strSCAPEShapeFunctionFile << " for input" << endl;
3433 }
3434
3435 // Opened OK
3436 int nLine = 0;
3437 int nExpected = 0, nRead = 0;
3438 string strRec;
3439
3440 // Read in the number of data lines expected
3441 InStream >> nExpected;
3442
3443 // Set up the vectors to hold the input data
3444 vector<double> VdDepthOverDB;
3445 vector<double> VdErosionPotential;
3446 vector<double> VdErosionPotentialFirstDeriv;
3447
3448 // Now read the rest of the data from the file to get the Erosion Potential Shape function
3449 while (getline(InStream, strRec))
3450 {
3451 nLine++;
3452
3453 // Trim off leading and trailing whitespace
3454 strRec = strTrim(&strRec);
3455
3456 // If it is a blank line or a comment then ignore it
3457 if ((strRec.empty()) || (strRec[0] == QUOTE1) || (strRec[0] == QUOTE2))
3458 continue;
3459
3460 // It isn't so increment counter
3461 nRead++;
3462
3463 // Split the string, and remove whitespace
3464 vector<string> strTmp = VstrSplit(&strRec, SPACE);
3465
3466 for (unsigned int i = 0; i < strTmp.size(); i++)
3467 {
3468 // Remove leading and trailing whitespace
3469 strTmp[i] = strTrim(&strTmp[i]);
3470
3471 // Check that this is a valid double
3472 if (! bIsStringValidDouble(strTmp[i]))
3473 {
3474 cerr << ERR << "on line " + to_string(nLine) + " invalid floating point number for Erosion Potential Shape data '" << strTmp[i] << "' in " << m_strSCAPEShapeFunctionFile << endl;
3476 }
3477 }
3478
3479 // Convert to doubles then append the values to the vectors
3480 VdDepthOverDB.push_back(strtod(strTmp[0].c_str(), NULL));
3481 VdErosionPotential.push_back(strtod(strTmp[1].c_str(), NULL));
3482 VdErosionPotentialFirstDeriv.push_back(strtod(strTmp[2].c_str(), NULL));
3483 }
3484
3485 // Now create the look up table values
3486 m_VdErosionPotential = VdErosionPotential;
3487 m_VdDepthOverDB = VdDepthOverDB;
3488 m_dDepthOverDBMax = VdDepthOverDB[14];
3489
3490 // Close file
3491 InStream.close();
3492
3493 // Did we read in what we expected?
3494 if (nExpected != nRead)
3495 {
3496 cout << ERR << "read in " << nRead << " lines from " << m_strSCAPEShapeFunctionFile << " but " << nExpected << " lines expected" << endl;
3498 }
3499
3500 // Is the shape funcion well defined? i.e. it must be -ve or 0.0 for all values
3501 for (unsigned int j = 0; j < m_VdErosionPotential.size(); j++)
3502 {
3503 if (m_VdErosionPotential[j] > 0)
3504 {
3505 cout << ERR << " in " << m_strSCAPEShapeFunctionFile << ", erosion potential function cannot be positive" << endl;
3507 }
3508 }
3509
3510 // OK, now use this data to create a look-up table to be used for the rest of the simulation
3511 if (!bCreateErosionPotentialLookUp(&VdDepthOverDB, &VdErosionPotential, &VdErosionPotentialFirstDeriv))
3512 {
3513 cout << ERR << "line " + to_string(nLine) + " in " << m_strSCAPEShapeFunctionFile << ": erosion potential function is unbounded for high values of depth over DB" << endl;
3515 }
3516
3517 return RTN_OK;
3518}
3519
3520//===============================================================================================================================
3522//===============================================================================================================================
3523int CSimulation::nReadWaveStationInputFile(int const nWaveStations)
3524{
3525 // Create an ifstream object
3526 ifstream InStream;
3527
3528 // Try to open the file for input
3529 InStream.open(m_strDeepWaterWavesInputFile.c_str(), ios::in);
3530
3531 // Did it open OK?
3532 if (!InStream.is_open())
3533 {
3534 // Error: cannot open time series file for input
3535 cerr << ERR << "cannot open " << m_strDeepWaterWavesInputFile << " for input" << endl;
3537 }
3538
3539 // Opened OK
3540 int nLine = 0;
3541 int nExpectedStations = 0;
3542 int nRead = 0;
3543 int nTimeStepsRead = 0;
3544 string strRec, strErr;
3545
3546 // Read each line, ignoring blank lines and comment lines
3547 while (getline(InStream, strRec))
3548 {
3549 nLine++;
3550
3551 // Trim off leading and trailing whitespace
3552 strRec = strTrim(&strRec);
3553
3554 // If it is a blank line or a comment then ignore it
3555 if ((!strRec.empty()) && (strRec[0] != QUOTE1) && (strRec[0] != QUOTE2))
3556 {
3557 // It isn't so increment counter
3558 nRead++;
3559
3560 // The header lines (the first four lines of the file) contains leading description separated by a colon from the data
3561 if (nRead < 5)
3562 {
3563 // Find the colon: note that lines MUST have a colon separating data from leading description portion
3564 size_t nPos = strRec.find(COLON);
3565
3566 if (nPos == string::npos)
3567 {
3568 // Error: badly formatted (no colon)
3569 cerr << ERR << "on line " << to_string(nLine) << "badly formatted (no ':') in " << m_strDeepWaterWavesInputFile << endl
3570 << "'" << strRec << "'" << endl;
3572 }
3573
3574 if (nPos == strRec.size() - 1)
3575 {
3576 // Error: badly formatted (colon with nothing following)
3577 cerr << ERR << "on line " << to_string(nLine) << "badly formatted (nothing following ':') in " << m_strDeepWaterWavesInputFile << endl
3578 << "'" << strRec << "'" << endl;
3580 }
3581
3582 // Strip off leading portion (the bit up to and including the colon)
3583 string strRH = strRec.substr(nPos + 1);
3584
3585 // Remove leading whitespace
3586 strRH = strTrimLeft(&strRH);
3587
3588 // Look for a trailing comment, if found then terminate string at that point and trim off any trailing whitespace
3589 nPos = strRH.rfind(QUOTE1);
3590
3591 if (nPos != string::npos)
3592 strRH.resize(nPos);
3593
3594 nPos = strRH.rfind(QUOTE2);
3595
3596 if (nPos != string::npos)
3597 strRH.resize(nPos);
3598
3599 // Remove trailing whitespace
3600 strRH = strTrimRight(&strRH);
3601
3602 int nSec = 0;
3603 int nMin = 0;
3604 int nHour = 0;
3605 int nDay = 0;
3606 int nMonth = 0;
3607 int nYear = 0;
3608 double dMult;
3609 double dThisIter;
3610 vector<string> VstrTmp;
3611
3612 switch (nRead)
3613 {
3614 case 1:
3615 // Get the start date/time for this data, format is [hh-mm-ss dd/mm/yyyy]
3616 VstrTmp = VstrSplit(&strRH, SPACE);
3617
3618 // Both date and time here?
3619 if (VstrTmp.size() < 2)
3620 {
3621 strErr = "line " + to_string(nLine) + ": must have both date and time for start of data in";
3622 break;
3623 }
3624
3625 // OK, first sort out the time
3626 if (!bParseTime(&VstrTmp[0], nHour, nMin, nSec))
3627 {
3628 strErr = "line " + to_string(nLine) + ": could not understand start time for data";
3629 break;
3630 }
3631
3632 // Next sort out the date
3633 if (!bParseDate(&VstrTmp[1], nDay, nMonth, nYear))
3634 {
3635 strErr = "line " + to_string(nLine) + ": could not understand start date for data";
3636 break;
3637 }
3638
3639 // Compare time and date with simulation time and date
3640 if ((nSec != m_nSimStartSec) ||
3641 (nMin != m_nSimStartMin) ||
3642 (nHour != m_nSimStartHour) ||
3643 (nDay != m_nSimStartDay) ||
3644 (nMonth != m_nSimStartMonth) ||
3645 (nYear != m_nSimStartYear))
3646 {
3647 strErr = "line " + to_string(nLine) + ": start time and date for wave time series data differs from simulation start time and date,";
3648 break;
3649 }
3650
3651 break;
3652
3653 case 2:
3654 // Get the timestep of this data (in hours or days)
3655 strRH = strToLower(&strRH);
3656
3657 dMult = dGetTimeMultiplier(&strRH);
3658
3659 if (static_cast<int>(dMult) == TIME_UNKNOWN)
3660 {
3661 strErr = "line " + to_string(nLine) + ": unknown units for timestep";
3662 break;
3663 }
3664
3665 // We have the multiplier, now calculate the timestep in hours: look for the whitespace between the number and unit
3666 nPos = strRH.rfind(SPACE);
3667
3668 if (nPos == string::npos)
3669 {
3670 strErr = "line " + to_string(nLine) + ": format of timestep line";
3671 break;
3672 }
3673
3674 // Cut off rh bit of string
3675 strRH.resize(nPos);
3676
3677 // Remove trailing spaces
3678 strRH = strTrimRight(&strRH);
3679
3680 // Check that this is a valid double
3681 if (!bIsStringValidDouble(strRH))
3682 {
3683 strErr = "line " + to_string(nLine) + ": invalid floating point number for timestep";
3684 break;
3685 }
3686
3687 dThisIter = strtod(strRH.c_str(), NULL) * dMult; // in hours
3688
3689 if (dThisIter <= 0)
3690 strErr = "line " + to_string(nLine) + ": timestep must be > 0";
3691
3692 if (!bFPIsEqual(dThisIter, m_dTimeStep, TOLERANCE))
3693 strErr = "line " + to_string(nLine) + ": timestep must be the same as the simulation timestep";
3694
3695 break;
3696
3697 case 3:
3698
3699 // Read the number of stations
3700 if (!bIsStringValidInt(strRH))
3701 {
3702 strErr = "line " + to_string(nLine) + ": invalid integer for number of wave stations '" + strRH + "' in " + m_strDeepWaterWavesInputFile;
3703 break;
3704 }
3705
3706 nExpectedStations = stoi(strRH);
3707
3708 // Check that the number of expected stations is equal to the number of stations on the point shape file
3709 if (nExpectedStations != nWaveStations)
3710 {
3711 // Error: number of points on shape file does not match the number of stations on the wave time series file
3712 strErr = "line " + to_string(nLine) + ": number of wave stations in " + m_strDeepWaterWaveStationsShapefile + " is " + to_string(nWaveStations) + " but we have " + to_string(nExpectedStations) + " stations";
3713
3714 break;
3715 }
3716
3717 break;
3718
3719 case 4:
3720
3721 // Read the expected number of time steps in the file
3722 if (!bIsStringValidInt(strRH))
3723 {
3724 strErr = "line " + to_string(nLine) + ": invalid integer for expected number of time steps '" + strRH + "' in " + m_strDeepWaterWaveStationsShapefile;
3725 break;
3726 }
3727
3729
3731 {
3732 // Error: must have value(s) for at least one timestep
3733 strErr = "line " + to_string(nLine) + ": must have values for at least one timestep";
3734 break;
3735 }
3736
3737 break;
3738 }
3739 }
3740
3741 else
3742 {
3743 // This is not a header line
3744 nTimeStepsRead++;
3745
3746 // Read in each wave attribute for each time step and station: split the string, and remove whitespace
3747 vector<string> VstrTmp = VstrSplit(&strRec, COMMA);
3748
3749 for (unsigned int i = 0; i < VstrTmp.size(); i++) // VstrTmp.size() should be 3 x nExpectedStations
3750 {
3751 // Remove leading and trailing whitespace
3752 VstrTmp[i] = strTrim(&VstrTmp[i]);
3753
3754 // Check that this is a valid double
3755 if (!bIsStringValidDouble(VstrTmp[i]))
3756 {
3757 strErr = "line " + to_string(nLine) + ": invalid floating point number for deep water wave value '" + VstrTmp[i] + "' in " + m_strDeepWaterWavesInputFile;
3758 break;
3759 }
3760 }
3761
3762 // Convert to doubles then append the values to the vectors
3763 int n = 0;
3764
3765 for (int i = 0; i < nExpectedStations; i++)
3766 {
3767 m_VdTSDeepWaterWaveStationHeight.push_back(strtod(VstrTmp[n + 0].c_str(), NULL));
3768 m_VdTSDeepWaterWaveStationAngle.push_back(strtod(VstrTmp[n + 1].c_str(), NULL));
3769 m_VdTSDeepWaterWaveStationPeriod.push_back(strtod(VstrTmp[n + 2].c_str(), NULL));
3770
3771 // Check some simple wave input stats
3774
3777
3778 n += 3;
3779 }
3780 }
3781 }
3782
3783 // Did an error occur?
3784 if (!strErr.empty())
3785 {
3786 // Error in input to initialisation file
3787 cerr << ERR << strErr << " in deep water wave time series file " << m_strDeepWaterWavesInputFile << endl
3788 << "'" << strRec << "'" << endl;
3789 InStream.close();
3790
3792 }
3793 }
3794
3795 if (nTimeStepsRead != m_nDeepWaterWaveDataNumTimeSteps)
3796 {
3797 // Error: number of timesteps read does not match the number given in the file's header
3798 cerr << ERR << "in " << m_strDeepWaterWavesInputFile << ", data for " << nTimeStepsRead << " timesteps was read, but " << m_nDeepWaterWaveDataNumTimeSteps << " timesteps were specified in the file's header" << endl;
3799
3801 }
3802
3803 // Close file
3804 InStream.close();
3805
3806 // Did we read in what we expected?
3807 unsigned int const nTotExpected = nExpectedStations * m_nDeepWaterWaveDataNumTimeSteps;
3808
3809 if (m_VdTSDeepWaterWaveStationHeight.size() != nTotExpected)
3810 {
3811 cout << ERR << "read in " << m_VdTSDeepWaterWaveStationHeight.size() << " lines from " << m_strDeepWaterWavesInputFile << " but " << nTotExpected << " values expected" << endl;
3812
3814 }
3815
3816 if (m_VdTSDeepWaterWaveStationAngle.size() != nTotExpected)
3817 {
3818 cout << ERR << "read in " << m_VdTSDeepWaterWaveStationAngle.size() << " lines from " << m_strDeepWaterWavesInputFile << " but " << nTotExpected << " values expected" << endl;
3819
3821 }
3822
3823 if (m_VdTSDeepWaterWaveStationPeriod.size() != nTotExpected)
3824 {
3825 cout << ERR << "read in " << m_VdTSDeepWaterWaveStationPeriod.size() << " lines from " << m_strDeepWaterWavesInputFile << " but " << nTotExpected << " values expected" << endl;
3826
3828 }
3829
3830 // All is OK, so we can now initialize the vectors that will store this timestep's deep water wave values
3831 for (int j = 0; j < nExpectedStations; j++)
3832 {
3836 }
3837
3838 // Finally, check whether the wave data will 'wrap' i.e. whether the number of timesteps is less than the total number of timesteps in the simulation
3839 int const nSimulationTimeSteps = static_cast<int>(floor(m_dSimDuration / m_dTimeStep));
3840
3841 if (m_nDeepWaterWaveDataNumTimeSteps < nSimulationTimeSteps)
3842 {
3844 string const strTmp = "Deep water wave data will wrap every " + (m_nDeepWaterWaveDataNumTimeSteps > 1 ? to_string(m_nDeepWaterWaveDataNumTimeSteps) + " " : "") + "time step" + (m_nDeepWaterWaveDataNumTimeSteps > 1 ? "s" : "") + " (every " + to_string(m_dWaveDataWrapHours) + " hours)\n";
3845
3846 cout << NOTE << strTmp;
3847 }
3848
3849 return RTN_OK;
3850}
3851
3852//===============================================================================================================================
3854//===============================================================================================================================
3856{
3857 // Create an ifstream object
3858 ifstream InStream;
3859
3860 // Try to open the file for input
3861 InStream.open(m_strSedimentInputEventFile.c_str(), ios::in);
3862
3863 // Did it open OK?
3864 if (!InStream.is_open())
3865 {
3866 // Error: cannot open time series file for input
3867 cerr << ERR << "cannot open " << m_strSedimentInputEventFile << " for input" << endl;
3869 }
3870
3871 // Opened OK
3872 int nLine = 0;
3873 int nRead = 0;
3874 string strRec, strErr;
3875
3876 // Read each line, ignoring comment lines
3877 while (getline(InStream, strRec))
3878 {
3879 nLine++;
3880
3881 // Trim off leading and trailing whitespace
3882 strRec = strTrim(&strRec);
3883
3884 // If it is a blank line or a comment then ignore it
3885 if ((!strRec.empty()) && (strRec[0] != QUOTE1) && (strRec[0] != QUOTE2))
3886 {
3887 // It isn't so increment counter
3888 nRead++;
3889
3890 // Split at commas
3891 vector<string> VstrTmp = VstrSplit(&strRec, COMMA);
3892
3893 // Check that have all we need
3894 unsigned int nTarget = 7;
3895
3897 nTarget = 5;
3898
3899 if (VstrTmp.size() < nTarget)
3900 {
3901 strErr = "line " + to_string(nLine) + ": too few data items on data line '" + to_string(nRead) + "' in " + m_strSedimentInputEventFile;
3902 break;
3903 }
3904
3905 // First item is the Location ID of the sediment input event (same as the ID in the shapefile)
3906 if (!bIsStringValidInt(VstrTmp[0]))
3907 {
3908 strErr = "line " + to_string(nLine) + ": invalid integer for Location ID of sediment input event '" + VstrTmp[0] + "' in " + m_strSedimentInputEventFile;
3909 break;
3910 }
3911
3912 int const nID = stoi(strTrim(&VstrTmp[0]));
3913
3914 // OK, check the ID against IDs read in from the shapefile
3915 auto result = find(m_VnSedimentInputLocationID.begin(), m_VnSedimentInputLocationID.end(), nID);
3916
3917 if (result == m_VnSedimentInputLocationID.end())
3918 {
3919 strErr = "line " + to_string(nLine) + ": invalid Location ID '" + to_string(nID) + "' for sediment input event location event in " + m_strSedimentInputEventFile;
3920 break;
3921 }
3922
3923 // Next get the timestep at which the sediment input event occurs. This may be specified either as a relative time (i.e. a number of hours or days after the simulation start) or as an absolute time (i.e. a time/date in the format hh-mm-ss dd/mm/yyyy)
3924 unsigned long const ulEventTimeStep = ulConvertToTimestep(&VstrTmp[1]);
3925
3926 if (ulEventTimeStep == SEDIMENT_INPUT_EVENT_ERROR)
3927 {
3928 strErr = "line " + to_string(nLine) + ": invalid time and/or date '" + VstrTmp[1] + "' for sediment input event in " + m_strSedimentInputEventFile;
3929 break;
3930 }
3931
3932 // Then the volume (m3) of fine sediment, first check that this is a valid double
3933 if (!bIsStringValidDouble(VstrTmp[2]))
3934 {
3935 strErr = "line " + to_string(nLine) + ": invalid floating point number '" + VstrTmp[2] + "' for fine sediment volume for sediment input event in " + m_strSedimentInputEventFile;
3936 break;
3937 }
3938
3939 double const dFineSedVol = stod(strTrim(&VstrTmp[2]));
3940
3941 if (dFineSedVol < 0)
3942 {
3943 strErr = "line " + to_string(nLine) + ": negative number '" + to_string(dFineSedVol) + "' for fine sediment volume for sediment input event in " + m_strSedimentInputEventFile;
3944 break;
3945 }
3946
3947 if (dFineSedVol > 0)
3948 m_bHaveFineSediment = true;
3949
3950 // Then the volume (m3) of sand sediment, first check that this is a valid double
3951 if (!bIsStringValidDouble(VstrTmp[3]))
3952 {
3953 strErr = "line " + to_string(nLine) + ": invalid floating point number '" + VstrTmp[3] + "' for sand-sized sediment volume for sediment input event in " + m_strSedimentInputEventFile;
3954 break;
3955 }
3956
3957 double const dSandSedVol = stod(strTrim(&VstrTmp[3]));
3958
3959 if (dSandSedVol < 0)
3960 {
3961 strErr = "line " + to_string(nLine) + ": negative number '" + to_string(dSandSedVol) + "' for sand-sized sediment volume for sediment input event in " + m_strSedimentInputEventFile;
3962 break;
3963 }
3964
3965 if (dSandSedVol > 0)
3966 m_bHaveSandSediment = true;
3967
3968 // Then the volume (m3) of coarse sediment, first check that this is a valid double
3969 if (!bIsStringValidDouble(VstrTmp[4]))
3970 {
3971 strErr = "line " + to_string(nLine) + ": invalid floating point number '" + VstrTmp[4] + "' for coarse sediment volume for sediment input event in " + m_strSedimentInputEventFile;
3972 break;
3973 }
3974
3975 double const dCoarseSedVol = stod(strTrim(&VstrTmp[4]));
3976
3977 if (dCoarseSedVol < 0)
3978 {
3979 strErr = "line " + to_string(nLine) + ": negative number '" + to_string(dCoarseSedVol) + "' for coarse sediment volume of sediment input event in " + m_strSedimentInputEventFile;
3980 break;
3981 }
3982
3983 if (dCoarseSedVol > 0)
3984 m_bHaveCoarseSediment = true;
3985
3986 // Only read the last two items if we have on-coast sediment block sediment input
3987 double dLen = 0;
3988 double dWidth = 0;
3989
3990 // double dThick = 0;
3992 {
3993 // The coast-normal length (m) of the sediment block, first check that this is a valid double
3994 if (!bIsStringValidDouble(VstrTmp[5]))
3995 {
3996 strErr = "line " + to_string(nLine) + ": invalid floating point number '" + VstrTmp[5] + "' for coast-normal length of sediment input event in " + m_strSedimentInputEventFile;
3997 break;
3998 }
3999
4000 dLen = stod(strTrim(&VstrTmp[5]));
4001
4002 if (dLen <= 0)
4003 {
4004 strErr = "line " + to_string(nLine) + ": coast-normal length of the sediment block '" + to_string(dLen) + "' must be > 0 in " + m_strSedimentInputEventFile;
4005 break;
4006 }
4007
4008 // The along-coast width (m) of the sediment block, first check that this is a valid double
4009 if (!bIsStringValidDouble(VstrTmp[6]))
4010 {
4011 strErr = "line " + to_string(nLine) + ": invalid floating point number '" + VstrTmp[6] + "' for along-coast width of sediment input event in " + m_strSedimentInputEventFile;
4012 break;
4013 }
4014
4015 dWidth = stod(strTrim(&VstrTmp[6]));
4016
4017 if ((!m_bSedimentInputAtCoast) && (dWidth <= 0))
4018 {
4019 strErr = "line " + to_string(nLine) + ": along-coast width (m) of the sediment block '" + to_string(dWidth) + "' must be > 0 in " + m_strSedimentInputEventFile;
4020 break;
4021 }
4022
4023 // // The along-coast thickness (m) of the sediment block, first check that this is a valid double
4024 // if (! bIsStringValidDouble(VstrTmp[7]))
4025 // {
4026 // strErr = "line " + to_string(nLine) + ": invalid floating point number '" + VstrTmp[7] + "' for along-coast thickness of sediment input event in " + m_strSedimentInputEventFile;
4027 // break;
4028 // }
4029 //
4030 // dThick = stod(strTrim(&VstrTmp[7]));
4031 // if ((! m_bSedimentInputAtCoast) && (dWidth <= 0))
4032 // {
4033 // strErr = "line " + to_string(nLine) + ": along-coast thickness (m) of the sediment block '" + to_string(dThick) + "' must be > 0 in " + m_strSedimentInputEventFile;
4034 // break;
4035 // }
4036 }
4037
4038 // Create the CSedInputEvent object
4039 CSedInputEvent *pEvent = new CSedInputEvent(nID, ulEventTimeStep, dFineSedVol, dSandSedVol, dCoarseSedVol, dLen, dWidth); //, dThick);
4040
4041 // And store it in the m_pVSedInputEvent vector
4042 m_pVSedInputEvent.push_back(pEvent);
4043 }
4044 }
4045
4046 // Did an error occur?
4047 if (!strErr.empty())
4048 {
4049 // Error in input to initialisation file
4050 cerr << ERR << strErr << " in sediment input event file " << m_strSedimentInputEventFile << endl
4051 << "'" << strRec << "'" << endl;
4052 InStream.close();
4053
4055 }
4056
4057 // Close file
4058 InStream.close();
4059
4060 return RTN_OK;
4061}
Class used to represent a sediment input event.
double m_dCliffDepositionPlanviewWidth
Planview width of cliff collapse talus (m)
Definition simulation.h:919
bool m_bCliffCollapseSave
Save cliff collapse raster GIS files?
Definition simulation.h:223
int m_nLogFileDetail
The level of detail in the log file output. Can be LOG_FILE_LOW_DETAIL, LOG_FILE_MIDDLE_DETAIL,...
Definition simulation.h:574
bool m_bAvgSeaDepthSave
Save average sea depth raster GIS files?
Definition simulation.h:112
vector< string > m_VstrInitialSandConsSedimentFile
The name of the initial sand-sized consolidated sediment GIS file.
double m_dAllCellsDeepWaterWaveHeight
Deep water wave height (m) for all sea cells.
Definition simulation.h:754
bool m_bDeepWaterWaveAngleSave
Save deep water wave angle raster GIS files?
Definition simulation.h:250
int m_nGISMaxSaveDigits
The maximum number of digits in GIS filenames. These can be sequential, or the iteration number.
Definition simulation.h:499
bool m_bTopSurfSave
Save fop surface (sediment and sea) raster DEMs?
Definition simulation.h:97
string m_strInitialSuspSedimentFile
Name of initial suspended sediment file.
vector< double > m_VdTSDeepWaterWaveStationPeriod
Time series of wave period at deep water wave station.
bool m_bSedimentTopSurfSave
Save sediment top surface raster DEMs?
Definition simulation.h:94
bool m_bFineUnconsSedSave
Save fine unconsolidated sediment raster GIS files?
Definition simulation.h:196
string m_strSedimentInputEventFile
The name of the sediment input events time series file.
bool m_bHaveConsolidatedSediment
Does this simulation consider consolidated sediment, or is it an unconsolidated sediment only simulat...
Definition simulation.h:448
double m_dNotchDepthAtCollapse
Notch overhang (i.e. length of horizontal incision) to initiate collapse (m)
Definition simulation.h:910
bool m_bFloodSWLSetupSurgeLine
Are we saving the flood still water level setup surge line? TODO 007.
Definition simulation.h:439
string m_strCMEIni
Folder for the CME .ini file.
bool m_bSedimentInputAtPoint
Do we have sediment inputat a point?
Definition simulation.h:394
double m_dG
Gravitational acceleration (m**2/sec)
Definition simulation.h:811
vector< string > m_VstrInitialCoarseUnconsSedimentFile
The name of the initial coarse-sized unconsolidated sediment GIS file.
int m_nBeachErosionDepositionEquation
Which beach erosion-deposition equation is used. Possible values are UNCONS_SEDIMENT_EQUATION_CERC an...
Definition simulation.h:529
bool m_bCoastSave
Save.
Definition simulation.h:268
bool m_bBeachDepositionTSSave
Save the beach (unconsolidated sediment) deposition time series file?
Definition simulation.h:319
static string strRemoveSubstr(string *, string const *)
Returns a string with a substring removed, and with whitespace trimmed.
Definition utils.cpp:2422
vector< string > m_VstrGDALICCDataType
GDAL data type for the initial consolidated coarse sediment GIS data.
static bool bParseTime(string const *, int &, int &, int &)
Parses a time string into hours, minutes, and seconds, and checks each of them.
Definition utils.cpp:2730
double m_dWaveDataWrapHours
Number of hours after which deep water wave data wraps.
Definition simulation.h:964
vector< string > m_VstrGDALICFDataType
GDAL data type for the initial consolidated fine sediment GIS data.
vector< CSedInputEvent * > m_pVSedInputEvent
Sediment input events.
double m_dMaxUserInputWavePeriod
Used to constrain depth of closure.
Definition simulation.h:766
bool m_bFloodSetupSurgeRunupTSSave
Save the flood setup surge runup time series file? TODO 007 Does this work correctly?
Definition simulation.h:331
vector< string > m_VstrGDALICCDriverCode
GDAL driver code for the initial consolidated coarse sediment GIS data.
double m_dCoastNormalLength
Length of the coastline-normal profiles, in m.
Definition simulation.h:826
vector< string > m_VstrGDALIUFDataType
GDAL data type for the initial unconsolidated fine sediment GIS data.
bool m_bSingleDeepWaterWaveValues
Do we have just a point source for (i.e. only a single measurement of) deep water wave values.
Definition simulation.h:385
string m_strRunName
The name of this simulation.
bool m_bAvgWaveAngleAndHeightSave
Save average wave angle and average wave height raster GIS files?
Definition simulation.h:130
string m_strSCAPEShapeFunctionFile
Name of SCAPE shape function file.
bool m_bAvgWaveAngleSave
Save average wave angle raster GIS files?
Definition simulation.h:124
int nReadWaveStationInputFile(int const)
Reads the deep water wave station input data. Each point in m_strDeepWaterWavesInputFile is a triad o...
bool m_bCliffEdgeSave
Save cliff edge vector GIS files?
Definition simulation.h:271
bool m_bInvalidNormalsSave
Save invalid coastline-normal vector GIS files?
Definition simulation.h:277
bool m_bShadowBoundarySave
Save wave shadow boundary vector GIS files?
Definition simulation.h:292
int nDoSimulationTimeMultiplier(string const *)
Given a string containing time units, this sets up the appropriate multiplier and display units for t...
Definition utils.cpp:326
int nReadSedimentInputEventFile(void)
Reads the sediment input event file.
vector< int > m_VnSedimentInputLocationID
ID for sediment input location, this corresponds with the ID in the sediment input time series file.
bool m_bActualBeachErosionSave
Save actual (supply-limited) beach (unconsolidated sediment) erosion raster GIS files?
Definition simulation.h:163
vector< double > m_VdErosionPotential
For erosion potential lookup.
vector< double > m_VdTideData
Tide data: one record per timestep, is the change (m) from still water level for that timestep.
vector< string > m_VstrGDALIUFProjection
GDAL projection for the initial unconsolidated fine sediment GIS data.
bool m_bStillWaterLevelTSSave
Save the still water level time series file?
Definition simulation.h:301
bool m_bRunUpSave
Are we saving runup? TODO 007.
Definition simulation.h:418
bool m_bCliffCollapseDepositionSave
Save cliff collapse deposition raster GIS files?
Definition simulation.h:229
string m_strSedimentInputEventShapefile
The name of the sediment input events shape file.
bool m_bTotalActualPlatformErosionSave
Save total actual (supply-limited) shore platform erosion raster GIS files?
Definition simulation.h:157
static string strTrimLeft(string const *)
Trims whitespace from the left side of a string, does not change the original string.
Definition utils.cpp:2342
bool m_bPolygonUnconsSedUpOrDownDriftSave
Save polygon unconsolidated sediment up- or down-drift raster GIS files?
Definition simulation.h:259
double m_dCoarseErodibility
The relative erodibility (0- 1) of coarse unconsolidated beach sediment.
Definition simulation.h:793
double m_dCliffTalusMinDepositionLength
Planview length of cliff deposition talus (m)
Definition simulation.h:922
string m_strVectorGISOutFormat
Base name for CME vector GIS output files.
vector< string > m_VstrGDALICFDriverCode
GDAL driver code for the initial consolidated fine sediment GIS data.
vector< string > m_VstrInitialFineConsSedimentFile
The name of the initial fine-sized consolidated sediment GIS file.
int m_nUnconsSedimentHandlingAtGridEdges
How sediment which moves off an edge of the grid is handled. Possible values are GRID_EDGE_CLOSED,...
Definition simulation.h:526
double m_dSandErodibility
The relative erodibility (0- 1) of sand unconsolidated beach sediment.
Definition simulation.h:790
bool m_bBasementElevSave
Save basement raster DEMs?
Definition simulation.h:91
int m_nSimStartHour
Start time of the simulation (hours)
Definition simulation.h:559
bool m_bCoarseUnconsSedSave
Save coarse unconsolidated sediment raster GIS files?
Definition simulation.h:202
bool m_bSuspSedTSSave
Save the suspended sediment time series file?
Definition simulation.h:325
string m_strDeepWaterWaveStationsShapefile
The name of the deep water wave stations shape file.
vector< double > m_VdDepthOverDB
For erosion potential lookup.
bool m_bCliffCollapseNetTSSave
Save the cliff collapse net change time series file?
Definition simulation.h:313
bool m_bPotentialPlatformErosionMaskSave
Save potential platform erosion mask raster GIS files?
Definition simulation.h:238
vector< string > m_VstrGDALICSDriverCode
GDAL driver code for the initial consolidated sand sediment GIS data.
double m_dWaveDepthRatioForWaveCalcs
Start depth for wave calculations.
Definition simulation.h:748
bool m_bWaveHeightSave
Save wave height raster GIS files?
Definition simulation.h:115
bool m_bFloodLocation
Are we saving the flood location? TODO 007.
Definition simulation.h:433
vector< string > m_VstrGDALIUCProjection
GDAL projection for the initial unconsolidated coarse sediment GIS data.
bool m_bLandformSave
Save coast landform raster GIS files?
Definition simulation.h:178
static string strTrim(string const *)
Trims whitespace from both sides of a string, does not change the original string.
Definition utils.cpp:2377
string m_strRasterGISOutFormat
Base name for CME raster GIS output files.
bool m_bTotalBeachDepositionSave
Save total beach (unconsolidated sediment) deposition raster GIS files?
Definition simulation.h:175
double m_dBeachSedimentPorosity
The porosity of unconsolidated beach sediment (0 - 1)
Definition simulation.h:784
int m_nSimStartSec
Start time of the simulation (seconds)
Definition simulation.h:553
int m_nSimStartDay
Start date of the simulation (day)
Definition simulation.h:562
bool m_bSandUnconsSedSave
Save sand unconsolidated sediment raster GIS files?
Definition simulation.h:199
bool m_bActualPlatformErosionTSSave
Save the actual (supply-limited) shore platform erosion time series file?
Definition simulation.h:304
unsigned long ulConvertToTimestep(string const *) const
For sediment input events, parses a string that may be relative (a number of hours or days after the ...
Definition utils.cpp:2791
int m_nCoastNormalSpacing
Average spacing between coastline normals, measured in cells.
Definition simulation.h:490
bool m_bTotCliffCollapseSave
Save total cliff collapse raster GIS files?
Definition simulation.h:226
int nReadShapeFunctionFile(void)
Reads the shape of the erosion potential distribution (see shape function in Walkden & Hall,...
bool m_bCliffSave
Save cliff region raster grids?
Definition simulation.h:103
bool m_bDoShorePlatformErosion
Simulate shore platform erosion?
Definition simulation.h:361
bool m_bSliceSave
Save slices?
Definition simulation.h:106
bool m_bRasterPolygonSave
Save raster polygon raster GIS files?
Definition simulation.h:235
double m_dInitialMeanSWL
The start-of-simulation still water level (m)
Definition simulation.h:703
bool m_bBeachDepositionSave
Save beach (unconsolidated sediment) deposition raster GIS files?
Definition simulation.h:172
vector< string > m_VstrGDALICSDriverDesc
GDAL driver description for the initial consolidated sand sediment GIS data.
bool m_bSaveRegular
Save GIS files at regular intervals?
Definition simulation.h:265
int m_nLayers
The number of sediment layers.
Definition simulation.h:463
int m_nCoastSmoothingWindowSize
The size of the window used for coast smoothing. Must be an odd number.
Definition simulation.h:469
bool m_bSedimentInputAlongLine
Do we have sediment input along a line?
Definition simulation.h:400
bool m_bSedimentInput
Do we have sediment input events?
Definition simulation.h:391
bool m_bNormalsSave
Save coastline-normal vector GIS files?
Definition simulation.h:274
bool m_bAvgWaveHeightSave
Save wave height raster GIS files?
Definition simulation.h:118
static string strToLower(string const *)
Returns the lower case version of an string, leaving the original unchanged.
Definition utils.cpp:2402
vector< double > m_VdThisIterDeepWaterWaveStationHeight
This-iteration wave height at deep water wave station.
vector< string > m_VstrGDALIUFDriverCode
GDAL driver code for the initial unconsolidated fine sediment GIS data.
bool m_bHaveSandSediment
Does this simulation consider sand-sized sediment?
Definition simulation.h:85
bool bReadRunDataFile(void)
Reads the run details input file and does some initialization.
int m_nUSave
If user-defined GIS save intervals, the number of these.
Definition simulation.h:505
double m_dDeanProfileStartAboveSWL
Berm height i.e. height above SWL of start of depositional Dean profile.
Definition simulation.h:955
int m_nSavGolCoastPoly
The order of the coastline profile smoothing polynomial if Savitzky-Golay smoothing is used (usually ...
Definition simulation.h:472
bool m_bSeaDepthSave
Save sea depth raster GIS files?
Definition simulation.h:109
bool m_bWaveAngleAndHeightSave
Save wave angle and wave height raster GIS files?
Definition simulation.h:127
double m_dNotchBaseBelowSWL
Notch base below SWL (m)
Definition simulation.h:913
string m_strInitialBasementDEMFile
Name of initial basement DEM file.
int m_nRunUpEquation
The run-up equation used TODO 007.
Definition simulation.h:577
bool m_bWorldFile
Write a GIS World file?
Definition simulation.h:382
static string strTrimRight(string const *)
Trims whitespace from the right side of a string, does not change the original string.
Definition utils.cpp:2357
string m_strLogFile
Name of output log file.
double m_dDepthOverDBMax
Maximum value of deoth over DB, is used in erosion potential look-up function.
Definition simulation.h:892
double m_dFineErodibility
The relative erodibility (0- 1) of fine unconsolidated beach sediment.
Definition simulation.h:787
double m_dBreakingWaveHeightDepthRatio
Breaking wave height-to-depth ratio.
Definition simulation.h:751
double m_dCoastNormalSpacing
Average spacing of the coastline-normal profiles, in m.
Definition simulation.h:820
bool m_bHaveWaveStationData
Do we have wave station data?
Definition simulation.h:388
double m_dSeaWaterDensity
Density of sea water in kg/m**3.
Definition simulation.h:700
int m_nSavGolCliffEdgePoly
The order of the cliff edge smoothing polynomial if Savitzky-Golay smoothing is used (usually 2 or 4,...
Definition simulation.h:481
double m_dR
Coast platform resistance to erosion R, see Walkden & Hall, 2011.
Definition simulation.h:769
bool m_bRasterNormalProfileSave
Save rasterized coastline-normal profiles GIS files?
Definition simulation.h:217
bool m_bActiveZoneSave
Save active zone raster GIS files?
Definition simulation.h:220
vector< string > m_VstrInitialSandUnconsSedimentFile
The name of the initial sand-sized unconsolidated sediment GIS file.
bool m_bOmitSearchWestEdge
Omit the west edge of the grid from coast-end searches?
Definition simulation.h:355
bool m_bSedimentInputAtCoast
Do we have sediment input at the coast?
Definition simulation.h:397
int m_nCliffEdgeSmooth
Which method to use for cliff edge smoothing.
Definition simulation.h:475
double m_dCliffErosionResistance
Resistance of cliff to notch erosion.
Definition simulation.h:907
vector< string > m_VstrGDALIUSProjection
GDAL projection for the initial unconsolidated sand sediment GIS data.
vector< double > m_VdThisIterDeepWaterWaveStationPeriod
This-iteration wave period at deep water wave station.
double m_dD50Sand
The D50 for sand sediment.
Definition simulation.h:775
string m_strCMEDir
The CME folder.
vector< int > m_VnProfileToSave
The numbers of the profiles which are to be saved.
bool m_bDeepWaterWaveHeightSave
Save deep water wave height raster GIS files?
Definition simulation.h:253
bool m_bMeanWaveEnergySave
Save mean wave energy raster GIS files?
Definition simulation.h:139
double m_dKLS
Transport parameter KLS in the CERC equation.
Definition simulation.h:805
int m_nWavePropagationModel
The wave propagation model used. Possible values are WAVE_MODEL_CSHORE and WAVE_MODEL_COVE.
Definition simulation.h:550
double m_dAllCellsDeepWaterWaveAngle
Deep water wave angle for all sea cells.
Definition simulation.h:757
vector< string > m_VstrGDALICFProjection
GDAL projection for the initial consolidated fine sediment GIS data.
vector< string > m_VstrGDALICCProjection
GDAL projection for the initial consolidated coarse sediment GIS data.
static double dGetTimeMultiplier(string const *)
Given a string containing time units, this returns the appropriate multiplier.
Definition utils.cpp:291
bool m_bCoastCurvatureSave
Save coastline-curvature vector GIS files?
Definition simulation.h:280
int m_nCliffEdgeSmoothWindow
The size of the window used for cliff edge smoothing. Must be an odd number.
Definition simulation.h:478
int m_nDeepWaterWaveDataNumTimeSteps
The duration of data for deep water waves, expressed as a number of timesteps.
Definition simulation.h:571
double m_dFinalMeanSWL
The end-of-simulation still water (m), is same as m_dInitialMeanSWL unless SWL changes.
Definition simulation.h:706
bool m_bRasterWaveFloodLineSave
Are we saving the raster wave flood line? TODO 007.
Definition simulation.h:427
bool m_bBreakingWaveHeightSave
Save breaking wave height raster GIS files?
Definition simulation.h:142
string m_strMailAddress
An email addresx to which to send end-of-simulation messages.
double m_dRegularSaveTime
The time of the next save, in hours from the start of the simulation, if we are saving regularly.
Definition simulation.h:682
bool m_bPolygonNodeSave
Save polygon node vector GIS files?
Definition simulation.h:283
bool m_bOmitSearchNorthEdge
Omit the north edge of the grid from coast-end searches?
Definition simulation.h:349
bool m_bFloodSetupSurgeTSSave
Save the flood setup surge time series file? TODO 007 Does this work correctly?
Definition simulation.h:328
bool m_bTotalPotentialPlatformErosionSave
Save total potential shore platform erosion raster GIS files?
Definition simulation.h:154
bool m_bSetupSurgeFloodMaskSave
Are we saving the setup surge flood mask? TODO 007.
Definition simulation.h:421
bool m_bWaveEnergySinceCollapseSave
Save wave energy since cliff collapse raster GIS files?
Definition simulation.h:136
double m_dD50Coarse
The D50 for coarse sediment.
Definition simulation.h:778
vector< unsigned long > m_VulProfileTimestep
Timesteps at which to save profiles.
bool m_bPotentialBeachErosionSave
Save potential beach (unconsolidated sediment) erosion raster GIS files?
Definition simulation.h:160
static bool bParseDate(string const *, int &, int &, int &)
Parses a date string into days, months, and years, and checks each of them.
Definition utils.cpp:2669
string m_strFloodLocationShapefile
The name of the flood loction events shape file.
bool m_bGISSaveDigitsSequential
Are the GIS save digits (which are part of each GIS file name) sequential, or are they the iteration ...
Definition simulation.h:445
int m_nSimStartMonth
Start date of the simulation (month)
Definition simulation.h:565
bool m_bSuspSedSave
Save suspended sediment raster GIS files?
Definition simulation.h:190
double m_dMinCliffTalusHeightFrac
Minimum height of the landward end of cliff collapse talus, as a fraction of cliff elevation.
Definition simulation.h:925
vector< string > m_VstrGDALIUSDriverDesc
bool m_bPolygonBoundarySave
Save polygon boundary vector GIS files?
Definition simulation.h:286
bool m_bStormSurgeSave
Are we saving the storm surge? TODO 007.
Definition simulation.h:415
vector< string > m_VstrInitialFineUnconsSedimentFile
The name of the initial fine-sized unconsolidated sediment GIS file.
bool m_bActualPlatformErosionSave
Save actual (supply-limited) shore platform erosion raster GIS files?
Definition simulation.h:151
int m_nSimStartMin
Start time of the simulation (minutes)
Definition simulation.h:556
bool bReadIniFile(void)
The bReadIniFile member function reads the initialization file.
bool m_bHaveFineSediment
Does this simulation consider fine-sized sediment?
Definition simulation.h:82
double m_dCliffDepositionA
Scale parameter A for cliff deposition (m^(1/3)), may be zero for auto-calculation.
Definition simulation.h:916
string m_strDataPathName
Folder in which the CME data file is found.
string m_strOutPath
Path for all output files.
bool m_bBeachErosionTSSave
Save the beach (unconsolidated sediment) erosion time series file?
Definition simulation.h:316
vector< string > m_VstrGDALICFDriverDesc
string m_strTideDataFile
Name of tide data file.
vector< string > m_VstrGDALIUFDriverDesc
bool m_bTotalPotentialBeachErosionSave
Save total potential beach (unconsolidated sediment) erosion raster GIS files?
Definition simulation.h:166
vector< string > m_VstrGDALIUSDataType
GDAL data type for the initial unconsolidated sand sediment GIS data.
string m_strInterventionClassFile
Name of intervention class file.
bool m_bFloodSWLSetupLine
Are we saving the flood still water level setup line? TODO 007.
Definition simulation.h:436
bool m_bSeaMaskSave
Save sea mask raster GIS files?
Definition simulation.h:241
bool m_bInterventionClassSave
Save intervention class raster GIS files?
Definition simulation.h:184
int m_nSimStartYear
Start date of the simulation (year)
Definition simulation.h:568
bool m_bTotalActualBeachErosionSave
Save total actual (supply-limited) beach (unconsolidated sediment) erosion raster GIS files?
Definition simulation.h:169
bool m_bRasterCoastlineSave
Save rasterized coastline GIS files?
Definition simulation.h:214
string m_strDeepWaterWavesInputFile
The name of the deep water wave stations time series file.
static string pstrChangeToBackslash(string const *)
Changes all forward slashes in the input string to backslashes, leaving the original unchanged.
Definition utils.cpp:2322
bool m_bInterventionHeightSave
Save intervention height raster GIS files?
Definition simulation.h:187
int m_nCoastCurvatureMovingWindowSize
WHAT IS THOS FOR?
Definition simulation.h:583
bool m_bRiverineFlooding
Are we doing flooding? TODO 007.
Definition simulation.h:409
bool m_bSandConsSedSave
Save sand consolidated sediment raster GIS files?
Definition simulation.h:208
bool m_bSedimentInputEventSave
Save sediment inut data?
Definition simulation.h:403
bool m_bHaveCoarseSediment
Does this simulation consider coarse-sized sediment?
Definition simulation.h:88
double m_dRegularSaveInterval
The interval between regular saves, in hours.
Definition simulation.h:685
bool m_bPolygonUnconsSedGainOrLossSave
Save polygon unconsolidated sediment gain or loss raster GIS files?
Definition simulation.h:262
double m_dTimeStep
The length of an iteration (a time step) in hours.
Definition simulation.h:676
bool m_bCliffCollapseDepositionTSSave
Save the cliff collapse deposition time series file?
Definition simulation.h:310
vector< string > m_VstrGDALIUCDriverCode
GDAL driver code for the initial unconsolidated coarse sediment GIS data.
bool m_bDeepWaterWaveAngleAndHeightSave
Save deep water wave angle and wave height raster GIS files?
Definition simulation.h:133
double m_dCoastNormalRandSpacingFactor
Random factor for spacing of along-coast normals.
Definition simulation.h:952
double m_dMaxUserInputWaveHeight
Maximum deep water wave height.
Definition simulation.h:763
vector< double > m_VdSliceElev
Elevations for raster slice output.
bool m_bBeachProtectionSave
Save beach protection raster GIS files>
Definition simulation.h:145
bool m_bDoBeachSedimentTransport
Simulate unconsolidated sediment (beach) transport?
Definition simulation.h:367
bool m_bFineConsSedSave
Save fine consolidated sediment raster GIS files?
Definition simulation.h:205
bool m_bShadowDowndriftBoundarySave
Save wave shadow downdrift boundary vector GIS files?
Definition simulation.h:295
int m_nCoastSmooth
Which method to use for coast smoothing.
Definition simulation.h:466
bool m_bDeepWaterWavePeriodSave
Save deep water wave period raster GIS files?
Definition simulation.h:256
string m_strInitialLandformFile
Name of initial landform file.
string m_strInterventionHeightFile
Name of intervention height file.
bool m_bBeachSedimentChangeNetTSSave
Save the beach (unconsolidated sediment) net change time series file?
Definition simulation.h:322
vector< string > m_VstrGDALICSDataType
GDAL data type for the initial consolidated sand sediment GIS data.
int nReadTideDataFile(void)
Reads the tide time series data.
bool m_bCoarseConsSedSave
Save coarse consolidated sediment raster GIS files?
Definition simulation.h:211
bool m_bSeaAreaTSSave
Save the sea area time series file?
Definition simulation.h:298
bool m_bScaleRasterOutput
Scale raster output?
Definition simulation.h:379
vector< string > m_VstrGDALICSProjection
GDAL dprojection for the initial consolidated sand sediment GIS data.
double m_dD50Fine
The D50 for fine sediment.
Definition simulation.h:772
unsigned long m_ulRandSeed[NUMBER_OF_RNGS]
A seed for each of the random number generators.
Definition simulation.h:604
bool m_bOmitSearchSouthEdge
Omit the south edge of the grid from coast-end searches?
Definition simulation.h:352
bool m_bBeachMaskSave
Save beach mask raster GIS files?
Definition simulation.h:244
bool m_bSlopeSave
Save slope raster grids?
Definition simulation.h:100
bool m_bAvgSuspSedSave
Save average suspended sediment raster GIS files?
Definition simulation.h:193
double m_dBeachSedimentDensity
The density of unconsolidated beach sediment (kg/m**3)
Definition simulation.h:781
vector< string > m_VstrInitialCoarseConsSedimentFile
The name of the initial coarse-sized consolidated sediment GIS file.
double m_dSimDuration
Duration of simulation, in hours.
Definition simulation.h:673
bool m_bCSVPerTimestepResults
Output per-timestep results in CSV format instead of fixed-width?
Definition simulation.h:346
double m_dCliffSlopeLimit
Slope limit for cliff toe detection.
Definition simulation.h:484
vector< double > m_VdThisIterDeepWaterWaveStationAngle
This-iteration wave orientation at deep water wave station.
bool m_bOutputProfileData
Output profile data?
Definition simulation.h:337
vector< string > m_VstrGDALIUCDriverDesc
double m_dMaxBeachElevAboveSWL
Maximum elevation of beach above SWL (m)
Definition simulation.h:904
bool m_bTotCliffCollapseDepositionSave
Save total cliff collapse deposition raster GIS files?
Definition simulation.h:232
double m_dAllCellsDeepWaterWavePeriod
Deep water wave period for all sea cells.
Definition simulation.h:760
bool bCreateErosionPotentialLookUp(vector< double > *, vector< double > *, vector< double > *)
Creates a look-up table for erosion potential, given depth over DB.
double m_dUSaveTime[SAVEMAX]
Save time, in hours from the start of the simukation, if we are not saving regularly.
Definition simulation.h:688
double m_dProfileMaxSlope
Maximum slope on coastline-normal profiles.
Definition simulation.h:901
int m_nProfileSmoothWindow
The size of the window used for running-mean coast-normal profile smoothing (must be odd)
Definition simulation.h:487
bool m_bDoCliffCollapse
Simulate cliff collapse?
Definition simulation.h:364
vector< string > m_VstrGDALICCDriverDesc
GDAL driver decription for the initial consolidated coarse sediment GIS data.
string m_strOutFile
Name of main output file.
bool m_bSetupSurgeRunupFloodMaskSave
Are we saving the setup surge runup flood mask? TODO 007.
Definition simulation.h:424
bool m_bWaveSetupSave
Are we saving the wave setup? TODO 007.
Definition simulation.h:412
vector< double > m_VdTSDeepWaterWaveStationHeight
Time series of wave heights at deep water wave station.
bool m_bShadowZoneCodesSave
Save wave shadow zones raster GIS files?
Definition simulation.h:247
vector< string > m_VstrGDALIUCDataType
GDAL data type for the initial unconsolidated coarse sediment GIS data.
bool m_bCliffCollapseErosionTSSave
Save the cliff collapse erosion time series file?
Definition simulation.h:307
bool m_bPotentialPlatformErosionSave
Save potential shore platform erosion raster GIS files?
Definition simulation.h:148
double m_dDurationUnitsMult
Multiplier for duration units, to convert to hours.
Definition simulation.h:640
bool m_bFloodSWLSetupSurgeRunupLine
Are we saving the flood still water level setup surge runup line? TODO 007.
Definition simulation.h:442
bool m_bOutputParallelProfileData
Output parallel profile data?
Definition simulation.h:340
double m_dKamphuis
Transport parameter for the Kamphuis equation.
Definition simulation.h:808
vector< double > m_VdTSDeepWaterWaveStationAngle
Time series of wave orientation at deep water wave station.
static vector< string > * VstrSplit(string const *, char const, vector< string > *)
From http://stackoverflow.com/questions/236129/split-a-string-in-c They implement (approximately) Pyt...
Definition utils.cpp:2443
bool m_bOutputErosionPotentialData
Output erosion potential data?
Definition simulation.h:343
bool m_bCliffNotchSave
Save cliff notch incision depth vector GIS files?
Definition simulation.h:289
bool m_bVectorWaveFloodLineSave
Are we saving the vector wave flood line? TODO 007.
Definition simulation.h:430
vector< string > m_VstrGDALIUSDriverCode
GDAL driver code for the initial unconsolidated sand sediment GIS data.
bool m_bWaveAngleSave
Save wave angle raster GIS files?
Definition simulation.h:121
bool m_bOmitSearchEastEdge
Omit the east edge of the grid from coast-end searches?
Definition simulation.h:358
bool m_bLocalSlopeSave
Save local slope raster GIS files?
Definition simulation.h:181
This file contains global definitions for CoastalME.
string const VECTOR_FLOOD_SWL_SETUP_SURGE_LINE_CODE
Definition cme.h:1167
string const TIME_SERIES_CLIFF_COLLAPSE_DEPOSITION_CODE
Definition cme.h:1211
string const TIME_SERIES_SUSPENDED_SEDIMENT_CODE
Definition cme.h:1226
string const RASTER_POTENTIAL_PLATFORM_EROSION_MASK_CODE
Definition cme.h:959
int const SMOOTH_NONE
Definition cme.h:772
int const WAVE_MODEL_COVE
Definition cme.h:782
int const RTN_ERR_READING_SEDIMENT_INPUT_EVENT
Definition cme.h:758
double const TOLERANCE
Definition cme.h:813
string const RASTER_CLIFF_COLLAPSE_EROSION_FINE_CODE
Definition cme.h:1009
string const TIME_SERIES_PLATFORM_EROSION_CODE
Definition cme.h:1205
string const RASTER_COARSE_CONS_CODE
Definition cme.h:1001
string const VECTOR_POLYGON_NODE_CODE
Definition cme.h:1145
string const RASTER_USUAL_OUTPUT_CODE
Definition cme.h:925
string const RASTER_DEEP_WATER_WAVE_ORIENTATION_CODE
Definition cme.h:1037
string const RASTER_DEEP_WATER_WAVE_HEIGHT_CODE
Definition cme.h:1039
string const TIME_SERIES_FLOOD_SETUP_SURGE_RUNUP_CODE
Definition cme.h:1232
string const RASTER_SLOPE_CODE
Definition cme.h:935
string const VECTOR_ALL_OUTPUT_CODE
Definition cme.h:1122
string const VECTOR_FLOOD_SWL_SETUP_SURGE_RUNUP_LINE_CODE
Definition cme.h:1169
string const RASTER_TOTAL_CLIFF_COLLAPSE_DEPOSITION_SAND_CODE
Definition cme.h:1025
string const RASTER_ACTIVE_ZONE_CODE
Definition cme.h:1007
int const NO_LOG_FILE
Definition cme.h:489
string const RASTER_CLIFF_COLLAPSE_EROSION_COARSE_CODE
Definition cme.h:1013
string const RASTER_SAND_CONS_CODE
Definition cme.h:999
string const TIME_SERIES_FLOOD_SETUP_SURGE_CODE
Definition cme.h:1229
int const RTN_ERR_SCAPE_SHAPE_FUNCTION_FILE
Definition cme.h:702
int const UNCONS_SEDIMENT_EQUATION_KAMPHUIS
Definition cme.h:787
string const ERR
Definition cme.h:892
string const RASTER_COAST_NORMAL_CODE
Definition cme.h:1005
int const DEFAULT_PROFILE_SPACING
Definition cme.h:485
string const VECTOR_CLIFF_EDGE_CODE
Definition cme.h:1127
string const SCAPE_DIR
Definition cme.h:885
string const LOGEXT
Definition cme.h:917
string const RASTER_AVG_SUSP_SED_CODE
Definition cme.h:989
string const RASTER_COAST_CODE
Definition cme.h:1003
string const RASTER_SEDIMENT_INPUT_EVENT_CODE
Definition cme.h:1047
string const VECTOR_WAVE_ENERGY_SINCE_COLLAPSE_CODE
Definition cme.h:1139
string const RASTER_WAVE_ORIENTATION_CODE
Definition cme.h:949
string const VECTOR_RUN_UP_CODE
Definition cme.h:1161
string const RASTER_ALL_OUTPUT_CODE
Definition cme.h:926
string const RASTER_CLIFF_COLLAPSE_EROSION_SAND_CODE
Definition cme.h:1011
string const RASTER_POLYGON_UPDRIFT_OR_DOWNDRIFT_CODE
Definition cme.h:1043
string const RASTER_WAVE_FLOOD_LINE_CODE
Definition cme.h:1053
int const WAVE_MODEL_CSHORE
Definition cme.h:783
string const RASTER_COARSE_UNCONS_CODE
Definition cme.h:995
string const OUTEXT
Definition cme.h:916
char const PATH_SEPARATOR
Definition cme.h:449
string const VECTOR_INVALID_NORMALS_CODE
Definition cme.h:1131
string const RASTER_BASEMENT_ELEVATION_CODE
Definition cme.h:931
string const RASTER_WAVE_HEIGHT_CODE
Definition cme.h:945
string const RASTER_CLIFF_COLLAPSE_DEPOSITION_COARSE_CODE
Definition cme.h:1023
char const COMMA
Definition cme.h:447
string const RASTER_INTERVENTION_CLASS_CODE
Definition cme.h:983
string const RASTER_POTENTIAL_PLATFORM_EROSION_CODE
Definition cme.h:961
string const RASTER_POTENTIAL_BEACH_EROSION_CODE
Definition cme.h:969
string const VECTOR_MEAN_WAVE_ENERGY_CODE
Definition cme.h:1141
string const VECTOR_STORM_SURGE_CODE
Definition cme.h:1159
int const TIME_UNKNOWN
Definition cme.h:520
double const D50_SAND_DEFAULT
Definition cme.h:798
string const RASTER_TOTAL_CLIFF_COLLAPSE_EROSION_COARSE_CODE
Definition cme.h:1019
bool bFPIsEqual(const T d1, const T d2, const T dEpsilon)
Definition cme.h:1293
string const VECTOR_USUAL_OUTPUT_CODE
Definition cme.h:1123
char const QUOTE1
Definition cme.h:450
string const RASTER_WAVE_PERIOD_CODE
Definition cme.h:951
int const GRID_EDGE_CLOSED
Definition cme.h:777
string const TIME_SERIES_CLIFF_COLLAPSE_NET_CODE
Definition cme.h:1214
int const GRID_EDGE_RECIRCULATE
Definition cme.h:779
int const RTN_ERR_OPEN_DEEP_WATER_WAVE_DATA
Definition cme.h:755
string const RASTER_TOTAL_ACTUAL_BEACH_EROSION_CODE
Definition cme.h:975
string const VECTOR_NORMALS_CODE
Definition cme.h:1129
string const RASTER_BEACH_DEPOSITION_CODE
Definition cme.h:977
string const RASTER_SHADOW_ZONE_CODE
Definition cme.h:1033
string const RASTER_TOTAL_BEACH_DEPOSITION_CODE
Definition cme.h:979
int const SAVEMAX
Definition cme.h:464
string const VECTOR_DEEP_WATER_WAVE_ANGLE_AND_HEIGHT_CODE
Definition cme.h:1155
int const NUMBER_OF_RNGS
Definition cme.h:463
double const D50_COARSE_DEFAULT
Definition cme.h:799
string const RASTER_BEACH_PROTECTION_CODE
Definition cme.h:957
string const RASTER_TOTAL_POTENTIAL_PLATFORM_EROSION_CODE
Definition cme.h:965
string const TIME_SERIES_CLIFF_COLLAPSE_EROSION_CODE
Definition cme.h:1208
string const RASTER_BEACH_MASK_CODE
Definition cme.h:955
string const RASTER_AVG_WAVE_HEIGHT_CODE
Definition cme.h:947
string const RASTER_SETUP_SURGE_FLOOD_MASK_CODE
Definition cme.h:1049
string const TIME_SERIES_BEACH_EROSION_CODE
Definition cme.h:1217
string const RASTER_TOTAL_POTENTIAL_BEACH_EROSION_CODE
Definition cme.h:973
int const SMOOTH_SAVITZKY_GOLAY
Definition cme.h:774
string const RASTER_AVG_SEA_DEPTH_CODE
Definition cme.h:941
string const RASTER_SAND_UNCONS_CODE
Definition cme.h:993
string const RASTER_CLIFF_CODE
Definition cme.h:937
string const READING_FILE_LOCATIONS
Definition cme.h:852
int const LOG_FILE_ALL
Definition cme.h:493
int const RTN_OK
Definition cme.h:694
string const VECTOR_CLIFF_NOTCH_SIZE_CODE
Definition cme.h:1149
string const RASTER_SETUP_SURGE_RUNUP_FLOOD_MASK_CODE
Definition cme.h:1051
string const RASTER_LANDFORM_CODE
Definition cme.h:981
string const RASTER_TOTAL_ACTUAL_PLATFORM_EROSION_CODE
Definition cme.h:967
int const RTN_ERR_READING_DEEP_WATER_WAVE_DATA
Definition cme.h:756
string const RASTER_ACTUAL_PLATFORM_EROSION_CODE
Definition cme.h:963
string const VECTOR_BREAKING_WAVE_HEIGHT_CODE
Definition cme.h:1143
unsigned long const SEDIMENT_INPUT_EVENT_ERROR
Definition cme.h:793
int const RTN_ERR_TIDEDATAFILE
Definition cme.h:703
string const RASTER_SUSP_SED_CODE
Definition cme.h:987
string const VECTOR_SHADOW_BOUNDARY_CODE
Definition cme.h:1151
string const VECTOR_COAST_CURVATURE_CODE
Definition cme.h:1133
double const DBL_NODATA
Definition cme.h:824
double const D50_FINE_DEFAULT
Definition cme.h:797
string const VECTOR_ALL_RIVER_FLOOD_OUTPUT_CODE
Definition cme.h:1124
string const CME_INI
Definition cme.h:828
string const NOTE
Definition cme.h:894
string const RASTER_CLIFF_COLLAPSE_DEPOSITION_SAND_CODE
Definition cme.h:1021
string const RASTER_SEA_DEPTH_CODE
Definition cme.h:939
string const RASTER_LOCAL_SLOPE_CODE
Definition cme.h:933
string const RASTER_FINE_CONS_CODE
Definition cme.h:997
char const QUOTE2
Definition cme.h:451
string const VECTOR_POLYGON_BOUNDARY_CODE
Definition cme.h:1147
string const RASTER_FINE_UNCONS_CODE
Definition cme.h:991
string const TIME_SERIES_STILL_WATER_LEVEL_CODE
Definition cme.h:1202
string const RASTER_SEDIMENT_TOP_CODE
Definition cme.h:927
int const UNCONS_SEDIMENT_EQUATION_CERC
Definition cme.h:786
string const RASTER_POLYGON_GAIN_OR_LOSS_CODE
Definition cme.h:1045
char const TILDE
Definition cme.h:454
string const RASTER_TOTAL_CLIFF_COLLAPSE_EROSION_SAND_CODE
Definition cme.h:1017
string const VECTOR_AVG_WAVE_ANGLE_AND_HEIGHT_CODE
Definition cme.h:1138
string const TIME_SERIES_BEACH_CHANGE_NET_CODE
Definition cme.h:1223
string const RASTER_INTERVENTION_HEIGHT_CODE
Definition cme.h:985
string const VECTOR_FLOOD_LINE_CODE
Definition cme.h:1163
string const TIME_SERIES_BEACH_DEPOSITION_CODE
Definition cme.h:1220
string const VECTOR_FLOOD_SWL_SETUP_LINE_CODE
Definition cme.h:1165
string const VECTOR_WAVE_SETUP_CODE
Definition cme.h:1157
string const RASTER_POLYGON_CODE
Definition cme.h:1029
string const RASTER_ACTUAL_BEACH_EROSION_CODE
Definition cme.h:971
string const RASTER_INUNDATION_MASK_CODE
Definition cme.h:943
string const VECTOR_COAST_CODE
Definition cme.h:1125
char const COLON
Definition cme.h:446
string const RASTER_TOTAL_CLIFF_COLLAPSE_EROSION_FINE_CODE
Definition cme.h:1015
string const RASTER_AVG_WAVE_ORIENTATION_CODE
Definition cme.h:953
string const SCAPE_SHAPE_FUNCTION_FILE
Definition cme.h:886
string const TIME_SERIES_SEA_AREA_CODE
Definition cme.h:1199
string const RASTER_DEEP_WATER_WAVE_PERIOD_CODE
Definition cme.h:1041
string const RASTER_TOTAL_CLIFF_COLLAPSE_DEPOSITION_COARSE_CODE
Definition cme.h:1027
string const RASTER_TOP_CODE
Definition cme.h:929
char const SPACE
Definition cme.h:453
string const VECTOR_DOWNDRIFT_BOUNDARY_CODE
Definition cme.h:1153
Contains CSedInputEvent definitions.
Contains CSimulation definitions.
bool bIsStringValidInt(string &str)
Checks to see if a string can be read as a valid integer, from https://stackoverflow....
bool bIsStringValidDouble(string &str)
Checks to see if a string can be read as a valid double number. Does not find trailing (i....