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
10
11/* ==============================================================================================================================
12
13 This file is part of CoastalME, the Coastal Modelling Environment.
14
15 CoastalME is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
16
17 This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20==============================================================================================================================*/
21#include <cstdio>
22
23#include <cstdlib>
24using std::atol;
25using std::strtod;
26
27#include <cctype>
28using std::isdigit;
29using std::tolower;
30
31#include <cmath>
32using std::floor;
33
34#include <fstream>
35using std::ifstream;
36
37#include <iostream>
38using std::cerr;
39using std::cout;
40using std::endl;
41using std::ios;
42
43#include <string>
44using std::to_string;
45
46#include <algorithm>
47using std::find;
48using std::sort;
49using std::transform;
50
51#include <random>
52using std::random_device;
53
54#include "cme.h"
55#include "configuration.h"
57#include "simulation.h"
58#include "yaml_parser.h"
59
60//===============================================================================================================================
62//===============================================================================================================================
64{
65 // Check if user has supplied home directory
66 if (m_strCMEIni.empty())
67 // if not use the cme executable directory to find cme.ini
69
70 else
71 {
72 // if user has supplied home directory replace cme run directory with user supplied dir
74 }
75
76 m_strCMEIni.append(CME_INI);
77
78 // The .ini file is assumed to be in the CoastalME executable's directory
79 string const strFilePathName(m_strCMEIni);
80
81 // Tell the user what is happening
82 cout << READING_FILE_LOCATIONS << strFilePathName << endl;
83
84 // Create an ifstream object
85 ifstream InStream;
86
87 // Try to open .ini file for input
88 InStream.open(strFilePathName.c_str(), ios::in);
89
90 // Did it open OK?
91 if (! InStream.is_open())
92 {
93 // Error: cannot open .ini file for input
94 cerr << ERR << "cannot open " << strFilePathName << " for input" << endl;
95 return false;
96 }
97
98 int nLine = 0;
99 int i = 0;
100 string strRec, strErr;
101
102 while (getline(InStream, strRec))
103 {
104 nLine++;
105
106 // Trim off leading and trailing whitespace
107 strRec = strTrim(&strRec);
108
109 // If it is a blank line or a comment then ignore it
110 if ((! strRec.empty()) && (strRec[0] != QUOTE1) && (strRec[0] != QUOTE2))
111 {
112 // It isn't so increment counter
113 i++;
114
115 // Find the colon: note that lines MUST have a colon separating data from leading description portion
116 size_t nPos = strRec.find(COLON);
117
118 if (nPos == string::npos)
119 {
120 // Error: badly formatted (no colon)
121 cerr << ERR << "on line " << nLine << ": badly formatted (no ':') in " << strFilePathName << endl
122 << "'" << strRec << "'" << endl;
123 return false;
124 }
125
126 if (nPos == strRec.size() - 1)
127 {
128 // Error: badly formatted (colon with nothing following)
129 cerr << ERR << "on line " << nLine << ": badly formatted (nothing following ':') in " << strFilePathName << endl
130 << "'" << strRec << "'" << endl;
131 return false;
132 }
133
134 // Strip off leading portion (the bit up to and including the colon)
135 string strRH = strRec.erase(0, nPos + 1);
136
137 // Remove leading whitespace
138 strRH = strTrimLeft(&strRH);
139
140 // Look for a trailing comment, if found then terminate string at that point and trim off any trailing whitespace
141 nPos = strRH.rfind(QUOTE1);
142
143 if (nPos != string::npos)
144 strRH.resize(nPos);
145
146 nPos = strRH.rfind(QUOTE2);
147
148 if (nPos != string::npos)
149 strRH.resize(nPos);
150
151 // Remove trailing whitespace
152 strRH = strTrimRight(&strRH);
153
154 switch (i)
155 {
156 case 1:
157 // The main input run-data filename
158 if (strRH.empty())
159 strErr = "line " + to_string(nLine) + ": path and name of main datafile";
160
161 else
162 {
163 // First check that we don't already have an input run-data filename, e.g. one entered on the command-line
164 if (m_strDataPathName.empty())
165 {
166 // We don't: so first check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
167 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
168 // It has an absolute path, so use it 'as is'
169 m_strDataPathName = strRH;
170
171 else
172 {
173 // It has a relative path, so prepend the CoastalME dir
175 m_strDataPathName.append(strRH);
176 }
177 }
178 }
179
180 break;
181
182 case 2:
183 // Path for CoastalME output
184 if (strRH.empty())
185 strErr = "line " + to_string(nLine) + ": path for CoastalME output";
186
187 else
188 {
189 // Check for trailing slash on CoastalME output directory name (is vital)
190 if (strRH[strRH.size() - 1] != PATH_SEPARATOR)
191 strRH.push_back(PATH_SEPARATOR);
192
193 // Now check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
194 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
195 // It is an absolute path, so use it 'as is'
196 m_strOutPath = strRH;
197
198 else
199 {
200 // It is a relative path, so prepend the CoastalME dir
202 m_strOutPath.append(strRH);
203 }
204 }
205
206 break;
207
208 case 3:
209 // Email address, only useful if running under Linux/Unix
210 if (! strRH.empty())
211 {
212 // Something was entered, do rudimentary check for valid email address
213 if (strRH.find('@') == string::npos)
214 strErr = "line " + to_string(nLine) + ": email address for messages";
215
216 else
217 m_strMailAddress = strRH;
218 }
219
220 break;
221 }
222
223 // Did an error occur?
224 if (! strErr.empty())
225 {
226 // Error in input to initialisation file
227 cerr << ERR << "reading " << strErr << " in " << strFilePathName << endl
228 << "'" << strRec << "'" << endl;
229 InStream.close();
230
231 return false;
232 }
233 }
234 }
235
236 InStream.close();
237 return true;
238}
239
240
241//===============================================================================================================================
243// TODO 000 Should user input be split in two main files: one for
244// frequently-changed things, one for rarely-changed things? If so, what should
245// go into each file ('testing only' OK, but what else?)
246//===============================================================================================================================
248{
249 // Detect file format
250 bool bIsYaml;
251 if (! bDetectFileFormat(m_strDataPathName, bIsYaml))
252 {
253 cerr << ERR << "failed to detect file format for " << m_strDataPathName
254 << endl;
255 return false;
256 }
257
258 // Use appropriate parser based on format
259 if (bIsYaml)
260 {
261 return bReadYamlFile();
262 }
263 // Continue with original .dat file parsing
264 //
265 // Create an ifstream object
266 ifstream InStream;
267
268 // Try to open run details file for input
269 InStream.open(m_strDataPathName.c_str(), ios::in);
270
271 // Did it open OK?
272 if (!InStream.is_open())
273 {
274 // Error: cannot open run details file for input
275 cerr << ERR << "cannot open " << m_strDataPathName << " for input" << endl;
276 return false;
277 }
278
279 int nLine = 0;
280 int i = 0;
281 size_t nPos;
282 string strRec, strErr;
283
284 while (getline(InStream, strRec))
285 {
286 nLine++;
287
288 // Trim off leading and trailing whitespace
289 strRec = strTrim(&strRec);
290
291 // If it is a blank line or a comment then ignore it
292 if ((!strRec.empty()) && (strRec[0] != QUOTE1) && (strRec[0] != QUOTE2))
293 {
294 // It isn't so increment counter
295 i++;
296
297 // Find the colon: note that lines MUST have a colon separating data from leading description portion
298 nPos = strRec.find(COLON);
299
300 if (nPos == string::npos)
301 {
302 // Error: badly formatted (no colon)
303 cerr << ERR << "on line " << to_string(nLine) << "badly formatted (no ':') in " << m_strDataPathName << endl
304 << strRec << endl;
305 return false;
306 }
307
308 // Strip off leading portion (the bit up to and including the colon)
309 string strRH = strRec.erase(0, nPos + 1);
310
311 // Remove leading whitespace after the colon
312 strRH = strTrimLeft(&strRH);
313
314 // Look for trailing comments, if found then terminate string at that point and trim off any trailing whitespace
315 bool bFound = true;
316
317 while (bFound)
318 {
319 bFound = false;
320
321 nPos = strRH.rfind(QUOTE1);
322
323 if (nPos != string::npos)
324 {
325 strRH.resize(nPos);
326 bFound = true;
327 }
328
329 nPos = strRH.rfind(QUOTE2);
330
331 if (nPos != string::npos)
332 {
333 strRH.resize(nPos);
334 bFound = true;
335 }
336
337 // Trim trailing spaces
338 strRH = strTrimRight(&strRH);
339 }
340
341#ifdef _WIN32
342 // For Windows, make sure has backslashes, not Unix-style slashes
343 strRH = pstrChangeToBackslash(&strRH);
344#endif
345 bool bFirst = true;
346 int nRet = 0;
347 int nHour = 0;
348 int nMin = 0;
349 int nSec = 0;
350 int nDay = 0;
351 int nMonth = 0;
352 int nYear = 0;
353 double dMult = 0;
354 string strTmp;
355 vector<string> VstrTmp;
356
357 switch (i)
358 {
359 // ---------------------------------------------- Run Information -----------------------------------------------------
360 case 1:
361 // Text output file names, don't change case
362 if (strRH.empty())
363 strErr = "line " + to_string(nLine) + ": output file names";
364
365 else
366 {
367 m_strRunName = strRH;
368
370 m_strOutFile.append(strRH);
371 m_strOutFile.append(OUTEXT);
372
374 m_strLogFile.append(strRH);
375 m_strLogFile.append(LOGEXT);
376 }
377
378 break;
379
380 case 2:
381 // Content of log file, 0 = no log file, 1 = least detail, 3 = most detail
382 if (! bIsStringValidInt(strRH))
383 {
384 strErr = "line " + to_string(nLine) + ": invalid integer for log file detail level '" + strRH + "' in " + m_strDataPathName;
385 break;
386 }
387
388 m_nLogFileDetail = stoi(strRH);
389
391 strErr = "line " + to_string(nLine) + ": log file detail level";
392
393 break;
394
395 case 3:
396 // Output per-timestep results in CSV format?
397 strRH = strToLower(&strRH);
398
400
401 if (strRH.find('y') != string::npos)
403
404 break;
405
406 case 4:
407 // Get the start date/time of the simulation, format is [hh-mm-ss dd/mm/yyyy]
408 VstrTmp = VstrSplit(&strRH, SPACE);
409
410 // Both date and time here?
411 if (VstrTmp.size() < 2)
412 {
413 strErr = "line " + to_string(nLine) + ": must have both date and time for simulation start in '" + m_strDataPathName + "'";
414 break;
415 }
416
417 // OK, first sort out the time
418 if (! bParseTime(&VstrTmp[0], nHour, nMin, nSec))
419 {
420 strErr = "line " + to_string(nLine) + ": could not understand simulation start time in '" + m_strDataPathName + "'";
421 break;
422 }
423
424 // Next sort out the date
425 if (! bParseDate(&VstrTmp[1], nDay, nMonth, nYear))
426 {
427 strErr = "line " + to_string(nLine) + ": could not understand simulation start date in '" + m_strDataPathName + "'";
428 break;
429 }
430
431 // Store simulation start time and date
432 m_nSimStartSec = nSec;
433 m_nSimStartMin = nMin;
434 m_nSimStartHour = nHour;
435 m_nSimStartDay = nDay;
436 m_nSimStartMonth = nMonth;
437 m_nSimStartYear = nYear;
438
439 break;
440
441 case 5:
442 // Duration of simulation (in hours, days, months, or years): sort out multiplier and user units, as used in the per-timestep output
443 strRH = strToLower(&strRH);
444
445 nRet = nDoSimulationTimeMultiplier(&strRH);
446
447 if (nRet != RTN_OK)
448 {
449 strErr = "line " + to_string(nLine) + ": units for duration of simulation";
450 break;
451 }
452
453 // And now calculate the duration of the simulation in hours: first find whitespace between the number and the unit
454 nPos = strRH.rfind(SPACE);
455
456 if (nPos == string::npos)
457 {
458 strErr = "line " + to_string(nLine) + ": format of duration simulation line";
459 break;
460 }
461
462 // Cut off rh bit of string
463 strRH.resize(nPos);
464
465 // Remove trailing spaces
466 strRH = strTrimRight(&strRH);
467
468 // Calculate the duration of the simulation in hours
469 m_dSimDuration = strtod(strRH.c_str(), NULL) * m_dDurationUnitsMult;
470
471 if (m_dSimDuration <= 0)
472 strErr = "line " + to_string(nLine) + ": duration of simulation must be > 0";
473
474 break;
475
476 case 6:
477 // Timestep of simulation (in hours or days)
478 strRH = strToLower(&strRH);
479
480 dMult = dGetTimeMultiplier(&strRH);
481
482 if (static_cast<int>(dMult) == TIME_UNKNOWN)
483 {
484 strErr = "line " + to_string(nLine) + ": units for simulation timestep";
485 break;
486 }
487
488 // We have the multiplier, now calculate the timestep in hours: look for the whitespace between the number and unit
489 nPos = strRH.rfind(SPACE);
490
491 if (nPos == string::npos)
492 {
493 strErr = "line " + to_string(nLine) + ": format of simulation timestep";
494 break;
495 }
496
497 // Cut off rh bit of string
498 strRH.resize(nPos);
499
500 // Remove trailing spaces
501 strRH = strTrimRight(&strRH);
502
503 // Check that this is a valid double
504 if (! bIsStringValidDouble(strRH))
505 {
506 strErr = "line " + to_string(nLine) + ": invalid floating point number for timestep '" + strRH + "' in " + m_strDataPathName;
507 break;
508 }
509
510 m_dTimeStep = strtod(strRH.c_str(), NULL) * dMult; // in hours
511
512 if (m_dTimeStep <= 0)
513 strErr = "line " + to_string(nLine) + ": timestep of simulation must be > 0";
514
516 strErr = "line " + to_string(nLine) + ": timestep of simulation must be < the duration of the simulation";
517
518 break;
519
520 case 7:
521 {
522 // Save interval(s) - can handle multiple groups with different units if groups are comma-separated e.g., "6 12 24 48 hours, 1 2 6 months, 1 years"
523 strRH = strToLower(&strRH);
524
525 // Split by commas to handle multiple unit groups
526 string const strOriginal = strRH;
527 size_t nCommaPos = 0;
528
529 m_bSaveRegular = false; // Start with assumption of multiple values
530
531 do
532 {
533 string strGroup;
534 size_t const nNextComma = strOriginal.find(',', nCommaPos);
535
536 if (nNextComma != string::npos)
537 {
538 strGroup = strOriginal.substr(nCommaPos, nNextComma - nCommaPos);
539 nCommaPos = nNextComma + 1;
540 }
541
542 else
543 {
544 strGroup = strOriginal.substr(nCommaPos);
545 nCommaPos = string::npos;
546 }
547
548 // Trim whitespace from group
549 strGroup = strTrimLeft(&strGroup);
550 strGroup = strTrimRight(&strGroup);
551
552 if (strGroup.empty())
553 continue;
554
555 // Get the multiplier for this group
556 dMult = dGetTimeMultiplier(&strGroup);
557
558 if (static_cast<int>(dMult) == TIME_UNKNOWN)
559 {
560 strErr = "line " + to_string(nLine) + ": units for save intervals in group '" + strGroup + "'";
561 break;
562 }
563
564 // Remove the unit text from the end
565 size_t const nLastSpace = strGroup.rfind(SPACE);
566
567 if (nLastSpace == string::npos)
568 {
569 strErr = "line " + to_string(nLine) + ": format of save times/intervals in group '" + strGroup + "'";
570 break;
571 }
572
573 string strNumbers = strGroup.substr(0, nLastSpace);
574 strNumbers = strTrimRight(&strNumbers);
575
576 // Parse numbers in this group
577 size_t nSpacePos = 0;
578 strNumbers += SPACE; // Add trailing space to help parsing
579
580 do
581 {
582 size_t const nNextSpace = strNumbers.find(SPACE, nSpacePos);
583
584 if (nNextSpace == string::npos)
585 break;
586
587 string const strNumber = strNumbers.substr(nSpacePos, nNextSpace - nSpacePos);
588
589 if (!strNumber.empty())
590 {
591 if (m_nUSave > static_cast<int>(SAVEMAX) - 1)
592 {
593 strErr = "line " + to_string(nLine) + ": too many save intervals";
594 break;
595 }
596
597 double const dValue = strtod(strNumber.c_str(), NULL) * dMult;
598 m_dUSaveTime[m_nUSave++] = dValue;
599 }
600
601 nSpacePos = nNextSpace + 1;
602 } while (nSpacePos < strNumbers.length());
603
604 if (! strErr.empty())
605 break;
606 } while (nCommaPos != string::npos);
607
608 if (! strErr.empty())
609 break;
610
611 // Check if we only have one value (making it a regular interval)
612 if (m_nUSave == 1)
613 {
614 m_bSaveRegular = true;
616
618 strErr = "line " + to_string(nLine) + ": save interval cannot be less than timestep";
619
620 else
622 }
623
624 else if (m_nUSave > 1)
625 {
626 // Multiple values - sort them and validate
628
629 if (m_dUSaveTime[0] < m_dTimeStep)
630 {
631 strErr = "line " + to_string(nLine) + ": first save time cannot be less than timestep";
632 break;
633 }
634
635 // Put a dummy save interval as the last entry in the array
637 }
638
639 else
640 {
641 strErr = "line " + to_string(nLine) + ": no save times specified";
642 }
643 }
644 break;
645
646 case 8:
647 // Random number seed(s)
648 if (strRH.empty())
649 {
650 // User didn't specify a random number seed, so seed with a real random value, if available
651 random_device rdev;
652 m_ulRandSeed[0] = rdev();
653
654 // Only one seed specified, so make all seeds the same
655 for (int n = 1; n < NUMBER_OF_RNGS; n++)
656 m_ulRandSeed[n] = m_ulRandSeed[n - 1];
657 }
658
659 else
660 {
661 // User did specify at least one random number seed. Next find out whether we're dealing with a single seed or more than one: check for a space
662 nPos = strRH.find(SPACE);
663
664 if (nPos == string::npos)
665 {
666 // No space, so we have just one one number
667 m_ulRandSeed[0] = atol(strRH.c_str());
668
669 // Only one seed specified, so make all seeds the same
670 for (int n = 1; n < NUMBER_OF_RNGS; n++)
671 m_ulRandSeed[n] = m_ulRandSeed[n - 1];
672 }
673
674 else
675 {
676 // The user has supplied more than one random number seed
677 int n = 0;
678
679 do
680 {
681 // Get LH bit
682 strTmp = strRH.substr(0, nPos);
683 m_ulRandSeed[n++] = atol(strTmp.c_str());
684
685 if (n == NUMBER_OF_RNGS)
686 // All random number seeds read
687 break;
688
689 // We need more seeds, so get the RH bit
690 strRH = strRH.substr(nPos, strRH.size() - nPos);
691 strRH = strTrimLeft(&strRH);
692
693 if (strRH.size() == 0)
694 // No more seeds left to read
695 break;
696 } while (true);
697
698 // If we haven't filled all random number seeds, make all the remainder the same as the last one read
699 if (n < NUMBER_OF_RNGS - 1)
700 {
701 for (int m = n; m < NUMBER_OF_RNGS; m++)
703 }
704 }
705 }
706
707 break;
708
709 case 9:
710 // Max save digits for GIS output file names
711 if (! bIsStringValidInt(strRH))
712 {
713 strErr = "line " + to_string(nLine) + ": invalid integer for max save digits for GIS output file names '" + strRH + "' in " + m_strDataPathName;
714 break;
715 }
716
717 m_nGISMaxSaveDigits = stoi(strRH);
718
719 if (m_nGISMaxSaveDigits < 2)
720 strErr = "line " + to_string(nLine) + ": max save digits for GIS output file names must be > 1";
721
722 break;
723
724 case 10:
725 // Save digits for GIS output sequential or iteration number? [s = sequential, i = iteration]: s
726 if (strRH.empty())
727 strErr = "line " + to_string(nLine) + ": must specify save digits for GIS output as sequential or as iteration number";
728
729 else
730 {
731 // Convert to lower case
732 strRH = strToLower(&strRH);
733
734 if (strRH.find('s') != string::npos)
735 {
736 // First look for 's'
738 }
739
740 else if (strRH.find('i') != string::npos)
741 {
742 // Now look for 'i'
744 }
745
746 else
747 {
748 strErr = "line ";
749 strErr += to_string(nLine);
750 strErr += ": invalid code for save digits for GIS output save number (must be s or i)";
751
752 break;
753 }
754 }
755
756 break;
757
758 case 11:
759 // Raster GIS files to output
760 if (strRH.empty())
761 {
762 strErr = "line ";
763 strErr += to_string(nLine);
764 strErr += ": must contain '";
765 strErr += RASTER_ALL_OUTPUT_CODE;
766 strErr += "', or '";
767 strErr += RASTER_USUAL_OUTPUT_CODE;
768 strErr += "', or at least one raster GIS output code";
769 }
770 else
771 {
772 // Convert to lower case
773 strRH = strToLower(&strRH);
774
775 if (strRH.find(RASTER_ALL_OUTPUT_CODE) != string::npos)
776 {
777 // Set switches for all GIS raster output. Some of these (e.g. all relating to fine sediment) are ignored if e.g. no fine sediment layers are read in
778 m_bSuspSedSave = true;
779 m_bAvgSuspSedSave = true;
781 m_bFineConsSedSave = true;
783 m_bSandConsSedSave = true;
788 m_bTalusSave = true;
789 m_bSeaDepthSave = true;
790 m_bWaveHeightSave = true;
791 m_bWaveAngleSave = true;
802 m_bLandformSave = true;
803 m_bSlopeConsSedSave = true;
805 m_bCliffToeSave = true;
806 m_bAvgSeaDepthSave = true;
808 m_bAvgWaveAngleSave = true;
810 m_bBasementElevSave = true;
813 m_bActiveZoneSave = true;
820 m_bSeaMaskSave = true;
821 m_bBeachMaskSave = true;
830 }
831 else if (strRH.find(RASTER_USUAL_OUTPUT_CODE) != string::npos)
832 {
833 // Set switches for usual GIS raster output. Again, some of these (e.g. all relating to fine sediment) are ignored if they are irrelevant
834 m_bSuspSedSave = true;
835 m_bAvgSuspSedSave = true;
837 m_bFineConsSedSave = true;
839 m_bSandConsSedSave = true;
844 m_bTalusSave = true;
845 m_bSeaDepthSave = true;
846 m_bWaveHeightSave = true;
847 m_bWaveAngleSave = true;
858 m_bLandformSave = true;
859 m_bSlopeConsSedSave = true;
862 m_bAvgWaveAngleSave = true;
864 m_bBasementElevSave = true;
865 m_bActiveZoneSave = true;
878 }
879 else
880 {
881 // We are not outputting either the "usual" or the "all" collections of raster GIS files, so set switches (and remove strings) for those optional files for which the user specified the code
882 if (strRH.find(RASTER_SEDIMENT_TOP_CODE) != string::npos)
883 {
886 }
887
888 if (strRH.find(RASTER_TOP_ELEVATION_INC_SEA_CODE) != string::npos)
889 {
892 }
893
894 if (strRH.find(RASTER_TALUS_CODE) != string::npos)
895 {
896 m_bTalusSave = true;
897 strRH = strRemoveSubstr(&strRH, &RASTER_TALUS_CODE);
898 }
899
900 if (strRH.find(RASTER_SEA_DEPTH_CODE) != string::npos)
901 {
902 m_bSeaDepthSave = true;
903 strRH = strRemoveSubstr(&strRH, &RASTER_SEA_DEPTH_CODE);
904 }
905
906 if (strRH.find(RASTER_WAVE_HEIGHT_CODE) != string::npos)
907 {
908 m_bWaveHeightSave = true;
910 }
911
912 if (strRH.find(RASTER_WAVE_ORIENTATION_CODE) != string::npos)
913 {
914 m_bWaveAngleSave = true;
916 }
917
918 if (strRH.find(RASTER_WAVE_PERIOD_CODE) != string::npos)
919 {
922 }
923
924 if (strRH.find(RASTER_POTENTIAL_PLATFORM_EROSION_CODE) != string::npos)
925 {
928 }
929
930 if (strRH.find(RASTER_ACTUAL_PLATFORM_EROSION_CODE) != string::npos)
931 {
934 }
935
936 if (strRH.find(RASTER_TOTAL_POTENTIAL_PLATFORM_EROSION_CODE) != string::npos)
937 {
940 }
941
942 if (strRH.find(RASTER_TOTAL_ACTUAL_PLATFORM_EROSION_CODE) != string::npos)
943 {
946 }
947
948 if (strRH.find(RASTER_POTENTIAL_BEACH_EROSION_CODE) != string::npos)
949 {
952 }
953
954 if (strRH.find(RASTER_ACTUAL_BEACH_EROSION_CODE) != string::npos)
955 {
958 }
959
960 if (strRH.find(RASTER_TOTAL_POTENTIAL_BEACH_EROSION_CODE) != string::npos)
961 {
964 }
965
966 if (strRH.find(RASTER_TOTAL_ACTUAL_BEACH_EROSION_CODE) != string::npos)
967 {
970 }
971
972 if (strRH.find(RASTER_LANDFORM_CODE) != string::npos)
973 {
974 m_bLandformSave = true;
975 strRH = strRemoveSubstr(&strRH, &RASTER_LANDFORM_CODE);
976 }
977
978 if (strRH.find(RASTER_AVG_SEA_DEPTH_CODE) != string::npos)
979 {
980 m_bAvgSeaDepthSave = true;
982 }
983
984 if (strRH.find(RASTER_AVG_WAVE_HEIGHT_CODE) != string::npos)
985 {
988 }
989
990 if (strRH.find(RASTER_AVG_WAVE_ORIENTATION_CODE) != string::npos)
991 {
992 m_bAvgWaveAngleSave = true;
994 }
995
996 if (strRH.find(RASTER_BEACH_PROTECTION_CODE) != string::npos)
997 {
1000 }
1001
1002 if (strRH.find(RASTER_BASEMENT_ELEVATION_CODE) != string::npos)
1003 {
1004 m_bBasementElevSave = true;
1006 }
1007
1008 if (strRH.find(RASTER_SUSP_SED_CODE) != string::npos)
1009 {
1010 m_bSuspSedSave = true;
1011 strRH = strRemoveSubstr(&strRH, &RASTER_SUSP_SED_CODE);
1012 }
1013
1014 if (strRH.find(RASTER_AVG_SUSP_SED_CODE) != string::npos)
1015 {
1016 m_bAvgSuspSedSave = true;
1017 strRH = strRemoveSubstr(&strRH, &RASTER_AVG_SUSP_SED_CODE);
1018 }
1019
1020 if (strRH.find(RASTER_FINE_UNCONS_CODE) != string::npos)
1021 {
1022 m_bFineUnconsSedSave = true;
1023 strRH = strRemoveSubstr(&strRH, &RASTER_FINE_UNCONS_CODE);
1024 }
1025
1026 if (strRH.find(RASTER_SAND_UNCONS_CODE) != string::npos)
1027 {
1028 m_bSandUnconsSedSave = true;
1029 strRH = strRemoveSubstr(&strRH, &RASTER_SAND_UNCONS_CODE);
1030 }
1031
1032 if (strRH.find(RASTER_COARSE_UNCONS_CODE) != string::npos)
1033 {
1036 }
1037
1038 if (strRH.find(RASTER_FINE_CONS_CODE) != string::npos)
1039 {
1040 m_bFineConsSedSave = true;
1041 strRH = strRemoveSubstr(&strRH, &RASTER_FINE_CONS_CODE);
1042 }
1043
1044 if (strRH.find(RASTER_SAND_CONS_CODE) != string::npos)
1045 {
1046 m_bSandConsSedSave = true;
1047 strRH = strRemoveSubstr(&strRH, &RASTER_SAND_CONS_CODE);
1048 }
1049
1050 if (strRH.find(RASTER_COARSE_CONS_CODE) != string::npos)
1051 {
1052 m_bCoarseConsSedSave = true;
1053 strRH = strRemoveSubstr(&strRH, &RASTER_COARSE_CONS_CODE);
1054 }
1055
1056 if (strRH.find(RASTER_COAST_CODE) != string::npos)
1057 {
1059 strRH = strRemoveSubstr(&strRH, &RASTER_COAST_CODE);
1060 }
1061
1062 if (strRH.find(RASTER_COAST_NORMAL_CODE) != string::npos)
1063 {
1065 strRH = strRemoveSubstr(&strRH, &RASTER_COAST_NORMAL_CODE);
1066 }
1067
1068 if (strRH.find(RASTER_ACTIVE_ZONE_CODE) != string::npos)
1069 {
1070 m_bActiveZoneSave = true;
1071 strRH = strRemoveSubstr(&strRH, &RASTER_ACTIVE_ZONE_CODE);
1072 }
1073
1074 if (strRH.find(RASTER_CLIFF_COLLAPSE_EROSION_FINE_CODE) != string::npos)
1075 {
1076 m_bCliffCollapseSave = true;
1078 }
1079
1080 if (strRH.find(RASTER_CLIFF_COLLAPSE_EROSION_SAND_CODE) != string::npos)
1081 {
1082 m_bCliffCollapseSave = true;
1084 }
1085
1086 if (strRH.find(RASTER_CLIFF_COLLAPSE_EROSION_COARSE_CODE) != string::npos)
1087 {
1088 m_bCliffCollapseSave = true;
1090 }
1091
1092 if (strRH.find(RASTER_TOTAL_CLIFF_COLLAPSE_EROSION_FINE_CODE) != string::npos)
1093 {
1096 }
1097
1098 if (strRH.find(RASTER_TOTAL_CLIFF_COLLAPSE_EROSION_SAND_CODE) != string::npos)
1099 {
1102 }
1103
1104 if (strRH.find(RASTER_TOTAL_CLIFF_COLLAPSE_EROSION_COARSE_CODE) != string::npos)
1105 {
1108 }
1109
1110 if (strRH.find(RASTER_CLIFF_COLLAPSE_DEPOSITION_SAND_CODE) != string::npos)
1111 {
1114 }
1115
1116 if (strRH.find(RASTER_CLIFF_COLLAPSE_DEPOSITION_COARSE_CODE) != string::npos)
1117 {
1120 }
1121
1122 if (strRH.find(RASTER_TOTAL_CLIFF_COLLAPSE_DEPOSITION_SAND_CODE) != string::npos)
1123 {
1126 }
1127
1128 if (strRH.find(RASTER_TOTAL_CLIFF_COLLAPSE_DEPOSITION_COARSE_CODE) != string::npos)
1129 {
1132 }
1133
1134 if (strRH.find(RASTER_POLYGON_CODE) != string::npos)
1135 {
1136 m_bRasterPolygonSave = true;
1137 strRH = strRemoveSubstr(&strRH, &RASTER_POLYGON_CODE);
1138 }
1139
1140 if (strRH.find(RASTER_POTENTIAL_PLATFORM_EROSION_MASK_CODE) != string::npos)
1141 {
1144 }
1145
1146 if (strRH.find(RASTER_INUNDATION_MASK_CODE) != string::npos)
1147 {
1148 m_bSeaMaskSave = true;
1150 }
1151
1152 if (strRH.find(RASTER_BEACH_MASK_CODE) != string::npos)
1153 {
1154 m_bBeachMaskSave = true;
1155 strRH = strRemoveSubstr(&strRH, &RASTER_BEACH_MASK_CODE);
1156 }
1157
1158 if (strRH.find(RASTER_INTERVENTION_CLASS_CODE) != string::npos)
1159 {
1162 }
1163
1164 if (strRH.find(RASTER_INTERVENTION_HEIGHT_CODE) != string::npos)
1165 {
1168 }
1169
1170 if (strRH.find(RASTER_SHADOW_ZONE_CODE) != string::npos)
1171 {
1173 strRH = strRemoveSubstr(&strRH, &RASTER_SHADOW_ZONE_CODE);
1174 }
1175
1176 if (strRH.find(RASTER_DEEP_WATER_WAVE_ORIENTATION_CODE) != string::npos)
1177 {
1180 }
1181
1182 if (strRH.find(RASTER_DEEP_WATER_WAVE_HEIGHT_CODE) != string::npos)
1183 {
1186 }
1187
1188 if (strRH.find(RASTER_DEEP_WATER_WAVE_PERIOD_CODE) != string::npos)
1189 {
1192 }
1193
1194 if (strRH.find(RASTER_POLYGON_UPDRIFT_OR_DOWNDRIFT_CODE) != string::npos)
1195 {
1198 }
1199
1200 if (strRH.find(RASTER_POLYGON_GAIN_OR_LOSS_CODE) != string::npos)
1201 {
1204 }
1205
1206 if (strRH.find(RASTER_BEACH_DEPOSITION_CODE) != string::npos)
1207 {
1210 }
1211
1212 if (strRH.find(RASTER_TOTAL_BEACH_DEPOSITION_CODE) != string::npos)
1213 {
1216 }
1217
1218 if (strRH.find(RASTER_SEDIMENT_INPUT_EVENT_CODE) != string::npos)
1219 {
1222 }
1223
1224 if (strRH.find(RASTER_SETUP_SURGE_FLOOD_MASK_CODE) != string::npos)
1225 {
1228 }
1229
1230 if (strRH.find(RASTER_SETUP_SURGE_RUNUP_FLOOD_MASK_CODE) != string::npos)
1231 {
1234 }
1235
1236 if (strRH.find(RASTER_WAVE_FLOOD_LINE_CODE) != string::npos)
1237 {
1240 }
1241
1242 if (strRH.find(RASTER_CLIFF_NOTCH_ALL_CODE) != string::npos)
1243 {
1244 m_bCliffNotchAllSave = true;
1246 }
1247
1248 if (strRH.find(RASTER_CLIFF_COLLAPSE_TIMESTEP_CODE) != string::npos)
1249 {
1252 }
1253
1254 // Check to see if all codes have been removed
1255 if (! strRH.empty())
1256 strErr = "line " + to_string(nLine) + ": unknown code '" + strRH + "' in list of codes for raster GIS output";
1257 }
1258 }
1259
1260 break;
1261
1262 case 12:
1263 // Raster GIS output format (note must retain original case). Blank means use same format as input DEM file (if possible)
1265
1266 // TODO 065 Remove this when GDAL gpkg raster output is working correctly
1267 if (strRH.find("gpkg") != string::npos)
1268 strErr = "GDAL gpkg raster create() is not yet working correctly. Please choose another output format.";
1269
1270 break;
1271
1272 case 13:
1273 // If needed, scale GIS raster output values
1274 strRH = strToLower(&strRH);
1275
1276 m_bScaleRasterOutput = false;
1277
1278 if (strRH.find('y') != string::npos)
1279 m_bScaleRasterOutput = true;
1280
1281 break;
1282
1283 case 14:
1284 // If needed, also output GIS raster world file
1285 strRH = strToLower(&strRH);
1286
1287 m_bWorldFile = false;
1288
1289 if (strRH.find('y') != string::npos)
1290 m_bWorldFile = true;
1291
1292 break;
1293
1294 case 15:
1295 // Elevations for raster slice output, if desired
1296 if (! strRH.empty())
1297 {
1298 m_bSliceSave = true;
1299
1300 // OK, so find out whether we're dealing with a single seed or more than one: check for a space
1301 nPos = strRH.find(SPACE);
1302
1303 if (nPos != string::npos)
1304 {
1305 // There's a space, so we must have more than one number
1306 do
1307 {
1308 // Get LH bit
1309 strTmp = strRH.substr(0, nPos);
1310 m_VdSliceElev.push_back(strtod(strTmp.c_str(), NULL));
1311
1312 // Get the RH bit
1313 strRH = strRH.substr(nPos, strRH.size() - nPos);
1314 strRH = strTrimLeft(&strRH);
1315
1316 // Now look for another space
1317 nPos = strRH.find(SPACE);
1318 } while (nPos != string::npos);
1319 }
1320
1321 // Read either the single number, or the left-over number
1322 m_VdSliceElev.push_back(strtod(strTmp.c_str(), NULL));
1323 }
1324
1325 break;
1326
1327 case 16:
1328 // Vector GIS files to output
1329 if (strRH.empty())
1330 {
1331 strErr = "line ";
1332 strErr += to_string(nLine);
1333 strErr += ": must contain '";
1334 strErr += VECTOR_ALL_OUTPUT_CODE;
1335 strErr += "', or '";
1336 strErr += VECTOR_USUAL_OUTPUT_CODE;
1337 strErr += "', or at least one vector GIS output code";
1338 }
1339
1340 else
1341 {
1342 strRH = strToLower(&strRH);
1343
1344 if (strRH.find(VECTOR_ALL_OUTPUT_CODE) != string::npos)
1345 {
1346 // Output all vector files
1347 m_bCoastSave = true;
1348 m_bCliffEdgeSave = true;
1350 m_bNormalsSave = true;
1351 m_bInvalidNormalsSave = true;
1354 m_bMeanWaveEnergySave = true;
1356 m_bCoastCurvatureSave = true;
1357 m_bPolygonNodeSave = true;
1359 m_bCliffNotchSave = true;
1360 m_bShadowBoundarySave = true;
1363 m_bWaveSetupSave = true;
1364 m_bStormSurgeSave = true;
1365 m_bRunUpSave = true;
1367 }
1368 else if (strRH.find(VECTOR_USUAL_OUTPUT_CODE) != string::npos)
1369 {
1370 // Output the "usual" collection of vector output files
1371 m_bCoastSave = true;
1372 m_bCliffEdgeSave = true;
1374 m_bNormalsSave = true;
1375 m_bInvalidNormalsSave = true;
1378 m_bMeanWaveEnergySave = true;
1381 m_bCliffNotchSave = true;
1382 m_bShadowBoundarySave = true;
1385 }
1386 else
1387 {
1388 // Output only those vector files for which the user specified the code
1389 if (strRH.find(VECTOR_COAST_CODE) != string::npos)
1390 {
1391 m_bCoastSave = true;
1392 strRH = strRemoveSubstr(&strRH, &VECTOR_COAST_CODE);
1393 }
1394
1395 if (strRH.find(VECTOR_CLIFF_EDGE_CODE) != string::npos)
1396 {
1397 m_bCliffEdgeSave = true;
1398 strRH = strRemoveSubstr(&strRH, &VECTOR_CLIFF_EDGE_CODE);
1399 }
1400
1401 if (strRH.find(VECTOR_AVG_WAVE_ANGLE_AND_HEIGHT_CODE) != string::npos)
1402 {
1405 }
1406
1407 if (strRH.find(VECTOR_NORMALS_CODE) != string::npos)
1408 {
1409 m_bNormalsSave = true;
1410 strRH = strRemoveSubstr(&strRH, &VECTOR_NORMALS_CODE);
1411 }
1412
1413 if (strRH.find(VECTOR_INVALID_NORMALS_CODE) != string::npos)
1414 {
1415 m_bInvalidNormalsSave = true;
1417 }
1418
1419 if (strRH.find(VECTOR_AVG_WAVE_ANGLE_AND_HEIGHT_CODE) != string::npos)
1420 {
1423 }
1424
1425 if (strRH.find(VECTOR_COAST_CURVATURE_CODE) != string::npos)
1426 {
1427 m_bCoastCurvatureSave = true;
1429 }
1430
1431 if (strRH.find(VECTOR_WAVE_ENERGY_SINCE_COLLAPSE_CODE) != string::npos)
1432 {
1435 }
1436
1437 if (strRH.find(VECTOR_MEAN_WAVE_ENERGY_CODE) != string::npos)
1438 {
1439 m_bMeanWaveEnergySave = true;
1441 }
1442
1443 if (strRH.find(VECTOR_BREAKING_WAVE_HEIGHT_CODE) != string::npos)
1444 {
1447 }
1448
1449 if (strRH.find(VECTOR_POLYGON_NODE_CODE) != string::npos)
1450 {
1451 m_bPolygonNodeSave = true;
1452 strRH = strRemoveSubstr(&strRH, &VECTOR_POLYGON_NODE_CODE);
1453 }
1454
1455 if (strRH.find(VECTOR_POLYGON_BOUNDARY_CODE) != string::npos)
1456 {
1459 }
1460
1461 if (strRH.find(VECTOR_CLIFF_NOTCH_ACTIVE_CODE) != string::npos)
1462 {
1463 m_bCliffNotchSave = true;
1465 }
1466
1467 if (strRH.find(VECTOR_SHADOW_ZONE_BOUNDARY_CODE) != string::npos)
1468 {
1469 m_bShadowBoundarySave = true;
1471 }
1472
1473 if (strRH.find(VECTOR_DOWNDRIFT_ZONE_BOUNDARY_CODE) != string::npos)
1474 {
1477 }
1478
1479 if (strRH.find(VECTOR_DEEP_WATER_WAVE_ANGLE_AND_HEIGHT_CODE) != string::npos)
1480 {
1483 }
1484
1485 if (strRH.find(VECTOR_WAVE_SETUP_CODE) != string::npos)
1486 {
1487 m_bWaveSetupSave = true;
1488 strRH = strRemoveSubstr(&strRH, &VECTOR_WAVE_SETUP_CODE);
1489 }
1490
1491 if (strRH.find(VECTOR_STORM_SURGE_CODE) != string::npos)
1492 {
1493 m_bStormSurgeSave = true;
1494 strRH = strRemoveSubstr(&strRH, &VECTOR_STORM_SURGE_CODE);
1495 }
1496
1497 if (strRH.find(VECTOR_RUN_UP_CODE) != string::npos)
1498 {
1499 m_bRunUpSave = true;
1500 strRH = strRemoveSubstr(&strRH, &VECTOR_RUN_UP_CODE);
1501 }
1502
1503 if (strRH.find(VECTOR_FLOOD_LINE_CODE) != string::npos)
1504 {
1506 strRH = strRemoveSubstr(&strRH, &VECTOR_FLOOD_LINE_CODE);
1507 }
1508
1509 // Check to see if all codes have been removed
1510 if (! strRH.empty())
1511 strErr = "line " + to_string(nLine) + ": unknown code '" + strRH + "' in list of vector GIS output codes";
1512 }
1513 }
1514
1515 break;
1516
1517 case 17:
1518 // Vector GIS output format (note must retain original case)
1520
1521 if (strRH.empty())
1522 strErr = "line " + to_string(nLine) + ": vector GIS output format";
1523
1524 break;
1525
1526 case 18:
1527 // Time series files to output
1528 if (! strRH.empty())
1529 {
1530 strRH = strToLower(&strRH);
1531
1532 // First check for "all"
1533 if (strRH.find(RASTER_ALL_OUTPUT_CODE) != string::npos)
1534 {
1535 m_bSeaAreaTSSave = true;
1536 m_bSWLTSSave = true;
1541 m_bBeachErosionTSSave = true;
1544 m_bSuspSedTSSave = true;
1548 }
1549 else
1550 {
1551 if (strRH.find(TIME_SERIES_SEA_AREA_CODE) != string::npos)
1552 {
1553 m_bSeaAreaTSSave = true;
1555 }
1556
1557 if (strRH.find(TIME_SERIES_SWL_CODE) != string::npos)
1558 {
1559 m_bSWLTSSave = true;
1560 strRH = strRemoveSubstr(&strRH, &TIME_SERIES_SWL_CODE);
1561 }
1562
1563 if (strRH.find(TIME_SERIES_PLATFORM_EROSION_CODE) != string::npos)
1564 {
1567 }
1568
1569 if (strRH.find(TIME_SERIES_CLIFF_COLLAPSE_EROSION_CODE) != string::npos)
1570 {
1573 }
1574
1575 if (strRH.find(TIME_SERIES_CLIFF_COLLAPSE_DEPOSITION_CODE) != string::npos)
1576 {
1579 }
1580
1581 if (strRH.find(TIME_SERIES_CLIFF_COLLAPSE_NET_CODE) != string::npos)
1582 {
1585 }
1586
1587 if (strRH.find(TIME_SERIES_BEACH_EROSION_CODE) != string::npos)
1588 {
1589 m_bBeachErosionTSSave = true;
1591 }
1592
1593 if (strRH.find(TIME_SERIES_BEACH_DEPOSITION_CODE) != string::npos)
1594 {
1597 }
1598
1599 if (strRH.find(TIME_SERIES_BEACH_CHANGE_NET_CODE) != string::npos)
1600 {
1603 }
1604
1605 if (strRH.find(TIME_SERIES_SUSPENDED_SEDIMENT_CODE) != string::npos)
1606 {
1607 m_bSuspSedTSSave = true;
1609 }
1610
1611 if (strRH.find(TIME_SERIES_FLOOD_SETUP_SURGE_CODE) != string::npos)
1612 {
1615 }
1616
1617 if (strRH.find(TIME_SERIES_FLOOD_SETUP_SURGE_RUNUP_CODE) != string::npos)
1618 {
1621 }
1622
1623 if (strRH.find(TIME_SERIES_CLIFF_NOTCH_ELEV_CODE) != string::npos)
1624 {
1627 }
1628
1629 // Check to see if all codes have been removed
1630 if (! strRH.empty())
1631 strErr = "line " + to_string(nLine) + ": unknown code '" + strRH + "' in list of time series output files";
1632 }
1633 }
1634
1635 break;
1636
1637 case 19:
1638 // Vector coastline smoothing algorithm: 0 = none, 1 = running mean, 2 = Savitzky-Golay
1639 if (! bIsStringValidInt(strRH))
1640 {
1641 strErr = "line " + to_string(nLine) + ": invalid integer for coastline smoothing algorithm '" + strRH + "' in " + m_strDataPathName;
1642 break;
1643 }
1644
1645 m_nCoastSmooth = stoi(strRH);
1646
1648 strErr = "line " + to_string(nLine) + ": coastline vector smoothing algorithm must be " + to_string(SMOOTH_NONE) + ", " + to_string(SMOOTH_RUNNING_MEAN) + ", or " + to_string(SMOOTH_SAVITZKY_GOLAY);
1649
1650 break;
1651
1652 case 20:
1653 // Size of coastline smoothing window: must be odd
1654 if (! bIsStringValidInt(strRH))
1655 {
1656 strErr = "line " + to_string(nLine) + ": invalid integer for coastline smoothing window '" + strRH + "' in " + m_strDataPathName;
1657 break;
1658 }
1659
1660 m_nCoastSmoothingWindowSize = stoi(strRH);
1661
1663 strErr = "line " + to_string(nLine) + ": size of coastline vector smoothing window (must be > 0 and odd)";
1664
1665 break;
1666
1667 case 21:
1668 // Order of coastline profile smoothing polynomial for Savitzky-Golay: usually 2 or 4, max is 6
1669 if (! bIsStringValidInt(strRH))
1670 {
1671 strErr = "line " + to_string(nLine) + ": invalid integer for Savitzky-Golay polynomial for coastline smoothing '" + strRH + "' in " + m_strDataPathName;
1672 break;
1673 }
1674
1675 m_nSavGolCoastPoly = stoi(strRH);
1676
1677 if ((m_nSavGolCoastPoly <= 0) || (m_nSavGolCoastPoly > 6))
1678 strErr = "line " + to_string(nLine) + ": value of Savitzky-Golay polynomial for coastline smoothing (must be <= 6)";
1679
1680 break;
1681
1682 case 22:
1683 // Grid edge(s) to omit when searching for coastline [NSWE]
1684 strRH = strToLower(&strRH);
1685
1686 if (strRH.find('n') != string::npos)
1687 {
1689 }
1690
1691 if (strRH.find('s') != string::npos)
1692 {
1694 }
1695
1696 if (strRH.find('w') != string::npos)
1697 {
1698 m_bOmitSearchWestEdge = true;
1699 }
1700
1701 if (strRH.find('e') != string::npos)
1702 {
1703 m_bOmitSearchEastEdge = true;
1704 }
1705
1706 break;
1707
1708 case 23:
1709 // Profile slope running-mean smoothing window size: must be odd
1710 if (! bIsStringValidInt(strRH))
1711 {
1712 strErr = "line " + to_string(nLine) + ": invalid integer for size of coastline smoothing window '" + strRH + "' in " + m_strDataPathName;
1713 break;
1714 }
1715
1716 m_nProfileSmoothWindow = stoi(strRH);
1717
1719 strErr = "line " + to_string(nLine) + ": size of profile vector smoothing window (must be >= 0, if > 0 must be odd)";
1720
1721 break;
1722
1723 case 24:
1724 // Max local slope (m/m), first check that this is a valid double
1725 if (! bIsStringValidDouble(strRH))
1726 {
1727 strErr = "line " + to_string(nLine) + ": invalid floating point number for max local slope '" + strRH + "' in " + m_strDataPathName;
1728 break;
1729 }
1730
1731 m_dProfileMaxSlope = strtod(strRH.c_str(), NULL);
1732
1733 if (m_dProfileMaxSlope <= 0)
1734 strErr = "line " + to_string(nLine) + ": max local slope must be > 0";
1735
1736 break;
1737
1738 case 25:
1739 // Maximum elevation of beach above SWL, first check that this is a valid double
1740 if (! bIsStringValidDouble(strRH))
1741 {
1742 strErr = "line " + to_string(nLine) + ": invalid floating point number for maximum elevation of beach above SWL '" + strRH + "' in " + m_strDataPathName;
1743 break;
1744 }
1745
1746 m_dMaxBeachElevAboveSWL = strtod(strRH.c_str(), NULL);
1747
1749 strErr = "line " + to_string(nLine) + ": maximum elevation of beach above SWL must be >= 0";
1750
1751 break;
1752
1753 // ------------------------------------------------- Raster GIS layers ------------------------------------------------
1754 case 26:
1755 // Number of sediment layers
1756 if (! bIsStringValidInt(strRH))
1757 {
1758 strErr = "line " + to_string(nLine) + ": invalid integer for number of sediment layers '" + strRH + "' in " + m_strDataPathName;
1759 break;
1760 }
1761
1762 m_nLayers = stoi(strRH);
1763
1764 if (m_nLayers < 1)
1765 {
1766 strErr = "line " + to_string(nLine) + ": must be at least one sediment layer";
1767 break;
1768 }
1769
1770 // OK we know the number of layers, so add elements to these vectors
1771 for (int j = 0; j < m_nLayers; j++)
1772 {
1779 m_VstrGDALIUFDriverCode.push_back("");
1780 m_VstrGDALIUFDriverDesc.push_back("");
1781 m_VstrGDALIUFProjection.push_back("");
1782 m_VstrGDALIUFDataType.push_back("");
1783 m_VstrGDALIUSDriverCode.push_back("");
1784 m_VstrGDALIUSDriverDesc.push_back("");
1785 m_VstrGDALIUSProjection.push_back("");
1786 m_VstrGDALIUSDataType.push_back("");
1787 m_VstrGDALIUCDriverCode.push_back("");
1788 m_VstrGDALIUCDriverDesc.push_back("");
1789 m_VstrGDALIUCProjection.push_back("");
1790 m_VstrGDALIUCDataType.push_back("");
1791 m_VstrGDALICFDriverCode.push_back("");
1792 m_VstrGDALICFDriverDesc.push_back("");
1793 m_VstrGDALICFProjection.push_back("");
1794 m_VstrGDALICFDataType.push_back("");
1795 m_VstrGDALICSDriverCode.push_back("");
1796 m_VstrGDALICSDriverDesc.push_back("");
1797 m_VstrGDALICSProjection.push_back("");
1798 m_VstrGDALICSDataType.push_back("");
1799 m_VstrGDALICCDriverCode.push_back("");
1800 m_VstrGDALICCDriverDesc.push_back("");
1801 m_VstrGDALICCProjection.push_back("");
1802 m_VstrGDALICCDataType.push_back("");
1803 }
1804
1805 break;
1806
1807 case 27:
1808 // Basement DEM file (can be blank)
1809 if (! strRH.empty())
1810 {
1811#ifdef _WIN32
1812 // For Windows, make sure has backslashes, not Unix-style slashes
1813 strRH = pstrChangeToBackslash(&strRH);
1814#endif
1815
1816 // Now check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
1817 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
1818 // It has an absolute path, so use it 'as is'
1820 else
1821 {
1822 // It has a relative path, so prepend the CoastalME dir
1824 m_strInitialBasementDEMFile.append(strRH);
1825 }
1826 }
1827
1828 break;
1829
1830 case 28:
1831 // Read 6 x sediment files for each layer
1832 for (int nLayer = 0; nLayer < m_nLayers; nLayer++)
1833 {
1834 for (int j = 1; j <= 6; j++)
1835 {
1836 if (! bFirst)
1837 {
1838 do
1839 {
1840 if (!getline(InStream, strRec))
1841 {
1842 cerr << ERR << "premature end of file in " << m_strDataPathName << endl;
1843 return false;
1844 }
1845
1846 nLine++;
1847
1848 // Trim off leading and trailing whitespace
1849 strRec = strTrim(&strRec);
1850 }
1851
1852 // If it is a blank line or a comment then ignore it
1853 while (strRec.empty() || (strRec[0] == QUOTE1) || (strRec[0] == QUOTE2));
1854
1855 // Not blank or a comment, so find the colon: lines MUST have a colon separating data from leading description portion
1856 nPos = strRec.find(COLON);
1857
1858 if (nPos == string::npos)
1859 {
1860 // Error: badly formatted (no colon)
1861 cerr << ERR << "on line " << to_string(nLine) << ": badly formatted (no ':') in " << m_strDataPathName << endl
1862 << strRec << endl;
1863 return false;
1864 }
1865
1866 // Strip off leading portion (the bit up to and including the colon)
1867 strRH = strRec.substr(nPos + 1);
1868 // ERROR strRH.resize(nPos);
1869
1870 // Remove leading whitespace after the colon
1871 strRH = strTrimLeft(&strRH);
1872
1873 // Look for a trailing comment, if found then terminate string at that point and trim off any trailing whitespace
1874 nPos = strRH.rfind(QUOTE1);
1875
1876 if (nPos != string::npos)
1877 strRH.resize(nPos);
1878
1879 nPos = strRH.rfind(QUOTE2);
1880
1881 if (nPos != string::npos)
1882 strRH.resize(nPos);
1883
1884 // Trim trailing spaces
1885 strRH = strTrimRight(&strRH);
1886
1887#ifdef _WIN32
1888 // For Windows, make sure has backslashes, not Unix-style slashes
1889 strRH = pstrChangeToBackslash(&strRH);
1890#endif
1891 }
1892
1893 bFirst = false;
1894
1895 switch (j)
1896 {
1897 case 1:
1898
1899 // Initial fine unconsolidated sediment depth GIS file (can be blank)
1900 if (! strRH.empty())
1901 {
1902 // Set switch
1903 m_bHaveFineSediment = true;
1904#ifdef _WIN32
1905 // For Windows, make sure has backslashes, not Unix-style slashes
1906 strRH = pstrChangeToBackslash(&strRH);
1907#endif
1908
1909 // Now check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
1910 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
1911 {
1912 // It has an absolute path, so use it 'as is'
1914 }
1915
1916 else
1917 {
1918 // It has a relative path, so prepend the CoastalME dir
1920 m_VstrInitialFineUnconsSedimentFile[nLayer].append(strRH);
1921 }
1922 }
1923
1924 break;
1925
1926 case 2:
1927 // Initial sand unconsolidated sediment depth GIS file (can be blank)
1928 if (! strRH.empty())
1929 {
1930 // Set switch
1931 m_bHaveSandSediment = true;
1932#ifdef _WIN32
1933 // For Windows, make sure has backslashes, not Unix-style slashes
1934 strRH = pstrChangeToBackslash(&strRH);
1935#endif
1936
1937 // Now check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
1938 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
1939 {
1940 // It has an absolute path, so use it 'as is'
1942 }
1943
1944 else
1945 {
1946 // It has a relative path, so prepend the CoastalME dir
1948 m_VstrInitialSandUnconsSedimentFile[nLayer].append(strRH);
1949 }
1950 }
1951
1952 break;
1953
1954 case 3:
1955 // Initial coarse unconsolidated sediment depth GIS file (can be blank)
1956 if (! strRH.empty())
1957 {
1958 // Set switch
1959 m_bHaveCoarseSediment = true;
1960#ifdef _WIN32
1961 // For Windows, make sure has backslashes, not Unix-style slashes
1962 strRH = pstrChangeToBackslash(&strRH);
1963#endif
1964
1965 // Now check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
1966 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
1967 {
1968 // It has an absolute path, so use it 'as is'
1970 }
1971
1972 else
1973 {
1974 // It has a relative path, so prepend the CoastalME dir
1976 m_VstrInitialCoarseUnconsSedimentFile[nLayer].append(strRH);
1977 }
1978 }
1979
1980 break;
1981
1982 case 4:
1983 // Initial fine consolidated sediment depth GIS file (can be blank)
1984 if (! strRH.empty())
1985 {
1986 // Set switches
1988 m_bHaveFineSediment = true;
1989#ifdef _WIN32
1990 // For Windows, make sure has backslashes, not Unix-style slashes
1991 strRH = pstrChangeToBackslash(&strRH);
1992#endif
1993
1994 // Now check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
1995 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
1996 {
1997 // It has an absolute path, so use it 'as is'
1998 m_VstrInitialFineConsSedimentFile[nLayer] = strRH;
1999 }
2000
2001 else
2002 {
2003 // It has a relative path, so prepend the CoastalME dir
2005 m_VstrInitialFineConsSedimentFile[nLayer].append(strRH);
2006 }
2007 }
2008
2009 break;
2010
2011 case 5:
2012 // Initial sand consolidated sediment depth GIS file (can be blank)
2013 if (! strRH.empty())
2014 {
2015 // Set switches
2017 m_bHaveSandSediment = true;
2018#ifdef _WIN32
2019 // For Windows, make sure has backslashes, not Unix-style slashes
2020 strRH = pstrChangeToBackslash(&strRH);
2021#endif
2022
2023 // Now check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
2024 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
2025 {
2026 // It has an absolute path, so use it 'as is'
2027 m_VstrInitialSandConsSedimentFile[nLayer] = strRH;
2028 }
2029 else
2030 {
2031 // It has a relative path, so prepend the CoastalME dir
2033 m_VstrInitialSandConsSedimentFile[nLayer].append(strRH);
2034 }
2035 }
2036
2037 break;
2038
2039 case 6:
2040 // Initial coarse consolidated sediment depth GIS file (can be blank)
2041 if (! strRH.empty())
2042 {
2043 // Set switches
2045 m_bHaveCoarseSediment = true;
2046#ifdef _WIN32
2047 // For Windows, make sure has backslashes, not Unix-style slashes
2048 strRH = pstrChangeToBackslash(&strRH);
2049#endif
2050
2051 // Now check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
2052 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
2053 {
2054 // It has an absolute path, so use it 'as is'
2056 }
2057
2058 else
2059 {
2060 // It has a relative path, so prepend the CoastalME dir
2062 m_VstrInitialCoarseConsSedimentFile[nLayer].append(strRH);
2063 }
2064 }
2065
2066 break;
2067 }
2068
2069 // Did an error occur?
2070 if (! strErr.empty())
2071 {
2072 // Error in input to run details file
2073 cerr << ERR << "reading " << strErr << " in " << m_strDataPathName << endl
2074 << "'" << strRec << "'" << endl;
2075 InStream.close();
2076 return false;
2077 }
2078 }
2079 }
2080
2081 break;
2082
2083 case 29:
2084 // Initial suspended sediment depth GIS file (can be blank)
2085 if (! strRH.empty())
2086 {
2087 // Set switch
2088 m_bHaveFineSediment = true;
2089#ifdef _WIN32
2090 // For Windows, make sure has backslashes, not Unix-style slashes
2091 strRH = pstrChangeToBackslash(&strRH);
2092#endif
2093
2094 // Now check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
2095 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
2096 {
2097 // It has an absolute path, so use it 'as is'
2099 }
2100
2101 else
2102 {
2103 // It has a relative path, so prepend the CoastalME dir
2105 m_strInitialSuspSedimentFile.append(strRH);
2106 }
2107 }
2108
2109 break;
2110
2111 case 30:
2112 // Initial Landform class GIS file (can be blank)
2113 if (! strRH.empty())
2114 {
2115#ifdef _WIN32
2116 // For Windows, make sure has backslashes, not Unix-style slashes
2117 strRH = pstrChangeToBackslash(&strRH);
2118#endif
2119
2120 // Now check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
2121 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
2122 {
2123 // It has an absolute path, so use it 'as is'
2125 }
2126
2127 else
2128 {
2129 // It has a relative path, so prepend the CoastalME dir
2131 m_strInitialLandformFile.append(strRH);
2132 }
2133 }
2134
2135 break;
2136
2137 case 31:
2138 // Initial Intervention class GIS file (can be blank: if so then intervention height file must also be blank)
2139 if (! strRH.empty())
2140 {
2141#ifdef _WIN32
2142 // For Windows, make sure has backslashes, not Unix-style slashes
2143 strRH = pstrChangeToBackslash(&strRH);
2144#endif
2145
2146 // Now check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
2147 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
2148 {
2149 // It has an absolute path, so use it 'as is'
2151 }
2152
2153 else
2154 {
2155 // It has a relative path, so prepend the CoastalME dir
2157 m_strInterventionClassFile.append(strRH);
2158 }
2159
2160 // Set the save switches
2163 }
2164
2165 break;
2166
2167 case 32:
2168 // Initial Intervention height GIS file (can be blank: if so then intervention class file must also be blank)
2169 if (strRH.empty())
2170 {
2171 if (! m_strInterventionClassFile.empty())
2172 strErr = "line " + to_string(nLine) + ": must specify both intervention class and intervention height files";
2173
2174 break;
2175 }
2176
2177 else
2178 {
2179 if (m_strInterventionClassFile.empty())
2180 {
2181 strErr = "line " + to_string(nLine) + ": must specify both intervention class and intervention height files";
2182 break;
2183 }
2184
2185#ifdef _WIN32
2186 // For Windows, make sure has backslashes, not Unix-style slashes
2187 strRH = pstrChangeToBackslash(&strRH);
2188#endif
2189
2190 // Now check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
2191 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
2192 {
2193 // It has an absolute path, so use it 'as is'
2195 }
2196
2197 else
2198 {
2199 // It has a relative path, so prepend the CoastalME dir
2201 m_strInterventionHeightFile.append(strRH);
2202 }
2203 }
2204
2205 break;
2206
2207 // ---------------------------------------------------- Hydrology data ------------------------------------------------
2208 case 33:
2209 // Wave propagation model [0 = COVE, 1 = CShore]
2210 if (! bIsStringValidInt(strRH))
2211 {
2212 strErr = "line " + to_string(nLine) + ": invalid integer for wave propagation model '" + strRH + "' in " + m_strDataPathName;
2213 break;
2214 }
2215
2216 m_nWavePropagationModel = stoi(strRH);
2217
2219 strErr = "line " + to_string(nLine) + ": wave propagation model must be " + to_string( WAVE_MODEL_COVE) + " or" + to_string( WAVE_MODEL_CSHORE);
2220
2221 break;
2222
2223 case 34:
2224 // Density of sea water (kg/m3), first check that this is a valid double
2225 if (! bIsStringValidDouble(strRH))
2226 {
2227 strErr = "line " + to_string(nLine) + ": invalid floating point number for sea water density '" + strRH + "' in " + m_strDataPathName;
2228 break;
2229 }
2230
2231 m_dSeaWaterDensity = strtod(strRH.c_str(), NULL);
2232
2233 if (m_dSeaWaterDensity <= 0)
2234 strErr = "line " + to_string(nLine) + ": sea water density must be > 0";
2235
2236 break;
2237
2238 case 35:
2239 // Initial mean still water level (m), first check that this is a valid double TODO 041 Make this a per-timestep SWL file
2240 if (! bIsStringValidDouble(strRH))
2241 {
2242 strErr = "line " + to_string(nLine) + ": invalid floating point number for initial SWL '" + strRH + "' in " + m_strDataPathName;
2243 break;
2244 }
2245
2246 m_dInitialMeanSWL = strtod(strRH.c_str(), NULL);
2247 break;
2248
2249 case 36:
2250 // Final mean still water level (m) [blank = same as initial MSWL]
2251 if (strRH.empty())
2253
2254 else
2255 {
2256 // Check that this is a valid double
2257 if (! bIsStringValidDouble(strRH))
2258 {
2259 strErr = "line " + to_string(nLine) + ": invalid floating point number for final SWL '" + strRH + "' in " + m_strDataPathName;
2260 break;
2261 }
2262
2263 m_dFinalMeanSWL = strtod(strRH.c_str(), NULL);
2264 }
2265
2266 break;
2267
2268 case 37:
2269 // Deep water wave height (m) or a file of point vectors giving deep water wave height (m) and orientation (for units, see below)
2270 if (strRH.empty())
2271 strErr = "line " + to_string(nLine) + ": deep water wave height in " + m_strDataPathName + " must be either a number or a filename (filename must not start with a number)";
2272
2273 else
2274 {
2275 if (isdigit(strRH.at(0))) // If this starts with a number then is a single value, otherwise is a filename. Note that filename must not start with number
2276 {
2277 // Just one value of wave height for all deep water cells, first check that this is a valid double
2278 if (! bIsStringValidDouble(strRH))
2279 {
2280 strErr = "line " + to_string(nLine) + ": invalid floating point number for deep water wave height '" + strRH + "' in " + m_strDataPathName;
2281 break;
2282 }
2283
2285 m_bHaveWaveStationData = false;
2286
2287 m_dAllCellsDeepWaterWaveHeight = strtod(strRH.c_str(), NULL);
2288
2290 strErr = "line " + to_string(nLine) + ": deep water wave height must be > 0";
2291 }
2292
2293 else
2294 {
2295 // We are reading deep water wave height and deep water wave orientation from two files. This first file is a point shape file with the location of the buoys and integer ID for each one
2297#ifdef _WIN32
2298 // For Windows, make sure has backslashes, not Unix-style slashes
2299 strRH = pstrChangeToBackslash(&strRH);
2300#endif
2301
2302 // Now check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
2303 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
2304 {
2305 // It has an absolute path, so use it 'as is'
2307 }
2308
2309 else
2310 {
2311 // It has a relative path, so prepend the CoastalME dir
2314 }
2315 }
2316 }
2317
2318 break;
2319
2320 case 38:
2321 // Deep water wave height input file. Each point in m_strDeepWaterWavesInputFile is a triad of wave height, orientation and period for each time step
2323 {
2324 if (strRH.empty())
2325 {
2326 strErr = "line " + to_string(nLine) + ": filename missing for deep water wave height input";
2327 break;
2328 }
2329
2330#ifdef _WIN32
2331 // For Windows, make sure has backslashes, not Unix-style slashes
2332 strRH = pstrChangeToBackslash(&strRH);
2333#endif
2334
2335 // Now check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
2336 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
2337 {
2338 // It has an absolute path, so use it 'as is'
2340 }
2341
2342 else
2343 {
2344 // It has a relative path, so prepend the CoastalME dir
2346 m_strDeepWaterWavesInputFile.append(strRH);
2347 }
2348 }
2349
2350 break;
2351
2352 case 39:
2353 // Deep water wave orientation in input CRS: this is the oceanographic convention i.e. direction TOWARDS which the waves move (in degrees clockwise from north)
2355 {
2356 // Only read this if we have just a single value of wave height for all deep water cells. Check that this is a valid double
2357 if (! bIsStringValidDouble(strRH))
2358 {
2359 strErr = "line " + to_string(nLine) + ": invalid floating point number for deep water wave orientation '" + strRH + "' in " + m_strDataPathName;
2360 break;
2361 }
2362
2363 m_dAllCellsDeepWaterWaveAngle = strtod(strRH.c_str(), NULL);
2364
2366 strErr = "line " + to_string(nLine) + ": deep water wave orientation must be zero degrees or more";
2367
2368 else if (m_dAllCellsDeepWaterWaveAngle >= 360)
2369 strErr = "line " + to_string(nLine) + ": deep water wave orientation must be less than 360 degrees";
2370 }
2371
2372 break;
2373
2374 case 40:
2375 // Wave period (sec)
2377 {
2378 // Only read this if we also have just a single value of wave height for all deep water cells. Check that this is a valid double
2379 if (! bIsStringValidDouble(strRH))
2380 {
2381 strErr = "line " + to_string(nLine) + ": invalid floating point number for wave period '" + strRH + "' in " + m_strDataPathName;
2382 break;
2383 }
2384
2385 m_dAllCellsDeepWaterWavePeriod = strtod(strRH.c_str(), NULL);
2386
2388 strErr = "line " + to_string(nLine) + ": wave period must be > 0";
2389 }
2390
2391 break;
2392
2393 case 41:
2394 // Tide data file (can be blank). This is the change (m) from still water level for each timestep
2395 if (! strRH.empty())
2396 {
2397#ifdef _WIN32
2398 // For Windows, make sure has backslashes, not Unix-style slashes
2399 strRH = pstrChangeToBackslash(&strRH);
2400#endif
2401
2402 // Now check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
2403 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
2404 // It has an absolute path, so use it 'as is'
2405 m_strTideDataFile = strRH;
2406
2407 else
2408 {
2409 // It has a relative path, so prepend the CoastalME dir
2411 m_strTideDataFile.append(strRH);
2412 }
2413 }
2414
2415 break;
2416
2417 case 42:
2418 // Breaking wave height-to-depth ratio, check that this is a valid double
2419 if (! bIsStringValidDouble(strRH))
2420 {
2421 strErr = "line " + to_string(nLine) + ": invalid floating point number for breaking wave height to depth ratio '" + strRH + "' in " + m_strDataPathName;
2422 break;
2423 }
2424
2425 m_dBreakingWaveHeightDepthRatio = strtod(strRH.c_str(), NULL);
2426
2428 strErr = "line " + to_string(nLine) + ": breaking wave height to depth ratio must be > 0";
2429
2430 break;
2431
2432 // ----------------------------------------------------- Sediment data ------------------------------------------------
2433 case 43:
2434 // Simulate coast platform erosion?
2435 strRH = strToLower(&strRH);
2436
2437 if (strRH.find('y') != string::npos)
2439
2440 break;
2441
2442 case 44:
2443 // If simulating coast platform erosion, R (coast platform resistance to erosion) values along profile, see Walkden & Hall, 2011
2445 {
2446 // First check that this is a valid double
2447 if (! bIsStringValidDouble(strRH))
2448 {
2449 strErr = "line " + to_string(nLine) + ": invalid floating point number for R (coast platform resistance to erosion) '" + strRH + "' in " + m_strDataPathName;
2450 break;
2451 }
2452
2453 m_dR = strtod(strRH.c_str(), NULL);
2454
2455 if (m_dR <= 0)
2456 strErr = "line " + to_string(nLine) + ": R (coast platform resistance to erosion) value must be > 0";
2457 }
2458
2459 break;
2460
2461 case 45:
2462 // Simulate beach sediment transport?
2463 strRH = strToLower(&strRH);
2464
2466
2467 if (strRH.find('y') != string::npos)
2469
2470 break;
2471
2472 case 46:
2473 // If simulating beach sediment transport, beach sediment transport at grid edges [0 = closed, 1 = open, 2 = re-circulate]
2475 {
2476 if (! bIsStringValidInt(strRH))
2477 {
2478 strErr = "line " + to_string(nLine) + ": invalid integer for beach sediment transport at grid edges '" + strRH + "' in " + m_strDataPathName;
2479 break;
2480 }
2481
2483
2485 strErr = "line " + to_string(nLine) + ": switch for handling of beach sediment at grid edges must be " + to_string(GRID_EDGE_CLOSED) + ", " + to_string(GRID_EDGE_OPEN) + ", or " + to_string(GRID_EDGE_RECIRCULATE);
2486 }
2487
2488 break;
2489
2490 case 47:
2491 // If simulating beach sediment transport, beach erosion/deposition equation [0 = CERC, 1 = Kamphuis]
2493 {
2494 if (! bIsStringValidInt(strRH))
2495 {
2496 strErr = "line " + to_string(nLine) + ": invalid integer for beach erosion/deposition equation '" + strRH + "' in " + m_strDataPathName;
2497 break;
2498 }
2499
2501
2503 strErr = "line " + to_string(nLine) + ": switch for beach erosion/deposition equation must be " + to_string(UNCONS_SEDIMENT_EQUATION_CERC) + " or" + to_string(UNCONS_SEDIMENT_EQUATION_KAMPHUIS);
2504 }
2505
2506 break;
2507
2508 case 48:
2509 // Median size of fine sediment (mm), always needed [0 = default, only for Kamphuis eqn]. First check that this is a valid double
2510 if (! bIsStringValidDouble(strRH))
2511 {
2512 strErr = "line " + to_string(nLine) + ": invalid floating point number for median particle size of fine sediment '" + strRH + "' in " + m_strDataPathName;
2513 break;
2514 }
2515
2516 m_dD50Fine = strtod(strRH.c_str(), NULL);
2517
2518 if (m_dD50Fine < 0)
2519 strErr = "line " + to_string(nLine) + ": median particle size of fine sediment must be > 0";
2520 else if (bFPIsEqual(m_dD50Fine, 0.0, TOLERANCE))
2521 // Use default value
2523
2524 break;
2525
2526 case 49:
2527 // Median size of sand sediment (mm), always needed [0 = default, only for Kamphuis eqn]. First check that this is a valid double
2528 if (! bIsStringValidDouble(strRH))
2529 {
2530 strErr = "line " + to_string(nLine) + ": invalid floating point number for median particle size of sand sediment '" + strRH + "' in " + m_strDataPathName;
2531 break;
2532 }
2533
2534 m_dD50Sand = strtod(strRH.c_str(), NULL);
2535
2536 if (m_dD50Sand < 0)
2537 strErr = "line " + to_string(nLine) + ": median particle size of sand sediment must be > 0";
2538 else if (bFPIsEqual(m_dD50Sand, 0.0, TOLERANCE))
2539 // Use default value
2541
2542 break;
2543
2544 case 50:
2545 // Median size of coarse sediment (mm), always needed [0 = default, only for Kamphuis eqn]. First check that this is a valid double
2546 if (! bIsStringValidDouble(strRH))
2547 {
2548 strErr = "line " + to_string(nLine) + ": invalid floating point number for median particle size of coarse sediment '" + strRH + "' in " + m_strDataPathName;
2549 break;
2550 }
2551
2552 m_dD50Coarse = strtod(strRH.c_str(), NULL);
2553
2554 if (m_dD50Coarse < 0)
2555 strErr = "line " + to_string(nLine) + ": median particle size of coarse sediment must be > 0";
2556 else if (bFPIsEqual(m_dD50Coarse, 0.0, TOLERANCE))
2557 // Use default value
2559
2560 break;
2561
2562 case 51:
2563 // Density of unconsolidated beach sediment (kg/m3)
2565 {
2566 // First check that this is a valid double
2567 if (! bIsStringValidDouble(strRH))
2568 {
2569 strErr = "line " + to_string(nLine) + ": invalid floating point number for density of beach sediment '" + strRH + "' in " + m_strDataPathName;
2570 break;
2571 }
2572
2573 m_dBeachSedimentDensity = strtod(strRH.c_str(), NULL);
2574
2575 if (m_dBeachSedimentDensity <= 0)
2576 strErr = "line " + to_string(nLine) + ": density of beach sediment must be > 0";
2577 }
2578
2579 break;
2580
2581 case 52:
2582 // Beach sediment porosity
2584 {
2585 // First check that this is a valid double
2586 if (! bIsStringValidDouble(strRH))
2587 {
2588 strErr = "line " + to_string(nLine) + ": invalid floating point number for porosity of beach sediment '" + strRH + "' in " + m_strDataPathName;
2589 break;
2590 }
2591
2592 m_dBeachSedimentPorosity = strtod(strRH.c_str(), NULL);
2593
2594 if (m_dBeachSedimentPorosity <= 0)
2595 strErr = "line " + to_string(nLine) + ": porosity of beach sediment must be > 0";
2596 }
2597
2598 break;
2599
2600 case 53:
2601 // Relative erodibility (0 - 1) of fine-sized sediment, always needed. First check that this is a valid double
2602 if (! bIsStringValidDouble(strRH))
2603 {
2604 strErr = "line " + to_string(nLine) + ": invalid floating point number for erodibility of fine-sized sediment '" + strRH + "' in " + m_strDataPathName;
2605 break;
2606 }
2607
2608 m_dFineErodibility = strtod(strRH.c_str(), NULL);
2609
2610 if ((m_dFineErodibility < 0) || (m_dFineErodibility > 1))
2611 strErr = "line " + to_string(nLine) + ": relative erodibility of fine-sized sediment must be between 0 and 1";
2612
2613 break;
2614
2615 case 54:
2616 // Relative erodibility (0 - 1) of sand-sized sediment, always needed. First check that this is a valid double
2617 if (! bIsStringValidDouble(strRH))
2618 {
2619 strErr = "line " + to_string(nLine) + ": invalid floating point number for erodibility of sand-sized sediment '" + strRH + "' in " + m_strDataPathName;
2620 break;
2621 }
2622
2623 m_dSandErodibility = strtod(strRH.c_str(), NULL);
2624
2625 if ((m_dSandErodibility < 0) || (m_dSandErodibility > 1))
2626 strErr = "line " + to_string(nLine) + ": relative erodibility of sand-sized sediment must be between 0 and 1";
2627
2628 break;
2629
2630 case 55:
2631 // Relative erodibility (0 - 1) of coarse-sized sediment, always needed. First check that this is a valid double
2632 if (! bIsStringValidDouble(strRH))
2633 {
2634 strErr = "line " + to_string(nLine) + ": invalid floating point number for erodibility of coarse-sized sediment '" + strRH + "' in " + m_strDataPathName;
2635 break;
2636 }
2637
2638 m_dCoarseErodibility = strtod(strRH.c_str(), NULL);
2639
2640 if ((m_dCoarseErodibility < 0) || (m_dCoarseErodibility > 1))
2641 {
2642 strErr = "line " + to_string(nLine) + ": relative erodibility of coarse-sized sediment must be between 0 and 1";
2643 break;
2644 }
2645
2647 strErr = "line " + to_string(nLine) + ": must have at least one non-zero erodibility value";
2648
2649 break;
2650
2651 case 56:
2652 // Transport parameter KLS in CERC equation
2654 {
2655 // First check that this is a valid double
2656 if (! bIsStringValidDouble(strRH))
2657 {
2658 strErr = "line " + to_string(nLine) + ": invalid floating point number for transport parameter KLS of CERC equation '" + strRH + "' in " + m_strDataPathName;
2659 break;
2660 }
2661
2662 m_dKLS = strtod(strRH.c_str(), NULL);
2663
2664 // However, many sites do not have transport data available to calibrate K, and for design applications without calibration data the CERC formula provides only order-of-magnitude accuracy (Fowler et al., 1995; Wang et al., 1998). The recommended value of K = 0.39 has been commonly used to represent the potential longshore transport rate. However, Miller (1998) found that the CERC formula sometimes over and sometimes under predicted longshore transport rate for measurements during storms, indicating the value of K also can be higher than 0.39
2665 // TODO 042 Should this be a user input, or not? The comment above seems inconclusive
2666 // m_dKLS = tMin(m_dKLS, 0.39);
2667
2668 if (m_dKLS <= 0)
2669 strErr = "line " + to_string(nLine) + ": transport parameter KLS of CERC equation must be > 0";
2670 }
2671
2672 break;
2673
2674 case 57:
2675 // Transport parameter for Kamphuis equation
2677 {
2678 // First check that this is a valid double
2679 if (! bIsStringValidDouble(strRH))
2680 {
2681 strErr = "line " + to_string(nLine) + ": invalid floating point number for transport parameter of Kamphuis equation '" + strRH + "' in " + m_strDataPathName;
2682 break;
2683 }
2684
2685 m_dKamphuis = strtod(strRH.c_str(), NULL);
2686
2687 if (m_dKamphuis <= 0)
2688 strErr = "line " + to_string(nLine) + ": transport parameter of Kamphuis equation must be > 0";
2689 }
2690
2691 break;
2692
2693 case 58:
2694 // Berm height i.e. height above SWL of start of depositional Dean profile
2696 {
2697 // First check that this is a valid double
2698 if (! bIsStringValidDouble(strRH))
2699 {
2700 strErr = "line " + to_string(nLine) + ": invalid floating point number for Dean profile start height above SWL '" + strRH + "' in " + m_strDataPathName;
2701 break;
2702 }
2703
2704 m_dDeanProfileStartAboveSWL = strtod(strRH.c_str(), NULL);
2705
2707 strErr = "line " + to_string(nLine) + ": Berm height (Dean profile start height above SWL) must be >= 0";
2708 }
2709
2710 break;
2711
2712 // ------------------------------------------------ Cliff collapse data -----------------------------------------------
2713 case 59:
2714 // Simulate cliff collapse?
2716 {
2717 // Only consider cliff collapse if we have some consolidated sedimemt
2718 strRH = strToLower(&strRH);
2719
2720 if (strRH.find('y') != string::npos)
2721 m_bDoCliffCollapse = true;
2722 }
2723
2724 break;
2725
2726 case 60:
2727 // Cliff resistance to erosion
2729 {
2730 // First check that this is a valid double
2731 if (! bIsStringValidDouble(strRH))
2732 {
2733 strErr = "line " + to_string(nLine) + ": invalid floating point number for cliff resistance to erosion '" + strRH + "' in " + m_strDataPathName;
2734 break;
2735 }
2736
2737 m_dCliffErosionResistance = strtod(strRH.c_str(), NULL);
2738
2740 strErr = "line " + to_string(nLine) + ": cliff resistance to erosion must be > 0";
2741 }
2742
2743 break;
2744
2745 case 61:
2746 // Notch overhang at collapse (m)
2748 {
2749 // First check that this is a valid double
2750 if (! bIsStringValidDouble(strRH))
2751 {
2752 strErr = "line " + to_string(nLine) + ": invalid floating point number for cliff notch overhang at collapse '" + strRH + "' in " + m_strDataPathName;
2753 break;
2754 }
2755
2756 m_dNotchIncisionAtCollapse = strtod(strRH.c_str(), NULL);
2757
2759 strErr = "line " + to_string(nLine) + ": cliff notch overhang at collapse must be > 0";
2760 }
2761
2762 break;
2763
2764 case 62:
2765 // Notch apex above mean high water (MHW) level (m)
2767 {
2768 m_dNotchApexAboveMHW = strtod(strRH.c_str(), NULL);
2769
2770 if (m_dNotchApexAboveMHW < 0)
2771 strErr = "line " + to_string(nLine) + ": distance of cliff notch apex above MHW level must be >= 0";
2772 }
2773
2774 break;
2775
2776 case 63:
2777 // Scale parameter A for cliff deposition (m^(1/3)) [0 = auto]
2779 {
2780 // First check that this is a valid double
2781 if (! bIsStringValidDouble(strRH))
2782 {
2783 strErr = "line " + to_string(nLine) + ": invalid floating point number for scale parameter A for cliff deposition '" + strRH + "' in " + m_strDataPathName;
2784 break;
2785 }
2786
2787 m_dCliffDepositionA = strtod(strRH.c_str(), NULL);
2788
2789 if (m_dCliffDepositionA < 0)
2790 strErr = "line " + to_string(nLine) + ": scale parameter A for cliff deposition must be 0 [= auto] or greater";
2791 }
2792
2793 break;
2794
2795 case 64:
2796 // Approximate planview width of cliff collapse talus (in m)
2798 {
2799 // First check that this is a valid double
2800 if (! bIsStringValidDouble(strRH))
2801 {
2802 strErr = "line " + to_string(nLine) + ": invalid floating point number for width of cliff collapse talus '" + strRH + "' in " + m_strDataPathName;
2803 break;
2804 }
2805
2806 m_dCliffDepositionPlanviewWidth = strtod(strRH.c_str(), NULL);
2807
2809 strErr = "line " + to_string(nLine) + ": planview width of cliff deposition must be > 0";
2810 }
2811
2812 break;
2813
2814 case 65:
2815 // Planview length of cliff deposition talus (m)
2817 {
2818 // First check that this is a valid double
2819 if (! bIsStringValidDouble(strRH))
2820 {
2821 strErr = "line " + to_string(nLine) + ": invalid floating point number for planview length of cliff deposition '" + strRH + "' in " + m_strDataPathName;
2822 break;
2823 }
2824
2825 m_dCliffTalusMinDepositionLength = strtod(strRH.c_str(), NULL);
2826
2828 strErr = "line " + to_string(nLine) + ": planview length of cliff deposition must be > 0";
2829 }
2830
2831 break;
2832
2833 case 66:
2834 // Minimum height of landward end of talus, as a fraction of cliff elevation
2836 {
2837 // First check that this is a valid double
2838 if (! bIsStringValidDouble(strRH))
2839 {
2840 strErr = "line " + to_string(nLine) + ": invalid floating point number for height of cliff collapse (as a fraction of cliff elevation) '" + strRH + "' in " + m_strDataPathName;
2841 break;
2842 }
2843
2844 m_dMinCliffTalusHeightFrac = strtod(strRH.c_str(), NULL);
2845
2847 strErr = "line " + to_string(nLine) + ": minimum height of cliff collapse (as a fraction of cliff elevation) must be >= 0";
2848 }
2849
2850 break;
2851
2852 // -------------------------------------------------- Input events data -----------------------------------------------
2853 case 67:
2854 // Simulate riverine flooding?
2855 strRH = strToLower(&strRH);
2856
2857 if (strRH.find('y') != string::npos)
2858 {
2859 m_bRiverineFlooding = true;
2863 }
2864
2865 break;
2866
2867 case 68:
2868 // Output riverine flooding vector files
2870 {
2871 if (! strRH.empty())
2872 {
2873 // Convert to lower case
2874 strRH = strToLower(&strRH);
2875
2876 // First look for "all"
2877 if (strRH.find(VECTOR_ALL_RIVER_FLOOD_OUTPUT_CODE) != string::npos)
2878 {
2882 }
2883
2884 else
2885 {
2886 // We are not outputting all vector flood GIS files, so set switches (and remove strings) for those optional files for which the user specified the code
2887 if (strRH.find(VECTOR_FLOOD_SWL_SETUP_LINE_CODE) != string::npos)
2888 {
2891 }
2892
2893 if (strRH.find(VECTOR_FLOOD_SWL_SETUP_SURGE_LINE_CODE) != string::npos)
2894 {
2897 }
2898
2899 if (strRH.find(VECTOR_FLOOD_SWL_SETUP_SURGE_RUNUP_LINE_CODE) != string::npos)
2900 {
2903 }
2904
2905 // Check to see if all codes have been removed
2906 if (! strRH.empty())
2907 strErr = "line " + to_string(nLine) + ": unknown code '" + strRH + "' in list of riverine flooding output codes";
2908 }
2909 }
2910 else
2911 strErr = "line " + to_string(nLine) + ": if simulating riverine flooding, must contain '" + VECTOR_ALL_RIVER_FLOOD_OUTPUT_CODE + "' or at least one vector GIS output code for riverine flooding";
2912 }
2913
2914 break;
2915
2916 case 69:
2918 {
2919 // Characteristic locations for flood?
2920 strRH = strToLower(&strRH);
2921
2922 m_bFloodLocationSave = false;
2923
2924 if (strRH.find('y') != string::npos)
2925 m_bFloodLocationSave = true;
2926 }
2927
2928 break;
2929
2930 case 70:
2932 {
2933 // Path of location points file
2934 if (! strRH.empty())
2935 {
2936#ifdef _WIN32
2937 // For Windows, make sure has backslashes, not Unix-style slashes
2938 strRH = pstrChangeToBackslash(&strRH);
2939#endif
2940
2941 // Now check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
2942 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
2943 // It has an absolute path, so use it 'as is'
2945
2946 else
2947 {
2948 // It has a relative path, so prepend the CoastalME dir
2950 m_strFloodLocationShapefile.append(strRH);
2951 }
2952
2953 // Set the switch
2954 m_bFloodLocationSave = true;
2955 }
2956
2957 else
2958 strErr = "line " + to_string(nLine) + ": path of location points file must not be empty if simulating floods";
2959 }
2960
2961 break;
2962
2963 case 71:
2964 // Simulate sediment input?
2965 strRH = strToLower(&strRH);
2966
2967 if (strRH.find('y') != string::npos)
2968 {
2969 m_bSedimentInput = true;
2971 }
2972
2973 break;
2974
2975 case 72:
2976 // Sediment input location (point or line shapefile)
2977 if (m_bSedimentInput)
2978 {
2979 if (! strRH.empty())
2980 {
2981#ifdef _WIN32
2982 // For Windows, make sure has backslashes, not Unix-style slashes
2983 strRH = pstrChangeToBackslash(&strRH);
2984#endif
2985
2986 // Now check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
2987 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
2988 // It has an absolute path, so use it 'as is'
2990
2991 else
2992 {
2993 // It has a relative path, so prepend the CoastalME dir
2996 }
2997 }
2998 }
2999
3000 break;
3001
3002 case 73:
3003 // Sediment input type: required if have shapefile [P = Point, C = coast block, L = line]
3004 if (m_bSedimentInput)
3005 {
3006 strRH = strToLower(&strRH);
3007
3008 if (strRH.find('p') != string::npos)
3010
3011 else if (strRH.find('c') != string::npos)
3013
3014 else if (strRH.find('l') != string::npos)
3016
3017 else
3018 strErr = "line " + to_string(nLine) + ": Sediment input type must be P, C, or L";
3019 }
3020
3021 break;
3022
3023 case 74:
3024 // Sediment input details file (required if have shapefile)
3025 if (m_bSedimentInput)
3026 {
3027 if (strRH.empty())
3028 {
3029 strErr = "line " + to_string(nLine) + ": filename missing for sediment input";
3030 break;
3031 }
3032
3033#ifdef _WIN32
3034 // For Windows, make sure has backslashes, not Unix-style slashes
3035 strRH = pstrChangeToBackslash(&strRH);
3036#endif
3037
3038 // Now check for leading slash, or leading Unix home dir symbol, or occurrence of a drive letter
3039 if ((strRH[0] == PATH_SEPARATOR) || (strRH[0] == TILDE) || (strRH[1] == COLON))
3040 {
3041 // It has an absolute path, so use it 'as is'
3043 }
3044
3045 else
3046 {
3047 // It has a relative path, so prepend the CoastalME dir
3049 m_strSedimentInputEventFile.append(strRH);
3050 }
3051 }
3052
3053 break;
3054
3055 // ------------------------------------------------------ Other data --------------------------------------------------
3056 case 75:
3057 // Gravitational acceleration (m2/s). First check that this is a valid double
3058 if (! bIsStringValidDouble(strRH))
3059 {
3060 strErr = "line " + to_string(nLine) + ": invalid floating point number for gravitational acceleration '" + strRH + "' in " + m_strDataPathName;
3061 break;
3062 }
3063
3064 m_dG = strtod(strRH.c_str(), NULL);
3065
3066 if (m_dG <= 0)
3067 strErr = "line " + to_string(nLine) + ": gravitational acceleration must be > 0";
3068
3069 break;
3070
3071 case 76:
3072 // Spacing of coastline normals (m)
3073 m_dCoastNormalSpacing = strtod(strRH.c_str(), NULL);
3074
3076 m_nCoastNormalSpacing = DEFAULT_PROFILE_SPACING; // In cells, we will set m_dCoastNormalSpacing later when we know m_dCellSide
3077
3078 else if (m_dCoastNormalSpacing < 0)
3079 strErr = "line " + to_string(nLine) + ": spacing of coastline normals must be > 0";
3080
3081 break;
3082
3083 case 77:
3084 // Random factor for spacing of normals [0 to 1, 0 = deterministic], check that this is a valid double
3085 if (! bIsStringValidDouble(strRH))
3086 {
3087 strErr = "line " + to_string(nLine) + ": invalid floating point number for random factor for spacing of coastline normals '" + strRH + "' in " + m_strDataPathName;
3088 break;
3089 }
3090
3091 m_dCoastNormalRandSpacingFactor = strtod(strRH.c_str(), NULL);
3092
3094 strErr = "line " + to_string(nLine) + ": random factor for spacing of coastline normals must be >= 0";
3096 strErr = "line " + to_string(nLine) + ": random factor for spacing of coastline normals must be < 1";
3097
3098 break;
3099
3100 case 78:
3101 // Length of coastline normals (m), check that this is a valid double
3102 if (! bIsStringValidDouble(strRH))
3103 {
3104 strErr = "line " + to_string(nLine) + ": invalid floating point number for length of coastline normals '" + strRH + "' in " + m_strDataPathName;
3105 break;
3106 }
3107
3108 m_dCoastNormalLength = strtod(strRH.c_str(), NULL);
3109
3110 if (m_dCoastNormalLength <= 0)
3111 strErr = "line " + to_string(nLine) + ": length of coastline normals must be > 0";
3112
3113 break;
3114
3115 case 79:
3116 // Start depth for wave calcs (ratio to deep water wave height), check that this is a valid double
3117 if (! bIsStringValidDouble(strRH))
3118 {
3119 strErr = "line " + to_string(nLine) + ": invalid floating point number for start depth for wave calcs '" + strRH + "' in " + m_strDataPathName;
3120 break;
3121 }
3122
3123 m_dWaveDepthRatioForWaveCalcs = strtod(strRH.c_str(), NULL);
3124
3126 strErr = "line " + to_string(nLine) + ": start depth for wave calcs must be > 0";
3127
3128 break;
3129
3130 // ----------------------------------------------------- Testing only -------------------------------------------------
3131 case 80:
3132 // Output profile data?
3133 strRH = strToLower(&strRH);
3134
3136
3137 if (strRH.find('y') != string::npos)
3138 {
3140
3142 {
3143 strErr = "line " + to_string(nLine) + ": cannot save profiile data if not simulating shore platform erosion";
3144 break;
3145 }
3146
3147 // TODO 043 What about randomness of profile spacing, since profile location is determined by curvature?
3148 }
3149
3150 break;
3151
3152 case 81:
3153 // Numbers of profiles to be saved
3155 {
3156 VstrTmp = VstrSplit(&strRH, SPACE);
3157
3158 for (unsigned int j = 0; j < VstrTmp.size(); j++)
3159 {
3160 VstrTmp[j] = strTrim(&VstrTmp[j]);
3161
3162 if (! bIsStringValidInt(VstrTmp[j]))
3163 {
3164 strErr = "line " + to_string(nLine) + ": invalid integer for profile to be saved '" + VstrTmp[j] + "' in " + m_strDataPathName;
3165 break;
3166 }
3167
3168 int const nTmp = stoi(VstrTmp[j]);
3169
3170 if (nTmp < 0)
3171 {
3172 strErr = "line " + to_string(nLine) + ": Profile number for saving must be >= 0";
3173 break;
3174 }
3175
3176 m_VnProfileToSave.push_back(nTmp);
3177 }
3178 }
3179
3180 break;
3181
3182 case 82:
3183 // Timesteps to save profiles
3185 {
3186 VstrTmp = VstrSplit(&strRH, SPACE);
3187
3188 for (unsigned int j = 0; j < VstrTmp.size(); j++)
3189 {
3190 VstrTmp[j] = strTrim(&VstrTmp[j]);
3191 unsigned long const ulTmp = atol(VstrTmp[j].c_str());
3192
3193 if (ulTmp < 1)
3194 {
3195 strErr = "line " + to_string(nLine) + ": Timestep for profile saves must >= 1";
3196 break;
3197 }
3198
3199 m_VulProfileTimestep.push_back(ulTmp);
3200 }
3201 }
3202
3203 break;
3204
3205 case 83:
3206 // Output parallel profile data?
3207 strRH = strToLower(&strRH);
3208
3210
3211 if (strRH.find('y') != string::npos)
3213
3214 break;
3215
3216 case 84:
3217 // Output erosion potential look-up data?
3218 strRH = strToLower(&strRH);
3219
3221
3222 if (strRH.find('y') != string::npos)
3224
3225 break;
3226
3227 case 85:
3228 // Cliff toe location? approach [0 = none, 1 = by slope threshold]
3230 {
3231 strRH = strToLower(&strRH);
3232
3233 m_bCliffToeLocate = false;
3234
3235 if (strRH.find('y') != string::npos)
3236 {
3237 m_bCliffToeLocate = true;
3238 m_bCliffToeSave = true;
3240 }
3241 }
3242
3243 break;
3244
3245 case 86:
3246 // Cliff edge smoothing algorithm: 0 = none, 1 = running mean, 2 = Savitzky-Golay
3248 {
3249 if (! bIsStringValidInt(strRH))
3250 {
3251 strErr = "line ";
3252 strErr += to_string(nLine);
3253 strErr += ": invalid integer for cliff edge smoothing algorithm '";
3254 strErr += strRH;
3255 strErr += "' in " + m_strDataPathName;
3256
3257 break;
3258 }
3259
3260 m_nCliffEdgeSmooth = stoi(strRH);
3261
3263 strErr = "line " + to_string(nLine) + ": cliff edge smoothing algorithm must be " + to_string(SMOOTH_NONE) + ", " + to_string(SMOOTH_RUNNING_MEAN) + ", or " + to_string(SMOOTH_SAVITZKY_GOLAY);
3264 }
3265
3266 break;
3267
3268 case 87:
3269 // Size of cliff edge smoothing window: must be odd
3271 {
3272 if (! bIsStringValidInt(strRH))
3273 {
3274 strErr = "line " + to_string(nLine) + ": invalid integer for cliff edge smoothing window '" + strRH + "' in " + m_strDataPathName;
3275 break;
3276 }
3277
3278 m_nCliffEdgeSmoothWindow = stoi(strRH);
3279
3281 strErr = "line " + to_string(nLine) + ": size of cliff edge smoothing window (must be > 0 and odd)";
3282 }
3283
3284 break;
3285
3286 case 88:
3287 // Order of cliff edge smoothing polynomial for Savitzky-Golay: usually 2 or 4, max is 6
3289 {
3290 if (! bIsStringValidInt(strRH))
3291 {
3292 strErr = "line " + to_string(nLine) + ": invalid integer for Savitzky-Golay polynomial for cliff edge smoothing '" + strRH + "' in " + m_strDataPathName;
3293 break;
3294 }
3295
3296 m_nSavGolCliffEdgePoly = stoi(strRH);
3297
3299 strErr = "line " + to_string(nLine) + ": order of Savitzky-Golay polynomial for cliff edge smoothing (must be 2, 4 or 6)";
3300 }
3301
3302 break;
3303
3304 case 89:
3305 // Slope limit for cliff toe detection
3307 {
3308 if (! bIsStringValidDouble(strRH))
3309 {
3310 strErr = "line " + to_string(nLine) + ": invalid number for cliff toe slope limit '" + strRH + "' in " + m_strDataPathName;
3311 break;
3312 }
3313
3314 m_dSlopeThresholdForCliffToe = stod(strRH);
3315
3317 strErr = "line " + to_string(nLine) + ": cliff toe slope limit must be > 0";
3318 }
3319
3320 break;
3321
3322 case 90:
3323 // Run-up equation?
3324 if (bIsStringValidInt(strRH))
3325 m_nRunUpEquation = stoi(strRH);
3326 else
3327 strErr = "line " + to_string(nLine) + ": invalid code for run-up equation used in simulating floods";
3328
3329 if ((m_nRunUpEquation < 0) || (m_nRunUpEquation > 3))
3330 strErr = "line " + to_string(nLine) + ": runup equation code must be between 0 and 3";
3331
3332 break;
3333 }
3334
3335 // Did an error occur?
3336 if (! strErr.empty())
3337 {
3338 // Error in input to run details file
3339 cerr << endl << ERR << strErr << ".\nPlease edit " << m_strDataPathName << " and change this line:" << endl;
3340 cerr << "'" << strRec << "'" << endl << endl;
3341 InStream.close();
3342 return false;
3343 }
3344 }
3345 }
3346
3347 // Close file
3348 InStream.close();
3349
3350 // Finally, need to check that we have at least one raster file, so that we know the grid size and units (and preferably also the projection)
3351 bool bNoRasterFiles = true;
3352
3353 if ((! m_strInitialBasementDEMFile.empty()) || (! m_strInitialSuspSedimentFile.empty()) || (! m_strInitialLandformFile.empty()) || (! m_strInterventionHeightFile.empty()))
3354 bNoRasterFiles = false;
3355
3356 for (int j = 0; j < m_nLayers; j++)
3357 {
3359 bNoRasterFiles = false;
3360 }
3361
3362 if (bNoRasterFiles)
3363 {
3364 // No raster files
3365 cerr << ERR << "at least one raster GIS file is needed" << endl;
3366 return false;
3367 }
3368
3369 return true;
3370}
3371
3372//===============================================================================================================================
3374//===============================================================================================================================
3376{
3377 // Create an ifstream object
3378 ifstream InStream;
3379
3380 // Try to open the file for input
3381 InStream.open(m_strTideDataFile.c_str(), ios::in);
3382
3383 // Did it open OK?
3384 if (! InStream.is_open())
3385 {
3386 // Error: cannot open tide data file for input
3387 cerr << ERR << "cannot open " << m_strTideDataFile << " for input" << endl;
3388 return RTN_ERR_TIDEDATAFILE;
3389 }
3390
3391 // Opened OK
3392 int nLine = 0;
3393 string strRec;
3394
3395 // Now read the data from the file
3396 while (getline(InStream, strRec))
3397 {
3398 nLine++;
3399
3400 // Trim off leading and trailing whitespace
3401 strRec = strTrim(&strRec);
3402
3403 // If it is a blank line or a comment then ignore it
3404 if ((strRec.empty()) || (strRec[0] == QUOTE1) || (strRec[0] == QUOTE2))
3405 continue;
3406
3407 // Check that this is a valid double
3408 if (! bIsStringValidDouble(strRec))
3409 {
3410 cerr << ERR << "invalid floating point number for tide data '" << strRec << "' on line " << nLine << " of " << m_strTideDataFile << endl;
3411 return RTN_ERR_TIDEDATAFILE;
3412 }
3413
3414 // Convert to double then append the value to the vector
3415 m_VdTideData.push_back(strtod(strRec.c_str(), NULL));
3416 }
3417
3418 // Close file
3419 InStream.close();
3420
3421 return RTN_OK;
3422}
3423
3424//===============================================================================================================================
3427//===============================================================================================================================
3429{
3430 // Sort out the path and filename
3434
3435 // Create an ifstream object
3436 ifstream InStream;
3437
3438 // Try to open the file for input
3439 InStream.open(m_strSCAPEShapeFunctionFile.c_str(), ios::in);
3440
3441 // Did it open OK?
3442 if (! InStream.is_open())
3443 {
3444 // Error: cannot open shape function file for input
3445 cerr << ERR << "cannot open " << m_strSCAPEShapeFunctionFile << " for input" << endl;
3447 }
3448
3449 // Opened OK
3450 int nLine = 0;
3451 int nExpected = 0, nRead = 0;
3452 string strRec;
3453
3454 // Read in the number of data lines expected
3455 InStream >> nExpected;
3456
3457 // Set up the vectors to hold the input data
3458 vector<double> VdDepthOverDB;
3459 vector<double> VdErosionPotential;
3460 vector<double> VdErosionPotentialFirstDeriv;
3461
3462 // Now read the rest of the data from the file to get the Erosion Potential Shape function
3463 while (getline(InStream, strRec))
3464 {
3465 nLine++;
3466
3467 // Trim off leading and trailing whitespace
3468 strRec = strTrim(&strRec);
3469
3470 // If it is a blank line or a comment then ignore it
3471 if ((strRec.empty()) || (strRec[0] == QUOTE1) || (strRec[0] == QUOTE2))
3472 continue;
3473
3474 // It isn't so increment counter
3475 nRead++;
3476
3477 // Split the string, and remove whitespace
3478 vector<string> strTmp = VstrSplit(&strRec, SPACE);
3479
3480 for (unsigned int i = 0; i < strTmp.size(); i++)
3481 {
3482 // Remove leading and trailing whitespace
3483 strTmp[i] = strTrim(&strTmp[i]);
3484
3485 // Check that this is a valid double
3486 if (! bIsStringValidDouble(strTmp[i]))
3487 {
3488 cerr << ERR << "on line " + to_string(nLine) + " invalid floating point number for Erosion Potential Shape data '" << strTmp[i] << "' in " << m_strSCAPEShapeFunctionFile << endl;
3490 }
3491 }
3492
3493 // Convert to doubles then append the values to the vectors
3494 VdDepthOverDB.push_back(strtod(strTmp[0].c_str(), NULL));
3495 VdErosionPotential.push_back(strtod(strTmp[1].c_str(), NULL));
3496 VdErosionPotentialFirstDeriv.push_back(strtod(strTmp[2].c_str(), NULL));
3497 }
3498
3499 // Now create the look up table values
3500 m_VdErosionPotential = VdErosionPotential;
3501 m_VdDepthOverDB = VdDepthOverDB;
3502 m_dDepthOverDBMax = VdDepthOverDB[14];
3503
3504 // Close file
3505 InStream.close();
3506
3507 // Did we read in what we expected?
3508 if (nExpected != nRead)
3509 {
3510 cout << ERR << "read in " << nRead << " lines from " << m_strSCAPEShapeFunctionFile << " but " << nExpected << " lines expected" << endl;
3512 }
3513
3514 // Is the shape funcion well defined? i.e. it must be -ve or 0.0 for all values
3515 for (unsigned int j = 0; j < m_VdErosionPotential.size(); j++)
3516 {
3517 if (m_VdErosionPotential[j] > 0)
3518 {
3519 cout << ERR << " in " << m_strSCAPEShapeFunctionFile << ", erosion potential function cannot be positive" << endl;
3521 }
3522 }
3523
3524 // OK, now use this data to create a look-up table to be used for the rest of the simulation
3525 if (! bCreateErosionPotentialLookUp(&VdDepthOverDB, &VdErosionPotential, &VdErosionPotentialFirstDeriv))
3526 {
3527 cout << ERR << "line " + to_string(nLine) + " in " << m_strSCAPEShapeFunctionFile << ": erosion potential function is unbounded for high values of depth over DB" << endl;
3529 }
3530
3531 return RTN_OK;
3532}
3533
3534//===============================================================================================================================
3538//===============================================================================================================================
3539int CSimulation::nReadWaveStationInputFile(int const nWaveStations)
3540{
3541 // Create an ifstream object
3542 ifstream InStream;
3543
3544 // Try to open the file for input
3545 InStream.open(m_strDeepWaterWavesInputFile.c_str(), ios::in);
3546
3547 // Did it open OK?
3548 if (!InStream.is_open())
3549 {
3550 // Error: cannot open time series file for input
3551 cerr << ERR << "cannot open " << m_strDeepWaterWavesInputFile << " for input" << endl;
3553 }
3554
3555 // Opened OK
3556 int nLine = 0;
3557 int nExpectedStations = 0;
3558 int nRead = 0;
3559 int nTimeStepsRead = 0;
3560 string strRec, strErr;
3561
3562 // Read each line, ignoring blank lines and comment lines
3563 while (getline(InStream, strRec))
3564 {
3565 nLine++;
3566
3567 // Trim off leading and trailing whitespace
3568 strRec = strTrim(&strRec);
3569
3570 // If it is a blank line or a comment then ignore it
3571 if ((!strRec.empty()) && (strRec[0] != QUOTE1) && (strRec[0] != QUOTE2))
3572 {
3573 // It isn't so increment counter
3574 nRead++;
3575
3576 // The header lines (the first four lines of the file) contains leading description separated by a colon from the data
3577 if (nRead < 5)
3578 {
3579 // Find the colon: note that lines MUST have a colon separating data from leading description portion
3580 size_t nPos = strRec.find(COLON);
3581
3582 if (nPos == string::npos)
3583 {
3584 // Error: badly formatted (no colon)
3585 cerr << ERR << "on line " << to_string(nLine) << "badly formatted (no ':') in " << m_strDeepWaterWavesInputFile << endl
3586 << "'" << strRec << "'" << endl;
3588 }
3589
3590 if (nPos == strRec.size() - 1)
3591 {
3592 // Error: badly formatted (colon with nothing following)
3593 cerr << ERR << "on line " << to_string(nLine) << "badly formatted (nothing following ':') in " << m_strDeepWaterWavesInputFile << endl
3594 << "'" << strRec << "'" << endl;
3596 }
3597
3598 // Strip off leading portion (the bit up to and including the colon)
3599 string strRH = strRec.substr(nPos + 1);
3600
3601 // Remove leading whitespace
3602 strRH = strTrimLeft(&strRH);
3603
3604 // Look for a trailing comment, if found then terminate string at that point and trim off any trailing whitespace
3605 nPos = strRH.rfind(QUOTE1);
3606
3607 if (nPos != string::npos)
3608 strRH.resize(nPos);
3609
3610 nPos = strRH.rfind(QUOTE2);
3611
3612 if (nPos != string::npos)
3613 strRH.resize(nPos);
3614
3615 // Remove trailing whitespace
3616 strRH = strTrimRight(&strRH);
3617
3618 int nSec = 0;
3619 int nMin = 0;
3620 int nHour = 0;
3621 int nDay = 0;
3622 int nMonth = 0;
3623 int nYear = 0;
3624 double dMult;
3625 double dThisIter;
3626 vector<string> VstrTmp;
3627
3628 switch (nRead)
3629 {
3630 case 1:
3631 // Get the start date/time for this data, format is [hh-mm-ss dd/mm/yyyy]
3632 VstrTmp = VstrSplit(&strRH, SPACE);
3633
3634 // Both date and time here?
3635 if (VstrTmp.size() < 2)
3636 {
3637 strErr = "line " + to_string(nLine) + ": must have both date and time for start of data in";
3638 break;
3639 }
3640
3641 // OK, first sort out the time
3642 if (! bParseTime(&VstrTmp[0], nHour, nMin, nSec))
3643 {
3644 strErr = "line " + to_string(nLine) + ": could not understand start time for data";
3645 break;
3646 }
3647
3648 // Next sort out the date
3649 if (! bParseDate(&VstrTmp[1], nDay, nMonth, nYear))
3650 {
3651 strErr = "line " + to_string(nLine) + ": could not understand start date for data";
3652 break;
3653 }
3654
3655 // Compare time and date with simulation time and date
3656 if ((nSec != m_nSimStartSec) ||
3657 (nMin != m_nSimStartMin) ||
3658 (nHour != m_nSimStartHour) ||
3659 (nDay != m_nSimStartDay) ||
3660 (nMonth != m_nSimStartMonth) ||
3661 (nYear != m_nSimStartYear))
3662 {
3663 strErr = "line " + to_string(nLine) + ": start time and date for wave time series data differs from simulation start time and date,";
3664 break;
3665 }
3666
3667 break;
3668
3669 case 2:
3670 // Get the timestep of this data (in hours or days)
3671 strRH = strToLower(&strRH);
3672
3673 dMult = dGetTimeMultiplier(&strRH);
3674
3675 if (static_cast<int>(dMult) == TIME_UNKNOWN)
3676 {
3677 strErr = "line " + to_string(nLine) + ": unknown units for timestep";
3678 break;
3679 }
3680
3681 // We have the multiplier, now calculate the timestep in hours: look for the whitespace between the number and unit
3682 nPos = strRH.rfind(SPACE);
3683
3684 if (nPos == string::npos)
3685 {
3686 strErr = "line " + to_string(nLine) + ": format of timestep line";
3687 break;
3688 }
3689
3690 // Cut off rh bit of string
3691 strRH.resize(nPos);
3692
3693 // Remove trailing spaces
3694 strRH = strTrimRight(&strRH);
3695
3696 // Check that this is a valid double
3697 if (! bIsStringValidDouble(strRH))
3698 {
3699 strErr = "line " + to_string(nLine) + ": invalid floating point number for timestep";
3700 break;
3701 }
3702
3703 dThisIter = strtod(strRH.c_str(), NULL) * dMult; // in hours
3704
3705 if (dThisIter <= 0)
3706 strErr = "line " + to_string(nLine) + ": timestep must be > 0";
3707
3708 if (dThisIter >= 24)
3709 strErr = "line " + to_string(nLine) + ": timestep must be < 24 hours";
3710
3711 if (! bFPIsEqual(dThisIter, m_dTimeStep, TOLERANCE))
3712 strErr = "line " + to_string(nLine) + ": timestep must be the same as the simulation timestep";
3713
3714 break;
3715
3716 case 3:
3717 // Read the number of stations
3718 if (! bIsStringValidInt(strRH))
3719 {
3720 strErr = "line " + to_string(nLine) + ": invalid integer for number of wave stations '" + strRH + "' in " + m_strDeepWaterWavesInputFile;
3721 break;
3722 }
3723
3724 nExpectedStations = stoi(strRH);
3725
3726 // Check that the number of expected stations is equal to the number of stations on the point shape file
3727 if (nExpectedStations != nWaveStations)
3728 {
3729 // Error: number of points on shape file does not match the number of stations on the wave time series file
3730 strErr = "line " + to_string(nLine) + ": number of wave stations in " + m_strDeepWaterWaveStationsShapefile + " is " + to_string(nWaveStations) + " but we have " + to_string(nExpectedStations) + " stations";
3731
3732 break;
3733 }
3734
3735 break;
3736
3737 case 4:
3738 // Read the expected number of time steps in the file
3739 if (! bIsStringValidInt(strRH))
3740 {
3741 strErr = "line " + to_string(nLine) + ": invalid integer for expected number of time steps '" + strRH + "' in " + m_strDeepWaterWaveStationsShapefile;
3742 break;
3743 }
3744
3746
3748 {
3749 // Error: must have value(s) for at least one timestep
3750 strErr = "line " + to_string(nLine) + ": must have values for at least one timestep";
3751 break;
3752 }
3753
3754 break;
3755 }
3756 }
3757 else
3758 {
3759 // This is not a header line
3760 nTimeStepsRead++;
3761
3762 // Read in each wave attribute for each time step and station: split the string, and remove whitespace
3763 vector<string> VstrTmp = VstrSplit(&strRec, COMMA);
3764
3765 for (unsigned int i = 0; i < VstrTmp.size(); i++) // VstrTmp.size() should be 3 x nExpectedStations
3766 {
3767 // Remove leading and trailing whitespace
3768 VstrTmp[i] = strTrim(&VstrTmp[i]);
3769
3770 // Check that this is a valid double
3771 if (! bIsStringValidDouble(VstrTmp[i]))
3772 {
3773 strErr = "line " + to_string(nLine) + ": invalid floating point number for deep water wave value '" + VstrTmp[i] + "' in " + m_strDeepWaterWavesInputFile;
3774 break;
3775 }
3776 }
3777
3778 // Convert to doubles then append the values to the vectors
3779 int n = 0;
3780
3781 for (int i = 0; i < nExpectedStations; i++)
3782 {
3783 m_VdTSDeepWaterWaveStationHeight.push_back(strtod(VstrTmp[n + 0].c_str(), NULL));
3784 m_VdTSDeepWaterWaveStationAngle.push_back(strtod(VstrTmp[n + 1].c_str(), NULL));
3785 m_VdTSDeepWaterWaveStationPeriod.push_back(strtod(VstrTmp[n + 2].c_str(), NULL));
3786
3787 // Check some simple wave input stats
3790
3793
3794 n += 3;
3795 }
3796 }
3797 }
3798
3799 // Did an error occur?
3800 if (! strErr.empty())
3801 {
3802 // Error in input to initialisation file
3803 cerr << ERR << strErr << " in deep water wave time series file " << m_strDeepWaterWavesInputFile << endl
3804 << "'" << strRec << "'" << endl;
3805 InStream.close();
3806
3808 }
3809 }
3810
3811 if (nTimeStepsRead != m_nDeepWaterWaveDataNumTimeSteps)
3812 {
3813 // Error: number of timesteps read does not match the number given in the file's header
3814 cerr << ERR << "in " << m_strDeepWaterWavesInputFile << ", data for " << nTimeStepsRead << " timesteps was read, but " << m_nDeepWaterWaveDataNumTimeSteps << " timesteps were specified in the file's header" << endl;
3815
3817 }
3818
3819 // Close file
3820 InStream.close();
3821
3822 // Did we read in what we expected?
3823 unsigned int const nTotExpected = nExpectedStations * m_nDeepWaterWaveDataNumTimeSteps;
3824
3825 if (m_VdTSDeepWaterWaveStationHeight.size() != nTotExpected)
3826 {
3827 cout << ERR << "read in " << m_VdTSDeepWaterWaveStationHeight.size() << " lines from " << m_strDeepWaterWavesInputFile << " but " << nTotExpected << " values expected" << endl;
3828
3830 }
3831
3832 if (m_VdTSDeepWaterWaveStationAngle.size() != nTotExpected)
3833 {
3834 cout << ERR << "read in " << m_VdTSDeepWaterWaveStationAngle.size() << " lines from " << m_strDeepWaterWavesInputFile << " but " << nTotExpected << " values expected" << endl;
3835
3837 }
3838
3839 if (m_VdTSDeepWaterWaveStationPeriod.size() != nTotExpected)
3840 {
3841 cout << ERR << "read in " << m_VdTSDeepWaterWaveStationPeriod.size() << " lines from " << m_strDeepWaterWavesInputFile << " but " << nTotExpected << " values expected" << endl;
3842
3844 }
3845
3846 // All is OK, so we can now initialise the vectors that will store this timestep's deep water wave values
3847 for (int j = 0; j < nExpectedStations; j++)
3848 {
3852 }
3853
3854 // Finally, check whether the wave data will 'wrap' i.e. whether the number of timesteps is less than the total number of timesteps in the simulation
3855 int const nSimulationTimeSteps = static_cast<int>(floor(m_dSimDuration / m_dTimeStep));
3856
3857 if (m_nDeepWaterWaveDataNumTimeSteps < nSimulationTimeSteps)
3858 {
3860 string const strTmp = "Deep water wave data will wrap every " + (m_nDeepWaterWaveDataNumTimeSteps > 1 ? to_string(m_nDeepWaterWaveDataNumTimeSteps) + " " : "") + "time step" + (m_nDeepWaterWaveDataNumTimeSteps > 1 ? "s" : "") + " (every " + to_string(m_dWaveDataWrapHours) + " hours)\n";
3861
3862 cout << NOTE << strTmp;
3863 }
3864
3865 return RTN_OK;
3866}
3867
3868
3869//===============================================================================================================================
3871//===============================================================================================================================
3873{
3874 // Create an ifstream object
3875 ifstream InStream;
3876
3877 // Try to open the file for input
3878 InStream.open(m_strSedimentInputEventFile.c_str(), ios::in);
3879
3880 // Did it open OK?
3881 if (! InStream.is_open())
3882 {
3883 // Error: cannot open time series file for input
3884 cerr << ERR << "cannot open " << m_strSedimentInputEventFile << " for input" << endl;
3886 }
3887
3888 // Opened OK
3889 int nLine = 0;
3890 int nRead = 0;
3891 string strRec, strErr;
3892
3893 // Read each line, ignoring comment lines
3894 while (getline(InStream, strRec))
3895 {
3896 nLine++;
3897
3898 // Trim off leading and trailing whitespace
3899 strRec = strTrim(&strRec);
3900
3901 // If it is a blank line or a comment then ignore it
3902 if ((! strRec.empty()) && (strRec[0] != QUOTE1) && (strRec[0] != QUOTE2))
3903 {
3904 // It isn't so increment counter
3905 nRead++;
3906
3907 // Split at commas
3908 vector<string> VstrTmp = VstrSplit(&strRec, COMMA);
3909
3910 // Check that have all we need
3911 unsigned int nTarget = 7;
3912
3914 nTarget = 5;
3915
3916 if (VstrTmp.size() < nTarget)
3917 {
3918 strErr = "line " + to_string(nLine) + ": too few data items on data line '" + to_string(nRead) + "' in " + m_strSedimentInputEventFile;
3919 break;
3920 }
3921
3922 // First item is the Location ID of the sediment input event (same as the ID in the shapefile)
3923 if (! bIsStringValidInt(VstrTmp[0]))
3924 {
3925 strErr = "line " + to_string(nLine) + ": invalid integer for Location ID of sediment input event '" + VstrTmp[0] + "' in " + m_strSedimentInputEventFile;
3926 break;
3927 }
3928
3929 int const nID = stoi(strTrim(&VstrTmp[0]));
3930
3931 // OK, check the ID against IDs read in from the shapefile
3932 auto result = find(m_VnSedimentInputLocationID.begin(), m_VnSedimentInputLocationID.end(), nID);
3933
3934 if (result == m_VnSedimentInputLocationID.end())
3935 {
3936 strErr = "line " + to_string(nLine) + ": invalid Location ID '" + to_string(nID) + "' for sediment input event location event in " + m_strSedimentInputEventFile;
3937 break;
3938 }
3939
3940 // Next get the timestep at which the sediment input event occurs. This may be specified either as a relative time (i.e. a number of hours or days after the simulation start) or as an absolute time (i.e. a time/date in the format hh-mm-ss dd/mm/yyyy)
3941 unsigned long const ulEventTimeStep = ulConvertToTimestep(&VstrTmp[1]);
3942
3943 if (ulEventTimeStep == SEDIMENT_INPUT_EVENT_ERROR)
3944 {
3945 strErr = "line " + to_string(nLine) + ": invalid time and/or date '" + VstrTmp[1] + "' for sediment input event in " + m_strSedimentInputEventFile;
3946 break;
3947 }
3948
3949 // Then the volume (m3) of fine sediment, first check that this is a valid double
3950 if (! bIsStringValidDouble(VstrTmp[2]))
3951 {
3952 strErr = "line " + to_string(nLine) + ": invalid floating point number '" + VstrTmp[2] + "' for fine sediment volume for sediment input event in " + m_strSedimentInputEventFile;
3953 break;
3954 }
3955
3956 double const dFineSedVol = stod(strTrim(&VstrTmp[2]));
3957
3958 if (dFineSedVol < 0)
3959 {
3960 strErr = "line " + to_string(nLine) + ": negative number '" + to_string(dFineSedVol) + "' for fine sediment volume for sediment input event in " + m_strSedimentInputEventFile;
3961 break;
3962 }
3963
3964 if (dFineSedVol > 0)
3965 m_bHaveFineSediment = true;
3966
3967 // Then the volume (m3) of sand sediment, first check that this is a valid double
3968 if (! bIsStringValidDouble(VstrTmp[3]))
3969 {
3970 strErr = "line " + to_string(nLine) + ": invalid floating point number '" + VstrTmp[3] + "' for sand-sized sediment volume for sediment input event in " + m_strSedimentInputEventFile;
3971 break;
3972 }
3973
3974 double const dSandSedVol = stod(strTrim(&VstrTmp[3]));
3975
3976 if (dSandSedVol < 0)
3977 {
3978 strErr = "line " + to_string(nLine) + ": negative number '" + to_string(dSandSedVol) + "' for sand-sized sediment volume for sediment input event in " + m_strSedimentInputEventFile;
3979 break;
3980 }
3981
3982 if (dSandSedVol > 0)
3983 m_bHaveSandSediment = true;
3984
3985 // Then the volume (m3) of coarse sediment, first check that this is a valid double
3986 if (! bIsStringValidDouble(VstrTmp[4]))
3987 {
3988 strErr = "line " + to_string(nLine) + ": invalid floating point number '" + VstrTmp[4] + "' for coarse sediment volume for sediment input event in " + m_strSedimentInputEventFile;
3989 break;
3990 }
3991
3992 double const dCoarseSedVol = stod(strTrim(&VstrTmp[4]));
3993
3994 if (dCoarseSedVol < 0)
3995 {
3996 strErr = "line " + to_string(nLine) + ": negative number '" + to_string(dCoarseSedVol) + "' for coarse sediment volume of sediment input event in " + m_strSedimentInputEventFile;
3997 break;
3998 }
3999
4000 if (dCoarseSedVol > 0)
4001 m_bHaveCoarseSediment = true;
4002
4003 // Only read the last two items if we have on-coast sediment block sediment input
4004 double dLen = 0;
4005 double dWidth = 0;
4006
4007 // double dThick = 0;
4009 {
4010 // The coast-normal length (m) of the sediment block, first check that this is a valid double
4011 if (! bIsStringValidDouble(VstrTmp[5]))
4012 {
4013 strErr = "line " + to_string(nLine) + ": invalid floating point number '" + VstrTmp[5] + "' for coast-normal length of sediment input event in " + m_strSedimentInputEventFile;
4014 break;
4015 }
4016
4017 dLen = stod(strTrim(&VstrTmp[5]));
4018
4019 if (dLen <= 0)
4020 {
4021 strErr = "line " + to_string(nLine) + ": coast-normal length of the sediment block '" + to_string(dLen) + "' must be > 0 in " + m_strSedimentInputEventFile;
4022 break;
4023 }
4024
4025 // The along-coast width (m) of the sediment block, first check that this is a valid double
4026 if (! bIsStringValidDouble(VstrTmp[6]))
4027 {
4028 strErr = "line " + to_string(nLine) + ": invalid floating point number '" + VstrTmp[6] + "' for along-coast width of sediment input event in " + m_strSedimentInputEventFile;
4029 break;
4030 }
4031
4032 dWidth = stod(strTrim(&VstrTmp[6]));
4033
4034 if ((! m_bSedimentInputAtCoast) && (dWidth <= 0))
4035 {
4036 strErr = "line " + to_string(nLine) + ": along-coast width (m) of the sediment block '" + to_string(dWidth) + "' must be > 0 in " + m_strSedimentInputEventFile;
4037 break;
4038 }
4039
4040 // // The along-coast thickness (m) of the sediment block, first check that this is a valid double
4041 // if (! bIsStringValidDouble(VstrTmp[7]))
4042 // {
4043 // strErr = "line " + to_string(nLine) + ": invalid floating point number '" + VstrTmp[7] + "' for along-coast thickness of sediment input event in " + m_strSedimentInputEventFile;
4044 // break;
4045 // }
4046 //
4047 // dThick = stod(strTrim(&VstrTmp[7]));
4048 // if ((! m_bSedimentInputAtCoast) && (dWidth <= 0))
4049 // {
4050 // strErr = "line " + to_string(nLine) + ": along-coast thickness (m) of the sediment block '" + to_string(dThick) + "' must be > 0 in " + m_strSedimentInputEventFile;
4051 // break;
4052 // }
4053 }
4054
4055 // Create the CRWSedInputEvent object
4056 CRWSedInputEvent *pEvent = new CRWSedInputEvent(nID, ulEventTimeStep, dFineSedVol, dSandSedVol, dCoarseSedVol, dLen, dWidth); //, dThick);
4057
4058 // And store it in the m_pVSedInputEvent vector
4059 m_pVSedInputEvent.push_back(pEvent);
4060 }
4061 }
4062
4063 // Did an error occur?
4064 if (! strErr.empty())
4065 {
4066 // Error in input to initialisation file
4067 cerr << ERR << strErr << " in sediment input event file " << m_strSedimentInputEventFile << endl
4068 << "'" << strRec << "'" << endl;
4069 InStream.close();
4070
4072 }
4073
4074 // Close file
4075 InStream.close();
4076
4077 return RTN_OK;
4078}
4079
4080//===============================================================================================================================
4082//===============================================================================================================================
4083bool CSimulation::bDetectFileFormat(string const &strFileName, bool &bIsYaml)
4084{
4085 bIsYaml = false;
4086
4087 // First check command-line flag
4089 {
4090 bIsYaml = true;
4091 return true;
4092 }
4093
4094 // Check file extension
4095 size_t nDotPos = strFileName.find_last_of('.');
4096 if (nDotPos != string::npos)
4097 {
4098 string strExt = strFileName.substr(nDotPos + 1);
4099 std::transform(strExt.begin(), strExt.end(), strExt.begin(), ::tolower);
4100
4101 if (strExt == "yaml" || strExt == "yml")
4102 {
4103 bIsYaml = true;
4104 return true;
4105 }
4106 else if (strExt == "dat")
4107 {
4108 bIsYaml = false;
4109 return true;
4110 }
4111 }
4112
4113 // Default to .dat format if extension is ambiguous
4114 bIsYaml = false;
4115 return true;
4116}
4117
4118//===============================================================================================================================
4120//===============================================================================================================================
4122{
4123 CConfiguration config;
4124 if (! bConfigureFromYamlFile(config))
4125 return false;
4126
4127 // Apply configuration values to simulation object
4128 if (! bApplyConfiguration(config))
4129 return false;
4130
4131 return true;
4132}
4133
4134//===============================================================================================================================
4136//===============================================================================================================================
4138{
4139 CYamlParser parser;
4140
4141 if (! parser.bParseFile(m_strDataPathName))
4142 {
4143 cerr << ERR << "Failed to parse YAML file " << m_strDataPathName << ": "
4144 << parser.GetError() << endl;
4145 return false;
4146 }
4147
4148 CYamlNode root = parser.GetRoot();
4149
4150 // Helper function to process file paths with base path
4151 auto processFilePath = [&](string const &filePath) -> string
4152 {
4153 if (filePath.empty())
4154 return filePath;
4155
4156 // Check if base_path is specified in YAML
4157 string basePath;
4158 if (root.HasChild("base_path"))
4159 {
4160 basePath = root.GetChild("base_path").GetValue();
4161 if (! basePath.empty() && basePath.back() != PATH_SEPARATOR)
4162 {
4163 basePath += PATH_SEPARATOR;
4164 }
4165 }
4166
4167 // If no base path or file path is absolute, return as-is
4168 if (basePath.empty() || (filePath[0] == PATH_SEPARATOR) ||
4169 (filePath[0] == TILDE) ||
4170 (filePath.length() > 1 && filePath[1] == COLON))
4171 {
4172 return filePath;
4173 }
4174
4175 // Prepend base path to relative file path
4176 return basePath + filePath;
4177 };
4178
4179 try
4180 {
4181 // Run Information
4182 if (root.HasChild("run_information"))
4183 {
4184 CYamlNode runInfo = root.GetChild("run_information");
4185 if (runInfo.HasChild("output_file_names"))
4186 config.SetRunName(runInfo.GetChild("output_file_names").GetValue());
4187 if (runInfo.HasChild("log_file_detail"))
4188 config.SetLogFileDetail(
4189 runInfo.GetChild("log_file_detail").GetIntValue());
4190 if (runInfo.HasChild("csv_per_timestep_results"))
4192 runInfo.GetChild("csv_per_timestep_results").GetBoolValue());
4193 }
4194
4195 // simulation
4196 if (root.HasChild("simulation"))
4197
4198 {
4199 CYamlNode sim = root.GetChild("simulation");
4200 config.SetStartDateTime(sim.GetChild("start_date_time").GetValue());
4201 if (sim.HasChild("duration"))
4202 config.SetDuration(sim.GetChild("duration").GetValue());
4203 if (sim.HasChild("timestep"))
4204 config.SetTimestep(sim.GetChild("timestep").GetValue());
4205 if (sim.HasChild("save_times"))
4206 {
4207 CYamlNode saveTimes = sim.GetChild("save_times");
4208 if (saveTimes.IsSequence())
4209 config.SetSaveTimes(saveTimes.GetStringSequence());
4210 }
4211 if (sim.HasChild("random_seed"))
4212 config.SetRandomSeed(sim.GetChild("random_seed").GetIntValue());
4213 }
4214
4215 // GIS Output
4216 if (root.HasChild("gis_output"))
4217 {
4218 CYamlNode gis = root.GetChild("gis_output");
4219 if (gis.HasChild("max_save_digits"))
4220 config.SetMaxSaveDigits(gis.GetChild("max_save_digits").GetIntValue());
4221 if (gis.HasChild("save_digits_mode"))
4222 config.SetSaveDigitsMode(gis.GetChild("save_digits_mode").GetValue());
4223 if (gis.HasChild("raster_files"))
4224 {
4225 CYamlNode rasterFiles = gis.GetChild("raster_files");
4226 if (rasterFiles.IsSequence()){
4227 config.SetRasterFiles(rasterFiles.GetStringSequence());
4228 }
4229 else {
4230 //Allow the user to supply single entries not in list form
4231 std::vector<std::string> tempVec{rasterFiles.GetValue()};
4232 config.SetRasterFiles(tempVec);
4233 }
4234 }
4235 if (gis.HasChild("vector_files"))
4236 {
4237 CYamlNode vectorFiles = gis.GetChild("vector_files");
4238 if (vectorFiles.IsSequence())
4239 config.SetVectorFiles(vectorFiles.GetStringSequence());
4240 }
4241 if (gis.HasChild("raster_format"))
4242 config.SetRasterFormat(gis.GetChild("raster_format").GetValue());
4243 if (gis.HasChild("world_file"))
4244 config.SetWorldFile(gis.GetChild("world_file").GetBoolValue());
4245 if (gis.HasChild("scale_values"))
4246 config.SetScaleValues(gis.GetChild("scale_values").GetBoolValue());
4247 }
4248
4249 // Hydrology
4250 if (root.HasChild("hydrology"))
4251 {
4252 CYamlNode hydro = root.GetChild("hydrology");
4253 if (hydro.HasChild("wave_propagation_model"))
4254 {
4255 string strModel = hydro.GetChild("wave_propagation_model").GetValue();
4256 if (strModel == "COVE")
4257 config.SetWavePropagationModel(0);
4258 else if (strModel == "CShore")
4259 config.SetWavePropagationModel(1);
4260 }
4261 if (hydro.HasChild("seawater_density"))
4262 config.SetSeawaterDensity(
4263 hydro.GetChild("seawater_density").GetDoubleValue());
4264 if (hydro.HasChild("initial_water_level"))
4265 config.SetInitialWaterLevel(
4266 hydro.GetChild("initial_water_level").GetDoubleValue());
4267 if (hydro.HasChild("final_water_level"))
4268 config.SetFinalWaterLevel(
4269 hydro.GetChild("final_water_level").GetDoubleValue());
4270
4271 // Wave data configuration - read wave_input_mode first
4272 string strWaveInputMode = "fixed"; // default
4273 if (hydro.HasChild("wave_input_mode"))
4274 {
4275 strWaveInputMode = hydro.GetChild("wave_input_mode").GetValue();
4276 config.SetWaveInputMode(strWaveInputMode);
4277 }
4278
4279 // Conditionally read wave parameters based on input mode
4280 if (strWaveInputMode == "time_series")
4281 {
4282 // Read time series wave inputs
4283 if (hydro.HasChild("wave_height_time_series"))
4285 processFilePath(hydro.GetChild("wave_height_time_series").GetValue()));
4286 if (hydro.HasChild("wave_height_shape_file"))
4288 processFilePath(hydro.GetChild("wave_height_shape_file").GetValue()));
4289 }
4290 else if (strWaveInputMode == "fixed")
4291 {
4292 // Read fixed wave condition inputs
4293 if (hydro.HasChild("wave_height"))
4295 hydro.GetChild("wave_height").GetDoubleValue());
4296 if (hydro.HasChild("wave_orientation"))
4298 hydro.GetChild("wave_orientation").GetDoubleValue());
4299 if (hydro.HasChild("wave_period"))
4300 config.SetWavePeriod(hydro.GetChild("wave_period").GetDoubleValue());
4301 }
4302 else
4303 {
4304 cerr << ERR << "Unknown wave_input_mode '" << strWaveInputMode
4305 << "'. Must be 'fixed' or 'time_series'" << endl;
4306 return false;
4307 }
4308 // Tide data configuration
4309 if (hydro.HasChild("tide_data_file"))
4310 config.SetTideDataFile(processFilePath(hydro.GetChild("tide_data_file").GetValue()));
4311 if (hydro.HasChild("breaking_wave_ratio"))
4312 config.SetBreakingWaveRatio(
4313 hydro.GetChild("breaking_wave_ratio").GetDoubleValue());
4314 }
4315
4316 // Grid and Coastline
4317 if (root.HasChild("grid_and_coastline"))
4318 {
4319 CYamlNode grid = root.GetChild("grid_and_coastline");
4320 if (grid.HasChild("coastline_smoothing"))
4321 {
4322 string strSmoothing = grid.GetChild("coastline_smoothing").GetValue();
4323 if (strSmoothing == "none")
4324 config.SetCoastlineSmoothing(0);
4325 else if (strSmoothing == "running_mean")
4326 config.SetCoastlineSmoothing(1);
4327 else if (strSmoothing == "savitzky_golay")
4328 config.SetCoastlineSmoothing(2);
4329 else
4330 config.SetCoastlineSmoothing(
4331 grid.GetChild("coastline_smoothing").GetIntValue());
4332 }
4333 if (grid.HasChild("coastline_smoothing_window"))
4335 grid.GetChild("coastline_smoothing_window").GetIntValue());
4336 if (grid.HasChild("polynomial_order"))
4337 config.SetPolynomialOrder(
4338 grid.GetChild("polynomial_order").GetIntValue());
4339 if (grid.HasChild("omit_grid_edges"))
4340 config.SetOmitGridEdges(grid.GetChild("omit_grid_edges").GetValue());
4341 if (grid.HasChild("profile_smoothing_window"))
4343 grid.GetChild("profile_smoothing_window").GetIntValue());
4344 if (grid.HasChild("max_local_slope"))
4345 config.SetMaxLocalSlope(
4346 grid.GetChild("max_local_slope").GetDoubleValue());
4347 if (grid.HasChild("max_beach_elevation"))
4348 config.SetMaxBeachElevation(
4349 grid.GetChild("max_beach_elevation").GetDoubleValue());
4350 }
4351
4352 // Layers and Files
4353 if (root.HasChild("layers_and_files"))
4354 {
4355 CYamlNode layers = root.GetChild("layers_and_files");
4356 if (layers.HasChild("num_layers"))
4357 config.SetNumLayers(layers.GetChild("num_layers").GetIntValue());
4358 if (layers.HasChild("basement_dem_file"))
4359 config.SetBasementDEMFile(
4360 processFilePath(layers.GetChild("basement_dem_file").GetValue()));
4361 if (layers.HasChild("suspended_sediment_file"))
4362 config.SetSuspendedSedFile(processFilePath(
4363 layers.GetChild("suspended_sediment_file").GetValue()));
4364 if (layers.HasChild("landform_file"))
4365 config.SetLandformFile(
4366 processFilePath(layers.GetChild("landform_file)").GetValue()));
4367 if (layers.HasChild("intervention_class_file"))
4368 config.SetInterventionClassFile(processFilePath(
4369 layers.GetChild("intervention_class_file").GetValue()));
4370 if (layers.HasChild("intervention_height_file"))
4371 config.SetInterventionHeightFile(processFilePath(
4372 layers.GetChild("intervention_height_file").GetValue()));
4373
4374 // Handle layer-specific files (assuming layer_0, layer_1, etc.)
4375 if (layers.HasChild("layer_0"))
4376 {
4377 CYamlNode layer0 = layers.GetChild("layer_0");
4378 vector<string> unconsFine, unconsSand, unconsCoarse;
4379 vector<string> consFine, consSand, consCoarse;
4380
4381 if (layer0.HasChild("unconsolidated_fine"))
4382 unconsFine.push_back(processFilePath(
4383 layer0.GetChild("unconsolidated_fine").GetValue()));
4384 if (layer0.HasChild("unconsolidated_sand"))
4385 unconsSand.push_back(processFilePath(
4386 layer0.GetChild("unconsolidated_sand").GetValue()));
4387 if (layer0.HasChild("unconsolidated_coarse"))
4388 unconsCoarse.push_back(processFilePath(
4389 layer0.GetChild("unconsolidated_coarse").GetValue()));
4390 if (layer0.HasChild("consolidated_fine"))
4391 consFine.push_back(
4392 processFilePath(layer0.GetChild("consolidated_fine").GetValue()));
4393 if (layer0.HasChild("consolidated_sand"))
4394 consSand.push_back(
4395 processFilePath(layer0.GetChild("consolidated_sand").GetValue()));
4396 if (layer0.HasChild("consolidated_coarse"))
4397 consCoarse.push_back(processFilePath(
4398 layer0.GetChild("consolidated_coarse").GetValue()));
4399
4400 config.SetUnconsFineFiles(unconsFine);
4401 config.SetUnconsSandFiles(unconsSand);
4402 config.SetUnconsCoarseFiles(unconsCoarse);
4403 config.SetConsFineFiles(consFine);
4404 config.SetConsSandFiles(consSand);
4405 config.SetConsCoarseFiles(consCoarse);
4406 }
4407 }
4408
4409 // Sediment and Erosion
4410 if (root.HasChild("sediment_and_erosion"))
4411 {
4412 CYamlNode sed = root.GetChild("sediment_and_erosion");
4413 if (sed.HasChild("coast_platform_erosion"))
4415 sed.GetChild("coast_platform_erosion").GetBoolValue());
4416 if (sed.HasChild("platform_erosion_resistance"))
4418 sed.GetChild("platform_erosion_resistance").GetDoubleValue());
4419 if (sed.HasChild("beach_sediment_transport"))
4421 sed.GetChild("beach_sediment_transport").GetBoolValue());
4422 if (sed.HasChild("beach_transport_at_edges"))
4424 sed.GetChild("beach_transport_at_edges").GetIntValue());
4425 if (sed.HasChild("beach_erosion_equation"))
4426 {
4427 string strEqn = sed.GetChild("beach_erosion_equation").GetValue();
4428 config.SetBeachErosionEquation(strEqn == "CERC" ? 0 : 1);
4429 }
4430 if (sed.HasChild("sediment_density"))
4431 config.SetSedimentDensity(
4432 sed.GetChild("sediment_density").GetDoubleValue());
4433 if (sed.HasChild("beach_sediment_porosity"))
4435 sed.GetChild("beach_sediment_porosity").GetDoubleValue());
4436 if (sed.HasChild("transport_kls"))
4437 config.SetTransportKLS(sed.GetChild("transport_kls").GetDoubleValue());
4438 if (sed.HasChild("kamphuis_parameter"))
4439 config.SetKamphuis(sed.GetChild("kamphuis_parameter").GetDoubleValue());
4440 if (sed.HasChild("berm_height"))
4441 config.SetBermHeight(sed.GetChild("berm_height").GetDoubleValue());
4442
4443 // Handle nested median_sizes and erosivity sections
4444 if (sed.HasChild("median_sizes"))
4445 {
4446 CYamlNode sizes = sed.GetChild("median_sizes");
4447 if (sizes.HasChild("fine"))
4448 config.SetFineMedianSize(sizes.GetChild("fine").GetDoubleValue());
4449 if (sizes.HasChild("sand"))
4450 config.SetSandMedianSize(sizes.GetChild("sand").GetDoubleValue());
4451 if (sizes.HasChild("coarse"))
4452 config.SetCoarseMedianSize(sizes.GetChild("coarse").GetDoubleValue());
4453 }
4454 if (sed.HasChild("erosivity"))
4455 {
4456 CYamlNode eros = sed.GetChild("erosivity");
4457 if (eros.HasChild("fine"))
4458 config.SetFineErosivity(eros.GetChild("fine").GetDoubleValue());
4459 if (eros.HasChild("sand"))
4460 config.SetSandErosivity(eros.GetChild("sand").GetDoubleValue());
4461 if (eros.HasChild("coarse"))
4462 config.SetCoarseErosivity(eros.GetChild("coarse").GetDoubleValue());
4463 }
4464 }
4465
4466 // Cliff Parameters
4467 if (root.HasChild("cliff_parameters"))
4468 {
4469 CYamlNode cliff = root.GetChild("cliff_parameters");
4470 if (cliff.HasChild("cliff_collapse"))
4471 config.SetCliffCollapse(
4472 cliff.GetChild("cliff_collapse").GetBoolValue());
4473 if (cliff.HasChild("cliff_erosion_resistance"))
4475 cliff.GetChild("cliff_erosion_resistance").GetDoubleValue());
4476 if (cliff.HasChild("notch_overhang"))
4477 config.SetNotchOverhang(
4478 cliff.GetChild("notch_overhang").GetDoubleValue());
4479 if (cliff.HasChild("notch_base"))
4480 config.SetNotchBase(cliff.GetChild("notch_base").GetDoubleValue());
4481 if (cliff.HasChild("deposition_scale_parameter_a"))
4482 config.SetCliffDepositionA(
4483 cliff.GetChild("deposition_scale_parameter_a").GetDoubleValue());
4484 if (cliff.HasChild("talus_width"))
4485 config.SetTalusWidth(cliff.GetChild("talus_width").GetDoubleValue());
4486 if (cliff.HasChild("min_talus_length"))
4487 config.SetMinTalusLength(
4488 cliff.GetChild("min_talus_length").GetDoubleValue());
4489 if (cliff.HasChild("min_talus_height"))
4490 config.SetMinTalusHeight(
4491 cliff.GetChild("min_talus_height").GetDoubleValue());
4492 }
4493
4494 // Flood Parameters
4495 if (root.HasChild("flood_parameters"))
4496 {
4497 CYamlNode flood = root.GetChild("flood_parameters");
4498 if (flood.HasChild("flood_input"))
4499 config.SetFloodInput(flood.GetChild("flood_input").GetBoolValue());
4500 if (flood.HasChild("flood_coastline"))
4501 config.SetFloodCoastline(flood.GetChild("flood_coastline").GetValue());
4502 if (flood.HasChild("runup_equation"))
4503 config.SetRunupEquation(flood.GetChild("runup_equation").GetValue());
4504 if (flood.HasChild("characteristic_locations"))
4505 config.SetFloodLocations(
4506 flood.GetChild("characteristic_locations").GetValue());
4507 if (flood.HasChild("flood_input_location"))
4508 config.SetFloodInputLocation(
4509 flood.GetChild("flood_input_location").GetValue());
4510 }
4511
4512 // Sediment Input Parameters
4513 if (root.HasChild("sediment_input_parameters"))
4514 {
4515 CYamlNode sedInput = root.GetChild("sediment_input_parameters");
4516 if (sedInput.HasChild("sediment_input"))
4517 config.SetSedimentInput(
4518 sedInput.GetChild("sediment_input").GetBoolValue());
4519 if (sedInput.HasChild("location"))
4521 sedInput.GetChild("location").GetValue());
4522 if (sedInput.HasChild("type"))
4523 config.SetSedimentInputType(sedInput.GetChild("type").GetValue());
4524 if (sedInput.HasChild("details_file"))
4526 sedInput.GetChild("details_file").GetValue());
4527 }
4528
4529 // Physics and Geometry
4530 if (root.HasChild("physics_and_geometry"))
4531 {
4532 CYamlNode physics = root.GetChild("physics_and_geometry");
4533 if (physics.HasChild("gravitational_acceleration"))
4535 physics.GetChild("gravitational_acceleration").GetDoubleValue());
4536 if (physics.HasChild("normal_spacing"))
4537 config.SetNormalSpacing(
4538 physics.GetChild("normal_spacing").GetDoubleValue());
4539 if (physics.HasChild("random_factor"))
4540 config.SetRandomFactor(
4541 physics.GetChild("random_factor").GetDoubleValue());
4542 if (physics.HasChild("normal_length"))
4543 config.SetNormalLength(
4544 physics.GetChild("normal_length").GetDoubleValue());
4545 if (physics.HasChild("start_depth_ratio"))
4546 config.SetStartDepthRatio(
4547 physics.GetChild("start_depth_ratio").GetDoubleValue());
4548 if (physics.HasChild("synthetic_transect_spacing"))
4550 physics.GetChild("synthetic_transect_spacing").GetDoubleValue());
4551 }
4552
4553 // Profile and Output
4554 if (root.HasChild("profile_and_output"))
4555 {
4556 CYamlNode profile = root.GetChild("profile_and_output");
4557 if (profile.HasChild("save_profile_data"))
4558 config.SetSaveProfileData(
4559 profile.GetChild("save_profile_data").GetBoolValue());
4560 if (profile.HasChild("save_parallel_profiles"))
4562 profile.GetChild("save_parallel_profiles").GetBoolValue());
4563 if (profile.HasChild("output_erosion_potential"))
4565 profile.GetChild("output_erosion_potential").GetBoolValue());
4566 if (profile.HasChild("curvature_window"))
4567 config.SetCurvatureWindow(
4568 profile.GetChild("curvature_window").GetIntValue());
4569
4570 // Handle numeric lists
4571 if (profile.HasChild("profile_numbers"))
4572 {
4573 CYamlNode profileNums = profile.GetChild("profile_numbers");
4574 if (profileNums.IsSequence())
4575 {
4576 vector<int> vecNums;
4577 vector<CYamlNode> seq = profileNums.GetSequence();
4578 for (auto const &node : seq)
4579 vecNums.push_back(node.GetIntValue());
4580 config.SetProfileNumbers(vecNums);
4581 }
4582 }
4583 if (profile.HasChild("profile_timesteps"))
4584 {
4585 CYamlNode profileTimes = profile.GetChild("profile_timesteps");
4586 if (profileTimes.IsSequence())
4587 {
4588 vector<unsigned long> vecTimes;
4589 vector<CYamlNode> seq = profileTimes.GetSequence();
4590 for (auto const &node : seq)
4591 vecTimes.push_back(node.GetULongValue());
4592 config.SetProfileTimesteps(vecTimes);
4593 }
4594 }
4595 }
4596
4597 // Cliff Edge Processing
4598 if (root.HasChild("cliff_edge_processing"))
4599 {
4600 CYamlNode cliffEdge = root.GetChild("cliff_edge_processing");
4601 if (cliffEdge.HasChild("cliff_edge_smoothing"))
4602 {
4603 string strSmoothing =
4604 cliffEdge.GetChild("cliff_edge_smoothing").GetValue();
4605 if (strSmoothing == "none")
4606 config.SetCliffEdgeSmoothing(0);
4607 else if (strSmoothing == "running_mean")
4608 config.SetCliffEdgeSmoothing(1);
4609 else if (strSmoothing == "savitzky_golay")
4610 config.SetCliffEdgeSmoothing(2);
4611 else
4612 config.SetCliffEdgeSmoothing(
4613 cliffEdge.GetChild("cliff_edge_smoothing").GetIntValue());
4614 }
4615 if (cliffEdge.HasChild("cliff_edge_smoothing_window"))
4617 cliffEdge.GetChild("cliff_edge_smoothing_window").GetIntValue());
4618 if (cliffEdge.HasChild("cliff_edge_polynomial_order"))
4620 cliffEdge.GetChild("cliff_edge_polynomial_order").GetIntValue());
4621 if (cliffEdge.HasChild("cliff_slope_limit"))
4622 config.SetCliffSlopeLimit(
4623 cliffEdge.GetChild("cliff_slope_limit").GetDoubleValue());
4624 }
4625 }
4626 catch (std::exception const &e)
4627 {
4628 cerr << ERR << "Error processing YAML configuration: " << e.what() << endl;
4629 return false;
4630 }
4631
4632 return true;
4633}
4634
4635//===============================================================================================================================
4637//===============================================================================================================================
4639{
4640 string strRec, strErr;
4641 // Case 1: Text output file names, don't change case
4642 m_strRunName = config.GetRunName();
4644 m_strOutFile.append(m_strRunName);
4645 m_strOutFile.append(OUTEXT);
4646
4648 m_strLogFile.append(m_strRunName);
4649 m_strLogFile.append(LOGEXT);
4650
4651 // Case 2: Content of log file (0 = no log file, 1 = least detail, 3 = most
4652 // detail)
4654
4655 // Case 3: Output per-timestep results in CSV format?
4657
4658 // Case 4: Parse start date/time [hh-mm-ss dd/mm/yyyy]
4659 string strStartDateTime = config.GetStartDateTime();
4660 if (! strStartDateTime.empty())
4661 {
4662 vector<string> VstrTmp = VstrSplit(&strStartDateTime, SPACE);
4663 if (VstrTmp.size() >= 2)
4664 {
4665 int nHour, nMin, nSec, nDay, nMonth, nYear;
4666 if (bParseTime(&VstrTmp[0], nHour, nMin, nSec))
4667 {
4668 if (bParseDate(&VstrTmp[1], nDay, nMonth, nYear))
4669 {
4670 m_nSimStartSec = nSec;
4671 m_nSimStartMin = nMin;
4672 m_nSimStartHour = nHour;
4673 m_nSimStartDay = nDay;
4674 m_nSimStartMonth = nMonth;
4675 m_nSimStartYear = nYear;
4676 }
4677 }
4678 }
4679 }
4680
4681 // Case 5: Duration of simulation (in hours, days, months, or years)
4682 string strDuration = config.GetDuration();
4683 if (! strDuration.empty())
4684 {
4685 string strDurationLower = strToLower(&strDuration);
4686 double dDurationMult = dGetTimeMultiplier(&strDurationLower);
4687 if (static_cast<int>(dDurationMult) != TIME_UNKNOWN)
4688 {
4689 // Extract numeric part and multiply
4690 string strNumeric = strDurationLower;
4691 // Remove the unit part to get just the number
4692 if (strNumeric.find("hour") != string::npos)
4693 strNumeric = strNumeric.substr(0, strNumeric.find("hour"));
4694 else if (strNumeric.find("day") != string::npos)
4695 strNumeric = strNumeric.substr(0, strNumeric.find("day"));
4696 else if (strNumeric.find("month") != string::npos)
4697 strNumeric = strNumeric.substr(0, strNumeric.find("month"));
4698 else if (strNumeric.find("year") != string::npos)
4699 strNumeric = strNumeric.substr(0, strNumeric.find("year"));
4700
4701 if (bIsStringValidDouble(strNumeric))
4702 {
4703 m_dSimDuration = strtod(strNumeric.c_str(), NULL) * dDurationMult;
4704 }
4705 }
4706 }
4707
4708 // Case 6: Timestep of simulation (in hours or days)
4709 string strTimestep = config.GetTimestep();
4710 if (! strTimestep.empty())
4711 {
4712 string strTimestepLower = strToLower(&strTimestep);
4713 double dTimestepMult = dGetTimeMultiplier(&strTimestepLower);
4714 if (static_cast<int>(dTimestepMult) != TIME_UNKNOWN)
4715 {
4716 // Extract numeric part and multiply
4717 std::string strNumeric = strTimestepLower;
4718 // Remove the unit part to get just the number
4719 if (strNumeric.find("hour") != string::npos)
4720 strNumeric = strNumeric.substr(0, strNumeric.find("hour"));
4721 else if (strNumeric.find("day") != string::npos)
4722 strNumeric = strNumeric.substr(0, strNumeric.find("day"));
4723 else if (strNumeric.find("month") != string::npos)
4724 strNumeric = strNumeric.substr(0, strNumeric.find("month"));
4725 else if (strNumeric.find("year") != string::npos)
4726 strNumeric = strNumeric.substr(0, strNumeric.find("year"));
4727
4728 if (bIsStringValidDouble(strNumeric))
4729 {
4730 m_dTimeStep = strtod(strNumeric.c_str(), NULL) * dTimestepMult;
4731 }
4732 if (m_dTimeStep <= 0)
4733 strErr =
4734 "timestep of simulation must be > 0";
4735
4737 strErr =
4738 " timestep of simulation must be < the duration of the "
4739 "simulation";
4740 }
4741 }
4742
4743 // Case 7: Save intervals - can handle multiple groups with different units
4744 vector<string> vecSaveTimes = config.GetSaveTimes();
4745 if (! vecSaveTimes.empty())
4746 {
4747 m_nUSave = 0;
4748 m_bSaveRegular = false;
4749
4750 for (string const &strSaveTime : vecSaveTimes)
4751 {
4752 if (strSaveTime.empty())
4753 continue;
4754
4755 string strSaveTimeLower = strToLower(&strSaveTime);
4756
4757 // Get multiplier for time units
4758 double dMult = dGetTimeMultiplier(&strSaveTimeLower);
4759 if (static_cast<int>(dMult) != TIME_UNKNOWN)
4760 {
4761 // Find last space to separate number from unit
4762 size_t nLastSpace = strSaveTimeLower.rfind(SPACE);
4763 if (nLastSpace != string::npos)
4764 {
4765 string strNumbers = strSaveTimeLower.substr(0, nLastSpace);
4766 strNumbers = strTrimRight(&strNumbers);
4767
4768 // Parse numbers (could be multiple space-separated values)
4769 vector<string> VstrNumbers = VstrSplit(&strNumbers, SPACE);
4770 for (string const &strNum : VstrNumbers)
4771 {
4772 if (! strNum.empty()) //&& bIsStringValidDouble(strNum))
4773 {
4774 if (m_nUSave < static_cast<int>(SAVEMAX) - 1)
4775 {
4776 double dValue = strtod(strNum.c_str(), NULL) * dMult;
4777 m_dUSaveTime[m_nUSave++] = dValue;
4778 }
4779 }
4780 }
4781 }
4782 }
4783 }
4784
4785 // Check if we have save times
4786 if (m_nUSave == 1)
4787 {
4788 m_bSaveRegular = true;
4791 }
4792 else if (m_nUSave > 1)
4793 {
4794 // Multiple values - sort them
4796 // Put a dummy save interval as the last entry
4798 }
4799 }
4800
4801 // Case 8: Random number seed(s)
4802 if (config.UseSystemTimeForRandomSeed())
4803 {
4804 // Use system time for random seed
4805 random_device rdev;
4806 m_ulRandSeed[0] = rdev();
4807 // Make all seeds the same
4808 for (int n = 1; n < NUMBER_OF_RNGS; n++)
4809 m_ulRandSeed[n] = m_ulRandSeed[0];
4810 }
4811 else
4812 {
4813 int nSeed = config.GetRandomSeed();
4814 if (nSeed != 0)
4815 {
4816 // Use specified seed
4817 m_ulRandSeed[0] = static_cast<unsigned long>(nSeed);
4818 // Make all seeds the same
4819 for (int n = 1; n < NUMBER_OF_RNGS; n++)
4820 m_ulRandSeed[n] = m_ulRandSeed[0];
4821 }
4822 }
4823
4824 // Case 9: Max save digits for GIS output
4826 if (m_nGISMaxSaveDigits < 2)
4827 strErr = "max save digits for GIS output file names must be > 1";
4828
4829 // Case 10: Save digits mode (sequential vs iteration)
4830 string strSaveDigitsMode = config.GetSaveDigitsMode();
4831 if (! strSaveDigitsMode.empty())
4832 {
4833 string strSaveDigitsLower = strToLower(&strSaveDigitsMode);
4834 if (strSaveDigitsLower.find('s') != string::npos)
4836 else if (strSaveDigitsLower.find('i') != string::npos)
4838 }
4839
4840 // Case 11: Raster GIS files to output
4841 vector<string> rasterFiles = config.GetRasterFiles();
4842 if (! rasterFiles.empty())
4843 {
4844 // Reset all raster output flags
4845 m_bSuspSedSave = false;
4846 m_bAvgSuspSedSave = false;
4847 m_bFineUnconsSedSave = false;
4848 m_bFineConsSedSave = false;
4849 m_bSandUnconsSedSave = false;
4850 m_bSandConsSedSave = false;
4851 m_bCoarseUnconsSedSave = false;
4852 m_bCoarseConsSedSave = false;
4854 m_bTopSurfIncSeaSave = false;
4855 m_bSeaDepthSave = false;
4856 m_bWaveHeightSave = false;
4857 m_bWaveAngleSave = false;
4866 m_bBeachDepositionSave = false;
4868 m_bLandformSave = false;
4869 // m_bLocalSlopeSave = false;
4870 // m_bSlopeSave = false;
4871 // m_bCliffSave = false;
4872 m_bAvgSeaDepthSave = false;
4873 m_bAvgWaveHeightSave = false;
4874 m_bAvgWaveAngleSave = false;
4875 m_bBeachProtectionSave = false;
4876 m_bBasementElevSave = false;
4877 m_bRasterCoastlineSave = false;
4879 m_bActiveZoneSave = false;
4880 m_bCliffCollapseSave = false;
4884 m_bRasterPolygonSave = false;
4886 m_bSeaMaskSave = false;
4887 m_bBeachMaskSave = false;
4888 m_bShadowZoneCodesSave = false;
4894
4895 // Set flags based on raster file codes (Case 11 implementation)
4896 for (string const &rasterCode : rasterFiles)
4897 {
4898 string code = rasterCode;
4899 std::transform(code.begin(), code.end(), code.begin(), ::tolower);
4900
4901 if (code == "suspended_sediment")
4902 m_bSuspSedSave = true;
4903 else if (code == "avg_suspended_sediment")
4904 m_bAvgSuspSedSave = true;
4905 else if (code == "fine_uncons")
4906 m_bFineUnconsSedSave = true;
4907 else if (code == "fine_cons")
4908 m_bFineConsSedSave = true;
4909 else if (code == "sand_uncons")
4910 m_bSandUnconsSedSave = true;
4911 else if (code == "sand_cons")
4912 m_bSandConsSedSave = true;
4913 else if (code == "coarse_uncons")
4915 else if (code == "coarse_cons")
4916 m_bCoarseConsSedSave = true;
4917 else if (code == "sediment_top_elevation")
4919 else if (code == "top_elevation")
4920 m_bTopSurfIncSeaSave = true;
4921 else if (code == "sea_depth")
4922 m_bSeaDepthSave = true;
4923 else if (code == "wave_height")
4924 m_bWaveHeightSave = true;
4925 else if (code == "wave_orientation")
4926 m_bWaveAngleSave = true;
4927 else if (code == "wave_period")
4929 else if (code == "potential_platform_erosion")
4931 else if (code == "actual_platform_erosion")
4933 else if (code == "total_potential_platform_erosion")
4935 else if (code == "total_actual_platform_erosion")
4937 else if (code == "potential_beach_erosion")
4939 else if (code == "actual_beach_erosion")
4941 else if (code == "total_potential_beach_erosion")
4943 else if (code == "total_actual_beach_erosion")
4945 else if (code == "beach_deposition")
4947 else if (code == "total_beach_deposition")
4949 else if (code == "landform")
4950 m_bLandformSave = true;
4951 // else if (code == "local_cons_sediment_slope")
4952 // m_bLocalSlopeSave = true;
4953 // else if (code == "slope")
4954 // m_bSlopeSave = true;
4955 // else if (code == "cliff")
4956 // m_bCliffSave = true;
4957 else if (code == "avg_sea_depth")
4958 m_bAvgSeaDepthSave = true;
4959 else if (code == "avg_wave_height")
4960 m_bAvgWaveHeightSave = true;
4961 else if (code == "avg_wave_orientation")
4962 m_bAvgWaveAngleSave = true;
4963 else if (code == "beach_protection")
4965 else if (code == "basement_elevation")
4966 m_bBasementElevSave = true;
4967 else if (code == "coastline")
4969 else if (code == "coast_normal")
4971 else if (code == "active_zone")
4972 m_bActiveZoneSave = true;
4973 else if (code == "cliff_collapse")
4974 m_bCliffCollapseSave = true;
4975 else if (code == "total_cliff_collapse")
4977 else if (code == "cliff_collapse_deposition")
4979 else if (code == "total_cliff_collapse_deposition")
4981 else if (code == "polygon")
4982 m_bRasterPolygonSave = true;
4983 else if (code == "potential_platform_erosion_mask")
4985 else if (code == "sea_mask")
4986 m_bSeaMaskSave = true;
4987 else if (code == "beach_mask")
4988 m_bBeachMaskSave = true;
4989 else if (code == "shadow_zone_codes")
4991 else if (code == "deep_water_wave_angle")
4993 else if (code == "deep_water_wave_height")
4995 else if (code == "deep_water_wave_period")
4997 else if (code == "polygon_uncons_sediment_up_or_down_drift")
4999 else if (code == "polygon_uncons_sediment_gain_or_loss")
5001 }
5002 }
5003
5004 // Case 12: GIS output format for raster and vector files
5006
5007 // Case 13: If needed, scale GIS raster output values
5009
5010 // Case 14: If needed, also output GIS raster world file
5011 m_bWorldFile = config.GetWorldFile();
5012
5013 // Case 15: Elevations for raster slice output, if desired
5014 if (! config.GetSliceElevations().empty())
5015 {
5016 m_bSliceSave = true;
5018 }
5019
5020 // Case 16: Vector GIS files to output
5021 vector<string> vectorFiles = config.GetVectorFiles();
5022 if (! vectorFiles.empty())
5023 {
5024 // Reset all vector output flags
5025 m_bCoastSave = false;
5026 m_bCliffEdgeSave = false;
5028 m_bNormalsSave = false;
5029 m_bInvalidNormalsSave = false;
5032 m_bMeanWaveEnergySave = false;
5034 m_bCoastCurvatureSave = false;
5035 m_bPolygonNodeSave = false;
5036 m_bPolygonBoundarySave = false;
5037 m_bCliffNotchSave = false;
5038 m_bShadowBoundarySave = false;
5041 m_bWaveSetupSave = false;
5042 m_bStormSurgeSave = false;
5043 m_bRunUpSave = false;
5045
5046 // Set flags based on vector file codes (Case 16 implementation)
5047 for (string const &vectorCode : vectorFiles)
5048 {
5049 string code = vectorCode;
5050 std::transform(code.begin(), code.end(), code.begin(), ::tolower);
5051
5052 if (code == "coast")
5053 m_bCoastSave = true;
5054 else if (code == "cliff_edge")
5055 m_bCliffEdgeSave = true;
5056 else if (code == "wave_angle")
5058 else if (code == "normals")
5059 m_bNormalsSave = true;
5060 else if (code == "invalid_normals")
5061 m_bInvalidNormalsSave = true;
5062 else if (code == "avg_wave_angle")
5064 else if (code == "wave_energy")
5066 else if (code == "mean_wave_energy")
5067 m_bMeanWaveEnergySave = true;
5068 else if (code == "breaking_wave_height")
5070 else if (code == "coast_curvature")
5071 m_bCoastCurvatureSave = true;
5072 else if (code == "polygon_node")
5073 m_bPolygonNodeSave = true;
5074 else if (code == "polygon")
5076 else if (code == "cliff_notch")
5077 m_bCliffNotchSave = true;
5078 else if (code == "wave_transect_points")
5080 else if (code == "shadow_boundary")
5081 m_bShadowBoundarySave = true;
5082 else if (code == "downdrift_boundary")
5084 else if (code == "deep_water_wave_angle")
5086 else if (code == "wave_setup")
5087 m_bWaveSetupSave = true;
5088 else if (code == "storm_surge")
5089 m_bStormSurgeSave = true;
5090 else if (code == "run_up")
5091 m_bRunUpSave = true;
5092 else if (code == "flood_line")
5094 }
5095 }
5096
5097 // Case 17: Vector GIS output format (note must retain original case)
5099
5100 // Case 18: Time series files to output
5101 // TODO: Migrate from bReadRunDataFile()
5102 vector<string> timeseriesFiles = config.GetTimeSeriesFiles();
5103 if (! timeseriesFiles.empty())
5104 {
5105 for (string const &timeseriesCode : timeseriesFiles)
5106 {
5107 string code = timeseriesCode;
5108 std::transform(code.begin(), code.end(), code.begin(), ::tolower);
5109
5110 if (code == "sea_area")
5111 m_bSeaAreaTSSave = true;
5112 if (code == "water_level")
5113 m_bSWLTSSave = true;
5114 if (code == "platform_erosion")
5116 if (code == "cliff_collapse_erosion")
5118 if (code == "cliff_collapse_deposition")
5120 if (code == "cliff_collapse_net")
5122 if (code == "beach_erosion")
5123 m_bBeachErosionTSSave = true;
5124 if (code == "beach_deposition")
5126 if (code == "beach_change_net")
5128 if (code == "suspended")
5129 m_bSuspSedTSSave = true;
5130 if (code == "suspended")
5131 m_bSuspSedTSSave = true;
5132 if (code == "wave_setup")
5134 if (code == "wave_runup")
5136 if (code == "cliff_notch")
5138 }
5139 }
5140
5141 // Case 19: Vector coastline smoothing algorithm: 0 = none, 1 = running mean,
5142 // 2 = Savitzky-Golay
5144
5145 // Case 20: Size of coastline smoothing window: must be odd
5147
5148 // Case 21: Order of coastline profile smoothing polynomial for
5149 // Savitzky-Golay: usually 2 or 4, max is 6
5151
5152 // Case 22: Omit grid edges from search (north/south/east/west)
5153 std::string strRH = config.GetOmitGridEdges();
5154 if (strRH.find('n') != string::npos)
5155 {
5157 }
5158
5159 if (strRH.find('s') != string::npos)
5160 {
5162 }
5163
5164 if (strRH.find('w') != string::npos)
5165 {
5166 m_bOmitSearchWestEdge = true;
5167 }
5168
5169 if (strRH.find('e') != string::npos)
5170 {
5171 m_bOmitSearchEastEdge = true;
5172 }
5173
5174 // Case 23: Profile slope running-mean smoothing window size: must be odd
5176
5177 // Case 24: Max local slope (m/m), first check that this is a valid double
5179
5180 // Case 25: Maximum elevation of beach above SWL, first check that this is a
5181 // valid double
5183
5184 // Case 26: Number of sediment layers
5185 m_nLayers = config.GetNumLayers();
5186 // OK we know the number of layers, so add elements to these vectors
5187 for (int j = 0; j < m_nLayers; j++)
5188 {
5195 m_VstrGDALIUFDriverCode.push_back("");
5196 m_VstrGDALIUFDriverDesc.push_back("");
5197 m_VstrGDALIUFProjection.push_back("");
5198 m_VstrGDALIUFDataType.push_back("");
5199 m_VstrGDALIUSDriverCode.push_back("");
5200 m_VstrGDALIUSDriverDesc.push_back("");
5201 m_VstrGDALIUSProjection.push_back("");
5202 m_VstrGDALIUSDataType.push_back("");
5203 m_VstrGDALIUCDriverCode.push_back("");
5204 m_VstrGDALIUCDriverDesc.push_back("");
5205 m_VstrGDALIUCProjection.push_back("");
5206 m_VstrGDALIUCDataType.push_back("");
5207 m_VstrGDALICFDriverCode.push_back("");
5208 m_VstrGDALICFDriverDesc.push_back("");
5209 m_VstrGDALICFProjection.push_back("");
5210 m_VstrGDALICFDataType.push_back("");
5211 m_VstrGDALICSDriverCode.push_back("");
5212 m_VstrGDALICSDriverDesc.push_back("");
5213 m_VstrGDALICSProjection.push_back("");
5214 m_VstrGDALICSDataType.push_back("");
5215 m_VstrGDALICCDriverCode.push_back("");
5216 m_VstrGDALICCDriverDesc.push_back("");
5217 m_VstrGDALICCProjection.push_back("");
5218 m_VstrGDALICCDataType.push_back("");
5219 }
5220
5221 // Case 27: Basement DEM file (can be blank)
5223
5224 // Cases 28: Initial sediment thickness files (unconsolidated and
5225 // consolidated)
5227 m_bHaveFineSediment = true;
5229 m_bHaveSandSediment = true;
5231 m_bHaveCoarseSediment = true;
5234 m_bHaveFineSediment = true;
5236 m_bHaveSandSediment = true;
5238 m_bHaveCoarseSediment = true;
5239
5240 // Case 29: Initial suspended sediment depth GIS file (can be blank)
5241 string strSuspendedSed = config.GetSuspendedSedFile();
5242 if (! strSuspendedSed.empty())
5243 {
5244 m_strInitialSuspSedimentFile = strSuspendedSed;
5245 }
5246
5247 // Case 30: Basic simulation input files
5249
5250 // Case 31: Initial Intervention class GIS file
5251 // (can be blank: if so then intervention height file must also be blank)
5252 string strInterventionClass = config.GetInterventionClassFile();
5253 if (! strInterventionClass.empty())
5254 m_strInterventionClassFile = strInterventionClass;
5255
5256 // Case 32: Initial Intervention height GIS file
5257 // (can be blank: if so then intervention class file must also be blank)
5258 string strInterventionHeight = config.GetInterventionHeightFile();
5259 if (! strInterventionHeight.empty())
5260 m_strInterventionHeightFile = strInterventionHeight;
5261
5262 // Case 33: Wave propagation model [0 = COVE, 1 = CShore]
5264
5265 // Case 34: Density of sea water (kg/m3), first check that this is a valid
5266 // double
5268
5269 // Case 35: Initial mean still water level (m), first check that this is a
5270 // valid double TODO 041 Make this a per-timestep SWL file
5272
5273 // Case 36: Final water level (optional)
5274 if (config.HasFinalWaterLevel())
5275 {
5276 if (! strInterventionHeight.empty())
5277 {
5279 }
5280 else
5281 {
5283 }
5284 }
5285 // Case 38-40 Parse Wave Data
5286 // Case 38: Deep water wave height (m) or a file of point vectors giving deep
5287 // Firstly has the user provided a filepath for wave data
5288 if (config.GetWaveHeightTimeSeries().empty())
5289 {
5291 m_bHaveWaveStationData = false;
5292 // Case 37: Deep water wave height (m) or a file of point vectors giving deep
5293 // water wave height (m) and orientation (for units, see below)
5295
5296 // Case 39: Deep water wave orientation in input CRS: this is the
5297 // oceanographic convention i.e. direction TOWARDS which the waves move (in
5298 // degrees clockwise from north)
5300
5301 // Case 40: Wave period (sec)
5303 }
5304 else
5305 {
5308 // m_dAllCellsDeepWaterWaveHeight = config.GetDeepWaterWaveHeight();
5310 }
5311
5312 // Case 41: Tide data file (can be blank). This is the change (m) from still
5313 // water level for each timestep
5315
5316 // Case 42: Breaking wave height-to-depth ratio, check that this is a valid
5317 // double
5319
5320 // Case 43: Simulate coast platform erosion?
5322
5323 // Case 44: If simulating coast platform erosion, R (coast platform resistance
5324 // to erosion) values along profile, see Walkden & Hall, 2011
5326 {
5328 }
5329
5330 // Case 45: Simulate beach sediment transport?
5332
5333 // Case 46: If simulating beach sediment transport, beach sediment transport
5334 // at grid edges [0 = closed, 1 = open, 2 = re-circulate]
5336
5337 // Case 47: If simulating beach sediment transport, beach erosion/deposition
5338 // equation [0 = CERC, 1 = Kamphuis]
5340
5341 // Case 48: Median size of fine sediment (mm), always needed [0 = default,
5342 // only for Kamphuis eqn]. First check that this is a valid double
5343 m_dD50Fine = config.GetFineMedianSize();
5344
5345 // Case 49: Median size of sand sediment (mm), always needed [0 = default,
5346 // only for Kamphuis eqn]. First check that this is a valid double
5347 m_dD50Sand = config.GetSandMedianSize();
5348
5349 // Case 50: Median size of coarse sediment (mm), always needed [0 = default,
5350 // only for Kamphuis eqn]. First check that this is a valid double
5352
5353 // Case 51: Density of unconsolidated beach sediment (kg/m3)
5355
5356 // Case 52: Beach sediment porosity
5358
5359 // Case 53: Relative erodibility (0 - 1) of fine-sized sediment, always
5360 // needed. First check that this is a valid double
5362
5363 // Case 54: Relative erodibility (0 - 1) of sand-sized sediment, always
5364 // needed. First check that this is a valid double
5366
5367 // Case 55: Relative erodibility (0 - 1) of coarse-sized sediment, always
5368 // needed. First check that this is a valid double
5370
5371 // Case 56: Transport parameter KLS in CERC equation
5372 m_dKLS = config.GetTransportKLS();
5373
5374 // Case 57: Transport parameter for Kamphuis equation
5375 m_dKamphuis = config.GetKamphuis();
5376
5377 // Case 58: Berm height i.e. height above SWL of start of depositional Dean
5378 // profile
5380
5381 // Case 59: Simulate cliff collapse?
5383
5384 // Case 60: Cliff resistance to erosion
5386 {
5388 }
5389
5390 // Case 61: Notch overhang at collapse (m)
5392 {
5394 }
5395
5396 // Case 62: Notch base below still water level (m)
5398 {
5400 }
5401
5402 // Case 63: Scale parameter A for cliff deposition (m^(1/3)) [0 = auto]
5404 {
5406 }
5407
5408 // Case 64: Approximate planview width of cliff collapse talus (in m)
5410 {
5412 }
5413
5414 // Case 65: Planview length of cliff deposition talus (m)
5416 {
5418 }
5419
5420 // Case 66: Minimum height of landward end of talus, as a fraction of cliff
5421 // elevation
5423 {
5425 }
5426
5427 // Case 67: Simulate riverine flooding?
5428 if (config.GetFloodInput())
5429 {
5430 m_bRiverineFlooding = true;
5434 }
5435
5436 // Case 68: Output riverine flooding vector files
5437 if (config.GetFloodInput())
5438 {
5439 // TODO: This is a guess, please check
5440 vector<string> floodFiles = config.GetFloodFiles();
5441 if (! floodFiles.empty())
5442 {
5443 for (string const &floodCode : floodFiles)
5444 {
5445 string code = floodCode;
5446 std::transform(code.begin(), code.end(), code.begin(), ::tolower);
5447
5448 if (code == "sea_area")
5449 m_bSeaAreaTSSave = true;
5450 }
5451 }
5452 }
5453
5454 // Case 69: Flooding runup equation?
5455 if (config.GetFloodInput())
5456 {
5457 // TODO: This is a guess, please check
5459 }
5460
5461 // Case 70: Somthing unknown relating to riverine flooding
5463 {
5464 // TODO: This is a guess, please check
5465 m_bFloodLocationSave = ! config.GetFloodInputLocation().empty();
5466 }
5467
5468 // Case 71: Somthing unknown relating to riverine flooding
5470 {
5471 // TODO: This is a guess, please check
5473 }
5474
5475 // Case 72: Simulate sediment input?
5476 if (config.GetSedimentInput())
5477 {
5478 m_bSedimentInput = true;
5480 }
5481
5482 // Case 73: Sediment input location (point or line shapefile)
5483 if (m_bSedimentInput)
5484 {
5486 }
5487
5488 // Case 74: Sediment input type: required if have shapefile [P = Point, C =
5489 // coast block, L = line]
5490 if (m_bSedimentInput)
5491 {
5492 strRH = config.GetSedimentInputType();
5493 if (strRH.find('p') != string::npos)
5495
5496 else if (strRH.find('c') != string::npos)
5498
5499 else if (strRH.find('l') != string::npos)
5501 }
5502
5503 // Case 75: Sediment input details file (required if have shapefile)
5504 if (m_bSedimentInput)
5505 {
5507 }
5508
5509 // Case 76: Gravitational acceleration (m2/s). First check that this is a
5510 // valid double
5512
5513 // Case 77: Spacing of coastline normals (m)
5517 DEFAULT_PROFILE_SPACING; // In cells, we will set
5518 // m_dCoastNormalSpacing later when we
5519 // know m_dCellSide
5520
5521 // Case 78: Random factor for spacing of normals [0 to 1, 0 = deterministic],
5522 // check that this is a valid double
5524
5525 // Case 79: Length of coastline normals (m), check that this is a valid double
5527
5528 // Approximate minimum spacing (m) between wave transects for interpolation densification
5530
5531 // Case 80: Start depth for wave calcs (ratio to deep water wave height)check
5532 // that this is a valid double
5534
5535 // Case 81: Output profile data?
5536 // ISSUE: Why are we now only outputing consolidated, this feels like a bodge
5538
5539 // Case 82: Numbers of profiles to be saved
5541 {
5543 }
5544
5545 // Case 83: Timesteps to save profiles
5547 {
5549 }
5550
5551 // Case 84: Output parallel profile data?
5553
5554 // Case 85: Output erosion potential look-up data?
5556
5557 // Case 86: Cliff toe location? approach [0 = none, 1 = by slope threshold]
5558 //TODO: Finish migration
5559 m_bCliffToeLocate = false;
5560
5561 // Case 87: Cliff edge smoothing algorithm: 0 = none, 1 = running mean, 2 =
5562 // Savitzky-Golay
5564
5565 // Case 89: Size of moving window for coastline curvature calculation (must be
5566 // odd)
5568
5569 // Case 90: Cliff slope limit for cliff toe detection
5571
5572 return true;
5573}
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
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
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)
double GetSyntheticTransectSpacing() const
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 SetWaveInputMode(string const &str)
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)
void SetSyntheticTransectSpacing(double d)
int GetNumLayers() const
Class used to represent a sediment input event.
double m_dCliffDepositionPlanviewWidth
Planview width of cliff collapse talus (m)
Definition simulation.h:939
bool m_bCliffCollapseSave
Save cliff collapse raster GIS files?
Definition simulation.h:216
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:588
bool m_bAvgSeaDepthSave
Save average sea depth raster GIS files?
Definition simulation.h:105
bool m_bCliffToeLocate
Cliff to location?
Definition simulation.h:462
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:768
bool m_bDeepWaterWaveAngleSave
Save deep water wave angle raster GIS files?
Definition simulation.h:243
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:516
double m_dSyntheticTransectSpacing
Approximate minimum spacing (m) between wave transects (real and synthetic) for wave interpolation de...
Definition simulation.h:843
string m_strInitialSuspSedimentFile
Name of initial suspended sediment file.
bool m_bSlopeConsSedSave
Save slope of consolidated sediment raster GIS files?
Definition simulation.h:174
vector< double > m_VdTSDeepWaterWaveStationPeriod
Time series of wave period at deep water wave station.
bool m_bFineUnconsSedSave
Save fine unconsolidated sediment raster GIS files?
Definition simulation.h:189
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:456
bool m_bFloodSWLSetupSurgeLine
Are we saving the flood still water level setup surge line? TODO 007 Finish surge and runup stuff.
Definition simulation.h:441
string m_strCMEIni
Folder for the CME .ini file.
bool m_bSedimentInputAtPoint
Do we have sediment inputat a point?
Definition simulation.h:396
double m_dG
Gravitational acceleration (m**2/sec)
Definition simulation.h:825
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:543
bool m_bCoastSave
Save coastline as vector GIS file?
Definition simulation.h:261
bool m_bBeachDepositionTSSave
Save the beach (unconsolidated sediment) deposition time series file?
Definition simulation.h:315
static string strRemoveSubstr(string *, string const *)
Returns a string with a substring removed, and with whitespace trimmed.
Definition utils.cpp:2559
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:2865
double m_dWaveDataWrapHours
Number of hours after which deep water wave data wraps.
Definition simulation.h:984
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:780
bool m_bFloodSetupSurgeRunupTSSave
Save the flood setup surge runup time series file? TODO 007 Finish surge and runup stuff.
Definition simulation.h:327
bool m_bTopSurfIncSeaSave
Save top surface (sediment, talus, and sea) raster DEMs?
Definition simulation.h:87
vector< string > m_VstrGDALICCDriverCode
GDAL driver code for the initial consolidated coarse sediment GIS data.
bool m_bSedIncTalusTopSurfSave
Save sediment (inc talus) top surface raster DEMs?
Definition simulation.h:84
double m_dCoastNormalLength
Length of the coastline-normal profiles, in m.
Definition simulation.h:840
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:387
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:123
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:117
int nReadWaveStationInputFile(int const)
bool m_bCliffEdgeSave
Save cliff edge vector GIS files?
Definition simulation.h:264
bool m_bInvalidNormalsSave
Save invalid coastline-normal vector GIS files?
Definition simulation.h:270
bool m_bShadowBoundarySave
Save wave shadow boundary vector GIS files?
Definition simulation.h:288
int nDoSimulationTimeMultiplier(string const *)
Given a string containing time units, this sets up the appropriate multiplier and display units for t...
Definition utils.cpp:411
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:156
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_bRunUpSave
Are we saving runup? TODO 007 Finish surge and runup stuff.
Definition simulation.h:420
bool m_bWaveTransectPointsSave
Save wave transect points vector GIS files?
Definition simulation.h:285
bool m_bYamlInputFormat
Use YAML format for input datafile instead of .dat format?
Definition simulation.h:348
bool m_bCliffCollapseDepositionSave
Save cliff collapse deposition raster GIS files?
Definition simulation.h:222
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:150
static string strTrimLeft(string const *)
Trims whitespace from the left side of a string, does not change the original string.
Definition utils.cpp:2479
bool m_bPolygonUnconsSedUpOrDownDriftSave
Save polygon unconsolidated sediment up- or down-drift raster GIS files?
Definition simulation.h:252
double m_dCoarseErodibility
The relative erodibility (0-1) of coarse unconsolidated beach sediment.
Definition simulation.h:807
double m_dCliffTalusMinDepositionLength
Planview length of cliff deposition talus (m)
Definition simulation.h:942
string m_strVectorGISOutFormat
Vector GIS output format.
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.
double m_dNotchIncisionAtCollapse
Notch overhang (i.e. length of horizontal incision at the apex elevation) to initiate collapse (m)
Definition simulation.h:927
int m_nUnconsSedimentHandlingAtGridEdges
How sediment which moves off an edge of the grid is handled. Possible values are GRID_EDGE_CLOSED,...
Definition simulation.h:540
double m_dSandErodibility
The relative erodibility (0-1) of sand unconsolidated beach sediment.
Definition simulation.h:804
bool m_bBasementElevSave
Save basement raster DEMs?
Definition simulation.h:81
int m_nSimStartHour
Start time of the simulation (hours)
Definition simulation.h:573
bool m_bCoarseUnconsSedSave
Save coarse unconsolidated sediment raster GIS files?
Definition simulation.h:195
bool m_bSuspSedTSSave
Save the suspended sediment time series file?
Definition simulation.h:321
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:309
bool m_bPotentialPlatformErosionMaskSave
Save potential platform erosion mask raster GIS files?
Definition simulation.h:231
vector< string > m_VstrGDALICSDriverCode
GDAL driver code for the initial consolidated sand sediment GIS data.
bool m_bFloodLocationSave
Are we saving the flood location? TODO 007 Finish surge and runup stuff.
Definition simulation.h:435
double m_dWaveDepthRatioForWaveCalcs
Start depth for wave calculations.
Definition simulation.h:762
bool m_bWaveHeightSave
Save wave height raster GIS files?
Definition simulation.h:108
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:171
static string strTrim(string const *)
Trims whitespace from both sides of a string, does not change the original string.
Definition utils.cpp:2514
string m_strRasterGISOutFormat
Raster GIS output format.
bool m_bTotalBeachDepositionSave
Save total beach (unconsolidated sediment) deposition raster GIS files?
Definition simulation.h:168
double m_dBeachSedimentPorosity
The porosity of unconsolidated beach sediment (0-1)
Definition simulation.h:798
int m_nSimStartSec
Start time of the simulation (seconds)
Definition simulation.h:567
int m_nSimStartDay
Start date of the simulation (day)
Definition simulation.h:576
bool m_bSandUnconsSedSave
Save sand unconsolidated sediment raster GIS files?
Definition simulation.h:192
bool m_bActualPlatformErosionTSSave
Save the actual (supply-limited) shore platform erosion time series file?
Definition simulation.h:300
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:2926
int m_nCoastNormalSpacing
Average spacing between coastline normals, measured in cells.
Definition simulation.h:507
bool m_bTotCliffCollapseSave
Save total cliff collapse raster GIS files?
Definition simulation.h:219
int nReadShapeFunctionFile(void)
bool m_bDoShorePlatformErosion
Simulate shore platform erosion?
Definition simulation.h:363
bool m_bSliceSave
Save slices?
Definition simulation.h:99
bool m_bRasterPolygonSave
Save raster polygon raster GIS files?
Definition simulation.h:228
double m_dInitialMeanSWL
The start-of-simulation still water level (m)
Definition simulation.h:717
bool m_bBeachDepositionSave
Save beach (unconsolidated sediment) deposition raster GIS files?
Definition simulation.h:165
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:258
int m_nLayers
The number of sediment layers.
Definition simulation.h:483
int m_nCoastSmoothingWindowSize
The size of the window used for coast smoothing. Must be an odd number.
Definition simulation.h:489
bool m_bSedimentInputAlongLine
Do we have sediment input along a line?
Definition simulation.h:402
bool m_bSedimentInput
Do we have sediment input events?
Definition simulation.h:393
bool m_bFloodSWLSetupSurgeRunupLineSave
Are we saving the flood still water level setup surge runup line? TODO 007 Finish surge and runup stu...
Definition simulation.h:450
bool m_bNormalsSave
Save coastline-normal vector GIS files?
Definition simulation.h:267
bool m_bAvgWaveHeightSave
Save wave height raster GIS files?
Definition simulation.h:111
static string strToLower(string const *)
Returns the lower case version of an string, leaving the original unchanged.
Definition utils.cpp:2539
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:75
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:522
double m_dDeanProfileStartAboveSWL
Berm height i.e. height above SWL of start of depositional Dean profile.
Definition simulation.h:975
int m_nSavGolCoastPoly
The order of the coastline profile smoothing polynomial if Savitzky-Golay smoothing is used (usually ...
Definition simulation.h:492
bool m_bSeaDepthSave
Save sea depth raster GIS files?
Definition simulation.h:102
bool m_bWaveAngleAndHeightSave
Save wave angle and wave height raster GIS files?
Definition simulation.h:120
string m_strInitialBasementDEMFile
Name of initial basement DEM file.
int m_nRunUpEquation
The run-up equation used TODO 007 Finish surge and runup stuff.
Definition simulation.h:591
bool m_bWorldFile
Write a GIS World file?
Definition simulation.h:384
static string strTrimRight(string const *)
Trims whitespace from the right side of a string, does not change the original string.
Definition utils.cpp:2494
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:909
double m_dFineErodibility
The relative erodibility (0-1) of fine unconsolidated beach sediment.
Definition simulation.h:801
double m_dBreakingWaveHeightDepthRatio
Breaking wave height-to-depth ratio.
Definition simulation.h:765
double m_dCoastNormalSpacing
Average spacing of the coastline-normal profiles, in m.
Definition simulation.h:834
bool m_bHaveWaveStationData
Do we have wave station data?
Definition simulation.h:390
double m_dSeaWaterDensity
Density of sea water in kg/m**3.
Definition simulation.h:714
bool m_bSlopeSaveForCliffToe
Save slope raster grids (used for cliff toe location)?
Definition simulation.h:93
int m_nSavGolCliffEdgePoly
The order of the cliff edge smoothing polynomial if Savitzky-Golay smoothing is used (usually 2 or 4,...
Definition simulation.h:501
double m_dR
Coast platform resistance to erosion R, see Walkden & Hall, 2011.
Definition simulation.h:783
bool m_bCliffCollapseTimestepSave
Are we saving the timestep at which each cliff occurred?
Definition simulation.h:447
bool m_bRasterNormalProfileSave
Save rasterized coastline-normal profiles GIS files?
Definition simulation.h:210
bool m_bActiveZoneSave
Save active zone raster GIS files?
Definition simulation.h:213
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:357
bool m_bSedimentInputAtCoast
Do we have sediment input at the coast?
Definition simulation.h:399
int m_nCliffEdgeSmooth
Which method to use for cliff edge smoothing.
Definition simulation.h:495
double m_dCliffErosionResistance
Resistance of cliff to notch erosion.
Definition simulation.h:924
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:789
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:246
double m_dSlopeThresholdForCliffToe
Slope limit for cliff toe detection.
bool m_bMeanWaveEnergySave
Save mean wave energy raster GIS files?
Definition simulation.h:132
bool m_bCliffToeSave
Save cliff toe raster grids?
Definition simulation.h:96
double m_dKLS
Transport parameter KLS in the CERC equation.
Definition simulation.h:819
int m_nWavePropagationModel
The wave propagation model used. Possible values are WAVE_MODEL_CSHORE and WAVE_MODEL_COVE.
Definition simulation.h:564
double m_dAllCellsDeepWaterWaveAngle
Deep water wave angle for all sea cells.
Definition simulation.h:771
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:376
bool m_bCoastCurvatureSave
Save coastline-curvature vector GIS files?
Definition simulation.h:273
int m_nCliffEdgeSmoothWindow
The size of the window used for cliff edge smoothing. Must be an odd number.
Definition simulation.h:498
int m_nDeepWaterWaveDataNumTimeSteps
The duration of data for deep water waves, expressed as a number of timesteps.
Definition simulation.h:585
double m_dFinalMeanSWL
The end-of-simulation still water (m), is same as m_dInitialMeanSWL unless SWL changes.
Definition simulation.h:720
bool m_bRasterWaveFloodLineSave
Are we saving the raster wave flood line? TODO 007 Finish surge and runup stuff.
Definition simulation.h:429
bool m_bSWLTSSave
Save the SWL (still water level) time series file?
Definition simulation.h:297
bool m_bBreakingWaveHeightSave
Save breaking wave height raster GIS files?
Definition simulation.h:135
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:696
bool m_bPolygonNodeSave
Save polygon node vector GIS files?
Definition simulation.h:276
bool m_bOmitSearchNorthEdge
Omit the north edge of the grid from coast-end searches?
Definition simulation.h:351
bool m_bFloodSetupSurgeTSSave
Save the flood setup surge time series file? TODO 007 Finish surge and runup stuff.
Definition simulation.h:324
bool m_bTotalPotentialPlatformErosionSave
Save total potential shore platform erosion raster GIS files?
Definition simulation.h:147
bool m_bSetupSurgeFloodMaskSave
Are we saving the setup surge flood mask? TODO 007 Finish surge and runup stuff.
Definition simulation.h:423
bool m_bWaveEnergySinceCollapseSave
Save wave energy since cliff collapse raster GIS files?
Definition simulation.h:129
double m_dD50Coarse
The D50 for coarse sediment.
Definition simulation.h:792
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:153
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:2804
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:453
int m_nSimStartMonth
Start date of the simulation (month)
Definition simulation.h:579
bool m_bSuspSedSave
Save suspended sediment raster GIS files?
Definition simulation.h:183
double m_dMinCliffTalusHeightFrac
Minimum height of the landward end of cliff collapse talus, as a fraction of cliff elevation.
Definition simulation.h:945
vector< string > m_VstrGDALIUSDriverDesc
GDAL driver description for the initial unconsolidated sand sediment GIS data.
bool m_bPolygonBoundarySave
Save polygon boundary vector GIS files?
Definition simulation.h:279
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 Finish surge and runup stuff.
Definition simulation.h:417
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:144
double m_dNotchApexAboveMHW
Distance of notch base below SWL (m)
Definition simulation.h:933
int m_nSimStartMin
Start time of the simulation (minutes)
Definition simulation.h:570
bool bReadIniFile(void)
The bReadIniFile member function reads the initialisation file.
bool m_bHaveFineSediment
Does this simulation consider fine-sized sediment?
Definition simulation.h:72
double m_dCliffDepositionA
Scale parameter A for cliff deposition (m^(1/3)), may be zero for auto-calculation.
Definition simulation.h:936
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:312
vector< string > m_VstrGDALICFDriverDesc
GDAL driver description for the initial consolidated fine sediment GIS data.
string m_strTideDataFile
Name of tide data file.
vector< string > m_VstrGDALIUFDriverDesc
GDAL driver description for the initial unconsolidated fine sediment GIS data.
bool m_bTotalPotentialBeachErosionSave
Save total potential beach (unconsolidated sediment) erosion raster GIS files?
Definition simulation.h:159
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_bSeaMaskSave
Save sea mask raster GIS files?
Definition simulation.h:234
bool m_bInterventionClassSave
Save intervention class raster GIS files?
Definition simulation.h:177
int m_nSimStartYear
Start date of the simulation (year)
Definition simulation.h:582
bool m_bTotalActualBeachErosionSave
Save total actual (supply-limited) beach (unconsolidated sediment) erosion raster GIS files?
Definition simulation.h:162
bool m_bRasterCoastlineSave
Save rasterized coastline GIS files?
Definition simulation.h:207
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:2459
bool m_bInterventionHeightSave
Save intervention height raster GIS files?
Definition simulation.h:180
bool m_bRiverineFlooding
Are we doing riverine flooding?
Definition simulation.h:411
bool m_bSandConsSedSave
Save sand consolidated sediment raster GIS files?
Definition simulation.h:201
bool m_bSedimentInputEventSave
Save sediment inut data?
Definition simulation.h:405
bool m_bHaveCoarseSediment
Does this simulation consider coarse-sized sediment?
Definition simulation.h:78
double m_dRegularSaveInterval
The interval between regular saves, in hours.
Definition simulation.h:699
bool m_bPolygonUnconsSedGainOrLossSave
Save polygon unconsolidated sediment gain or loss raster GIS files?
Definition simulation.h:255
double m_dTimeStep
The length of an iteration (a timestep) in hours.
Definition simulation.h:690
bool m_bCliffCollapseDepositionTSSave
Save the cliff collapse deposition time series file?
Definition simulation.h:306
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:126
double m_dCoastNormalRandSpacingFactor
Random factor for spacing of along-coast normals.
Definition simulation.h:972
double m_dMaxUserInputWaveHeight
Maximum deep water wave height.
Definition simulation.h:777
vector< double > m_VdSliceElev
Elevations for raster slice output.
bool m_bOutputConsolidatedProfileData
Output profile data?
Definition simulation.h:336
bool m_bBeachProtectionSave
Save beach protection raster GIS files>
Definition simulation.h:138
bool m_bDoBeachSedimentTransport
Simulate unconsolidated sediment (beach) transport?
Definition simulation.h:369
bool m_bFineConsSedSave
Save fine consolidated sediment raster GIS files?
Definition simulation.h:198
bool m_bShadowDowndriftBoundarySave
Save wave shadow downdrift boundary vector GIS files?
Definition simulation.h:291
bool m_bCliffNotchElevTSSave
Save the cliff notch elevation time series file?
Definition simulation.h:330
int m_nCoastSmooth
Which method to use for coast smoothing.
Definition simulation.h:486
bool m_bDeepWaterWavePeriodSave
Save deep water wave period raster GIS files?
Definition simulation.h:249
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:318
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:204
bool m_bSeaAreaTSSave
Save the sea area time series file?
Definition simulation.h:294
bool m_bScaleRasterOutput
Scale raster output?
Definition simulation.h:381
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:786
unsigned long m_ulRandSeed[NUMBER_OF_RNGS]
A seed for each of the random number generators.
Definition simulation.h:615
bool m_bOmitSearchSouthEdge
Omit the south edge of the grid from coast-end searches?
Definition simulation.h:354
bool m_bBeachMaskSave
Save beach mask raster GIS files?
Definition simulation.h:237
bool m_bAvgSuspSedSave
Save average suspended sediment raster GIS files?
Definition simulation.h:186
double m_dBeachSedimentDensity
The density of unconsolidated beach sediment (kg/m**3)
Definition simulation.h:795
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:687
bool m_bTalusSave
Save talus depth?
Definition simulation.h:90
bool m_bCSVPerTimestepResults
Output per-timestep results in CSV format instead of fixed-width?
Definition simulation.h:345
bool m_bCliffNotchAllSave
Are we saving all cliff notches?
Definition simulation.h:444
vector< double > m_VdThisIterDeepWaterWaveStationAngle
This-iteration wave orientation at deep water wave station.
vector< string > m_VstrGDALIUCDriverDesc
GDAL driver description for the initial unconsolidated coarse sediment GIS data.
double m_dMaxBeachElevAboveSWL
Maximum elevation of beach above SWL (m)
Definition simulation.h:921
bool m_bTotCliffCollapseDepositionSave
Save total cliff collapse deposition raster GIS files?
Definition simulation.h:225
double m_dAllCellsDeepWaterWavePeriod
Deep water wave period for all sea cells.
Definition simulation.h:774
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:702
double m_dProfileMaxSlope
Maximum slope on coastline-normal profiles.
Definition simulation.h:918
int m_nProfileSmoothWindow
The size of the window used for running-mean coast-normal profile smoothing (must be odd)
Definition simulation.h:504
bool m_bDoCliffCollapse
Simulate cliff collapse?
Definition simulation.h:366
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 Finish surge and runup stuff.
Definition simulation.h:426
bool m_bWaveSetupSave
Are we saving the wave setup? TODO 007 Finish surge and runup stuff.
Definition simulation.h:414
vector< CRWSedInputEvent * > m_pVSedInputEvent
Sediment input events.
bool m_bFloodSWLSetupLineSave
Are we saving the flood still water level setup line? TODO 007 Finish surge and runup stuff.
Definition simulation.h:438
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:240
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:303
bool m_bPotentialPlatformErosionSave
Save potential shore platform erosion raster GIS files?
Definition simulation.h:141
double m_dDurationUnitsMult
Multiplier for duration units, to convert to hours.
Definition simulation.h:654
bool m_bOutputParallelProfileData
Output parallel profile data?
Definition simulation.h:339
double m_dKamphuis
Transport parameter for the Kamphuis equation.
Definition simulation.h:822
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:2580
bool m_bOutputErosionPotentialData
Output erosion potential data?
Definition simulation.h:342
bool m_bCliffNotchSave
Save cliff notch incision depth vector GIS files?
Definition simulation.h:282
bool m_bVectorWaveFloodLineSave
Are we saving the vector wave flood line? TODO 007 Finish surge and runup stuff.
Definition simulation.h:432
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:114
bool m_bOmitSearchEastEdge
Omit the east edge of the grid from coast-end searches?
Definition simulation.h:360
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:71
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:1068
string const TIME_SERIES_CLIFF_COLLAPSE_DEPOSITION_CODE
Definition cme.h:1133
string const TIME_SERIES_SUSPENDED_SEDIMENT_CODE
Definition cme.h:1149
string const RASTER_POTENTIAL_PLATFORM_EROSION_MASK_CODE
Definition cme.h:911
int const SMOOTH_NONE
Definition cme.h:675
int const WAVE_MODEL_COVE
Definition cme.h:685
int const RTN_ERR_READING_SEDIMENT_INPUT_EVENT
Definition cme.h:647
double const TOLERANCE
Definition cme.h:725
string const RASTER_CLIFF_COLLAPSE_EROSION_FINE_CODE
Definition cme.h:867
string const TIME_SERIES_PLATFORM_EROSION_CODE
Definition cme.h:1145
string const RASTER_COARSE_CONS_CODE
Definition cme.h:876
string const VECTOR_POLYGON_NODE_CODE
Definition cme.h:1080
string const RASTER_USUAL_OUTPUT_CODE
Definition cme.h:963
string const RASTER_DEEP_WATER_WAVE_ORIENTATION_CODE
Definition cme.h:886
string const RASTER_DEEP_WATER_WAVE_HEIGHT_CODE
Definition cme.h:884
string const TIME_SERIES_FLOOD_SETUP_SURGE_RUNUP_CODE
Definition cme.h:1143
string const VECTOR_ALL_OUTPUT_CODE
Definition cme.h:1044
string const VECTOR_FLOOD_SWL_SETUP_SURGE_RUNUP_LINE_CODE
Definition cme.h:1070
string const RASTER_TOTAL_CLIFF_COLLAPSE_DEPOSITION_SAND_CODE
Definition cme.h:951
string const RASTER_ACTIVE_ZONE_CODE
Definition cme.h:838
int const NO_LOG_FILE
Definition cme.h:391
string const RASTER_CLIFF_COLLAPSE_EROSION_COARSE_CODE
Definition cme.h:865
string const RASTER_CLIFF_NOTCH_ALL_CODE
Definition cme.h:873
string const RASTER_SAND_CONS_CODE
Definition cme.h:914
string const TIME_SERIES_FLOOD_SETUP_SURGE_CODE
Definition cme.h:1141
string const TIME_SERIES_CLIFF_NOTCH_ELEV_CODE
Definition cme.h:1139
int const RTN_ERR_SCAPE_SHAPE_FUNCTION_FILE
Definition cme.h:593
int const UNCONS_SEDIMENT_EQUATION_KAMPHUIS
Definition cme.h:690
string const ERR
Definition cme.h:805
string const RASTER_COAST_NORMAL_CODE
Definition cme.h:882
int const DEFAULT_PROFILE_SPACING
Definition cme.h:387
string const VECTOR_CLIFF_EDGE_CODE
Definition cme.h:1050
string const SCAPE_DIR
Definition cme.h:798
string const LOGEXT
Definition cme.h:830
string const RASTER_AVG_SUSP_SED_CODE
Definition cme.h:847
string const RASTER_COAST_CODE
Definition cme.h:880
string const RASTER_SEDIMENT_INPUT_EVENT_CODE
Definition cme.h:920
string const VECTOR_WAVE_ENERGY_SINCE_COLLAPSE_CODE
Definition cme.h:1091
string const RASTER_WAVE_ORIENTATION_CODE
Definition cme.h:968
string const VECTOR_RUN_UP_CODE
Definition cme.h:1082
string const RASTER_ALL_OUTPUT_CODE
Definition cme.h:844
string const RASTER_CLIFF_COLLAPSE_EROSION_SAND_CODE
Definition cme.h:869
string const RASTER_POLYGON_UPDRIFT_OR_DOWNDRIFT_CODE
Definition cme.h:906
string const RASTER_WAVE_FLOOD_LINE_CODE
Definition cme.h:964
int const WAVE_MODEL_CSHORE
Definition cme.h:686
string const RASTER_COARSE_UNCONS_CODE
Definition cme.h:878
string const OUTEXT
Definition cme.h:829
char const PATH_SEPARATOR
Definition cme.h:353
string const VECTOR_INVALID_NORMALS_CODE
Definition cme.h:1072
string const VECTOR_CLIFF_NOTCH_ACTIVE_CODE
Definition cme.h:1052
string const RASTER_BASEMENT_ELEVATION_CODE
Definition cme.h:853
string const RASTER_WAVE_HEIGHT_CODE
Definition cme.h:966
string const RASTER_CLIFF_COLLAPSE_DEPOSITION_COARSE_CODE
Definition cme.h:861
char const COMMA
Definition cme.h:351
string const RASTER_INTERVENTION_CLASS_CODE
Definition cme.h:894
string const RASTER_POTENTIAL_PLATFORM_EROSION_CODE
Definition cme.h:910
string const RASTER_POTENTIAL_BEACH_EROSION_CODE
Definition cme.h:908
string const VECTOR_MEAN_WAVE_ENERGY_CODE
Definition cme.h:1074
string const VECTOR_STORM_SURGE_CODE
Definition cme.h:1086
int const TIME_UNKNOWN
Definition cme.h:422
double const D50_SAND_DEFAULT
Definition cme.h:710
string const RASTER_TOTAL_CLIFF_COLLAPSE_EROSION_COARSE_CODE
Definition cme.h:953
bool bFPIsEqual(const T d1, const T d2, const T dEpsilon)
Definition cme.h:1213
string const VECTOR_USUAL_OUTPUT_CODE
Definition cme.h:1088
char const QUOTE1
Definition cme.h:354
string const RASTER_WAVE_PERIOD_CODE
Definition cme.h:970
int const GRID_EDGE_CLOSED
Definition cme.h:680
string const TIME_SERIES_CLIFF_COLLAPSE_NET_CODE
Definition cme.h:1137
int const GRID_EDGE_RECIRCULATE
Definition cme.h:682
int const RTN_ERR_OPEN_DEEP_WATER_WAVE_DATA
Definition cme.h:644
string const RASTER_TOTAL_ACTUAL_BEACH_EROSION_CODE
Definition cme.h:943
string const VECTOR_NORMALS_CODE
Definition cme.h:1076
string const RASTER_BEACH_DEPOSITION_CODE
Definition cme.h:855
string const RASTER_SHADOW_ZONE_CODE
Definition cme.h:930
string const RASTER_TOTAL_BEACH_DEPOSITION_CODE
Definition cme.h:947
int const SAVEMAX
Definition cme.h:368
string const VECTOR_DEEP_WATER_WAVE_ANGLE_AND_HEIGHT_CODE
Definition cme.h:1060
int const NUMBER_OF_RNGS
Definition cme.h:367
double const D50_COARSE_DEFAULT
Definition cme.h:711
string const RASTER_BEACH_PROTECTION_CODE
Definition cme.h:859
string const RASTER_TOTAL_POTENTIAL_PLATFORM_EROSION_CODE
Definition cme.h:961
string const VECTOR_SHADOW_ZONE_BOUNDARY_CODE
Definition cme.h:1084
string const TIME_SERIES_CLIFF_COLLAPSE_EROSION_CODE
Definition cme.h:1135
string const RASTER_BEACH_MASK_CODE
Definition cme.h:857
string const RASTER_AVG_WAVE_HEIGHT_CODE
Definition cme.h:849
string const RASTER_SETUP_SURGE_FLOOD_MASK_CODE
Definition cme.h:924
string const TIME_SERIES_BEACH_EROSION_CODE
Definition cme.h:1131
string const RASTER_TOTAL_POTENTIAL_BEACH_EROSION_CODE
Definition cme.h:959
int const SMOOTH_SAVITZKY_GOLAY
Definition cme.h:677
string const RASTER_AVG_SEA_DEPTH_CODE
Definition cme.h:845
int const SMOOTH_RUNNING_MEAN
Definition cme.h:676
string const RASTER_SAND_UNCONS_CODE
Definition cme.h:916
string const TIME_SERIES_SWL_CODE
Definition cme.h:1151
string const READING_FILE_LOCATIONS
Definition cme.h:765
int const LOG_FILE_ALL
Definition cme.h:395
int const RTN_OK
Definition cme.h:585
string const RASTER_SETUP_SURGE_RUNUP_FLOOD_MASK_CODE
Definition cme.h:926
string const RASTER_LANDFORM_CODE
Definition cme.h:900
string const RASTER_TOTAL_ACTUAL_PLATFORM_EROSION_CODE
Definition cme.h:945
int const RTN_ERR_READING_DEEP_WATER_WAVE_DATA
Definition cme.h:645
string const RASTER_ACTUAL_PLATFORM_EROSION_CODE
Definition cme.h:842
string const VECTOR_BREAKING_WAVE_HEIGHT_CODE
Definition cme.h:1048
unsigned long const SEDIMENT_INPUT_EVENT_ERROR
Definition cme.h:704
int const RTN_ERR_TIDEDATAFILE
Definition cme.h:594
string const RASTER_SUSP_SED_CODE
Definition cme.h:937
string const VECTOR_COAST_CURVATURE_CODE
Definition cme.h:1055
double const DBL_NODATA
Definition cme.h:736
double const D50_FINE_DEFAULT
Definition cme.h:709
string const VECTOR_ALL_RIVER_FLOOD_OUTPUT_CODE
Definition cme.h:1045
string const CME_INI
Definition cme.h:740
string const NOTE
Definition cme.h:807
string const RASTER_CLIFF_COLLAPSE_DEPOSITION_SAND_CODE
Definition cme.h:863
string const RASTER_SEA_DEPTH_CODE
Definition cme.h:918
string const RASTER_FINE_CONS_CODE
Definition cme.h:890
char const QUOTE2
Definition cme.h:355
string const RASTER_CLIFF_COLLAPSE_TIMESTEP_CODE
Definition cme.h:871
string const VECTOR_POLYGON_BOUNDARY_CODE
Definition cme.h:1078
string const RASTER_FINE_UNCONS_CODE
Definition cme.h:892
string const VECTOR_DOWNDRIFT_ZONE_BOUNDARY_CODE
Definition cme.h:1062
string const RASTER_SEDIMENT_TOP_CODE
Definition cme.h:922
int const GRID_EDGE_OPEN
Definition cme.h:681
string const RASTER_TOP_ELEVATION_INC_SEA_CODE
Definition cme.h:941
int const UNCONS_SEDIMENT_EQUATION_CERC
Definition cme.h:689
string const RASTER_POLYGON_GAIN_OR_LOSS_CODE
Definition cme.h:903
char const TILDE
Definition cme.h:358
string const RASTER_TOTAL_CLIFF_COLLAPSE_EROSION_SAND_CODE
Definition cme.h:957
string const VECTOR_AVG_WAVE_ANGLE_AND_HEIGHT_CODE
Definition cme.h:1046
string const TIME_SERIES_BEACH_CHANGE_NET_CODE
Definition cme.h:1127
string const RASTER_INTERVENTION_HEIGHT_CODE
Definition cme.h:896
string const VECTOR_FLOOD_LINE_CODE
Definition cme.h:1064
string const TIME_SERIES_BEACH_DEPOSITION_CODE
Definition cme.h:1129
string const VECTOR_FLOOD_SWL_SETUP_LINE_CODE
Definition cme.h:1066
string const VECTOR_WAVE_SETUP_CODE
Definition cme.h:1093
string const RASTER_POLYGON_CODE
Definition cme.h:902
string const RASTER_ACTUAL_BEACH_EROSION_CODE
Definition cme.h:840
string const RASTER_INUNDATION_MASK_CODE
Definition cme.h:898
string const VECTOR_COAST_CODE
Definition cme.h:1054
char const COLON
Definition cme.h:350
string const RASTER_TOTAL_CLIFF_COLLAPSE_EROSION_FINE_CODE
Definition cme.h:955
string const RASTER_AVG_WAVE_ORIENTATION_CODE
Definition cme.h:851
string const SCAPE_SHAPE_FUNCTION_FILE
Definition cme.h:799
string const TIME_SERIES_SEA_AREA_CODE
Definition cme.h:1147
string const RASTER_DEEP_WATER_WAVE_PERIOD_CODE
Definition cme.h:888
string const RASTER_TALUS_CODE
Definition cme.h:939
string const RASTER_TOTAL_CLIFF_COLLAPSE_DEPOSITION_COARSE_CODE
Definition cme.h:949
char const SPACE
Definition cme.h:357
Unified configuration class for CoastalME simulation parameters.
Contains CRWSedInputEvent 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.