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