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 <cstdlib>
27using std::strtod;
28using std::atol;
29
30#include <cctype>
31using std::isdigit;
32using std::tolower;
33
34#include <cmath>
35using std::floor;
36
37#include <fstream>
38using std::ifstream;
39
40#include <iostream>
41using std::cerr;
42using std::cout;
43using std::endl;
44using std::ios;
45
46#include <string>
47using std::to_string;
48
49#include <algorithm>
50using std::find;
51using std::sort;
52using std::transform;
53
54#include <random>
55using std::random_device;
56
57#include "cme.h"
59#include "simulation.h"
60#include "yaml_parser.h"
61#include "configuration.h"
62
63//===============================================================================================================================
65//===============================================================================================================================
67{
68 // Check if user has supplied home directory
69 if (m_strCMEIni.empty())
70 // if not use the cme executable directory to find cme.ini
72
73 else
74 {
75 // if user has supplied home directory replace cme run directory with user supplied dir
77 }
78
79 m_strCMEIni.append(CME_INI);
80
81 // The .ini file is assumed to be in the CoastalME executable's directory
82 string const strFilePathName(m_strCMEIni);
83
84 // Tell the user what is happening
85 cout << READING_FILE_LOCATIONS << strFilePathName << endl;
86
87 // Create an ifstream object
88 ifstream InStream;
89
90 // Try to open .ini file for input
91 InStream.open(strFilePathName.c_str(), ios::in);
92
93 // Did it open OK?
94 if (!InStream.is_open())
95 {
96 // Error: cannot open .ini file for input
97 cerr << ERR << "cannot open " << strFilePathName << " for input" << endl;
98 return false;
99 }
100
101 int nLine = 0;
102 int i = 0;
103 string strRec, strErr;
104
105 while (getline(InStream, strRec))
106 {
107 nLine++;
108
109 // Trim off leading and trailing whitespace
110 strRec = strTrim(&strRec);
111
112 // If it is a blank line or a comment then ignore it
113 if ((!strRec.empty()) && (strRec[0] != QUOTE1) && (strRec[0] != QUOTE2))
114 {
115 // It isn't so increment counter
116 i++;
117
118 // Find the colon: note that lines MUST have a colon separating data from leading description portion
119 size_t nPos = strRec.find(COLON);
120
121 if (nPos == string::npos)
122 {
123 // Error: badly formatted (no colon)
124 cerr << ERR << "on line " << nLine << ": badly formatted (no ':') in " << strFilePathName << endl
125 << "'" << strRec << "'" << endl;
126 return false;
127 }
128
129 if (nPos == strRec.size() - 1)
130 {
131 // Error: badly formatted (colon with nothing following)
132 cerr << ERR << "on line " << nLine << ": badly formatted (nothing following ':') in " << strFilePathName << endl
133 << "'" << strRec << "'" << endl;
134 return false;
135 }
136
137 // Strip off leading portion (the bit up to and including the colon)
138 string strRH = strRec.erase(0, nPos + 1);
139
140 // Remove leading whitespace
141 strRH = strTrimLeft(&strRH);
142
143 // Look for a trailing comment, if found then terminate string at that point and trim off any trailing whitespace
144 nPos = strRH.rfind(QUOTE1);
145
146 if (nPos != string::npos)
147 strRH.resize(nPos);
148
149 nPos = strRH.rfind(QUOTE2);
150
151 if (nPos != string::npos)
152 strRH.resize(nPos);
153
154 // Remove trailing whitespace
155 strRH = strTrimRight(&strRH);
156
157 switch (i)
158 {
159 case 1:
160 // The main input run-data filename
161 if (strRH.empty())
162 strErr = "line " + to_string(nLine) + ": path and name of main datafile";
163
164 else
165 {
166 // First check that we don't already have an input run-data filename, e.g. one entered on the command-line
167 if (m_strDataPathName.empty())
168 {
169 // We don't: so first check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
170 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
171 // It has an absolute path, so use it 'as is'
172 m_strDataPathName = strRH;
173
174 else
175 {
176 // It has a relative path, so prepend the CoastalME dir
178 m_strDataPathName.append(strRH);
179 }
180 }
181 }
182
183 break;
184
185 case 2:
186 // Path for CoastalME output
187 if (strRH.empty())
188 strErr = "line " + to_string(nLine) + ": path for CoastalME output";
189
190 else
191 {
192 // Check for trailing slash on CoastalME output directory name (is vital)
193 if (strRH[strRH.size() - 1] != PATH_SEPARATOR)
194 strRH.push_back(PATH_SEPARATOR);
195
196 // Now check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
197 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
198 // It is an absolute path, so use it 'as is'
199 m_strOutPath = strRH;
200
201 else
202 {
203 // It is a relative path, so prepend the CoastalME dir
205 m_strOutPath.append(strRH);
206 }
207 }
208
209 break;
210
211 case 3:
212 // Email address, only useful if running under Linux/Unix
213 if (!strRH.empty())
214 {
215 // Something was entered, do rudimentary check for valid email address
216 if (strRH.find('@') == string::npos)
217 strErr = "line " + to_string(nLine) + ": email address for messages";
218
219 else
220 m_strMailAddress = strRH;
221 }
222
223 break;
224 }
225
226 // Did an error occur?
227 if (!strErr.empty())
228 {
229 // Error in input to initialisation file
230 cerr << ERR << "reading " << strErr << " in " << strFilePathName << endl
231 << "'" << strRec << "'" << endl;
232 InStream.close();
233
234 return false;
235 }
236 }
237 }
238
239 InStream.close();
240 return true;
241}
242
243//===============================================================================================================================
245//===============================================================================================================================
246bool CSimulation::bDetectFileFormat(string const& strFileName, bool& bIsYaml)
247{
248 bIsYaml = false;
249
250 // First check command-line flag
252 {
253 bIsYaml = true;
254 return true;
255 }
256
257 // Check file extension
258 size_t nDotPos = strFileName.find_last_of('.');
259 if (nDotPos != string::npos)
260 {
261 string strExt = strFileName.substr(nDotPos + 1);
262 std::transform(strExt.begin(), strExt.end(), strExt.begin(), ::tolower);
263
264 if (strExt == "yaml" || strExt == "yml")
265 {
266 bIsYaml = true;
267 return true;
268 }
269 else if (strExt == "dat")
270 {
271 bIsYaml = false;
272 return true;
273 }
274 }
275
276 // Default to .dat format if extension is ambiguous
277 bIsYaml = false;
278 return true;
279}
280
281//===============================================================================================================================
283// 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?)
284//===============================================================================================================================
286{
287 // Detect file format
288 bool bIsYaml;
290 {
291 cerr << ERR << "failed to detect file format for " << m_strDataPathName << endl;
292 return false;
293 }
294
295 // Use appropriate parser based on format
296 if (bIsYaml)
297 {
298 return bReadYamlFile();
299 }
300 else
301 {
302 // Continue with original .dat file parsing
303 // Create an ifstream object
304 ifstream InStream;
305
306 // Try to open run details file for input
307 InStream.open(m_strDataPathName.c_str(), ios::in);
308
309 // Did it open OK?
310 if (!InStream.is_open())
311 {
312 // Error: cannot open run details file for input
313 cerr << ERR << "cannot open " << m_strDataPathName << " for input" << endl;
314 return false;
315 }
316
317 int nLine = 0;
318 int i = 0;
319 size_t nPos;
320 string strRec, strErr;
321
322 while (getline(InStream, strRec))
323 {
324 nLine++;
325
326 // Trim off leading and trailing whitespace
327 strRec = strTrim(&strRec);
328
329 // If it is a blank line or a comment then ignore it
330 if ((!strRec.empty()) && (strRec[0] != QUOTE1) && (strRec[0] != QUOTE2))
331 {
332 // It isn't so increment counter
333 i++;
334
335 // Find the colon: note that lines MUST have a colon separating data from leading description portion
336 nPos = strRec.find(COLON);
337
338 if (nPos == string::npos)
339 {
340 // Error: badly formatted (no colon)
341 cerr << ERR << "on line " << to_string(nLine) << "badly formatted (no ':') in " << m_strDataPathName << endl
342 << strRec << endl;
343 return false;
344 }
345
346 // Strip off leading portion (the bit up to and including the colon)
347 string strRH = strRec.erase(0, nPos + 1);
348
349 // Remove leading whitespace after the colon
350 strRH = strTrimLeft(&strRH);
351
352 // Look for trailing comments, if found then terminate string at that point and trim off any trailing whitespace
353 bool bFound = true;
354
355 while (bFound)
356 {
357 bFound = false;
358
359 nPos = strRH.rfind(QUOTE1);
360
361 if (nPos != string::npos)
362 {
363 strRH.resize(nPos);
364 bFound = true;
365 }
366
367 nPos = strRH.rfind(QUOTE2);
368
369 if (nPos != string::npos)
370 {
371 strRH.resize(nPos);
372 bFound = true;
373 }
374
375 // Trim trailing spaces
376 strRH = strTrimRight(&strRH);
377 }
378
379#ifdef _WIN32
380 // For Windows, make sure has backslashes, not Unix-style slashes
381 strRH = pstrChangeToBackslash(&strRH);
382#endif
383 bool bFirst = true;
384 int nRet = 0;
385 int nHour = 0;
386 int nMin = 0;
387 int nSec = 0;
388 int nDay = 0;
389 int nMonth = 0;
390 int nYear = 0;
391 double dMult = 0;
392 string strTmp;
393 vector<string> VstrTmp;
394
395 switch (i)
396 {
397 // ---------------------------------------------- Run Information -----------------------------------------------------
398 case 1:
399 // Text output file names, don't change case
400 if (strRH.empty())
401 strErr = "line " + to_string(nLine) + ": output file names";
402
403 else
404 {
405 m_strRunName = strRH;
406
408 m_strOutFile.append(strRH);
409 m_strOutFile.append(OUTEXT);
410
412 m_strLogFile.append(strRH);
413 m_strLogFile.append(LOGEXT);
414 }
415
416 break;
417
418 case 2:
419 // Content of log file, 0 = no log file, 1 = least detail, 3 = most detail
420 if (! bIsStringValidInt(strRH))
421 {
422 strErr = "line " + to_string(nLine) + ": invalid integer for log file detail level '" + strRH + "' in " + m_strDataPathName;
423 break;
424 }
425
426 m_nLogFileDetail = stoi(strRH);
427
429 strErr = "line " + to_string(nLine) + ": log file detail level";
430
431 break;
432
433 case 3:
434 // Output per-timestep results in CSV format?
435 strRH = strToLower(&strRH);
436
438
439 if (strRH.find('y') != string::npos)
441
442 break;
443
444 case 4:
445 // Get the start date/time of the simulation, format is [hh-mm-ss dd/mm/yyyy]
446 VstrTmp = VstrSplit(&strRH, SPACE);
447
448 // Both date and time here?
449 if (VstrTmp.size() < 2)
450 {
451 strErr = "line " + to_string(nLine) + ": must have both date and time for simulation start in '" + m_strDataPathName + "'";
452 break;
453 }
454
455 // OK, first sort out the time
456 if (! bParseTime(&VstrTmp[0], nHour, nMin, nSec))
457 {
458 strErr = "line " + to_string(nLine) + ": could not understand simulation start time in '" + m_strDataPathName + "'";
459 break;
460 }
461
462 // Next sort out the date
463 if (! bParseDate(&VstrTmp[1], nDay, nMonth, nYear))
464 {
465 strErr = "line " + to_string(nLine) + ": could not understand simulation start date in '" + m_strDataPathName + "'";
466 break;
467 }
468
469 // Store simulation start time and date
470 m_nSimStartSec = nSec;
471 m_nSimStartMin = nMin;
472 m_nSimStartHour = nHour;
473 m_nSimStartDay = nDay;
474 m_nSimStartMonth = nMonth;
475 m_nSimStartYear = nYear;
476
477 break;
478
479 case 5:
480 // Duration of simulation (in hours, days, months, or years): sort out multiplier and user units, as used in the per-timestep output
481 strRH = strToLower(&strRH);
482
483 nRet = nDoSimulationTimeMultiplier(&strRH);
484
485 if (nRet != RTN_OK)
486 {
487 strErr = "line " + to_string(nLine) + ": units for duration of simulation";
488 break;
489 }
490
491 // And now calculate the duration of the simulation in hours: first find whitespace between the number and the unit
492 nPos = strRH.rfind(SPACE);
493
494 if (nPos == string::npos)
495 {
496 strErr = "line " + to_string(nLine) + ": format of duration simulation line";
497 break;
498 }
499
500 // Cut off rh bit of string
501 strRH.resize(nPos);
502
503 // Remove trailing spaces
504 strRH = strTrimRight(&strRH);
505
506 // Calculate the duration of the simulation in hours
507 m_dSimDuration = strtod(strRH.c_str(), NULL) * m_dDurationUnitsMult;
508
509 if (m_dSimDuration <= 0)
510 strErr = "line " + to_string(nLine) + ": duration of simulation must be > 0";
511
512 break;
513
514 case 6:
515 // Timestep of simulation (in hours or days)
516 strRH = strToLower(&strRH);
517
518 dMult = dGetTimeMultiplier(&strRH);
519
520 if (static_cast<int>(dMult) == TIME_UNKNOWN)
521 {
522 strErr = "line " + to_string(nLine) + ": units for simulation timestep";
523 break;
524 }
525
526 // we have the multiplier, now calculate the timestep in hours: look for the whitespace between the number and unit
527 nPos = strRH.rfind(SPACE);
528
529 if (nPos == string::npos)
530 {
531 strErr = "line " + to_string(nLine) + ": format of simulation timestep";
532 break;
533 }
534
535 // cut off rh bit of string
536 strRH.resize(nPos);
537
538 // remove trailing spaces
539 strRH = strTrimRight(&strRH);
540
541 // Check that this is a valid double
542 if (! bIsStringValidDouble(strRH))
543 {
544 strErr = "line " + to_string(nLine) + ": invalid floating point number for timestep '" + strRH + "' in " + m_strDataPathName;
545 break;
546 }
547
548 m_dTimeStep = strtod(strRH.c_str(), NULL) * dMult; // in hours
549
550 if (m_dTimeStep <= 0)
551 strErr = "line " + to_string(nLine) + ": timestep of simulation must be > 0";
552
554 strErr = "line " + to_string(nLine) + ": timestep of simulation must be < the duration of the simulation";
555
556 break;
557
558 case 7:
559 {
560 // 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"
561 strRH = strToLower(&strRH);
562
563 // Split by commas to handle multiple unit groups
564 string const strOriginal = strRH;
565 size_t nCommaPos = 0;
566
567 m_bSaveRegular = false; // Start with assumption of multiple values
568
569 do
570 {
571 string strGroup;
572 size_t const nNextComma = strOriginal.find(',', nCommaPos);
573
574 if (nNextComma != string::npos)
575 {
576 strGroup = strOriginal.substr(nCommaPos, nNextComma - nCommaPos);
577 nCommaPos = nNextComma + 1;
578 }
579
580 else
581 {
582 strGroup = strOriginal.substr(nCommaPos);
583 nCommaPos = string::npos;
584 }
585
586 // Trim whitespace from group
587 strGroup = strTrimLeft(&strGroup);
588 strGroup = strTrimRight(&strGroup);
589
590 if (strGroup.empty())
591 continue;
592
593 // Get the multiplier for this group
594 dMult = dGetTimeMultiplier(&strGroup);
595
596 if (static_cast<int>(dMult) == TIME_UNKNOWN)
597 {
598 strErr = "line " + to_string(nLine) + ": units for save intervals in group '" + strGroup + "'";
599 break;
600 }
601
602 // Remove the unit text from the end
603 size_t const nLastSpace = strGroup.rfind(SPACE);
604
605 if (nLastSpace == string::npos)
606 {
607 strErr = "line " + to_string(nLine) + ": format of save times/intervals in group '" + strGroup + "'";
608 break;
609 }
610
611 string strNumbers = strGroup.substr(0, nLastSpace);
612 strNumbers = strTrimRight(&strNumbers);
613
614 // Parse numbers in this group
615 size_t nSpacePos = 0;
616 strNumbers += SPACE; // Add trailing space to help parsing
617
618 do
619 {
620 size_t const nNextSpace = strNumbers.find(SPACE, nSpacePos);
621
622 if (nNextSpace == string::npos)
623 break;
624
625 string const strNumber = strNumbers.substr(nSpacePos, nNextSpace - nSpacePos);
626
627 if (!strNumber.empty())
628 {
629 if (m_nUSave > static_cast<int>(SAVEMAX) - 1)
630 {
631 strErr = "line " + to_string(nLine) + ": too many save intervals";
632 break;
633 }
634
635 double const dValue = strtod(strNumber.c_str(), NULL) * dMult;
636 m_dUSaveTime[m_nUSave++] = dValue;
637 }
638
639 nSpacePos = nNextSpace + 1;
640 } while (nSpacePos < strNumbers.length());
641
642 if (!strErr.empty())
643 break;
644 } while (nCommaPos != string::npos);
645
646 if (!strErr.empty())
647 break;
648
649 // Check if we only have one value (making it a regular interval)
650 if (m_nUSave == 1)
651 {
652 m_bSaveRegular = true;
654
656 strErr = "line " + to_string(nLine) + ": save interval cannot be less than timestep";
657
658 else
660 }
661
662 else if (m_nUSave > 1)
663 {
664 // Multiple values - sort them and validate
666
667 if (m_dUSaveTime[0] < m_dTimeStep)
668 {
669 strErr = "line " + to_string(nLine) + ": first save time cannot be less than timestep";
670 break;
671 }
672
673 // Put a dummy save interval as the last entry in the array
675 }
676
677 else
678 {
679 strErr = "line " + to_string(nLine) + ": no save times specified";
680 }
681 }
682 break;
683
684 case 8:
685 // Random number seed(s)
686 if (strRH.empty())
687 {
688 // User didn't specify a random number seed, so seed with a real random value, if available
689 random_device rdev;
690 m_ulRandSeed[0] = rdev();
691
692 // Only one seed specified, so make all seeds the same
693 for (int n = 1; n < NUMBER_OF_RNGS; n++)
694 m_ulRandSeed[n] = m_ulRandSeed[n - 1];
695 }
696
697 else
698 {
699 // 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
700 nPos = strRH.find(SPACE);
701
702 if (nPos == string::npos)
703 {
704 // No space, so we have just one one number
705 m_ulRandSeed[0] = atol(strRH.c_str());
706
707 // Only one seed specified, so make all seeds the same
708 for (int n = 1; n < NUMBER_OF_RNGS; n++)
709 m_ulRandSeed[n] = m_ulRandSeed[n - 1];
710 }
711
712 else
713 {
714 // The user has supplied more than one random number seed
715 int n = 0;
716
717 do
718 {
719 // Get LH bit
720 strTmp = strRH.substr(0, nPos);
721 m_ulRandSeed[n++] = atol(strTmp.c_str());
722
723 if (n == NUMBER_OF_RNGS)
724 // All random number seeds read
725 break;
726
727 // We need more seeds, so get the RH bit
728 strRH = strRH.substr(nPos, strRH.size() - nPos);
729 strRH = strTrimLeft(&strRH);
730
731 if (strRH.size() == 0)
732 // No more seeds left to read
733 break;
734 } while (true);
735
736 // If we haven't filled all random number seeds, make all the remainder the same as the last one read
737 if (n < NUMBER_OF_RNGS - 1)
738 {
739 for (int m = n; m < NUMBER_OF_RNGS; m++)
741 }
742 }
743 }
744
745 break;
746
747 case 9:
748 // Max save digits for GIS output file names
749 if (! bIsStringValidInt(strRH))
750 {
751 strErr = "line " + to_string(nLine) + ": invalid integer for max save digits for GIS output file names '" + strRH + "' in " + m_strDataPathName;
752 break;
753 }
754
755 m_nGISMaxSaveDigits = stoi(strRH);
756
757 if (m_nGISMaxSaveDigits < 2)
758 strErr = "line " + to_string(nLine) + ": max save digits for GIS output file names must be > 1";
759
760 break;
761
762 case 10:
763 // Save digits for GIS output sequential or iteration number? [s = sequential, i = iteration]: s
764 if (strRH.empty())
765 strErr = "line " + to_string(nLine) + ": must specify save digits for GIS output as sequential or as iteration number";
766
767 else
768 {
769 // Convert to lower case
770 strRH = strToLower(&strRH);
771
772 if (strRH.find('s') != string::npos)
773 {
774 // First look for 's'
776 }
777
778 else if (strRH.find('i') != string::npos)
779 {
780 // Now look for 'i'
782 }
783
784 else
785 {
786 strErr = "line ";
787 strErr += to_string(nLine);
788 strErr += ": invalid code for save digits for GIS output save number (must be s or i)";
789
790 break;
791 }
792 }
793
794 break;
795
796 case 11:
797 // Raster GIS files to output
798 if (strRH.empty())
799 {
800 strErr = "line ";
801 strErr += to_string(nLine);
802 strErr += ": must contain '";
803 strErr += RASTER_ALL_OUTPUT_CODE;
804 strErr += "', or '";
805 strErr += RASTER_USUAL_OUTPUT_CODE;
806 strErr += "', or at least one raster GIS output code";
807 }
808
809 else
810 {
811 // Convert to lower case
812 strRH = strToLower(&strRH);
813
814 if (strRH.find(RASTER_ALL_OUTPUT_CODE) != string::npos)
815 {
816 // 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
866 }
867
868 else if (strRH.find(RASTER_USUAL_OUTPUT_CODE) != string::npos)
869 {
870 // Set switches for usual GIS raster output. Again, some of these (e.g. all relating to fine sediment) are ignored if they are irrelevant
912 }
913 else
914 {
915 // 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
916 if (strRH.find(RASTER_SEDIMENT_TOP_CODE) != string::npos)
917 {
920 }
921
922 if (strRH.find(RASTER_TOP_CODE) != string::npos)
923 {
924 m_bTopSurfSave = true;
925 strRH = strRemoveSubstr(&strRH, &RASTER_TOP_CODE);
926 }
927
928 if (strRH.find(RASTER_SEA_DEPTH_CODE) != string::npos)
929 {
930 m_bSeaDepthSave = true;
931 strRH = strRemoveSubstr(&strRH, &RASTER_SEA_DEPTH_CODE);
932 }
933
934 if (strRH.find(RASTER_WAVE_HEIGHT_CODE) != string::npos)
935 {
936 m_bWaveHeightSave = true;
938 }
939
940 if (strRH.find(RASTER_WAVE_ORIENTATION_CODE) != string::npos)
941 {
942 m_bWaveAngleSave = true;
944 }
945
946 if (strRH.find(RASTER_WAVE_PERIOD_CODE) != string::npos)
947 {
950 }
951
952 if (strRH.find(RASTER_POTENTIAL_PLATFORM_EROSION_CODE) != string::npos)
953 {
956 }
957
958 if (strRH.find(RASTER_ACTUAL_PLATFORM_EROSION_CODE) != string::npos)
959 {
962 }
963
964 if (strRH.find(RASTER_TOTAL_POTENTIAL_PLATFORM_EROSION_CODE) != string::npos)
965 {
968 }
969
970 if (strRH.find(RASTER_TOTAL_ACTUAL_PLATFORM_EROSION_CODE) != string::npos)
971 {
974 }
975
976 if (strRH.find(RASTER_POTENTIAL_BEACH_EROSION_CODE) != string::npos)
977 {
980 }
981
982 if (strRH.find(RASTER_ACTUAL_BEACH_EROSION_CODE) != string::npos)
983 {
986 }
987
988 if (strRH.find(RASTER_TOTAL_POTENTIAL_BEACH_EROSION_CODE) != string::npos)
989 {
992 }
993
994 if (strRH.find(RASTER_TOTAL_ACTUAL_BEACH_EROSION_CODE) != string::npos)
995 {
998 }
999
1000 if (strRH.find(RASTER_LANDFORM_CODE) != string::npos)
1001 {
1002 m_bLandformSave = true;
1003 strRH = strRemoveSubstr(&strRH, &RASTER_LANDFORM_CODE);
1004 }
1005
1006 if (strRH.find(RASTER_LOCAL_SLOPE_CODE) != string::npos)
1007 {
1008 m_bLocalSlopeSave = true;
1009 strRH = strRemoveSubstr(&strRH, &RASTER_LOCAL_SLOPE_CODE);
1010 }
1011
1012 if (strRH.find(RASTER_SLOPE_CODE) != string::npos)
1013 {
1014 m_bSlopeSave = true;
1015 strRH = strRemoveSubstr(&strRH, &RASTER_SLOPE_CODE);
1016 }
1017
1018 if (strRH.find(RASTER_CLIFF_CODE) != string::npos)
1019 {
1020 m_bCliffSave = true;
1021 strRH = strRemoveSubstr(&strRH, &RASTER_CLIFF_CODE);
1022 }
1023
1024 if (strRH.find(RASTER_AVG_SEA_DEPTH_CODE) != string::npos)
1025 {
1026 m_bAvgSeaDepthSave = true;
1028 }
1029
1030 if (strRH.find(RASTER_AVG_WAVE_HEIGHT_CODE) != string::npos)
1031 {
1032 m_bAvgWaveHeightSave = true;
1034 }
1035
1036 if (strRH.find(RASTER_AVG_WAVE_ORIENTATION_CODE) != string::npos)
1037 {
1038 m_bAvgWaveAngleSave = true;
1040 }
1041
1042 if (strRH.find(RASTER_BEACH_PROTECTION_CODE) != string::npos)
1043 {
1046 }
1047
1048 if (strRH.find(RASTER_BASEMENT_ELEVATION_CODE) != string::npos)
1049 {
1050 m_bBasementElevSave = true;
1052 }
1053
1054 if (strRH.find(RASTER_SUSP_SED_CODE) != string::npos)
1055 {
1056 m_bSuspSedSave = true;
1057 strRH = strRemoveSubstr(&strRH, &RASTER_SUSP_SED_CODE);
1058 }
1059
1060 if (strRH.find(RASTER_AVG_SUSP_SED_CODE) != string::npos)
1061 {
1062 m_bAvgSuspSedSave = true;
1063 strRH = strRemoveSubstr(&strRH, &RASTER_AVG_SUSP_SED_CODE);
1064 }
1065
1066 if (strRH.find(RASTER_FINE_UNCONS_CODE) != string::npos)
1067 {
1068 m_bFineUnconsSedSave = true;
1069 strRH = strRemoveSubstr(&strRH, &RASTER_FINE_UNCONS_CODE);
1070 }
1071
1072 if (strRH.find(RASTER_SAND_UNCONS_CODE) != string::npos)
1073 {
1074 m_bSandUnconsSedSave = true;
1075 strRH = strRemoveSubstr(&strRH, &RASTER_SAND_UNCONS_CODE);
1076 }
1077
1078 if (strRH.find(RASTER_COARSE_UNCONS_CODE) != string::npos)
1079 {
1082 }
1083
1084 if (strRH.find(RASTER_FINE_CONS_CODE) != string::npos)
1085 {
1086 m_bFineConsSedSave = true;
1087 strRH = strRemoveSubstr(&strRH, &RASTER_FINE_CONS_CODE);
1088 }
1089
1090 if (strRH.find(RASTER_SAND_CONS_CODE) != string::npos)
1091 {
1092 m_bSandConsSedSave = true;
1093 strRH = strRemoveSubstr(&strRH, &RASTER_SAND_CONS_CODE);
1094 }
1095
1096 if (strRH.find(RASTER_COARSE_CONS_CODE) != string::npos)
1097 {
1098 m_bCoarseConsSedSave = true;
1099 strRH = strRemoveSubstr(&strRH, &RASTER_COARSE_CONS_CODE);
1100 }
1101
1102 if (strRH.find(RASTER_COAST_CODE) != string::npos)
1103 {
1105 strRH = strRemoveSubstr(&strRH, &RASTER_COAST_CODE);
1106 }
1107
1108 if (strRH.find(RASTER_COAST_NORMAL_CODE) != string::npos)
1109 {
1111 strRH = strRemoveSubstr(&strRH, &RASTER_COAST_NORMAL_CODE);
1112 }
1113
1114 if (strRH.find(RASTER_ACTIVE_ZONE_CODE) != string::npos)
1115 {
1116 m_bActiveZoneSave = true;
1117 strRH = strRemoveSubstr(&strRH, &RASTER_ACTIVE_ZONE_CODE);
1118 }
1119
1120 if (strRH.find(RASTER_CLIFF_COLLAPSE_EROSION_FINE_CODE) != string::npos)
1121 {
1122 m_bCliffCollapseSave = true;
1124 }
1125
1126 if (strRH.find(RASTER_CLIFF_COLLAPSE_EROSION_SAND_CODE) != string::npos)
1127 {
1128 m_bCliffCollapseSave = true;
1130 }
1131
1132 if (strRH.find(RASTER_CLIFF_COLLAPSE_EROSION_COARSE_CODE) != string::npos)
1133 {
1134 m_bCliffCollapseSave = true;
1136 }
1137
1138 if (strRH.find(RASTER_TOTAL_CLIFF_COLLAPSE_EROSION_FINE_CODE) != string::npos)
1139 {
1142 }
1143
1144 if (strRH.find(RASTER_TOTAL_CLIFF_COLLAPSE_EROSION_SAND_CODE) != string::npos)
1145 {
1148 }
1149
1150 if (strRH.find(RASTER_TOTAL_CLIFF_COLLAPSE_EROSION_COARSE_CODE) != string::npos)
1151 {
1154 }
1155
1156 if (strRH.find(RASTER_CLIFF_COLLAPSE_DEPOSITION_SAND_CODE) != string::npos)
1157 {
1160 }
1161
1162 if (strRH.find(RASTER_CLIFF_COLLAPSE_DEPOSITION_COARSE_CODE) != string::npos)
1163 {
1166 }
1167
1168 if (strRH.find(RASTER_TOTAL_CLIFF_COLLAPSE_DEPOSITION_SAND_CODE) != string::npos)
1169 {
1172 }
1173
1174 if (strRH.find(RASTER_TOTAL_CLIFF_COLLAPSE_DEPOSITION_COARSE_CODE) != string::npos)
1175 {
1178 }
1179
1180 if (strRH.find(RASTER_POLYGON_CODE) != string::npos)
1181 {
1182 m_bRasterPolygonSave = true;
1183 strRH = strRemoveSubstr(&strRH, &RASTER_POLYGON_CODE);
1184 }
1185
1186 if (strRH.find(RASTER_POTENTIAL_PLATFORM_EROSION_MASK_CODE) != string::npos)
1187 {
1190 }
1191
1192 if (strRH.find(RASTER_INUNDATION_MASK_CODE) != string::npos)
1193 {
1194 m_bSeaMaskSave = true;
1196 }
1197
1198 if (strRH.find(RASTER_BEACH_MASK_CODE) != string::npos)
1199 {
1200 m_bBeachMaskSave = true;
1201 strRH = strRemoveSubstr(&strRH, &RASTER_BEACH_MASK_CODE);
1202 }
1203
1204 if (strRH.find(RASTER_INTERVENTION_CLASS_CODE) != string::npos)
1205 {
1208 }
1209
1210 if (strRH.find(RASTER_INTERVENTION_HEIGHT_CODE) != string::npos)
1211 {
1214 }
1215
1216 if (strRH.find(RASTER_SHADOW_ZONE_CODE) != string::npos)
1217 {
1219 strRH = strRemoveSubstr(&strRH, &RASTER_SHADOW_ZONE_CODE);
1220 }
1221
1222 if (strRH.find(RASTER_DEEP_WATER_WAVE_ORIENTATION_CODE) != string::npos)
1223 {
1226 }
1227
1228 if (strRH.find(RASTER_DEEP_WATER_WAVE_HEIGHT_CODE) != string::npos)
1229 {
1232 }
1233
1234 if (strRH.find(RASTER_DEEP_WATER_WAVE_PERIOD_CODE) != string::npos)
1235 {
1238 }
1239
1240 if (strRH.find(RASTER_POLYGON_UPDRIFT_OR_DOWNDRIFT_CODE) != string::npos)
1241 {
1244 }
1245
1246 if (strRH.find(RASTER_POLYGON_GAIN_OR_LOSS_CODE) != string::npos)
1247 {
1250 }
1251
1252 if (strRH.find(RASTER_BEACH_DEPOSITION_CODE) != string::npos)
1253 {
1256 }
1257
1258 if (strRH.find(RASTER_TOTAL_BEACH_DEPOSITION_CODE) != string::npos)
1259 {
1262 }
1263
1264 if (strRH.find(RASTER_SEDIMENT_INPUT_EVENT_CODE) != string::npos)
1265 {
1268 }
1269
1270 if (strRH.find(RASTER_SETUP_SURGE_FLOOD_MASK_CODE) != string::npos)
1271 {
1274 }
1275
1276 if (strRH.find(RASTER_SETUP_SURGE_RUNUP_FLOOD_MASK_CODE) != string::npos)
1277 {
1280 }
1281
1282 if (strRH.find(RASTER_WAVE_FLOOD_LINE_CODE) != string::npos)
1283 {
1286 }
1287
1288 // Check to see if all codes have been removed
1289 if (!strRH.empty())
1290 strErr = "line " + to_string(nLine) + ": unknown code '" + strRH + "' in list of codes for raster GIS output";
1291 }
1292 }
1293
1294 break;
1295
1296 case 12:
1297 // Raster GIS output format (note must retain original case). Blank means use same format as input DEM file (if possible)
1299
1300 // TODO 065 Remove this when GDAL gpkg raster output is working correctly
1301 if (strRH.find("gpkg") != string::npos)
1302 strErr = "GDAL gpkg raster create() is not yet working correctly. Please choose another output format.";
1303
1304 break;
1305
1306 case 13:
1307 // If needed, scale GIS raster output values
1308 strRH = strToLower(&strRH);
1309
1310 m_bScaleRasterOutput = false;
1311
1312 if (strRH.find('y') != string::npos)
1313 m_bScaleRasterOutput = true;
1314
1315 break;
1316
1317 case 14:
1318 // If needed, also output GIS raster world file
1319 strRH = strToLower(&strRH);
1320
1321 m_bWorldFile = false;
1322
1323 if (strRH.find('y') != string::npos)
1324 m_bWorldFile = true;
1325
1326 break;
1327
1328 case 15:
1329 // Elevations for raster slice output, if desired
1330 if (!strRH.empty())
1331 {
1332 m_bSliceSave = true;
1333
1334 // OK, so find out whether we're dealing with a single seed or more than one: check for a space
1335 nPos = strRH.find(SPACE);
1336
1337 if (nPos != string::npos)
1338 {
1339 // There's a space, so we must have more than one number
1340 do
1341 {
1342 // Get LH bit
1343 strTmp = strRH.substr(0, nPos);
1344 m_VdSliceElev.push_back(strtod(strTmp.c_str(), NULL));
1345
1346 // Get the RH bit
1347 strRH = strRH.substr(nPos, strRH.size() - nPos);
1348 strRH = strTrimLeft(&strRH);
1349
1350 // Now look for another space
1351 nPos = strRH.find(SPACE);
1352 } while (nPos != string::npos);
1353 }
1354
1355 // Read either the single number, or the left-over number
1356 m_VdSliceElev.push_back(strtod(strTmp.c_str(), NULL));
1357 }
1358
1359 break;
1360
1361 case 16:
1362 // Vector GIS files to output
1363 if (strRH.empty())
1364 {
1365 strErr = "line ";
1366 strErr += to_string(nLine);
1367 strErr += ": must contain '";
1368 strErr += VECTOR_ALL_OUTPUT_CODE;
1369 strErr += "', or '";
1370 strErr += VECTOR_USUAL_OUTPUT_CODE;
1371 strErr += "', or at least one vector GIS output code";
1372 }
1373
1374 else
1375 {
1376 strRH = strToLower(&strRH);
1377
1378 if (strRH.find(VECTOR_ALL_OUTPUT_CODE) != string::npos)
1379 {
1380 // Output all vector files
1381 m_bCoastSave =
1399 m_bRunUpSave =
1401 }
1402
1403 else if (strRH.find(VECTOR_USUAL_OUTPUT_CODE) != string::npos)
1404 {
1405 // Output the "usual" collection of vector output files
1406 m_bCoastSave =
1420 }
1421
1422 else
1423 {
1424 // Output only those vector files for which the user specified the code
1425 if (strRH.find(VECTOR_COAST_CODE) != string::npos)
1426 {
1427 m_bCoastSave = true;
1428 strRH = strRemoveSubstr(&strRH, &VECTOR_COAST_CODE);
1429 }
1430
1431 if (strRH.find(VECTOR_CLIFF_EDGE_CODE) != string::npos)
1432 {
1433 m_bCliffEdgeSave = true;
1434 strRH = strRemoveSubstr(&strRH, &VECTOR_CLIFF_EDGE_CODE);
1435 }
1436
1437 if (strRH.find(VECTOR_AVG_WAVE_ANGLE_AND_HEIGHT_CODE) != string::npos)
1438 {
1441 }
1442
1443 if (strRH.find(VECTOR_NORMALS_CODE) != string::npos)
1444 {
1445 m_bNormalsSave = true;
1446 strRH = strRemoveSubstr(&strRH, &VECTOR_NORMALS_CODE);
1447 }
1448
1449 if (strRH.find(VECTOR_INVALID_NORMALS_CODE) != string::npos)
1450 {
1451 m_bInvalidNormalsSave = true;
1453 }
1454
1455 if (strRH.find(VECTOR_AVG_WAVE_ANGLE_AND_HEIGHT_CODE) != string::npos)
1456 {
1459 }
1460
1461 if (strRH.find(VECTOR_COAST_CURVATURE_CODE) != string::npos)
1462 {
1463 m_bCoastCurvatureSave = true;
1465 }
1466
1467 if (strRH.find(VECTOR_WAVE_ENERGY_SINCE_COLLAPSE_CODE) != string::npos)
1468 {
1471 }
1472
1473 if (strRH.find(VECTOR_MEAN_WAVE_ENERGY_CODE) != string::npos)
1474 {
1475 m_bMeanWaveEnergySave = true;
1477 }
1478
1479 if (strRH.find(VECTOR_BREAKING_WAVE_HEIGHT_CODE) != string::npos)
1480 {
1483 }
1484
1485 if (strRH.find(VECTOR_POLYGON_NODE_CODE) != string::npos)
1486 {
1487 m_bPolygonNodeSave = true;
1488 strRH = strRemoveSubstr(&strRH, &VECTOR_POLYGON_NODE_CODE);
1489 }
1490
1491 if (strRH.find(VECTOR_POLYGON_BOUNDARY_CODE) != string::npos)
1492 {
1495 }
1496
1497 if (strRH.find(VECTOR_CLIFF_NOTCH_SIZE_CODE) != string::npos)
1498 {
1499 m_bCliffNotchSave = true;
1501 }
1502
1503 if (strRH.find(VECTOR_SHADOW_BOUNDARY_CODE) != string::npos)
1504 {
1505 m_bShadowBoundarySave = true;
1507 }
1508
1509 if (strRH.find(VECTOR_DOWNDRIFT_BOUNDARY_CODE) != string::npos)
1510 {
1513 }
1514
1515 if (strRH.find(VECTOR_DEEP_WATER_WAVE_ANGLE_AND_HEIGHT_CODE) != string::npos)
1516 {
1519 }
1520
1521 if (strRH.find(VECTOR_WAVE_SETUP_CODE) != string::npos)
1522 {
1523 m_bWaveSetupSave = true;
1524 strRH = strRemoveSubstr(&strRH, &VECTOR_WAVE_SETUP_CODE);
1525 }
1526
1527 if (strRH.find(VECTOR_STORM_SURGE_CODE) != string::npos)
1528 {
1529 m_bStormSurgeSave = true;
1530 strRH = strRemoveSubstr(&strRH, &VECTOR_STORM_SURGE_CODE);
1531 }
1532
1533 if (strRH.find(VECTOR_RUN_UP_CODE) != string::npos)
1534 {
1535 m_bRunUpSave = true;
1536 strRH = strRemoveSubstr(&strRH, &VECTOR_RUN_UP_CODE);
1537 }
1538
1539 if (strRH.find(VECTOR_FLOOD_LINE_CODE) != string::npos)
1540 {
1542 strRH = strRemoveSubstr(&strRH, &VECTOR_FLOOD_LINE_CODE);
1543 }
1544
1545 // Check to see if all codes have been removed
1546 if (!strRH.empty())
1547 strErr = "line " + to_string(nLine) + ": unknown code '" + strRH + "' in list of vector GIS output codes";
1548 }
1549 }
1550
1551 break;
1552
1553 case 17:
1554 // Vector GIS output format (note must retain original case)
1556
1557 if (strRH.empty())
1558 strErr = "line " + to_string(nLine) + ": vector GIS output format";
1559
1560 break;
1561
1562 case 18:
1563 // Time series files to output
1564 if (!strRH.empty())
1565 {
1566 strRH = strToLower(&strRH);
1567
1568 // First check for "all"
1569 if (strRH.find(RASTER_ALL_OUTPUT_CODE) != string::npos)
1570 {
1583 }
1584
1585 else
1586 {
1587 if (strRH.find(TIME_SERIES_SEA_AREA_CODE) != string::npos)
1588 {
1589 m_bSeaAreaTSSave = true;
1591 }
1592
1593 if (strRH.find(TIME_SERIES_STILL_WATER_LEVEL_CODE) != string::npos)
1594 {
1597 }
1598
1599 if (strRH.find(TIME_SERIES_PLATFORM_EROSION_CODE) != string::npos)
1600 {
1603 }
1604
1605 if (strRH.find(TIME_SERIES_CLIFF_COLLAPSE_EROSION_CODE) != string::npos)
1606 {
1609 }
1610
1611 if (strRH.find(TIME_SERIES_CLIFF_COLLAPSE_DEPOSITION_CODE) != string::npos)
1612 {
1615 }
1616
1617 if (strRH.find(TIME_SERIES_CLIFF_COLLAPSE_NET_CODE) != string::npos)
1618 {
1621 }
1622
1623 if (strRH.find(TIME_SERIES_BEACH_EROSION_CODE) != string::npos)
1624 {
1625 m_bBeachErosionTSSave = true;
1627 }
1628
1629 if (strRH.find(TIME_SERIES_BEACH_DEPOSITION_CODE) != string::npos)
1630 {
1633 }
1634
1635 if (strRH.find(TIME_SERIES_BEACH_CHANGE_NET_CODE) != string::npos)
1636 {
1639 }
1640
1641 if (strRH.find(TIME_SERIES_SUSPENDED_SEDIMENT_CODE) != string::npos)
1642 {
1643 m_bSuspSedTSSave = true;
1645 }
1646
1647 if (strRH.find(TIME_SERIES_FLOOD_SETUP_SURGE_CODE) != string::npos)
1648 {
1651 }
1652
1653 if (strRH.find(TIME_SERIES_FLOOD_SETUP_SURGE_RUNUP_CODE) != string::npos)
1654 {
1657 }
1658
1659 // Check to see if all codes have been removed
1660 if (!strRH.empty())
1661 strErr = "line " + to_string(nLine) + ": unknown code '" + strRH + "' in list of time series output files";
1662 }
1663 }
1664
1665 break;
1666
1667 case 19:
1668 // Vector coastline smoothing algorithm: 0 = none, 1 = running mean, 2 = Savitzky-Golay
1669 if (! bIsStringValidInt(strRH))
1670 {
1671 strErr = "line " + to_string(nLine) + ": invalid integer for coastline smoothing algorithm '" + strRH + "' in " + m_strDataPathName;
1672 break;
1673 }
1674
1675 m_nCoastSmooth = stoi(strRH);
1676
1678 strErr = "line " + to_string(nLine) + ": coastline vector smoothing algorithm";
1679
1680 break;
1681
1682 case 20:
1683 // Size of coastline smoothing window: must be odd
1684 if (! bIsStringValidInt(strRH))
1685 {
1686 strErr = "line " + to_string(nLine) + ": invalid integer for coastline smoothing window '" + strRH + "' in " + m_strDataPathName;
1687 break;
1688 }
1689
1690 m_nCoastSmoothingWindowSize = stoi(strRH);
1691
1693 strErr = "line " + to_string(nLine) + ": size of coastline vector smoothing window (must be > 0 and odd)";
1694
1695 break;
1696
1697 case 21:
1698 // Order of coastline profile smoothing polynomial for Savitzky-Golay: usually 2 or 4, max is 6
1699 if (! bIsStringValidInt(strRH))
1700 {
1701 strErr = "line " + to_string(nLine) + ": invalid integer for Savitzky-Golay polynomial for coastline smoothing '" + strRH + "' in " + m_strDataPathName;
1702 break;
1703 }
1704
1705 m_nSavGolCoastPoly = stoi(strRH);
1706
1707 if ((m_nSavGolCoastPoly <= 0) || (m_nSavGolCoastPoly > 6))
1708 strErr = "line " + to_string(nLine) + ": value of Savitzky-Golay polynomial for coastline smoothing (must be <= 6)";
1709
1710 break;
1711
1712 case 22:
1713 // Grid edge(s) to omit when searching for coastline [NSWE]
1714 strRH = strToLower(&strRH);
1715
1716 if (strRH.find('n') != string::npos)
1717 {
1719 }
1720
1721 if (strRH.find('s') != string::npos)
1722 {
1724 }
1725
1726 if (strRH.find('w') != string::npos)
1727 {
1728 m_bOmitSearchWestEdge = true;
1729 }
1730
1731 if (strRH.find('e') != string::npos)
1732 {
1733 m_bOmitSearchEastEdge = true;
1734 }
1735
1736 break;
1737
1738 case 23:
1739 // Profile slope running-mean smoothing window size: must be odd
1740 if (! bIsStringValidInt(strRH))
1741 {
1742 strErr = "line " + to_string(nLine) + ": invalid integer for size of coastline smoothing window '" + strRH + "' in " + m_strDataPathName;
1743 break;
1744 }
1745
1746 m_nProfileSmoothWindow = stoi(strRH);
1747
1749 strErr = "line " + to_string(nLine) + ": size of profile vector smoothing window (must be >= 0, if > 0 must be odd)";
1750
1751 break;
1752
1753 case 24:
1754 // Max local slope (m/m), first check that this is a valid double
1755 if (! bIsStringValidDouble(strRH))
1756 {
1757 strErr = "line " + to_string(nLine) + ": invalid floating point number for max local slope '" + strRH + "' in " + m_strDataPathName;
1758 break;
1759 }
1760
1761 m_dProfileMaxSlope = strtod(strRH.c_str(), NULL);
1762
1763 if (m_dProfileMaxSlope <= 0)
1764 strErr = "line " + to_string(nLine) + ": max local slope must be > 0";
1765
1766 break;
1767
1768 case 25:
1769 // Maximum elevation of beach above SWL, first check that this is a valid double
1770 if (! bIsStringValidDouble(strRH))
1771 {
1772 strErr = "line " + to_string(nLine) + ": invalid floating point number for maximum elevation of beach above SWL '" + strRH + "' in " + m_strDataPathName;
1773 break;
1774 }
1775
1776 m_dMaxBeachElevAboveSWL = strtod(strRH.c_str(), NULL);
1777
1779 strErr = "line " + to_string(nLine) + ": maximum elevation of beach above SWL must be >= 0";
1780
1781 break;
1782
1783 // ------------------------------------------------- Raster GIS layers ------------------------------------------------
1784 case 26:
1785 // Number of sediment layers
1786 if (! bIsStringValidInt(strRH))
1787 {
1788 strErr = "line " + to_string(nLine) + ": invalid integer for number of sediment layers '" + strRH + "' in " + m_strDataPathName;
1789 break;
1790 }
1791
1792 m_nLayers = stoi(strRH);
1793
1794 if (m_nLayers < 1)
1795 {
1796 strErr = "line " + to_string(nLine) + ": must be at least one sediment layer";
1797 break;
1798 }
1799
1800 // OK we know the number of layers, so add elements to these vectors
1801 for (int j = 0; j < m_nLayers; j++)
1802 {
1809 m_VstrGDALIUFDriverCode.push_back("");
1810 m_VstrGDALIUFDriverDesc.push_back("");
1811 m_VstrGDALIUFProjection.push_back("");
1812 m_VstrGDALIUFDataType.push_back("");
1813 m_VstrGDALIUSDriverCode.push_back("");
1814 m_VstrGDALIUSDriverDesc.push_back("");
1815 m_VstrGDALIUSProjection.push_back("");
1816 m_VstrGDALIUSDataType.push_back("");
1817 m_VstrGDALIUCDriverCode.push_back("");
1818 m_VstrGDALIUCDriverDesc.push_back("");
1819 m_VstrGDALIUCProjection.push_back("");
1820 m_VstrGDALIUCDataType.push_back("");
1821 m_VstrGDALICFDriverCode.push_back("");
1822 m_VstrGDALICFDriverDesc.push_back("");
1823 m_VstrGDALICFProjection.push_back("");
1824 m_VstrGDALICFDataType.push_back("");
1825 m_VstrGDALICSDriverCode.push_back("");
1826 m_VstrGDALICSDriverDesc.push_back("");
1827 m_VstrGDALICSProjection.push_back("");
1828 m_VstrGDALICSDataType.push_back("");
1829 m_VstrGDALICCDriverCode.push_back("");
1830 m_VstrGDALICCDriverDesc.push_back("");
1831 m_VstrGDALICCProjection.push_back("");
1832 m_VstrGDALICCDataType.push_back("");
1833 }
1834
1835 break;
1836
1837 case 27:
1838 // Basement DEM file (can be blank)
1839 if (!strRH.empty())
1840 {
1841#ifdef _WIN32
1842 // For Windows, make sure has backslashes, not Unix-style slashes
1843 strRH = pstrChangeToBackslash(&strRH);
1844#endif
1845
1846 // Now check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
1847 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
1848 // It has an absolute path, so use it 'as is'
1850
1851 else
1852 {
1853 // It has a relative path, so prepend the CoastalME dir
1855 m_strInitialBasementDEMFile.append(strRH);
1856 }
1857 }
1858
1859 break;
1860
1861 case 28:
1862 // Read 6 x sediment files for each layer
1863 for (int nLayer = 0; nLayer < m_nLayers; nLayer++)
1864 {
1865 for (int j = 1; j <= 6; j++)
1866 {
1867 if (! bFirst)
1868 {
1869 do
1870 {
1871 if (!getline(InStream, strRec))
1872 {
1873 cerr << ERR << "premature end of file in " << m_strDataPathName << endl;
1874 return false;
1875 }
1876
1877 nLine++;
1878
1879 // Trim off leading and trailing whitespace
1880 strRec = strTrim(&strRec);
1881 }
1882
1883 // If it is a blank line or a comment then ignore it
1884 while (strRec.empty() || (strRec[0] == QUOTE1) || (strRec[0] == QUOTE2));
1885
1886 // Not blank or a comment, so find the colon: lines MUST have a colon separating data from leading description portion
1887 nPos = strRec.find(COLON);
1888
1889 if (nPos == string::npos)
1890 {
1891 // Error: badly formatted (no colon)
1892 cerr << ERR << "on line " << to_string(nLine) << ": badly formatted (no ':') in " << m_strDataPathName << endl
1893 << strRec << endl;
1894 return false;
1895 }
1896
1897 // Strip off leading portion (the bit up to and including the colon)
1898 strRH = strRec.substr(nPos + 1);
1899 // ERROR strRH.resize(nPos);
1900
1901 // Remove leading whitespace after the colon
1902 strRH = strTrimLeft(&strRH);
1903
1904 // Look for a trailing comment, if found then terminate string at that point and trim off any trailing whitespace
1905 nPos = strRH.rfind(QUOTE1);
1906
1907 if (nPos != string::npos)
1908 strRH.resize(nPos);
1909
1910 nPos = strRH.rfind(QUOTE2);
1911
1912 if (nPos != string::npos)
1913 strRH.resize(nPos);
1914
1915 // Trim trailing spaces
1916 strRH = strTrimRight(&strRH);
1917
1918#ifdef _WIN32
1919 // For Windows, make sure has backslashes, not Unix-style slashes
1920 strRH = pstrChangeToBackslash(&strRH);
1921#endif
1922 }
1923
1924 bFirst = false;
1925
1926 switch (j)
1927 {
1928 case 1:
1929
1930 // Initial fine unconsolidated sediment depth GIS file (can be blank)
1931 if (!strRH.empty())
1932 {
1933 // Set switch
1934 m_bHaveFineSediment = true;
1935#ifdef _WIN32
1936 // For Windows, make sure has backslashes, not Unix-style slashes
1937 strRH = pstrChangeToBackslash(&strRH);
1938#endif
1939
1940 // Now check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
1941 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
1942 {
1943 // It has an absolute path, so use it 'as is'
1945 }
1946
1947 else
1948 {
1949 // It has a relative path, so prepend the CoastalME dir
1951 m_VstrInitialFineUnconsSedimentFile[nLayer].append(strRH);
1952 }
1953 }
1954
1955 break;
1956
1957 case 2:
1958 // Initial sand unconsolidated sediment depth GIS file (can be blank)
1959 if (!strRH.empty())
1960 {
1961 // Set switch
1962 m_bHaveSandSediment = true;
1963#ifdef _WIN32
1964 // For Windows, make sure has backslashes, not Unix-style slashes
1965 strRH = pstrChangeToBackslash(&strRH);
1966#endif
1967
1968 // Now check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
1969 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
1970 {
1971 // It has an absolute path, so use it 'as is'
1973 }
1974
1975 else
1976 {
1977 // It has a relative path, so prepend the CoastalME dir
1979 m_VstrInitialSandUnconsSedimentFile[nLayer].append(strRH);
1980 }
1981 }
1982
1983 break;
1984
1985 case 3:
1986 // Initial coarse unconsolidated sediment depth GIS file (can be blank)
1987 if (!strRH.empty())
1988 {
1989 // Set switch
1990 m_bHaveCoarseSediment = true;
1991#ifdef _WIN32
1992 // For Windows, make sure has backslashes, not Unix-style slashes
1993 strRH = pstrChangeToBackslash(&strRH);
1994#endif
1995
1996 // Now check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
1997 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
1998 {
1999 // It has an absolute path, so use it 'as is'
2001 }
2002
2003 else
2004 {
2005 // It has a relative path, so prepend the CoastalME dir
2007 m_VstrInitialCoarseUnconsSedimentFile[nLayer].append(strRH);
2008 }
2009 }
2010
2011 break;
2012
2013 case 4:
2014 // Initial fine consolidated sediment depth GIS file (can be blank)
2015 if (!strRH.empty())
2016 {
2017 // Set switches
2019 m_bHaveFineSediment = true;
2020#ifdef _WIN32
2021 // For Windows, make sure has backslashes, not Unix-style slashes
2022 strRH = pstrChangeToBackslash(&strRH);
2023#endif
2024
2025 // Now check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
2026 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
2027 {
2028 // It has an absolute path, so use it 'as is'
2029 m_VstrInitialFineConsSedimentFile[nLayer] = strRH;
2030 }
2031
2032 else
2033 {
2034 // It has a relative path, so prepend the CoastalME dir
2036 m_VstrInitialFineConsSedimentFile[nLayer].append(strRH);
2037 }
2038 }
2039
2040 break;
2041
2042 case 5:
2043 // Initial sand consolidated sediment depth GIS file (can be blank)
2044 if (!strRH.empty())
2045 {
2046 // Set switches
2048 m_bHaveSandSediment = true;
2049#ifdef _WIN32
2050 // For Windows, make sure has backslashes, not Unix-style slashes
2051 strRH = pstrChangeToBackslash(&strRH);
2052#endif
2053
2054 // Now check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
2055 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
2056 {
2057 // It has an absolute path, so use it 'as is'
2058 m_VstrInitialSandConsSedimentFile[nLayer] = strRH;
2059 }
2060
2061 else
2062 {
2063 // It has a relative path, so prepend the CoastalME dir
2065 m_VstrInitialSandConsSedimentFile[nLayer].append(strRH);
2066 }
2067 }
2068
2069 break;
2070
2071 case 6:
2072 // Initial coarse consolidated sediment depth GIS file (can be blank)
2073 if (!strRH.empty())
2074 {
2075 // Set switches
2077 m_bHaveCoarseSediment = true;
2078#ifdef _WIN32
2079 // For Windows, make sure has backslashes, not Unix-style slashes
2080 strRH = pstrChangeToBackslash(&strRH);
2081#endif
2082
2083 // Now check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
2084 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
2085 {
2086 // It has an absolute path, so use it 'as is'
2088 }
2089
2090 else
2091 {
2092 // It has a relative path, so prepend the CoastalME dir
2094 m_VstrInitialCoarseConsSedimentFile[nLayer].append(strRH);
2095 }
2096 }
2097
2098 break;
2099 }
2100
2101 // Did an error occur?
2102 if (!strErr.empty())
2103 {
2104 // Error in input to run details file
2105 cerr << ERR << "reading " << strErr << " in " << m_strDataPathName << endl
2106 << "'" << strRec << "'" << endl;
2107 InStream.close();
2108 return false;
2109 }
2110 }
2111 }
2112
2113 break;
2114
2115 case 29:
2116 // Initial suspended sediment depth GIS file (can be blank)
2117 if (!strRH.empty())
2118 {
2119 // Set switch
2120 m_bHaveFineSediment = true;
2121#ifdef _WIN32
2122 // For Windows, make sure has backslashes, not Unix-style slashes
2123 strRH = pstrChangeToBackslash(&strRH);
2124#endif
2125
2126 // Now check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
2127 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
2128 {
2129 // It has an absolute path, so use it 'as is'
2131 }
2132
2133 else
2134 {
2135 // It has a relative path, so prepend the CoastalME dir
2137 m_strInitialSuspSedimentFile.append(strRH);
2138 }
2139 }
2140
2141 break;
2142
2143 case 30:
2144 // Initial Landform class GIS file (can be blank)
2145 if (!strRH.empty())
2146 {
2147#ifdef _WIN32
2148 // For Windows, make sure has backslashes, not Unix-style slashes
2149 strRH = pstrChangeToBackslash(&strRH);
2150#endif
2151
2152 // Now check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
2153 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
2154 {
2155 // It has an absolute path, so use it 'as is'
2157 }
2158
2159 else
2160 {
2161 // It has a relative path, so prepend the CoastalME dir
2163 m_strInitialLandformFile.append(strRH);
2164 }
2165 }
2166
2167 break;
2168
2169 case 31:
2170 // Initial Intervention class GIS file (can be blank: if so then intervention height file must also be blank)
2171 if (!strRH.empty())
2172 {
2173#ifdef _WIN32
2174 // For Windows, make sure has backslashes, not Unix-style slashes
2175 strRH = pstrChangeToBackslash(&strRH);
2176#endif
2177
2178 // Now check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
2179 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
2180 {
2181 // It has an absolute path, so use it 'as is'
2183 }
2184
2185 else
2186 {
2187 // It has a relative path, so prepend the CoastalME dir
2189 m_strInterventionClassFile.append(strRH);
2190 }
2191
2192 // Set the save switches
2195 }
2196
2197 break;
2198
2199 case 32:
2200 // Initial Intervention height GIS file (can be blank: if so then intervention class file must also be blank)
2201 if (strRH.empty())
2202 {
2203 if (! m_strInterventionClassFile.empty())
2204 strErr = "line " + to_string(nLine) + ": must specify both intervention class and intervention height files";
2205
2206 break;
2207 }
2208
2209 else
2210 {
2211 if (m_strInterventionClassFile.empty())
2212 {
2213 strErr = "line " + to_string(nLine) + ": must specify both intervention class and intervention height files";
2214 break;
2215 }
2216
2217#ifdef _WIN32
2218 // For Windows, make sure has backslashes, not Unix-style slashes
2219 strRH = pstrChangeToBackslash(&strRH);
2220#endif
2221
2222 // Now check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
2223 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
2224 {
2225 // It has an absolute path, so use it 'as is'
2227 }
2228
2229 else
2230 {
2231 // It has a relative path, so prepend the CoastalME dir
2233 m_strInterventionHeightFile.append(strRH);
2234 }
2235 }
2236
2237 break;
2238
2239 // ---------------------------------------------------- Hydrology data ------------------------------------------------
2240 case 33:
2241 // Wave propagation model [0 = COVE, 1 = CShore]
2242 if (! bIsStringValidInt(strRH))
2243 {
2244 strErr = "line " + to_string(nLine) + ": invalid integer for wave propagation model '" + strRH + "' in " + m_strDataPathName;
2245 break;
2246 }
2247
2248 m_nWavePropagationModel = stoi(strRH);
2249
2251 strErr = "line " + to_string(nLine) + ": wave propagation model must be 0 or 1";
2252
2253 break;
2254
2255 case 34:
2256 // Density of sea water (kg/m3), first check that this is a valid double
2257 if (! bIsStringValidDouble(strRH))
2258 {
2259 strErr = "line " + to_string(nLine) + ": invalid floating point number for sea water density '" + strRH + "' in " + m_strDataPathName;
2260 break;
2261 }
2262
2263 m_dSeaWaterDensity = strtod(strRH.c_str(), NULL);
2264
2265 if (m_dSeaWaterDensity <= 0)
2266 strErr = "line " + to_string(nLine) + ": sea water density must be > 0";
2267
2268 break;
2269
2270 case 35:
2271 // Initial mean still water level (m), first check that this is a valid double TODO 041 Make this a per-timestep SWL file
2272 if (! bIsStringValidDouble(strRH))
2273 {
2274 strErr = "line " + to_string(nLine) + ": invalid floating point number for initial SWL '" + strRH + "' in " + m_strDataPathName;
2275 break;
2276 }
2277
2278 m_dInitialMeanSWL = strtod(strRH.c_str(), NULL);
2279 break;
2280
2281 case 36:
2282 // Final mean still water level (m) [blank = same as initial MSWL]
2283 if (strRH.empty())
2285
2286 else
2287 {
2288 // Check that this is a valid double
2289 if (! bIsStringValidDouble(strRH))
2290 {
2291 strErr = "line " + to_string(nLine) + ": invalid floating point number for final SWL '" + strRH + "' in " + m_strDataPathName;
2292 break;
2293 }
2294
2295 m_dFinalMeanSWL = strtod(strRH.c_str(), NULL);
2296 }
2297
2298 break;
2299
2300 case 37:
2301 // Deep water wave height (m) or a file of point vectors giving deep water wave height (m) and orientation (for units, see below)
2302 if (strRH.empty())
2303 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)";
2304
2305 else
2306 {
2307 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
2308 {
2309 // Just one value of wave height for all deep water cells, first check that this is a valid double
2310 if (! bIsStringValidDouble(strRH))
2311 {
2312 strErr = "line " + to_string(nLine) + ": invalid floating point number for deep water wave height '" + strRH + "' in " + m_strDataPathName;
2313 break;
2314 }
2315
2317 m_bHaveWaveStationData = false;
2318
2319 m_dAllCellsDeepWaterWaveHeight = strtod(strRH.c_str(), NULL);
2320
2322 strErr = "line " + to_string(nLine) + ": deep water wave height must be > 0";
2323 }
2324
2325 else
2326 {
2327 // 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
2329#ifdef _WIN32
2330 // For Windows, make sure has backslashes, not Unix-style slashes
2331 strRH = pstrChangeToBackslash(&strRH);
2332#endif
2333
2334 // Now check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
2335 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
2336 {
2337 // It has an absolute path, so use it 'as is'
2339 }
2340
2341 else
2342 {
2343 // It has a relative path, so prepend the CoastalME dir
2346 }
2347 }
2348 }
2349
2350 break;
2351
2352 case 38:
2353 // Deep water wave height input file. Each point in m_strDeepWaterWavesInputFile is a triad of wave height, orientation and period for each time step
2355 {
2356 if (strRH.empty())
2357 {
2358 strErr = "line " + to_string(nLine) + ": filename missing for deep water wave height input";
2359 break;
2360 }
2361
2362#ifdef _WIN32
2363 // For Windows, make sure has backslashes, not Unix-style slashes
2364 strRH = pstrChangeToBackslash(&strRH);
2365#endif
2366
2367 // Now check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
2368 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
2369 {
2370 // It has an absolute path, so use it 'as is'
2372 }
2373
2374 else
2375 {
2376 // It has a relative path, so prepend the CoastalME dir
2378 m_strDeepWaterWavesInputFile.append(strRH);
2379 }
2380 }
2381
2382 break;
2383
2384 case 39:
2385 // 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)
2387 {
2388 // 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
2389 if (! bIsStringValidDouble(strRH))
2390 {
2391 strErr = "line " + to_string(nLine) + ": invalid floating point number for deep water wave orientation '" + strRH + "' in " + m_strDataPathName;
2392 break;
2393 }
2394
2395 m_dAllCellsDeepWaterWaveAngle = strtod(strRH.c_str(), NULL);
2396
2398 strErr = "line " + to_string(nLine) + ": deep water wave orientation must be zero degrees or more";
2399
2400 else if (m_dAllCellsDeepWaterWaveAngle >= 360)
2401 strErr = "line " + to_string(nLine) + ": deep water wave orientation must be less than 360 degrees";
2402 }
2403
2404 break;
2405
2406 case 40:
2407 // Wave period (sec)
2409 {
2410 // 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
2411 if (! bIsStringValidDouble(strRH))
2412 {
2413 strErr = "line " + to_string(nLine) + ": invalid floating point number for wave period '" + strRH + "' in " + m_strDataPathName;
2414 break;
2415 }
2416
2417 m_dAllCellsDeepWaterWavePeriod = strtod(strRH.c_str(), NULL);
2418
2420 strErr = "line " + to_string(nLine) + ": wave period must be > 0";
2421 }
2422
2423 break;
2424
2425 case 41:
2426 // Tide data file (can be blank). This is the change (m) from still water level for each timestep
2427 if (!strRH.empty())
2428 {
2429#ifdef _WIN32
2430 // For Windows, make sure has backslashes, not Unix-style slashes
2431 strRH = pstrChangeToBackslash(&strRH);
2432#endif
2433
2434 // Now check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
2435 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
2436 // It has an absolute path, so use it 'as is'
2437 m_strTideDataFile = strRH;
2438
2439 else
2440 {
2441 // It has a relative path, so prepend the CoastalME dir
2443 m_strTideDataFile.append(strRH);
2444 }
2445 }
2446
2447 break;
2448
2449 case 42:
2450 // Breaking wave height-to-depth ratio, check that this is a valid double
2451 if (! bIsStringValidDouble(strRH))
2452 {
2453 strErr = "line " + to_string(nLine) + ": invalid floating point number for breaking wave height to depth ratio '" + strRH + "' in " + m_strDataPathName;
2454 break;
2455 }
2456
2457 m_dBreakingWaveHeightDepthRatio = strtod(strRH.c_str(), NULL);
2458
2460 strErr = "line " + to_string(nLine) + ": breaking wave height to depth ratio must be > 0";
2461
2462 break;
2463
2464 // ----------------------------------------------------- Sediment data ------------------------------------------------
2465 case 43:
2466 // Simulate coast platform erosion?
2467 strRH = strToLower(&strRH);
2468
2469 if (strRH.find('y') != string::npos)
2471
2472 break;
2473
2474 case 44:
2475 // If simulating coast platform erosion, R (coast platform resistance to erosion) values along profile, see Walkden & Hall, 2011
2477 {
2478 // First check that this is a valid double
2479 if (! bIsStringValidDouble(strRH))
2480 {
2481 strErr = "line " + to_string(nLine) + ": invalid floating point number for R (coast platform resistance to erosion) '" + strRH + "' in " + m_strDataPathName;
2482 break;
2483 }
2484
2485 m_dR = strtod(strRH.c_str(), NULL);
2486
2487 if (m_dR <= 0)
2488 strErr = "line " + to_string(nLine) + ": R (coast platform resistance to erosion) value must be > 0";
2489 }
2490
2491 break;
2492
2493 case 45:
2494 // Simulate beach sediment transport?
2495 strRH = strToLower(&strRH);
2496
2498
2499 if (strRH.find('y') != string::npos)
2501
2502 break;
2503
2504 case 46:
2505 // If simulating beach sediment transport, beach sediment transport at grid edges [0 = closed, 1 = open, 2 = re-circulate]
2507 {
2508 if (! bIsStringValidInt(strRH))
2509 {
2510 strErr = "line " + to_string(nLine) + ": invalid integer for beach sediment transport at grid edges '" + strRH + "' in " + m_strDataPathName;
2511 break;
2512 }
2513
2515
2517 strErr = "line " + to_string(nLine) + ": switch for handling of beach sediment at grid edges must be 0, 1, or 2";
2518 }
2519
2520 break;
2521
2522 case 47:
2523 // If simulating beach sediment transport, beach erosion/deposition equation [0 = CERC, 1 = Kamphuis]
2525 {
2526 if (! bIsStringValidInt(strRH))
2527 {
2528 strErr = "line " + to_string(nLine) + ": invalid integer for beach erosion/deposition equation '" + strRH + "' in " + m_strDataPathName;
2529 break;
2530 }
2531
2533
2535 strErr = "line " + to_string(nLine) + ": switch for beach erosion/deposition equation must be 0 or 1";
2536 }
2537
2538 break;
2539
2540 case 48:
2541 // Median size of fine sediment (mm), always needed [0 = default, only for Kamphuis eqn]. First check that this is a valid double
2542 if (! bIsStringValidDouble(strRH))
2543 {
2544 strErr = "line " + to_string(nLine) + ": invalid floating point number for median particle size of fine sediment '" + strRH + "' in " + m_strDataPathName;
2545 break;
2546 }
2547
2548 m_dD50Fine = strtod(strRH.c_str(), NULL);
2549
2550 if (m_dD50Fine < 0)
2551 strErr = "line " + to_string(nLine) + ": median particle size of fine sediment must be > 0";
2552
2553 else if (bFPIsEqual(m_dD50Fine, 0.0, TOLERANCE))
2554 // Use default value
2556
2557 break;
2558
2559 case 49:
2560 // Median size of sand sediment (mm), always needed [0 = default, only for Kamphuis eqn]. First check that this is a valid double
2561 if (! bIsStringValidDouble(strRH))
2562 {
2563 strErr = "line " + to_string(nLine) + ": invalid floating point number for median particle size of sand sediment '" + strRH + "' in " + m_strDataPathName;
2564 break;
2565 }
2566
2567 m_dD50Sand = strtod(strRH.c_str(), NULL);
2568
2569 if (m_dD50Sand < 0)
2570 strErr = "line " + to_string(nLine) + ": median particle size of sand sediment must be > 0";
2571
2572 else if (bFPIsEqual(m_dD50Sand, 0.0, TOLERANCE))
2573 // Use default value
2575
2576 break;
2577
2578 case 50:
2579 // Median size of coarse sediment (mm), always needed [0 = default, only for Kamphuis eqn]. First check that this is a valid double
2580 if (! bIsStringValidDouble(strRH))
2581 {
2582 strErr = "line " + to_string(nLine) + ": invalid floating point number for median particle size of coarse sediment '" + strRH + "' in " + m_strDataPathName;
2583 break;
2584 }
2585
2586 m_dD50Coarse = strtod(strRH.c_str(), NULL);
2587
2588 if (m_dD50Coarse < 0)
2589 strErr = "line " + to_string(nLine) + ": median particle size of coarse sediment must be > 0";
2590
2591 else if (bFPIsEqual(m_dD50Coarse, 0.0, TOLERANCE))
2592 // Use default value
2594
2595 break;
2596
2597 case 51:
2598 // Density of unconsolidated beach sediment (kg/m3)
2600 {
2601 // First check that this is a valid double
2602 if (! bIsStringValidDouble(strRH))
2603 {
2604 strErr = "line " + to_string(nLine) + ": invalid floating point number for density of beach sediment '" + strRH + "' in " + m_strDataPathName;
2605 break;
2606 }
2607
2608 m_dBeachSedimentDensity = strtod(strRH.c_str(), NULL);
2609
2610 if (m_dBeachSedimentDensity <= 0)
2611 strErr = "line " + to_string(nLine) + ": density of beach sediment must be > 0";
2612 }
2613
2614 break;
2615
2616 case 52:
2617 // Beach sediment porosity
2619 {
2620 // First check that this is a valid double
2621 if (! bIsStringValidDouble(strRH))
2622 {
2623 strErr = "line " + to_string(nLine) + ": invalid floating point number for porosity of beach sediment '" + strRH + "' in " + m_strDataPathName;
2624 break;
2625 }
2626
2627 m_dBeachSedimentPorosity = strtod(strRH.c_str(), NULL);
2628
2629 if (m_dBeachSedimentPorosity <= 0)
2630 strErr = "line " + to_string(nLine) + ": porosity of beach sediment must be > 0";
2631 }
2632
2633 break;
2634
2635 case 53:
2636 // Relative erodibility (0 - 1) of fine-sized sediment, always needed. First check that this is a valid double
2637 if (! bIsStringValidDouble(strRH))
2638 {
2639 strErr = "line " + to_string(nLine) + ": invalid floating point number for erodibility of fine-sized sediment '" + strRH + "' in " + m_strDataPathName;
2640 break;
2641 }
2642
2643 m_dFineErodibility = strtod(strRH.c_str(), NULL);
2644
2645 if ((m_dFineErodibility < 0) || (m_dFineErodibility > 1))
2646 strErr = "line " + to_string(nLine) + ": relative erodibility of fine-sized sediment must be between 0 and 1";
2647
2648 break;
2649
2650 case 54:
2651 // Relative erodibility (0 - 1) of sand-sized sediment, always needed. First check that this is a valid double
2652 if (! bIsStringValidDouble(strRH))
2653 {
2654 strErr = "line " + to_string(nLine) + ": invalid floating point number for erodibility of sand-sized sediment '" + strRH + "' in " + m_strDataPathName;
2655 break;
2656 }
2657
2658 m_dSandErodibility = strtod(strRH.c_str(), NULL);
2659
2660 if ((m_dSandErodibility < 0) || (m_dSandErodibility > 1))
2661 strErr = "line " + to_string(nLine) + ": relative erodibility of sand-sized sediment must be between 0 and 1";
2662
2663 break;
2664
2665 case 55:
2666 // Relative erodibility (0 - 1) of coarse-sized sediment, always needed. First check that this is a valid double
2667 if (! bIsStringValidDouble(strRH))
2668 {
2669 strErr = "line " + to_string(nLine) + ": invalid floating point number for erodibility of coarse-sized sediment '" + strRH + "' in " + m_strDataPathName;
2670 break;
2671 }
2672
2673 m_dCoarseErodibility = strtod(strRH.c_str(), NULL);
2674
2675 if ((m_dCoarseErodibility < 0) || (m_dCoarseErodibility > 1))
2676 {
2677 strErr = "line " + to_string(nLine) + ": relative erodibility of coarse-sized sediment must be between 0 and 1";
2678 break;
2679 }
2680
2682 strErr = "line " + to_string(nLine) + ": must have at least one non-zero erodibility value";
2683
2684 break;
2685
2686 case 56:
2687 // Transport parameter KLS in CERC equation
2689 {
2690 // First check that this is a valid double
2691 if (! bIsStringValidDouble(strRH))
2692 {
2693 strErr = "line " + to_string(nLine) + ": invalid floating point number for transport parameter KLS of CERC equation '" + strRH + "' in " + m_strDataPathName;
2694 break;
2695 }
2696
2697 m_dKLS = strtod(strRH.c_str(), NULL);
2698
2699 // 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
2700 // TODO 042 Should this be a user input, or not? The comment above seems inconclusive
2701 // m_dKLS = tMin(m_dKLS, 0.39);
2702
2703 if (m_dKLS <= 0)
2704 strErr = "line " + to_string(nLine) + ": transport parameter KLS of CERC equation must be > 0";
2705 }
2706
2707 break;
2708
2709 case 57:
2710 // Transport parameter for Kamphuis equation
2712 {
2713 // First check that this is a valid double
2714 if (! bIsStringValidDouble(strRH))
2715 {
2716 strErr = "line " + to_string(nLine) + ": invalid floating point number for transport parameter of Kamphuis equation '" + strRH + "' in " + m_strDataPathName;
2717 break;
2718 }
2719
2720 m_dKamphuis = strtod(strRH.c_str(), NULL);
2721
2722 if (m_dKamphuis <= 0)
2723 strErr = "line " + to_string(nLine) + ": transport parameter of Kamphuis equation must be > 0";
2724 }
2725
2726 break;
2727
2728 case 58:
2729 // Berm height i.e. height above SWL of start of depositional Dean profile
2731 {
2732 // First check that this is a valid double
2733 if (! bIsStringValidDouble(strRH))
2734 {
2735 strErr = "line " + to_string(nLine) + ": invalid floating point number for Dean profile start height above SWL '" + strRH + "' in " + m_strDataPathName;
2736 break;
2737 }
2738
2739 m_dDeanProfileStartAboveSWL = strtod(strRH.c_str(), NULL);
2740
2742 strErr = "line " + to_string(nLine) + ": Berm height (Dean profile start height above SWL) must be >= 0";
2743 }
2744
2745 break;
2746
2747 // ------------------------------------------------ Cliff collapse data -----------------------------------------------
2748 case 59:
2749 // Simulate cliff collapse?
2751 {
2752 // Only consider cliff collapse if we have some consolidated sedimemt
2753 strRH = strToLower(&strRH);
2754
2755 if (strRH.find('y') != string::npos)
2756 m_bDoCliffCollapse = true;
2757 }
2758
2759 break;
2760
2761 case 60:
2762 // Cliff resistance to erosion
2764 {
2765 // First check that this is a valid double
2766 if (! bIsStringValidDouble(strRH))
2767 {
2768 strErr = "line " + to_string(nLine) + ": invalid floating point number for cliff resistance to erosion '" + strRH + "' in " + m_strDataPathName;
2769 break;
2770 }
2771
2772 m_dCliffErosionResistance = strtod(strRH.c_str(), NULL);
2773
2775 strErr = "line " + to_string(nLine) + ": cliff resistance to erosion must be > 0";
2776 }
2777
2778 break;
2779
2780 case 61:
2781 // Notch overhang at collapse (m)
2783 {
2784 // First check that this is a valid double
2785 if (! bIsStringValidDouble(strRH))
2786 {
2787 strErr = "line " + to_string(nLine) + ": invalid floating point number for cliff notch overhang at collapse '" + strRH + "' in " + m_strDataPathName;
2788 break;
2789 }
2790
2791 m_dNotchDepthAtCollapse = strtod(strRH.c_str(), NULL);
2792
2793 if (m_dNotchDepthAtCollapse <= 0)
2794 strErr = "line " + to_string(nLine) + ": cliff notch overhang at collapse must be > 0";
2795 }
2796
2797 break;
2798
2799 case 62:
2800 // Notch base below still water level (m)
2802 {
2803 m_dNotchBaseBelowSWL = strtod(strRH.c_str(), NULL);
2804
2805 if (m_dNotchBaseBelowSWL < 0)
2806 strErr = "line " + to_string(nLine) + ": cliff notch base below still water level must be > 0";
2807 }
2808
2809 break;
2810
2811 case 63:
2812 // Scale parameter A for cliff deposition (m^(1/3)) [0 = auto]
2814 {
2815 // First check that this is a valid double
2816 if (! bIsStringValidDouble(strRH))
2817 {
2818 strErr = "line " + to_string(nLine) + ": invalid floating point number for scale parameter A for cliff deposition '" + strRH + "' in " + m_strDataPathName;
2819 break;
2820 }
2821
2822 m_dCliffDepositionA = strtod(strRH.c_str(), NULL);
2823
2824 if (m_dCliffDepositionA < 0)
2825 strErr = "line " + to_string(nLine) + ": scale parameter A for cliff deposition must be 0 [= auto] or greater";
2826 }
2827
2828 break;
2829
2830 case 64:
2831 // Approximate planview width of cliff collapse talus (in m)
2833 {
2834 // First check that this is a valid double
2835 if (! bIsStringValidDouble(strRH))
2836 {
2837 strErr = "line " + to_string(nLine) + ": invalid floating point number for width of cliff collapse talus '" + strRH + "' in " + m_strDataPathName;
2838 break;
2839 }
2840
2841 m_dCliffDepositionPlanviewWidth = strtod(strRH.c_str(), NULL);
2842
2844 strErr = "line " + to_string(nLine) + ": planview width of cliff deposition must be > 0";
2845 }
2846
2847 break;
2848
2849 case 65:
2850 // Planview length of cliff deposition talus (m)
2852 {
2853 // First check that this is a valid double
2854 if (! bIsStringValidDouble(strRH))
2855 {
2856 strErr = "line " + to_string(nLine) + ": invalid floating point number for planview length of cliff deposition '" + strRH + "' in " + m_strDataPathName;
2857 break;
2858 }
2859
2860 m_dCliffTalusMinDepositionLength = strtod(strRH.c_str(), NULL);
2861
2863 strErr = "line " + to_string(nLine) + ": planview length of cliff deposition must be > 0";
2864 }
2865
2866 break;
2867
2868 case 66:
2869 // Minimum height of landward end of talus, as a fraction of cliff elevation
2871 {
2872 // First check that this is a valid double
2873 if (! bIsStringValidDouble(strRH))
2874 {
2875 strErr = "line " + to_string(nLine) + ": invalid floating point number for height of cliff collapse (as a fraction of cliff elevation) '" + strRH + "' in " + m_strDataPathName;
2876 break;
2877 }
2878
2879 m_dMinCliffTalusHeightFrac = strtod(strRH.c_str(), NULL);
2880
2882 strErr = "line " + to_string(nLine) + ": minimum height of cliff collapse (as a fraction of cliff elevation) must be >= 0";
2883 }
2884
2885 break;
2886
2887 // -------------------------------------------------- Input events data -----------------------------------------------
2888 case 67:
2889 // Simulate riverine flooding?
2890 strRH = strToLower(&strRH);
2891
2892 if (strRH.find('y') != string::npos)
2893 {
2894 m_bRiverineFlooding = true;
2898 }
2899
2900 break;
2901
2902 case 68:
2903 // Output riverine flooding vector files
2905 {
2906 if (!strRH.empty())
2907 {
2908 // Convert to lower case
2909 strRH = strToLower(&strRH);
2910
2911 // First look for "all"
2912 if (strRH.find(VECTOR_ALL_RIVER_FLOOD_OUTPUT_CODE) != string::npos)
2913 {
2917 }
2918
2919 else
2920 {
2921 // 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
2922 if (strRH.find(VECTOR_FLOOD_SWL_SETUP_LINE_CODE) != string::npos)
2923 {
2924 m_bFloodSWLSetupLine = true;
2926 }
2927
2928 if (strRH.find(VECTOR_FLOOD_SWL_SETUP_SURGE_LINE_CODE) != string::npos)
2929 {
2932 }
2933
2934 if (strRH.find(VECTOR_FLOOD_SWL_SETUP_SURGE_RUNUP_LINE_CODE) != string::npos)
2935 {
2938 }
2939
2940 // Check to see if all codes have been removed
2941 if (!strRH.empty())
2942 strErr = "line " + to_string(nLine) + ": unknown code '" + strRH + "' in list of riverine flooding output codes";
2943 }
2944 }
2945
2946 else
2947 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";
2948 }
2949
2950 break;
2951
2952 case 69:
2954 {
2955 // Run-up equation?
2956 if (bIsStringValidInt(strRH))
2957 {
2958 m_nRunUpEquation = stoi(strRH);
2959 }
2960
2961 else
2962 strErr = "line " + to_string(nLine) + ": invalid code for run-up equation used in simulating floods";
2963 }
2964
2965 break;
2966
2967 case 70:
2969 {
2970 // Characteristic locations for flood?
2971 strRH = strToLower(&strRH);
2972
2973 m_bFloodLocation = false;
2974
2975 if (strRH.find('y') != string::npos)
2976 {
2977 m_bFloodLocation = true;
2978 }
2979 }
2980
2981 break;
2982
2983 case 71:
2985 {
2986 // Path of location points file
2987 if (!strRH.empty())
2988 {
2989#ifdef _WIN32
2990 // For Windows, make sure has backslashes, not Unix-style slashes
2991 strRH = pstrChangeToBackslash(&strRH);
2992#endif
2993
2994 // Now check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
2995 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
2996 // It has an absolute path, so use it 'as is'
2998
2999 else
3000 {
3001 // It has a relative path, so prepend the CoastalME dir
3003 m_strFloodLocationShapefile.append(strRH);
3004 }
3005
3006 // Set the switch
3007 m_bFloodLocation = true;
3008 }
3009
3010 else
3011 strErr = "line " + to_string(nLine) + ": path of location points file must not be empty if simulating floods";
3012 }
3013
3014 break;
3015
3016 case 72:
3017 // Simulate sediment input?
3018 strRH = strToLower(&strRH);
3019
3020 if (strRH.find('y') != string::npos)
3021 {
3022 m_bSedimentInput = true;
3024 }
3025
3026 break;
3027
3028 case 73:
3029 // Sediment input location (point or line shapefile)
3030 if (m_bSedimentInput)
3031 {
3032 if (!strRH.empty())
3033 {
3034#ifdef _WIN32
3035 // For Windows, make sure has backslashes, not Unix-style slashes
3036 strRH = pstrChangeToBackslash(&strRH);
3037#endif
3038
3039 // Now check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
3040 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
3041 // It has an absolute path, so use it 'as is'
3043
3044 else
3045 {
3046 // It has a relative path, so prepend the CoastalME dir
3049 }
3050 }
3051 }
3052
3053 break;
3054
3055 case 74:
3056 // Sediment input type: required if have shapefile [P = Point, C = coast block, L = line]
3057 if (m_bSedimentInput)
3058 {
3059 strRH = strToLower(&strRH);
3060
3061 if (strRH.find('p') != string::npos)
3063
3064 else if (strRH.find('c') != string::npos)
3066
3067 else if (strRH.find('l') != string::npos)
3069
3070 else
3071 strErr = "line " + to_string(nLine) + ": Sediment input type must be P, C, or L";
3072 }
3073
3074 break;
3075
3076 case 75:
3077 // Sediment input details file (required if have shapefile)
3078 if (m_bSedimentInput)
3079 {
3080 if (strRH.empty())
3081 {
3082 strErr = "line " + to_string(nLine) + ": filename missing for sediment input";
3083 break;
3084 }
3085
3086#ifdef _WIN32
3087 // For Windows, make sure has backslashes, not Unix-style slashes
3088 strRH = pstrChangeToBackslash(&strRH);
3089#endif
3090
3091 // Now check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
3092 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
3093 {
3094 // It has an absolute path, so use it 'as is'
3096 }
3097
3098 else
3099 {
3100 // It has a relative path, so prepend the CoastalME dir
3102 m_strSedimentInputEventFile.append(strRH);
3103 }
3104 }
3105
3106 break;
3107
3108 // ------------------------------------------------------ Other data --------------------------------------------------
3109 case 76:
3110 // Gravitational acceleration (m2/s). First check that this is a valid double
3111 if (! bIsStringValidDouble(strRH))
3112 {
3113 strErr = "line " + to_string(nLine) + ": invalid floating point number for gravitational acceleration '" + strRH + "' in " + m_strDataPathName;
3114 break;
3115 }
3116
3117 m_dG = strtod(strRH.c_str(), NULL);
3118
3119 if (m_dG <= 0)
3120 strErr = "line " + to_string(nLine) + ": gravitational acceleration must be > 0";
3121
3122 break;
3123
3124 case 77:
3125 // Spacing of coastline normals (m)
3126 m_dCoastNormalSpacing = strtod(strRH.c_str(), NULL);
3127
3129 m_nCoastNormalSpacing = DEFAULT_PROFILE_SPACING; // In cells, we will set m_dCoastNormalSpacing later when we know m_dCellSide
3130
3131 else if (m_dCoastNormalSpacing < 0)
3132 strErr = "line " + to_string(nLine) + ": spacing of coastline normals must be > 0";
3133
3134 break;
3135
3136 case 78:
3137 // Random factor for spacing of normals [0 to 1, 0 = deterministic], check that this is a valid double
3138 if (! bIsStringValidDouble(strRH))
3139 {
3140 strErr = "line " + to_string(nLine) + ": invalid floating point number for random factor for spacing of coastline normals '" + strRH + "' in " + m_strDataPathName;
3141 break;
3142 }
3143
3144 m_dCoastNormalRandSpacingFactor = strtod(strRH.c_str(), NULL);
3145
3147 strErr = "line " + to_string(nLine) + ": random factor for spacing of coastline normals must be >= 0";
3148
3150 strErr = "line " + to_string(nLine) + ": random factor for spacing of coastline normals must be < 1";
3151
3152 break;
3153
3154 case 79:
3155 // Length of coastline normals (m), check that this is a valid double
3156 if (! bIsStringValidDouble(strRH))
3157 {
3158 strErr = "line " + to_string(nLine) + ": invalid floating point number for length of coastline normals '" + strRH + "' in " + m_strDataPathName;
3159 break;
3160 }
3161
3162 m_dCoastNormalLength = strtod(strRH.c_str(), NULL);
3163
3164 if (m_dCoastNormalLength <= 0)
3165 strErr = "line " + to_string(nLine) + ": length of coastline normals must be > 0";
3166
3167 break;
3168
3169 case 80:
3170 // Start depth for wave calcs (ratio to deep water wave height), check that this is a valid double
3171 if (! bIsStringValidDouble(strRH))
3172 {
3173 strErr = "line " + to_string(nLine) + ": invalid floating point number for start depth for wave calcs '" + strRH + "' in " + m_strDataPathName;
3174 break;
3175 }
3176
3177 m_dWaveDepthRatioForWaveCalcs = strtod(strRH.c_str(), NULL);
3178
3180 strErr = "line " + to_string(nLine) + ": start depth for wave calcs must be > 0";
3181
3182 break;
3183
3184 // ----------------------------------------------------- Testing only -------------------------------------------------
3185 case 81:
3186 // Output profile data?
3187 strRH = strToLower(&strRH);
3188
3189 m_bOutputProfileData = false;
3190
3191 if (strRH.find('y') != string::npos)
3192 {
3193 m_bOutputProfileData = true;
3194
3196 {
3197 strErr = "line " + to_string(nLine) + ": cannot save profiile data if not simulating shore platform erosion";
3198 break;
3199 }
3200
3201 // TODO 043 What about randomness of profile spacing, since profile location is determined by curvature?
3202 }
3203
3204 break;
3205
3206 case 82:
3207 // Numbers of profiles to be saved
3209 {
3210 VstrTmp = VstrSplit(&strRH, SPACE);
3211
3212 for (unsigned int j = 0; j < VstrTmp.size(); j++)
3213 {
3214 VstrTmp[j] = strTrim(&VstrTmp[j]);
3215
3216 if (! bIsStringValidInt(VstrTmp[j]))
3217 {
3218 strErr = "line " + to_string(nLine) + ": invalid integer for profile to be saved '" + VstrTmp[j] + "' in " + m_strDataPathName;
3219 break;
3220 }
3221
3222 int const nTmp = stoi(VstrTmp[j]);
3223
3224 if (nTmp < 0)
3225 {
3226 strErr = "line " + to_string(nLine) + ": Profile number for saving must be >= 0";
3227 break;
3228 }
3229
3230 m_VnProfileToSave.push_back(nTmp);
3231 }
3232 }
3233
3234 break;
3235
3236 case 83:
3237 // Timesteps to save profiles
3239 {
3240 VstrTmp = VstrSplit(&strRH, SPACE);
3241
3242 for (unsigned int j = 0; j < VstrTmp.size(); j++)
3243 {
3244 VstrTmp[j] = strTrim(&VstrTmp[j]);
3245 unsigned long const ulTmp = atol(VstrTmp[j].c_str());
3246
3247 if (ulTmp < 1)
3248 {
3249 strErr = "line " + to_string(nLine) + ": Timestep for profile saves must >= 1";
3250 break;
3251 }
3252
3253 m_VulProfileTimestep.push_back(ulTmp);
3254 }
3255 }
3256
3257 break;
3258
3259 case 84:
3260 // Output parallel profile data?
3261 strRH = strToLower(&strRH);
3262
3264
3265 if (strRH.find('y') != string::npos)
3267
3268 break;
3269
3270 case 85:
3271 // Output erosion potential look-up data?
3272 strRH = strToLower(&strRH);
3273
3275
3276 if (strRH.find('y') != string::npos)
3278
3279 break;
3280
3281 case 86:
3282 // Size of moving window for coastline curvature calculation (must be odd)
3283 if (! bIsStringValidInt(strRH))
3284 {
3285 strErr = "line ";
3286 strErr += to_string(nLine);
3287 strErr += ": invalid integer for size of moving window for coastline curvature calculation '";
3288 strErr += strRH;
3289 strErr += "' in ";
3290 strErr += m_strDataPathName;
3291
3292 break;
3293 }
3294
3296
3298 {
3299 strErr = "line ";
3300 strErr += to_string(nLine);
3301 strErr += ": size of moving window for coastline curvature calculation (must be > 0 and odd)";
3302 }
3303
3304 break;
3305
3306 case 87:
3307 // Cliff edge smoothing algorithm: 0 = none, 1 = running mean, 2 = Savitzky-Golay
3308 if (! bIsStringValidInt(strRH))
3309 {
3310 strErr = "line ";
3311 strErr += to_string(nLine);
3312 strErr += ": invalid integer for cliff edge smoothing algorithm '";
3313 strErr += strRH;
3314 strErr += "' in " + m_strDataPathName;
3315
3316 break;
3317 }
3318
3319 m_nCliffEdgeSmooth = stoi(strRH);
3320
3323 strErr = "line " + to_string(nLine) +
3324 ": cliff edge smoothing algorithm";
3325
3326 break;
3327
3328 case 88:
3329 // Size of cliff edge smoothing window: must be odd
3330 if (! bIsStringValidInt(strRH))
3331 {
3332 strErr = "line " + to_string(nLine) +
3333 ": invalid integer for cliff edge smoothing window '" +
3334 strRH + "' in " + m_strDataPathName;
3335 break;
3336 }
3337
3338 m_nCliffEdgeSmoothWindow = stoi(strRH);
3339
3341 strErr = "line " + to_string(nLine) +
3342 ": size of cliff edge smoothing window (must be > 0 and odd)";
3343
3344 break;
3345
3346 case 89:
3347 // Order of cliff edge smoothing polynomial for Savitzky-Golay: usually 2 or 4, max is 6
3348 if (! bIsStringValidInt(strRH))
3349 {
3350 strErr = "line " + to_string(nLine) +
3351 ": invalid integer for Savitzky-Golay polynomial for cliff edge smoothing '" +
3352 strRH + "' in " + m_strDataPathName;
3353 break;
3354 }
3355
3356 m_nSavGolCliffEdgePoly = stoi(strRH);
3357
3360 strErr = "line " + to_string(nLine) + ": order of Savitzky-Golay polynomial for cliff edge smoothing (must be 2, 4 or 6)";
3361
3362 break;
3363
3364 case 90:
3365 // Cliff slope limit for cliff toe detection
3366 if (! bIsStringValidDouble(strRH))
3367 {
3368 strErr = "line " + to_string(nLine) + ": invalid number for cliff slope limit '" + strRH + "' in " + m_strDataPathName;
3369 break;
3370 }
3371
3372 m_dCliffSlopeLimit = stod(strRH);
3373
3374 if (m_dCliffSlopeLimit <= 0)
3375 strErr = "line " + to_string(nLine) +
3376 ": cliff slope limit must be > 0";
3377
3378 break;
3379 }
3380
3381 // Did an error occur?
3382 if (! strErr.empty())
3383 {
3384 // Error in input to run details file
3385 cerr << endl << ERR << strErr << ".\nPlease edit " << m_strDataPathName << " and change this line:" << endl;
3386 cerr << "'" << strRec << "'" << endl << endl;
3387 InStream.close();
3388 return false;
3389 }
3390 }
3391 }
3392
3393 // Close file
3394 InStream.close();
3395
3396 // 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)
3397 bool bNoRasterFiles = true;
3398
3399 if ((! m_strInitialBasementDEMFile.empty()) || (! m_strInitialSuspSedimentFile.empty()) || (! m_strInitialLandformFile.empty()) || (! m_strInterventionHeightFile.empty()))
3400 bNoRasterFiles = false;
3401
3402 for (int j = 0; j < m_nLayers; j++)
3403 {
3405 bNoRasterFiles = false;
3406 }
3407
3408 if (bNoRasterFiles)
3409 {
3410 // No raster files
3411 cerr << ERR << "at least one raster GIS file is needed" << endl;
3412 return false;
3413 }
3414
3415 return true;
3416 } // End of else block for .dat file parsing
3417}
3418
3419//===============================================================================================================================
3421//===============================================================================================================================
3423{
3424 // Create an ifstream object
3425 ifstream InStream;
3426
3427 // Try to open the file for input
3428 InStream.open(m_strTideDataFile.c_str(), ios::in);
3429
3430 // Did it open OK?
3431 if (! InStream.is_open())
3432 {
3433 // Error: cannot open tide data file for input
3434 cerr << ERR << "cannot open " << m_strTideDataFile << " for input" << endl;
3435 return RTN_ERR_TIDEDATAFILE;
3436 }
3437
3438 // Opened OK
3439 int nLine = 0;
3440 string strRec;
3441
3442 // Now read the data from the file
3443 while (getline(InStream, strRec))
3444 {
3445 nLine++;
3446
3447 // Trim off leading and trailing whitespace
3448 strRec = strTrim(&strRec);
3449
3450 // If it is a blank line or a comment then ignore it
3451 if ((strRec.empty()) || (strRec[0] == QUOTE1) || (strRec[0] == QUOTE2))
3452 continue;
3453
3454 // Check that this is a valid double
3455 if (! bIsStringValidDouble(strRec))
3456 {
3457 cerr << ERR << "invalid floating point number for tide data '" << strRec << "' on line " << nLine << " of " << m_strTideDataFile << endl;
3458 return RTN_ERR_TIDEDATAFILE;
3459 }
3460
3461 // Convert to double then append the value to the vector
3462 m_VdTideData.push_back(strtod(strRec.c_str(), NULL));
3463 }
3464
3465 // Close file
3466 InStream.close();
3467
3468 return RTN_OK;
3469}
3470
3471//===============================================================================================================================
3473//===============================================================================================================================
3475{
3476 // Sort out the path and filename
3480
3481 // Create an ifstream object
3482 ifstream InStream;
3483
3484 // Try to open the file for input
3485 InStream.open(m_strSCAPEShapeFunctionFile.c_str(), ios::in);
3486
3487 // Did it open OK?
3488 if (! InStream.is_open())
3489 {
3490 // Error: cannot open shape function file for input
3491 cerr << ERR << "cannot open " << m_strSCAPEShapeFunctionFile << " for input" << endl;
3493 }
3494
3495 // Opened OK
3496 int nLine = 0;
3497 int nExpected = 0, nRead = 0;
3498 string strRec;
3499
3500 // Read in the number of data lines expected
3501 InStream >> nExpected;
3502
3503 // Set up the vectors to hold the input data
3504 vector<double> VdDepthOverDB;
3505 vector<double> VdErosionPotential;
3506 vector<double> VdErosionPotentialFirstDeriv;
3507
3508 // Now read the rest of the data from the file to get the Erosion Potential Shape function
3509 while (getline(InStream, strRec))
3510 {
3511 nLine++;
3512
3513 // Trim off leading and trailing whitespace
3514 strRec = strTrim(&strRec);
3515
3516 // If it is a blank line or a comment then ignore it
3517 if ((strRec.empty()) || (strRec[0] == QUOTE1) || (strRec[0] == QUOTE2))
3518 continue;
3519
3520 // It isn't so increment counter
3521 nRead++;
3522
3523 // Split the string, and remove whitespace
3524 vector<string> strTmp = VstrSplit(&strRec, SPACE);
3525
3526 for (unsigned int i = 0; i < strTmp.size(); i++)
3527 {
3528 // Remove leading and trailing whitespace
3529 strTmp[i] = strTrim(&strTmp[i]);
3530
3531 // Check that this is a valid double
3532 if (! bIsStringValidDouble(strTmp[i]))
3533 {
3534 cerr << ERR << "on line " + to_string(nLine) + " invalid floating point number for Erosion Potential Shape data '" << strTmp[i] << "' in " << m_strSCAPEShapeFunctionFile << endl;
3536 }
3537 }
3538
3539 // Convert to doubles then append the values to the vectors
3540 VdDepthOverDB.push_back(strtod(strTmp[0].c_str(), NULL));
3541 VdErosionPotential.push_back(strtod(strTmp[1].c_str(), NULL));
3542 VdErosionPotentialFirstDeriv.push_back(strtod(strTmp[2].c_str(), NULL));
3543 }
3544
3545 // Now create the look up table values
3546 m_VdErosionPotential = VdErosionPotential;
3547 m_VdDepthOverDB = VdDepthOverDB;
3548 m_dDepthOverDBMax = VdDepthOverDB[14];
3549
3550 // Close file
3551 InStream.close();
3552
3553 // Did we read in what we expected?
3554 if (nExpected != nRead)
3555 {
3556 cout << ERR << "read in " << nRead << " lines from " << m_strSCAPEShapeFunctionFile << " but " << nExpected << " lines expected" << endl;
3558 }
3559
3560 // Is the shape funcion well defined? i.e. it must be -ve or 0.0 for all values
3561 for (unsigned int j = 0; j < m_VdErosionPotential.size(); j++)
3562 {
3563 if (m_VdErosionPotential[j] > 0)
3564 {
3565 cout << ERR << " in " << m_strSCAPEShapeFunctionFile << ", erosion potential function cannot be positive" << endl;
3567 }
3568 }
3569
3570 // OK, now use this data to create a look-up table to be used for the rest of the simulation
3571 if (! bCreateErosionPotentialLookUp(&VdDepthOverDB, &VdErosionPotential, &VdErosionPotentialFirstDeriv))
3572 {
3573 cout << ERR << "line " + to_string(nLine) + " in " << m_strSCAPEShapeFunctionFile << ": erosion potential function is unbounded for high values of depth over DB" << endl;
3575 }
3576
3577 return RTN_OK;
3578}
3579
3580//===============================================================================================================================
3582//===============================================================================================================================
3583int CSimulation::nReadWaveStationInputFile(int const nWaveStations)
3584{
3585 // Create an ifstream object
3586 ifstream InStream;
3587
3588 // Try to open the file for input
3589 InStream.open(m_strDeepWaterWavesInputFile.c_str(), ios::in);
3590
3591 // Did it open OK?
3592 if (!InStream.is_open())
3593 {
3594 // Error: cannot open time series file for input
3595 cerr << ERR << "cannot open " << m_strDeepWaterWavesInputFile << " for input" << endl;
3597 }
3598
3599 // Opened OK
3600 int nLine = 0;
3601 int nExpectedStations = 0;
3602 int nRead = 0;
3603 int nTimeStepsRead = 0;
3604 string strRec, strErr;
3605
3606 // Read each line, ignoring blank lines and comment lines
3607 while (getline(InStream, strRec))
3608 {
3609 nLine++;
3610
3611 // Trim off leading and trailing whitespace
3612 strRec = strTrim(&strRec);
3613
3614 // If it is a blank line or a comment then ignore it
3615 if ((!strRec.empty()) && (strRec[0] != QUOTE1) && (strRec[0] != QUOTE2))
3616 {
3617 // It isn't so increment counter
3618 nRead++;
3619
3620 // The header lines (the first four lines of the file) contains leading description separated by a colon from the data
3621 if (nRead < 5)
3622 {
3623 // Find the colon: note that lines MUST have a colon separating data from leading description portion
3624 size_t nPos = strRec.find(COLON);
3625
3626 if (nPos == string::npos)
3627 {
3628 // Error: badly formatted (no colon)
3629 cerr << ERR << "on line " << to_string(nLine) << "badly formatted (no ':') in " << m_strDeepWaterWavesInputFile << endl
3630 << "'" << strRec << "'" << endl;
3632 }
3633
3634 if (nPos == strRec.size() - 1)
3635 {
3636 // Error: badly formatted (colon with nothing following)
3637 cerr << ERR << "on line " << to_string(nLine) << "badly formatted (nothing following ':') in " << m_strDeepWaterWavesInputFile << endl
3638 << "'" << strRec << "'" << endl;
3640 }
3641
3642 // Strip off leading portion (the bit up to and including the colon)
3643 string strRH = strRec.substr(nPos + 1);
3644
3645 // Remove leading whitespace
3646 strRH = strTrimLeft(&strRH);
3647
3648 // Look for a trailing comment, if found then terminate string at that point and trim off any trailing whitespace
3649 nPos = strRH.rfind(QUOTE1);
3650
3651 if (nPos != string::npos)
3652 strRH.resize(nPos);
3653
3654 nPos = strRH.rfind(QUOTE2);
3655
3656 if (nPos != string::npos)
3657 strRH.resize(nPos);
3658
3659 // Remove trailing whitespace
3660 strRH = strTrimRight(&strRH);
3661
3662 int nSec = 0;
3663 int nMin = 0;
3664 int nHour = 0;
3665 int nDay = 0;
3666 int nMonth = 0;
3667 int nYear = 0;
3668 double dMult;
3669 double dThisIter;
3670 vector<string> VstrTmp;
3671
3672 switch (nRead)
3673 {
3674 case 1:
3675 // Get the start date/time for this data, format is [hh-mm-ss dd/mm/yyyy]
3676 VstrTmp = VstrSplit(&strRH, SPACE);
3677
3678 // Both date and time here?
3679 if (VstrTmp.size() < 2)
3680 {
3681 strErr = "line " + to_string(nLine) + ": must have both date and time for start of data in";
3682 break;
3683 }
3684
3685 // OK, first sort out the time
3686 if (! bParseTime(&VstrTmp[0], nHour, nMin, nSec))
3687 {
3688 strErr = "line " + to_string(nLine) + ": could not understand start time for data";
3689 break;
3690 }
3691
3692 // Next sort out the date
3693 if (! bParseDate(&VstrTmp[1], nDay, nMonth, nYear))
3694 {
3695 strErr = "line " + to_string(nLine) + ": could not understand start date for data";
3696 break;
3697 }
3698
3699 // Compare time and date with simulation time and date
3700 if ((nSec != m_nSimStartSec) ||
3701 (nMin != m_nSimStartMin) ||
3702 (nHour != m_nSimStartHour) ||
3703 (nDay != m_nSimStartDay) ||
3704 (nMonth != m_nSimStartMonth) ||
3705 (nYear != m_nSimStartYear))
3706 {
3707 strErr = "line " + to_string(nLine) + ": start time and date for wave time series data differs from simulation start time and date,";
3708 break;
3709 }
3710
3711 break;
3712
3713 case 2:
3714 // Get the timestep of this data (in hours or days)
3715 strRH = strToLower(&strRH);
3716
3717 dMult = dGetTimeMultiplier(&strRH);
3718
3719 if (static_cast<int>(dMult) == TIME_UNKNOWN)
3720 {
3721 strErr = "line " + to_string(nLine) + ": unknown units for timestep";
3722 break;
3723 }
3724
3725 // We have the multiplier, now calculate the timestep in hours: look for the whitespace between the number and unit
3726 nPos = strRH.rfind(SPACE);
3727
3728 if (nPos == string::npos)
3729 {
3730 strErr = "line " + to_string(nLine) + ": format of timestep line";
3731 break;
3732 }
3733
3734 // Cut off rh bit of string
3735 strRH.resize(nPos);
3736
3737 // Remove trailing spaces
3738 strRH = strTrimRight(&strRH);
3739
3740 // Check that this is a valid double
3741 if (! bIsStringValidDouble(strRH))
3742 {
3743 strErr = "line " + to_string(nLine) + ": invalid floating point number for timestep";
3744 break;
3745 }
3746
3747 dThisIter = strtod(strRH.c_str(), NULL) * dMult; // in hours
3748
3749 if (dThisIter <= 0)
3750 strErr = "line " + to_string(nLine) + ": timestep must be > 0";
3751
3752 if (! bFPIsEqual(dThisIter, m_dTimeStep, TOLERANCE))
3753 strErr = "line " + to_string(nLine) + ": timestep must be the same as the simulation timestep";
3754
3755 break;
3756
3757 case 3:
3758
3759 // Read the number of stations
3760 if (! bIsStringValidInt(strRH))
3761 {
3762 strErr = "line " + to_string(nLine) + ": invalid integer for number of wave stations '" + strRH + "' in " + m_strDeepWaterWavesInputFile;
3763 break;
3764 }
3765
3766 nExpectedStations = stoi(strRH);
3767
3768 // Check that the number of expected stations is equal to the number of stations on the point shape file
3769 if (nExpectedStations != nWaveStations)
3770 {
3771 // Error: number of points on shape file does not match the number of stations on the wave time series file
3772 strErr = "line " + to_string(nLine) + ": number of wave stations in " + m_strDeepWaterWaveStationsShapefile + " is " + to_string(nWaveStations) + " but we have " + to_string(nExpectedStations) + " stations";
3773
3774 break;
3775 }
3776
3777 break;
3778
3779 case 4:
3780
3781 // Read the expected number of time steps in the file
3782 if (! bIsStringValidInt(strRH))
3783 {
3784 strErr = "line " + to_string(nLine) + ": invalid integer for expected number of time steps '" + strRH + "' in " + m_strDeepWaterWaveStationsShapefile;
3785 break;
3786 }
3787
3789
3791 {
3792 // Error: must have value(s) for at least one timestep
3793 strErr = "line " + to_string(nLine) + ": must have values for at least one timestep";
3794 break;
3795 }
3796
3797 break;
3798 }
3799 }
3800
3801 else
3802 {
3803 // This is not a header line
3804 nTimeStepsRead++;
3805
3806 // Read in each wave attribute for each time step and station: split the string, and remove whitespace
3807 vector<string> VstrTmp = VstrSplit(&strRec, COMMA);
3808
3809 for (unsigned int i = 0; i < VstrTmp.size(); i++) // VstrTmp.size() should be 3 x nExpectedStations
3810 {
3811 // Remove leading and trailing whitespace
3812 VstrTmp[i] = strTrim(&VstrTmp[i]);
3813
3814 // Check that this is a valid double
3815 if (! bIsStringValidDouble(VstrTmp[i]))
3816 {
3817 strErr = "line " + to_string(nLine) + ": invalid floating point number for deep water wave value '" + VstrTmp[i] + "' in " + m_strDeepWaterWavesInputFile;
3818 break;
3819 }
3820 }
3821
3822 // Convert to doubles then append the values to the vectors
3823 int n = 0;
3824
3825 for (int i = 0; i < nExpectedStations; i++)
3826 {
3827 m_VdTSDeepWaterWaveStationHeight.push_back(strtod(VstrTmp[n + 0].c_str(), NULL));
3828 m_VdTSDeepWaterWaveStationAngle.push_back(strtod(VstrTmp[n + 1].c_str(), NULL));
3829 m_VdTSDeepWaterWaveStationPeriod.push_back(strtod(VstrTmp[n + 2].c_str(), NULL));
3830
3831 // Check some simple wave input stats
3834
3837
3838 n += 3;
3839 }
3840 }
3841 }
3842
3843 // Did an error occur?
3844 if (!strErr.empty())
3845 {
3846 // Error in input to initialisation file
3847 cerr << ERR << strErr << " in deep water wave time series file " << m_strDeepWaterWavesInputFile << endl
3848 << "'" << strRec << "'" << endl;
3849 InStream.close();
3850
3852 }
3853 }
3854
3855 if (nTimeStepsRead != m_nDeepWaterWaveDataNumTimeSteps)
3856 {
3857 // Error: number of timesteps read does not match the number given in the file's header
3858 cerr << ERR << "in " << m_strDeepWaterWavesInputFile << ", data for " << nTimeStepsRead << " timesteps was read, but " << m_nDeepWaterWaveDataNumTimeSteps << " timesteps were specified in the file's header" << endl;
3859
3861 }
3862
3863 // Close file
3864 InStream.close();
3865
3866 // Did we read in what we expected?
3867 unsigned int const nTotExpected = nExpectedStations * m_nDeepWaterWaveDataNumTimeSteps;
3868
3869 if (m_VdTSDeepWaterWaveStationHeight.size() != nTotExpected)
3870 {
3871 cout << ERR << "read in " << m_VdTSDeepWaterWaveStationHeight.size() << " lines from " << m_strDeepWaterWavesInputFile << " but " << nTotExpected << " values expected" << endl;
3872
3874 }
3875
3876 if (m_VdTSDeepWaterWaveStationAngle.size() != nTotExpected)
3877 {
3878 cout << ERR << "read in " << m_VdTSDeepWaterWaveStationAngle.size() << " lines from " << m_strDeepWaterWavesInputFile << " but " << nTotExpected << " values expected" << endl;
3879
3881 }
3882
3883 if (m_VdTSDeepWaterWaveStationPeriod.size() != nTotExpected)
3884 {
3885 cout << ERR << "read in " << m_VdTSDeepWaterWaveStationPeriod.size() << " lines from " << m_strDeepWaterWavesInputFile << " but " << nTotExpected << " values expected" << endl;
3886
3888 }
3889
3890 // All is OK, so we can now initialize the vectors that will store this timestep's deep water wave values
3891 for (int j = 0; j < nExpectedStations; j++)
3892 {
3896 }
3897
3898 // 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
3899 int const nSimulationTimeSteps = static_cast<int>(floor(m_dSimDuration / m_dTimeStep));
3900
3901 if (m_nDeepWaterWaveDataNumTimeSteps < nSimulationTimeSteps)
3902 {
3904 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";
3905
3906 cout << NOTE << strTmp;
3907 }
3908
3909 return RTN_OK;
3910}
3911
3912//===============================================================================================================================
3914//===============================================================================================================================
3916{
3917 // Create an ifstream object
3918 ifstream InStream;
3919
3920 // Try to open the file for input
3921 InStream.open(m_strSedimentInputEventFile.c_str(), ios::in);
3922
3923 // Did it open OK?
3924 if (!InStream.is_open())
3925 {
3926 // Error: cannot open time series file for input
3927 cerr << ERR << "cannot open " << m_strSedimentInputEventFile << " for input" << endl;
3929 }
3930
3931 // Opened OK
3932 int nLine = 0;
3933 int nRead = 0;
3934 string strRec, strErr;
3935
3936 // Read each line, ignoring comment lines
3937 while (getline(InStream, strRec))
3938 {
3939 nLine++;
3940
3941 // Trim off leading and trailing whitespace
3942 strRec = strTrim(&strRec);
3943
3944 // If it is a blank line or a comment then ignore it
3945 if ((!strRec.empty()) && (strRec[0] != QUOTE1) && (strRec[0] != QUOTE2))
3946 {
3947 // It isn't so increment counter
3948 nRead++;
3949
3950 // Split at commas
3951 vector<string> VstrTmp = VstrSplit(&strRec, COMMA);
3952
3953 // Check that have all we need
3954 unsigned int nTarget = 7;
3955
3957 nTarget = 5;
3958
3959 if (VstrTmp.size() < nTarget)
3960 {
3961 strErr = "line " + to_string(nLine) + ": too few data items on data line '" + to_string(nRead) + "' in " + m_strSedimentInputEventFile;
3962 break;
3963 }
3964
3965 // First item is the Location ID of the sediment input event (same as the ID in the shapefile)
3966 if (! bIsStringValidInt(VstrTmp[0]))
3967 {
3968 strErr = "line " + to_string(nLine) + ": invalid integer for Location ID of sediment input event '" + VstrTmp[0] + "' in " + m_strSedimentInputEventFile;
3969 break;
3970 }
3971
3972 int const nID = stoi(strTrim(&VstrTmp[0]));
3973
3974 // OK, check the ID against IDs read in from the shapefile
3975 auto result = find(m_VnSedimentInputLocationID.begin(), m_VnSedimentInputLocationID.end(), nID);
3976
3977 if (result == m_VnSedimentInputLocationID.end())
3978 {
3979 strErr = "line " + to_string(nLine) + ": invalid Location ID '" + to_string(nID) + "' for sediment input event location event in " + m_strSedimentInputEventFile;
3980 break;
3981 }
3982
3983 // 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)
3984 unsigned long const ulEventTimeStep = ulConvertToTimestep(&VstrTmp[1]);
3985
3986 if (ulEventTimeStep == SEDIMENT_INPUT_EVENT_ERROR)
3987 {
3988 strErr = "line " + to_string(nLine) + ": invalid time and/or date '" + VstrTmp[1] + "' for sediment input event in " + m_strSedimentInputEventFile;
3989 break;
3990 }
3991
3992 // Then the volume (m3) of fine sediment, first check that this is a valid double
3993 if (! bIsStringValidDouble(VstrTmp[2]))
3994 {
3995 strErr = "line " + to_string(nLine) + ": invalid floating point number '" + VstrTmp[2] + "' for fine sediment volume for sediment input event in " + m_strSedimentInputEventFile;
3996 break;
3997 }
3998
3999 double const dFineSedVol = stod(strTrim(&VstrTmp[2]));
4000
4001 if (dFineSedVol < 0)
4002 {
4003 strErr = "line " + to_string(nLine) + ": negative number '" + to_string(dFineSedVol) + "' for fine sediment volume for sediment input event in " + m_strSedimentInputEventFile;
4004 break;
4005 }
4006
4007 if (dFineSedVol > 0)
4008 m_bHaveFineSediment = true;
4009
4010 // Then the volume (m3) of sand sediment, first check that this is a valid double
4011 if (! bIsStringValidDouble(VstrTmp[3]))
4012 {
4013 strErr = "line " + to_string(nLine) + ": invalid floating point number '" + VstrTmp[3] + "' for sand-sized sediment volume for sediment input event in " + m_strSedimentInputEventFile;
4014 break;
4015 }
4016
4017 double const dSandSedVol = stod(strTrim(&VstrTmp[3]));
4018
4019 if (dSandSedVol < 0)
4020 {
4021 strErr = "line " + to_string(nLine) + ": negative number '" + to_string(dSandSedVol) + "' for sand-sized sediment volume for sediment input event in " + m_strSedimentInputEventFile;
4022 break;
4023 }
4024
4025 if (dSandSedVol > 0)
4026 m_bHaveSandSediment = true;
4027
4028 // Then the volume (m3) of coarse sediment, first check that this is a valid double
4029 if (! bIsStringValidDouble(VstrTmp[4]))
4030 {
4031 strErr = "line " + to_string(nLine) + ": invalid floating point number '" + VstrTmp[4] + "' for coarse sediment volume for sediment input event in " + m_strSedimentInputEventFile;
4032 break;
4033 }
4034
4035 double const dCoarseSedVol = stod(strTrim(&VstrTmp[4]));
4036
4037 if (dCoarseSedVol < 0)
4038 {
4039 strErr = "line " + to_string(nLine) + ": negative number '" + to_string(dCoarseSedVol) + "' for coarse sediment volume of sediment input event in " + m_strSedimentInputEventFile;
4040 break;
4041 }
4042
4043 if (dCoarseSedVol > 0)
4044 m_bHaveCoarseSediment = true;
4045
4046 // Only read the last two items if we have on-coast sediment block sediment input
4047 double dLen = 0;
4048 double dWidth = 0;
4049
4050 // double dThick = 0;
4052 {
4053 // The coast-normal length (m) of the sediment block, first check that this is a valid double
4054 if (! bIsStringValidDouble(VstrTmp[5]))
4055 {
4056 strErr = "line " + to_string(nLine) + ": invalid floating point number '" + VstrTmp[5] + "' for coast-normal length of sediment input event in " + m_strSedimentInputEventFile;
4057 break;
4058 }
4059
4060 dLen = stod(strTrim(&VstrTmp[5]));
4061
4062 if (dLen <= 0)
4063 {
4064 strErr = "line " + to_string(nLine) + ": coast-normal length of the sediment block '" + to_string(dLen) + "' must be > 0 in " + m_strSedimentInputEventFile;
4065 break;
4066 }
4067
4068 // The along-coast width (m) of the sediment block, first check that this is a valid double
4069 if (! bIsStringValidDouble(VstrTmp[6]))
4070 {
4071 strErr = "line " + to_string(nLine) + ": invalid floating point number '" + VstrTmp[6] + "' for along-coast width of sediment input event in " + m_strSedimentInputEventFile;
4072 break;
4073 }
4074
4075 dWidth = stod(strTrim(&VstrTmp[6]));
4076
4077 if ((! m_bSedimentInputAtCoast) && (dWidth <= 0))
4078 {
4079 strErr = "line " + to_string(nLine) + ": along-coast width (m) of the sediment block '" + to_string(dWidth) + "' must be > 0 in " + m_strSedimentInputEventFile;
4080 break;
4081 }
4082
4083 // // The along-coast thickness (m) of the sediment block, first check that this is a valid double
4084 // if (! bIsStringValidDouble(VstrTmp[7]))
4085 // {
4086 // strErr = "line " + to_string(nLine) + ": invalid floating point number '" + VstrTmp[7] + "' for along-coast thickness of sediment input event in " + m_strSedimentInputEventFile;
4087 // break;
4088 // }
4089 //
4090 // dThick = stod(strTrim(&VstrTmp[7]));
4091 // if ((! m_bSedimentInputAtCoast) && (dWidth <= 0))
4092 // {
4093 // strErr = "line " + to_string(nLine) + ": along-coast thickness (m) of the sediment block '" + to_string(dThick) + "' must be > 0 in " + m_strSedimentInputEventFile;
4094 // break;
4095 // }
4096 }
4097
4098 // Create the CSedInputEvent object
4099 CSedInputEvent *pEvent = new CSedInputEvent(nID, ulEventTimeStep, dFineSedVol, dSandSedVol, dCoarseSedVol, dLen, dWidth); //, dThick);
4100
4101 // And store it in the m_pVSedInputEvent vector
4102 m_pVSedInputEvent.push_back(pEvent);
4103 }
4104 }
4105
4106 // Did an error occur?
4107 if (!strErr.empty())
4108 {
4109 // Error in input to initialisation file
4110 cerr << ERR << strErr << " in sediment input event file " << m_strSedimentInputEventFile << endl
4111 << "'" << strRec << "'" << endl;
4112 InStream.close();
4113
4115 }
4116
4117 // Close file
4118 InStream.close();
4119
4120 return RTN_OK;
4121}
4122
4123//===============================================================================================================================
4125//===============================================================================================================================
4127{
4128 CConfiguration config;
4129 if (!bConfigureFromYamlFile(config))
4130 return false;
4131
4132 // Apply configuration to simulation object - this will be implemented when updating bReadRunDataFile
4133 // For now, return success if YAML parsing worked
4134 return true;
4135}
4136
4137//===============================================================================================================================
4139//===============================================================================================================================
4141{
4142 CYamlParser parser;
4143
4144 if (! parser.bParseFile(m_strDataPathName))
4145 {
4146 cerr << ERR << "Failed to parse YAML file " << m_strDataPathName << ": "
4147 << parser.GetError() << endl;
4148 return false;
4149 }
4150
4151 CYamlNode root = parser.GetRoot();
4152
4153 // Helper function to process file paths with base path
4154 auto processFilePath = [&](const string& filePath) -> string {
4155 if (filePath.empty())
4156 return filePath;
4157
4158 // Check if base_path is specified in YAML
4159 string basePath;
4160 if (root.HasChild("base_path")) {
4161 basePath = root.GetChild("base_path").GetValue();
4162 if (!basePath.empty() && basePath.back() != PATH_SEPARATOR) {
4163 basePath += PATH_SEPARATOR;
4164 }
4165 }
4166
4167 // If no base path or file path is absolute, return as-is
4168 if (basePath.empty() ||
4169 (filePath[0] == PATH_SEPARATOR) || (filePath[0] == TILDE) ||
4170 (filePath.length() > 1 && filePath[1] == COLON)) {
4171 return filePath;
4172 }
4173
4174 // Prepend base path to relative file path
4175 return basePath + filePath;
4176 };
4177
4178 try
4179 {
4180 // Run Information
4181 if (root.HasChild("run_information"))
4182 {
4183 CYamlNode runInfo = root.GetChild("run_information");
4184 if (runInfo.HasChild("output_file_names"))
4185 config.SetRunName(runInfo.GetChild("output_file_names").GetValue());
4186 if (runInfo.HasChild("log_file_detail"))
4187 config.SetLogFileDetail(
4188 runInfo.GetChild("log_file_detail").GetIntValue());
4189 if (runInfo.HasChild("csv_per_timestep_results"))
4191 runInfo.GetChild("csv_per_timestep_results").GetBoolValue());
4192 }
4193
4194 // Simulation
4195 if (root.HasChild("simulation"))
4196 {
4197 CYamlNode sim = root.GetChild("simulation");
4198 if (sim.HasChild("start_date_time"))
4199 config.SetStartDateTime(sim.GetChild("start_date_time").GetValue());
4200 if (sim.HasChild("duration"))
4201 config.SetDuration(sim.GetChild("duration").GetValue());
4202 if (sim.HasChild("timestep"))
4203 config.SetTimestep(sim.GetChild("timestep").GetValue());
4204 if (sim.HasChild("save_times"))
4205 {
4206 CYamlNode saveTimes = sim.GetChild("save_times");
4207 if (saveTimes.IsSequence())
4208 config.SetSaveTimes(saveTimes.GetStringSequence());
4209 }
4210 if (sim.HasChild("random_seed"))
4211 config.SetRandomSeed(sim.GetChild("random_seed").GetIntValue());
4212 }
4213
4214 // GIS Output
4215 if (root.HasChild("gis_output"))
4216 {
4217 CYamlNode gis = root.GetChild("gis_output");
4218 if (gis.HasChild("max_save_digits"))
4219 config.SetMaxSaveDigits(gis.GetChild("max_save_digits").GetIntValue());
4220 if (gis.HasChild("save_digits_mode"))
4221 config.SetSaveDigitsMode(gis.GetChild("save_digits_mode").GetValue());
4222 if (gis.HasChild("raster_files"))
4223 {
4224 CYamlNode rasterFiles = gis.GetChild("raster_files");
4225 if (rasterFiles.IsSequence())
4226 config.SetRasterFiles(rasterFiles.GetStringSequence());
4227 }
4228 if (gis.HasChild("raster_format"))
4229 config.SetRasterFormat(gis.GetChild("raster_format").GetValue());
4230 if (gis.HasChild("world_file"))
4231 config.SetWorldFile(gis.GetChild("world_file").GetBoolValue());
4232 if (gis.HasChild("scale_values"))
4233 config.SetScaleValues(gis.GetChild("scale_values").GetBoolValue());
4234 }
4235
4236 // Hydrology
4237 if (root.HasChild("hydrology"))
4238 {
4239 CYamlNode hydro = root.GetChild("hydrology");
4240 if (hydro.HasChild("wave_propagation_model"))
4241 {
4242 string strModel = hydro.GetChild("wave_propagation_model").GetValue();
4243 if (strModel == "COVE")
4244 config.SetWavePropagationModel(0);
4245 else if (strModel == "CShore")
4246 config.SetWavePropagationModel(1);
4247 }
4248 if (hydro.HasChild("seawater_density"))
4249 config.SetSeawaterDensity(
4250 hydro.GetChild("seawater_density").GetDoubleValue());
4251 if (hydro.HasChild("initial_water_level"))
4252 config.SetInitialWaterLevel(
4253 hydro.GetChild("initial_water_level").GetDoubleValue());
4254 if (hydro.HasChild("wave_height"))
4256 hydro.GetChild("wave_height").GetDoubleValue());
4257 if (hydro.HasChild("wave_orientation"))
4259 hydro.GetChild("wave_orientation").GetDoubleValue());
4260 if (hydro.HasChild("wave_period"))
4261 config.SetWavePeriod(hydro.GetChild("wave_period").GetDoubleValue());
4262 if (hydro.HasChild("tide_data_file"))
4263 config.SetTideDataFile(processFilePath(hydro.GetChild("tide_data_file").GetValue()));
4264 if (hydro.HasChild("final_water_level"))
4265 config.SetFinalWaterLevel(
4266 hydro.GetChild("final_water_level").GetDoubleValue());
4267 if (hydro.HasChild("wave_height_time_series"))
4269 hydro.GetChild("wave_height_time_series").GetValue());
4270 if (hydro.HasChild("breaking_wave_ratio"))
4271 config.SetBreakingWaveRatio(
4272 hydro.GetChild("breaking_wave_ratio").GetDoubleValue());
4273 }
4274
4275 // Grid and Coastline
4276 if (root.HasChild("grid_and_coastline"))
4277 {
4278 CYamlNode grid = root.GetChild("grid_and_coastline");
4279 if (grid.HasChild("coastline_smoothing"))
4280 {
4281 string strSmoothing = grid.GetChild("coastline_smoothing").GetValue();
4282 if (strSmoothing == "none")
4283 config.SetCoastlineSmoothing(0);
4284 else if (strSmoothing == "running_mean")
4285 config.SetCoastlineSmoothing(1);
4286 else if (strSmoothing == "savitzky_golay")
4287 config.SetCoastlineSmoothing(2);
4288 else
4289 config.SetCoastlineSmoothing(
4290 grid.GetChild("coastline_smoothing").GetIntValue());
4291 }
4292 if (grid.HasChild("coastline_smoothing_window"))
4294 grid.GetChild("coastline_smoothing_window").GetIntValue());
4295 if (grid.HasChild("polynomial_order"))
4296 config.SetPolynomialOrder(
4297 grid.GetChild("polynomial_order").GetIntValue());
4298 if (grid.HasChild("omit_grid_edges"))
4299 config.SetOmitGridEdges(grid.GetChild("omit_grid_edges").GetValue());
4300 if (grid.HasChild("profile_smoothing_window"))
4302 grid.GetChild("profile_smoothing_window").GetIntValue());
4303 if (grid.HasChild("max_local_slope"))
4304 config.SetMaxLocalSlope(
4305 grid.GetChild("max_local_slope").GetDoubleValue());
4306 if (grid.HasChild("max_beach_elevation"))
4307 config.SetMaxBeachElevation(
4308 grid.GetChild("max_beach_elevation").GetDoubleValue());
4309 }
4310
4311 // Layers and Files
4312 if (root.HasChild("layers_and_files"))
4313 {
4314 CYamlNode layers = root.GetChild("layers_and_files");
4315 if (layers.HasChild("num_layers"))
4316 config.SetNumLayers(layers.GetChild("num_layers").GetIntValue());
4317 if (layers.HasChild("basement_dem_file"))
4318 config.SetBasementDEMFile(
4319 processFilePath(layers.GetChild("basement_dem_file").GetValue()));
4320 if (layers.HasChild("suspended_sediment_file"))
4321 config.SetSuspendedSedFile(
4322 processFilePath(layers.GetChild("suspended_sediment_file").GetValue()));
4323 if (layers.HasChild("landform_file"))
4324 config.SetLandformFile(processFilePath(layers.GetChild("landform_file").GetValue()));
4325 if (layers.HasChild("intervention_class_file"))
4327 processFilePath(layers.GetChild("intervention_class_file").GetValue()));
4328 if (layers.HasChild("intervention_height_file"))
4330 processFilePath(layers.GetChild("intervention_height_file").GetValue()));
4331
4332 // Handle layer-specific files (assuming layer_0, layer_1, etc.)
4333 if (layers.HasChild("layer_0"))
4334 {
4335 CYamlNode layer0 = layers.GetChild("layer_0");
4336 vector<string> unconsFine, unconsSand, unconsCoarse;
4337 vector<string> consFine, consSand, consCoarse;
4338
4339 if (layer0.HasChild("unconsolidated_fine"))
4340 unconsFine.push_back(
4341 processFilePath(layer0.GetChild("unconsolidated_fine").GetValue()));
4342 if (layer0.HasChild("unconsolidated_sand"))
4343 unconsSand.push_back(
4344 processFilePath(layer0.GetChild("unconsolidated_sand").GetValue()));
4345 if (layer0.HasChild("unconsolidated_coarse"))
4346 unconsCoarse.push_back(
4347 processFilePath(layer0.GetChild("unconsolidated_coarse").GetValue()));
4348 if (layer0.HasChild("consolidated_fine"))
4349 consFine.push_back(processFilePath(layer0.GetChild("consolidated_fine").GetValue()));
4350 if (layer0.HasChild("consolidated_sand"))
4351 consSand.push_back(processFilePath(layer0.GetChild("consolidated_sand").GetValue()));
4352 if (layer0.HasChild("consolidated_coarse"))
4353 consCoarse.push_back(
4354 processFilePath(layer0.GetChild("consolidated_coarse").GetValue()));
4355
4356 config.SetUnconsFineFiles(unconsFine);
4357 config.SetUnconsSandFiles(unconsSand);
4358 config.SetUnconsCoarseFiles(unconsCoarse);
4359 config.SetConsFineFiles(consFine);
4360 config.SetConsSandFiles(consSand);
4361 config.SetConsCoarseFiles(consCoarse);
4362 }
4363 }
4364
4365 // Sediment and Erosion
4366 if (root.HasChild("sediment_and_erosion"))
4367 {
4368 CYamlNode sed = root.GetChild("sediment_and_erosion");
4369 if (sed.HasChild("coast_platform_erosion"))
4371 sed.GetChild("coast_platform_erosion").GetBoolValue());
4372 if (sed.HasChild("platform_erosion_resistance"))
4374 sed.GetChild("platform_erosion_resistance").GetDoubleValue());
4375 if (sed.HasChild("beach_sediment_transport"))
4377 sed.GetChild("beach_sediment_transport").GetBoolValue());
4378 if (sed.HasChild("beach_transport_at_edges"))
4380 sed.GetChild("beach_transport_at_edges").GetIntValue());
4381 if (sed.HasChild("beach_erosion_equation"))
4382 {
4383 string strEqn = sed.GetChild("beach_erosion_equation").GetValue();
4384 config.SetBeachErosionEquation(strEqn == "CERC" ? 0 : 1);
4385 }
4386 if (sed.HasChild("sediment_density"))
4387 config.SetSedimentDensity(
4388 sed.GetChild("sediment_density").GetDoubleValue());
4389 if (sed.HasChild("beach_sediment_porosity"))
4391 sed.GetChild("beach_sediment_porosity").GetDoubleValue());
4392 if (sed.HasChild("transport_kls"))
4393 config.SetTransportKLS(sed.GetChild("transport_kls").GetDoubleValue());
4394 if (sed.HasChild("kamphuis_parameter"))
4395 config.SetKamphuis(sed.GetChild("kamphuis_parameter").GetDoubleValue());
4396 if (sed.HasChild("berm_height"))
4397 config.SetBermHeight(sed.GetChild("berm_height").GetDoubleValue());
4398
4399 // Handle nested median_sizes and erosivity sections
4400 if (sed.HasChild("median_sizes"))
4401 {
4402 CYamlNode sizes = sed.GetChild("median_sizes");
4403 if (sizes.HasChild("fine"))
4404 config.SetFineMedianSize(sizes.GetChild("fine").GetDoubleValue());
4405 if (sizes.HasChild("sand"))
4406 config.SetSandMedianSize(sizes.GetChild("sand").GetDoubleValue());
4407 if (sizes.HasChild("coarse"))
4408 config.SetCoarseMedianSize(sizes.GetChild("coarse").GetDoubleValue());
4409 }
4410 if (sed.HasChild("erosivity"))
4411 {
4412 CYamlNode eros = sed.GetChild("erosivity");
4413 if (eros.HasChild("fine"))
4414 config.SetFineErosivity(eros.GetChild("fine").GetDoubleValue());
4415 if (eros.HasChild("sand"))
4416 config.SetSandErosivity(eros.GetChild("sand").GetDoubleValue());
4417 if (eros.HasChild("coarse"))
4418 config.SetCoarseErosivity(eros.GetChild("coarse").GetDoubleValue());
4419 }
4420 }
4421
4422 // Cliff Parameters
4423 if (root.HasChild("cliff_parameters"))
4424 {
4425 CYamlNode cliff = root.GetChild("cliff_parameters");
4426 if (cliff.HasChild("cliff_collapse"))
4427 config.SetCliffCollapse(
4428 cliff.GetChild("cliff_collapse").GetBoolValue());
4429 if (cliff.HasChild("cliff_erosion_resistance"))
4431 cliff.GetChild("cliff_erosion_resistance").GetDoubleValue());
4432 if (cliff.HasChild("notch_overhang"))
4433 config.SetNotchOverhang(
4434 cliff.GetChild("notch_overhang").GetDoubleValue());
4435 if (cliff.HasChild("notch_base"))
4436 config.SetNotchBase(cliff.GetChild("notch_base").GetDoubleValue());
4437 if (cliff.HasChild("deposition_scale_parameter_a"))
4438 config.SetCliffDepositionA(
4439 cliff.GetChild("deposition_scale_parameter_a").GetDoubleValue());
4440 if (cliff.HasChild("talus_width"))
4441 config.SetTalusWidth(cliff.GetChild("talus_width").GetDoubleValue());
4442 if (cliff.HasChild("min_talus_length"))
4443 config.SetMinTalusLength(
4444 cliff.GetChild("min_talus_length").GetDoubleValue());
4445 if (cliff.HasChild("min_talus_height"))
4446 config.SetMinTalusHeight(
4447 cliff.GetChild("min_talus_height").GetDoubleValue());
4448 }
4449
4450 // Flood Parameters
4451 if (root.HasChild("flood_parameters"))
4452 {
4453 CYamlNode flood = root.GetChild("flood_parameters");
4454 if (flood.HasChild("flood_input"))
4455 config.SetFloodInput(flood.GetChild("flood_input").GetBoolValue());
4456 if (flood.HasChild("flood_coastline"))
4457 config.SetFloodCoastline(flood.GetChild("flood_coastline").GetValue());
4458 if (flood.HasChild("runup_equation"))
4459 config.SetRunupEquation(flood.GetChild("runup_equation").GetValue());
4460 if (flood.HasChild("characteristic_locations"))
4461 config.SetFloodLocations(
4462 processFilePath(flood.GetChild("characteristic_locations").GetValue()));
4463 if (flood.HasChild("flood_input_location"))
4464 config.SetFloodInputLocation(
4465 processFilePath(flood.GetChild("flood_input_location").GetValue()));
4466 }
4467
4468 // Sediment Input Parameters
4469 if (root.HasChild("sediment_input_parameters"))
4470 {
4471 CYamlNode sedInput = root.GetChild("sediment_input_parameters");
4472 if (sedInput.HasChild("sediment_input"))
4473 config.SetSedimentInput(
4474 sedInput.GetChild("sediment_input").GetBoolValue());
4475 if (sedInput.HasChild("location"))
4477 processFilePath(sedInput.GetChild("location").GetValue()));
4478 if (sedInput.HasChild("type"))
4479 config.SetSedimentInputType(sedInput.GetChild("type").GetValue());
4480 if (sedInput.HasChild("details_file"))
4482 processFilePath(sedInput.GetChild("details_file").GetValue()));
4483 }
4484
4485 // Physics and Geometry
4486 if (root.HasChild("physics_and_geometry"))
4487 {
4488 CYamlNode physics = root.GetChild("physics_and_geometry");
4489 if (physics.HasChild("gravitational_acceleration"))
4491 physics.GetChild("gravitational_acceleration").GetDoubleValue());
4492 if (physics.HasChild("normal_spacing"))
4493 config.SetNormalSpacing(
4494 physics.GetChild("normal_spacing").GetDoubleValue());
4495 if (physics.HasChild("random_factor"))
4496 config.SetRandomFactor(
4497 physics.GetChild("random_factor").GetDoubleValue());
4498 if (physics.HasChild("normal_length"))
4499 config.SetNormalLength(
4500 physics.GetChild("normal_length").GetDoubleValue());
4501 if (physics.HasChild("start_depth_ratio"))
4502 config.SetStartDepthRatio(
4503 physics.GetChild("start_depth_ratio").GetDoubleValue());
4504 }
4505
4506 // Profile and Output
4507 if (root.HasChild("profile_and_output"))
4508 {
4509 CYamlNode profile = root.GetChild("profile_and_output");
4510 if (profile.HasChild("save_profile_data"))
4511 config.SetSaveProfileData(
4512 profile.GetChild("save_profile_data").GetBoolValue());
4513 if (profile.HasChild("save_parallel_profiles"))
4515 profile.GetChild("save_parallel_profiles").GetBoolValue());
4516 if (profile.HasChild("output_erosion_potential"))
4518 profile.GetChild("output_erosion_potential").GetBoolValue());
4519 if (profile.HasChild("curvature_window"))
4520 config.SetCurvatureWindow(
4521 profile.GetChild("curvature_window").GetIntValue());
4522
4523 // Handle numeric lists
4524 if (profile.HasChild("profile_numbers"))
4525 {
4526 CYamlNode profileNums = profile.GetChild("profile_numbers");
4527 if (profileNums.IsSequence())
4528 {
4529 vector<int> vecNums;
4530 vector<CYamlNode> seq = profileNums.GetSequence();
4531 for (auto const &node : seq)
4532 vecNums.push_back(node.GetIntValue());
4533 config.SetProfileNumbers(vecNums);
4534 }
4535 }
4536 if (profile.HasChild("profile_timesteps"))
4537 {
4538 CYamlNode profileTimes = profile.GetChild("profile_timesteps");
4539 if (profileTimes.IsSequence())
4540 {
4541 vector<int> vecTimes;
4542 vector<CYamlNode> seq = profileTimes.GetSequence();
4543 for (auto const &node : seq)
4544 vecTimes.push_back(node.GetIntValue());
4545 config.SetProfileTimesteps(vecTimes);
4546 }
4547 }
4548 }
4549
4550 // Cliff Edge Processing
4551 if (root.HasChild("cliff_edge_processing"))
4552 {
4553 CYamlNode cliffEdge = root.GetChild("cliff_edge_processing");
4554 if (cliffEdge.HasChild("cliff_edge_smoothing"))
4555 {
4556 string strSmoothing =
4557 cliffEdge.GetChild("cliff_edge_smoothing").GetValue();
4558 if (strSmoothing == "none")
4559 config.SetCliffEdgeSmoothing(0);
4560 else if (strSmoothing == "running_mean")
4561 config.SetCliffEdgeSmoothing(1);
4562 else if (strSmoothing == "savitzky_golay")
4563 config.SetCliffEdgeSmoothing(2);
4564 else
4565 config.SetCliffEdgeSmoothing(
4566 cliffEdge.GetChild("cliff_edge_smoothing").GetIntValue());
4567 }
4568 if (cliffEdge.HasChild("cliff_edge_smoothing_window"))
4570 cliffEdge.GetChild("cliff_edge_smoothing_window").GetIntValue());
4571 if (cliffEdge.HasChild("cliff_edge_polynomial_order"))
4573 cliffEdge.GetChild("cliff_edge_polynomial_order").GetIntValue());
4574 if (cliffEdge.HasChild("cliff_slope_limit"))
4575 config.SetCliffSlopeLimit(
4576 cliffEdge.GetChild("cliff_slope_limit").GetDoubleValue());
4577 }
4578 }
4579 catch (std::exception const &e)
4580 {
4581 cerr << ERR << "Error processing YAML configuration: " << e.what() << endl;
4582 return false;
4583 }
4584
4585 return true;
4586}
4587
4588//===============================================================================================================================
4590//===============================================================================================================================
4592{
4593 // Apply only the essential GIS output settings that exist
4596
4597 // Apply run information
4598 m_strRunName = config.GetRunName();
4600
4601 // Construct log file path like in .dat parsing
4603 m_strOutFile.append(m_strRunName);
4604 m_strOutFile.append(OUTEXT);
4605
4607 m_strLogFile.append(m_strRunName);
4608 m_strLogFile.append(LOGEXT);
4609
4610 // Parse and apply timing settings
4611 string strDuration = config.GetDuration();
4612 string strTimestep = config.GetTimestep();
4613
4614 // Parse duration (like "24hours" -> hours as double)
4615 if (! strDuration.empty())
4616 {
4617 string strDurationLower = strToLower(&strDuration);
4618 double dDurationMult = dGetTimeMultiplier(&strDurationLower);
4619 if (dDurationMult != TIME_UNKNOWN)
4620 {
4621 // Extract numeric part and multiply
4622 string strNumeric = strDurationLower;
4623 // Remove the unit part to get just the number
4624 if (strNumeric.find("hour") != string::npos)
4625 strNumeric = strNumeric.substr(0, strNumeric.find("hour"));
4626 else if (strNumeric.find("day") != string::npos)
4627 strNumeric = strNumeric.substr(0, strNumeric.find("day"));
4628 else if (strNumeric.find("month") != string::npos)
4629 strNumeric = strNumeric.substr(0, strNumeric.find("month"));
4630 else if (strNumeric.find("year") != string::npos)
4631 strNumeric = strNumeric.substr(0, strNumeric.find("year"));
4632
4633 if (bIsStringValidDouble(strNumeric))
4634 {
4635 m_dSimDuration = strtod(strNumeric.c_str(), NULL) * dDurationMult;
4636 }
4637 }
4638 }
4639
4640 // Parse timestep (like "6hours" -> hours as double)
4641 if (! strTimestep.empty())
4642 {
4643 string strTimestepLower = strToLower(&strTimestep);
4644 double dTimestepMult = dGetTimeMultiplier(&strTimestepLower);
4645 if (dTimestepMult != TIME_UNKNOWN)
4646 {
4647 // Extract numeric part and multiply
4648 string strNumeric = strTimestepLower;
4649 // Remove the unit part to get just the number
4650 if (strNumeric.find("hour") != string::npos)
4651 strNumeric = strNumeric.substr(0, strNumeric.find("hour"));
4652 else if (strNumeric.find("day") != string::npos)
4653 strNumeric = strNumeric.substr(0, strNumeric.find("day"));
4654 else if (strNumeric.find("month") != string::npos)
4655 strNumeric = strNumeric.substr(0, strNumeric.find("month"));
4656 else if (strNumeric.find("year") != string::npos)
4657 strNumeric = strNumeric.substr(0, strNumeric.find("year"));
4658
4659 if (bIsStringValidDouble(strNumeric))
4660 {
4661 m_dTimeStep = strtod(strNumeric.c_str(), NULL) * dTimestepMult;
4662 }
4663 }
4664 }
4665
4666 // Apply basic simulation settings that exist in both classes
4669
4670 // Apply wave settings
4674
4675 // Apply tide and wave settings
4678
4679 m_nLayers = config.GetNumLayers();
4686
4687 for (int j = 0; j < m_nLayers; j++)
4688 {
4695 m_VstrGDALIUFDriverCode.push_back("");
4696 m_VstrGDALIUFDriverDesc.push_back("");
4697 m_VstrGDALIUFProjection.push_back("");
4698 m_VstrGDALIUFDataType.push_back("");
4699 m_VstrGDALIUSDriverCode.push_back("");
4700 m_VstrGDALIUSDriverDesc.push_back("");
4701 m_VstrGDALIUSProjection.push_back("");
4702 m_VstrGDALIUSDataType.push_back("");
4703 m_VstrGDALIUCDriverCode.push_back("");
4704 m_VstrGDALIUCDriverDesc.push_back("");
4705 m_VstrGDALIUCProjection.push_back("");
4706 m_VstrGDALIUCDataType.push_back("");
4707 m_VstrGDALICFDriverCode.push_back("");
4708 m_VstrGDALICFDriverDesc.push_back("");
4709 m_VstrGDALICFProjection.push_back("");
4710 m_VstrGDALICFDataType.push_back("");
4711 m_VstrGDALICSDriverCode.push_back("");
4712 m_VstrGDALICSDriverDesc.push_back("");
4713 m_VstrGDALICSProjection.push_back("");
4714 m_VstrGDALICSDataType.push_back("");
4715 m_VstrGDALICCDriverCode.push_back("");
4716 m_VstrGDALICCDriverDesc.push_back("");
4717 m_VstrGDALICCProjection.push_back("");
4718 m_VstrGDALICCDataType.push_back("");
4719 }
4720
4721 return true;
4722}
Unified configuration class for CoastalME simulation parameters.
void SetCoastlineSmoothingWindow(int n)
string GetRunName() const
void SetSedimentInput(bool b)
void SetBeachSedimentPorosity(double d)
void SetBermHeight(double d)
void SetMinTalusHeight(double d)
void SetCoarseErosivity(double d)
void SetCurvatureWindow(int n)
void SetMaxBeachElevation(double d)
void SetNotchBase(double d)
void SetInterventionClassFile(string const &str)
string GetBasementDEMFile() const
double GetBreakingWaveRatio() const
void SetSeawaterDensity(double d)
void SetSaveDigitsMode(string const &str)
void SetInitialWaterLevel(double d)
void SetCliffDepositionA(double d)
void SetFloodInput(bool b)
void SetNormalLength(double d)
vector< string > GetConsCoarseFiles() const
void SetTideDataFile(string const &str)
void SetBeachErosionEquation(int n)
void SetDeepWaterWaveHeight(double d)
void SetFineMedianSize(double d)
vector< string > GetUnconsFineFiles() const
void SetFloodCoastline(string const &str)
void SetRandomFactor(double d)
void SetConsSandFiles(vector< string > const &vec)
string GetTimestep() const
void SetPolynomialOrder(int n)
void SetCliffErosionResistance(double d)
void SetCliffEdgePolynomialOrder(int n)
void SetDuration(string const &str)
void SetMaxSaveDigits(int n)
void SetCoarseMedianSize(double d)
void SetCliffSlopeLimit(double d)
void SetRunName(string const &str)
void SetProfileTimesteps(vector< int > const &vec)
void SetFloodInputLocation(string const &str)
void SetGravitationalAcceleration(double d)
void SetScaleValues(bool b)
void SetBeachTransportAtEdges(int n)
void SetProfileNumbers(vector< int > const &vec)
void SetKamphuis(double d)
string GetDuration() const
void SetSedimentInputLocation(string const &str)
double GetDeepWaterWaveHeight() const
void SetWaveHeightTimeSeries(string const &str)
void SetDeepWaterWaveOrientation(double d)
double GetDeepWaterWaveOrientation() const
void SetNormalSpacing(double d)
void SetSaveProfileData(bool b)
void SetConsCoarseFiles(vector< string > const &vec)
void SetSedimentDensity(double d)
void SetSandErosivity(double d)
void SetFineErosivity(double d)
string GetVectorFormat() const
void SetCliffEdgeSmoothing(int n)
void SetCliffEdgeSmoothingWindow(int n)
void SetProfileSmoothingWindow(int n)
void SetUnconsSandFiles(vector< string > const &vec)
void SetSedimentInputDetails(string const &str)
void SetOmitGridEdges(string const &str)
void SetStartDateTime(string const &str)
void SetSuspendedSedFile(string const &str)
vector< string > GetUnconsSandFiles() const
void SetPlatformErosionResistance(double d)
void SetBasementDEMFile(string const &str)
void SetUnconsCoarseFiles(vector< string > const &vec)
void SetWavePropagationModel(int n)
void SetBeachSedimentTransport(bool b)
void SetCSVPerTimestepResults(bool b)
void SetSandMedianSize(double d)
void SetFinalWaterLevel(double d)
vector< string > GetConsSandFiles() const
void SetRandomSeed(int n)
void SetRasterFormat(string const &str)
void SetWavePeriod(double d)
void SetFloodLocations(string const &str)
vector< string > GetConsFineFiles() const
void SetRunupEquation(string const &str)
void SetNotchOverhang(double d)
void SetNumLayers(int n)
void SetInterventionHeightFile(string const &str)
void SetUnconsFineFiles(vector< string > const &vec)
string GetTideDataFile() const
void SetOutputErosionPotential(bool b)
void SetCliffCollapse(bool b)
void SetBreakingWaveRatio(double d)
double GetWavePeriod() const
void SetWorldFile(bool b)
void SetConsFineFiles(vector< string > const &vec)
vector< string > GetUnconsCoarseFiles() const
void SetTalusWidth(double d)
int GetLogFileDetail() const
void SetCoastlineSmoothing(int n)
void SetMinTalusLength(double d)
void SetTransportKLS(double d)
void SetSaveTimes(vector< string > const &vec)
void SetLandformFile(string const &str)
void SetStartDepthRatio(double d)
void SetRasterFiles(vector< string > const &vec)
void SetSaveParallelProfiles(bool b)
void SetMaxLocalSlope(double d)
string GetLandformFile() const
string GetRasterFormat() const
void SetLogFileDetail(int n)
void SetTimestep(string const &str)
void SetCoastPlatformErosion(bool b)
void SetSedimentInputType(string const &str)
int GetNumLayers() const
Class used to represent a sediment input event.
double m_dCliffDepositionPlanviewWidth
Planview width of cliff collapse talus (m)
Definition simulation.h:924
bool m_bCliffCollapseSave
Save cliff collapse raster GIS files?
Definition simulation.h:225
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:579
bool m_bAvgSeaDepthSave
Save average sea depth raster GIS files?
Definition simulation.h:114
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:759
bool m_bDeepWaterWaveAngleSave
Save deep water wave angle raster GIS files?
Definition simulation.h:252
bool bReadYamlFile(void)
Reads YAML configuration file.
int m_nGISMaxSaveDigits
The maximum number of digits in GIS filenames. These can be sequential, or the iteration number.
Definition simulation.h:504
bool m_bTopSurfSave
Save fop surface (sediment and sea) raster DEMs?
Definition simulation.h:99
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:96
bool m_bFineUnconsSedSave
Save fine unconsolidated sediment raster GIS files?
Definition simulation.h:198
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:453
double m_dNotchDepthAtCollapse
Notch overhang (i.e. length of horizontal incision) to initiate collapse (m)
Definition simulation.h:915
bool m_bFloodSWLSetupSurgeLine
Are we saving the flood still water level setup surge line? TODO 007.
Definition simulation.h:444
string m_strCMEIni
Folder for the CME .ini file.
bool m_bSedimentInputAtPoint
Do we have sediment inputat a point?
Definition simulation.h:399
double m_dG
Gravitational acceleration (m**2/sec)
Definition simulation.h:816
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:534
bool m_bCoastSave
Save.
Definition simulation.h:270
bool m_bBeachDepositionTSSave
Save the beach (unconsolidated sediment) deposition time series file?
Definition simulation.h:321
static string strRemoveSubstr(string *, string const *)
Returns a string with a substring removed, and with whitespace trimmed.
Definition utils.cpp:2452
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:2760
double m_dWaveDataWrapHours
Number of hours after which deep water wave data wraps.
Definition simulation.h:969
vector< string > m_VstrGDALICFDataType
GDAL data type for the initial consolidated fine sediment GIS data.
double m_dMaxUserInputWavePeriod
Used to constrain depth of closure.
Definition simulation.h:771
bool m_bFloodSetupSurgeRunupTSSave
Save the flood setup surge runup time series file? TODO 007 Does this work correctly?
Definition simulation.h:333
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:831
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:390
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:132
bool bConfigureFromYamlFile(CConfiguration &config)
Configures simulation from YAML file.
string m_strSCAPEShapeFunctionFile
Name of SCAPE shape function file.
bool m_bAvgWaveAngleSave
Save average wave angle raster GIS files?
Definition simulation.h:126
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:273
bool m_bInvalidNormalsSave
Save invalid coastline-normal vector GIS files?
Definition simulation.h:279
bool m_bShadowBoundarySave
Save wave shadow boundary vector GIS files?
Definition simulation.h:294
int nDoSimulationTimeMultiplier(string const *)
Given a string containing time units, this sets up the appropriate multiplier and display units for t...
Definition utils.cpp:324
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:165
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:303
bool m_bRunUpSave
Are we saving runup? TODO 007.
Definition simulation.h:423
bool m_bYamlInputFormat
Use YAML format for input datafile instead of .dat format?
Definition simulation.h:351
bool m_bCliffCollapseDepositionSave
Save cliff collapse deposition raster GIS files?
Definition simulation.h:231
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:159
static string strTrimLeft(string const *)
Trims whitespace from the left side of a string, does not change the original string.
Definition utils.cpp:2372
bool m_bPolygonUnconsSedUpOrDownDriftSave
Save polygon unconsolidated sediment up- or down-drift raster GIS files?
Definition simulation.h:261
double m_dCoarseErodibility
The relative erodibility (0- 1) of coarse unconsolidated beach sediment.
Definition simulation.h:798
double m_dCliffTalusMinDepositionLength
Planview length of cliff deposition talus (m)
Definition simulation.h:927
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:531
double m_dSandErodibility
The relative erodibility (0- 1) of sand unconsolidated beach sediment.
Definition simulation.h:795
bool m_bBasementElevSave
Save basement raster DEMs?
Definition simulation.h:93
int m_nSimStartHour
Start time of the simulation (hours)
Definition simulation.h:564
bool m_bCoarseUnconsSedSave
Save coarse unconsolidated sediment raster GIS files?
Definition simulation.h:204
bool m_bSuspSedTSSave
Save the suspended sediment time series file?
Definition simulation.h:327
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:315
bool m_bPotentialPlatformErosionMaskSave
Save potential platform erosion mask raster GIS files?
Definition simulation.h:240
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:753
bool m_bWaveHeightSave
Save wave height raster GIS files?
Definition simulation.h:117
bool m_bFloodLocation
Are we saving the flood location? TODO 007.
Definition simulation.h:438
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:180
static string strTrim(string const *)
Trims whitespace from both sides of a string, does not change the original string.
Definition utils.cpp:2407
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:177
double m_dBeachSedimentPorosity
The porosity of unconsolidated beach sediment (0 - 1)
Definition simulation.h:789
int m_nSimStartSec
Start time of the simulation (seconds)
Definition simulation.h:558
int m_nSimStartDay
Start date of the simulation (day)
Definition simulation.h:567
bool m_bSandUnconsSedSave
Save sand unconsolidated sediment raster GIS files?
Definition simulation.h:201
bool m_bActualPlatformErosionTSSave
Save the actual (supply-limited) shore platform erosion time series file?
Definition simulation.h:306
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:2821
int m_nCoastNormalSpacing
Average spacing between coastline normals, measured in cells.
Definition simulation.h:495
bool m_bTotCliffCollapseSave
Save total cliff collapse raster GIS files?
Definition simulation.h:228
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:105
bool m_bDoShorePlatformErosion
Simulate shore platform erosion?
Definition simulation.h:366
bool m_bSliceSave
Save slices?
Definition simulation.h:108
bool m_bRasterPolygonSave
Save raster polygon raster GIS files?
Definition simulation.h:237
double m_dInitialMeanSWL
The start-of-simulation still water level (m)
Definition simulation.h:708
bool m_bBeachDepositionSave
Save beach (unconsolidated sediment) deposition raster GIS files?
Definition simulation.h:174
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:267
int m_nLayers
The number of sediment layers.
Definition simulation.h:468
int m_nCoastSmoothingWindowSize
The size of the window used for coast smoothing. Must be an odd number.
Definition simulation.h:474
bool m_bSedimentInputAlongLine
Do we have sediment input along a line?
Definition simulation.h:405
bool m_bSedimentInput
Do we have sediment input events?
Definition simulation.h:396
bool m_bNormalsSave
Save coastline-normal vector GIS files?
Definition simulation.h:276
bool m_bAvgWaveHeightSave
Save wave height raster GIS files?
Definition simulation.h:120
static string strToLower(string const *)
Returns the lower case version of an string, leaving the original unchanged.
Definition utils.cpp:2432
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:87
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:510
double m_dDeanProfileStartAboveSWL
Berm height i.e. height above SWL of start of depositional Dean profile.
Definition simulation.h:960
int m_nSavGolCoastPoly
The order of the coastline profile smoothing polynomial if Savitzky-Golay smoothing is used (usually ...
Definition simulation.h:477
bool m_bSeaDepthSave
Save sea depth raster GIS files?
Definition simulation.h:111
bool m_bWaveAngleAndHeightSave
Save wave angle and wave height raster GIS files?
Definition simulation.h:129
double m_dNotchBaseBelowSWL
Notch base below SWL (m)
Definition simulation.h:918
string m_strInitialBasementDEMFile
Name of initial basement DEM file.
int m_nRunUpEquation
The run-up equation used TODO 007.
Definition simulation.h:582
bool m_bWorldFile
Write a GIS World file?
Definition simulation.h:387
static string strTrimRight(string const *)
Trims whitespace from the right side of a string, does not change the original string.
Definition utils.cpp:2387
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:897
double m_dFineErodibility
The relative erodibility (0- 1) of fine unconsolidated beach sediment.
Definition simulation.h:792
double m_dBreakingWaveHeightDepthRatio
Breaking wave height-to-depth ratio.
Definition simulation.h:756
double m_dCoastNormalSpacing
Average spacing of the coastline-normal profiles, in m.
Definition simulation.h:825
bool m_bHaveWaveStationData
Do we have wave station data?
Definition simulation.h:393
double m_dSeaWaterDensity
Density of sea water in kg/m**3.
Definition simulation.h:705
int m_nSavGolCliffEdgePoly
The order of the cliff edge smoothing polynomial if Savitzky-Golay smoothing is used (usually 2 or 4,...
Definition simulation.h:486
double m_dR
Coast platform resistance to erosion R, see Walkden & Hall, 2011.
Definition simulation.h:774
bool m_bRasterNormalProfileSave
Save rasterized coastline-normal profiles GIS files?
Definition simulation.h:219
bool m_bActiveZoneSave
Save active zone raster GIS files?
Definition simulation.h:222
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:360
bool m_bSedimentInputAtCoast
Do we have sediment input at the coast?
Definition simulation.h:402
int m_nCliffEdgeSmooth
Which method to use for cliff edge smoothing.
Definition simulation.h:480
double m_dCliffErosionResistance
Resistance of cliff to notch erosion.
Definition simulation.h:912
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:780
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:255
bool m_bMeanWaveEnergySave
Save mean wave energy raster GIS files?
Definition simulation.h:141
double m_dKLS
Transport parameter KLS in the CERC equation.
Definition simulation.h:810
int m_nWavePropagationModel
The wave propagation model used. Possible values are WAVE_MODEL_CSHORE and WAVE_MODEL_COVE.
Definition simulation.h:555
double m_dAllCellsDeepWaterWaveAngle
Deep water wave angle for all sea cells.
Definition simulation.h:762
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:289
bool m_bCoastCurvatureSave
Save coastline-curvature vector GIS files?
Definition simulation.h:282
int m_nCliffEdgeSmoothWindow
The size of the window used for cliff edge smoothing. Must be an odd number.
Definition simulation.h:483
int m_nDeepWaterWaveDataNumTimeSteps
The duration of data for deep water waves, expressed as a number of timesteps.
Definition simulation.h:576
double m_dFinalMeanSWL
The end-of-simulation still water (m), is same as m_dInitialMeanSWL unless SWL changes.
Definition simulation.h:711
bool m_bRasterWaveFloodLineSave
Are we saving the raster wave flood line? TODO 007.
Definition simulation.h:432
bool m_bBreakingWaveHeightSave
Save breaking wave height raster GIS files?
Definition simulation.h:144
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:687
bool m_bPolygonNodeSave
Save polygon node vector GIS files?
Definition simulation.h:285
bool m_bOmitSearchNorthEdge
Omit the north edge of the grid from coast-end searches?
Definition simulation.h:354
bool m_bFloodSetupSurgeTSSave
Save the flood setup surge time series file? TODO 007 Does this work correctly?
Definition simulation.h:330
bool m_bTotalPotentialPlatformErosionSave
Save total potential shore platform erosion raster GIS files?
Definition simulation.h:156
bool m_bSetupSurgeFloodMaskSave
Are we saving the setup surge flood mask? TODO 007.
Definition simulation.h:426
bool m_bWaveEnergySinceCollapseSave
Save wave energy since cliff collapse raster GIS files?
Definition simulation.h:138
double m_dD50Coarse
The D50 for coarse sediment.
Definition simulation.h:783
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:162
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:2699
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:450
int m_nSimStartMonth
Start date of the simulation (month)
Definition simulation.h:570
bool m_bSuspSedSave
Save suspended sediment raster GIS files?
Definition simulation.h:192
double m_dMinCliffTalusHeightFrac
Minimum height of the landward end of cliff collapse talus, as a fraction of cliff elevation.
Definition simulation.h:930
vector< string > m_VstrGDALIUSDriverDesc
bool m_bPolygonBoundarySave
Save polygon boundary vector GIS files?
Definition simulation.h:288
bool bDetectFileFormat(string const &strFileName, bool &bIsYaml)
Detects whether the input file is in YAML or .dat format.
bool m_bStormSurgeSave
Are we saving the storm surge? TODO 007.
Definition simulation.h:420
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:153
vector< CSedInputEvent * > m_pVSedInputEvent
Sediment input events.
int m_nSimStartMin
Start time of the simulation (minutes)
Definition simulation.h:561
bool bReadIniFile(void)
The bReadIniFile member function reads the initialization file.
bool m_bHaveFineSediment
Does this simulation consider fine-sized sediment?
Definition simulation.h:84
double m_dCliffDepositionA
Scale parameter A for cliff deposition (m^(1/3)), may be zero for auto-calculation.
Definition simulation.h:921
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:318
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:168
vector< string > m_VstrGDALIUSDataType
GDAL data type for the initial unconsolidated sand sediment GIS data.
bool bApplyConfiguration(CConfiguration const &config)
Applies configuration values to simulation member variables.
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:441
bool m_bSeaMaskSave
Save sea mask raster GIS files?
Definition simulation.h:243
bool m_bInterventionClassSave
Save intervention class raster GIS files?
Definition simulation.h:186
int m_nSimStartYear
Start date of the simulation (year)
Definition simulation.h:573
bool m_bTotalActualBeachErosionSave
Save total actual (supply-limited) beach (unconsolidated sediment) erosion raster GIS files?
Definition simulation.h:171
bool m_bRasterCoastlineSave
Save rasterized coastline GIS files?
Definition simulation.h:216
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:2352
bool m_bInterventionHeightSave
Save intervention height raster GIS files?
Definition simulation.h:189
int m_nCoastCurvatureMovingWindowSize
WHAT IS THOS FOR?
Definition simulation.h:588
bool m_bRiverineFlooding
Are we doing flooding? TODO 007.
Definition simulation.h:414
bool m_bSandConsSedSave
Save sand consolidated sediment raster GIS files?
Definition simulation.h:210
bool m_bSedimentInputEventSave
Save sediment inut data?
Definition simulation.h:408
bool m_bHaveCoarseSediment
Does this simulation consider coarse-sized sediment?
Definition simulation.h:90
double m_dRegularSaveInterval
The interval between regular saves, in hours.
Definition simulation.h:690
bool m_bPolygonUnconsSedGainOrLossSave
Save polygon unconsolidated sediment gain or loss raster GIS files?
Definition simulation.h:264
double m_dTimeStep
The length of an iteration (a time step) in hours.
Definition simulation.h:681
bool m_bCliffCollapseDepositionTSSave
Save the cliff collapse deposition time series file?
Definition simulation.h:312
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:135
double m_dCoastNormalRandSpacingFactor
Random factor for spacing of along-coast normals.
Definition simulation.h:957
double m_dMaxUserInputWaveHeight
Maximum deep water wave height.
Definition simulation.h:768
vector< double > m_VdSliceElev
Elevations for raster slice output.
bool m_bBeachProtectionSave
Save beach protection raster GIS files>
Definition simulation.h:147
bool m_bDoBeachSedimentTransport
Simulate unconsolidated sediment (beach) transport?
Definition simulation.h:372
bool m_bFineConsSedSave
Save fine consolidated sediment raster GIS files?
Definition simulation.h:207
bool m_bShadowDowndriftBoundarySave
Save wave shadow downdrift boundary vector GIS files?
Definition simulation.h:297
int m_nCoastSmooth
Which method to use for coast smoothing.
Definition simulation.h:471
bool m_bDeepWaterWavePeriodSave
Save deep water wave period raster GIS files?
Definition simulation.h:258
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:324
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:213
bool m_bSeaAreaTSSave
Save the sea area time series file?
Definition simulation.h:300
bool m_bScaleRasterOutput
Scale raster output?
Definition simulation.h:384
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:777
unsigned long m_ulRandSeed[NUMBER_OF_RNGS]
A seed for each of the random number generators.
Definition simulation.h:609
bool m_bOmitSearchSouthEdge
Omit the south edge of the grid from coast-end searches?
Definition simulation.h:357
bool m_bBeachMaskSave
Save beach mask raster GIS files?
Definition simulation.h:246
bool m_bSlopeSave
Save slope raster grids?
Definition simulation.h:102
bool m_bAvgSuspSedSave
Save average suspended sediment raster GIS files?
Definition simulation.h:195
double m_dBeachSedimentDensity
The density of unconsolidated beach sediment (kg/m**3)
Definition simulation.h:786
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:678
bool m_bCSVPerTimestepResults
Output per-timestep results in CSV format instead of fixed-width?
Definition simulation.h:348
double m_dCliffSlopeLimit
Slope limit for cliff toe detection.
Definition simulation.h:489
vector< double > m_VdThisIterDeepWaterWaveStationAngle
This-iteration wave orientation at deep water wave station.
bool m_bOutputProfileData
Output profile data?
Definition simulation.h:339
vector< string > m_VstrGDALIUCDriverDesc
double m_dMaxBeachElevAboveSWL
Maximum elevation of beach above SWL (m)
Definition simulation.h:909
bool m_bTotCliffCollapseDepositionSave
Save total cliff collapse deposition raster GIS files?
Definition simulation.h:234
double m_dAllCellsDeepWaterWavePeriod
Deep water wave period for all sea cells.
Definition simulation.h:765
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:693
double m_dProfileMaxSlope
Maximum slope on coastline-normal profiles.
Definition simulation.h:906
int m_nProfileSmoothWindow
The size of the window used for running-mean coast-normal profile smoothing (must be odd)
Definition simulation.h:492
bool m_bDoCliffCollapse
Simulate cliff collapse?
Definition simulation.h:369
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:429
bool m_bWaveSetupSave
Are we saving the wave setup? TODO 007.
Definition simulation.h:417
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:249
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:309
bool m_bPotentialPlatformErosionSave
Save potential shore platform erosion raster GIS files?
Definition simulation.h:150
double m_dDurationUnitsMult
Multiplier for duration units, to convert to hours.
Definition simulation.h:645
bool m_bFloodSWLSetupSurgeRunupLine
Are we saving the flood still water level setup surge runup line? TODO 007.
Definition simulation.h:447
bool m_bOutputParallelProfileData
Output parallel profile data?
Definition simulation.h:342
double m_dKamphuis
Transport parameter for the Kamphuis equation.
Definition simulation.h:813
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:2473
bool m_bOutputErosionPotentialData
Output erosion potential data?
Definition simulation.h:345
bool m_bCliffNotchSave
Save cliff notch incision depth vector GIS files?
Definition simulation.h:291
bool m_bVectorWaveFloodLineSave
Are we saving the vector wave flood line? TODO 007.
Definition simulation.h:435
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:123
bool m_bOmitSearchEastEdge
Omit the east edge of the grid from coast-end searches?
Definition simulation.h:363
bool m_bLocalSlopeSave
Save local slope raster GIS files?
Definition simulation.h:183
Simple YAML node class to represent parsed values.
Definition yaml_parser.h:39
bool IsSequence() const
vector< string > GetStringSequence() const
string GetValue() const
vector< CYamlNode > GetSequence() const
bool HasChild(string const &strKey) const
bool GetBoolValue(bool bDefault=false) const
double GetDoubleValue(double dDefault=0.0) const
CYamlNode GetChild(string const &strKey) const
int GetIntValue(int nDefault=0) const
Simple YAML parser class.
Definition yaml_parser.h:70
string GetError() const
bool bParseFile(string const &strFileName)
CYamlNode GetRoot() const
This file contains global definitions for CoastalME.
string const VECTOR_FLOOD_SWL_SETUP_SURGE_LINE_CODE
Definition cme.h:1178
string const TIME_SERIES_CLIFF_COLLAPSE_DEPOSITION_CODE
Definition cme.h:1222
string const TIME_SERIES_SUSPENDED_SEDIMENT_CODE
Definition cme.h:1237
string const RASTER_POTENTIAL_PLATFORM_EROSION_MASK_CODE
Definition cme.h:970
int const SMOOTH_NONE
Definition cme.h:781
int const WAVE_MODEL_COVE
Definition cme.h:791
int const RTN_ERR_READING_SEDIMENT_INPUT_EVENT
Definition cme.h:756
double const TOLERANCE
Definition cme.h:823
string const RASTER_CLIFF_COLLAPSE_EROSION_FINE_CODE
Definition cme.h:1020
string const TIME_SERIES_PLATFORM_EROSION_CODE
Definition cme.h:1216
string const RASTER_COARSE_CONS_CODE
Definition cme.h:1012
string const VECTOR_POLYGON_NODE_CODE
Definition cme.h:1156
string const RASTER_USUAL_OUTPUT_CODE
Definition cme.h:936
string const RASTER_DEEP_WATER_WAVE_ORIENTATION_CODE
Definition cme.h:1048
string const RASTER_DEEP_WATER_WAVE_HEIGHT_CODE
Definition cme.h:1050
string const TIME_SERIES_FLOOD_SETUP_SURGE_RUNUP_CODE
Definition cme.h:1243
string const RASTER_SLOPE_CODE
Definition cme.h:946
string const VECTOR_ALL_OUTPUT_CODE
Definition cme.h:1133
string const VECTOR_FLOOD_SWL_SETUP_SURGE_RUNUP_LINE_CODE
Definition cme.h:1180
string const RASTER_TOTAL_CLIFF_COLLAPSE_DEPOSITION_SAND_CODE
Definition cme.h:1036
string const RASTER_ACTIVE_ZONE_CODE
Definition cme.h:1018
int const NO_LOG_FILE
Definition cme.h:489
string const RASTER_CLIFF_COLLAPSE_EROSION_COARSE_CODE
Definition cme.h:1024
string const RASTER_SAND_CONS_CODE
Definition cme.h:1010
string const TIME_SERIES_FLOOD_SETUP_SURGE_CODE
Definition cme.h:1240
int const RTN_ERR_SCAPE_SHAPE_FUNCTION_FILE
Definition cme.h:702
int const UNCONS_SEDIMENT_EQUATION_KAMPHUIS
Definition cme.h:796
string const ERR
Definition cme.h:903
string const RASTER_COAST_NORMAL_CODE
Definition cme.h:1016
int const DEFAULT_PROFILE_SPACING
Definition cme.h:485
string const VECTOR_CLIFF_EDGE_CODE
Definition cme.h:1138
string const SCAPE_DIR
Definition cme.h:896
string const LOGEXT
Definition cme.h:928
string const RASTER_AVG_SUSP_SED_CODE
Definition cme.h:1000
string const RASTER_COAST_CODE
Definition cme.h:1014
string const RASTER_SEDIMENT_INPUT_EVENT_CODE
Definition cme.h:1058
string const VECTOR_WAVE_ENERGY_SINCE_COLLAPSE_CODE
Definition cme.h:1150
string const RASTER_WAVE_ORIENTATION_CODE
Definition cme.h:960
string const VECTOR_RUN_UP_CODE
Definition cme.h:1172
string const RASTER_ALL_OUTPUT_CODE
Definition cme.h:937
string const RASTER_CLIFF_COLLAPSE_EROSION_SAND_CODE
Definition cme.h:1022
string const RASTER_POLYGON_UPDRIFT_OR_DOWNDRIFT_CODE
Definition cme.h:1054
string const RASTER_WAVE_FLOOD_LINE_CODE
Definition cme.h:1064
int const WAVE_MODEL_CSHORE
Definition cme.h:792
string const RASTER_COARSE_UNCONS_CODE
Definition cme.h:1006
string const OUTEXT
Definition cme.h:927
char const PATH_SEPARATOR
Definition cme.h:449
string const VECTOR_INVALID_NORMALS_CODE
Definition cme.h:1142
string const RASTER_BASEMENT_ELEVATION_CODE
Definition cme.h:942
string const RASTER_WAVE_HEIGHT_CODE
Definition cme.h:956
string const RASTER_CLIFF_COLLAPSE_DEPOSITION_COARSE_CODE
Definition cme.h:1034
char const COMMA
Definition cme.h:447
string const RASTER_INTERVENTION_CLASS_CODE
Definition cme.h:994
string const RASTER_POTENTIAL_PLATFORM_EROSION_CODE
Definition cme.h:972
string const RASTER_POTENTIAL_BEACH_EROSION_CODE
Definition cme.h:980
string const VECTOR_MEAN_WAVE_ENERGY_CODE
Definition cme.h:1152
string const VECTOR_STORM_SURGE_CODE
Definition cme.h:1170
int const TIME_UNKNOWN
Definition cme.h:520
double const D50_SAND_DEFAULT
Definition cme.h:808
string const RASTER_TOTAL_CLIFF_COLLAPSE_EROSION_COARSE_CODE
Definition cme.h:1030
bool bFPIsEqual(const T d1, const T d2, const T dEpsilon)
Definition cme.h:1304
string const VECTOR_USUAL_OUTPUT_CODE
Definition cme.h:1134
char const QUOTE1
Definition cme.h:450
string const RASTER_WAVE_PERIOD_CODE
Definition cme.h:962
int const GRID_EDGE_CLOSED
Definition cme.h:786
string const TIME_SERIES_CLIFF_COLLAPSE_NET_CODE
Definition cme.h:1225
int const GRID_EDGE_RECIRCULATE
Definition cme.h:788
int const RTN_ERR_OPEN_DEEP_WATER_WAVE_DATA
Definition cme.h:753
string const RASTER_TOTAL_ACTUAL_BEACH_EROSION_CODE
Definition cme.h:986
string const VECTOR_NORMALS_CODE
Definition cme.h:1140
string const RASTER_BEACH_DEPOSITION_CODE
Definition cme.h:988
string const RASTER_SHADOW_ZONE_CODE
Definition cme.h:1044
string const RASTER_TOTAL_BEACH_DEPOSITION_CODE
Definition cme.h:990
int const SAVEMAX
Definition cme.h:464
string const VECTOR_DEEP_WATER_WAVE_ANGLE_AND_HEIGHT_CODE
Definition cme.h:1166
int const NUMBER_OF_RNGS
Definition cme.h:463
double const D50_COARSE_DEFAULT
Definition cme.h:809
string const RASTER_BEACH_PROTECTION_CODE
Definition cme.h:968
string const RASTER_TOTAL_POTENTIAL_PLATFORM_EROSION_CODE
Definition cme.h:976
string const TIME_SERIES_CLIFF_COLLAPSE_EROSION_CODE
Definition cme.h:1219
string const RASTER_BEACH_MASK_CODE
Definition cme.h:966
string const RASTER_AVG_WAVE_HEIGHT_CODE
Definition cme.h:958
string const RASTER_SETUP_SURGE_FLOOD_MASK_CODE
Definition cme.h:1060
string const TIME_SERIES_BEACH_EROSION_CODE
Definition cme.h:1228
string const RASTER_TOTAL_POTENTIAL_BEACH_EROSION_CODE
Definition cme.h:984
int const SMOOTH_SAVITZKY_GOLAY
Definition cme.h:783
string const RASTER_AVG_SEA_DEPTH_CODE
Definition cme.h:952
string const RASTER_SAND_UNCONS_CODE
Definition cme.h:1004
string const RASTER_CLIFF_CODE
Definition cme.h:948
string const READING_FILE_LOCATIONS
Definition cme.h:863
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:1160
string const RASTER_SETUP_SURGE_RUNUP_FLOOD_MASK_CODE
Definition cme.h:1062
string const RASTER_LANDFORM_CODE
Definition cme.h:992
string const RASTER_TOTAL_ACTUAL_PLATFORM_EROSION_CODE
Definition cme.h:978
int const RTN_ERR_READING_DEEP_WATER_WAVE_DATA
Definition cme.h:754
string const RASTER_ACTUAL_PLATFORM_EROSION_CODE
Definition cme.h:974
string const VECTOR_BREAKING_WAVE_HEIGHT_CODE
Definition cme.h:1154
unsigned long const SEDIMENT_INPUT_EVENT_ERROR
Definition cme.h:803
int const RTN_ERR_TIDEDATAFILE
Definition cme.h:703
string const RASTER_SUSP_SED_CODE
Definition cme.h:998
string const VECTOR_SHADOW_BOUNDARY_CODE
Definition cme.h:1162
string const VECTOR_COAST_CURVATURE_CODE
Definition cme.h:1144
double const DBL_NODATA
Definition cme.h:834
double const D50_FINE_DEFAULT
Definition cme.h:807
string const VECTOR_ALL_RIVER_FLOOD_OUTPUT_CODE
Definition cme.h:1135
string const CME_INI
Definition cme.h:838
string const NOTE
Definition cme.h:905
string const RASTER_CLIFF_COLLAPSE_DEPOSITION_SAND_CODE
Definition cme.h:1032
string const RASTER_SEA_DEPTH_CODE
Definition cme.h:950
string const RASTER_LOCAL_SLOPE_CODE
Definition cme.h:944
string const RASTER_FINE_CONS_CODE
Definition cme.h:1008
char const QUOTE2
Definition cme.h:451
string const VECTOR_POLYGON_BOUNDARY_CODE
Definition cme.h:1158
string const RASTER_FINE_UNCONS_CODE
Definition cme.h:1002
string const TIME_SERIES_STILL_WATER_LEVEL_CODE
Definition cme.h:1213
string const RASTER_SEDIMENT_TOP_CODE
Definition cme.h:938
int const UNCONS_SEDIMENT_EQUATION_CERC
Definition cme.h:795
string const RASTER_POLYGON_GAIN_OR_LOSS_CODE
Definition cme.h:1056
char const TILDE
Definition cme.h:454
string const RASTER_TOTAL_CLIFF_COLLAPSE_EROSION_SAND_CODE
Definition cme.h:1028
string const VECTOR_AVG_WAVE_ANGLE_AND_HEIGHT_CODE
Definition cme.h:1149
string const TIME_SERIES_BEACH_CHANGE_NET_CODE
Definition cme.h:1234
string const RASTER_INTERVENTION_HEIGHT_CODE
Definition cme.h:996
string const VECTOR_FLOOD_LINE_CODE
Definition cme.h:1174
string const TIME_SERIES_BEACH_DEPOSITION_CODE
Definition cme.h:1231
string const VECTOR_FLOOD_SWL_SETUP_LINE_CODE
Definition cme.h:1176
string const VECTOR_WAVE_SETUP_CODE
Definition cme.h:1168
string const RASTER_POLYGON_CODE
Definition cme.h:1040
string const RASTER_ACTUAL_BEACH_EROSION_CODE
Definition cme.h:982
string const RASTER_INUNDATION_MASK_CODE
Definition cme.h:954
string const VECTOR_COAST_CODE
Definition cme.h:1136
char const COLON
Definition cme.h:446
string const RASTER_TOTAL_CLIFF_COLLAPSE_EROSION_FINE_CODE
Definition cme.h:1026
string const RASTER_AVG_WAVE_ORIENTATION_CODE
Definition cme.h:964
string const SCAPE_SHAPE_FUNCTION_FILE
Definition cme.h:897
string const TIME_SERIES_SEA_AREA_CODE
Definition cme.h:1210
string const RASTER_DEEP_WATER_WAVE_PERIOD_CODE
Definition cme.h:1052
string const RASTER_TOTAL_CLIFF_COLLAPSE_DEPOSITION_COARSE_CODE
Definition cme.h:1038
string const RASTER_TOP_CODE
Definition cme.h:940
char const SPACE
Definition cme.h:453
string const VECTOR_DOWNDRIFT_BOUNDARY_CODE
Definition cme.h:1164
Unified configuration class for CoastalME simulation parameters.
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....
Simple YAML parser for CoastalME configuration files.