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 if (gis.HasChild("vector_files"))
4230 {
4231 CYamlNode vectorFiles = gis.GetChild("vector_files");
4232 if (vectorFiles.IsSequence())
4233 config.SetVectorFiles(vectorFiles.GetStringSequence());
4234 }
4235 if (gis.HasChild("raster_format"))
4236 config.SetRasterFormat(gis.GetChild("raster_format").GetValue());
4237 if (gis.HasChild("world_file"))
4238 config.SetWorldFile(gis.GetChild("world_file").GetBoolValue());
4239 if (gis.HasChild("scale_values"))
4240 config.SetScaleValues(gis.GetChild("scale_values").GetBoolValue());
4241 }
4242
4243 // Hydrology
4244 if (root.HasChild("hydrology"))
4245 {
4246 CYamlNode hydro = root.GetChild("hydrology");
4247 if (hydro.HasChild("wave_propagation_model"))
4248 {
4249 string strModel = hydro.GetChild("wave_propagation_model").GetValue();
4250 if (strModel == "COVE")
4251 config.SetWavePropagationModel(0);
4252 else if (strModel == "CShore")
4253 config.SetWavePropagationModel(1);
4254 }
4255 if (hydro.HasChild("seawater_density"))
4256 config.SetSeawaterDensity(
4257 hydro.GetChild("seawater_density").GetDoubleValue());
4258 if (hydro.HasChild("initial_water_level"))
4259 config.SetInitialWaterLevel(
4260 hydro.GetChild("initial_water_level").GetDoubleValue());
4261 if (hydro.HasChild("final_water_level"))
4262 config.SetFinalWaterLevel(
4263 hydro.GetChild("final_water_level").GetDoubleValue());
4264
4265 // Wave data configuration
4266 if (hydro.HasChild("wave_height_time_series"))
4268 hydro.GetChild("wave_height_time_series").GetValue());
4269 if (hydro.HasChild("wave_height_shape_file"))
4271 hydro.GetChild("wave_height_shape_file").GetValue());
4272 if (hydro.HasChild("wave_height"))
4274 hydro.GetChild("wave_height").GetDoubleValue());
4275 if (hydro.HasChild("wave_orientation"))
4277 hydro.GetChild("wave_orientation").GetDoubleValue());
4278 if (hydro.HasChild("wave_period"))
4279 config.SetWavePeriod(hydro.GetChild("wave_period").GetDoubleValue());
4280
4281 // Tide data configuration
4282 if (hydro.HasChild("tide_data_file"))
4283 config.SetTideDataFile(processFilePath(hydro.GetChild("tide_data_file").GetValue()));
4284 if (hydro.HasChild("breaking_wave_ratio"))
4285 config.SetBreakingWaveRatio(
4286 hydro.GetChild("breaking_wave_ratio").GetDoubleValue());
4287 }
4288
4289 // Grid and Coastline
4290 if (root.HasChild("grid_and_coastline"))
4291 {
4292 CYamlNode grid = root.GetChild("grid_and_coastline");
4293 if (grid.HasChild("coastline_smoothing"))
4294 {
4295 string strSmoothing = grid.GetChild("coastline_smoothing").GetValue();
4296 if (strSmoothing == "none")
4297 config.SetCoastlineSmoothing(0);
4298 else if (strSmoothing == "running_mean")
4299 config.SetCoastlineSmoothing(1);
4300 else if (strSmoothing == "savitzky_golay")
4301 config.SetCoastlineSmoothing(2);
4302 else
4303 config.SetCoastlineSmoothing(
4304 grid.GetChild("coastline_smoothing").GetIntValue());
4305 }
4306 if (grid.HasChild("coastline_smoothing_window"))
4308 grid.GetChild("coastline_smoothing_window").GetIntValue());
4309 if (grid.HasChild("polynomial_order"))
4310 config.SetPolynomialOrder(
4311 grid.GetChild("polynomial_order").GetIntValue());
4312 if (grid.HasChild("omit_grid_edges"))
4313 config.SetOmitGridEdges(grid.GetChild("omit_grid_edges").GetValue());
4314 if (grid.HasChild("profile_smoothing_window"))
4316 grid.GetChild("profile_smoothing_window").GetIntValue());
4317 if (grid.HasChild("max_local_slope"))
4318 config.SetMaxLocalSlope(
4319 grid.GetChild("max_local_slope").GetDoubleValue());
4320 if (grid.HasChild("max_beach_elevation"))
4321 config.SetMaxBeachElevation(
4322 grid.GetChild("max_beach_elevation").GetDoubleValue());
4323 }
4324
4325 // Layers and Files
4326 if (root.HasChild("layers_and_files"))
4327 {
4328 CYamlNode layers = root.GetChild("layers_and_files");
4329 if (layers.HasChild("num_layers"))
4330 config.SetNumLayers(layers.GetChild("num_layers").GetIntValue());
4331 if (layers.HasChild("basement_dem_file"))
4332 config.SetBasementDEMFile(
4333 processFilePath(layers.GetChild("basement_dem_file").GetValue()));
4334 if (layers.HasChild("suspended_sediment_file"))
4335 config.SetSuspendedSedFile(processFilePath(
4336 layers.GetChild("suspended_sediment_file").GetValue()));
4337 if (layers.HasChild("landform_file"))
4338 config.SetLandformFile(
4339 processFilePath(layers.GetChild("landform_file)").GetValue()));
4340 if (layers.HasChild("intervention_class_file"))
4341 config.SetInterventionClassFile(processFilePath(
4342 layers.GetChild("intervention_class_file").GetValue()));
4343 if (layers.HasChild("intervention_height_file"))
4344 config.SetInterventionHeightFile(processFilePath(
4345 layers.GetChild("intervention_height_file").GetValue()));
4346
4347 // Handle layer-specific files (assuming layer_0, layer_1, etc.)
4348 if (layers.HasChild("layer_0"))
4349 {
4350 CYamlNode layer0 = layers.GetChild("layer_0");
4351 vector<string> unconsFine, unconsSand, unconsCoarse;
4352 vector<string> consFine, consSand, consCoarse;
4353
4354 if (layer0.HasChild("unconsolidated_fine"))
4355 unconsFine.push_back(processFilePath(
4356 layer0.GetChild("unconsolidated_fine").GetValue()));
4357 if (layer0.HasChild("unconsolidated_sand"))
4358 unconsSand.push_back(processFilePath(
4359 layer0.GetChild("unconsolidated_sand").GetValue()));
4360 if (layer0.HasChild("unconsolidated_coarse"))
4361 unconsCoarse.push_back(processFilePath(
4362 layer0.GetChild("unconsolidated_coarse").GetValue()));
4363 if (layer0.HasChild("consolidated_fine"))
4364 consFine.push_back(
4365 processFilePath(layer0.GetChild("consolidated_fine").GetValue()));
4366 if (layer0.HasChild("consolidated_sand"))
4367 consSand.push_back(
4368 processFilePath(layer0.GetChild("consolidated_sand").GetValue()));
4369 if (layer0.HasChild("consolidated_coarse"))
4370 consCoarse.push_back(processFilePath(
4371 layer0.GetChild("consolidated_coarse").GetValue()));
4372
4373 config.SetUnconsFineFiles(unconsFine);
4374 config.SetUnconsSandFiles(unconsSand);
4375 config.SetUnconsCoarseFiles(unconsCoarse);
4376 config.SetConsFineFiles(consFine);
4377 config.SetConsSandFiles(consSand);
4378 config.SetConsCoarseFiles(consCoarse);
4379 }
4380 }
4381
4382 // Sediment and Erosion
4383 if (root.HasChild("sediment_and_erosion"))
4384 {
4385 CYamlNode sed = root.GetChild("sediment_and_erosion");
4386 if (sed.HasChild("coast_platform_erosion"))
4388 sed.GetChild("coast_platform_erosion").GetBoolValue());
4389 if (sed.HasChild("platform_erosion_resistance"))
4391 sed.GetChild("platform_erosion_resistance").GetDoubleValue());
4392 if (sed.HasChild("beach_sediment_transport"))
4394 sed.GetChild("beach_sediment_transport").GetBoolValue());
4395 if (sed.HasChild("beach_transport_at_edges"))
4397 sed.GetChild("beach_transport_at_edges").GetIntValue());
4398 if (sed.HasChild("beach_erosion_equation"))
4399 {
4400 string strEqn = sed.GetChild("beach_erosion_equation").GetValue();
4401 config.SetBeachErosionEquation(strEqn == "CERC" ? 0 : 1);
4402 }
4403 if (sed.HasChild("sediment_density"))
4404 config.SetSedimentDensity(
4405 sed.GetChild("sediment_density").GetDoubleValue());
4406 if (sed.HasChild("beach_sediment_porosity"))
4408 sed.GetChild("beach_sediment_porosity").GetDoubleValue());
4409 if (sed.HasChild("transport_kls"))
4410 config.SetTransportKLS(sed.GetChild("transport_kls").GetDoubleValue());
4411 if (sed.HasChild("kamphuis_parameter"))
4412 config.SetKamphuis(sed.GetChild("kamphuis_parameter").GetDoubleValue());
4413 if (sed.HasChild("berm_height"))
4414 config.SetBermHeight(sed.GetChild("berm_height").GetDoubleValue());
4415
4416 // Handle nested median_sizes and erosivity sections
4417 if (sed.HasChild("median_sizes"))
4418 {
4419 CYamlNode sizes = sed.GetChild("median_sizes");
4420 if (sizes.HasChild("fine"))
4421 config.SetFineMedianSize(sizes.GetChild("fine").GetDoubleValue());
4422 if (sizes.HasChild("sand"))
4423 config.SetSandMedianSize(sizes.GetChild("sand").GetDoubleValue());
4424 if (sizes.HasChild("coarse"))
4425 config.SetCoarseMedianSize(sizes.GetChild("coarse").GetDoubleValue());
4426 }
4427 if (sed.HasChild("erosivity"))
4428 {
4429 CYamlNode eros = sed.GetChild("erosivity");
4430 if (eros.HasChild("fine"))
4431 config.SetFineErosivity(eros.GetChild("fine").GetDoubleValue());
4432 if (eros.HasChild("sand"))
4433 config.SetSandErosivity(eros.GetChild("sand").GetDoubleValue());
4434 if (eros.HasChild("coarse"))
4435 config.SetCoarseErosivity(eros.GetChild("coarse").GetDoubleValue());
4436 }
4437 }
4438
4439 // Cliff Parameters
4440 if (root.HasChild("cliff_parameters"))
4441 {
4442 CYamlNode cliff = root.GetChild("cliff_parameters");
4443 if (cliff.HasChild("cliff_collapse"))
4444 config.SetCliffCollapse(
4445 cliff.GetChild("cliff_collapse").GetBoolValue());
4446 if (cliff.HasChild("cliff_erosion_resistance"))
4448 cliff.GetChild("cliff_erosion_resistance").GetDoubleValue());
4449 if (cliff.HasChild("notch_overhang"))
4450 config.SetNotchOverhang(
4451 cliff.GetChild("notch_overhang").GetDoubleValue());
4452 if (cliff.HasChild("notch_base"))
4453 config.SetNotchBase(cliff.GetChild("notch_base").GetDoubleValue());
4454 if (cliff.HasChild("deposition_scale_parameter_a"))
4455 config.SetCliffDepositionA(
4456 cliff.GetChild("deposition_scale_parameter_a").GetDoubleValue());
4457 if (cliff.HasChild("talus_width"))
4458 config.SetTalusWidth(cliff.GetChild("talus_width").GetDoubleValue());
4459 if (cliff.HasChild("min_talus_length"))
4460 config.SetMinTalusLength(
4461 cliff.GetChild("min_talus_length").GetDoubleValue());
4462 if (cliff.HasChild("min_talus_height"))
4463 config.SetMinTalusHeight(
4464 cliff.GetChild("min_talus_height").GetDoubleValue());
4465 }
4466
4467 // Flood Parameters
4468 if (root.HasChild("flood_parameters"))
4469 {
4470 CYamlNode flood = root.GetChild("flood_parameters");
4471 if (flood.HasChild("flood_input"))
4472 config.SetFloodInput(flood.GetChild("flood_input").GetBoolValue());
4473 if (flood.HasChild("flood_coastline"))
4474 config.SetFloodCoastline(flood.GetChild("flood_coastline").GetValue());
4475 if (flood.HasChild("runup_equation"))
4476 config.SetRunupEquation(flood.GetChild("runup_equation").GetValue());
4477 if (flood.HasChild("characteristic_locations"))
4478 config.SetFloodLocations(
4479 flood.GetChild("characteristic_locations").GetValue());
4480 if (flood.HasChild("flood_input_location"))
4481 config.SetFloodInputLocation(
4482 flood.GetChild("flood_input_location").GetValue());
4483 }
4484
4485 // Sediment Input Parameters
4486 if (root.HasChild("sediment_input_parameters"))
4487 {
4488 CYamlNode sedInput = root.GetChild("sediment_input_parameters");
4489 if (sedInput.HasChild("sediment_input"))
4490 config.SetSedimentInput(
4491 sedInput.GetChild("sediment_input").GetBoolValue());
4492 if (sedInput.HasChild("location"))
4494 sedInput.GetChild("location").GetValue());
4495 if (sedInput.HasChild("type"))
4496 config.SetSedimentInputType(sedInput.GetChild("type").GetValue());
4497 if (sedInput.HasChild("details_file"))
4499 sedInput.GetChild("details_file").GetValue());
4500 }
4501
4502 // Physics and Geometry
4503 if (root.HasChild("physics_and_geometry"))
4504 {
4505 CYamlNode physics = root.GetChild("physics_and_geometry");
4506 if (physics.HasChild("gravitational_acceleration"))
4508 physics.GetChild("gravitational_acceleration").GetDoubleValue());
4509 if (physics.HasChild("normal_spacing"))
4510 config.SetNormalSpacing(
4511 physics.GetChild("normal_spacing").GetDoubleValue());
4512 if (physics.HasChild("random_factor"))
4513 config.SetRandomFactor(
4514 physics.GetChild("random_factor").GetDoubleValue());
4515 if (physics.HasChild("normal_length"))
4516 config.SetNormalLength(
4517 physics.GetChild("normal_length").GetDoubleValue());
4518 if (physics.HasChild("start_depth_ratio"))
4519 config.SetStartDepthRatio(
4520 physics.GetChild("start_depth_ratio").GetDoubleValue());
4521 if (physics.HasChild("synthetic_transect_spacing"))
4523 physics.GetChild("synthetic_transect_spacing").GetDoubleValue());
4524 }
4525
4526 // Profile and Output
4527 if (root.HasChild("profile_and_output"))
4528 {
4529 CYamlNode profile = root.GetChild("profile_and_output");
4530 if (profile.HasChild("save_profile_data"))
4531 config.SetSaveProfileData(
4532 profile.GetChild("save_profile_data").GetBoolValue());
4533 if (profile.HasChild("save_parallel_profiles"))
4535 profile.GetChild("save_parallel_profiles").GetBoolValue());
4536 if (profile.HasChild("output_erosion_potential"))
4538 profile.GetChild("output_erosion_potential").GetBoolValue());
4539 if (profile.HasChild("curvature_window"))
4540 config.SetCurvatureWindow(
4541 profile.GetChild("curvature_window").GetIntValue());
4542
4543 // Handle numeric lists
4544 if (profile.HasChild("profile_numbers"))
4545 {
4546 CYamlNode profileNums = profile.GetChild("profile_numbers");
4547 if (profileNums.IsSequence())
4548 {
4549 vector<int> vecNums;
4550 vector<CYamlNode> seq = profileNums.GetSequence();
4551 for (auto const &node : seq)
4552 vecNums.push_back(node.GetIntValue());
4553 config.SetProfileNumbers(vecNums);
4554 }
4555 }
4556 if (profile.HasChild("profile_timesteps"))
4557 {
4558 CYamlNode profileTimes = profile.GetChild("profile_timesteps");
4559 if (profileTimes.IsSequence())
4560 {
4561 vector<unsigned long> vecTimes;
4562 vector<CYamlNode> seq = profileTimes.GetSequence();
4563 for (auto const &node : seq)
4564 vecTimes.push_back(node.GetULongValue());
4565 config.SetProfileTimesteps(vecTimes);
4566 }
4567 }
4568 }
4569
4570 // Cliff Edge Processing
4571 if (root.HasChild("cliff_edge_processing"))
4572 {
4573 CYamlNode cliffEdge = root.GetChild("cliff_edge_processing");
4574 if (cliffEdge.HasChild("cliff_edge_smoothing"))
4575 {
4576 string strSmoothing =
4577 cliffEdge.GetChild("cliff_edge_smoothing").GetValue();
4578 if (strSmoothing == "none")
4579 config.SetCliffEdgeSmoothing(0);
4580 else if (strSmoothing == "running_mean")
4581 config.SetCliffEdgeSmoothing(1);
4582 else if (strSmoothing == "savitzky_golay")
4583 config.SetCliffEdgeSmoothing(2);
4584 else
4585 config.SetCliffEdgeSmoothing(
4586 cliffEdge.GetChild("cliff_edge_smoothing").GetIntValue());
4587 }
4588 if (cliffEdge.HasChild("cliff_edge_smoothing_window"))
4590 cliffEdge.GetChild("cliff_edge_smoothing_window").GetIntValue());
4591 if (cliffEdge.HasChild("cliff_edge_polynomial_order"))
4593 cliffEdge.GetChild("cliff_edge_polynomial_order").GetIntValue());
4594 if (cliffEdge.HasChild("cliff_slope_limit"))
4595 config.SetCliffSlopeLimit(
4596 cliffEdge.GetChild("cliff_slope_limit").GetDoubleValue());
4597 }
4598 }
4599 catch (std::exception const &e)
4600 {
4601 cerr << ERR << "Error processing YAML configuration: " << e.what() << endl;
4602 return false;
4603 }
4604
4605 return true;
4606}
4607
4608//===============================================================================================================================
4610//===============================================================================================================================
4612{
4613 string strRec, strErr;
4614 // Case 1: Text output file names, don't change case
4615 m_strRunName = config.GetRunName();
4617 m_strOutFile.append(m_strRunName);
4618 m_strOutFile.append(OUTEXT);
4619
4621 m_strLogFile.append(m_strRunName);
4622 m_strLogFile.append(LOGEXT);
4623
4624 // Case 2: Content of log file (0 = no log file, 1 = least detail, 3 = most
4625 // detail)
4627
4628 // Case 3: Output per-timestep results in CSV format?
4630
4631 // Case 4: Parse start date/time [hh-mm-ss dd/mm/yyyy]
4632 string strStartDateTime = config.GetStartDateTime();
4633 if (! strStartDateTime.empty())
4634 {
4635 vector<string> VstrTmp = VstrSplit(&strStartDateTime, SPACE);
4636 if (VstrTmp.size() >= 2)
4637 {
4638 int nHour, nMin, nSec, nDay, nMonth, nYear;
4639 if (bParseTime(&VstrTmp[0], nHour, nMin, nSec))
4640 {
4641 if (bParseDate(&VstrTmp[1], nDay, nMonth, nYear))
4642 {
4643 m_nSimStartSec = nSec;
4644 m_nSimStartMin = nMin;
4645 m_nSimStartHour = nHour;
4646 m_nSimStartDay = nDay;
4647 m_nSimStartMonth = nMonth;
4648 m_nSimStartYear = nYear;
4649 }
4650 }
4651 }
4652 }
4653
4654 // Case 5: Duration of simulation (in hours, days, months, or years)
4655 string strDuration = config.GetDuration();
4656 if (! strDuration.empty())
4657 {
4658 string strDurationLower = strToLower(&strDuration);
4659 double dDurationMult = dGetTimeMultiplier(&strDurationLower);
4660 if (static_cast<int>(dDurationMult) != TIME_UNKNOWN)
4661 {
4662 // Extract numeric part and multiply
4663 string strNumeric = strDurationLower;
4664 // Remove the unit part to get just the number
4665 if (strNumeric.find("hour") != string::npos)
4666 strNumeric = strNumeric.substr(0, strNumeric.find("hour"));
4667 else if (strNumeric.find("day") != string::npos)
4668 strNumeric = strNumeric.substr(0, strNumeric.find("day"));
4669 else if (strNumeric.find("month") != string::npos)
4670 strNumeric = strNumeric.substr(0, strNumeric.find("month"));
4671 else if (strNumeric.find("year") != string::npos)
4672 strNumeric = strNumeric.substr(0, strNumeric.find("year"));
4673
4674 if (bIsStringValidDouble(strNumeric))
4675 {
4676 m_dSimDuration = strtod(strNumeric.c_str(), NULL) * dDurationMult;
4677 }
4678 }
4679 }
4680
4681 // Case 6: Timestep of simulation (in hours or days)
4682 string strTimestep = config.GetTimestep();
4683 if (! strTimestep.empty())
4684 {
4685 string strTimestepLower = strToLower(&strTimestep);
4686 double dTimestepMult = dGetTimeMultiplier(&strTimestepLower);
4687 if (static_cast<int>(dTimestepMult) != TIME_UNKNOWN)
4688 {
4689 // Extract numeric part and multiply
4690 std::string strNumeric = strTimestepLower;
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_dTimeStep = strtod(strNumeric.c_str(), NULL) * dTimestepMult;
4704 }
4705 if (m_dTimeStep <= 0)
4706 strErr =
4707 "timestep of simulation must be > 0";
4708
4710 strErr =
4711 " timestep of simulation must be < the duration of the "
4712 "simulation";
4713 }
4714 }
4715
4716 // Case 7: Save intervals - can handle multiple groups with different units
4717 vector<string> vecSaveTimes = config.GetSaveTimes();
4718 if (! vecSaveTimes.empty())
4719 {
4720 m_nUSave = 0;
4721 m_bSaveRegular = false;
4722
4723 for (string const &strSaveTime : vecSaveTimes)
4724 {
4725 if (strSaveTime.empty())
4726 continue;
4727
4728 string strSaveTimeLower = strToLower(&strSaveTime);
4729
4730 // Get multiplier for time units
4731 double dMult = dGetTimeMultiplier(&strSaveTimeLower);
4732 if (static_cast<int>(dMult) != TIME_UNKNOWN)
4733 {
4734 // Find last space to separate number from unit
4735 size_t nLastSpace = strSaveTimeLower.rfind(SPACE);
4736 if (nLastSpace != string::npos)
4737 {
4738 string strNumbers = strSaveTimeLower.substr(0, nLastSpace);
4739 strNumbers = strTrimRight(&strNumbers);
4740
4741 // Parse numbers (could be multiple space-separated values)
4742 vector<string> VstrNumbers = VstrSplit(&strNumbers, SPACE);
4743 for (string const &strNum : VstrNumbers)
4744 {
4745 if (! strNum.empty()) //&& bIsStringValidDouble(strNum))
4746 {
4747 if (m_nUSave < static_cast<int>(SAVEMAX) - 1)
4748 {
4749 double dValue = strtod(strNum.c_str(), NULL) * dMult;
4750 m_dUSaveTime[m_nUSave++] = dValue;
4751 }
4752 }
4753 }
4754 }
4755 }
4756 }
4757
4758 // Check if we have save times
4759 if (m_nUSave == 1)
4760 {
4761 m_bSaveRegular = true;
4764 }
4765 else if (m_nUSave > 1)
4766 {
4767 // Multiple values - sort them
4769 // Put a dummy save interval as the last entry
4771 }
4772 }
4773
4774 // Case 8: Random number seed(s)
4775 if (config.UseSystemTimeForRandomSeed())
4776 {
4777 // Use system time for random seed
4778 random_device rdev;
4779 m_ulRandSeed[0] = rdev();
4780 // Make all seeds the same
4781 for (int n = 1; n < NUMBER_OF_RNGS; n++)
4782 m_ulRandSeed[n] = m_ulRandSeed[0];
4783 }
4784 else
4785 {
4786 int nSeed = config.GetRandomSeed();
4787 if (nSeed != 0)
4788 {
4789 // Use specified seed
4790 m_ulRandSeed[0] = static_cast<unsigned long>(nSeed);
4791 // Make all seeds the same
4792 for (int n = 1; n < NUMBER_OF_RNGS; n++)
4793 m_ulRandSeed[n] = m_ulRandSeed[0];
4794 }
4795 }
4796
4797 // Case 9: Max save digits for GIS output
4799 if (m_nGISMaxSaveDigits < 2)
4800 strErr = "max save digits for GIS output file names must be > 1";
4801
4802 // Case 10: Save digits mode (sequential vs iteration)
4803 string strSaveDigitsMode = config.GetSaveDigitsMode();
4804 if (! strSaveDigitsMode.empty())
4805 {
4806 string strSaveDigitsLower = strToLower(&strSaveDigitsMode);
4807 if (strSaveDigitsLower.find('s') != string::npos)
4809 else if (strSaveDigitsLower.find('i') != string::npos)
4811 }
4812
4813 // Case 11: Raster GIS files to output
4814 vector<string> rasterFiles = config.GetRasterFiles();
4815 if (! rasterFiles.empty())
4816 {
4817 // Reset all raster output flags
4818 m_bSuspSedSave = false;
4819 m_bAvgSuspSedSave = false;
4820 m_bFineUnconsSedSave = false;
4821 m_bFineConsSedSave = false;
4822 m_bSandUnconsSedSave = false;
4823 m_bSandConsSedSave = false;
4824 m_bCoarseUnconsSedSave = false;
4825 m_bCoarseConsSedSave = false;
4827 m_bTopSurfIncSeaSave = false;
4828 m_bSeaDepthSave = false;
4829 m_bWaveHeightSave = false;
4830 m_bWaveAngleSave = false;
4839 m_bBeachDepositionSave = false;
4841 m_bLandformSave = false;
4842 // m_bLocalSlopeSave = false;
4843 // m_bSlopeSave = false;
4844 // m_bCliffSave = false;
4845 m_bAvgSeaDepthSave = false;
4846 m_bAvgWaveHeightSave = false;
4847 m_bAvgWaveAngleSave = false;
4848 m_bBeachProtectionSave = false;
4849 m_bBasementElevSave = false;
4850 m_bRasterCoastlineSave = false;
4852 m_bActiveZoneSave = false;
4853 m_bCliffCollapseSave = false;
4857 m_bRasterPolygonSave = false;
4859 m_bSeaMaskSave = false;
4860 m_bBeachMaskSave = false;
4861 m_bShadowZoneCodesSave = false;
4867
4868 // Set flags based on raster file codes (Case 11 implementation)
4869 for (string const &rasterCode : rasterFiles)
4870 {
4871 string code = rasterCode;
4872 std::transform(code.begin(), code.end(), code.begin(), ::tolower);
4873
4874 if (code == "suspended_sediment")
4875 m_bSuspSedSave = true;
4876 else if (code == "avg_suspended_sediment")
4877 m_bAvgSuspSedSave = true;
4878 else if (code == "fine_uncons")
4879 m_bFineUnconsSedSave = true;
4880 else if (code == "fine_cons")
4881 m_bFineConsSedSave = true;
4882 else if (code == "sand_uncons")
4883 m_bSandUnconsSedSave = true;
4884 else if (code == "sand_cons")
4885 m_bSandConsSedSave = true;
4886 else if (code == "coarse_uncons")
4888 else if (code == "coarse_cons")
4889 m_bCoarseConsSedSave = true;
4890 else if (code == "sediment_top_elevation")
4892 else if (code == "top_elevation")
4893 m_bTopSurfIncSeaSave = true;
4894 else if (code == "sea_depth")
4895 m_bSeaDepthSave = true;
4896 else if (code == "wave_height")
4897 m_bWaveHeightSave = true;
4898 else if (code == "wave_orientation")
4899 m_bWaveAngleSave = true;
4900 else if (code == "wave_period")
4902 else if (code == "potential_platform_erosion")
4904 else if (code == "actual_platform_erosion")
4906 else if (code == "total_potential_platform_erosion")
4908 else if (code == "total_actual_platform_erosion")
4910 else if (code == "potential_beach_erosion")
4912 else if (code == "actual_beach_erosion")
4914 else if (code == "total_potential_beach_erosion")
4916 else if (code == "total_actual_beach_erosion")
4918 else if (code == "beach_deposition")
4920 else if (code == "total_beach_deposition")
4922 else if (code == "landform")
4923 m_bLandformSave = true;
4924 // else if (code == "local_cons_sediment_slope")
4925 // m_bLocalSlopeSave = true;
4926 // else if (code == "slope")
4927 // m_bSlopeSave = true;
4928 // else if (code == "cliff")
4929 // m_bCliffSave = true;
4930 else if (code == "avg_sea_depth")
4931 m_bAvgSeaDepthSave = true;
4932 else if (code == "avg_wave_height")
4933 m_bAvgWaveHeightSave = true;
4934 else if (code == "avg_wave_orientation")
4935 m_bAvgWaveAngleSave = true;
4936 else if (code == "beach_protection")
4938 else if (code == "basement_elevation")
4939 m_bBasementElevSave = true;
4940 else if (code == "coastline")
4942 else if (code == "coast_normal")
4944 else if (code == "active_zone")
4945 m_bActiveZoneSave = true;
4946 else if (code == "cliff_collapse")
4947 m_bCliffCollapseSave = true;
4948 else if (code == "total_cliff_collapse")
4950 else if (code == "cliff_collapse_deposition")
4952 else if (code == "total_cliff_collapse_deposition")
4954 else if (code == "polygon")
4955 m_bRasterPolygonSave = true;
4956 else if (code == "potential_platform_erosion_mask")
4958 else if (code == "sea_mask")
4959 m_bSeaMaskSave = true;
4960 else if (code == "beach_mask")
4961 m_bBeachMaskSave = true;
4962 else if (code == "shadow_zone_codes")
4964 else if (code == "deep_water_wave_angle")
4966 else if (code == "deep_water_wave_height")
4968 else if (code == "deep_water_wave_period")
4970 else if (code == "polygon_uncons_sediment_up_or_down_drift")
4972 else if (code == "polygon_uncons_sediment_gain_or_loss")
4974 }
4975 }
4976
4977 // Case 12: GIS output format for raster and vector files
4979
4980 // Case 13: If needed, scale GIS raster output values
4982
4983 // Case 14: If needed, also output GIS raster world file
4984 m_bWorldFile = config.GetWorldFile();
4985
4986 // Case 15: Elevations for raster slice output, if desired
4987 if (! config.GetSliceElevations().empty())
4988 {
4989 m_bSliceSave = true;
4991 }
4992
4993 // Case 16: Vector GIS files to output
4994 vector<string> vectorFiles = config.GetVectorFiles();
4995 if (! vectorFiles.empty())
4996 {
4997 // Reset all vector output flags
4998 m_bCoastSave = false;
4999 m_bCliffEdgeSave = false;
5001 m_bNormalsSave = false;
5002 m_bInvalidNormalsSave = false;
5005 m_bMeanWaveEnergySave = false;
5007 m_bCoastCurvatureSave = false;
5008 m_bPolygonNodeSave = false;
5009 m_bPolygonBoundarySave = false;
5010 m_bCliffNotchSave = false;
5011 m_bShadowBoundarySave = false;
5014 m_bWaveSetupSave = false;
5015 m_bStormSurgeSave = false;
5016 m_bRunUpSave = false;
5018
5019 // Set flags based on vector file codes (Case 16 implementation)
5020 for (string const &vectorCode : vectorFiles)
5021 {
5022 string code = vectorCode;
5023 std::transform(code.begin(), code.end(), code.begin(), ::tolower);
5024
5025 if (code == "coast")
5026 m_bCoastSave = true;
5027 else if (code == "cliff_edge")
5028 m_bCliffEdgeSave = true;
5029 else if (code == "wave_angle")
5031 else if (code == "normals")
5032 m_bNormalsSave = true;
5033 else if (code == "invalid_normals")
5034 m_bInvalidNormalsSave = true;
5035 else if (code == "avg_wave_angle")
5037 else if (code == "wave_energy")
5039 else if (code == "mean_wave_energy")
5040 m_bMeanWaveEnergySave = true;
5041 else if (code == "breaking_wave_height")
5043 else if (code == "coast_curvature")
5044 m_bCoastCurvatureSave = true;
5045 else if (code == "polygon_node")
5046 m_bPolygonNodeSave = true;
5047 else if (code == "polygon")
5049 else if (code == "cliff_notch")
5050 m_bCliffNotchSave = true;
5051 else if (code == "wave_transect_points")
5053 else if (code == "shadow_boundary")
5054 m_bShadowBoundarySave = true;
5055 else if (code == "downdrift_boundary")
5057 else if (code == "deep_water_wave_angle")
5059 else if (code == "wave_setup")
5060 m_bWaveSetupSave = true;
5061 else if (code == "storm_surge")
5062 m_bStormSurgeSave = true;
5063 else if (code == "run_up")
5064 m_bRunUpSave = true;
5065 else if (code == "flood_line")
5067 }
5068 }
5069
5070 // Case 17: Vector GIS output format (note must retain original case)
5072
5073 // Case 18: Time series files to output
5074 // TODO: Migrate from bReadRunDataFile()
5075 vector<string> timeseriesFiles = config.GetTimeSeriesFiles();
5076 if (! timeseriesFiles.empty())
5077 {
5078 for (string const &timeseriesCode : timeseriesFiles)
5079 {
5080 string code = timeseriesCode;
5081 std::transform(code.begin(), code.end(), code.begin(), ::tolower);
5082
5083 if (code == "sea_area")
5084 m_bSeaAreaTSSave = true;
5085 if (code == "water_level")
5086 m_bSWLTSSave = true;
5087 if (code == "platform_erosion")
5089 if (code == "cliff_collapse_erosion")
5091 if (code == "cliff_collapse_deposition")
5093 if (code == "cliff_collapse_net")
5095 if (code == "beach_erosion")
5096 m_bBeachErosionTSSave = true;
5097 if (code == "beach_deposition")
5099 if (code == "beach_change_net")
5101 if (code == "suspended")
5102 m_bSuspSedTSSave = true;
5103 if (code == "suspended")
5104 m_bSuspSedTSSave = true;
5105 if (code == "wave_setup")
5107 if (code == "wave_runup")
5109 if (code == "cliff_notch")
5111 }
5112 }
5113
5114 // Case 19: Vector coastline smoothing algorithm: 0 = none, 1 = running mean,
5115 // 2 = Savitzky-Golay
5117
5118 // Case 20: Size of coastline smoothing window: must be odd
5120
5121 // Case 21: Order of coastline profile smoothing polynomial for
5122 // Savitzky-Golay: usually 2 or 4, max is 6
5124
5125 // Case 22: Omit grid edges from search (north/south/east/west)
5126 std::string strRH = config.GetOmitGridEdges();
5127 if (strRH.find('n') != string::npos)
5128 {
5130 }
5131
5132 if (strRH.find('s') != string::npos)
5133 {
5135 }
5136
5137 if (strRH.find('w') != string::npos)
5138 {
5139 m_bOmitSearchWestEdge = true;
5140 }
5141
5142 if (strRH.find('e') != string::npos)
5143 {
5144 m_bOmitSearchEastEdge = true;
5145 }
5146
5147 // Case 23: Profile slope running-mean smoothing window size: must be odd
5149
5150 // Case 24: Max local slope (m/m), first check that this is a valid double
5152
5153 // Case 25: Maximum elevation of beach above SWL, first check that this is a
5154 // valid double
5156
5157 // Case 26: Number of sediment layers
5158 m_nLayers = config.GetNumLayers();
5159 // OK we know the number of layers, so add elements to these vectors
5160 for (int j = 0; j < m_nLayers; j++)
5161 {
5168 m_VstrGDALIUFDriverCode.push_back("");
5169 m_VstrGDALIUFDriverDesc.push_back("");
5170 m_VstrGDALIUFProjection.push_back("");
5171 m_VstrGDALIUFDataType.push_back("");
5172 m_VstrGDALIUSDriverCode.push_back("");
5173 m_VstrGDALIUSDriverDesc.push_back("");
5174 m_VstrGDALIUSProjection.push_back("");
5175 m_VstrGDALIUSDataType.push_back("");
5176 m_VstrGDALIUCDriverCode.push_back("");
5177 m_VstrGDALIUCDriverDesc.push_back("");
5178 m_VstrGDALIUCProjection.push_back("");
5179 m_VstrGDALIUCDataType.push_back("");
5180 m_VstrGDALICFDriverCode.push_back("");
5181 m_VstrGDALICFDriverDesc.push_back("");
5182 m_VstrGDALICFProjection.push_back("");
5183 m_VstrGDALICFDataType.push_back("");
5184 m_VstrGDALICSDriverCode.push_back("");
5185 m_VstrGDALICSDriverDesc.push_back("");
5186 m_VstrGDALICSProjection.push_back("");
5187 m_VstrGDALICSDataType.push_back("");
5188 m_VstrGDALICCDriverCode.push_back("");
5189 m_VstrGDALICCDriverDesc.push_back("");
5190 m_VstrGDALICCProjection.push_back("");
5191 m_VstrGDALICCDataType.push_back("");
5192 }
5193
5194 // Case 27: Basement DEM file (can be blank)
5196
5197 // Cases 28: Initial sediment thickness files (unconsolidated and
5198 // consolidated)
5200 m_bHaveFineSediment = true;
5202 m_bHaveSandSediment = true;
5204 m_bHaveCoarseSediment = true;
5207 m_bHaveFineSediment = true;
5209 m_bHaveSandSediment = true;
5211 m_bHaveCoarseSediment = true;
5212
5213 // Case 29: Initial suspended sediment depth GIS file (can be blank)
5214 string strSuspendedSed = config.GetSuspendedSedFile();
5215 if (! strSuspendedSed.empty())
5216 {
5217 m_strInitialSuspSedimentFile = strSuspendedSed;
5218 }
5219
5220 // Case 30: Basic simulation input files
5222
5223 // Case 31: Initial Intervention class GIS file
5224 // (can be blank: if so then intervention height file must also be blank)
5225 string strInterventionClass = config.GetInterventionClassFile();
5226 if (! strInterventionClass.empty())
5227 m_strInterventionClassFile = strInterventionClass;
5228
5229 // Case 32: Initial Intervention height GIS file
5230 // (can be blank: if so then intervention class file must also be blank)
5231 string strInterventionHeight = config.GetInterventionHeightFile();
5232 if (! strInterventionHeight.empty())
5233 m_strInterventionHeightFile = strInterventionHeight;
5234
5235 // Case 33: Wave propagation model [0 = COVE, 1 = CShore]
5237
5238 // Case 34: Density of sea water (kg/m3), first check that this is a valid
5239 // double
5241
5242 // Case 35: Initial mean still water level (m), first check that this is a
5243 // valid double TODO 041 Make this a per-timestep SWL file
5245
5246 // Case 36: Final water level (optional)
5247 if (config.HasFinalWaterLevel())
5248 {
5249 if (! strInterventionHeight.empty())
5250 {
5252 }
5253 else
5254 {
5256 }
5257 }
5258 // Case 38-40 Parse Wave Data
5259 // Case 38: Deep water wave height (m) or a file of point vectors giving deep
5260 // Firstly has the user provided a filepath for wave data
5261 if (config.GetWaveHeightTimeSeries().empty())
5262 {
5264 m_bHaveWaveStationData = false;
5265 // Case 37: Deep water wave height (m) or a file of point vectors giving deep
5266 // water wave height (m) and orientation (for units, see below)
5268
5269 // Case 39: Deep water wave orientation in input CRS: this is the
5270 // oceanographic convention i.e. direction TOWARDS which the waves move (in
5271 // degrees clockwise from north)
5273
5274 // Case 40: Wave period (sec)
5276 }
5277 else
5278 {
5282 }
5283
5284 // Case 41: Tide data file (can be blank). This is the change (m) from still
5285 // water level for each timestep
5287
5288 // Case 42: Breaking wave height-to-depth ratio, check that this is a valid
5289 // double
5291
5292 // Case 43: Simulate coast platform erosion?
5294
5295 // Case 44: If simulating coast platform erosion, R (coast platform resistance
5296 // to erosion) values along profile, see Walkden & Hall, 2011
5298 {
5300 }
5301
5302 // Case 45: Simulate beach sediment transport?
5304
5305 // Case 46: If simulating beach sediment transport, beach sediment transport
5306 // at grid edges [0 = closed, 1 = open, 2 = re-circulate]
5308
5309 // Case 47: If simulating beach sediment transport, beach erosion/deposition
5310 // equation [0 = CERC, 1 = Kamphuis]
5312
5313 // Case 48: Median size of fine sediment (mm), always needed [0 = default,
5314 // only for Kamphuis eqn]. First check that this is a valid double
5315 m_dD50Fine = config.GetFineMedianSize();
5316
5317 // Case 49: Median size of sand sediment (mm), always needed [0 = default,
5318 // only for Kamphuis eqn]. First check that this is a valid double
5319 m_dD50Sand = config.GetSandMedianSize();
5320
5321 // Case 50: Median size of coarse sediment (mm), always needed [0 = default,
5322 // only for Kamphuis eqn]. First check that this is a valid double
5324
5325 // Case 51: Density of unconsolidated beach sediment (kg/m3)
5327
5328 // Case 52: Beach sediment porosity
5330
5331 // Case 53: Relative erodibility (0 - 1) of fine-sized sediment, always
5332 // needed. First check that this is a valid double
5334
5335 // Case 54: Relative erodibility (0 - 1) of sand-sized sediment, always
5336 // needed. First check that this is a valid double
5338
5339 // Case 55: Relative erodibility (0 - 1) of coarse-sized sediment, always
5340 // needed. First check that this is a valid double
5342
5343 // Case 56: Transport parameter KLS in CERC equation
5344 m_dKLS = config.GetTransportKLS();
5345
5346 // Case 57: Transport parameter for Kamphuis equation
5347 m_dKamphuis = config.GetKamphuis();
5348
5349 // Case 58: Berm height i.e. height above SWL of start of depositional Dean
5350 // profile
5352
5353 // Case 59: Simulate cliff collapse?
5355
5356 // Case 60: Cliff resistance to erosion
5358 {
5360 }
5361
5362 // Case 61: Notch overhang at collapse (m)
5364 {
5366 }
5367
5368 // Case 62: Notch base below still water level (m)
5370 {
5372 }
5373
5374 // Case 63: Scale parameter A for cliff deposition (m^(1/3)) [0 = auto]
5376 {
5378 }
5379
5380 // Case 64: Approximate planview width of cliff collapse talus (in m)
5382 {
5384 }
5385
5386 // Case 65: Planview length of cliff deposition talus (m)
5388 {
5390 }
5391
5392 // Case 66: Minimum height of landward end of talus, as a fraction of cliff
5393 // elevation
5395 {
5397 }
5398
5399 // Case 67: Simulate riverine flooding?
5400 if (config.GetFloodInput())
5401 {
5402 m_bRiverineFlooding = true;
5406 }
5407
5408 // Case 68: Output riverine flooding vector files
5409 if (config.GetFloodInput())
5410 {
5411 // TODO: This is a guess, please check
5412 vector<string> floodFiles = config.GetFloodFiles();
5413 if (! floodFiles.empty())
5414 {
5415 for (string const &floodCode : floodFiles)
5416 {
5417 string code = floodCode;
5418 std::transform(code.begin(), code.end(), code.begin(), ::tolower);
5419
5420 if (code == "sea_area")
5421 m_bSeaAreaTSSave = true;
5422 }
5423 }
5424 }
5425
5426 // Case 69: Flooding runup equation?
5427 if (config.GetFloodInput())
5428 {
5429 // TODO: This is a guess, please check
5431 }
5432
5433 // Case 70: Somthing unknown relating to riverine flooding
5435 {
5436 // TODO: This is a guess, please check
5437 m_bFloodLocationSave = ! config.GetFloodInputLocation().empty();
5438 }
5439
5440 // Case 71: Somthing unknown relating to riverine flooding
5442 {
5443 // TODO: This is a guess, please check
5445 }
5446
5447 // Case 72: Simulate sediment input?
5448 if (config.GetSedimentInput())
5449 {
5450 m_bSedimentInput = true;
5452 }
5453
5454 // Case 73: Sediment input location (point or line shapefile)
5455 if (m_bSedimentInput)
5456 {
5458 }
5459
5460 // Case 74: Sediment input type: required if have shapefile [P = Point, C =
5461 // coast block, L = line]
5462 if (m_bSedimentInput)
5463 {
5464 strRH = config.GetSedimentInputType();
5465 if (strRH.find('p') != string::npos)
5467
5468 else if (strRH.find('c') != string::npos)
5470
5471 else if (strRH.find('l') != string::npos)
5473 }
5474
5475 // Case 75: Sediment input details file (required if have shapefile)
5476 if (m_bSedimentInput)
5477 {
5479 }
5480
5481 // Case 76: Gravitational acceleration (m2/s). First check that this is a
5482 // valid double
5484
5485 // Case 77: Spacing of coastline normals (m)
5489 DEFAULT_PROFILE_SPACING; // In cells, we will set
5490 // m_dCoastNormalSpacing later when we
5491 // know m_dCellSide
5492
5493 // Case 78: Random factor for spacing of normals [0 to 1, 0 = deterministic],
5494 // check that this is a valid double
5496
5497 // Case 79: Length of coastline normals (m), check that this is a valid double
5499
5500 // Approximate minimum spacing (m) between wave transects for interpolation densification
5502
5503 // Case 80: Start depth for wave calcs (ratio to deep water wave height)check
5504 // that this is a valid double
5506
5507 // Case 81: Output profile data?
5508 // ISSUE: Why are we now only outputing consolidated, this feels like a bodge
5510
5511 // Case 82: Numbers of profiles to be saved
5513 {
5515 }
5516
5517 // Case 83: Timesteps to save profiles
5519 {
5521 }
5522
5523 // Case 84: Output parallel profile data?
5525
5526 // Case 85: Output erosion potential look-up data?
5528
5529 // Case 86: Cliff toe location? approach [0 = none, 1 = by slope threshold]
5530 //TODO: Finish migration
5531 m_bCliffToeLocate = false;
5532
5533 // Case 87: Cliff edge smoothing algorithm: 0 = none, 1 = running mean, 2 =
5534 // Savitzky-Golay
5536
5537 // Case 89: Size of moving window for coastline curvature calculation (must be
5538 // odd)
5540
5541 // Case 90: Cliff slope limit for cliff toe detection
5543
5544 return true;
5545}
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 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.