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
18the terms of the GNU General Public License as published by the Free Software
19Foundation; either version 3 of the License, or (at your option) any later
20version.
21
22 This program is distributed in the hope that it will be useful, but WITHOUT
23ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
24FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
25
26 You should have received a copy of the GNU General Public License along with
27this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave,
28Cambridge, MA 02139, USA.
29
30==============================================================================================================================*/
31#include <cstdio>
32
33#include <cstdlib>
34using std::atol;
35using std::strtod;
36
37#include <cctype>
38using std::isdigit;
39using std::tolower;
40
41#include <cmath>
42using std::floor;
43
44#include <fstream>
45using std::ifstream;
46
47#include <iostream>
48using std::cerr;
49using std::cout;
50using std::endl;
51using std::ios;
52
53#include <string>
54using std::to_string;
55
56#include <algorithm>
57using std::find;
58using std::sort;
59using std::transform;
60
61#include <random>
62using std::random_device;
63
64#include "cme.h"
65#include "configuration.h"
67#include "simulation.h"
68#include "yaml_parser.h"
69
70//===============================================================================================================================
72//===============================================================================================================================
74{
75 // Check if user has supplied home directory
76 if (m_strCMEIni.empty())
77 // if not use the cme executable directory to find cme.ini
79
80 else
81 {
82 // if user has supplied home directory replace cme run directory with user
83 // supplied dir
85 }
86
87 m_strCMEIni.append(CME_INI);
88
89 // The .ini file is assumed to be in the CoastalME executable's directory
90 string const strFilePathName(m_strCMEIni);
91
92 // Tell the user what is happening
93 cout << READING_FILE_LOCATIONS << strFilePathName << endl;
94
95 // Create an ifstream object
96 ifstream InStream;
97
98 // Try to open .ini file for input
99 InStream.open(strFilePathName.c_str(), ios::in);
100
101 // Did it open OK?
102 if (! InStream.is_open())
103 {
104 // Error: cannot open .ini file for input
105 cerr << ERR << "cannot open " << strFilePathName << " for input" << endl;
106 return false;
107 }
108
109 int nLine = 0;
110 int i = 0;
111 string strRec, strErr;
112
113 while (getline(InStream, strRec))
114 {
115 nLine++;
116
117 // Trim off leading and trailing whitespace
118 strRec = strTrim(&strRec);
119
120 // If it is a blank line or a comment then ignore it
121 if ((! strRec.empty()) && (strRec[0] != QUOTE1) && (strRec[0] != QUOTE2))
122 {
123 // It isn't so increment counter
124 i++;
125
126 // Find the colon: note that lines MUST have a colon separating data from
127 // leading description portion
128 size_t nPos = strRec.find(COLON);
129
130 if (nPos == string::npos)
131 {
132 // Error: badly formatted (no colon)
133 cerr << ERR << "on line " << nLine << ": badly formatted (no ':') in "
134 << strFilePathName << endl
135 << "'" << strRec << "'" << endl;
136 return false;
137 }
138
139 if (nPos == strRec.size() - 1)
140 {
141 // Error: badly formatted (colon with nothing following)
142 cerr << ERR << "on line " << nLine
143 << ": badly formatted (nothing following ':') in "
144 << strFilePathName << endl
145 << "'" << strRec << "'" << endl;
146 return false;
147 }
148
149 // Strip off leading portion (the bit up to and including the colon)
150 string strRH = strRec.erase(0, nPos + 1);
151
152 // Remove leading whitespace
153 strRH = strTrimLeft(&strRH);
154
155 // Look for a trailing comment, if found then terminate string at that
156 // point and trim off any trailing whitespace
157 nPos = strRH.rfind(QUOTE1);
158
159 if (nPos != string::npos)
160 strRH.resize(nPos);
161
162 nPos = strRH.rfind(QUOTE2);
163
164 if (nPos != string::npos)
165 strRH.resize(nPos);
166
167 // Remove trailing whitespace
168 strRH = strTrimRight(&strRH);
169
170 switch (i)
171 {
172 case 1:
173 // The main input run-data filename
174 if (strRH.empty())
175 strErr =
176 "line " + to_string(nLine) + ": path and name of main datafile";
177
178 else
179 {
180 // First check that we don't already have an input run-data filename,
181 // e.g. one entered on the command-line
182 if (m_strDataPathName.empty())
183 {
184 // We don't: so first check for leading slash, or leading Unix home
185 // dir symbol, or occurrence of a drive letter
186 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) ||
187 (strRH[1] == COLON))
188 // It has an absolute path, so use it 'as is'
189 m_strDataPathName = strRH;
190
191 else
192 {
193 // It has a relative path, so prepend the CoastalME dir
195 m_strDataPathName.append(strRH);
196 }
197 }
198 }
199
200 break;
201
202 case 2:
203 // Path for CoastalME output
204 if (strRH.empty())
205 strErr = "line " + to_string(nLine) + ": path for CoastalME output";
206
207 else
208 {
209 // Check for trailing slash on CoastalME output directory name (is
210 // vital)
211 if (strRH[strRH.size() - 1] != PATH_SEPARATOR)
212 strRH.push_back(PATH_SEPARATOR);
213
214 // Now check for leading slash, or leading Unix home dir symbol, or
215 // occurrence of a drive letter
216 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) ||
217 (strRH[1] == COLON))
218 // It is an absolute path, so use it 'as is'
219 m_strOutPath = strRH;
220
221 else
222 {
223 // It is a relative path, so prepend the CoastalME dir
225 m_strOutPath.append(strRH);
226 }
227 }
228
229 break;
230
231 case 3:
232 // Email address, only useful if running under Linux/Unix
233 if (! strRH.empty())
234 {
235 // Something was entered, do rudimentary check for valid email address
236 if (strRH.find('@') == string::npos)
237 strErr =
238 "line " + to_string(nLine) + ": email address for messages";
239
240 else
241 m_strMailAddress = strRH;
242 }
243
244 break;
245 }
246
247 // Did an error occur?
248 if (! strErr.empty())
249 {
250 // Error in input to initialisation file
251 cerr << ERR << "reading " << strErr << " in " << strFilePathName << endl
252 << "'" << strRec << "'" << endl;
253 InStream.close();
254
255 return false;
256 }
257 }
258 }
259
260 InStream.close();
261 return true;
262}
263
264//===============================================================================================================================
266//===============================================================================================================================
267bool CSimulation::bDetectFileFormat(string const &strFileName, bool &bIsYaml)
268{
269 bIsYaml = false;
270
271 // First check command-line flag
273 {
274 bIsYaml = true;
275 return true;
276 }
277
278 // Check file extension
279 size_t nDotPos = strFileName.find_last_of('.');
280 if (nDotPos != string::npos)
281 {
282 string strExt = strFileName.substr(nDotPos + 1);
283 std::transform(strExt.begin(), strExt.end(), strExt.begin(), ::tolower);
284
285 if (strExt == "yaml" || strExt == "yml")
286 {
287 bIsYaml = true;
288 return true;
289 }
290 else if (strExt == "dat")
291 {
292 bIsYaml = false;
293 return true;
294 }
295 }
296
297 // Default to .dat format if extension is ambiguous
298 bIsYaml = false;
299 return true;
300}
301
302//===============================================================================================================================
304// TODO 000 Should user input be split in two main files: one for
305// frequently-changed things, one for rarely-changed things? If so, what should
306// go into each file ('testing only' OK, but what else?)
307//===============================================================================================================================
309{
310 // Detect file format
311 bool bIsYaml;
312 if (! bDetectFileFormat(m_strDataPathName, bIsYaml))
313 {
314 cerr << ERR << "failed to detect file format for " << m_strDataPathName
315 << endl;
316 return false;
317 }
318
319 // Use appropriate parser based on format
320 if (bIsYaml)
321 {
322 return bReadYamlFile();
323 }
324 // Continue with original .dat file parsing
325 // Create an ifstream object
326 ifstream InStream;
327
328 // Try to open run details file for input
329 InStream.open(m_strDataPathName.c_str(), ios::in);
330
331 // Did it open OK?
332 if (! InStream.is_open())
333 {
334 // Error: cannot open run details file for input
335 cerr << ERR << "cannot open " << m_strDataPathName << " for input"
336 << endl;
337 return false;
338 }
339
340 int nLine = 0;
341 int i = 0;
342 size_t nPos;
343 string strRec, strErr;
344
345 while (getline(InStream, strRec))
346 {
347 nLine++;
348
349 // Trim off leading and trailing whitespace
350 strRec = strTrim(&strRec);
351
352 // If it is a blank line or a comment then ignore it
353 if ((! strRec.empty()) && (strRec[0] != QUOTE1) && (strRec[0] != QUOTE2))
354 {
355 // It isn't so increment counter
356 i++;
357
358 // Find the colon: note that lines MUST have a colon separating data
359 // from leading description portion
360 nPos = strRec.find(COLON);
361
362 if (nPos == string::npos)
363 {
364 // Error: badly formatted (no colon)
365 cerr << ERR << "on line " << to_string(nLine)
366 << "badly formatted (no ':') in " << m_strDataPathName << endl
367 << strRec << endl;
368 return false;
369 }
370
371 // Strip off leading portion (the bit up to and including the colon)
372 string strRH = strRec.erase(0, nPos + 1);
373
374 // Remove leading whitespace after the colon
375 strRH = strTrimLeft(&strRH);
376
377 // Look for trailing comments, if found then terminate string at that
378 // point and trim off any trailing whitespace
379 bool bFound = true;
380
381 while (bFound)
382 {
383 bFound = false;
384
385 nPos = strRH.rfind(QUOTE1);
386
387 if (nPos != string::npos)
388 {
389 strRH.resize(nPos);
390 bFound = true;
391 }
392
393 nPos = strRH.rfind(QUOTE2);
394
395 if (nPos != string::npos)
396 {
397 strRH.resize(nPos);
398 bFound = true;
399 }
400
401 // Trim trailing spaces
402 strRH = strTrimRight(&strRH);
403 }
404
405#ifdef _WIN32
406 // For Windows, make sure has backslashes, not Unix-style slashes
407 strRH = pstrChangeToBackslash(&strRH);
408#endif
409 bool bFirst = true;
410 int nRet = 0;
411 int nHour = 0;
412 int nMin = 0;
413 int nSec = 0;
414 int nDay = 0;
415 int nMonth = 0;
416 int nYear = 0;
417 double dMult = 0;
418 string strTmp;
419 vector<string> VstrTmp;
420
421 switch (i)
422 {
423 // ---------------------------------------------- Run Information
424 // -----------------------------------------------------
425 case 1:
426 // Text output file names, don't change case
427 if (strRH.empty())
428 strErr = "line " + to_string(nLine) + ": output file names";
429
430 else
431 {
432 m_strRunName = strRH;
433
435 m_strOutFile.append(strRH);
436 m_strOutFile.append(OUTEXT);
437
439 m_strLogFile.append(strRH);
440 m_strLogFile.append(LOGEXT);
441 }
442
443 break;
444
445 case 2:
446 // Content of log file, 0 = no log file, 1 = least detail, 3 = most
447 // detail
448 if (! bIsStringValidInt(strRH))
449 {
450 strErr = "line " + to_string(nLine) +
451 ": invalid integer for log file detail level '" + strRH +
452 "' in " + m_strDataPathName;
453 break;
454 }
455
456 m_nLogFileDetail = stoi(strRH);
457
460 strErr = "line " + to_string(nLine) + ": log file detail level";
461
462 break;
463
464 case 3:
465 // Output per-timestep results in CSV format?
466 strRH = strToLower(&strRH);
467
469
470 if (strRH.find('y') != string::npos)
472
473 break;
474
475 case 4:
476 // Get the start date/time of the simulation, format is [hh-mm-ss
477 // dd/mm/yyyy]
478 VstrTmp = VstrSplit(&strRH, SPACE);
479
480 // Both date and time here?
481 if (VstrTmp.size() < 2)
482 {
483 strErr =
484 "line " + to_string(nLine) +
485 ": must have both date and time for simulation start in '" +
486 m_strDataPathName + "'";
487 break;
488 }
489
490 // OK, first sort out the time
491 if (! bParseTime(&VstrTmp[0], nHour, nMin, nSec))
492 {
493 strErr = "line " + to_string(nLine) +
494 ": could not understand simulation start time in '" +
495 m_strDataPathName + "'";
496 break;
497 }
498
499 // Next sort out the date
500 if (! bParseDate(&VstrTmp[1], nDay, nMonth, nYear))
501 {
502 strErr = "line " + to_string(nLine) +
503 ": could not understand simulation start date in '" +
504 m_strDataPathName + "'";
505 break;
506 }
507
508 // Store simulation start time and date
509 m_nSimStartSec = nSec;
510 m_nSimStartMin = nMin;
511 m_nSimStartHour = nHour;
512 m_nSimStartDay = nDay;
513 m_nSimStartMonth = nMonth;
514 m_nSimStartYear = nYear;
515
516 break;
517
518 case 5:
519 // Duration of simulation (in hours, days, months, or years): sort out
520 // multiplier and user units, as used in the per-timestep output
521 strRH = strToLower(&strRH);
522
523 nRet = nDoSimulationTimeMultiplier(&strRH);
524
525 if (nRet != RTN_OK)
526 {
527 strErr = "line " + to_string(nLine) +
528 ": units for duration of simulation";
529 break;
530 }
531
532 // And now calculate the duration of the simulation in hours: first
533 // find whitespace between the number and the unit
534 nPos = strRH.rfind(SPACE);
535
536 if (nPos == string::npos)
537 {
538 strErr = "line " + to_string(nLine) +
539 ": format of duration simulation line";
540 break;
541 }
542
543 // Cut off rh bit of string
544 strRH.resize(nPos);
545
546 // Remove trailing spaces
547 strRH = strTrimRight(&strRH);
548
549 // Calculate the duration of the simulation in hours
550 m_dSimDuration = strtod(strRH.c_str(), NULL) * m_dDurationUnitsMult;
551
552 if (m_dSimDuration <= 0)
553 strErr = "line " + to_string(nLine) +
554 ": duration of simulation must be > 0";
555
556 break;
557
558 case 6:
559 // Timestep of simulation (in hours or days)
560 strRH = strToLower(&strRH);
561
562 dMult = dGetTimeMultiplier(&strRH);
563
564 if (static_cast<int>(dMult) == TIME_UNKNOWN)
565 {
566 strErr =
567 "line " + to_string(nLine) + ": units for simulation timestep";
568 break;
569 }
570
571 // we have the multiplier, now calculate the timestep in hours: look
572 // for the whitespace between the number and unit
573 nPos = strRH.rfind(SPACE);
574
575 if (nPos == string::npos)
576 {
577 strErr =
578 "line " + to_string(nLine) + ": format of simulation timestep";
579 break;
580 }
581
582 // cut off rh bit of string
583 strRH.resize(nPos);
584
585 // remove trailing spaces
586 strRH = strTrimRight(&strRH);
587
588 // Check that this is a valid double
589 if (! bIsStringValidDouble(strRH))
590 {
591 strErr = "line " + to_string(nLine) +
592 ": invalid floating point number for timestep '" + strRH +
593 "' in " + m_strDataPathName;
594 break;
595 }
596
597 m_dTimeStep = strtod(strRH.c_str(), NULL) * dMult; // in hours
598
599 if (m_dTimeStep <= 0)
600 strErr = "line " + to_string(nLine) +
601 ": timestep of simulation must be > 0";
602
604 strErr = "line " + to_string(nLine) +
605 ": timestep of simulation must be < the duration of the "
606 "simulation";
607
608 break;
609
610 case 7:
611 {
612 // Save interval(s) - can handle multiple groups with different units
613 // if groups are comma-separated e.g., "6 12 24 48 hours, 1 2 6
614 // months, 1 years"
615 strRH = strToLower(&strRH);
616
617 // Split by commas to handle multiple unit groups
618 string const strOriginal = strRH;
619 size_t nCommaPos = 0;
620
621 m_bSaveRegular = false; // Start with assumption of multiple values
622
623 do
624 {
625 string strGroup;
626 size_t const nNextComma = strOriginal.find(',', nCommaPos);
627
628 if (nNextComma != string::npos)
629 {
630 strGroup = strOriginal.substr(nCommaPos, nNextComma - nCommaPos);
631 nCommaPos = nNextComma + 1;
632 }
633
634 else
635 {
636 strGroup = strOriginal.substr(nCommaPos);
637 nCommaPos = string::npos;
638 }
639
640 // Trim whitespace from group
641 strGroup = strTrimLeft(&strGroup);
642 strGroup = strTrimRight(&strGroup);
643
644 if (strGroup.empty())
645 continue;
646
647 // Get the multiplier for this group
648 dMult = dGetTimeMultiplier(&strGroup);
649
650 if (static_cast<int>(dMult) == TIME_UNKNOWN)
651 {
652 strErr = "line " + to_string(nLine) +
653 ": units for save intervals in group '" + strGroup + "'";
654 break;
655 }
656
657 // Remove the unit text from the end
658 size_t const nLastSpace = strGroup.rfind(SPACE);
659
660 if (nLastSpace == string::npos)
661 {
662 strErr = "line " + to_string(nLine) +
663 ": format of save times/intervals in group '" +
664 strGroup + "'";
665 break;
666 }
667
668 string strNumbers = strGroup.substr(0, nLastSpace);
669 strNumbers = strTrimRight(&strNumbers);
670
671 // Parse numbers in this group
672 size_t nSpacePos = 0;
673 strNumbers += SPACE; // Add trailing space to help parsing
674
675 do
676 {
677 size_t const nNextSpace = strNumbers.find(SPACE, nSpacePos);
678
679 if (nNextSpace == string::npos)
680 break;
681
682 string const strNumber =
683 strNumbers.substr(nSpacePos, nNextSpace - nSpacePos);
684
685 if (! strNumber.empty())
686 {
687 if (m_nUSave > static_cast<int>(SAVEMAX) - 1)
688 {
689 strErr =
690 "line " + to_string(nLine) + ": too many save intervals";
691 break;
692 }
693
694 double const dValue = strtod(strNumber.c_str(), NULL) * dMult;
695 m_dUSaveTime[m_nUSave++] = dValue;
696 }
697
698 nSpacePos = nNextSpace + 1;
699 } while (nSpacePos < strNumbers.length());
700
701 if (! strErr.empty())
702 break;
703 } while (nCommaPos != string::npos);
704
705 if (! strErr.empty())
706 break;
707
708 // Check if we only have one value (making it a regular interval)
709 if (m_nUSave == 1)
710 {
711 m_bSaveRegular = true;
713
715 strErr = "line " + to_string(nLine) +
716 ": save interval cannot be less than timestep";
717
718 else
720 }
721
722 else if (m_nUSave > 1)
723 {
724 // Multiple values - sort them and validate
726
727 if (m_dUSaveTime[0] < m_dTimeStep)
728 {
729 strErr = "line " + to_string(nLine) +
730 ": first save time cannot be less than timestep";
731 break;
732 }
733
734 // Put a dummy save interval as the last entry in the array
736 }
737
738 else
739 {
740 strErr = "line " + to_string(nLine) + ": no save times specified";
741 }
742 }
743 break;
744
745 case 8:
746 // Random number seed(s)
747 if (strRH.empty())
748 {
749 // User didn't specify a random number seed, so seed with a real
750 // random value, if available
751 random_device rdev;
752 m_ulRandSeed[0] = rdev();
753
754 // Only one seed specified, so make all seeds the same
755 for (int n = 1; n < NUMBER_OF_RNGS; n++)
756 m_ulRandSeed[n] = m_ulRandSeed[n - 1];
757 }
758
759 else
760 {
761 // User did specify at least one random number seed. Next find out
762 // whether we're dealing with a single seed or more than one: check
763 // for a space
764 nPos = strRH.find(SPACE);
765
766 if (nPos == string::npos)
767 {
768 // No space, so we have just one one number
769 m_ulRandSeed[0] = atol(strRH.c_str());
770
771 // Only one seed specified, so make all seeds the same
772 for (int n = 1; n < NUMBER_OF_RNGS; n++)
773 m_ulRandSeed[n] = m_ulRandSeed[n - 1];
774 }
775
776 else
777 {
778 // The user has supplied more than one random number seed
779 int n = 0;
780
781 do
782 {
783 // Get LH bit
784 strTmp = strRH.substr(0, nPos);
785 m_ulRandSeed[n++] = atol(strTmp.c_str());
786
787 if (n == NUMBER_OF_RNGS)
788 // All random number seeds read
789 break;
790
791 // We need more seeds, so get the RH bit
792 strRH = strRH.substr(nPos, strRH.size() - nPos);
793 strRH = strTrimLeft(&strRH);
794
795 if (strRH.size() == 0)
796 // No more seeds left to read
797 break;
798 } while (true);
799
800 // If we haven't filled all random number seeds, make all the
801 // remainder the same as the last one read
802 if (n < NUMBER_OF_RNGS - 1)
803 {
804 for (int m = n; m < NUMBER_OF_RNGS; m++)
806 }
807 }
808 }
809
810 break;
811
812 case 9:
813 // Max save digits for GIS output file names
814 if (! bIsStringValidInt(strRH))
815 {
816 strErr = "line " + to_string(nLine) +
817 ": invalid integer for max save digits for GIS output "
818 "file names '" +
819 strRH + "' in " + m_strDataPathName;
820 break;
821 }
822
823 m_nGISMaxSaveDigits = stoi(strRH);
824
825 if (m_nGISMaxSaveDigits < 2)
826 strErr = "line " + to_string(nLine) +
827 ": max save digits for GIS output file names must be > 1";
828
829 break;
830
831 case 10:
832 // Save digits for GIS output sequential or iteration number? [s =
833 // sequential, i = iteration]: s
834 if (strRH.empty())
835 strErr = "line " + to_string(nLine) +
836 ": must specify save digits for GIS output as sequential "
837 "or as iteration number";
838
839 else
840 {
841 // Convert to lower case
842 strRH = strToLower(&strRH);
843
844 if (strRH.find('s') != string::npos)
845 {
846 // First look for 's'
848 }
849
850 else if (strRH.find('i') != string::npos)
851 {
852 // Now look for 'i'
854 }
855
856 else
857 {
858 strErr = "line ";
859 strErr += to_string(nLine);
860 strErr +=
861 ": invalid code for save digits for GIS output save "
862 "number (must be s or i)";
863
864 break;
865 }
866 }
867
868 break;
869
870 case 11:
871 // Raster GIS files to output
872 if (strRH.empty())
873 {
874 strErr = "line ";
875 strErr += to_string(nLine);
876 strErr += ": must contain '";
877 strErr += RASTER_ALL_OUTPUT_CODE;
878 strErr += "', or '";
879 strErr += RASTER_USUAL_OUTPUT_CODE;
880 strErr += "', or at least one raster GIS output code";
881 }
882
883 else
884 {
885 // Convert to lower case
886 strRH = strToLower(&strRH);
887
888 if (strRH.find(RASTER_ALL_OUTPUT_CODE) != string::npos)
889 {
890 // Set switches for all GIS raster output. Some of these (e.g. all
891 // relating to fine sediment) are ignored if e.g. no fine sediment
892 // layers are read in
893 m_bSuspSedSave = true;
894 m_bAvgSuspSedSave = true;
896 m_bFineConsSedSave = true;
898 m_bSandConsSedSave = true;
902 m_bTopSurfSave = true;
903 m_bSeaDepthSave = true;
904 m_bWaveHeightSave = true;
905 m_bWaveAngleSave = true;
916 m_bLandformSave = true;
917 m_bLocalSlopeSave = true;
918 m_bSlopeSave = true;
919 m_bCliffSave = true;
920 m_bAvgSeaDepthSave = true;
922 m_bAvgWaveAngleSave = true;
924 m_bBasementElevSave = true;
927 m_bActiveZoneSave = true;
934 m_bSeaMaskSave = true;
935 m_bBeachMaskSave = true;
942 }
943
944 else if (strRH.find(RASTER_USUAL_OUTPUT_CODE) != string::npos)
945 {
946 // Set switches for usual GIS raster output. Again, some of these
947 // (e.g. all relating to fine sediment) are ignored if they are
948 // irrelevant
949 m_bSuspSedSave = true;
950 m_bAvgSuspSedSave = true;
952 m_bFineConsSedSave = true;
954 m_bSandConsSedSave = true;
958 m_bTopSurfSave = true;
959 m_bSeaDepthSave = true;
960 m_bWaveHeightSave = true;
961 m_bWaveAngleSave = true;
972 m_bLandformSave = true;
973 m_bLocalSlopeSave = true;
974 m_bSlopeSave = true;
976 m_bAvgWaveAngleSave = true;
978 m_bBasementElevSave = true;
979 m_bActiveZoneSave = true;
990 }
991 else
992 {
993 // We are not outputting either the "usual" or the "all"
994 // collections of raster GIS files, so set switches (and remove
995 // strings) for those optional files for which the user specified
996 // the code
997 if (strRH.find(RASTER_SEDIMENT_TOP_CODE) != string::npos)
998 {
1000 strRH = strRemoveSubstr(&strRH, &RASTER_SEDIMENT_TOP_CODE);
1001 }
1002
1003 if (strRH.find(RASTER_TOP_CODE) != string::npos)
1004 {
1005 m_bTopSurfSave = true;
1006 strRH = strRemoveSubstr(&strRH, &RASTER_TOP_CODE);
1007 }
1008
1009 if (strRH.find(RASTER_SEA_DEPTH_CODE) != string::npos)
1010 {
1011 m_bSeaDepthSave = true;
1012 strRH = strRemoveSubstr(&strRH, &RASTER_SEA_DEPTH_CODE);
1013 }
1014
1015 if (strRH.find(RASTER_WAVE_HEIGHT_CODE) != string::npos)
1016 {
1017 m_bWaveHeightSave = true;
1018 strRH = strRemoveSubstr(&strRH, &RASTER_WAVE_HEIGHT_CODE);
1019 }
1020
1021 if (strRH.find(RASTER_WAVE_ORIENTATION_CODE) != string::npos)
1022 {
1023 m_bWaveAngleSave = true;
1025 }
1026
1027 if (strRH.find(RASTER_WAVE_PERIOD_CODE) != string::npos)
1028 {
1030 strRH = strRemoveSubstr(&strRH, &RASTER_WAVE_PERIOD_CODE);
1031 }
1032
1034 string::npos)
1035 {
1037 strRH = strRemoveSubstr(
1039 }
1040
1041 if (strRH.find(RASTER_ACTUAL_PLATFORM_EROSION_CODE) !=
1042 string::npos)
1043 {
1045 strRH = strRemoveSubstr(&strRH,
1047 }
1048
1050 string::npos)
1051 {
1053 strRH = strRemoveSubstr(
1055 }
1056
1058 string::npos)
1059 {
1061 strRH = strRemoveSubstr(
1063 }
1064
1065 if (strRH.find(RASTER_POTENTIAL_BEACH_EROSION_CODE) !=
1066 string::npos)
1067 {
1069 strRH = strRemoveSubstr(&strRH,
1071 }
1072
1073 if (strRH.find(RASTER_ACTUAL_BEACH_EROSION_CODE) !=
1074 string::npos)
1075 {
1077 strRH =
1079 }
1080
1082 string::npos)
1083 {
1085 strRH = strRemoveSubstr(
1087 }
1088
1090 string::npos)
1091 {
1093 strRH = strRemoveSubstr(
1095 }
1096
1097 if (strRH.find(RASTER_LANDFORM_CODE) != string::npos)
1098 {
1099 m_bLandformSave = true;
1100 strRH = strRemoveSubstr(&strRH, &RASTER_LANDFORM_CODE);
1101 }
1102
1103 if (strRH.find(RASTER_LOCAL_SLOPE_CODE) != string::npos)
1104 {
1105 m_bLocalSlopeSave = true;
1106 strRH = strRemoveSubstr(&strRH, &RASTER_LOCAL_SLOPE_CODE);
1107 }
1108
1109 if (strRH.find(RASTER_SLOPE_CODE) != string::npos)
1110 {
1111 m_bSlopeSave = true;
1112 strRH = strRemoveSubstr(&strRH, &RASTER_SLOPE_CODE);
1113 }
1114
1115 if (strRH.find(RASTER_CLIFF_CODE) != string::npos)
1116 {
1117 m_bCliffSave = true;
1118 strRH = strRemoveSubstr(&strRH, &RASTER_CLIFF_CODE);
1119 }
1120
1121 if (strRH.find(RASTER_AVG_SEA_DEPTH_CODE) != string::npos)
1122 {
1123 m_bAvgSeaDepthSave = true;
1125 }
1126
1127 if (strRH.find(RASTER_AVG_WAVE_HEIGHT_CODE) != string::npos)
1128 {
1129 m_bAvgWaveHeightSave = true;
1131 }
1132
1133 if (strRH.find(RASTER_AVG_WAVE_ORIENTATION_CODE) !=
1134 string::npos)
1135 {
1136 m_bAvgWaveAngleSave = true;
1137 strRH =
1139 }
1140
1141 if (strRH.find(RASTER_BEACH_PROTECTION_CODE) != string::npos)
1142 {
1145 }
1146
1147 if (strRH.find(RASTER_BASEMENT_ELEVATION_CODE) != string::npos)
1148 {
1149 m_bBasementElevSave = true;
1150 strRH =
1152 }
1153
1154 if (strRH.find(RASTER_SUSP_SED_CODE) != string::npos)
1155 {
1156 m_bSuspSedSave = true;
1157 strRH = strRemoveSubstr(&strRH, &RASTER_SUSP_SED_CODE);
1158 }
1159
1160 if (strRH.find(RASTER_AVG_SUSP_SED_CODE) != string::npos)
1161 {
1162 m_bAvgSuspSedSave = true;
1163 strRH = strRemoveSubstr(&strRH, &RASTER_AVG_SUSP_SED_CODE);
1164 }
1165
1166 if (strRH.find(RASTER_FINE_UNCONS_CODE) != string::npos)
1167 {
1168 m_bFineUnconsSedSave = true;
1169 strRH = strRemoveSubstr(&strRH, &RASTER_FINE_UNCONS_CODE);
1170 }
1171
1172 if (strRH.find(RASTER_SAND_UNCONS_CODE) != string::npos)
1173 {
1174 m_bSandUnconsSedSave = true;
1175 strRH = strRemoveSubstr(&strRH, &RASTER_SAND_UNCONS_CODE);
1176 }
1177
1178 if (strRH.find(RASTER_COARSE_UNCONS_CODE) != string::npos)
1179 {
1182 }
1183
1184 if (strRH.find(RASTER_FINE_CONS_CODE) != string::npos)
1185 {
1186 m_bFineConsSedSave = true;
1187 strRH = strRemoveSubstr(&strRH, &RASTER_FINE_CONS_CODE);
1188 }
1189
1190 if (strRH.find(RASTER_SAND_CONS_CODE) != string::npos)
1191 {
1192 m_bSandConsSedSave = true;
1193 strRH = strRemoveSubstr(&strRH, &RASTER_SAND_CONS_CODE);
1194 }
1195
1196 if (strRH.find(RASTER_COARSE_CONS_CODE) != string::npos)
1197 {
1198 m_bCoarseConsSedSave = true;
1199 strRH = strRemoveSubstr(&strRH, &RASTER_COARSE_CONS_CODE);
1200 }
1201
1202 if (strRH.find(RASTER_COAST_CODE) != string::npos)
1203 {
1205 strRH = strRemoveSubstr(&strRH, &RASTER_COAST_CODE);
1206 }
1207
1208 if (strRH.find(RASTER_COAST_NORMAL_CODE) != string::npos)
1209 {
1211 strRH = strRemoveSubstr(&strRH, &RASTER_COAST_NORMAL_CODE);
1212 }
1213
1214 if (strRH.find(RASTER_ACTIVE_ZONE_CODE) != string::npos)
1215 {
1216 m_bActiveZoneSave = true;
1217 strRH = strRemoveSubstr(&strRH, &RASTER_ACTIVE_ZONE_CODE);
1218 }
1219
1221 string::npos)
1222 {
1223 m_bCliffCollapseSave = true;
1224 strRH = strRemoveSubstr(
1226 }
1227
1229 string::npos)
1230 {
1231 m_bCliffCollapseSave = true;
1232 strRH = strRemoveSubstr(
1234 }
1235
1237 string::npos)
1238 {
1239 m_bCliffCollapseSave = true;
1240 strRH = strRemoveSubstr(
1242 }
1243
1245 string::npos)
1246 {
1248 strRH = strRemoveSubstr(
1250 }
1251
1253 string::npos)
1254 {
1256 strRH = strRemoveSubstr(
1258 }
1259
1261 string::npos)
1262 {
1264 strRH = strRemoveSubstr(
1266 }
1267
1269 string::npos)
1270 {
1272 strRH = strRemoveSubstr(
1274 }
1275
1277 string::npos)
1278 {
1280 strRH = strRemoveSubstr(
1282 }
1283
1284 if (strRH.find(
1286 string::npos)
1287 {
1289 strRH = strRemoveSubstr(
1291 }
1292
1293 if (strRH.find(
1295 string::npos)
1296 {
1298 strRH = strRemoveSubstr(
1299 &strRH,
1301 }
1302
1303 if (strRH.find(RASTER_POLYGON_CODE) != string::npos)
1304 {
1305 m_bRasterPolygonSave = true;
1306 strRH = strRemoveSubstr(&strRH, &RASTER_POLYGON_CODE);
1307 }
1308
1310 string::npos)
1311 {
1313 strRH = strRemoveSubstr(
1315 }
1316
1317 if (strRH.find(RASTER_INUNDATION_MASK_CODE) != string::npos)
1318 {
1319 m_bSeaMaskSave = true;
1321 }
1322
1323 if (strRH.find(RASTER_BEACH_MASK_CODE) != string::npos)
1324 {
1325 m_bBeachMaskSave = true;
1326 strRH = strRemoveSubstr(&strRH, &RASTER_BEACH_MASK_CODE);
1327 }
1328
1329 if (strRH.find(RASTER_INTERVENTION_CLASS_CODE) != string::npos)
1330 {
1332 strRH =
1334 }
1335
1336 if (strRH.find(RASTER_INTERVENTION_HEIGHT_CODE) != string::npos)
1337 {
1339 strRH =
1341 }
1342
1343 if (strRH.find(RASTER_SHADOW_ZONE_CODE) != string::npos)
1344 {
1346 strRH = strRemoveSubstr(&strRH, &RASTER_SHADOW_ZONE_CODE);
1347 }
1348
1350 string::npos)
1351 {
1353 strRH = strRemoveSubstr(
1355 }
1356
1357 if (strRH.find(RASTER_DEEP_WATER_WAVE_HEIGHT_CODE) !=
1358 string::npos)
1359 {
1361 strRH = strRemoveSubstr(&strRH,
1363 }
1364
1365 if (strRH.find(RASTER_DEEP_WATER_WAVE_PERIOD_CODE) !=
1366 string::npos)
1367 {
1369 strRH = strRemoveSubstr(&strRH,
1371 }
1372
1374 string::npos)
1375 {
1377 strRH = strRemoveSubstr(
1379 }
1380
1381 if (strRH.find(RASTER_POLYGON_GAIN_OR_LOSS_CODE) !=
1382 string::npos)
1383 {
1385 strRH =
1387 }
1388
1389 if (strRH.find(RASTER_BEACH_DEPOSITION_CODE) != string::npos)
1390 {
1393 }
1394
1395 if (strRH.find(RASTER_TOTAL_BEACH_DEPOSITION_CODE) !=
1396 string::npos)
1397 {
1399 strRH = strRemoveSubstr(&strRH,
1401 }
1402
1403 if (strRH.find(RASTER_SEDIMENT_INPUT_EVENT_CODE) !=
1404 string::npos)
1405 {
1407 strRH =
1409 }
1410
1411 if (strRH.find(RASTER_SETUP_SURGE_FLOOD_MASK_CODE) !=
1412 string::npos)
1413 {
1415 strRH = strRemoveSubstr(&strRH,
1417 }
1418
1420 string::npos)
1421 {
1423 strRH = strRemoveSubstr(
1425 }
1426
1427 if (strRH.find(RASTER_WAVE_FLOOD_LINE_CODE) != string::npos)
1428 {
1431 }
1432
1433 // Check to see if all codes have been removed
1434 if (! strRH.empty())
1435 strErr = "line " + to_string(nLine) + ": unknown code '" +
1436 strRH + "' in list of codes for raster GIS output";
1437 }
1438 }
1439
1440 break;
1441
1442 case 12:
1443 // Raster GIS output format (note must retain original case). Blank
1444 // means use same format as input DEM file (if possible)
1446
1447 // TODO 065 Remove this when GDAL gpkg raster output is working
1448 // correctly
1449 if (strRH.find("gpkg") != string::npos)
1450 strErr =
1451 "GDAL gpkg raster create() is not yet working correctly. "
1452 "Please choose another output format.";
1453
1454 break;
1455
1456 case 13:
1457 // If needed, scale GIS raster output values
1458 strRH = strToLower(&strRH);
1459
1460 m_bScaleRasterOutput = false;
1461
1462 if (strRH.find('y') != string::npos)
1463 m_bScaleRasterOutput = true;
1464
1465 break;
1466
1467 case 14:
1468 // If needed, also output GIS raster world file
1469 strRH = strToLower(&strRH);
1470
1471 m_bWorldFile = false;
1472
1473 if (strRH.find('y') != string::npos)
1474 m_bWorldFile = true;
1475
1476 break;
1477
1478 case 15:
1479 // Elevations for raster slice output, if desired
1480 if (! strRH.empty())
1481 {
1482 m_bSliceSave = true;
1483
1484 // OK, so find out whether we're dealing with a single seed or more
1485 // than one: check for a space
1486 nPos = strRH.find(SPACE);
1487
1488 if (nPos != string::npos)
1489 {
1490 // There's a space, so we must have more than one number
1491 do
1492 {
1493 // Get LH bit
1494 strTmp = strRH.substr(0, nPos);
1495 m_VdSliceElev.push_back(strtod(strTmp.c_str(), NULL));
1496
1497 // Get the RH bit
1498 strRH = strRH.substr(nPos, strRH.size() - nPos);
1499 strRH = strTrimLeft(&strRH);
1500
1501 // Now look for another space
1502 nPos = strRH.find(SPACE);
1503 } while (nPos != string::npos);
1504 }
1505
1506 // Read either the single number, or the left-over number
1507 m_VdSliceElev.push_back(strtod(strTmp.c_str(), NULL));
1508 }
1509
1510 break;
1511
1512 case 16:
1513 // Vector GIS files to output
1514 if (strRH.empty())
1515 {
1516 strErr = "line ";
1517 strErr += to_string(nLine);
1518 strErr += ": must contain '";
1519 strErr += VECTOR_ALL_OUTPUT_CODE;
1520 strErr += "', or '";
1521 strErr += VECTOR_USUAL_OUTPUT_CODE;
1522 strErr += "', or at least one vector GIS output code";
1523 }
1524
1525 else
1526 {
1527 strRH = strToLower(&strRH);
1528
1529 if (strRH.find(VECTOR_ALL_OUTPUT_CODE) != string::npos)
1530 {
1531 // Output all vector files
1543 true;
1544 }
1545
1546 else if (strRH.find(VECTOR_USUAL_OUTPUT_CODE) != string::npos)
1547 {
1548 // Output the "usual" collection of vector output files
1558 true;
1559 }
1560
1561 else
1562 {
1563 // Output only those vector files for which the user specified the
1564 // code
1565 if (strRH.find(VECTOR_COAST_CODE) != string::npos)
1566 {
1567 m_bCoastSave = true;
1568 strRH = strRemoveSubstr(&strRH, &VECTOR_COAST_CODE);
1569 }
1570
1571 if (strRH.find(VECTOR_CLIFF_EDGE_CODE) != string::npos)
1572 {
1573 m_bCliffEdgeSave = true;
1574 strRH = strRemoveSubstr(&strRH, &VECTOR_CLIFF_EDGE_CODE);
1575 }
1576
1577 if (strRH.find(VECTOR_AVG_WAVE_ANGLE_AND_HEIGHT_CODE) !=
1578 string::npos)
1579 {
1581 strRH = strRemoveSubstr(&strRH,
1583 }
1584
1585 if (strRH.find(VECTOR_NORMALS_CODE) != string::npos)
1586 {
1587 m_bNormalsSave = true;
1588 strRH = strRemoveSubstr(&strRH, &VECTOR_NORMALS_CODE);
1589 }
1590
1591 if (strRH.find(VECTOR_INVALID_NORMALS_CODE) != string::npos)
1592 {
1593 m_bInvalidNormalsSave = true;
1595 }
1596
1597 if (strRH.find(VECTOR_AVG_WAVE_ANGLE_AND_HEIGHT_CODE) !=
1598 string::npos)
1599 {
1601 strRH = strRemoveSubstr(&strRH,
1603 }
1604
1605 if (strRH.find(VECTOR_COAST_CURVATURE_CODE) != string::npos)
1606 {
1607 m_bCoastCurvatureSave = true;
1609 }
1610
1612 string::npos)
1613 {
1615 strRH = strRemoveSubstr(
1617 }
1618
1619 if (strRH.find(VECTOR_MEAN_WAVE_ENERGY_CODE) != string::npos)
1620 {
1621 m_bMeanWaveEnergySave = true;
1623 }
1624
1625 if (strRH.find(VECTOR_BREAKING_WAVE_HEIGHT_CODE) !=
1626 string::npos)
1627 {
1629 strRH =
1631 }
1632
1633 if (strRH.find(VECTOR_POLYGON_NODE_CODE) != string::npos)
1634 {
1635 m_bPolygonNodeSave = true;
1636 strRH = strRemoveSubstr(&strRH, &VECTOR_POLYGON_NODE_CODE);
1637 }
1638
1639 if (strRH.find(VECTOR_POLYGON_BOUNDARY_CODE) != string::npos)
1640 {
1643 }
1644
1645 if (strRH.find(VECTOR_CLIFF_NOTCH_SIZE_CODE) != string::npos)
1646 {
1647 m_bCliffNotchSave = true;
1649 }
1650
1651 if (strRH.find(VECTOR_SHADOW_BOUNDARY_CODE) != string::npos)
1652 {
1653 m_bShadowBoundarySave = true;
1655 }
1656
1657 if (strRH.find(VECTOR_DOWNDRIFT_BOUNDARY_CODE) != string::npos)
1658 {
1660 strRH =
1662 }
1663
1665 string::npos)
1666 {
1668 strRH = strRemoveSubstr(
1670 }
1671
1672 if (strRH.find(VECTOR_WAVE_SETUP_CODE) != string::npos)
1673 {
1674 m_bWaveSetupSave = true;
1675 strRH = strRemoveSubstr(&strRH, &VECTOR_WAVE_SETUP_CODE);
1676 }
1677
1678 if (strRH.find(VECTOR_STORM_SURGE_CODE) != string::npos)
1679 {
1680 m_bStormSurgeSave = true;
1681 strRH = strRemoveSubstr(&strRH, &VECTOR_STORM_SURGE_CODE);
1682 }
1683
1684 if (strRH.find(VECTOR_RUN_UP_CODE) != string::npos)
1685 {
1686 m_bRunUpSave = true;
1687 strRH = strRemoveSubstr(&strRH, &VECTOR_RUN_UP_CODE);
1688 }
1689
1690 if (strRH.find(VECTOR_FLOOD_LINE_CODE) != string::npos)
1691 {
1693 strRH = strRemoveSubstr(&strRH, &VECTOR_FLOOD_LINE_CODE);
1694 }
1695
1696 // Check to see if all codes have been removed
1697 if (! strRH.empty())
1698 strErr = "line " + to_string(nLine) + ": unknown code '" +
1699 strRH + "' in list of vector GIS output codes";
1700 }
1701 }
1702
1703 break;
1704
1705 case 17:
1706 // Vector GIS output format (note must retain original case)
1708
1709 if (strRH.empty())
1710 strErr = "line " + to_string(nLine) + ": vector GIS output format";
1711
1712 break;
1713
1714 case 18:
1715 // Time series files to output
1716 if (! strRH.empty())
1717 {
1718 strRH = strToLower(&strRH);
1719
1720 // First check for "all"
1721 if (strRH.find(RASTER_ALL_OUTPUT_CODE) != string::npos)
1722 {
1723 m_bSeaAreaTSSave = true;
1729 m_bBeachErosionTSSave = true;
1732 m_bSuspSedTSSave = true;
1735 }
1736
1737 else
1738 {
1739 if (strRH.find(TIME_SERIES_SEA_AREA_CODE) != string::npos)
1740 {
1741 m_bSeaAreaTSSave = true;
1743 }
1744
1745 if (strRH.find(TIME_SERIES_STILL_WATER_LEVEL_CODE) !=
1746 string::npos)
1747 {
1749 strRH = strRemoveSubstr(&strRH,
1751 }
1752
1753 if (strRH.find(TIME_SERIES_PLATFORM_EROSION_CODE) !=
1754 string::npos)
1755 {
1757 strRH =
1759 }
1760
1762 string::npos)
1763 {
1765 strRH = strRemoveSubstr(
1767 }
1768
1770 string::npos)
1771 {
1773 strRH = strRemoveSubstr(
1775 }
1776
1777 if (strRH.find(TIME_SERIES_CLIFF_COLLAPSE_NET_CODE) !=
1778 string::npos)
1779 {
1781 strRH = strRemoveSubstr(&strRH,
1783 }
1784
1785 if (strRH.find(TIME_SERIES_BEACH_EROSION_CODE) != string::npos)
1786 {
1787 m_bBeachErosionTSSave = true;
1788 strRH =
1790 }
1791
1792 if (strRH.find(TIME_SERIES_BEACH_DEPOSITION_CODE) !=
1793 string::npos)
1794 {
1796 strRH =
1798 }
1799
1800 if (strRH.find(TIME_SERIES_BEACH_CHANGE_NET_CODE) !=
1801 string::npos)
1802 {
1804 strRH =
1806 }
1807
1808 if (strRH.find(TIME_SERIES_SUSPENDED_SEDIMENT_CODE) !=
1809 string::npos)
1810 {
1811 m_bSuspSedTSSave = true;
1812 strRH = strRemoveSubstr(&strRH,
1814 }
1815
1816 if (strRH.find(TIME_SERIES_FLOOD_SETUP_SURGE_CODE) !=
1817 string::npos)
1818 {
1820 strRH = strRemoveSubstr(&strRH,
1822 }
1823
1825 string::npos)
1826 {
1828 strRH = strRemoveSubstr(
1830 }
1831
1832 // Check to see if all codes have been removed
1833 if (! strRH.empty())
1834 strErr = "line " + to_string(nLine) + ": unknown code '" +
1835 strRH + "' in list of time series output files";
1836 }
1837 }
1838
1839 break;
1840
1841 case 19:
1842 // Vector coastline smoothing algorithm: 0 = none, 1 = running mean, 2
1843 // = Savitzky-Golay
1844 if (! bIsStringValidInt(strRH))
1845 {
1846 strErr = "line " + to_string(nLine) +
1847 ": invalid integer for coastline smoothing algorithm '" +
1848 strRH + "' in " + m_strDataPathName;
1849 break;
1850 }
1851
1852 m_nCoastSmooth = stoi(strRH);
1853
1854 if ((m_nCoastSmooth < SMOOTH_NONE) ||
1856 strErr = "line " + to_string(nLine) +
1857 ": coastline vector smoothing algorithm";
1858
1859 break;
1860
1861 case 20:
1862 // Size of coastline smoothing window: must be odd
1863 if (! bIsStringValidInt(strRH))
1864 {
1865 strErr = "line " + to_string(nLine) +
1866 ": invalid integer for coastline smoothing window '" +
1867 strRH + "' in " + m_strDataPathName;
1868 break;
1869 }
1870
1871 m_nCoastSmoothingWindowSize = stoi(strRH);
1872
1873 if ((m_nCoastSmoothingWindowSize <= 0) ||
1875 strErr = "line " + to_string(nLine) +
1876 ": size of coastline vector smoothing window (must be > 0 "
1877 "and odd)";
1878
1879 break;
1880
1881 case 21:
1882 // Order of coastline profile smoothing polynomial for Savitzky-Golay:
1883 // usually 2 or 4, max is 6
1884 if (! bIsStringValidInt(strRH))
1885 {
1886 strErr = "line " + to_string(nLine) +
1887 ": invalid integer for Savitzky-Golay polynomial for "
1888 "coastline smoothing '" +
1889 strRH + "' in " + m_strDataPathName;
1890 break;
1891 }
1892
1893 m_nSavGolCoastPoly = stoi(strRH);
1894
1895 if ((m_nSavGolCoastPoly <= 0) || (m_nSavGolCoastPoly > 6))
1896 strErr = "line " + to_string(nLine) +
1897 ": value of Savitzky-Golay polynomial for coastline "
1898 "smoothing (must be <= 6)";
1899
1900 break;
1901
1902 case 22:
1903 // Grid edge(s) to omit when searching for coastline [NSWE]
1904 strRH = strToLower(&strRH);
1905
1906 if (strRH.find('n') != string::npos)
1907 {
1909 }
1910
1911 if (strRH.find('s') != string::npos)
1912 {
1914 }
1915
1916 if (strRH.find('w') != string::npos)
1917 {
1918 m_bOmitSearchWestEdge = true;
1919 }
1920
1921 if (strRH.find('e') != string::npos)
1922 {
1923 m_bOmitSearchEastEdge = true;
1924 }
1925
1926 break;
1927
1928 case 23:
1929 // Profile slope running-mean smoothing window size: must be odd
1930 if (! bIsStringValidInt(strRH))
1931 {
1932 strErr =
1933 "line " + to_string(nLine) +
1934 ": invalid integer for size of coastline smoothing window '" +
1935 strRH + "' in " + m_strDataPathName;
1936 break;
1937 }
1938
1939 m_nProfileSmoothWindow = stoi(strRH);
1940
1941 if ((m_nProfileSmoothWindow < 0) ||
1943 strErr = "line " + to_string(nLine) +
1944 ": size of profile vector smoothing window (must be >= 0, "
1945 "if > 0 must be odd)";
1946
1947 break;
1948
1949 case 24:
1950 // Max local slope (m/m), first check that this is a valid double
1951 if (! bIsStringValidDouble(strRH))
1952 {
1953 strErr = "line " + to_string(nLine) +
1954 ": invalid floating point number for max local slope '" +
1955 strRH + "' in " + m_strDataPathName;
1956 break;
1957 }
1958
1959 m_dProfileMaxSlope = strtod(strRH.c_str(), NULL);
1960
1961 if (m_dProfileMaxSlope <= 0)
1962 strErr =
1963 "line " + to_string(nLine) + ": max local slope must be > 0";
1964
1965 break;
1966
1967 case 25:
1968 // Maximum elevation of beach above SWL, first check that this is a
1969 // valid double
1970 if (! bIsStringValidDouble(strRH))
1971 {
1972 strErr = "line " + to_string(nLine) +
1973 ": invalid floating point number for maximum elevation of "
1974 "beach above SWL '" +
1975 strRH + "' in " + m_strDataPathName;
1976 break;
1977 }
1978
1979 m_dMaxBeachElevAboveSWL = strtod(strRH.c_str(), NULL);
1980
1982 strErr = "line " + to_string(nLine) +
1983 ": maximum elevation of beach above SWL must be >= 0";
1984
1985 break;
1986
1987 // ------------------------------------------------- Raster GIS layers
1988 // ------------------------------------------------
1989 case 26:
1990 // Number of sediment layers
1991 if (! bIsStringValidInt(strRH))
1992 {
1993 strErr = "line " + to_string(nLine) +
1994 ": invalid integer for number of sediment layers '" +
1995 strRH + "' in " + m_strDataPathName;
1996 break;
1997 }
1998
1999 m_nLayers = stoi(strRH);
2000
2001 if (m_nLayers < 1)
2002 {
2003 strErr = "line " + to_string(nLine) +
2004 ": must be at least one sediment layer";
2005 break;
2006 }
2007
2008 // OK we know the number of layers, so add elements to these vectors
2009 for (int j = 0; j < m_nLayers; j++)
2010 {
2017 m_VstrGDALIUFDriverCode.push_back("");
2018 m_VstrGDALIUFDriverDesc.push_back("");
2019 m_VstrGDALIUFProjection.push_back("");
2020 m_VstrGDALIUFDataType.push_back("");
2021 m_VstrGDALIUSDriverCode.push_back("");
2022 m_VstrGDALIUSDriverDesc.push_back("");
2023 m_VstrGDALIUSProjection.push_back("");
2024 m_VstrGDALIUSDataType.push_back("");
2025 m_VstrGDALIUCDriverCode.push_back("");
2026 m_VstrGDALIUCDriverDesc.push_back("");
2027 m_VstrGDALIUCProjection.push_back("");
2028 m_VstrGDALIUCDataType.push_back("");
2029 m_VstrGDALICFDriverCode.push_back("");
2030 m_VstrGDALICFDriverDesc.push_back("");
2031 m_VstrGDALICFProjection.push_back("");
2032 m_VstrGDALICFDataType.push_back("");
2033 m_VstrGDALICSDriverCode.push_back("");
2034 m_VstrGDALICSDriverDesc.push_back("");
2035 m_VstrGDALICSProjection.push_back("");
2036 m_VstrGDALICSDataType.push_back("");
2037 m_VstrGDALICCDriverCode.push_back("");
2038 m_VstrGDALICCDriverDesc.push_back("");
2039 m_VstrGDALICCProjection.push_back("");
2040 m_VstrGDALICCDataType.push_back("");
2041 }
2042
2043 break;
2044
2045 case 27:
2046 // Basement DEM file (can be blank)
2047 if (! strRH.empty())
2048 {
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
2055 // occurrence of a drive letter
2056 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) ||
2057 (strRH[1] == COLON))
2058 // It has an absolute path, so use it 'as is'
2060
2061 else
2062 {
2063 // It has a relative path, so prepend the CoastalME dir
2065 m_strInitialBasementDEMFile.append(strRH);
2066 }
2067 }
2068
2069 break;
2070
2071 case 28:
2072 // Read 6 x sediment files for each layer
2073 for (int nLayer = 0; nLayer < m_nLayers; nLayer++)
2074 {
2075 for (int j = 1; j <= 6; j++)
2076 {
2077 if (! bFirst)
2078 {
2079 do
2080 {
2081 if (! getline(InStream, strRec))
2082 {
2083 cerr << ERR << "premature end of file in "
2084 << m_strDataPathName << endl;
2085 return false;
2086 }
2087
2088 nLine++;
2089
2090 // Trim off leading and trailing whitespace
2091 strRec = strTrim(&strRec);
2092 }
2093
2094 // If it is a blank line or a comment then ignore it
2095 while (strRec.empty() || (strRec[0] == QUOTE1) ||
2096 (strRec[0] == QUOTE2));
2097
2098 // Not blank or a comment, so find the colon: lines MUST have a
2099 // colon separating data from leading description portion
2100 nPos = strRec.find(COLON);
2101
2102 if (nPos == string::npos)
2103 {
2104 // Error: badly formatted (no colon)
2105 cerr << ERR << "on line " << to_string(nLine)
2106 << ": badly formatted (no ':') in " << m_strDataPathName
2107 << endl
2108 << strRec << endl;
2109 return false;
2110 }
2111
2112 // Strip off leading portion (the bit up to and including the
2113 // colon)
2114 strRH = strRec.substr(nPos + 1);
2115 // ERROR strRH.resize(nPos);
2116
2117 // Remove leading whitespace after the colon
2118 strRH = strTrimLeft(&strRH);
2119
2120 // Look for a trailing comment, if found then terminate string
2121 // at that point and trim off any trailing whitespace
2122 nPos = strRH.rfind(QUOTE1);
2123
2124 if (nPos != string::npos)
2125 strRH.resize(nPos);
2126
2127 nPos = strRH.rfind(QUOTE2);
2128
2129 if (nPos != string::npos)
2130 strRH.resize(nPos);
2131
2132 // Trim trailing spaces
2133 strRH = strTrimRight(&strRH);
2134
2135#ifdef _WIN32
2136 // For Windows, make sure has backslashes, not Unix-style
2137 // slashes
2138 strRH = pstrChangeToBackslash(&strRH);
2139#endif
2140 }
2141
2142 bFirst = false;
2143
2144 switch (j)
2145 {
2146 case 1:
2147
2148 // Initial fine unconsolidated sediment depth GIS file (can be
2149 // blank)
2150 if (! strRH.empty())
2151 {
2152 // Set switch
2153 m_bHaveFineSediment = true;
2154#ifdef _WIN32
2155 // For Windows, make sure has backslashes, not Unix-style
2156 // slashes
2157 strRH = pstrChangeToBackslash(&strRH);
2158#endif
2159
2160 // Now check for leading slash, or leading Unix home dir
2161 // symbol, or occurrence of a drive letter
2162 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) ||
2163 (strRH[1] == COLON))
2164 {
2165 // It has an absolute path, so use it 'as is'
2167 }
2168
2169 else
2170 {
2171 // It has a relative path, so prepend the CoastalME dir
2173 m_VstrInitialFineUnconsSedimentFile[nLayer].append(strRH);
2174 }
2175 }
2176
2177 break;
2178
2179 case 2:
2180 // Initial sand unconsolidated sediment depth GIS file (can be
2181 // blank)
2182 if (! strRH.empty())
2183 {
2184 // Set switch
2185 m_bHaveSandSediment = true;
2186#ifdef _WIN32
2187 // For Windows, make sure has backslashes, not Unix-style
2188 // slashes
2189 strRH = pstrChangeToBackslash(&strRH);
2190#endif
2191
2192 // Now check for leading slash, or leading Unix home dir
2193 // symbol, or occurrence of a drive letter
2194 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) ||
2195 (strRH[1] == COLON))
2196 {
2197 // It has an absolute path, so use it 'as is'
2199 }
2200
2201 else
2202 {
2203 // It has a relative path, so prepend the CoastalME dir
2205 m_VstrInitialSandUnconsSedimentFile[nLayer].append(strRH);
2206 }
2207 }
2208
2209 break;
2210
2211 case 3:
2212 // Initial coarse unconsolidated sediment depth GIS file (can be
2213 // blank)
2214 if (! strRH.empty())
2215 {
2216 // Set switch
2217 m_bHaveCoarseSediment = true;
2218#ifdef _WIN32
2219 // For Windows, make sure has backslashes, not Unix-style
2220 // slashes
2221 strRH = pstrChangeToBackslash(&strRH);
2222#endif
2223
2224 // Now check for leading slash, or leading Unix home dir
2225 // symbol, or occurrence of a drive letter
2226 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) ||
2227 (strRH[1] == COLON))
2228 {
2229 // It has an absolute path, so use it 'as is'
2231 }
2232
2233 else
2234 {
2235 // It has a relative path, so prepend the CoastalME dir
2237 m_VstrInitialCoarseUnconsSedimentFile[nLayer].append(strRH);
2238 }
2239 }
2240
2241 break;
2242
2243 case 4:
2244 // Initial fine consolidated sediment depth GIS file (can be
2245 // blank)
2246 if (! strRH.empty())
2247 {
2248 // Set switches
2250 m_bHaveFineSediment = true;
2251#ifdef _WIN32
2252 // For Windows, make sure has backslashes, not Unix-style
2253 // slashes
2254 strRH = pstrChangeToBackslash(&strRH);
2255#endif
2256
2257 // Now check for leading slash, or leading Unix home dir
2258 // symbol, or occurrence of a drive letter
2259 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) ||
2260 (strRH[1] == COLON))
2261 {
2262 // It has an absolute path, so use it 'as is'
2263 m_VstrInitialFineConsSedimentFile[nLayer] = strRH;
2264 }
2265
2266 else
2267 {
2268 // It has a relative path, so prepend the CoastalME dir
2270 m_VstrInitialFineConsSedimentFile[nLayer].append(strRH);
2271 }
2272 }
2273
2274 break;
2275
2276 case 5:
2277 // Initial sand consolidated sediment depth GIS file (can be
2278 // blank)
2279 if (! strRH.empty())
2280 {
2281 // Set switches
2283 m_bHaveSandSediment = true;
2284#ifdef _WIN32
2285 // For Windows, make sure has backslashes, not Unix-style
2286 // slashes
2287 strRH = pstrChangeToBackslash(&strRH);
2288#endif
2289
2290 // Now check for leading slash, or leading Unix home dir
2291 // symbol, or occurrence of a drive letter
2292 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) ||
2293 (strRH[1] == COLON))
2294 {
2295 // It has an absolute path, so use it 'as is'
2296 m_VstrInitialSandConsSedimentFile[nLayer] = strRH;
2297 }
2298
2299 else
2300 {
2301 // It has a relative path, so prepend the CoastalME dir
2303 m_VstrInitialSandConsSedimentFile[nLayer].append(strRH);
2304 }
2305 }
2306
2307 break;
2308
2309 case 6:
2310 // Initial coarse consolidated sediment depth GIS file (can be
2311 // blank)
2312 if (! strRH.empty())
2313 {
2314 // Set switches
2316 m_bHaveCoarseSediment = true;
2317#ifdef _WIN32
2318 // For Windows, make sure has backslashes, not Unix-style
2319 // slashes
2320 strRH = pstrChangeToBackslash(&strRH);
2321#endif
2322
2323 // Now check for leading slash, or leading Unix home dir
2324 // symbol, or occurrence of a drive letter
2325 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) ||
2326 (strRH[1] == COLON))
2327 {
2328 // It has an absolute path, so use it 'as is'
2330 }
2331
2332 else
2333 {
2334 // It has a relative path, so prepend the CoastalME dir
2336 m_VstrInitialCoarseConsSedimentFile[nLayer].append(strRH);
2337 }
2338 }
2339
2340 break;
2341 }
2342
2343 // Did an error occur?
2344 if (! strErr.empty())
2345 {
2346 // Error in input to run details file
2347 cerr << ERR << "reading " << strErr << " in "
2348 << m_strDataPathName << endl
2349 << "'" << strRec << "'" << endl;
2350 InStream.close();
2351 return false;
2352 }
2353 }
2354 }
2355
2356 break;
2357
2358 case 29:
2359 // Initial suspended sediment depth GIS file (can be blank)
2360 if (! strRH.empty())
2361 {
2362 // Set switch
2363 m_bHaveFineSediment = true;
2364#ifdef _WIN32
2365 // For Windows, make sure has backslashes, not Unix-style slashes
2366 strRH = pstrChangeToBackslash(&strRH);
2367#endif
2368
2369 // Now check for leading slash, or leading Unix home dir symbol, or
2370 // occurrence of a drive letter
2371 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) ||
2372 (strRH[1] == COLON))
2373 {
2374 // It has an absolute path, so use it 'as is'
2376 }
2377
2378 else
2379 {
2380 // It has a relative path, so prepend the CoastalME dir
2382 m_strInitialSuspSedimentFile.append(strRH);
2383 }
2384 }
2385
2386 break;
2387
2388 case 30:
2389 // Initial Landform class GIS file (can be blank)
2390 if (! strRH.empty())
2391 {
2392#ifdef _WIN32
2393 // For Windows, make sure has backslashes, not Unix-style slashes
2394 strRH = pstrChangeToBackslash(&strRH);
2395#endif
2396
2397 // Now check for leading slash, or leading Unix home dir symbol, or
2398 // occurrence of a drive letter
2399 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) ||
2400 (strRH[1] == COLON))
2401 {
2402 // It has an absolute path, so use it 'as is'
2404 }
2405
2406 else
2407 {
2408 // It has a relative path, so prepend the CoastalME dir
2410 m_strInitialLandformFile.append(strRH);
2411 }
2412 }
2413
2414 break;
2415
2416 case 31:
2417 // Initial Intervention class GIS file (can be blank: if so then
2418 // intervention height file must also be blank)
2419 if (! strRH.empty())
2420 {
2421#ifdef _WIN32
2422 // For Windows, make sure has backslashes, not Unix-style slashes
2423 strRH = pstrChangeToBackslash(&strRH);
2424#endif
2425
2426 // Now check for leading slash, or leading Unix home dir symbol, or
2427 // occurrence of a drive letter
2428 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) ||
2429 (strRH[1] == COLON))
2430 {
2431 // It has an absolute path, so use it 'as is'
2433 }
2434
2435 else
2436 {
2437 // It has a relative path, so prepend the CoastalME dir
2439 m_strInterventionClassFile.append(strRH);
2440 }
2441
2442 // Set the save switches
2445 }
2446
2447 break;
2448
2449 case 32:
2450 // Initial Intervention height GIS file (can be blank: if so then
2451 // intervention class file must also be blank)
2452 if (strRH.empty())
2453 {
2454 if (! m_strInterventionClassFile.empty())
2455 strErr = "line " + to_string(nLine) +
2456 ": must specify both intervention class and "
2457 "intervention height files";
2458
2459 break;
2460 }
2461
2462 else
2463 {
2464 if (m_strInterventionClassFile.empty())
2465 {
2466 strErr = "line " + to_string(nLine) +
2467 ": must specify both intervention class and "
2468 "intervention height files";
2469 break;
2470 }
2471
2472#ifdef _WIN32
2473 // For Windows, make sure has backslashes, not Unix-style slashes
2474 strRH = pstrChangeToBackslash(&strRH);
2475#endif
2476
2477 // Now check for leading slash, or leading Unix home dir symbol, or
2478 // occurrence of a drive letter
2479 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) ||
2480 (strRH[1] == COLON))
2481 {
2482 // It has an absolute path, so use it 'as is'
2484 }
2485
2486 else
2487 {
2488 // It has a relative path, so prepend the CoastalME dir
2490 m_strInterventionHeightFile.append(strRH);
2491 }
2492 }
2493
2494 break;
2495
2496 // ---------------------------------------------------- Hydrology data
2497 // ------------------------------------------------
2498 case 33:
2499 // Wave propagation model [0 = COVE, 1 = CShore]
2500 if (! bIsStringValidInt(strRH))
2501 {
2502 strErr = "line " + to_string(nLine) +
2503 ": invalid integer for wave propagation model '" + strRH +
2504 "' in " + m_strDataPathName;
2505 break;
2506 }
2507
2508 m_nWavePropagationModel = stoi(strRH);
2509
2512 strErr = "line " + to_string(nLine) +
2513 ": wave propagation model must be 0 or 1";
2514
2515 break;
2516
2517 case 34:
2518 // Density of sea water (kg/m3), first check that this is a valid
2519 // double
2520 if (! bIsStringValidDouble(strRH))
2521 {
2522 strErr = "line " + to_string(nLine) +
2523 ": invalid floating point number for sea water density '" +
2524 strRH + "' in " + m_strDataPathName;
2525 break;
2526 }
2527
2528 m_dSeaWaterDensity = strtod(strRH.c_str(), NULL);
2529
2530 if (m_dSeaWaterDensity <= 0)
2531 strErr =
2532 "line " + to_string(nLine) + ": sea water density must be > 0";
2533
2534 break;
2535
2536 case 35:
2537 // Initial mean still water level (m), first check that this is a
2538 // valid double TODO 041 Make this a per-timestep SWL file
2539 if (! bIsStringValidDouble(strRH))
2540 {
2541 strErr = "line " + to_string(nLine) +
2542 ": invalid floating point number for initial SWL '" +
2543 strRH + "' in " + m_strDataPathName;
2544 break;
2545 }
2546
2547 m_dInitialMeanSWL = strtod(strRH.c_str(), NULL);
2548 break;
2549
2550 case 36:
2551 // Final mean still water level (m) [blank = same as initial MSWL]
2552 if (strRH.empty())
2554
2555 else
2556 {
2557 // Check that this is a valid double
2558 if (! bIsStringValidDouble(strRH))
2559 {
2560 strErr = "line " + to_string(nLine) +
2561 ": invalid floating point number for final SWL '" +
2562 strRH + "' in " + m_strDataPathName;
2563 break;
2564 }
2565
2566 m_dFinalMeanSWL = strtod(strRH.c_str(), NULL);
2567 }
2568
2569 break;
2570
2571 case 37:
2572 // Deep water wave height (m) or a file of point vectors giving deep
2573 // water wave height (m) and orientation (for units, see below)
2574 if (strRH.empty())
2575 strErr = "line " + to_string(nLine) +
2576 ": deep water wave height in " + m_strDataPathName +
2577 " must be either a number or a filename (filename must "
2578 "not start with a number)";
2579
2580 else
2581 {
2582 if (isdigit(
2583 strRH.at(0))) // If this starts with a number then is a
2584 // single value, otherwise is a filename. Note
2585 // that filename must not start with number
2586 {
2587 // Just one value of wave height for all deep water cells, first
2588 // check that this is a valid double
2589 if (! bIsStringValidDouble(strRH))
2590 {
2591 strErr = "line " + to_string(nLine) +
2592 ": invalid floating point number for deep water wave "
2593 "height '" +
2594 strRH + "' in " + m_strDataPathName;
2595 break;
2596 }
2597
2599 m_bHaveWaveStationData = false;
2600
2601 m_dAllCellsDeepWaterWaveHeight = strtod(strRH.c_str(), NULL);
2602
2604 strErr = "line " + to_string(nLine) +
2605 ": deep water wave height must be > 0";
2606 }
2607
2608 else
2609 {
2610 // We are reading deep water wave height and deep water wave
2611 // orientation from two files. This first file is a point shape
2612 // file with the location of the buoys and integer ID for each one
2614#ifdef _WIN32
2615 // For Windows, make sure has backslashes, not Unix-style slashes
2616 strRH = pstrChangeToBackslash(&strRH);
2617#endif
2618
2619 // Now check for leading slash, or leading Unix home dir symbol,
2620 // or occurrence of a drive letter
2621 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) ||
2622 (strRH[1] == COLON))
2623 {
2624 // It has an absolute path, so use it 'as is'
2626 }
2627
2628 else
2629 {
2630 // It has a relative path, so prepend the CoastalME dir
2633 }
2634 }
2635 }
2636
2637 break;
2638
2639 case 38:
2640 // Deep water wave height input file. Each point in
2641 // m_strDeepWaterWavesInputFile is a triad of wave height, orientation
2642 // and period for each time step
2644 {
2645 if (strRH.empty())
2646 {
2647 strErr = "line " + to_string(nLine) +
2648 ": filename missing for deep water wave height input";
2649 break;
2650 }
2651
2652#ifdef _WIN32
2653 // For Windows, make sure has backslashes, not Unix-style slashes
2654 strRH = pstrChangeToBackslash(&strRH);
2655#endif
2656
2657 // Now check for leading slash, or leading Unix home dir symbol, or
2658 // occurrence of a drive letter
2659 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) ||
2660 (strRH[1] == COLON))
2661 {
2662 // It has an absolute path, so use it 'as is'
2664 }
2665
2666 else
2667 {
2668 // It has a relative path, so prepend the CoastalME dir
2670 m_strDeepWaterWavesInputFile.append(strRH);
2671 }
2672 }
2673
2674 break;
2675
2676 case 39:
2677 // Deep water wave orientation in input CRS: this is the oceanographic
2678 // convention i.e. direction TOWARDS which the waves move (in degrees
2679 // clockwise from north)
2681 {
2682 // Only read this if we have just a single value of wave height for
2683 // all deep water cells. Check that this is a valid double
2684 if (! bIsStringValidDouble(strRH))
2685 {
2686 strErr = "line " + to_string(nLine) +
2687 ": invalid floating point number for deep water wave "
2688 "orientation '" +
2689 strRH + "' in " + m_strDataPathName;
2690 break;
2691 }
2692
2693 m_dAllCellsDeepWaterWaveAngle = strtod(strRH.c_str(), NULL);
2694
2696 strErr =
2697 "line " + to_string(nLine) +
2698 ": deep water wave orientation must be zero degrees or more";
2699
2700 else if (m_dAllCellsDeepWaterWaveAngle >= 360)
2701 strErr =
2702 "line " + to_string(nLine) +
2703 ": deep water wave orientation must be less than 360 degrees";
2704 }
2705
2706 break;
2707
2708 case 40:
2709 // Wave period (sec)
2711 {
2712 // Only read this if we also have just a single value of wave height
2713 // for all deep water cells. Check that this is a valid double
2714 if (! bIsStringValidDouble(strRH))
2715 {
2716 strErr = "line " + to_string(nLine) +
2717 ": invalid floating point number for wave period '" +
2718 strRH + "' in " + m_strDataPathName;
2719 break;
2720 }
2721
2722 m_dAllCellsDeepWaterWavePeriod = strtod(strRH.c_str(), NULL);
2723
2725 strErr = "line " + to_string(nLine) + ": wave period must be > 0";
2726 }
2727
2728 break;
2729
2730 case 41:
2731 // Tide data file (can be blank). This is the change (m) from still
2732 // water level for each timestep
2733 if (! strRH.empty())
2734 {
2735#ifdef _WIN32
2736 // For Windows, make sure has backslashes, not Unix-style slashes
2737 strRH = pstrChangeToBackslash(&strRH);
2738#endif
2739
2740 // Now check for leading slash, or leading Unix home dir symbol, or
2741 // occurrence of a drive letter
2742 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) ||
2743 (strRH[1] == COLON))
2744 // It has an absolute path, so use it 'as is'
2745 m_strTideDataFile = strRH;
2746
2747 else
2748 {
2749 // It has a relative path, so prepend the CoastalME dir
2751 m_strTideDataFile.append(strRH);
2752 }
2753 }
2754
2755 break;
2756
2757 case 42:
2758 // Breaking wave height-to-depth ratio, check that this is a valid
2759 // double
2760 if (! bIsStringValidDouble(strRH))
2761 {
2762 strErr = "line " + to_string(nLine) +
2763 ": invalid floating point number for breaking wave height "
2764 "to depth ratio '" +
2765 strRH + "' in " + m_strDataPathName;
2766 break;
2767 }
2768
2769 m_dBreakingWaveHeightDepthRatio = strtod(strRH.c_str(), NULL);
2770
2772 strErr = "line " + to_string(nLine) +
2773 ": breaking wave height to depth ratio must be > 0";
2774
2775 break;
2776
2777 // ----------------------------------------------------- Sediment data
2778 // ------------------------------------------------
2779 case 43:
2780 // Simulate coast platform erosion?
2781 strRH = strToLower(&strRH);
2782
2783 if (strRH.find('y') != string::npos)
2785
2786 break;
2787
2788 case 44:
2789 // If simulating coast platform erosion, R (coast platform resistance
2790 // to erosion) values along profile, see Walkden & Hall, 2011
2792 {
2793 // First check that this is a valid double
2794 if (! bIsStringValidDouble(strRH))
2795 {
2796 strErr = "line " + to_string(nLine) +
2797 ": invalid floating point number for R (coast platform "
2798 "resistance to erosion) '" +
2799 strRH + "' in " + m_strDataPathName;
2800 break;
2801 }
2802
2803 m_dR = strtod(strRH.c_str(), NULL);
2804
2805 if (m_dR <= 0)
2806 strErr = "line " + to_string(nLine) +
2807 ": R (coast platform resistance to erosion) value must "
2808 "be > 0";
2809 }
2810
2811 break;
2812
2813 case 45:
2814 // Simulate beach sediment transport?
2815 strRH = strToLower(&strRH);
2816
2818
2819 if (strRH.find('y') != string::npos)
2821
2822 break;
2823
2824 case 46:
2825 // If simulating beach sediment transport, beach sediment transport at
2826 // grid edges [0 = closed, 1 = open, 2 = re-circulate]
2828 {
2829 if (! bIsStringValidInt(strRH))
2830 {
2831 strErr = "line " + to_string(nLine) +
2832 ": invalid integer for beach sediment transport at grid "
2833 "edges '" +
2834 strRH + "' in " + m_strDataPathName;
2835 break;
2836 }
2837
2839
2842 strErr = "line " + to_string(nLine) +
2843 ": switch for handling of beach sediment at grid edges "
2844 "must be 0, 1, or 2";
2845 }
2846
2847 break;
2848
2849 case 47:
2850 // If simulating beach sediment transport, beach erosion/deposition
2851 // equation [0 = CERC, 1 = Kamphuis]
2853 {
2854 if (! bIsStringValidInt(strRH))
2855 {
2856 strErr =
2857 "line " + to_string(nLine) +
2858 ": invalid integer for beach erosion/deposition equation '" +
2859 strRH + "' in " + m_strDataPathName;
2860 break;
2861 }
2862
2864
2869 strErr = "line " + to_string(nLine) +
2870 ": switch for beach erosion/deposition equation must be "
2871 "0 or 1";
2872 }
2873
2874 break;
2875
2876 case 48:
2877 // Median size of fine sediment (mm), always needed [0 = default, only
2878 // for Kamphuis eqn]. First check that this is a valid double
2879 if (! bIsStringValidDouble(strRH))
2880 {
2881 strErr = "line " + to_string(nLine) +
2882 ": invalid floating point number for median particle size "
2883 "of fine sediment '" +
2884 strRH + "' in " + m_strDataPathName;
2885 break;
2886 }
2887
2888 m_dD50Fine = strtod(strRH.c_str(), NULL);
2889
2890 if (m_dD50Fine < 0)
2891 strErr = "line " + to_string(nLine) +
2892 ": median particle size of fine sediment must be > 0";
2893
2894 else if (bFPIsEqual(m_dD50Fine, 0.0, TOLERANCE))
2895 // Use default value
2897
2898 break;
2899
2900 case 49:
2901 // Median size of sand sediment (mm), always needed [0 = default, only
2902 // for Kamphuis eqn]. First check that this is a valid double
2903 if (! bIsStringValidDouble(strRH))
2904 {
2905 strErr = "line " + to_string(nLine) +
2906 ": invalid floating point number for median particle size "
2907 "of sand sediment '" +
2908 strRH + "' in " + m_strDataPathName;
2909 break;
2910 }
2911
2912 m_dD50Sand = strtod(strRH.c_str(), NULL);
2913
2914 if (m_dD50Sand < 0)
2915 strErr = "line " + to_string(nLine) +
2916 ": median particle size of sand sediment must be > 0";
2917
2918 else if (bFPIsEqual(m_dD50Sand, 0.0, TOLERANCE))
2919 // Use default value
2921
2922 break;
2923
2924 case 50:
2925 // Median size of coarse sediment (mm), always needed [0 = default,
2926 // only for Kamphuis eqn]. First check that this is a valid double
2927 if (! bIsStringValidDouble(strRH))
2928 {
2929 strErr = "line " + to_string(nLine) +
2930 ": invalid floating point number for median particle size "
2931 "of coarse sediment '" +
2932 strRH + "' in " + m_strDataPathName;
2933 break;
2934 }
2935
2936 m_dD50Coarse = strtod(strRH.c_str(), NULL);
2937
2938 if (m_dD50Coarse < 0)
2939 strErr = "line " + to_string(nLine) +
2940 ": median particle size of coarse sediment must be > 0";
2941
2942 else if (bFPIsEqual(m_dD50Coarse, 0.0, TOLERANCE))
2943 // Use default value
2945
2946 break;
2947
2948 case 51:
2949 // Density of unconsolidated beach sediment (kg/m3)
2951 {
2952 // First check that this is a valid double
2953 if (! bIsStringValidDouble(strRH))
2954 {
2955 strErr = "line " + to_string(nLine) +
2956 ": invalid floating point number for density of beach "
2957 "sediment '" +
2958 strRH + "' in " + m_strDataPathName;
2959 break;
2960 }
2961
2962 m_dBeachSedimentDensity = strtod(strRH.c_str(), NULL);
2963
2964 if (m_dBeachSedimentDensity <= 0)
2965 strErr = "line " + to_string(nLine) +
2966 ": density of beach sediment must be > 0";
2967 }
2968
2969 break;
2970
2971 case 52:
2972 // Beach sediment porosity
2974 {
2975 // First check that this is a valid double
2976 if (! bIsStringValidDouble(strRH))
2977 {
2978 strErr = "line " + to_string(nLine) +
2979 ": invalid floating point number for porosity of beach "
2980 "sediment '" +
2981 strRH + "' in " + m_strDataPathName;
2982 break;
2983 }
2984
2985 m_dBeachSedimentPorosity = strtod(strRH.c_str(), NULL);
2986
2987 if (m_dBeachSedimentPorosity <= 0)
2988 strErr = "line " + to_string(nLine) +
2989 ": porosity of beach sediment must be > 0";
2990 }
2991
2992 break;
2993
2994 case 53:
2995 // Relative erodibility (0 - 1) of fine-sized sediment, always needed.
2996 // First check that this is a valid double
2997 if (! bIsStringValidDouble(strRH))
2998 {
2999 strErr = "line " + to_string(nLine) +
3000 ": invalid floating point number for erodibility of "
3001 "fine-sized sediment '" +
3002 strRH + "' in " + m_strDataPathName;
3003 break;
3004 }
3005
3006 m_dFineErodibility = strtod(strRH.c_str(), NULL);
3007
3008 if ((m_dFineErodibility < 0) || (m_dFineErodibility > 1))
3009 strErr = "line " + to_string(nLine) +
3010 ": relative erodibility of fine-sized sediment must be "
3011 "between 0 and 1";
3012
3013 break;
3014
3015 case 54:
3016 // Relative erodibility (0 - 1) of sand-sized sediment, always needed.
3017 // First check that this is a valid double
3018 if (! bIsStringValidDouble(strRH))
3019 {
3020 strErr = "line " + to_string(nLine) +
3021 ": invalid floating point number for erodibility of "
3022 "sand-sized sediment '" +
3023 strRH + "' in " + m_strDataPathName;
3024 break;
3025 }
3026
3027 m_dSandErodibility = strtod(strRH.c_str(), NULL);
3028
3029 if ((m_dSandErodibility < 0) || (m_dSandErodibility > 1))
3030 strErr = "line " + to_string(nLine) +
3031 ": relative erodibility of sand-sized sediment must be "
3032 "between 0 and 1";
3033
3034 break;
3035
3036 case 55:
3037 // Relative erodibility (0 - 1) of coarse-sized sediment, always
3038 // needed. First check that this is a valid double
3039 if (! bIsStringValidDouble(strRH))
3040 {
3041 strErr = "line " + to_string(nLine) +
3042 ": invalid floating point number for erodibility of "
3043 "coarse-sized sediment '" +
3044 strRH + "' in " + m_strDataPathName;
3045 break;
3046 }
3047
3048 m_dCoarseErodibility = strtod(strRH.c_str(), NULL);
3049
3050 if ((m_dCoarseErodibility < 0) || (m_dCoarseErodibility > 1))
3051 {
3052 strErr = "line " + to_string(nLine) +
3053 ": relative erodibility of coarse-sized sediment must be "
3054 "between 0 and 1";
3055 break;
3056 }
3057
3060 strErr = "line " + to_string(nLine) +
3061 ": must have at least one non-zero erodibility value";
3062
3063 break;
3064
3065 case 56:
3066 // Transport parameter KLS in CERC equation
3068 {
3069 // First check that this is a valid double
3070 if (! bIsStringValidDouble(strRH))
3071 {
3072 strErr = "line " + to_string(nLine) +
3073 ": invalid floating point number for transport "
3074 "parameter KLS of CERC equation '" +
3075 strRH + "' in " + m_strDataPathName;
3076 break;
3077 }
3078
3079 m_dKLS = strtod(strRH.c_str(), NULL);
3080
3081 // However, many sites do not have transport data available to
3082 // calibrate K, and for design applications without calibration data
3083 // the CERC formula provides only order-of-magnitude accuracy
3084 // (Fowler et al., 1995; Wang et al., 1998). The recommended value
3085 // of K = 0.39 has been commonly used to represent the potential
3086 // longshore transport rate. However, Miller (1998) found that the
3087 // CERC formula sometimes over and sometimes under predicted
3088 // longshore transport rate for measurements during storms,
3089 // indicating the value of K also can be higher than 0.39
3090 // TODO 042 Should this be a user input, or not? The comment above
3091 // seems inconclusive m_dKLS = tMin(m_dKLS, 0.39);
3092
3093 if (m_dKLS <= 0)
3094 strErr = "line " + to_string(nLine) +
3095 ": transport parameter KLS of CERC equation must be > 0";
3096 }
3097
3098 break;
3099
3100 case 57:
3101 // Transport parameter for Kamphuis equation
3103 {
3104 // First check that this is a valid double
3105 if (! bIsStringValidDouble(strRH))
3106 {
3107 strErr = "line " + to_string(nLine) +
3108 ": invalid floating point number for transport "
3109 "parameter of Kamphuis equation '" +
3110 strRH + "' in " + m_strDataPathName;
3111 break;
3112 }
3113
3114 m_dKamphuis = strtod(strRH.c_str(), NULL);
3115
3116 if (m_dKamphuis <= 0)
3117 strErr = "line " + to_string(nLine) +
3118 ": transport parameter of Kamphuis equation must be > 0";
3119 }
3120
3121 break;
3122
3123 case 58:
3124 // Berm height i.e. height above SWL of start of depositional Dean
3125 // profile
3127 {
3128 // First check that this is a valid double
3129 if (! bIsStringValidDouble(strRH))
3130 {
3131 strErr = "line " + to_string(nLine) +
3132 ": invalid floating point number for Dean profile start "
3133 "height above SWL '" +
3134 strRH + "' in " + m_strDataPathName;
3135 break;
3136 }
3137
3138 m_dDeanProfileStartAboveSWL = strtod(strRH.c_str(), NULL);
3139
3141 strErr = "line " + to_string(nLine) +
3142 ": Berm height (Dean profile start height above SWL) "
3143 "must be >= 0";
3144 }
3145
3146 break;
3147
3148 // ------------------------------------------------ Cliff collapse data
3149 // -----------------------------------------------
3150 case 59:
3151 // Simulate cliff collapse?
3153 {
3154 // Only consider cliff collapse if we have some consolidated
3155 // sedimemt
3156 strRH = strToLower(&strRH);
3157
3158 if (strRH.find('y') != string::npos)
3159 m_bDoCliffCollapse = true;
3160 }
3161
3162 break;
3163
3164 case 60:
3165 // Cliff resistance to erosion
3167 {
3168 // First check that this is a valid double
3169 if (! bIsStringValidDouble(strRH))
3170 {
3171 strErr = "line " + to_string(nLine) +
3172 ": invalid floating point number for cliff resistance "
3173 "to erosion '" +
3174 strRH + "' in " + m_strDataPathName;
3175 break;
3176 }
3177
3178 m_dCliffErosionResistance = strtod(strRH.c_str(), NULL);
3179
3181 strErr = "line " + to_string(nLine) +
3182 ": cliff resistance to erosion must be > 0";
3183 }
3184
3185 break;
3186
3187 case 61:
3188 // Notch overhang at collapse (m)
3190 {
3191 // First check that this is a valid double
3192 if (! bIsStringValidDouble(strRH))
3193 {
3194 strErr = "line " + to_string(nLine) +
3195 ": invalid floating point number for cliff notch "
3196 "overhang at collapse '" +
3197 strRH + "' in " + m_strDataPathName;
3198 break;
3199 }
3200
3201 m_dNotchDepthAtCollapse = strtod(strRH.c_str(), NULL);
3202
3203 if (m_dNotchDepthAtCollapse <= 0)
3204 strErr = "line " + to_string(nLine) +
3205 ": cliff notch overhang at collapse must be > 0";
3206 }
3207
3208 break;
3209
3210 case 62:
3211 // Notch base below still water level (m)
3213 {
3214 m_dNotchBaseBelowSWL = strtod(strRH.c_str(), NULL);
3215
3216 if (m_dNotchBaseBelowSWL < 0)
3217 strErr = "line " + to_string(nLine) +
3218 ": cliff notch base below still water level must be > 0";
3219 }
3220
3221 break;
3222
3223 case 63:
3224 // Scale parameter A for cliff deposition (m^(1/3)) [0 = auto]
3226 {
3227 // First check that this is a valid double
3228 if (! bIsStringValidDouble(strRH))
3229 {
3230 strErr = "line " + to_string(nLine) +
3231 ": invalid floating point number for scale parameter A "
3232 "for cliff deposition '" +
3233 strRH + "' in " + m_strDataPathName;
3234 break;
3235 }
3236
3237 m_dCliffDepositionA = strtod(strRH.c_str(), NULL);
3238
3239 if (m_dCliffDepositionA < 0)
3240 strErr = "line " + to_string(nLine) +
3241 ": scale parameter A for cliff deposition must be 0 [= "
3242 "auto] or greater";
3243 }
3244
3245 break;
3246
3247 case 64:
3248 // Approximate planview width of cliff collapse talus (in m)
3250 {
3251 // First check that this is a valid double
3252 if (! bIsStringValidDouble(strRH))
3253 {
3254 strErr = "line " + to_string(nLine) +
3255 ": invalid floating point number for width of cliff "
3256 "collapse talus '" +
3257 strRH + "' in " + m_strDataPathName;
3258 break;
3259 }
3260
3261 m_dCliffDepositionPlanviewWidth = strtod(strRH.c_str(), NULL);
3262
3264 strErr = "line " + to_string(nLine) +
3265 ": planview width of cliff deposition must be > 0";
3266 }
3267
3268 break;
3269
3270 case 65:
3271 // Planview length of cliff deposition talus (m)
3273 {
3274 // First check that this is a valid double
3275 if (! bIsStringValidDouble(strRH))
3276 {
3277 strErr = "line " + to_string(nLine) +
3278 ": invalid floating point number for planview length of "
3279 "cliff deposition '" +
3280 strRH + "' in " + m_strDataPathName;
3281 break;
3282 }
3283
3284 m_dCliffTalusMinDepositionLength = strtod(strRH.c_str(), NULL);
3285
3287 strErr = "line " + to_string(nLine) +
3288 ": planview length of cliff deposition must be > 0";
3289 }
3290
3291 break;
3292
3293 case 66:
3294 // Minimum height of landward end of talus, as a fraction of cliff
3295 // elevation
3297 {
3298 // First check that this is a valid double
3299 if (! bIsStringValidDouble(strRH))
3300 {
3301 strErr = "line " + to_string(nLine) +
3302 ": invalid floating point number for height of cliff "
3303 "collapse (as a fraction of cliff elevation) '" +
3304 strRH + "' in " + m_strDataPathName;
3305 break;
3306 }
3307
3308 m_dMinCliffTalusHeightFrac = strtod(strRH.c_str(), NULL);
3309
3311 strErr = "line " + to_string(nLine) +
3312 ": minimum height of cliff collapse (as a fraction of "
3313 "cliff elevation) must be >= 0";
3314 }
3315
3316 break;
3317
3318 // -------------------------------------------------- Input events data
3319 // -----------------------------------------------
3320 case 67:
3321 // Simulate riverine flooding?
3322 strRH = strToLower(&strRH);
3323
3324 if (strRH.find('y') != string::npos)
3325 {
3326 m_bRiverineFlooding = true;
3330 }
3331
3332 break;
3333
3334 case 68:
3335 // Output riverine flooding vector files
3337 {
3338 if (! strRH.empty())
3339 {
3340 // Convert to lower case
3341 strRH = strToLower(&strRH);
3342
3343 // First look for "all"
3344 if (strRH.find(VECTOR_ALL_RIVER_FLOOD_OUTPUT_CODE) !=
3345 string::npos)
3346 {
3349 }
3350
3351 else
3352 {
3353 // We are not outputting all vector flood GIS files, so set
3354 // switches (and remove strings) for those optional files for
3355 // which the user specified the code
3356 if (strRH.find(VECTOR_FLOOD_SWL_SETUP_LINE_CODE) !=
3357 string::npos)
3358 {
3359 m_bFloodSWLSetupLine = true;
3360 strRH = strRemoveSubstr(&strRH,
3362 }
3363
3365 string::npos)
3366 {
3368 strRH = strRemoveSubstr(
3370 }
3371
3373 string::npos)
3374 {
3376 strRH = strRemoveSubstr(
3378 }
3379
3380 // Check to see if all codes have been removed
3381 if (! strRH.empty())
3382 strErr = "line " + to_string(nLine) + ": unknown code '" +
3383 strRH +
3384 "' in list of riverine flooding output codes";
3385 }
3386 }
3387
3388 else
3389 strErr = "line " + to_string(nLine) +
3390 ": if simulating riverine flooding, must contain '" +
3392 "' or at least one vector GIS output code for riverine "
3393 "flooding";
3394 }
3395
3396 break;
3397
3398 case 69:
3400 {
3401 // Run-up equation?
3402 if (bIsStringValidInt(strRH))
3403 {
3404 m_nRunUpEquation = stoi(strRH);
3405 }
3406
3407 else
3408 strErr = "line " + to_string(nLine) +
3409 ": invalid code for run-up equation used in simulating "
3410 "floods";
3411 }
3412
3413 break;
3414
3415 case 70:
3417 {
3418 // Characteristic locations for flood?
3419 strRH = strToLower(&strRH);
3420
3421 m_bFloodLocation = false;
3422
3423 if (strRH.find('y') != string::npos)
3424 {
3425 m_bFloodLocation = true;
3426 }
3427 }
3428
3429 break;
3430
3431 case 71:
3433 {
3434 // Path of location points file
3435 if (! strRH.empty())
3436 {
3437#ifdef _WIN32
3438 // For Windows, make sure has backslashes, not Unix-style slashes
3439 strRH = pstrChangeToBackslash(&strRH);
3440#endif
3441
3442 // Now check for leading slash, or leading Unix home dir symbol,
3443 // or occurrence of a drive letter
3444 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) ||
3445 (strRH[1] == COLON))
3446 // It has an absolute path, so use it 'as is'
3448
3449 else
3450 {
3451 // It has a relative path, so prepend the CoastalME dir
3453 m_strFloodLocationShapefile.append(strRH);
3454 }
3455
3456 // Set the switch
3457 m_bFloodLocation = true;
3458 }
3459
3460 else
3461 strErr = "line " + to_string(nLine) +
3462 ": path of location points file must not be empty if "
3463 "simulating floods";
3464 }
3465
3466 break;
3467
3468 case 72:
3469 // Simulate sediment input?
3470 strRH = strToLower(&strRH);
3471
3472 if (strRH.find('y') != string::npos)
3473 {
3474 m_bSedimentInput = true;
3476 }
3477
3478 break;
3479
3480 case 73:
3481 // Sediment input location (point or line shapefile)
3482 if (m_bSedimentInput)
3483 {
3484 if (! strRH.empty())
3485 {
3486#ifdef _WIN32
3487 // For Windows, make sure has backslashes, not Unix-style slashes
3488 strRH = pstrChangeToBackslash(&strRH);
3489#endif
3490
3491 // Now check for leading slash, or leading Unix home dir symbol,
3492 // or occurrence of a drive letter
3493 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) ||
3494 (strRH[1] == COLON))
3495 // It has an absolute path, so use it 'as is'
3497
3498 else
3499 {
3500 // It has a relative path, so prepend the CoastalME dir
3503 }
3504 }
3505 }
3506
3507 break;
3508
3509 case 74:
3510 // Sediment input type: required if have shapefile [P = Point, C =
3511 // coast block, L = line]
3512 if (m_bSedimentInput)
3513 {
3514 strRH = strToLower(&strRH);
3515
3516 if (strRH.find('p') != string::npos)
3518
3519 else if (strRH.find('c') != string::npos)
3521
3522 else if (strRH.find('l') != string::npos)
3524
3525 else
3526 strErr = "line " + to_string(nLine) +
3527 ": Sediment input type must be P, C, or L";
3528 }
3529
3530 break;
3531
3532 case 75:
3533 // Sediment input details file (required if have shapefile)
3534 if (m_bSedimentInput)
3535 {
3536 if (strRH.empty())
3537 {
3538 strErr = "line " + to_string(nLine) +
3539 ": filename missing for sediment input";
3540 break;
3541 }
3542
3543#ifdef _WIN32
3544 // For Windows, make sure has backslashes, not Unix-style slashes
3545 strRH = pstrChangeToBackslash(&strRH);
3546#endif
3547
3548 // Now check for leading slash, or leading Unix home dir symbol, or
3549 // occurrence of a drive letter
3550 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) ||
3551 (strRH[1] == COLON))
3552 {
3553 // It has an absolute path, so use it 'as is'
3555 }
3556
3557 else
3558 {
3559 // It has a relative path, so prepend the CoastalME dir
3561 m_strSedimentInputEventFile.append(strRH);
3562 }
3563 }
3564
3565 break;
3566
3567 // ------------------------------------------------------ Other data
3568 // --------------------------------------------------
3569 case 76:
3570 // Gravitational acceleration (m2/s). First check that this is a valid
3571 // double
3572 if (! bIsStringValidDouble(strRH))
3573 {
3574 strErr = "line " + to_string(nLine) +
3575 ": invalid floating point number for gravitational "
3576 "acceleration '" +
3577 strRH + "' in " + m_strDataPathName;
3578 break;
3579 }
3580
3581 m_dG = strtod(strRH.c_str(), NULL);
3582
3583 if (m_dG <= 0)
3584 strErr = "line " + to_string(nLine) +
3585 ": gravitational acceleration must be > 0";
3586
3587 break;
3588
3589 case 77:
3590 // Spacing of coastline normals (m)
3591 m_dCoastNormalSpacing = strtod(strRH.c_str(), NULL);
3592
3595 DEFAULT_PROFILE_SPACING; // In cells, we will set
3596 // m_dCoastNormalSpacing later when we
3597 // know m_dCellSide
3598
3599 else if (m_dCoastNormalSpacing < 0)
3600 strErr = "line " + to_string(nLine) +
3601 ": spacing of coastline normals must be > 0";
3602
3603 break;
3604
3605 case 78:
3606 // Random factor for spacing of normals [0 to 1, 0 = deterministic],
3607 // check that this is a valid double
3608 if (! bIsStringValidDouble(strRH))
3609 {
3610 strErr = "line " + to_string(nLine) +
3611 ": invalid floating point number for random factor for "
3612 "spacing of coastline normals '" +
3613 strRH + "' in " + m_strDataPathName;
3614 break;
3615 }
3616
3617 m_dCoastNormalRandSpacingFactor = strtod(strRH.c_str(), NULL);
3618
3620 strErr =
3621 "line " + to_string(nLine) +
3622 ": random factor for spacing of coastline normals must be >= 0";
3623
3625 strErr =
3626 "line " + to_string(nLine) +
3627 ": random factor for spacing of coastline normals must be < 1";
3628
3629 break;
3630
3631 case 79:
3632 // Length of coastline normals (m), check that this is a valid double
3633 if (! bIsStringValidDouble(strRH))
3634 {
3635 strErr = "line " + to_string(nLine) +
3636 ": invalid floating point number for length of coastline "
3637 "normals '" +
3638 strRH + "' in " + m_strDataPathName;
3639 break;
3640 }
3641
3642 m_dCoastNormalLength = strtod(strRH.c_str(), NULL);
3643
3644 if (m_dCoastNormalLength <= 0)
3645 strErr = "line " + to_string(nLine) +
3646 ": length of coastline normals must be > 0";
3647
3648 break;
3649
3650 case 80:
3651 // Start depth for wave calcs (ratio to deep water wave height), check
3652 // that this is a valid double
3653 if (! bIsStringValidDouble(strRH))
3654 {
3655 strErr = "line " + to_string(nLine) +
3656 ": invalid floating point number for start depth for wave "
3657 "calcs '" +
3658 strRH + "' in " + m_strDataPathName;
3659 break;
3660 }
3661
3662 m_dWaveDepthRatioForWaveCalcs = strtod(strRH.c_str(), NULL);
3663
3665 strErr = "line " + to_string(nLine) +
3666 ": start depth for wave calcs must be > 0";
3667
3668 break;
3669
3670 // ----------------------------------------------------- Testing only
3671 // -------------------------------------------------
3672 case 81:
3673 // Output profile data?
3674 strRH = strToLower(&strRH);
3675
3676 m_bOutputProfileData = false;
3677
3678 if (strRH.find('y') != string::npos)
3679 {
3680 m_bOutputProfileData = true;
3681
3683 {
3684 strErr = "line " + to_string(nLine) +
3685 ": cannot save profiile data if not simulating shore "
3686 "platform erosion";
3687 break;
3688 }
3689
3690 // TODO 043 What about randomness of profile spacing, since profile
3691 // location is determined by curvature?
3692 }
3693
3694 break;
3695
3696 case 82:
3697 // Numbers of profiles to be saved
3699 {
3700 VstrTmp = VstrSplit(&strRH, SPACE);
3701
3702 for (unsigned int j = 0; j < VstrTmp.size(); j++)
3703 {
3704 VstrTmp[j] = strTrim(&VstrTmp[j]);
3705
3706 if (! bIsStringValidInt(VstrTmp[j]))
3707 {
3708 strErr = "line " + to_string(nLine) +
3709 ": invalid integer for profile to be saved '" +
3710 VstrTmp[j] + "' in " + m_strDataPathName;
3711 break;
3712 }
3713
3714 int const nTmp = stoi(VstrTmp[j]);
3715
3716 if (nTmp < 0)
3717 {
3718 strErr = "line " + to_string(nLine) +
3719 ": Profile number for saving must be >= 0";
3720 break;
3721 }
3722
3723 m_VnProfileToSave.push_back(nTmp);
3724 }
3725 }
3726
3727 break;
3728
3729 case 83:
3730 // Timesteps to save profiles
3732 {
3733 VstrTmp = VstrSplit(&strRH, SPACE);
3734
3735 for (unsigned int j = 0; j < VstrTmp.size(); j++)
3736 {
3737 VstrTmp[j] = strTrim(&VstrTmp[j]);
3738 unsigned long const ulTmp = atol(VstrTmp[j].c_str());
3739
3740 if (ulTmp < 1)
3741 {
3742 strErr = "line " + to_string(nLine) +
3743 ": Timestep for profile saves must >= 1";
3744 break;
3745 }
3746
3747 m_VulProfileTimestep.push_back(ulTmp);
3748 }
3749 }
3750
3751 break;
3752
3753 case 84:
3754 // Output parallel profile data?
3755 strRH = strToLower(&strRH);
3756
3758
3759 if (strRH.find('y') != string::npos)
3761
3762 break;
3763
3764 case 85:
3765 // Output erosion potential look-up data?
3766 strRH = strToLower(&strRH);
3767
3769
3770 if (strRH.find('y') != string::npos)
3772
3773 break;
3774
3775 case 86:
3776 // Size of moving window for coastline curvature calculation (must be
3777 // odd)
3778 if (! bIsStringValidInt(strRH))
3779 {
3780 strErr = "line ";
3781 strErr += to_string(nLine);
3782 strErr +=
3783 ": invalid integer for size of moving window for "
3784 "coastline curvature calculation '";
3785 strErr += strRH;
3786 strErr += "' in ";
3787 strErr += m_strDataPathName;
3788
3789 break;
3790 }
3791
3793
3796 {
3797 strErr = "line ";
3798 strErr += to_string(nLine);
3799 strErr +=
3800 ": size of moving window for coastline curvature "
3801 "calculation (must be > 0 and odd)";
3802 }
3803
3804 break;
3805
3806 case 87:
3807 // Cliff edge smoothing algorithm: 0 = none, 1 = running mean, 2 =
3808 // Savitzky-Golay
3809 if (! bIsStringValidInt(strRH))
3810 {
3811 strErr = "line ";
3812 strErr += to_string(nLine);
3813 strErr += ": invalid integer for cliff edge smoothing algorithm '";
3814 strErr += strRH;
3815 strErr += "' in " + m_strDataPathName;
3816
3817 break;
3818 }
3819
3820 m_nCliffEdgeSmooth = stoi(strRH);
3821
3824 strErr =
3825 "line " + to_string(nLine) + ": cliff edge smoothing algorithm";
3826
3827 break;
3828
3829 case 88:
3830 // Size of cliff edge smoothing window: must be odd
3831 if (! bIsStringValidInt(strRH))
3832 {
3833 strErr = "line " + to_string(nLine) +
3834 ": invalid integer for cliff edge smoothing window '" +
3835 strRH + "' in " + m_strDataPathName;
3836 break;
3837 }
3838
3839 m_nCliffEdgeSmoothWindow = stoi(strRH);
3840
3841 if ((m_nCliffEdgeSmoothWindow <= 0) ||
3843 strErr =
3844 "line " + to_string(nLine) +
3845 ": size of cliff edge smoothing window (must be > 0 and odd)";
3846
3847 break;
3848
3849 case 89:
3850 // Order of cliff edge smoothing polynomial for Savitzky-Golay:
3851 // usually 2 or 4, max is 6
3852 if (! bIsStringValidInt(strRH))
3853 {
3854 strErr = "line " + to_string(nLine) +
3855 ": invalid integer for Savitzky-Golay polynomial for "
3856 "cliff edge smoothing '" +
3857 strRH + "' in " + m_strDataPathName;
3858 break;
3859 }
3860
3861 m_nSavGolCliffEdgePoly = stoi(strRH);
3862
3865 strErr = "line " + to_string(nLine) +
3866 ": order of Savitzky-Golay polynomial for cliff edge "
3867 "smoothing (must be 2, 4 or 6)";
3868
3869 break;
3870
3871 case 90:
3872 // Cliff slope limit for cliff toe detection
3873 if (! bIsStringValidDouble(strRH))
3874 {
3875 strErr = "line " + to_string(nLine) +
3876 ": invalid number for cliff slope limit '" + strRH +
3877 "' in " + m_strDataPathName;
3878 break;
3879 }
3880
3881 m_dCliffSlopeLimit = stod(strRH);
3882
3883 if (m_dCliffSlopeLimit <= 0)
3884 strErr =
3885 "line " + to_string(nLine) + ": cliff slope limit must be > 0";
3886
3887 break;
3888 }
3889
3890 // Did an error occur?
3891 if (! strErr.empty())
3892 {
3893 // Error in input to run details file
3894 cerr << endl
3895 << ERR << strErr << ".\nPlease edit " << m_strDataPathName
3896 << " and change this line:" << endl;
3897 cerr << "'" << strRec << "'" << endl
3898 << endl;
3899 InStream.close();
3900 return false;
3901 }
3902 }
3903 }
3904
3905 // Close file
3906 InStream.close();
3907
3908 // Finally, need to check that we have at least one raster file, so that we
3909 // know the grid size and units (and preferably also the projection)
3910 bool bNoRasterFiles = true;
3911
3912 if ((! m_strInitialBasementDEMFile.empty()) ||
3913 (! m_strInitialSuspSedimentFile.empty()) ||
3914 (! m_strInitialLandformFile.empty()) ||
3915 (! m_strInterventionHeightFile.empty()))
3916 bNoRasterFiles = false;
3917
3918 for (int j = 0; j < m_nLayers; j++)
3919 {
3920 if ((! m_VstrInitialFineUnconsSedimentFile[j].empty()) ||
3921 (! m_VstrInitialSandUnconsSedimentFile[j].empty()) ||
3923 (! m_VstrInitialFineConsSedimentFile[j].empty()) ||
3924 (! m_VstrInitialSandConsSedimentFile[j].empty()) ||
3926 bNoRasterFiles = false;
3927 }
3928
3929 if (bNoRasterFiles)
3930 {
3931 // No raster files
3932 cerr << ERR << "at least one raster GIS file is needed" << endl;
3933 return false;
3934 }
3935
3936 return true;
3937}
3938
3939//===============================================================================================================================
3941//===============================================================================================================================
3943{
3944 // Create an ifstream object
3945 ifstream InStream;
3946
3947 // Try to open the file for input
3948 InStream.open(m_strTideDataFile.c_str(), ios::in);
3949
3950 // Did it open OK?
3951 if (! InStream.is_open())
3952 {
3953 // Error: cannot open tide data file for input
3954 cerr << ERR << "cannot open " << m_strTideDataFile << " for input" << endl;
3955 return RTN_ERR_TIDEDATAFILE;
3956 }
3957
3958 // Opened OK
3959 int nLine = 0;
3960 string strRec;
3961
3962 // Now read the data from the file
3963 while (getline(InStream, strRec))
3964 {
3965 nLine++;
3966
3967 // Trim off leading and trailing whitespace
3968 strRec = strTrim(&strRec);
3969
3970 // If it is a blank line or a comment then ignore it
3971 if ((strRec.empty()) || (strRec[0] == QUOTE1) || (strRec[0] == QUOTE2))
3972 continue;
3973
3974 // Check that this is a valid double
3975 if (! bIsStringValidDouble(strRec))
3976 {
3977 cerr << ERR << "invalid floating point number for tide data '" << strRec
3978 << "' on line " << nLine << " of " << m_strTideDataFile << endl;
3979 return RTN_ERR_TIDEDATAFILE;
3980 }
3981
3982 // Convert to double then append the value to the vector
3983 m_VdTideData.push_back(strtod(strRec.c_str(), NULL));
3984 }
3985
3986 // Close file
3987 InStream.close();
3988
3989 return RTN_OK;
3990}
3991
3992//===============================================================================================================================
3995//===============================================================================================================================
3997{
3998 // Sort out the path and filename
4002
4003 // Create an ifstream object
4004 ifstream InStream;
4005
4006 // Try to open the file for input
4007 InStream.open(m_strSCAPEShapeFunctionFile.c_str(), ios::in);
4008
4009 // Did it open OK?
4010 if (! InStream.is_open())
4011 {
4012 // Error: cannot open shape function file for input
4013 cerr << ERR << "cannot open " << m_strSCAPEShapeFunctionFile << " for input"
4014 << endl;
4016 }
4017
4018 // Opened OK
4019 int nLine = 0;
4020 int nExpected = 0, nRead = 0;
4021 string strRec;
4022
4023 // Read in the number of data lines expected
4024 InStream >> nExpected;
4025
4026 // Set up the vectors to hold the input data
4027 vector<double> VdDepthOverDB;
4028 vector<double> VdErosionPotential;
4029 vector<double> VdErosionPotentialFirstDeriv;
4030
4031 // Now read the rest of the data from the file to get the Erosion Potential
4032 // Shape function
4033 while (getline(InStream, strRec))
4034 {
4035 nLine++;
4036
4037 // Trim off leading and trailing whitespace
4038 strRec = strTrim(&strRec);
4039
4040 // If it is a blank line or a comment then ignore it
4041 if ((strRec.empty()) || (strRec[0] == QUOTE1) || (strRec[0] == QUOTE2))
4042 continue;
4043
4044 // It isn't so increment counter
4045 nRead++;
4046
4047 // Split the string, and remove whitespace
4048 vector<string> strTmp = VstrSplit(&strRec, SPACE);
4049
4050 for (unsigned int i = 0; i < strTmp.size(); i++)
4051 {
4052 // Remove leading and trailing whitespace
4053 strTmp[i] = strTrim(&strTmp[i]);
4054
4055 // Check that this is a valid double
4056 if (! bIsStringValidDouble(strTmp[i]))
4057 {
4058 cerr << ERR
4059 << "on line " + to_string(nLine) +
4060 " invalid floating point number for Erosion Potential "
4061 "Shape data '"
4062 << strTmp[i] << "' in " << m_strSCAPEShapeFunctionFile << endl;
4064 }
4065 }
4066
4067 // Convert to doubles then append the values to the vectors
4068 VdDepthOverDB.push_back(strtod(strTmp[0].c_str(), NULL));
4069 VdErosionPotential.push_back(strtod(strTmp[1].c_str(), NULL));
4070 VdErosionPotentialFirstDeriv.push_back(strtod(strTmp[2].c_str(), NULL));
4071 }
4072
4073 // Now create the look up table values
4074 m_VdErosionPotential = VdErosionPotential;
4075 m_VdDepthOverDB = VdDepthOverDB;
4076 m_dDepthOverDBMax = VdDepthOverDB[14];
4077
4078 // Close file
4079 InStream.close();
4080
4081 // Did we read in what we expected?
4082 if (nExpected != nRead)
4083 {
4084 cout << ERR << "read in " << nRead << " lines from "
4085 << m_strSCAPEShapeFunctionFile << " but " << nExpected
4086 << " lines expected" << endl;
4088 }
4089
4090 // Is the shape funcion well defined? i.e. it must be -ve or 0.0 for all
4091 // values
4092 for (unsigned int j = 0; j < m_VdErosionPotential.size(); j++)
4093 {
4094 if (m_VdErosionPotential[j] > 0)
4095 {
4096 cout << ERR << " in " << m_strSCAPEShapeFunctionFile
4097 << ", erosion potential function cannot be positive" << endl;
4099 }
4100 }
4101
4102 // OK, now use this data to create a look-up table to be used for the rest of
4103 // the simulation
4104 if (! bCreateErosionPotentialLookUp(&VdDepthOverDB, &VdErosionPotential,
4105 &VdErosionPotentialFirstDeriv))
4106 {
4107 cout << ERR << "line " + to_string(nLine) + " in "
4109 << ": erosion potential function is unbounded for high values of "
4110 "depth over DB"
4111 << endl;
4113 }
4114
4115 return RTN_OK;
4116}
4117
4118//===============================================================================================================================
4122//===============================================================================================================================
4123int CSimulation::nReadWaveStationInputFile(int const nWaveStations)
4124{
4125 // Create an ifstream object
4126 ifstream InStream;
4127
4128 // Try to open the file for input
4129 InStream.open(m_strDeepWaterWavesInputFile.c_str(), ios::in);
4130
4131 // Did it open OK?
4132 if (! InStream.is_open())
4133 {
4134 // Error: cannot open time series file for input
4135 cerr << ERR << "cannot open " << m_strDeepWaterWavesInputFile
4136 << " for input" << endl;
4138 }
4139
4140 // Opened OK
4141 int nLine = 0;
4142 int nExpectedStations = 0;
4143 int nRead = 0;
4144 int nTimeStepsRead = 0;
4145 string strRec, strErr;
4146
4147 // Read each line, ignoring blank lines and comment lines
4148 while (getline(InStream, strRec))
4149 {
4150 nLine++;
4151
4152 // Trim off leading and trailing whitespace
4153 strRec = strTrim(&strRec);
4154
4155 // If it is a blank line or a comment then ignore it
4156 if ((! strRec.empty()) && (strRec[0] != QUOTE1) && (strRec[0] != QUOTE2))
4157 {
4158 // It isn't so increment counter
4159 nRead++;
4160
4161 // The header lines (the first four lines of the file) contains leading
4162 // description separated by a colon from the data
4163 if (nRead < 5)
4164 {
4165 // Find the colon: note that lines MUST have a colon separating data
4166 // from leading description portion
4167 size_t nPos = strRec.find(COLON);
4168
4169 if (nPos == string::npos)
4170 {
4171 // Error: badly formatted (no colon)
4172 cerr << ERR << "on line " << to_string(nLine)
4173 << "badly formatted (no ':') in " << m_strDeepWaterWavesInputFile
4174 << endl
4175 << "'" << strRec << "'" << endl;
4177 }
4178
4179 if (nPos == strRec.size() - 1)
4180 {
4181 // Error: badly formatted (colon with nothing following)
4182 cerr << ERR << "on line " << to_string(nLine)
4183 << "badly formatted (nothing following ':') in "
4185 << "'" << strRec << "'" << endl;
4187 }
4188
4189 // Strip off leading portion (the bit up to and including the colon)
4190 string strRH = strRec.substr(nPos + 1);
4191
4192 // Remove leading whitespace
4193 strRH = strTrimLeft(&strRH);
4194
4195 // Look for a trailing comment, if found then terminate string at that
4196 // point and trim off any trailing whitespace
4197 nPos = strRH.rfind(QUOTE1);
4198
4199 if (nPos != string::npos)
4200 strRH.resize(nPos);
4201
4202 nPos = strRH.rfind(QUOTE2);
4203
4204 if (nPos != string::npos)
4205 strRH.resize(nPos);
4206
4207 // Remove trailing whitespace
4208 strRH = strTrimRight(&strRH);
4209
4210 int nSec = 0;
4211 int nMin = 0;
4212 int nHour = 0;
4213 int nDay = 0;
4214 int nMonth = 0;
4215 int nYear = 0;
4216 double dMult;
4217 double dThisIter;
4218 vector<string> VstrTmp;
4219
4220 switch (nRead)
4221 {
4222 case 1:
4223 // Get the start date/time for this data, format is [hh-mm-ss
4224 // dd/mm/yyyy]
4225 VstrTmp = VstrSplit(&strRH, SPACE);
4226
4227 // Both date and time here?
4228 if (VstrTmp.size() < 2)
4229 {
4230 strErr = "line " + to_string(nLine) +
4231 ": must have both date and time for start of data in";
4232 break;
4233 }
4234
4235 // OK, first sort out the time
4236 if (! bParseTime(&VstrTmp[0], nHour, nMin, nSec))
4237 {
4238 strErr = "line " + to_string(nLine) +
4239 ": could not understand start time for data";
4240 break;
4241 }
4242
4243 // Next sort out the date
4244 if (! bParseDate(&VstrTmp[1], nDay, nMonth, nYear))
4245 {
4246 strErr = "line " + to_string(nLine) +
4247 ": could not understand start date for data";
4248 break;
4249 }
4250
4251 // Compare time and date with simulation time and date
4252 if ((nSec != m_nSimStartSec) || (nMin != m_nSimStartMin) ||
4253 (nHour != m_nSimStartHour) || (nDay != m_nSimStartDay) ||
4254 (nMonth != m_nSimStartMonth) || (nYear != m_nSimStartYear))
4255 {
4256 strErr = "line " + to_string(nLine) +
4257 ": start time and date for wave time series data differs "
4258 "from simulation start time and date,";
4259 break;
4260 }
4261
4262 break;
4263
4264 case 2:
4265 // Get the timestep of this data (in hours or days)
4266 strRH = strToLower(&strRH);
4267
4268 dMult = dGetTimeMultiplier(&strRH);
4269
4270 if (static_cast<int>(dMult) == TIME_UNKNOWN)
4271 {
4272 strErr =
4273 "line " + to_string(nLine) + ": unknown units for timestep";
4274 break;
4275 }
4276
4277 // We have the multiplier, now calculate the timestep in hours: look
4278 // for the whitespace between the number and unit
4279 nPos = strRH.rfind(SPACE);
4280
4281 if (nPos == string::npos)
4282 {
4283 strErr = "line " + to_string(nLine) + ": format of timestep line";
4284 break;
4285 }
4286
4287 // Cut off rh bit of string
4288 strRH.resize(nPos);
4289
4290 // Remove trailing spaces
4291 strRH = strTrimRight(&strRH);
4292
4293 // Check that this is a valid double
4294 if (! bIsStringValidDouble(strRH))
4295 {
4296 strErr = "line " + to_string(nLine) +
4297 ": invalid floating point number for timestep";
4298 break;
4299 }
4300
4301 dThisIter = strtod(strRH.c_str(), NULL) * dMult; // in hours
4302
4303 if (dThisIter <= 0)
4304 strErr = "line " + to_string(nLine) + ": timestep must be > 0";
4305
4306 if (! bFPIsEqual(dThisIter, m_dTimeStep, TOLERANCE))
4307 strErr = "line " + to_string(nLine) +
4308 ": timestep must be the same as the simulation timestep";
4309
4310 break;
4311
4312 case 3:
4313
4314 // Read the number of stations
4315 if (! bIsStringValidInt(strRH))
4316 {
4317 strErr = "line " + to_string(nLine) +
4318 ": invalid integer for number of wave stations '" + strRH +
4320 break;
4321 }
4322
4323 nExpectedStations = stoi(strRH);
4324
4325 // Check that the number of expected stations is equal to the number
4326 // of stations on the point shape file
4327 if (nExpectedStations != nWaveStations)
4328 {
4329 // Error: number of points on shape file does not match the number
4330 // of stations on the wave time series file
4331 strErr = "line " + to_string(nLine) +
4332 ": number of wave stations in " +
4334 to_string(nWaveStations) + " but we have " +
4335 to_string(nExpectedStations) + " stations";
4336
4337 break;
4338 }
4339
4340 break;
4341
4342 case 4:
4343
4344 // Read the expected number of time steps in the file
4345 if (! bIsStringValidInt(strRH))
4346 {
4347 strErr = "line " + to_string(nLine) +
4348 ": invalid integer for expected number of time steps '" +
4349 strRH + "' in " + m_strDeepWaterWaveStationsShapefile;
4350 break;
4351 }
4352
4354
4356 {
4357 // Error: must have value(s) for at least one timestep
4358 strErr = "line " + to_string(nLine) +
4359 ": must have values for at least one timestep";
4360 break;
4361 }
4362
4363 break;
4364 }
4365 }
4366
4367 else
4368 {
4369 // This is not a header line
4370 nTimeStepsRead++;
4371
4372 // Read in each wave attribute for each time step and station: split the
4373 // string, and remove whitespace
4374 vector<string> VstrTmp = VstrSplit(&strRec, COMMA);
4375
4376 for (unsigned int i = 0; i < VstrTmp.size();
4377 i++) // VstrTmp.size() should be 3 x nExpectedStations
4378 {
4379 // Remove leading and trailing whitespace
4380 VstrTmp[i] = strTrim(&VstrTmp[i]);
4381
4382 // Check that this is a valid double
4383 if (! bIsStringValidDouble(VstrTmp[i]))
4384 {
4385 strErr =
4386 "line " + to_string(nLine) +
4387 ": invalid floating point number for deep water wave value '" +
4388 VstrTmp[i] + "' in " + m_strDeepWaterWavesInputFile;
4389 break;
4390 }
4391 }
4392
4393 // Convert to doubles then append the values to the vectors
4394 int n = 0;
4395
4396 for (int i = 0; i < nExpectedStations; i++)
4397 {
4399 strtod(VstrTmp[n + 0].c_str(), NULL));
4401 strtod(VstrTmp[n + 1].c_str(), NULL));
4403 strtod(VstrTmp[n + 2].c_str(), NULL));
4404
4405 // Check some simple wave input stats
4409
4413
4414 n += 3;
4415 }
4416 }
4417 }
4418
4419 // Did an error occur?
4420 if (! strErr.empty())
4421 {
4422 // Error in input to initialisation file
4423 cerr << ERR << strErr << " in deep water wave time series file "
4425 << "'" << strRec << "'" << endl;
4426 InStream.close();
4427
4429 }
4430 }
4431
4432 if (nTimeStepsRead != m_nDeepWaterWaveDataNumTimeSteps)
4433 {
4434 // Error: number of timesteps read does not match the number given in the
4435 // file's header
4436 cerr << ERR << "in " << m_strDeepWaterWavesInputFile << ", data for "
4437 << nTimeStepsRead << " timesteps was read, but "
4439 << " timesteps were specified in the file's header" << endl;
4440
4442 }
4443
4444 // Close file
4445 InStream.close();
4446
4447 // Did we read in what we expected?
4448 unsigned int const nTotExpected =
4449 nExpectedStations * m_nDeepWaterWaveDataNumTimeSteps;
4450
4451 if (m_VdTSDeepWaterWaveStationHeight.size() != nTotExpected)
4452 {
4453 cout << ERR << "read in " << m_VdTSDeepWaterWaveStationHeight.size()
4454 << " lines from " << m_strDeepWaterWavesInputFile << " but "
4455 << nTotExpected << " values expected" << endl;
4456
4458 }
4459
4460 if (m_VdTSDeepWaterWaveStationAngle.size() != nTotExpected)
4461 {
4462 cout << ERR << "read in " << m_VdTSDeepWaterWaveStationAngle.size()
4463 << " lines from " << m_strDeepWaterWavesInputFile << " but "
4464 << nTotExpected << " values expected" << endl;
4465
4467 }
4468
4469 if (m_VdTSDeepWaterWaveStationPeriod.size() != nTotExpected)
4470 {
4471 cout << ERR << "read in " << m_VdTSDeepWaterWaveStationPeriod.size()
4472 << " lines from " << m_strDeepWaterWavesInputFile << " but "
4473 << nTotExpected << " values expected" << endl;
4474
4476 }
4477
4478 // All is OK, so we can now initialize the vectors that will store this
4479 // timestep's deep water wave values
4480 for (int j = 0; j < nExpectedStations; j++)
4481 {
4485 }
4486
4487 // Finally, check whether the wave data will 'wrap' i.e. whether the number of
4488 // timesteps is less than the total number of timesteps in the simulation
4489 int const nSimulationTimeSteps =
4490 static_cast<int>(floor(m_dSimDuration / m_dTimeStep));
4491
4492 if (m_nDeepWaterWaveDataNumTimeSteps < nSimulationTimeSteps)
4493 {
4495 string const strTmp =
4496 "Deep water wave data will wrap every " +
4498 "time step" + (m_nDeepWaterWaveDataNumTimeSteps > 1 ? "s" : "") +
4499 " (every " + to_string(m_dWaveDataWrapHours) + " hours)\n";
4500
4501 cout << NOTE << strTmp;
4502 }
4503
4504 return RTN_OK;
4505}
4506
4507//===============================================================================================================================
4509//===============================================================================================================================
4511{
4512 // Create an ifstream object
4513 ifstream InStream;
4514
4515 // Try to open the file for input
4516 InStream.open(m_strSedimentInputEventFile.c_str(), ios::in);
4517
4518 // Did it open OK?
4519 if (! InStream.is_open())
4520 {
4521 // Error: cannot open time series file for input
4522 cerr << ERR << "cannot open " << m_strSedimentInputEventFile << " for input"
4523 << endl;
4525 }
4526
4527 // Opened OK
4528 int nLine = 0;
4529 int nRead = 0;
4530 string strRec, strErr;
4531
4532 // Read each line, ignoring comment lines
4533 while (getline(InStream, strRec))
4534 {
4535 nLine++;
4536
4537 // Trim off leading and trailing whitespace
4538 strRec = strTrim(&strRec);
4539
4540 // If it is a blank line or a comment then ignore it
4541 if ((! strRec.empty()) && (strRec[0] != QUOTE1) && (strRec[0] != QUOTE2))
4542 {
4543 // It isn't so increment counter
4544 nRead++;
4545
4546 // Split at commas
4547 vector<string> VstrTmp = VstrSplit(&strRec, COMMA);
4548
4549 // Check that have all we need
4550 unsigned int nTarget = 7;
4551
4553 nTarget = 5;
4554
4555 if (VstrTmp.size() < nTarget)
4556 {
4557 strErr = "line " + to_string(nLine) +
4558 ": too few data items on data line '" + to_string(nRead) +
4560 break;
4561 }
4562
4563 // First item is the Location ID of the sediment input event (same as the
4564 // ID in the shapefile)
4565 if (! bIsStringValidInt(VstrTmp[0]))
4566 {
4567 strErr = "line " + to_string(nLine) +
4568 ": invalid integer for Location ID of sediment input event '" +
4569 VstrTmp[0] + "' in " + m_strSedimentInputEventFile;
4570 break;
4571 }
4572
4573 int const nID = stoi(strTrim(&VstrTmp[0]));
4574
4575 // OK, check the ID against IDs read in from the shapefile
4576 auto result = find(m_VnSedimentInputLocationID.begin(),
4577 m_VnSedimentInputLocationID.end(), nID);
4578
4579 if (result == m_VnSedimentInputLocationID.end())
4580 {
4581 strErr = "line " + to_string(nLine) + ": invalid Location ID '" +
4582 to_string(nID) +
4583 "' for sediment input event location event in " +
4585 break;
4586 }
4587
4588 // Next get the timestep at which the sediment input event occurs. This
4589 // may be specified either as a relative time (i.e. a number of hours or
4590 // days after the simulation start) or as an absolute time (i.e. a
4591 // time/date in the format hh-mm-ss dd/mm/yyyy)
4592 unsigned long const ulEventTimeStep = ulConvertToTimestep(&VstrTmp[1]);
4593
4594 if (ulEventTimeStep == SEDIMENT_INPUT_EVENT_ERROR)
4595 {
4596 strErr = "line " + to_string(nLine) + ": invalid time and/or date '" +
4597 VstrTmp[1] + "' for sediment input event in " +
4599 break;
4600 }
4601
4602 // Then the volume (m3) of fine sediment, first check that this is a valid
4603 // double
4604 if (! bIsStringValidDouble(VstrTmp[2]))
4605 {
4606 strErr = "line " + to_string(nLine) +
4607 ": invalid floating point number '" + VstrTmp[2] +
4608 "' for fine sediment volume for sediment input event in " +
4610 break;
4611 }
4612
4613 double const dFineSedVol = stod(strTrim(&VstrTmp[2]));
4614
4615 if (dFineSedVol < 0)
4616 {
4617 strErr = "line " + to_string(nLine) + ": negative number '" +
4618 to_string(dFineSedVol) +
4619 "' for fine sediment volume for sediment input event in " +
4621 break;
4622 }
4623
4624 if (dFineSedVol > 0)
4625 m_bHaveFineSediment = true;
4626
4627 // Then the volume (m3) of sand sediment, first check that this is a valid
4628 // double
4629 if (! bIsStringValidDouble(VstrTmp[3]))
4630 {
4631 strErr =
4632 "line " + to_string(nLine) + ": invalid floating point number '" +
4633 VstrTmp[3] +
4634 "' for sand-sized sediment volume for sediment input event in " +
4636 break;
4637 }
4638
4639 double const dSandSedVol = stod(strTrim(&VstrTmp[3]));
4640
4641 if (dSandSedVol < 0)
4642 {
4643 strErr =
4644 "line " + to_string(nLine) + ": negative number '" +
4645 to_string(dSandSedVol) +
4646 "' for sand-sized sediment volume for sediment input event in " +
4648 break;
4649 }
4650
4651 if (dSandSedVol > 0)
4652 m_bHaveSandSediment = true;
4653
4654 // Then the volume (m3) of coarse sediment, first check that this is a
4655 // valid double
4656 if (! bIsStringValidDouble(VstrTmp[4]))
4657 {
4658 strErr = "line " + to_string(nLine) +
4659 ": invalid floating point number '" + VstrTmp[4] +
4660 "' for coarse sediment volume for sediment input event in " +
4662 break;
4663 }
4664
4665 double const dCoarseSedVol = stod(strTrim(&VstrTmp[4]));
4666
4667 if (dCoarseSedVol < 0)
4668 {
4669 strErr = "line " + to_string(nLine) + ": negative number '" +
4670 to_string(dCoarseSedVol) +
4671 "' for coarse sediment volume of sediment input event in " +
4673 break;
4674 }
4675
4676 if (dCoarseSedVol > 0)
4677 m_bHaveCoarseSediment = true;
4678
4679 // Only read the last two items if we have on-coast sediment block
4680 // sediment input
4681 double dLen = 0;
4682 double dWidth = 0;
4683
4684 // double dThick = 0;
4686 {
4687 // The coast-normal length (m) of the sediment block, first check that
4688 // this is a valid double
4689 if (! bIsStringValidDouble(VstrTmp[5]))
4690 {
4691 strErr = "line " + to_string(nLine) +
4692 ": invalid floating point number '" + VstrTmp[5] +
4693 "' for coast-normal length of sediment input event in " +
4695 break;
4696 }
4697
4698 dLen = stod(strTrim(&VstrTmp[5]));
4699
4700 if (dLen <= 0)
4701 {
4702 strErr = "line " + to_string(nLine) +
4703 ": coast-normal length of the sediment block '" +
4704 to_string(dLen) + "' must be > 0 in " +
4706 break;
4707 }
4708
4709 // The along-coast width (m) of the sediment block, first check that
4710 // this is a valid double
4711 if (! bIsStringValidDouble(VstrTmp[6]))
4712 {
4713 strErr = "line " + to_string(nLine) +
4714 ": invalid floating point number '" + VstrTmp[6] +
4715 "' for along-coast width of sediment input event in " +
4717 break;
4718 }
4719
4720 dWidth = stod(strTrim(&VstrTmp[6]));
4721
4722 if ((! m_bSedimentInputAtCoast) && (dWidth <= 0))
4723 {
4724 strErr = "line " + to_string(nLine) +
4725 ": along-coast width (m) of the sediment block '" +
4726 to_string(dWidth) + "' must be > 0 in " +
4728 break;
4729 }
4730
4731 // // The along-coast thickness (m) of the sediment block, first check
4732 // that this is a valid double if (! bIsStringValidDouble(VstrTmp[7]))
4733 // {
4734 // strErr = "line " + to_string(nLine) + ": invalid floating point
4735 // number '" + VstrTmp[7] + "' for along-coast thickness of sediment
4736 // input event in " + m_strSedimentInputEventFile; break;
4737 // }
4738 //
4739 // dThick = stod(strTrim(&VstrTmp[7]));
4740 // if ((! m_bSedimentInputAtCoast) && (dWidth <= 0))
4741 // {
4742 // strErr = "line " + to_string(nLine) + ": along-coast thickness (m) of
4743 // the sediment block '" + to_string(dThick) + "' must be > 0 in " +
4744 // m_strSedimentInputEventFile; break;
4745 // }
4746 }
4747
4748 // Create the CSedInputEvent object
4749 CSedInputEvent *pEvent =
4750 new CSedInputEvent(nID, ulEventTimeStep, dFineSedVol, dSandSedVol,
4751 dCoarseSedVol, dLen, dWidth); //, dThick);
4752
4753 // And store it in the m_pVSedInputEvent vector
4754 m_pVSedInputEvent.push_back(pEvent);
4755 }
4756 }
4757
4758 // Did an error occur?
4759 if (! strErr.empty())
4760 {
4761 // Error in input to initialisation file
4762 cerr << ERR << strErr << " in sediment input event file "
4764 << "'" << strRec << "'" << endl;
4765 InStream.close();
4766
4768 }
4769
4770 // Close file
4771 InStream.close();
4772
4773 return RTN_OK;
4774}
4775
4776//===============================================================================================================================
4778//===============================================================================================================================
4780{
4781 CConfiguration config;
4782 if (! bConfigureFromYamlFile(config))
4783 return false;
4784
4785 // Apply configuration values to simulation object
4786 if (! bApplyConfiguration(config))
4787 return false;
4788
4789 return true;
4790}
4791
4792//===============================================================================================================================
4794//===============================================================================================================================
4796{
4797 CYamlParser parser;
4798
4799 if (! parser.bParseFile(m_strDataPathName))
4800 {
4801 cerr << ERR << "Failed to parse YAML file " << m_strDataPathName << ": "
4802 << parser.GetError() << endl;
4803 return false;
4804 }
4805
4806 CYamlNode root = parser.GetRoot();
4807
4808 // Helper function to process file paths with base path
4809 auto processFilePath = [&](string const &filePath) -> string
4810 {
4811 if (filePath.empty())
4812 return filePath;
4813
4814 // Check if base_path is specified in YAML
4815 string basePath;
4816 if (root.HasChild("base_path"))
4817 {
4818 basePath = root.GetChild("base_path").GetValue();
4819 if (! basePath.empty() && basePath.back() != PATH_SEPARATOR)
4820 {
4821 basePath += PATH_SEPARATOR;
4822 }
4823 }
4824
4825 // If no base path or file path is absolute, return as-is
4826 if (basePath.empty() || (filePath[0] == PATH_SEPARATOR) ||
4827 (filePath[0] == TILDE) ||
4828 (filePath.length() > 1 && filePath[1] == COLON))
4829 {
4830 return filePath;
4831 }
4832
4833 // Prepend base path to relative file path
4834 return basePath + filePath;
4835 };
4836
4837 try
4838 {
4839 // Run Information
4840 if (root.HasChild("run_information"))
4841 {
4842 CYamlNode runInfo = root.GetChild("run_information");
4843 if (runInfo.HasChild("output_file_names"))
4844 config.SetRunName(runInfo.GetChild("output_file_names").GetValue());
4845 if (runInfo.HasChild("log_file_detail"))
4846 config.SetLogFileDetail(
4847 runInfo.GetChild("log_file_detail").GetIntValue());
4848 if (runInfo.HasChild("csv_per_timestep_results"))
4850 runInfo.GetChild("csv_per_timestep_results").GetBoolValue());
4851 }
4852
4853 // simulation
4854 if (root.HasChild("simulation"))
4855
4856 {
4857 CYamlNode sim = root.GetChild("simulation");
4858 config.SetStartDateTime(sim.GetChild("start_date_time").GetValue());
4859 if (sim.HasChild("duration"))
4860 config.SetDuration(sim.GetChild("duration").GetValue());
4861 if (sim.HasChild("timestep"))
4862 config.SetTimestep(sim.GetChild("timestep").GetValue());
4863 if (sim.HasChild("save_times"))
4864 {
4865 CYamlNode saveTimes = sim.GetChild("save_times");
4866 if (saveTimes.IsSequence())
4867 config.SetSaveTimes(saveTimes.GetStringSequence());
4868 }
4869 if (sim.HasChild("random_seed"))
4870 config.SetRandomSeed(sim.GetChild("random_seed").GetIntValue());
4871 }
4872
4873 // GIS Output
4874 if (root.HasChild("gis_output"))
4875 {
4876 CYamlNode gis = root.GetChild("gis_output");
4877 if (gis.HasChild("max_save_digits"))
4878 config.SetMaxSaveDigits(gis.GetChild("max_save_digits").GetIntValue());
4879 if (gis.HasChild("save_digits_mode"))
4880 config.SetSaveDigitsMode(gis.GetChild("save_digits_mode").GetValue());
4881 if (gis.HasChild("raster_files"))
4882 {
4883 CYamlNode rasterFiles = gis.GetChild("raster_files");
4884 if (rasterFiles.IsSequence())
4885 config.SetRasterFiles(rasterFiles.GetStringSequence());
4886 }
4887 if (gis.HasChild("vector_files"))
4888 {
4889 CYamlNode vectorFiles = gis.GetChild("vector_files");
4890 if (vectorFiles.IsSequence())
4891 config.SetVectorFiles(vectorFiles.GetStringSequence());
4892 }
4893 if (gis.HasChild("raster_format"))
4894 config.SetRasterFormat(gis.GetChild("raster_format").GetValue());
4895 if (gis.HasChild("world_file"))
4896 config.SetWorldFile(gis.GetChild("world_file").GetBoolValue());
4897 if (gis.HasChild("scale_values"))
4898 config.SetScaleValues(gis.GetChild("scale_values").GetBoolValue());
4899 }
4900
4901 // Hydrology
4902 if (root.HasChild("hydrology"))
4903 {
4904 CYamlNode hydro = root.GetChild("hydrology");
4905 if (hydro.HasChild("wave_propagation_model"))
4906 {
4907 string strModel = hydro.GetChild("wave_propagation_model").GetValue();
4908 if (strModel == "COVE")
4909 config.SetWavePropagationModel(0);
4910 else if (strModel == "CShore")
4911 config.SetWavePropagationModel(1);
4912 }
4913 if (hydro.HasChild("seawater_density"))
4914 config.SetSeawaterDensity(
4915 hydro.GetChild("seawater_density").GetDoubleValue());
4916 if (hydro.HasChild("initial_water_level"))
4917 config.SetInitialWaterLevel(
4918 hydro.GetChild("initial_water_level").GetDoubleValue());
4919 if (hydro.HasChild("final_water_level"))
4920 config.SetFinalWaterLevel(
4921 hydro.GetChild("final_water_level").GetDoubleValue());
4922
4923 // Wave data configuration
4924 if (hydro.HasChild("wave_height_time_series"))
4926 hydro.GetChild("wave_height_time_series").GetValue());
4927 if (hydro.HasChild("wave_height_shape_file"))
4929 hydro.GetChild("wave_height_shape_file").GetValue());
4930 if (hydro.HasChild("wave_height"))
4932 hydro.GetChild("wave_height").GetDoubleValue());
4933 if (hydro.HasChild("wave_orientation"))
4935 hydro.GetChild("wave_orientation").GetDoubleValue());
4936 if (hydro.HasChild("wave_period"))
4937 config.SetWavePeriod(hydro.GetChild("wave_period").GetDoubleValue());
4938
4939 // Tide data configuration
4940 if (hydro.HasChild("tide_data_file"))
4941 config.SetTideDataFile(processFilePath(hydro.GetChild("tide_data_file").GetValue()));
4942 if (hydro.HasChild("breaking_wave_ratio"))
4943 config.SetBreakingWaveRatio(
4944 hydro.GetChild("breaking_wave_ratio").GetDoubleValue());
4945 }
4946
4947 // Grid and Coastline
4948 if (root.HasChild("grid_and_coastline"))
4949 {
4950 CYamlNode grid = root.GetChild("grid_and_coastline");
4951 if (grid.HasChild("coastline_smoothing"))
4952 {
4953 string strSmoothing = grid.GetChild("coastline_smoothing").GetValue();
4954 if (strSmoothing == "none")
4955 config.SetCoastlineSmoothing(0);
4956 else if (strSmoothing == "running_mean")
4957 config.SetCoastlineSmoothing(1);
4958 else if (strSmoothing == "savitzky_golay")
4959 config.SetCoastlineSmoothing(2);
4960 else
4961 config.SetCoastlineSmoothing(
4962 grid.GetChild("coastline_smoothing").GetIntValue());
4963 }
4964 if (grid.HasChild("coastline_smoothing_window"))
4966 grid.GetChild("coastline_smoothing_window").GetIntValue());
4967 if (grid.HasChild("polynomial_order"))
4968 config.SetPolynomialOrder(
4969 grid.GetChild("polynomial_order").GetIntValue());
4970 if (grid.HasChild("omit_grid_edges"))
4971 config.SetOmitGridEdges(grid.GetChild("omit_grid_edges").GetValue());
4972 if (grid.HasChild("profile_smoothing_window"))
4974 grid.GetChild("profile_smoothing_window").GetIntValue());
4975 if (grid.HasChild("max_local_slope"))
4976 config.SetMaxLocalSlope(
4977 grid.GetChild("max_local_slope").GetDoubleValue());
4978 if (grid.HasChild("max_beach_elevation"))
4979 config.SetMaxBeachElevation(
4980 grid.GetChild("max_beach_elevation").GetDoubleValue());
4981 }
4982
4983 // Layers and Files
4984 if (root.HasChild("layers_and_files"))
4985 {
4986 CYamlNode layers = root.GetChild("layers_and_files");
4987 if (layers.HasChild("num_layers"))
4988 config.SetNumLayers(layers.GetChild("num_layers").GetIntValue());
4989 if (layers.HasChild("basement_dem_file"))
4990 config.SetBasementDEMFile(
4991 processFilePath(layers.GetChild("basement_dem_file").GetValue()));
4992 if (layers.HasChild("suspended_sediment_file"))
4993 config.SetSuspendedSedFile(processFilePath(
4994 layers.GetChild("suspended_sediment_file").GetValue()));
4995 if (layers.HasChild("landform_file"))
4996 config.SetLandformFile(
4997 processFilePath(layers.GetChild("landform_file)").GetValue()));
4998 if (layers.HasChild("intervention_class_file"))
4999 config.SetInterventionClassFile(processFilePath(
5000 layers.GetChild("intervention_class_file").GetValue()));
5001 if (layers.HasChild("intervention_height_file"))
5002 config.SetInterventionHeightFile(processFilePath(
5003 layers.GetChild("intervention_height_file").GetValue()));
5004
5005 // Handle layer-specific files (assuming layer_0, layer_1, etc.)
5006 if (layers.HasChild("layer_0"))
5007 {
5008 CYamlNode layer0 = layers.GetChild("layer_0");
5009 vector<string> unconsFine, unconsSand, unconsCoarse;
5010 vector<string> consFine, consSand, consCoarse;
5011
5012 if (layer0.HasChild("unconsolidated_fine"))
5013 unconsFine.push_back(processFilePath(
5014 layer0.GetChild("unconsolidated_fine").GetValue()));
5015 if (layer0.HasChild("unconsolidated_sand"))
5016 unconsSand.push_back(processFilePath(
5017 layer0.GetChild("unconsolidated_sand").GetValue()));
5018 if (layer0.HasChild("unconsolidated_coarse"))
5019 unconsCoarse.push_back(processFilePath(
5020 layer0.GetChild("unconsolidated_coarse").GetValue()));
5021 if (layer0.HasChild("consolidated_fine"))
5022 consFine.push_back(
5023 processFilePath(layer0.GetChild("consolidated_fine").GetValue()));
5024 if (layer0.HasChild("consolidated_sand"))
5025 consSand.push_back(
5026 processFilePath(layer0.GetChild("consolidated_sand").GetValue()));
5027 if (layer0.HasChild("consolidated_coarse"))
5028 consCoarse.push_back(processFilePath(
5029 layer0.GetChild("consolidated_coarse").GetValue()));
5030
5031 config.SetUnconsFineFiles(unconsFine);
5032 config.SetUnconsSandFiles(unconsSand);
5033 config.SetUnconsCoarseFiles(unconsCoarse);
5034 config.SetConsFineFiles(consFine);
5035 config.SetConsSandFiles(consSand);
5036 config.SetConsCoarseFiles(consCoarse);
5037 }
5038 }
5039
5040 // Sediment and Erosion
5041 if (root.HasChild("sediment_and_erosion"))
5042 {
5043 CYamlNode sed = root.GetChild("sediment_and_erosion");
5044 if (sed.HasChild("coast_platform_erosion"))
5046 sed.GetChild("coast_platform_erosion").GetBoolValue());
5047 if (sed.HasChild("platform_erosion_resistance"))
5049 sed.GetChild("platform_erosion_resistance").GetDoubleValue());
5050 if (sed.HasChild("beach_sediment_transport"))
5052 sed.GetChild("beach_sediment_transport").GetBoolValue());
5053 if (sed.HasChild("beach_transport_at_edges"))
5055 sed.GetChild("beach_transport_at_edges").GetIntValue());
5056 if (sed.HasChild("beach_erosion_equation"))
5057 {
5058 string strEqn = sed.GetChild("beach_erosion_equation").GetValue();
5059 config.SetBeachErosionEquation(strEqn == "CERC" ? 0 : 1);
5060 }
5061 if (sed.HasChild("sediment_density"))
5062 config.SetSedimentDensity(
5063 sed.GetChild("sediment_density").GetDoubleValue());
5064 if (sed.HasChild("beach_sediment_porosity"))
5066 sed.GetChild("beach_sediment_porosity").GetDoubleValue());
5067 if (sed.HasChild("transport_kls"))
5068 config.SetTransportKLS(sed.GetChild("transport_kls").GetDoubleValue());
5069 if (sed.HasChild("kamphuis_parameter"))
5070 config.SetKamphuis(sed.GetChild("kamphuis_parameter").GetDoubleValue());
5071 if (sed.HasChild("berm_height"))
5072 config.SetBermHeight(sed.GetChild("berm_height").GetDoubleValue());
5073
5074 // Handle nested median_sizes and erosivity sections
5075 if (sed.HasChild("median_sizes"))
5076 {
5077 CYamlNode sizes = sed.GetChild("median_sizes");
5078 if (sizes.HasChild("fine"))
5079 config.SetFineMedianSize(sizes.GetChild("fine").GetDoubleValue());
5080 if (sizes.HasChild("sand"))
5081 config.SetSandMedianSize(sizes.GetChild("sand").GetDoubleValue());
5082 if (sizes.HasChild("coarse"))
5083 config.SetCoarseMedianSize(sizes.GetChild("coarse").GetDoubleValue());
5084 }
5085 if (sed.HasChild("erosivity"))
5086 {
5087 CYamlNode eros = sed.GetChild("erosivity");
5088 if (eros.HasChild("fine"))
5089 config.SetFineErosivity(eros.GetChild("fine").GetDoubleValue());
5090 if (eros.HasChild("sand"))
5091 config.SetSandErosivity(eros.GetChild("sand").GetDoubleValue());
5092 if (eros.HasChild("coarse"))
5093 config.SetCoarseErosivity(eros.GetChild("coarse").GetDoubleValue());
5094 }
5095 }
5096
5097 // Cliff Parameters
5098 if (root.HasChild("cliff_parameters"))
5099 {
5100 CYamlNode cliff = root.GetChild("cliff_parameters");
5101 if (cliff.HasChild("cliff_collapse"))
5102 config.SetCliffCollapse(
5103 cliff.GetChild("cliff_collapse").GetBoolValue());
5104 if (cliff.HasChild("cliff_erosion_resistance"))
5106 cliff.GetChild("cliff_erosion_resistance").GetDoubleValue());
5107 if (cliff.HasChild("notch_overhang"))
5108 config.SetNotchOverhang(
5109 cliff.GetChild("notch_overhang").GetDoubleValue());
5110 if (cliff.HasChild("notch_base"))
5111 config.SetNotchBase(cliff.GetChild("notch_base").GetDoubleValue());
5112 if (cliff.HasChild("deposition_scale_parameter_a"))
5113 config.SetCliffDepositionA(
5114 cliff.GetChild("deposition_scale_parameter_a").GetDoubleValue());
5115 if (cliff.HasChild("talus_width"))
5116 config.SetTalusWidth(cliff.GetChild("talus_width").GetDoubleValue());
5117 if (cliff.HasChild("min_talus_length"))
5118 config.SetMinTalusLength(
5119 cliff.GetChild("min_talus_length").GetDoubleValue());
5120 if (cliff.HasChild("min_talus_height"))
5121 config.SetMinTalusHeight(
5122 cliff.GetChild("min_talus_height").GetDoubleValue());
5123 }
5124
5125 // Flood Parameters
5126 if (root.HasChild("flood_parameters"))
5127 {
5128 CYamlNode flood = root.GetChild("flood_parameters");
5129 if (flood.HasChild("flood_input"))
5130 config.SetFloodInput(flood.GetChild("flood_input").GetBoolValue());
5131 if (flood.HasChild("flood_coastline"))
5132 config.SetFloodCoastline(flood.GetChild("flood_coastline").GetValue());
5133 if (flood.HasChild("runup_equation"))
5134 config.SetRunupEquation(flood.GetChild("runup_equation").GetValue());
5135 if (flood.HasChild("characteristic_locations"))
5136 config.SetFloodLocations(
5137 flood.GetChild("characteristic_locations").GetValue());
5138 if (flood.HasChild("flood_input_location"))
5139 config.SetFloodInputLocation(
5140 flood.GetChild("flood_input_location").GetValue());
5141 }
5142
5143 // Sediment Input Parameters
5144 if (root.HasChild("sediment_input_parameters"))
5145 {
5146 CYamlNode sedInput = root.GetChild("sediment_input_parameters");
5147 if (sedInput.HasChild("sediment_input"))
5148 config.SetSedimentInput(
5149 sedInput.GetChild("sediment_input").GetBoolValue());
5150 if (sedInput.HasChild("location"))
5152 sedInput.GetChild("location").GetValue());
5153 if (sedInput.HasChild("type"))
5154 config.SetSedimentInputType(sedInput.GetChild("type").GetValue());
5155 if (sedInput.HasChild("details_file"))
5157 sedInput.GetChild("details_file").GetValue());
5158 }
5159
5160 // Physics and Geometry
5161 if (root.HasChild("physics_and_geometry"))
5162 {
5163 CYamlNode physics = root.GetChild("physics_and_geometry");
5164 if (physics.HasChild("gravitational_acceleration"))
5166 physics.GetChild("gravitational_acceleration").GetDoubleValue());
5167 if (physics.HasChild("normal_spacing"))
5168 config.SetNormalSpacing(
5169 physics.GetChild("normal_spacing").GetDoubleValue());
5170 if (physics.HasChild("random_factor"))
5171 config.SetRandomFactor(
5172 physics.GetChild("random_factor").GetDoubleValue());
5173 if (physics.HasChild("normal_length"))
5174 config.SetNormalLength(
5175 physics.GetChild("normal_length").GetDoubleValue());
5176 if (physics.HasChild("start_depth_ratio"))
5177 config.SetStartDepthRatio(
5178 physics.GetChild("start_depth_ratio").GetDoubleValue());
5179 }
5180
5181 // Profile and Output
5182 if (root.HasChild("profile_and_output"))
5183 {
5184 CYamlNode profile = root.GetChild("profile_and_output");
5185 if (profile.HasChild("save_profile_data"))
5186 config.SetSaveProfileData(
5187 profile.GetChild("save_profile_data").GetBoolValue());
5188 if (profile.HasChild("save_parallel_profiles"))
5190 profile.GetChild("save_parallel_profiles").GetBoolValue());
5191 if (profile.HasChild("output_erosion_potential"))
5193 profile.GetChild("output_erosion_potential").GetBoolValue());
5194 if (profile.HasChild("curvature_window"))
5195 config.SetCurvatureWindow(
5196 profile.GetChild("curvature_window").GetIntValue());
5197
5198 // Handle numeric lists
5199 if (profile.HasChild("profile_numbers"))
5200 {
5201 CYamlNode profileNums = profile.GetChild("profile_numbers");
5202 if (profileNums.IsSequence())
5203 {
5204 vector<int> vecNums;
5205 vector<CYamlNode> seq = profileNums.GetSequence();
5206 for (auto const &node : seq)
5207 vecNums.push_back(node.GetIntValue());
5208 config.SetProfileNumbers(vecNums);
5209 }
5210 }
5211 if (profile.HasChild("profile_timesteps"))
5212 {
5213 CYamlNode profileTimes = profile.GetChild("profile_timesteps");
5214 if (profileTimes.IsSequence())
5215 {
5216 vector<int> vecTimes;
5217 vector<CYamlNode> seq = profileTimes.GetSequence();
5218 for (auto const &node : seq)
5219 vecTimes.push_back(node.GetIntValue());
5220 config.SetProfileTimesteps(vecTimes);
5221 }
5222 }
5223 }
5224
5225 // Cliff Edge Processing
5226 if (root.HasChild("cliff_edge_processing"))
5227 {
5228 CYamlNode cliffEdge = root.GetChild("cliff_edge_processing");
5229 if (cliffEdge.HasChild("cliff_edge_smoothing"))
5230 {
5231 string strSmoothing =
5232 cliffEdge.GetChild("cliff_edge_smoothing").GetValue();
5233 if (strSmoothing == "none")
5234 config.SetCliffEdgeSmoothing(0);
5235 else if (strSmoothing == "running_mean")
5236 config.SetCliffEdgeSmoothing(1);
5237 else if (strSmoothing == "savitzky_golay")
5238 config.SetCliffEdgeSmoothing(2);
5239 else
5240 config.SetCliffEdgeSmoothing(
5241 cliffEdge.GetChild("cliff_edge_smoothing").GetIntValue());
5242 }
5243 if (cliffEdge.HasChild("cliff_edge_smoothing_window"))
5245 cliffEdge.GetChild("cliff_edge_smoothing_window").GetIntValue());
5246 if (cliffEdge.HasChild("cliff_edge_polynomial_order"))
5248 cliffEdge.GetChild("cliff_edge_polynomial_order").GetIntValue());
5249 if (cliffEdge.HasChild("cliff_slope_limit"))
5250 config.SetCliffSlopeLimit(
5251 cliffEdge.GetChild("cliff_slope_limit").GetDoubleValue());
5252 }
5253 }
5254 catch (std::exception const &e)
5255 {
5256 cerr << ERR << "Error processing YAML configuration: " << e.what() << endl;
5257 return false;
5258 }
5259
5260 return true;
5261}
5262
5263//===============================================================================================================================
5265//===============================================================================================================================
5267{
5268 string strRec, strErr;
5269 // Case 1: Text output file names, don't change case
5270 m_strRunName = config.GetRunName();
5272 m_strOutFile.append(m_strRunName);
5273 m_strOutFile.append(OUTEXT);
5274
5276 m_strLogFile.append(m_strRunName);
5277 m_strLogFile.append(LOGEXT);
5278
5279 // Case 2: Content of log file (0 = no log file, 1 = least detail, 3 = most
5280 // detail)
5282
5283 // Case 3: Output per-timestep results in CSV format?
5285
5286 // Case 4: Parse start date/time [hh-mm-ss dd/mm/yyyy]
5287 string strStartDateTime = config.GetStartDateTime();
5288 if (! strStartDateTime.empty())
5289 {
5290 vector<string> VstrTmp = VstrSplit(&strStartDateTime, SPACE);
5291 if (VstrTmp.size() >= 2)
5292 {
5293 int nHour, nMin, nSec, nDay, nMonth, nYear;
5294 if (bParseTime(&VstrTmp[0], nHour, nMin, nSec))
5295 {
5296 if (bParseDate(&VstrTmp[1], nDay, nMonth, nYear))
5297 {
5298 m_nSimStartSec = nSec;
5299 m_nSimStartMin = nMin;
5300 m_nSimStartHour = nHour;
5301 m_nSimStartDay = nDay;
5302 m_nSimStartMonth = nMonth;
5303 m_nSimStartYear = nYear;
5304 }
5305 }
5306 }
5307 }
5308
5309 // Case 5: Duration of simulation (in hours, days, months, or years)
5310 string strDuration = config.GetDuration();
5311 if (! strDuration.empty())
5312 {
5313 string strDurationLower = strToLower(&strDuration);
5314 double dDurationMult = dGetTimeMultiplier(&strDurationLower);
5315 if (static_cast<int>(dDurationMult) != TIME_UNKNOWN)
5316 {
5317 // Extract numeric part and multiply
5318 string strNumeric = strDurationLower;
5319 // Remove the unit part to get just the number
5320 if (strNumeric.find("hour") != string::npos)
5321 strNumeric = strNumeric.substr(0, strNumeric.find("hour"));
5322 else if (strNumeric.find("day") != string::npos)
5323 strNumeric = strNumeric.substr(0, strNumeric.find("day"));
5324 else if (strNumeric.find("month") != string::npos)
5325 strNumeric = strNumeric.substr(0, strNumeric.find("month"));
5326 else if (strNumeric.find("year") != string::npos)
5327 strNumeric = strNumeric.substr(0, strNumeric.find("year"));
5328
5329 if (bIsStringValidDouble(strNumeric))
5330 {
5331 m_dSimDuration = strtod(strNumeric.c_str(), NULL) * dDurationMult;
5332 }
5333 }
5334 }
5335
5336 // Case 6: Timestep of simulation (in hours or days)
5337 string strTimestep = config.GetTimestep();
5338 if (! strTimestep.empty())
5339 {
5340 string strTimestepLower = strToLower(&strTimestep);
5341 double dTimestepMult = dGetTimeMultiplier(&strTimestepLower);
5342 if (static_cast<int>(dTimestepMult) != TIME_UNKNOWN)
5343 {
5344 // Extract numeric part and multiply
5345 std::string strNumeric = strTimestepLower;
5346 // Remove the unit part to get just the number
5347 if (strNumeric.find("hour") != string::npos)
5348 strNumeric = strNumeric.substr(0, strNumeric.find("hour"));
5349 else if (strNumeric.find("day") != string::npos)
5350 strNumeric = strNumeric.substr(0, strNumeric.find("day"));
5351 else if (strNumeric.find("month") != string::npos)
5352 strNumeric = strNumeric.substr(0, strNumeric.find("month"));
5353 else if (strNumeric.find("year") != string::npos)
5354 strNumeric = strNumeric.substr(0, strNumeric.find("year"));
5355
5356 if (bIsStringValidDouble(strNumeric))
5357 {
5358 m_dTimeStep = strtod(strNumeric.c_str(), NULL) * dTimestepMult;
5359 }
5360 if (m_dTimeStep <= 0)
5361 strErr =
5362 "timestep of simulation must be > 0";
5363
5365 strErr =
5366 " timestep of simulation must be < the duration of the "
5367 "simulation";
5368 }
5369 }
5370
5371 // Case 7: Save intervals - can handle multiple groups with different units
5372 vector<string> vecSaveTimes = config.GetSaveTimes();
5373 if (! vecSaveTimes.empty())
5374 {
5375 m_nUSave = 0;
5376 m_bSaveRegular = false;
5377
5378 for (string const &strSaveTime : vecSaveTimes)
5379 {
5380 if (strSaveTime.empty())
5381 continue;
5382
5383 string strSaveTimeLower = strToLower(&strSaveTime);
5384
5385 // Get multiplier for time units
5386 double dMult = dGetTimeMultiplier(&strSaveTimeLower);
5387 if (static_cast<int>(dMult) != TIME_UNKNOWN)
5388 {
5389 // Find last space to separate number from unit
5390 size_t nLastSpace = strSaveTimeLower.rfind(SPACE);
5391 if (nLastSpace != string::npos)
5392 {
5393 string strNumbers = strSaveTimeLower.substr(0, nLastSpace);
5394 strNumbers = strTrimRight(&strNumbers);
5395
5396 // Parse numbers (could be multiple space-separated values)
5397 vector<string> VstrNumbers = VstrSplit(&strNumbers, SPACE);
5398 for (string const &strNum : VstrNumbers)
5399 {
5400 if (! strNum.empty()) //&& bIsStringValidDouble(strNum))
5401 {
5402 if (m_nUSave < static_cast<int>(SAVEMAX) - 1)
5403 {
5404 double dValue = strtod(strNum.c_str(), NULL) * dMult;
5405 m_dUSaveTime[m_nUSave++] = dValue;
5406 }
5407 }
5408 }
5409 }
5410 }
5411 }
5412
5413 // Check if we have save times
5414 if (m_nUSave == 1)
5415 {
5416 m_bSaveRegular = true;
5419 }
5420 else if (m_nUSave > 1)
5421 {
5422 // Multiple values - sort them
5424 // Put a dummy save interval as the last entry
5426 }
5427 }
5428
5429 // Case 8: Random number seed(s)
5430 if (config.UseSystemTimeForRandomSeed())
5431 {
5432 // Use system time for random seed
5433 random_device rdev;
5434 m_ulRandSeed[0] = rdev();
5435 // Make all seeds the same
5436 for (int n = 1; n < NUMBER_OF_RNGS; n++)
5437 m_ulRandSeed[n] = m_ulRandSeed[0];
5438 }
5439 else
5440 {
5441 int nSeed = config.GetRandomSeed();
5442 if (nSeed != 0)
5443 {
5444 // Use specified seed
5445 m_ulRandSeed[0] = static_cast<unsigned long>(nSeed);
5446 // Make all seeds the same
5447 for (int n = 1; n < NUMBER_OF_RNGS; n++)
5448 m_ulRandSeed[n] = m_ulRandSeed[0];
5449 }
5450 }
5451
5452 // Case 9: Max save digits for GIS output
5454 if (m_nGISMaxSaveDigits < 2)
5455 strErr = "max save digits for GIS output file names must be > 1";
5456
5457 // Case 10: Save digits mode (sequential vs iteration)
5458 string strSaveDigitsMode = config.GetSaveDigitsMode();
5459 if (! strSaveDigitsMode.empty())
5460 {
5461 string strSaveDigitsLower = strToLower(&strSaveDigitsMode);
5462 if (strSaveDigitsLower.find('s') != string::npos)
5464 else if (strSaveDigitsLower.find('i') != string::npos)
5466 }
5467
5468 // Case 11: Raster GIS files to output
5469 vector<string> rasterFiles = config.GetRasterFiles();
5470 if (! rasterFiles.empty())
5471 {
5472 // Reset all raster output flags
5473 m_bSuspSedSave = false;
5474 m_bAvgSuspSedSave = false;
5475 m_bFineUnconsSedSave = false;
5476 m_bFineConsSedSave = false;
5477 m_bSandUnconsSedSave = false;
5478 m_bSandConsSedSave = false;
5479 m_bCoarseUnconsSedSave = false;
5480 m_bCoarseConsSedSave = false;
5481 m_bSedimentTopSurfSave = false;
5482 m_bTopSurfSave = false;
5483 m_bSeaDepthSave = false;
5484 m_bWaveHeightSave = false;
5485 m_bWaveAngleSave = false;
5494 m_bBeachDepositionSave = false;
5496 m_bLandformSave = false;
5497 m_bLocalSlopeSave = false;
5498 m_bSlopeSave = false;
5499 m_bCliffSave = false;
5500 m_bAvgSeaDepthSave = false;
5501 m_bAvgWaveHeightSave = false;
5502 m_bAvgWaveAngleSave = false;
5503 m_bBeachProtectionSave = false;
5504 m_bBasementElevSave = false;
5505 m_bRasterCoastlineSave = false;
5507 m_bActiveZoneSave = false;
5508 m_bCliffCollapseSave = false;
5512 m_bRasterPolygonSave = false;
5514 m_bSeaMaskSave = false;
5515 m_bBeachMaskSave = false;
5516 m_bShadowZoneCodesSave = false;
5522
5523 // Set flags based on raster file codes (Case 11 implementation)
5524 for (string const &rasterCode : rasterFiles)
5525 {
5526 string code = rasterCode;
5527 std::transform(code.begin(), code.end(), code.begin(), ::tolower);
5528
5529 if (code == "suspended_sediment")
5530 m_bSuspSedSave = true;
5531 else if (code == "avg_suspended_sediment")
5532 m_bAvgSuspSedSave = true;
5533 else if (code == "fine_uncons")
5534 m_bFineUnconsSedSave = true;
5535 else if (code == "fine_cons")
5536 m_bFineConsSedSave = true;
5537 else if (code == "sand_uncons")
5538 m_bSandUnconsSedSave = true;
5539 else if (code == "sand_cons")
5540 m_bSandConsSedSave = true;
5541 else if (code == "coarse_uncons")
5543 else if (code == "coarse_cons")
5544 m_bCoarseConsSedSave = true;
5545 else if (code == "sediment_top_elevation")
5547 else if (code == "top_elevation")
5548 m_bTopSurfSave = true;
5549 else if (code == "sea_depth")
5550 m_bSeaDepthSave = true;
5551 else if (code == "wave_height")
5552 m_bWaveHeightSave = true;
5553 else if (code == "wave_orientation")
5554 m_bWaveAngleSave = true;
5555 else if (code == "wave_period")
5557 else if (code == "potential_platform_erosion")
5559 else if (code == "actual_platform_erosion")
5561 else if (code == "total_potential_platform_erosion")
5563 else if (code == "total_actual_platform_erosion")
5565 else if (code == "potential_beach_erosion")
5567 else if (code == "actual_beach_erosion")
5569 else if (code == "total_potential_beach_erosion")
5571 else if (code == "total_actual_beach_erosion")
5573 else if (code == "beach_deposition")
5575 else if (code == "total_beach_deposition")
5577 else if (code == "landform")
5578 m_bLandformSave = true;
5579 else if (code == "local_cons_sediment_slope")
5580 m_bLocalSlopeSave = true;
5581 else if (code == "slope")
5582 m_bSlopeSave = true;
5583 else if (code == "cliff")
5584 m_bCliffSave = true;
5585 else if (code == "avg_sea_depth")
5586 m_bAvgSeaDepthSave = true;
5587 else if (code == "avg_wave_height")
5588 m_bAvgWaveHeightSave = true;
5589 else if (code == "avg_wave_orientation")
5590 m_bAvgWaveAngleSave = true;
5591 else if (code == "beach_protection")
5593 else if (code == "basement_elevation")
5594 m_bBasementElevSave = true;
5595 else if (code == "coastline")
5597 else if (code == "coast_normal")
5599 else if (code == "active_zone")
5600 m_bActiveZoneSave = true;
5601 else if (code == "cliff_collapse")
5602 m_bCliffCollapseSave = true;
5603 else if (code == "total_cliff_collapse")
5605 else if (code == "cliff_collapse_deposition")
5607 else if (code == "total_cliff_collapse_deposition")
5609 else if (code == "polygon")
5610 m_bRasterPolygonSave = true;
5611 else if (code == "potential_platform_erosion_mask")
5613 else if (code == "sea_mask")
5614 m_bSeaMaskSave = true;
5615 else if (code == "beach_mask")
5616 m_bBeachMaskSave = true;
5617 else if (code == "shadow_zone_codes")
5619 else if (code == "deep_water_wave_angle")
5621 else if (code == "deep_water_wave_height")
5623 else if (code == "deep_water_wave_period")
5625 else if (code == "polygon_uncons_sediment_up_or_down_drift")
5627 else if (code == "polygon_uncons_sediment_gain_or_loss")
5629 }
5630 }
5631
5632 // Case 12: GIS output format for raster and vector files
5634
5635 // Case 13: If needed, scale GIS raster output values
5637
5638 // Case 14: If needed, also output GIS raster world file
5639 m_bWorldFile = config.GetWorldFile();
5640
5641 // Case 15: Elevations for raster slice output, if desired
5642 if (! config.GetSliceElevations().empty())
5643 {
5644 m_bSliceSave = true;
5646 }
5647
5648 // Case 16: Vector GIS files to output
5649 vector<string> vectorFiles = config.GetVectorFiles();
5650 if (! vectorFiles.empty())
5651 {
5652 // Reset all vector output flags
5653 m_bCoastSave = false;
5654 m_bCliffEdgeSave = false;
5656 m_bNormalsSave = false;
5657 m_bInvalidNormalsSave = false;
5660 m_bMeanWaveEnergySave = false;
5662 m_bCoastCurvatureSave = false;
5663 m_bPolygonNodeSave = false;
5664 m_bPolygonBoundarySave = false;
5665 m_bCliffNotchSave = false;
5666 m_bShadowBoundarySave = false;
5669 m_bWaveSetupSave = false;
5670 m_bStormSurgeSave = false;
5671 m_bRunUpSave = false;
5673
5674 // Set flags based on vector file codes (Case 16 implementation)
5675 for (string const &vectorCode : vectorFiles)
5676 {
5677 string code = vectorCode;
5678 std::transform(code.begin(), code.end(), code.begin(), ::tolower);
5679
5680 if (code == "coast")
5681 m_bCoastSave = true;
5682 else if (code == "cliff_edge")
5683 m_bCliffEdgeSave = true;
5684 else if (code == "wave_angle")
5686 else if (code == "normals")
5687 m_bNormalsSave = true;
5688 else if (code == "invalid_normals")
5689 m_bInvalidNormalsSave = true;
5690 else if (code == "avg_wave_angle")
5692 else if (code == "wave_energy")
5694 else if (code == "mean_wave_energy")
5695 m_bMeanWaveEnergySave = true;
5696 else if (code == "breaking_wave_height")
5698 else if (code == "coast_curvature")
5699 m_bCoastCurvatureSave = true;
5700 else if (code == "polygon_node")
5701 m_bPolygonNodeSave = true;
5702 else if (code == "polygon")
5704 else if (code == "cliff_notch")
5705 m_bCliffNotchSave = true;
5706 else if (code == "shadow_boundary")
5707 m_bShadowBoundarySave = true;
5708 else if (code == "downdrift_boundary")
5710 else if (code == "deep_water_wave_angle")
5712 else if (code == "wave_setup")
5713 m_bWaveSetupSave = true;
5714 else if (code == "storm_surge")
5715 m_bStormSurgeSave = true;
5716 else if (code == "run_up")
5717 m_bRunUpSave = true;
5718 else if (code == "flood_line")
5720 }
5721 }
5722
5723 // Case 17: Vector GIS output format (note must retain original case)
5725
5726 // Case 18: Time series files to output
5727 // TODO: Migrate from bReadRunDataFile()
5728 vector<string> timeseriesFiles = config.GetTimeSeriesFiles();
5729 if (! timeseriesFiles.empty())
5730 {
5731 for (string const &timeseriesCode : timeseriesFiles)
5732 {
5733 string code = timeseriesCode;
5734 std::transform(code.begin(), code.end(), code.begin(), ::tolower);
5735
5736 if (code == "sea_area")
5737 m_bSeaAreaTSSave = true;
5738 if (code == "water_level")
5740 if (code == "platform_erosion")
5742 if (code == "cliff_collapse_erosion")
5744 if (code == "cliff_collapse_deposition")
5746 if (code == "cliff_collapse_net")
5748 if (code == "beach_erosion")
5749 m_bBeachErosionTSSave = true;
5750 if (code == "beach_deposition")
5752 if (code == "beach_change_net")
5754 if (code == "suspended")
5755 m_bSuspSedTSSave = true;
5756 if (code == "wave_setup")
5758 if (code == "wave_runup")
5760 }
5761 }
5762
5763 // Case 19: Vector coastline smoothing algorithm: 0 = none, 1 = running mean,
5764 // 2 = Savitzky-Golay
5766
5767 // Case 20: Size of coastline smoothing window: must be odd
5769
5770 // Case 21: Order of coastline profile smoothing polynomial for
5771 // Savitzky-Golay: usually 2 or 4, max is 6
5773
5774 // Case 22: Omit grid edges from search (north/south/east/west)
5775 std::string strRH = config.GetOmitGridEdges();
5776 if (strRH.find('n') != string::npos)
5777 {
5779 }
5780
5781 if (strRH.find('s') != string::npos)
5782 {
5784 }
5785
5786 if (strRH.find('w') != string::npos)
5787 {
5788 m_bOmitSearchWestEdge = true;
5789 }
5790
5791 if (strRH.find('e') != string::npos)
5792 {
5793 m_bOmitSearchEastEdge = true;
5794 }
5795
5796 // Case 23: Profile slope running-mean smoothing window size: must be odd
5798
5799 // Case 24: Max local slope (m/m), first check that this is a valid double
5801
5802 // Case 25: Maximum elevation of beach above SWL, first check that this is a
5803 // valid double
5805
5806 // Case 26: Number of sediment layers
5807 m_nLayers = config.GetNumLayers();
5808 // OK we know the number of layers, so add elements to these vectors
5809 for (int j = 0; j < m_nLayers; j++)
5810 {
5817 m_VstrGDALIUFDriverCode.push_back("");
5818 m_VstrGDALIUFDriverDesc.push_back("");
5819 m_VstrGDALIUFProjection.push_back("");
5820 m_VstrGDALIUFDataType.push_back("");
5821 m_VstrGDALIUSDriverCode.push_back("");
5822 m_VstrGDALIUSDriverDesc.push_back("");
5823 m_VstrGDALIUSProjection.push_back("");
5824 m_VstrGDALIUSDataType.push_back("");
5825 m_VstrGDALIUCDriverCode.push_back("");
5826 m_VstrGDALIUCDriverDesc.push_back("");
5827 m_VstrGDALIUCProjection.push_back("");
5828 m_VstrGDALIUCDataType.push_back("");
5829 m_VstrGDALICFDriverCode.push_back("");
5830 m_VstrGDALICFDriverDesc.push_back("");
5831 m_VstrGDALICFProjection.push_back("");
5832 m_VstrGDALICFDataType.push_back("");
5833 m_VstrGDALICSDriverCode.push_back("");
5834 m_VstrGDALICSDriverDesc.push_back("");
5835 m_VstrGDALICSProjection.push_back("");
5836 m_VstrGDALICSDataType.push_back("");
5837 m_VstrGDALICCDriverCode.push_back("");
5838 m_VstrGDALICCDriverDesc.push_back("");
5839 m_VstrGDALICCProjection.push_back("");
5840 m_VstrGDALICCDataType.push_back("");
5841 }
5842
5843 // Case 27: Basement DEM file (can be blank)
5845
5846 // Cases 28: Initial sediment thickness files (unconsolidated and
5847 // consolidated)
5849 m_bHaveFineSediment = true;
5851 m_bHaveSandSediment = true;
5853 m_bHaveCoarseSediment = true;
5856 m_bHaveFineSediment = true;
5858 m_bHaveSandSediment = true;
5860 m_bHaveCoarseSediment = true;
5861
5862 // Case 29: Initial suspended sediment depth GIS file (can be blank)
5863 string strSuspendedSed = config.GetSuspendedSedFile();
5864 if (! strSuspendedSed.empty())
5865 {
5866 m_strInitialSuspSedimentFile = strSuspendedSed;
5867 }
5868
5869 // Case 30: Basic simulation input files
5871
5872 // Case 31: Initial Intervention class GIS file
5873 // (can be blank: if so then intervention height file must also be blank)
5874 string strInterventionClass = config.GetInterventionClassFile();
5875 if (! strInterventionClass.empty())
5876 m_strInterventionClassFile = strInterventionClass;
5877
5878 // Case 32: Initial Intervention height GIS file
5879 // (can be blank: if so then intervention class file must also be blank)
5880 string strInterventionHeight = config.GetInterventionHeightFile();
5881 if (! strInterventionHeight.empty())
5882 m_strInterventionHeightFile = strInterventionHeight;
5883
5884 // Case 33: Wave propagation model [0 = COVE, 1 = CShore]
5886
5887 // Case 34: Density of sea water (kg/m3), first check that this is a valid
5888 // double
5890
5891 // Case 35: Initial mean still water level (m), first check that this is a
5892 // valid double TODO 041 Make this a per-timestep SWL file
5894
5895 // Case 36: Final water level (optional)
5896 if (config.HasFinalWaterLevel())
5897 {
5898 if (! strInterventionHeight.empty())
5899 {
5901 }
5902 else
5903 {
5905 }
5906 }
5907 // Case 38-40 Parse Wave Data
5908 // Case 38: Deep water wave height (m) or a file of point vectors giving deep
5909 // Firstly has the user provided a filepath for wave data
5910 if (config.GetWaveHeightTimeSeries().empty())
5911 {
5913 m_bHaveWaveStationData = false;
5914 // Case 37: Deep water wave height (m) or a file of point vectors giving deep
5915 // water wave height (m) and orientation (for units, see below)
5917
5918 // Case 39: Deep water wave orientation in input CRS: this is the
5919 // oceanographic convention i.e. direction TOWARDS which the waves move (in
5920 // degrees clockwise from north)
5922
5923 // Case 40: Wave period (sec)
5925 }
5926 else
5927 {
5931 }
5932
5933 // Case 41: Tide data file (can be blank). This is the change (m) from still
5934 // water level for each timestep
5936
5937 // Case 42: Breaking wave height-to-depth ratio, check that this is a valid
5938 // double
5940
5941 // Case 43: Simulate coast platform erosion?
5943
5944 // Case 44: If simulating coast platform erosion, R (coast platform resistance
5945 // to erosion) values along profile, see Walkden & Hall, 2011
5947 {
5949 }
5950
5951 // Case 45: Simulate beach sediment transport?
5953
5954 // Case 46: If simulating beach sediment transport, beach sediment transport
5955 // at grid edges [0 = closed, 1 = open, 2 = re-circulate]
5957
5958 // Case 47: If simulating beach sediment transport, beach erosion/deposition
5959 // equation [0 = CERC, 1 = Kamphuis]
5961
5962 // Case 48: Median size of fine sediment (mm), always needed [0 = default,
5963 // only for Kamphuis eqn]. First check that this is a valid double
5964 m_dD50Fine = config.GetFineMedianSize();
5965
5966 // Case 49: Median size of sand sediment (mm), always needed [0 = default,
5967 // only for Kamphuis eqn]. First check that this is a valid double
5968 m_dD50Sand = config.GetSandMedianSize();
5969
5970 // Case 50: Median size of coarse sediment (mm), always needed [0 = default,
5971 // only for Kamphuis eqn]. First check that this is a valid double
5973
5974 // Case 51: Density of unconsolidated beach sediment (kg/m3)
5976
5977 // Case 52: Beach sediment porosity
5979
5980 // Case 53: Relative erodibility (0 - 1) of fine-sized sediment, always
5981 // needed. First check that this is a valid double
5983
5984 // Case 54: Relative erodibility (0 - 1) of sand-sized sediment, always
5985 // needed. First check that this is a valid double
5987
5988 // Case 55: Relative erodibility (0 - 1) of coarse-sized sediment, always
5989 // needed. First check that this is a valid double
5991
5992 // Case 56: Transport parameter KLS in CERC equation
5993 m_dKLS = config.GetTransportKLS();
5994
5995 // Case 57: Transport parameter for Kamphuis equation
5996 m_dKamphuis = config.GetKamphuis();
5997
5998 // Case 58: Berm height i.e. height above SWL of start of depositional Dean
5999 // profile
6001
6002 // Case 59: Simulate cliff collapse?
6004
6005 // Case 60: Cliff resistance to erosion
6007 {
6009 }
6010
6011 // Case 61: Notch overhang at collapse (m)
6013 {
6015 }
6016
6017 // Case 62: Notch base below still water level (m)
6019 {
6021 }
6022
6023 // Case 63: Scale parameter A for cliff deposition (m^(1/3)) [0 = auto]
6025 {
6027 }
6028
6029 // Case 64: Approximate planview width of cliff collapse talus (in m)
6031 {
6033 }
6034
6035 // Case 65: Planview length of cliff deposition talus (m)
6037 {
6039 }
6040
6041 // Case 66: Minimum height of landward end of talus, as a fraction of cliff
6042 // elevation
6044 {
6046 }
6047
6048 // Case 67: Simulate riverine flooding?
6049 if (config.GetFloodInput())
6050 {
6051 m_bRiverineFlooding = true;
6055 }
6056
6057 // Case 68: Output riverine flooding vector files
6058 if (config.GetFloodInput())
6059 {
6060 // TODO: This is a guess, please check
6061 vector<string> floodFiles = config.GetFloodFiles();
6062 if (! floodFiles.empty())
6063 {
6064 for (string const &floodCode : floodFiles)
6065 {
6066 string code = floodCode;
6067 std::transform(code.begin(), code.end(), code.begin(), ::tolower);
6068
6069 if (code == "sea_area")
6070 m_bSeaAreaTSSave = true;
6071 }
6072 }
6073 }
6074
6075 // Case 69: Flooding runup equation?
6076 if (config.GetFloodInput())
6077 {
6078 // TODO: This is a guess, please check
6080 }
6081
6082 // Case 70: Somthing unknown relating to riverine flooding
6084 {
6085 // TODO: This is a guess, please check
6086 m_bFloodLocation = ! config.GetFloodInputLocation().empty();
6087 }
6088
6089 // Case 71: Somthing unknown relating to riverine flooding
6091 {
6092 // TODO: This is a guess, please check
6094 }
6095
6096 // Case 72: Simulate sediment input?
6097 if (config.GetSedimentInput())
6098 {
6099 m_bSedimentInput = true;
6101 }
6102
6103 // Case 73: Sediment input location (point or line shapefile)
6104 if (m_bSedimentInput)
6105 {
6107 }
6108
6109 // Case 74: Sediment input type: required if have shapefile [P = Point, C =
6110 // coast block, L = line]
6111 if (m_bSedimentInput)
6112 {
6113 strRH = config.GetSedimentInputType();
6114 if (strRH.find('p') != string::npos)
6116
6117 else if (strRH.find('c') != string::npos)
6119
6120 else if (strRH.find('l') != string::npos)
6122 }
6123
6124 // Case 75: Sediment input details file (required if have shapefile)
6125 if (m_bSedimentInput)
6126 {
6128 }
6129
6130 // Case 76: Gravitational acceleration (m2/s). First check that this is a
6131 // valid double
6133
6134 // Case 77: Spacing of coastline normals (m)
6138 DEFAULT_PROFILE_SPACING; // In cells, we will set
6139 // m_dCoastNormalSpacing later when we
6140 // know m_dCellSide
6141
6142 // Case 78: Random factor for spacing of normals [0 to 1, 0 = deterministic],
6143 // check that this is a valid double
6145
6146 // Case 79: Length of coastline normals (m), check that this is a valid double
6148
6149 // Case 80: Start depth for wave calcs (ratio to deep water wave height)check
6150 // that this is a valid double
6152
6153 // Case 81: Output profile data?
6155
6156 // Case 82: Numbers of profiles to be saved
6158 {
6160 }
6161
6162 // Case 83: Timesteps to save profiles
6164 {
6166 }
6167
6168 // Case 84: Output parallel profile data?
6170
6171 // Case 85: Output erosion potential look-up data?
6173
6174 // Case 86: Size of moving window for coastline curvature calculation (must be
6175 // odd)
6177
6178 // Case 87: Cliff edge smoothing algorithm: 0 = none, 1 = running mean, 2 =
6179 // Savitzky-Golay
6181
6182 // Case 88: Size of cliff edge smoothing window: must be odd
6184
6185 // Case 89: Order of cliff edge smoothing polynomial for Savitzky-Golay:
6186 // usually 2 or 4, max is 6
6188
6189 // Case 90: Cliff slope limit for cliff toe detection
6191
6192 return true;
6193}
Unified configuration class for CoastalME simulation parameters.
bool HasFinalWaterLevel() const
void SetCoastlineSmoothingWindow(int n)
string GetOmitGridEdges() const
int GetPolynomialOrder() const
bool GetFloodInput() const
string GetRunName() const
double GetBeachSedimentPorosity() const
void SetSedimentInput(bool b)
double GetFineErosivity() const
string GetInterventionHeightFile() const
void SetBeachSedimentPorosity(double d)
bool GetSaveProfileData() const
int GetCliffEdgeSmoothing() const
void SetBermHeight(double d)
int GetCoastlineSmoothingWindow() const
double GetMaxBeachElevation() const
void SetMinTalusHeight(double d)
void SetCoarseErosivity(double d)
double GetFinalWaterLevel() const
void SetCurvatureWindow(int n)
void SetMaxBeachElevation(double d)
void SetNotchBase(double d)
void SetInterventionClassFile(string const &str)
bool GetBeachSedimentTransport() const
string GetBasementDEMFile() const
double GetBreakingWaveRatio() const
void SetSeawaterDensity(double d)
double GetPlatformErosionResistance() const
void SetSaveDigitsMode(string const &str)
void SetInitialWaterLevel(double d)
void SetCliffDepositionA(double d)
double GetSedimentDensity() const
double GetNormalLength() const
void SetFloodInput(bool b)
void SetNormalLength(double d)
string GetWaveStationDataFile() const
double GetRandomFactor() const
vector< string > GetTimeSeriesFiles() const
Get time series files with keyword expansion support.
vector< string > GetFloodFiles() const
Get time series files with keyword expansion support.
string GetStartDateTime() const
vector< string > GetConsCoarseFiles() const
void SetProfileTimesteps(vector< unsigned long > const &vec)
void SetTideDataFile(string const &str)
void SetBeachErosionEquation(int n)
void SetDeepWaterWaveHeight(double d)
double GetCoarseErosivity() const
int GetCliffEdgePolynomialOrder() const
double GetCliffSlopeLimit() const
void SetFineMedianSize(double d)
vector< int > GetProfileNumbers() const
vector< string > GetUnconsFineFiles() const
int GetBeachErosionEquation() const
void SetFloodCoastline(string const &str)
string GetSaveDigitsMode() const
double GetSandMedianSize() const
int GetCurvatureWindow() const
int GetMaxSaveDigits() const
void SetRandomFactor(double d)
void SetConsSandFiles(vector< string > const &vec)
string GetInterventionClassFile() const
string GetTimestep() const
double GetNotchOverhang() const
int GetCliffEdgeSmoothingWindow() const
void SetWaveStationDataFile(string const &str)
double GetCoarseMedianSize() const
double GetMaxLocalSlope() const
double GetSandErosivity() const
void SetPolynomialOrder(int n)
vector< string > GetSaveTimes() const
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 SetFloodInputLocation(string const &str)
void SetGravitationalAcceleration(double d)
void SetScaleValues(bool b)
void SetBeachTransportAtEdges(int n)
double GetSeawaterDensity() const
bool GetWorldFile() const
double GetNotchBase() const
void SetProfileNumbers(vector< int > const &vec)
int GetRunupEquation() const
void SetKamphuis(double d)
double GetMinTalusLength() const
string GetDuration() const
void SetSedimentInputLocation(string const &str)
double GetDeepWaterWaveHeight() const
void SetWaveHeightTimeSeries(string const &str)
void SetVectorFiles(vector< string > const &vec)
bool GetCSVPerTimestepResults() const
void SetDeepWaterWaveOrientation(double d)
double GetDeepWaterWaveOrientation() const
double GetCliffErosionResistance() const
void SetNormalSpacing(double d)
void SetSaveProfileData(bool b)
int GetWavePropagationModel() const
void SetConsCoarseFiles(vector< string > const &vec)
void SetSedimentDensity(double d)
void SetSandErosivity(double d)
void SetFineErosivity(double d)
vector< unsigned long > GetProfileTimesteps() const
vector< double > GetSliceElevations() const
string GetVectorFormat() const
void SetCliffEdgeSmoothing(int n)
double GetTalusWidth() const
void SetCliffEdgeSmoothingWindow(int n)
void SetProfileSmoothingWindow(int n)
int GetBeachTransportAtEdges() const
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)
double GetFineMedianSize() const
void SetBasementDEMFile(string const &str)
bool GetCoastPlatformErosion() const
double GetBermHeight() const
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)
double GetTransportKLS() const
vector< string > GetConsSandFiles() const
void SetRandomSeed(int n)
int GetProfileSmoothingWindow() const
bool GetCliffCollapse() const
double GetNormalSpacing() const
void SetRasterFormat(string const &str)
void SetWavePeriod(double d)
void SetFloodLocations(string const &str)
string GetSedimentInputType() const
vector< string > GetConsFineFiles() const
int GetCoastlineSmoothing() const
void SetRunupEquation(string const &str)
bool GetSedimentInput() const
void SetNotchOverhang(double d)
bool GetScaleValues() const
void SetNumLayers(int n)
bool GetSaveParallelProfiles() const
void SetInterventionHeightFile(string const &str)
string GetFloodLocations() const
double GetGravitationalAcceleration() const
void SetUnconsFineFiles(vector< string > const &vec)
double GetKamphuis() const
string GetTideDataFile() const
void SetOutputErosionPotential(bool b)
void SetCliffCollapse(bool b)
string GetFloodInputLocation() const
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)
vector< string > GetRasterFiles() const
Get raster files with keyword expansion support.
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)
vector< string > GetVectorFiles() const
Get vector files with keyword expansion support.
void SetRasterFiles(vector< string > const &vec)
void SetSaveParallelProfiles(bool b)
double GetMinTalusHeight() const
double GetInitialWaterLevel() const
void SetMaxLocalSlope(double d)
string GetLandformFile() const
bool GetOutputErosionPotential() const
string GetRasterFormat() const
string GetWaveHeightTimeSeries() const
int GetRandomSeed() const
string GetSedimentInputLocation() const
string GetSuspendedSedFile() const
void SetLogFileDetail(int n)
void SetTimestep(string const &str)
bool UseSystemTimeForRandomSeed() const
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)
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)
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.