CoastalME (Coastal Modelling Environment)
Simulates the long-term behaviour of complex coastlines
Loading...
Searching...
No Matches
do_shore_platform_erosion.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 <assert.h>
25
26#include <cmath>
27
28#include <iostream>
29using std::cerr;
30using std::cout;
31using std::endl;
32using std::ios;
33
34#include <iomanip>
35using std::setiosflags;
36
37#include <array>
38using std::array;
39
40#include <algorithm>
41using std::shuffle;
42
43#include "cme.h"
44#include "hermite_cubic.h"
45#include "interpolate.h"
46#include "simulation.h"
47#include "coast.h"
48
49//===============================================================================================================================
51//===============================================================================================================================
53{
55 LogStream << m_ulIter << ": Calculating shore platform erosion" << endl;
56
57 // // DEBUG CODE ===========================================================================================================
58 // string strOutFile = m_strOutPath + "01_polygon_shore_platform_test_";
59 // strOutFile += to_string(m_ulIter);
60 // strOutFile += ".tif";
61 //
62 // GDALDriver* pDriver = GetGDALDriverManager()->GetDriverByName("gtiff");
63 // GDALDataset* pDataSet = pDriver->Create(strOutFile.c_str(), m_nXGridSize, m_nYGridSize, 1, GDT_Float64, m_papszGDALRasterOptions);
64 // pDataSet->SetProjection(m_strGDALBasementDEMProjection.c_str());
65 // pDataSet->SetGeoTransform(m_dGeoTransform);
66 // double* pdRaster = new double[m_nXGridSize * m_nYGridSize];
67 // int n = 0;
68 // int nInPoly = 0;
69 // int nNotInPoly = 0;
70 //
71 // for (int nY = 0; nY < m_nYGridSize; nY++)
72 // {
73 // for (int nX = 0; nX < m_nXGridSize; nX++)
74 // {
75 // int nID = m_pRasterGrid->m_Cell[nX][nY].nGetPolygonID();
76 // if (nID == INT_NODATA)
77 // nNotInPoly++;
78 // else
79 // nInPoly++;
80 //
81 // pdRaster[n++] = nID;
82 // }
83 // }
84 //
85 // GDALRasterBand* pBand = pDataSet->GetRasterBand(1);
86 // pBand->SetNoDataValue(m_dMissingValue);
87 // int nRet = pBand->RasterIO(GF_Write, 0, 0, m_nXGridSize, m_nYGridSize, pdRaster, m_nXGridSize, m_nYGridSize, GDT_Float64, 0, 0, NULL);
88 // if (nRet == CE_Failure)
89 // LogStream << nRet << endl;
90 //
91 // GDALClose(pDataSet);
92 // delete[] pdRaster;
93 //
94 // LogStream << m_ulIter << " Number of cells in a polygon = " << nInPoly << endl;
95 // LogStream << m_ulIter << " Number of cells not in any polygon = " << nNotInPoly << endl;
96 // // DEBUG CODE ===========================================================================================================
97
98 // TODO 023 Only do potential erosion if cell is in a polygon
99
100 // Set direction
101 static bool bDownCoast = true;
102
103 // Do this for each coast
104 for (int nCoast = 0; nCoast < static_cast<int>(m_VCoast.size()); nCoast++)
105 {
106 int const nNumProfiles = m_VCoast[nCoast].nGetNumProfiles();
107
108 // Calculate potential platform erosion along each coastline-normal profile, do in down-coast sequence
109 for (int nn = 0; nn < nNumProfiles; nn++)
110 {
111 CGeomProfile* pProfile;
112
113 if (bDownCoast)
114 pProfile = m_VCoast[nCoast].pGetProfileWithDownCoastSeq(nn);
115
116 else
117 pProfile = m_VCoast[nCoast].pGetProfileWithUpCoastSeq(nn);
118
119 int const nRet = nCalcPotentialPlatformErosionOnProfile(nCoast, pProfile);
120
121 if (nRet != RTN_OK)
122 return nRet;
123 }
124
125 // Calculate potential platform erosion between the coastline-normal profiles. Do this in down-coast sequence
126 for (int nn = 0; nn < nNumProfiles - 1; nn++)
127 {
128 CGeomProfile* pProfile = m_VCoast[nCoast].pGetProfileWithDownCoastSeq(nn);
129
130 // Calculate potential erosion for sea cells between this profile and the next profile (or up to the edge of the grid) on these cells
132
133 if (nRet != RTN_OK)
134 return nRet;
135
137
138 if (nRet != RTN_OK)
139 return nRet;
140 }
141 }
142
143 // Swap direction for next timestep
144 bDownCoast = ! bDownCoast;
145
146 // Fills in 'holes' in the potential platform erosion i.e. orphan cells which get omitted because of rounding problems
148
149 // Do the same for beach protection
151
152 // Finally calculate actual platform erosion on all sea cells (both on profiles, and between profiles)
153 for (int nX = 0; nX < m_nXGridSize; nX++)
154 {
155 for (int nY = 0; nY < m_nYGridSize; nY++)
156 {
157 if (m_pRasterGrid->m_Cell[nX][nY].bPotentialPlatformErosion())
158 // Calculate actual (supply-limited) shore platform erosion on each cell that has potential platform erosion, also add the eroded sand/coarse sediment to that cell's polygon, ready to be redistributed within the polygon during beach erosion/deposition
160 }
161 }
162
164 {
165 LogStream << m_ulIter << ": total potential shore platform erosion (m^3) = " << m_dThisIterPotentialPlatformErosion * m_dCellArea << " (on profiles = " << m_dTotPotentialPlatformErosionOnProfiles * m_dCellArea << ", between profiles = " << m_dTotPotentialPlatformErosionBetweenProfiles * m_dCellArea << ")" << endl;
166
168 }
169
170 return RTN_OK;
171}
172
173//===============================================================================================================================
175//===============================================================================================================================
177{
178 // Only work on this profile if it is problem-free TODO 024 Or if it has just hit dry land?
179 if (! pProfile->bOKIncStartAndEndOfCoast()) // || (pProfile->nGetProblemCode() == PROFILE_DRYLAND))
180 return RTN_OK;
181
182 // Get the length of the profile (in cells) and the index of the coast point at which this profile starts
183 int const nProfSize = pProfile->nGetNumCellsInProfile();
184 int const nCoastPoint = pProfile->nGetCoastPoint();
185
186 // Get the breaking depth for this profile from the coastline point
187 double dDepthOfBreaking = m_VCoast[nCoast].dGetDepthOfBreaking(nCoastPoint);
188
189 if (bFPIsEqual(dDepthOfBreaking, DBL_NODATA, TOLERANCE))
190 // This profile is not in the active zone, so no platform erosion here
191 return RTN_OK;
192
193 if (bFPIsEqual(dDepthOfBreaking, 0.0, TOLERANCE))
194 {
195 // Safety check, altho' this shouldn't happen
197 LogStream << m_ulIter << ": depth of breaking is zero for profile " << pProfile->nGetCoastID() << " of coast " << nCoast << endl;
198
199 return RTN_OK;
200 }
201
202 // LogStream << m_ulIter << ": ON PROFILE nProfile = " << nProfile << " dDepthOfBreaking = " << dDepthOfBreaking << endl;
203
204 // Get the height of the associated breaking wave from the coast point: this height is used in beach protection calcs
205 double const dBreakingWaveHeight = m_VCoast[nCoast].dGetBreakingWaveHeight(nCoastPoint);
206
207 // Calculate the length of the profile in external CRS units
208 int const nSegments = pProfile->nGetProfileSize() - 1;
209 double dProfileLenXY = 0;
210
211 for (int nSeg = 0; nSeg < nSegments; nSeg++)
212 {
213 // Do once for every line segment
214 double const dSegStartX = pProfile->pPtGetPointInProfile(nSeg)->dGetX();
215 double const dSegStartY = pProfile->pPtGetPointInProfile(nSeg)->dGetY();
216 double const dSegEndX = pProfile->pPtGetPointInProfile(nSeg + 1)->dGetX(); // Is OK
217 double const dSegEndY = pProfile->pPtGetPointInProfile(nSeg + 1)->dGetY();
218
219 double const dSegLen = hypot(dSegStartX - dSegEndX, dSegStartY - dSegEndY);
220 dProfileLenXY += dSegLen;
221 }
222
223 // Next calculate the average distance between profile points, again in external CRS units. Assume that the sample points are equally spaced along the profile (not quite true)
224 double const dSpacingXY = dProfileLenXY / (nProfSize - 1);
225
226 // Set up vectors for the coastline-normal profile elevations. The length of this vector line is given by the number of cells 'under' the profile. Thus each point on the vector relates to a single cell in the grid. This assumes that all points on the profile vector are equally spaced (not quite true, depends on the orientation of the line segments which comprise the profile)
227 // The elevation of each of these profile points is the elevation of the centroid of the cell that is 'under' the point. However we cannot always be confident that this is the 'true' elevation of the point on the vector since (unless the profile runs planview N-S or W-E) the vector does not always run exactly through the centroid of the cell
228 vector<double> VdProfileZ(nProfSize, 0); // Initial (pre-erosion) elevation of both consolidated and unconsolidated sediment for cells 'under' the profile
229 vector<double> VdProfileDistXY(nProfSize, 0); // Along-profile distance measured from the coast, in external CRS units
230 vector<double> dVConsProfileZ(nProfSize, 0); // Initial (pre-erosion) elevation of consolidated sediment only for cells 'under' the profile
231 vector<double> dVConsZDiff(nProfSize, 0);
232 vector<double> dVConsSlope(nProfSize, 0);
233
234 for (int i = 0; i < nProfSize; i++)
235 {
236 int const nX = pProfile->pPtiVGetCellsInProfile()->at(i).nGetX();
237 int const nY = pProfile->pPtiVGetCellsInProfile()->at(i).nGetY();
238
239 // Get the number of the highest layer with non-zero thickness
240 int const nTopLayer = m_pRasterGrid->m_Cell[nX][nY].nGetTopNonZeroLayerAboveBasement();
241
242 // Safety check
243 if (nTopLayer == INT_NODATA)
245
246 if (nTopLayer == NO_NONZERO_THICKNESS_LAYERS)
247 // TODO 025 We are down to basement
248 return RTN_OK;
249
250 // Get the elevation for consolidated sediment only on this cell
251 dVConsProfileZ[i] = m_pRasterGrid->m_Cell[nX][nY].dGetConsSedTopForLayerAboveBasement(nTopLayer);
252
253 // Get the elevation for both consolidated and unconsolidated sediment on this cell
254 VdProfileZ[i] = m_pRasterGrid->m_Cell[nX][nY].dGetSedimentTopElev();
255
256 // And store the X-Y plane distance from the start of the profile
257 VdProfileDistXY[i] = i * dSpacingXY;
258 }
259
260 for (int i = 0; i < nProfSize - 1; i++)
261 {
262 // For the consolidated-only profile, get the Z differences (already in external CRS units)
263 dVConsZDiff[i] = dVConsProfileZ[i] - dVConsProfileZ[i + 1];
264
265 // Calculate dZ/dXY, the Z slope (i.e. rise over run) in the XY direction. Note that we use the elevation difference on the seaward side of 'this' point
266 dVConsSlope[i] = dVConsZDiff[i] / dSpacingXY;
267 }
268
269 // Sort out the final value
270 dVConsSlope[nProfSize - 1] = dVConsSlope[nProfSize - 2];
271
273 {
274 // Smooth the vector of slopes for the consolidated-only profile
275 dVConsSlope = dVSmoothProfileSlope(&dVConsSlope);
276 }
277
278 vector<double> dVProfileDepthOverDB(nProfSize, 0); // Depth over wave breaking depth at the coastline-normal sample points
279 vector<double> dVProfileErosionPotential(nProfSize, 0); // Erosion potential at the coastline-normal sample points
280
281 // Calculate the erosion potential along this profile using the shape function
282 double dTotalErosionPotential = 0;
283
284 for (int i = 0; i < nProfSize; i++)
285 {
286 // Use the actual depth of water here (i.e. the depth to the top of the unconsolidated sediment, including the thickness of consolidated sediment beneath it)
287 dVProfileDepthOverDB[i] = m_dThisIterSWL - VdProfileZ[i];
288 dVProfileDepthOverDB[i] /= dDepthOfBreaking;
289
290 // Constrain dDepthOverDB[i] to be between 0 (can get small -ve values due to rounding errors) and m_dDepthOverDBMax
291 dVProfileDepthOverDB[i] = tMax(dVProfileDepthOverDB[i], 0.0);
292 dVProfileDepthOverDB[i] = tMin(dVProfileDepthOverDB[i], m_dDepthOverDBMax);
293
294 // And then use the look-up table to find the value of erosion potential at this point on the profile
295 dVProfileErosionPotential[i] = dLookUpErosionPotential(dVProfileDepthOverDB[i]);
296
297 // If erosion potential (a -ve value) is tiny, set it to zero
298 if (dVProfileErosionPotential[i] > -SEDIMENT_ELEV_TOLERANCE)
299 dVProfileErosionPotential[i] = 0;
300
301 // Keep track of the total erosion potential for this profile
302 dTotalErosionPotential += dVProfileErosionPotential[i];
303 }
304
305 // Constrain erosion potential at every point on the profile, so that the integral of erosion potential on the whole profile is unity (Walkden and Hall 2005). Note that here, erosion potential is -ve so we must constrain to -1
306 for (int i = 0; i < nProfSize; i++)
307 {
308 if (dTotalErosionPotential < 0)
309 dVProfileErosionPotential[i] /= (-dTotalErosionPotential);
310 }
311
312 vector<double> dVRecessionXY(nProfSize, 0);
313 vector<double> dVSCAPEXY(nProfSize, 0);
314
315 // Calculate recession at every point on the coastline-normal profile
316 for (int i = 0; i < nProfSize; i++)
317 {
318 // dRecession = dForce * (dBeachProtection / dR) * dErosionPotential * dSlope * dTime where:
319 // dVRecession [m] is the landward migration distance defined in the profile relative (XY) CRS
320 // dForce is given by Equation 4 in Walkden & Hall, 2005
321 // dVBeachProtection [1] is beach protection factor [1, 0] = [no protection, fully protected]. (This is calculated later, see dCalcBeachProtectionFactor())
322 // dVR [m^(9/4)s^(2/3)] is the material strength and some hydrodynamic constant
323 // dVProfileErosionPotential [?] is the erosion potential at each point along the profile
324 // dVSlope [1] is the along-profile slope
325 // m_dTimeStep * 3600 [s] is the time interval in seconds
326 //
327 // dRecession is horizontal recession (along the XY direction):
328 //
329 // dVRecessionXY[i] = (dForce * dVBeachProtection[i] * dVErosionPotentialFunc[i] * dVSlope[i] * m_dTimeStep * 3600) / dVR[i]
330 //
331 // XY recession must be -ve or zero. If it is +ve then it represents accretion not erosion, which must be described by a different set of equations. So we also need to constrain XY recession to be <= 0
332 dVRecessionXY[i] = tMin(m_VCoast[nCoast].dGetWaveEnergyAtBreaking(nCoastPoint) * dVProfileErosionPotential[i] * dVConsSlope[i] / m_dR, 0.0);
333 dVSCAPEXY[i] = VdProfileDistXY[i] - dVRecessionXY[i];
334 }
335
336 vector<double> dVChangeElevZ(nProfSize, 0);
337
338 // We have calculated the XY-plane recession at every point on the profile, so now convert this to a change in Z-plane elevation at every inundated point on the profile (not the coast point). Again we use the elevation difference on the seaward side of 'this' point
339 for (int i = 1; i < nProfSize - 1; i++)
340 {
341 // Vertical lowering dZ = dXY * tan(a), where tan(a) is the slope of the SCAPE profile in the XY direction
342 double dSCAPEHorizDist = dVSCAPEXY[i + 1] - dVSCAPEXY[i];
343 double dSCAPEVertDist = dVConsProfileZ[i] - dVConsProfileZ[i + 1];
344 double dSCAPESlope = dSCAPEVertDist / dSCAPEHorizDist;
345 double dDeltaZ = dVRecessionXY[i] * dSCAPESlope;
346
347 // Safety check: if thickness model has some jumps, dVConsProfileZ might be very high, limiting dSCAPESlope to 0 because all time erode a high fix quantity
348 if (dSCAPESlope > 1)
349 {
350 dDeltaZ = 0;
351 }
352
353 int const nX = pProfile->pPtiVGetCellsInProfile()->at(i).nGetX();
354 int const nY = pProfile->pPtiVGetCellsInProfile()->at(i).nGetY();
355
356 // Store the local slope of the consolidated sediment, this is just for output display purposes
357 m_pRasterGrid->m_Cell[nX][nY].SetLocalConsSlope(dVConsSlope[i]);
358
359 // dDeltaZ is zero or -ve: if dDeltaZ is zero then do nothing, if -ve then remove some sediment from this cell
360 if (dDeltaZ < 0)
361 {
362 // If there has already been potential erosion on this cell, then it must be a shared line segment (i.e. has co-incident profiles)
363 double dPrevPotentialErosion = -m_pRasterGrid->m_Cell[nX][nY].dGetPotentialPlatformErosion();
364
365 if (dPrevPotentialErosion < 0)
366 {
367 // Average the two values
368 // LogStream << m_ulIter << ": [" << nX << "][" << nY << "] under profile " << nProfile << " has previous potential platform erosion = " << dPrevPotentialErosion << endl;
369 dDeltaZ = ((dDeltaZ + dPrevPotentialErosion) / 2);
370 }
371
372 // Constrain the lowering so we don't get negative slopes or +ve erosion amounts (dDeltaZ must be -ve), this is implicit in SCAPE
373 dDeltaZ = tMax(dDeltaZ, -dVConsZDiff[i]);
374 dDeltaZ = tMin(dDeltaZ, 0.0);
375 dVChangeElevZ[i] = dDeltaZ;
376
377 // Set the potential (unconstrained) erosion for this cell, is a +ve value
378 m_pRasterGrid->m_Cell[nX][nY].SetPotentialPlatformErosion(-dDeltaZ);
379
380 // Update this-timestep totals
382 m_dThisIterPotentialPlatformErosion -= dDeltaZ; // Since dDeltaZ is a -ve value
383// assert(isfinite(m_dThisIterPotentialPlatformErosion));
384// assert(m_dThisIterPotentialPlatformErosion >= 0);
385
386 // Increment the check values
389 }
390
391 // Finally, calculate the beach protection factor, this will be used in estimating actual (supply-limited) erosion
392 double dBeachProtectionFactor = dCalcBeachProtectionFactor(nX, nY, dBreakingWaveHeight);
393 m_pRasterGrid->m_Cell[nX][nY].SetBeachProtectionFactor(dBeachProtectionFactor);
394 }
395
396 // If desired, save this coastline-normal profile data for checking purposes
398 {
399 int nRet = nSaveProfile(nCoast, pProfile, nProfSize, &VdProfileDistXY, &dVConsProfileZ, &dVProfileDepthOverDB, &dVProfileErosionPotential, &dVConsSlope, &dVRecessionXY, &dVChangeElevZ, pProfile->pPtiVGetCellsInProfile(), &dVSCAPEXY);
400
401 if (nRet != RTN_OK)
402 return nRet;
403 }
404
405 return RTN_OK;
406}
407
408//===============================================================================================================================
410//===============================================================================================================================
411int CSimulation::nCalcPotentialPlatformErosionBetweenProfiles(int const nCoast, CGeomProfile* pProfile, int const nDirection)
412{
413 // Only work on this profile if it is problem-free
414 if (! pProfile->bOKIncStartAndEndOfCoast())
415 return RTN_OK;
416
417 int const nProfSize = pProfile->nGetNumCellsInProfile();
418 int const nCoastProfileStart = pProfile->nGetCoastPoint();
419 int const nProfileStartX = pProfile->pPtiVGetCellsInProfile()->at(0).nGetX();
420 int const nProfileStartY = pProfile->pPtiVGetCellsInProfile()->at(0).nGetY();
421 int const nCoastMax = m_VCoast[nCoast].nGetCoastlineSize();
422 int nDistFromProfile = 0;
423 int nParCoastXLast = nProfileStartX;
424 int nParCoastYLast = nProfileStartY;
425
426 // Start at the coast end of this coastline-normal profile, then move one cell forward along the coast, then construct a parallel profile from this new coastline start cell. Calculate erosion along this parallel profile in the same way as above. Move another cell forward along the coastline, do the same. Keep going until hit another profile
427 while (true)
428 {
429 // Increment the distance from the start coast-normal profile
430 nDistFromProfile++;
431
432 // Start the parallel profile nDistFromProfile cells along the coastline from the coastline-normal profile, direction depending on nDirection
433 int nThisPointOnCoast = nCoastProfileStart;
434
435 if (nDirection == DIRECTION_DOWNCOAST)
436 nThisPointOnCoast += nDistFromProfile;
437
438 else
439 nThisPointOnCoast -= nDistFromProfile;
440
441 // Have we reached the beginning of the coast?
442 if ((nDirection == DIRECTION_UPCOAST) && (nThisPointOnCoast < 0))
443 {
444// LogStream << m_ulIter << ": LEAVING LOOP since hit nThisPointOnCoast = " << nThisPointOnCoast << " while doing potential platform erosion " << (nDirection == DIRECTION_DOWNCOAST ? "down" : "up") << "-coast from profile = " << nProfile << ", dist from profile = " << nDistFromProfile << endl;
445
446 break;
447 }
448
449 // Have we reached the end of the coast?
450 if ((nDirection == DIRECTION_DOWNCOAST) && (nThisPointOnCoast >= nCoastMax))
451 {
452 // LogStream << m_ulIter << ": LEAVING LOOP since hit nThisPointOnCoast = " << nThisPointOnCoast << " while doing potential platform erosion " << (nDirection == DIRECTION_DOWNCOAST ? "down" : "up") << "-coast from profile = " << nProfile << ", dist from profile = " << nDistFromProfile << endl;
453
454 break;
455 }
456
457 // LogStream << m_ulIter << ": from profile " << nProfile << ", doing potential platform erosion " << (nDirection == DIRECTION_DOWNCOAST ? "down" : "up") << "-coast, dist from profile = " << nDistFromProfile << endl;
458
459 double dDepthOfBreaking = m_VCoast[nCoast].dGetDepthOfBreaking(nThisPointOnCoast);
460
461 if (bFPIsEqual(dDepthOfBreaking, DBL_NODATA, TOLERANCE))
462 {
463 // This parallel profile is not in the active zone, so no platform erosion here. Move on to the next point along the coastline in this direction
464 // if (m_nLogFileDetail == LOG_FILE_ALL)
465 // LogStream << m_ulIter << ": not in active zone at coastline " << nCoast << " coast point " << nThisPointOnCoast << " when constructing parallel profile for potential platform erosion. Working from profile " << pProfile->nGetCoastID() << ", " << (nDirection == DIRECTION_DOWNCOAST ? "down" : "up") << "-coast, dist from profile = " << nDistFromProfile << endl;
466
467 continue;
468 }
469
470// LogStream << m_ulIter << ": BETWEEN PROFILES " << (nDirection == DIRECTION_DOWNCOAST ? "down" : "up") << "-coast from profile " << nProfile << " nThisPointOnCoast = " << nThisPointOnCoast << " dDepthOfBreaking = " << dDepthOfBreaking << " nParProfSize = " << nParProfSize << endl;
471
472 // All is OK, so get the grid coordinates of this point, which is the coastline start point for the parallel profile
473 int const nParCoastX = m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(nThisPointOnCoast)->nGetX();
474 int const nParCoastY = m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(nThisPointOnCoast)->nGetY();
475
476 if ((nParCoastX == nParCoastXLast) && (nParCoastY == nParCoastYLast))
477 {
478 // Should not happen, but could do due to rounding errors
480 LogStream << WARN << m_ulIter << ": rounding problem on coast " << nCoast << " profile " << pProfile->nGetCoastID() << " at [" << nParCoastX << "][" << nParCoastY << "]" << endl;
481
482 // So move on to the next point along the coastline in this direction
483 continue;
484 }
485
486 // Is this coastline start point the start point of an adjacent coastline-normal vector?
487 if (m_pRasterGrid->m_Cell[nParCoastX][nParCoastY].bIsProfile())
488 {
489// LogStream << m_ulIter << ": coast " << nCoast << ", LEAVING LOOP since hit another profile at nThisPointOnCoast = " << nThisPointOnCoast << " while doing potential platform erosion " << (nDirection == DIRECTION_DOWNCOAST ? "down" : "up") << "-coast from profile = " << nProfile << ", dist from profile = " << nDistFromProfile << endl;
490 break;
491 }
492
493 // Get the height of the associated breaking wave from the coast point: this height is used in beach protection calcs. Note that it will be DBL_NODATA if not in active zone
494 double const dBreakingWaveHeight = m_VCoast[nCoast].dGetBreakingWaveHeight(nThisPointOnCoast);
495
496 // OK, now construct a parallel profile
497 vector<CGeom2DIPoint> PtiVGridParProfile; // Integer coords (grid CRS) of cells under the parallel profile
498 vector<CGeom2DPoint> PtVExtCRSParProfile; // coordinates (external CRS) of cells under the parallel profile
499
500 ConstructParallelProfile(nProfileStartX, nProfileStartY, nParCoastX, nParCoastY, nProfSize, pProfile->pPtiVGetCellsInProfile(), &PtiVGridParProfile, &PtVExtCRSParProfile);
501
502 int const nParProfSize = static_cast<int>(PtiVGridParProfile.size());
503
504 // We have a parallel profile which starts at the coast, but is it long enough to be useful? May have been cut short because it extended outside the grid, or we hit an adjacent profile
505 if (nParProfSize < 3)
506 {
507 // We cannot use this parallel profile, it is too short to calculate along-profile slope, so abandon it and move on to the next parallel profile in this direction
508 nParCoastXLast = nParCoastX;
509 nParCoastYLast = nParCoastY;
510 // LogStream << m_ulIter << ": parallel profile abandoned since too short, starts at [" << nParCoastX << "][" << nParCoastY << "] coastline point " << nThisPointOnCoast << ", length = " << nParProfSize << endl;
511 continue;
512 }
513
514 // This parallel profile is OK, so calculate potential erosion along it. First calculate the length of the parallel profile in external CRS units
515 double const dParProfileLenXY = dGetDistanceBetween(&PtVExtCRSParProfile[0], &PtVExtCRSParProfile[nParProfSize - 1]);
516
517 // Next calculate the distance between profile points, again in external CRS units. Assume that the sample points are equally spaced along the parallel profile (not quite true)
518 double dParSpacingXY = dParProfileLenXY / (nParProfSize - 1);
519
520 // Safety check
521 if (bFPIsEqual(dParSpacingXY, 0.0, TOLERANCE))
522 dParSpacingXY = TOLERANCE;
523
524 // LogStream << "dParSpacingXY = " << dParSpacingXY << endl;
525
526 vector<double> dVParProfileZ(nParProfSize, 0); // Initial (pre-erosion) elevation of both consolidated and unconsolidated sediment for cells 'under' the parallel profile
527 vector<double> dVParProfileDistXY(nParProfSize, 0); // Along-profile distance measured from the coast, in external CRS units
528 vector<double> dVParConsProfileZ(nParProfSize, 0); // Initial (pre-erosion) elevation of consolidated sediment only for cells 'under' the parallel profile
529 vector<double> dVParConsZDiff(nParProfSize, 0);
530 vector<double> dVParConsSlope(nParProfSize, 0);
531
532 for (int i = 0; i < nParProfSize; i++)
533 {
534 int const nXPar = PtiVGridParProfile[i].nGetX();
535 int const nYPar = PtiVGridParProfile[i].nGetY();
536
537 // Is this a sea cell?
538 if (! m_pRasterGrid->m_Cell[nXPar][nYPar].bIsInundated())
539 {
540 // It isn't so move along, nothing to do here
541 // LogStream << m_ulIter << " : [" << nXPar << "][" << nYPar << "] is not inundated" << endl;
542 continue;
543 }
544
545 // Is this cell in a polygon?
546 int nPolyID = m_pRasterGrid->m_Cell[nXPar][nYPar].nGetPolygonID();
547
548 if (nPolyID == INT_NODATA)
549 {
550 // It isn't. This can happen at the seaward end of polygons TODO 026 Is it a problem?
551 // LogStream << m_ulIter << " : [" << nXPar << "][" << nYPar << "] = {" << dGridCentroidXToExtCRSX(nXPar) << ", " << dGridCentroidYToExtCRSY(nYPar) << "} is not in a polygon" << endl;
552 continue;
553 }
554
555 // Get the number of the highest layer with non-zero thickness
556 int const nTopLayer = m_pRasterGrid->m_Cell[nXPar][nYPar].nGetTopNonZeroLayerAboveBasement();
557
558 // Safety check
559 if (nTopLayer == INT_NODATA)
561
562 if (nTopLayer == NO_NONZERO_THICKNESS_LAYERS)
563 // TODO 025 We are down to basement
564 return RTN_OK;
565
566 // Get the elevation for consolidated sediment only on this cell
567 dVParConsProfileZ[i] = m_pRasterGrid->m_Cell[nXPar][nYPar].dGetConsSedTopForLayerAboveBasement(nTopLayer);
568
569 // Get the elevation for both consolidated and unconsolidated sediment on this cell
570 dVParProfileZ[i] = m_pRasterGrid->m_Cell[nXPar][nYPar].dGetSedimentTopElev();
571
572 // And store the X-Y plane distance from the start of the profile
573 dVParProfileDistXY[i] = i * dParSpacingXY;
574 }
575
576 for (int i = 0; i < nParProfSize - 1; i++)
577 {
578 // For the consolidated-only profile, get the Z differences (already in external CRS units)
579 dVParConsZDiff[i] = dVParConsProfileZ[i] - dVParConsProfileZ[i + 1];
580
581 // Calculate dZ/dXY, the Z slope (i.e. rise over run) in the XY direction. Note that we use the elevation difference on the seaward side of 'this' point
582 dVParConsSlope[i] = dVParConsZDiff[i] / dParSpacingXY;
583 }
584
585 // Sort out the final slope value
586 dVParConsSlope[nParProfSize - 1] = dVParConsSlope[nParProfSize - 2];
587
589 {
590 // Smooth the vector of slopes for the consolidated-only profile
591 dVParConsSlope = dVSmoothProfileSlope(&dVParConsSlope);
592 }
593
594 // Initialize the parallel profile vector with depth / m_dWaveBreakingDepth
595 vector<double> dVParProfileDepthOverDB(nParProfSize, 0); // Depth / wave breaking depth at the parallel profile sample points
596 vector<double> dVParProfileErosionPotential(nParProfSize, 0); // Erosion potential at the parallel profile sample points
597
598 // Calculate the erosion potential along this profile using the shape function which we read in earlier
599 double dTotalErosionPotential = 0;
600
601 // Safety check TODO 061 Is this safety check to depth of breaking a reasonable thing to do?
602 if (dDepthOfBreaking <= 0.0)
603 dDepthOfBreaking = 1e-10;
604
605 for (int i = 0; i < nParProfSize; i++)
606 {
607 // Use the actual depth of water here (i.e. the depth to the top of the unconsolidated sediment, including the thickness of consolidated sediment beneath it)
608 dVParProfileDepthOverDB[i] = m_dThisIterSWL - dVParProfileZ[i];
609 dVParProfileDepthOverDB[i] /= dDepthOfBreaking;
610
611 // Constrain dDepthOverDB[i] to be between 0 (can get small -ve due to rounding errors) and m_dDepthOverDBMax
612 dVParProfileDepthOverDB[i] = tMax(dVParProfileDepthOverDB[i], 0.0);
613 dVParProfileDepthOverDB[i] = tMin(dVParProfileDepthOverDB[i], m_dDepthOverDBMax);
614
615 // And then use the look-up table to find the value of erosion potential at this point on the profile
616 dVParProfileErosionPotential[i] = dLookUpErosionPotential(dVParProfileDepthOverDB[i]);
617
618 // If erosion potential (a -ve value) is tiny, set it to zero
619 if (dVParProfileErosionPotential[i] > -SEDIMENT_ELEV_TOLERANCE)
620 dVParProfileErosionPotential[i] = 0;
621
622 // Keep track of the total erosion potential for this profile
623 dTotalErosionPotential += dVParProfileErosionPotential[i];
624 }
625
626 // Constrain erosion potential at every point on the profile, so that the integral of erosion potential on the whole profile is unity (Walkden and Hall 2005). Note that here, erosion potential is -ve so we must constrain to -1
627 for (int i = 0; i < nParProfSize; i++)
628 {
629 if (dTotalErosionPotential < 0)
630 dVParProfileErosionPotential[i] /= (-dTotalErosionPotential);
631 }
632
633 vector<double> dVParRecessionXY(nParProfSize, 0);
634 vector<double> dVParSCAPEXY(nParProfSize, 0);
635
636 // Calculate recession at every point on the parallel profile
637 for (int i = 0; i < nParProfSize; i++)
638 {
639 // dRecession = dForce * (dBeachProtection / dR) * dErosionPotential * dSlope * dTime
640 // where:
641 // dVRecession [m] is the landward migration distance defined in the profile relative (XY) CRS
642 // dForce is given by Equation 4 in Walkden & Hall, 2005
643 // dVBeachProtection [1] is beach protection factor [1, 0] = [no protection, fully protected] (This is calculated later, see dCalcBeachProtectionFactor())
644 // dVR [m^(9/4)s^(2/3)] is the material strength and some hydrodynamic constant
645 // dVProfileErosionPotential [?] is the erosion potential at each point along the profile
646 // dVSlope [1] is the along-profile slope
647 // m_dTimeStep * 3600 [s] is the time interval in seconds
648 //
649 // dRecession is horizontal recession (along the XY direction):
650 //
651 // dVRecessionXY[i] = (dForce * dVBeachProtection[i] * dVErosionPotentialFunc[i] * dVSlope[i] * m_dTimeStep * 3600) / dVR[i]
652 //
653 //
654 // XY recession must be -ve or zero. If it is +ve then it represents accretion not erosion, which must be described by a different set of equations. So we also need to constrain XY recession to be <= 0
655 dVParRecessionXY[i] = tMin(m_VCoast[nCoast].dGetWaveEnergyAtBreaking(nThisPointOnCoast) * dVParProfileErosionPotential[i] * dVParConsSlope[i] / m_dR, 0.0);
656 dVParSCAPEXY[i] = dVParProfileDistXY[i] - dVParRecessionXY[i];
657
658 // LogStream << m_ulIter << ": [" << nXPar << "][" << nYPar << "] = {" << dGridCentroidXToExtCRSX(nXPar) << ", " << dGridCentroidYToExtCRSY(nYPar) << "} wave energy = " << m_VCoast[nCoast].dGetWaveEnergyAtBreaking(nThisPointOnCoast) << " erosion potential = " << dVParProfileErosionPotential[i] << " slope = " << dVParProfileSlope[i] << " dVParZDiff[i] = " << dVParZDiff[i] << " nParProfSize = " << nParProfSize << endl;
659 }
660
661 vector<double> dVParDeltaZ(nParProfSize, 0);
662
663 // We have calculated the XY-plane recession at every point on the profile, so now convert this to a change in Z-plane elevation at every inundated point on the profile (not the coast point). Again we use the elevation difference on the seaward side of 'this' point
664 for (int i = 1; i < nParProfSize - 1; i++)
665 {
666 // Vertical lowering dZ = dXY * tan(a), where tan(a) is the slope of the SCAPE profile in the XY direction
667 double dSCAPEHorizDist = dVParSCAPEXY[i + 1] - dVParSCAPEXY[i];
668
669 // Safety check
670 if (bFPIsEqual(dSCAPEHorizDist, 0.0, TOLERANCE))
671 continue;
672
673 double dSCAPEVertDist = dVParConsProfileZ[i] - dVParConsProfileZ[i + 1];
674 double dSCAPESlope = dSCAPEVertDist / dSCAPEHorizDist;
675 double dDeltaZ = dVParRecessionXY[i] * dSCAPESlope;
676
677 // Safety check: if thickness model has some jumps, dVConsProfileZ might be very high, limiting dSCAPESlope to 0 because all time erode a high fix quantity
678 if (dSCAPESlope > 1)
679 {
680 dDeltaZ = 0;
681 }
682
683 int const nXPar = PtiVGridParProfile[i].nGetX();
684 int const nYPar = PtiVGridParProfile[i].nGetY();
685
686 // Store the local slope of the consolidated sediment, this is just for output display purposes
687 m_pRasterGrid->m_Cell[nXPar][nYPar].SetLocalConsSlope(dVParConsSlope[i]);
688
689 // dDeltaZ is zero or -ve: if dDeltaZ is zero then do nothing, if -ve then remove some sediment from this cell
690 if (dDeltaZ < 0)
691 {
692 // Has this cell already been eroded during this timestep?
693 if (m_pRasterGrid->m_Cell[nXPar][nYPar].bPotentialPlatformErosion())
694 {
695 // It has
696 double const dPrevPotentialErosion = -m_pRasterGrid->m_Cell[nXPar][nYPar].dGetPotentialPlatformErosion();
697
698 // LogStream << m_ulIter << ": [" << nXPar << "][" << nYPar << "] parallel profile " << nDistFromProfile << " coast points " << (nDirection == DIRECTION_DOWNCOAST ? "down" : "up") << "-coast from profile " << nProfile << " has previous potential platform erosion = " << dPrevPotentialErosion << ", current potential platform erosion = " << dDeltaZ << ", max value = " << tMin(dPrevPotentialErosion, dDeltaZ) << endl;
699
700 // Use the larger of the two -ve values
701 dDeltaZ = tMin(dPrevPotentialErosion, dDeltaZ);
702
703 // Adjust this-timestep totals, since this cell has already been eroded
705 m_dThisIterPotentialPlatformErosion += dPrevPotentialErosion; // Since dPrevPotentialErosion is +ve
706 // assert(isfinite(m_dThisIterPotentialPlatformErosion));
707 // assert(m_dThisIterPotentialPlatformErosion >= 0);
708
709 // And also adjust the check values
711 m_dTotPotentialPlatformErosionBetweenProfiles += dPrevPotentialErosion; // Since -ve
712 }
713
714 // Constrain the lowering so we don't get negative slopes or +ve erosion amounts (dDeltaZ must be -ve), this is implicit in SCAPE
715 dDeltaZ = tMax(dDeltaZ, -dVParConsZDiff[i]);
716 dDeltaZ = tMin(dDeltaZ, 0.0);
717 dVParDeltaZ[i] = dDeltaZ;
718
719 // Set the potential (unconstrained) erosion for this cell, it is a +ve value
720 m_pRasterGrid->m_Cell[nXPar][nYPar].SetPotentialPlatformErosion(-dDeltaZ);
721// LogStream << "[" << nXPar << "][" << nYPar << "] = {" << dGridCentroidXToExtCRSX(nXPar) << ", " << dGridCentroidYToExtCRSY(nYPar) << "} has potential platform erosion = " << -dDeltaZ << endl;
722
723 // Update this-timestep totals
725 m_dThisIterPotentialPlatformErosion -= dDeltaZ; // Since dDeltaZ is a -ve value
726// assert(isfinite(m_dThisIterPotentialPlatformErosion));
727// assert(m_dThisIterPotentialPlatformErosion >= 0);
728
729 // Increment the check values
731 m_dTotPotentialPlatformErosionBetweenProfiles -= dDeltaZ; // Since -ve
732 }
733
734 // Finally, calculate the beach protection factor, this will be used in estimating actual (supply-limited) erosion
735 double const dBeachProtectionFactor = dCalcBeachProtectionFactor(nXPar, nYPar, dBreakingWaveHeight);
736 m_pRasterGrid->m_Cell[nXPar][nYPar].SetBeachProtectionFactor(dBeachProtectionFactor);
737 }
738
739 // If desired, save this parallel coastline-normal profile for checking purposes
741 {
742 int const nRet = nSaveParProfile(nCoast, pProfile, nParProfSize, nDirection, nDistFromProfile, &dVParProfileDistXY, &dVParConsProfileZ, &dVParProfileDepthOverDB, &dVParProfileErosionPotential, &dVParConsSlope, &dVParRecessionXY, &dVParDeltaZ, pProfile->pPtiVGetCellsInProfile(), &dVParSCAPEXY);
743
744 if (nRet != RTN_OK)
745 return nRet;
746 }
747
748 // Update for next time round the loop
749 nParCoastXLast = nParCoastX;
750 nParCoastYLast = nParCoastY;
751 }
752
753 return RTN_OK;
754}
755
756//===============================================================================================================================
758//===============================================================================================================================
759void CSimulation::DoActualPlatformErosionOnCell(int const nX, int const nY)
760{
761// LogStream << m_ulIter << ": doing platform erosion on cell [" << nX << "][" << nY << "] = {" << dGridCentroidXToExtCRSX(nX) << ", " << dGridCentroidYToExtCRSY(nY) << "}" << endl;
762
763 // Get the beach protection factor, which quantifies the extent to which unconsolidated sediment on the shore platform (beach) protects the shore platform
764 double const dBeachProtectionFactor = m_pRasterGrid->m_Cell[nX][nY].dGetBeachProtectionFactor();
765
766 if (bFPIsEqual(dBeachProtectionFactor, 0.0, TOLERANCE))
767 // The beach is sufficiently thick to prevent any platform erosion (or we are down to basement)
768 return;
769
770 // Get the potential depth of potential erosion, considering beach protection
771 double dThisPotentialErosion = m_pRasterGrid->m_Cell[nX][nY].dGetPotentialPlatformErosion() * dBeachProtectionFactor;
772
773 // We will be eroding the topmost layer that has non-zero thickness
774 int nThisLayer = m_pRasterGrid->m_Cell[nX][nY].nGetTopNonZeroLayerAboveBasement();
775
776 // Safety check
777 if (nThisLayer == INT_NODATA)
778 {
779 cerr << ERR << "no sediment layer in DoActualPlatformErosionOnCell()" << endl;
780 return;
781 }
782
783 if (nThisLayer == NO_NONZERO_THICKNESS_LAYERS)
784 // No layer with non-zero thickness left, we are down to basement
785 return;
786
787 // OK, we have a layer that can be eroded so find out how much consolidated sediment we have available on this cell
788 double dExistingAvailableFine = m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nThisLayer)->pGetConsolidatedSediment()->dGetFineDepth();
789 double dExistingAvailableSand = m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nThisLayer)->pGetConsolidatedSediment()->dGetSandDepth();
790 double dExistingAvailableCoarse = m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nThisLayer)->pGetConsolidatedSediment()->dGetCoarseDepth();
791
792 // Now partition the total lowering for this cell between the three size fractions: do this by relative erodibility
793 int nFineWeight = (dExistingAvailableFine > 0 ? 1 : 0);
794 int nSandWeight = (dExistingAvailableSand > 0 ? 1 : 0);
795 int nCoarseWeight = (dExistingAvailableCoarse > 0 ? 1 : 0);
796
797 double dTotErodibility = (nFineWeight * m_dFineErodibilityNormalized) + (nSandWeight * m_dSandErodibilityNormalized) + (nCoarseWeight * m_dCoarseErodibilityNormalized);
798 double dTotActualErosion = 0;
799 double dSandEroded = 0;
800 double dCoarseEroded = 0;
801
802 if (nFineWeight)
803 {
804 // Erode some fine-sized consolidated sediment
805 double dFineLowering = (m_dFineErodibilityNormalized * dThisPotentialErosion) / dTotErodibility;
806
807 // Make sure we don't get -ve amounts left on the cell
808 double dFineEroded = tMin(dExistingAvailableFine, dFineLowering);
809 double dRemaining = dExistingAvailableFine - dFineEroded;
810
811 dTotActualErosion += dFineEroded;
812
813 // Set the value for this layer
814 m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nThisLayer)->pGetConsolidatedSediment()->SetFineDepth(dRemaining);
815
816 // And set the changed-this-timestep switch
817 m_bConsChangedThisIter[nThisLayer] = true;
818
819 // And increment the per-timestep total, also add to the suspended sediment load
822 }
823
824 if (nSandWeight)
825 {
826 // Erode some sand-sized consolidated sediment
827 double dSandLowering = (m_dSandErodibilityNormalized * dThisPotentialErosion) / dTotErodibility;
828
829 // Make sure we don't get -ve amounts left on the source cell
830 dSandEroded = tMin(dExistingAvailableSand, dSandLowering);
831 double dRemaining = dExistingAvailableSand - dSandEroded;
832
833 dTotActualErosion += dSandEroded;
834
835 // Set the new value of sand consolidated sediment depth for this layer
836 m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nThisLayer)->pGetConsolidatedSediment()->SetSandDepth(dRemaining);
837
838 // And add this to the depth of sand unconsolidated sediment for this layer
839 m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nThisLayer)->pGetUnconsolidatedSediment()->AddSandDepth(dSandEroded);
840
841 // Set the changed-this-timestep switch
842 m_bConsChangedThisIter[nThisLayer] = true;
843
844 // And increment the per-timestep total
846 }
847
848 if (nCoarseWeight)
849 {
850 // Erode some coarse-sized consolidated sediment
851 double dCoarseLowering = (m_dCoarseErodibilityNormalized * dThisPotentialErosion) / dTotErodibility;
852
853 // Make sure we don't get -ve amounts left on the source cell
854 dCoarseEroded = tMin(dExistingAvailableCoarse, dCoarseLowering);
855 double dRemaining = dExistingAvailableCoarse - dCoarseEroded;
856
857 dTotActualErosion += dCoarseEroded;
858
859 // Set the new value of coarse consolidated sediment depth for this layer
860 m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nThisLayer)->pGetConsolidatedSediment()->SetCoarseDepth(dRemaining);
861
862 // And add this to the depth of coarse unconsolidated sediment for this layer
863 m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nThisLayer)->pGetUnconsolidatedSediment()->AddCoarseDepth(dCoarseEroded);
864
865 // Set the changed-this-timestep switch
866 m_bConsChangedThisIter[nThisLayer] = true;
867
868 // And increment the per-timestep total
870 }
871
872 // Did we erode anything?
873 if (dTotActualErosion > 0)
874 {
875 // We did, so set the actual erosion value for this cell
876 m_pRasterGrid->m_Cell[nX][nY].SetActualPlatformErosion(dTotActualErosion);
877
878 // Recalculate the elevation of every layer
879 m_pRasterGrid->m_Cell[nX][nY].CalcAllLayerElevsAndD50();
880
881 // And update the cell's sea depth
882 m_pRasterGrid->m_Cell[nX][nY].SetSeaDepth();
883
884 // Update per-timestep totals
886
887 // Add eroded sand/coarse sediment for this cell to the polygon that contains the cell, ready for redistribution during beach erosion/deposition (fine sediment has already been dealt with)
888 int nPolyID = m_pRasterGrid->m_Cell[nX][nY].nGetPolygonID();
889
890 if (nPolyID == INT_NODATA)
891 {
892 // Can get occasional problems with polygon rasterization near the coastline, so also search the eight adjacent cells
893 array<int, 8> nDirection = {NORTH, NORTH_EAST, EAST, SOUTH_EAST, SOUTH, SOUTH_WEST, WEST, NORTH_WEST};
894 shuffle(nDirection.begin(), nDirection.end(), m_Rand[0]);
895
896 for (int n = 0; n < 8; n++)
897 {
898 int nXAdj;
899 int nYAdj;
900
901 if (nDirection[n] == NORTH)
902 {
903 nXAdj = nX;
904 nYAdj = nY - 1;
905
906 if (nYAdj >= 0)
907 {
908 nPolyID = m_pRasterGrid->m_Cell[nXAdj][nYAdj].nGetPolygonID();
909
910 if (nPolyID != INT_NODATA)
911 break;
912 }
913 }
914
915 else if (nDirection[n] == NORTH_EAST)
916 {
917 nXAdj = nX + 1;
918 nYAdj = nY - 1;
919
920 if ((nXAdj < m_nXGridSize) && (nYAdj >= 0))
921 {
922 nPolyID = m_pRasterGrid->m_Cell[nXAdj][nYAdj].nGetPolygonID();
923
924 if (nPolyID != INT_NODATA)
925 break;
926 }
927 }
928
929 else if (nDirection[n] == EAST)
930 {
931 nXAdj = nX + 1;
932 nYAdj = nY;
933
934 if (nXAdj < m_nXGridSize)
935 {
936 nPolyID = m_pRasterGrid->m_Cell[nXAdj][nYAdj].nGetPolygonID();
937
938 if (nPolyID != INT_NODATA)
939 break;
940 }
941 }
942
943 else if (nDirection[n] == SOUTH_EAST)
944 {
945 nXAdj = nX + 1;
946 nYAdj = nY + 1;
947
948 if ((nXAdj < m_nXGridSize) && (nYAdj < m_nYGridSize))
949 {
950 nPolyID = m_pRasterGrid->m_Cell[nXAdj][nYAdj].nGetPolygonID();
951
952 if (nPolyID != INT_NODATA)
953 break;
954 }
955 }
956
957 else if (nDirection[n] == SOUTH)
958 {
959 nXAdj = nX;
960 nYAdj = nY + 1;
961
962 if (nYAdj < m_nYGridSize)
963 {
964 nPolyID = m_pRasterGrid->m_Cell[nXAdj][nYAdj].nGetPolygonID();
965
966 if (nPolyID != INT_NODATA)
967 break;
968 }
969 }
970
971 else if (nDirection[n] == SOUTH_WEST)
972 {
973 nXAdj = nX - 1;
974 nYAdj = nY + 1;
975
976 if ((nXAdj >= 0) && (nXAdj < m_nXGridSize))
977 {
978 nPolyID = m_pRasterGrid->m_Cell[nXAdj][nYAdj].nGetPolygonID();
979
980 if (nPolyID != INT_NODATA)
981 break;
982 }
983 }
984
985 else if (nDirection[n] == WEST)
986 {
987 nXAdj = nX - 1;
988 nYAdj = nY;
989
990 if (nXAdj >= 0)
991 {
992 nPolyID = m_pRasterGrid->m_Cell[nXAdj][nYAdj].nGetPolygonID();
993
994 if (nPolyID != INT_NODATA)
995 break;
996 }
997 }
998
999 else if (nDirection[n] == NORTH_WEST)
1000 {
1001 nXAdj = nX - 1;
1002 nYAdj = nY - 1;
1003
1004 if ((nXAdj >= 0) && (nYAdj >= 0))
1005 {
1006 nPolyID = m_pRasterGrid->m_Cell[nXAdj][nYAdj].nGetPolygonID();
1007
1008 if (nPolyID != INT_NODATA)
1009 break;
1010 }
1011 }
1012 }
1013 }
1014
1015 // TEST
1016 assert(nPolyID < m_VCoast[0].nGetNumPolygons());
1017
1018 // Safety check
1019 if (nPolyID == INT_NODATA)
1020 {
1021 // Uh-oh, we have a problem
1023 LogStream << m_ulIter << ": " << WARN << "platform erosion on cell [" << nX << "][" << nY << "] = {" << dGridCentroidXToExtCRSX(nX) << ", " << dGridCentroidYToExtCRSY(nY) << "} but this is not in a polygon" << endl;
1024
1025 // m_dDepositionSandDiff and m_dDepositionCoarseDiff are both +ve
1026 m_dDepositionSandDiff += dSandEroded;
1027 m_dDepositionCoarseDiff += dCoarseEroded;
1028
1029 return;
1030 }
1031
1032 // All OK, so add this to the polygon's total of unconsolidated sand/coarse sediment, to be deposited or moved later. These values are +ve (deposition)
1033 m_pVCoastPolygon[nPolyID]->AddPlatformErosionUnconsSand(dSandEroded);
1034 m_pVCoastPolygon[nPolyID]->AddPlatformErosionUnconsCoarse(dCoarseEroded);
1035 }
1036}
1037
1038//===============================================================================================================================
1040//===============================================================================================================================
1041bool CSimulation::bCreateErosionPotentialLookUp(vector<double> *VdDepthOverDBIn, vector<double> *VdErosionPotentialIn, vector<double> *VdErosionPotentialFirstDerivIn)
1042{
1043 // Set up a temporary vector to hold the incremental DepthOverDB values
1044 vector<double> VdDepthOverDB;
1045 double dTempDOverDB = 0;
1046
1047 while (dTempDOverDB <= 1.1) // Arbitrary max value, we will adjust this later
1048 {
1049 VdDepthOverDB.push_back(dTempDOverDB); // These are the incremental sample values of DepthOverDB
1050 dTempDOverDB += DEPTH_OVER_DB_INCREMENT;
1051
1052 m_VdErosionPotential.push_back(0); // This will hold the corresponding value of erosion potential for each sample point
1053 }
1054
1055 int nSize = static_cast<int>(VdDepthOverDB.size());
1056 vector<double> VdDeriv(nSize, 0); // First derivative at the sample points: calculated by the spline function but not subsequently used
1057 vector<double> VdDeriv2(nSize, 0.); // Second derivative at the sample points, ditto
1058 vector<double> VdDeriv3(nSize, 0.); // Third derivative at the sample points, ditto
1059
1060 // Calculate the value of erosion potential (is a -ve value) for each of the sample values of DepthOverDB, and store it for use in the look-up function
1061 hermite_cubic_spline_value(static_cast<int>(VdDepthOverDBIn->size()), &(VdDepthOverDBIn->at(0)), &(VdErosionPotentialIn->at(0)), &(VdErosionPotentialFirstDerivIn->at(0)), nSize, &(VdDepthOverDB[0]), &(m_VdErosionPotential[0]), &(VdDeriv[0]), &(VdDeriv2[0]), &(VdDeriv3[0]));
1062
1063 // Tidy the erosion potential look-up data: cut off values (after the first) for which erosion potential is no longer -ve
1064 int nLastVal = -1;
1065
1066 for (int n = 1; n < nSize - 1; n++)
1067 if (m_VdErosionPotential[n] > 0)
1068 {
1069 nLastVal = n;
1070 break;
1071 }
1072
1073 if (nLastVal > 0)
1074 {
1075 // Erosion potential is no longer -ve at this value of DepthOverDB, so set the maximum value of DepthOverDB that will be used in the simulation (any DepthOverDB value greater than this produces zero erosion potential)
1076 m_dDepthOverDBMax = VdDepthOverDB[nLastVal];
1077 m_VdErosionPotential.erase(m_VdErosionPotential.begin() + nLastVal + 1, m_VdErosionPotential.end());
1078 m_VdErosionPotential.back() = 0;
1079 }
1080
1081 else
1082 // Erosion potential is unbounded, i.e. it is still -ve when we have reached the end of the look-up vector
1083 return false;
1084
1085 // All OK
1086 return true;
1087}
1088
1089//===============================================================================================================================
1091//===============================================================================================================================
1092double CSimulation::dLookUpErosionPotential(double const dDepthOverDB) const
1093{
1094 // If dDepthOverDB exceeds the maximum value which we calculated earlier, erosion potential is zero
1095 if (dDepthOverDB > m_dDepthOverDBMax)
1096 return 0;
1097
1098 // OK, dDepthOverDB is less than the maximum so look up a corresponding value for erosion potential. The look-up index is dDepthOverDB divided by (the Depth Over DB increment used when creating the look-up vector). But since this look-up index may not be an integer, split the look-up index into integer and fractional parts and deal with each separately
1099 double dErosionPotential = dGetInterpolatedValue(&m_VdDepthOverDB, &m_VdErosionPotential, dDepthOverDB, false);
1100
1101 return dErosionPotential;
1102}
1103
1104//===============================================================================================================================
1106//===============================================================================================================================
1107double CSimulation::dCalcBeachProtectionFactor(int const nX, int const nY, double const dBreakingWaveHeight)
1108{
1109 // Safety check
1110 if (bFPIsEqual(dBreakingWaveHeight, DBL_NODATA, TOLERANCE))
1111 return 0;
1112
1113 // We are considering the unconsolidated sediment (beach) of the topmost layer that has non-zero thickness
1114 int nThisLayer = m_pRasterGrid->m_Cell[nX][nY].nGetTopNonZeroLayerAboveBasement();
1115
1116 // Safety check
1117 if (nThisLayer == INT_NODATA)
1118 {
1119 cerr << ERR << "no sediment layer in dCalcBeachProtectionFactor()" << endl;
1120 return 0;
1121 }
1122
1123 if (nThisLayer == NO_NONZERO_THICKNESS_LAYERS)
1124 // There are no layers with non-zero thickness left (i.e. we are down to basement) so no beach protection
1125 return 0;
1126
1127 // In SCAPE, 0.23 * the significant breaking wave height is assumed to be the maximum depth of beach that waves can penetrate to erode a platform. For depths less than this, the beach protective ability is assumed to vary linearly
1128 double dBeachDepth = m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nThisLayer)->dGetUnconsolidatedThickness();
1129 double dMaxPenetrationDepth = BEACH_PROTECTION_HB_RATIO * dBreakingWaveHeight;
1130 double dFactor = 0;
1131
1132 if (dMaxPenetrationDepth > 0)
1133 dFactor = tMax(1 - (dBeachDepth / dMaxPenetrationDepth), 0.0);
1134
1135 // LogStream << m_ulIter << ": cell[" << nX << "][" << nY << "] has beach protection factor = " << dFactor << endl;
1136
1137 return dFactor;
1138}
1139
1140//===============================================================================================================================
1142//===============================================================================================================================
1144{
1145 for (int nX = 0; nX < m_nXGridSize; nX++)
1146 {
1147 for (int nY = 0; nY < m_nYGridSize; nY++)
1148 {
1149 if ((m_pRasterGrid->m_Cell[nX][nY].bIsInContiguousSea()) && (bFPIsEqual(m_pRasterGrid->m_Cell[nX][nY].dGetBeachProtectionFactor(), DBL_NODATA, TOLERANCE)))
1150 {
1151 // This is a sea cell, and it has an initialized beach protection value. So look at its N-S and W-E neighbours
1152 int nXTmp;
1153 int nYTmp;
1154 int nAdjacent = 0;
1155 double dBeachProtection = 0;
1156
1157 // North
1158 nXTmp = nX;
1159 nYTmp = nY - 1;
1160
1161 if ((bIsWithinValidGrid(nXTmp, nYTmp)) && (! bFPIsEqual(m_pRasterGrid->m_Cell[nXTmp][nYTmp].dGetBeachProtectionFactor(), DBL_NODATA, TOLERANCE)))
1162 {
1163 nAdjacent++;
1164 dBeachProtection += m_pRasterGrid->m_Cell[nXTmp][nYTmp].dGetBeachProtectionFactor();
1165 }
1166
1167 // East
1168 nXTmp = nX + 1;
1169 nYTmp = nY;
1170
1171 if ((bIsWithinValidGrid(nXTmp, nYTmp)) && (! bFPIsEqual(m_pRasterGrid->m_Cell[nXTmp][nYTmp].dGetBeachProtectionFactor(), DBL_NODATA, TOLERANCE)))
1172 {
1173 nAdjacent++;
1174 dBeachProtection += m_pRasterGrid->m_Cell[nXTmp][nYTmp].dGetBeachProtectionFactor();
1175 }
1176
1177 // South
1178 nXTmp = nX;
1179 nYTmp = nY + 1;
1180
1181 if ((bIsWithinValidGrid(nXTmp, nYTmp)) && (! bFPIsEqual(m_pRasterGrid->m_Cell[nXTmp][nYTmp].dGetBeachProtectionFactor(), DBL_NODATA, TOLERANCE)))
1182 {
1183 nAdjacent++;
1184 dBeachProtection += m_pRasterGrid->m_Cell[nXTmp][nYTmp].dGetBeachProtectionFactor();
1185 }
1186
1187 // West
1188 nXTmp = nX - 1;
1189 nYTmp = nY;
1190
1191 if ((bIsWithinValidGrid(nXTmp, nYTmp)) && (! bFPIsEqual(m_pRasterGrid->m_Cell[nXTmp][nYTmp].dGetBeachProtectionFactor(), DBL_NODATA, TOLERANCE)))
1192 {
1193 nAdjacent++;
1194 dBeachProtection += m_pRasterGrid->m_Cell[nXTmp][nYTmp].dGetBeachProtectionFactor();
1195 }
1196
1197 // If this sea cell has four neighbours with initialized beach protection values, then assume that it should not have an uninitialized beach protection value. Set it to the average of its neighbours
1198 if (nAdjacent == 4)
1199 {
1200 m_pRasterGrid->m_Cell[nX][nY].SetBeachProtectionFactor(dBeachProtection / 4);
1201 }
1202 }
1203 }
1204 }
1205}
1206
1207//===============================================================================================================================
1209//===============================================================================================================================
1211{
1212 for (int nX = 0; nX < m_nXGridSize; nX++)
1213 {
1214 for (int nY = 0; nY < m_nYGridSize; nY++)
1215 {
1216 if ((m_pRasterGrid->m_Cell[nX][nY].bIsInContiguousSea()) && (bFPIsEqual(m_pRasterGrid->m_Cell[nX][nY].dGetPotentialPlatformErosion(), 0.0, TOLERANCE)))
1217 {
1218 // This is a sea cell, it has a zero potential platform erosion value. So look at its N-S and W-E neighbours
1219 int nXTmp;
1220 int nYTmp;
1221 int nAdjacent = 0;
1222 double dPotentialPlatformErosion = 0;
1223
1224 // North
1225 nXTmp = nX;
1226 nYTmp = nY - 1;
1227
1228 if ((bIsWithinValidGrid(nXTmp, nYTmp)) && (! bFPIsEqual(m_pRasterGrid->m_Cell[nXTmp][nYTmp].dGetPotentialPlatformErosion(), 0.0, TOLERANCE)))
1229 {
1230 nAdjacent++;
1231 dPotentialPlatformErosion += m_pRasterGrid->m_Cell[nXTmp][nYTmp].dGetPotentialPlatformErosion();
1232 }
1233
1234 // East
1235 nXTmp = nX + 1;
1236 nYTmp = nY;
1237
1238 if ((bIsWithinValidGrid(nXTmp, nYTmp)) && (! bFPIsEqual(m_pRasterGrid->m_Cell[nXTmp][nYTmp].dGetPotentialPlatformErosion(), 0.0, TOLERANCE)))
1239 {
1240 nAdjacent++;
1241 dPotentialPlatformErosion += m_pRasterGrid->m_Cell[nXTmp][nYTmp].dGetPotentialPlatformErosion();
1242 }
1243
1244 // South
1245 nXTmp = nX;
1246 nYTmp = nY + 1;
1247
1248 if ((bIsWithinValidGrid(nXTmp, nYTmp)) && (! bFPIsEqual(m_pRasterGrid->m_Cell[nXTmp][nYTmp].dGetPotentialPlatformErosion(), 0.0, TOLERANCE)))
1249 {
1250 nAdjacent++;
1251 dPotentialPlatformErosion += m_pRasterGrid->m_Cell[nXTmp][nYTmp].dGetPotentialPlatformErosion();
1252 }
1253
1254 // West
1255 nXTmp = nX - 1;
1256 nYTmp = nY;
1257
1258 if ((bIsWithinValidGrid(nXTmp, nYTmp)) && (! bFPIsEqual(m_pRasterGrid->m_Cell[nXTmp][nYTmp].dGetPotentialPlatformErosion(), 0.0, TOLERANCE)))
1259 {
1260 nAdjacent++;
1261 dPotentialPlatformErosion += m_pRasterGrid->m_Cell[nXTmp][nYTmp].dGetPotentialPlatformErosion();
1262 }
1263
1264 // If this sea cell has four neighbours with non-zero potential platform erosion values, then assume that it should not have a zero potential platform erosion value. Set it to the average of its neighbours
1265 if (nAdjacent == 4)
1266 {
1267 double dThisPotentialPlatformErosion = dPotentialPlatformErosion / 4;
1268
1269 m_pRasterGrid->m_Cell[nX][nY].SetPotentialPlatformErosion(dThisPotentialPlatformErosion);
1270
1271 // Update this-timestep totals
1273 m_dThisIterPotentialPlatformErosion += dThisPotentialPlatformErosion;
1274 // assert(isfinite(m_dThisIterPotentialPlatformErosion));
1275
1276 // Increment the check values
1278 m_dTotPotentialPlatformErosionBetweenProfiles += dThisPotentialPlatformErosion;
1279 }
1280 }
1281 }
1282 }
1283}
1284
1285//===============================================================================================================================
1287//===============================================================================================================================
1288void CSimulation::ConstructParallelProfile(int const nProfileStartX, int const nProfileStartY, int const nParCoastX, int const nParCoastY, int const nProfSize, vector<CGeom2DIPoint> *const pPtViGridProfile, vector<CGeom2DIPoint> *pPtiVGridParProfile, vector<CGeom2DPoint> *pPtVExtCRSParProfile)
1289{
1290 // OK, we have the coastline start point for the parallel profile. Now construct a temporary profile, parallel to the coastline-normal profile, starting from this point
1291 int nXOffset = nParCoastX - nProfileStartX;
1292 int nYOffset = nParCoastY - nProfileStartY;
1293
1294 // Append co-ord values for the temporary profile
1295 for (int nProfileStartPoint = 0; nProfileStartPoint < nProfSize; nProfileStartPoint++)
1296 {
1297 // Get the grid coordinates of the cell which is this distance seaward, from the coastline-normal profile
1298 int nXProf = pPtViGridProfile->at(nProfileStartPoint).nGetX();
1299 int nYProf = pPtViGridProfile->at(nProfileStartPoint).nGetY();
1300
1301 // Now calculate the grid coordinates of this cell, which is potentially in the parallel profile
1302 int nXPar = nXProf + nXOffset;
1303 int nYPar = nYProf + nYOffset;
1304
1305 // Is this cell within the grid? If not, cut short the profile
1306 if (! bIsWithinValidGrid(nXPar, nYPar))
1307 {
1308 // LogStream << "NOT WITHIN GRID [" << nXPar << "][" << nYPar << "]" << endl;
1309 return;
1310 }
1311
1312 // Have we hit an adjacent coastline-normal profile? If so, cut short
1313 if (m_pRasterGrid->m_Cell[nXPar][nYPar].bIsProfile())
1314 {
1315 // LogStream << "HIT PROFILE " << m_pRasterGrid->m_Cell[nXPar][nYPar].nGetProfileID() << " at [" << nXPar << "][" << nYPar << "] = {" << dGridCentroidXToExtCRSX(nXPar) << ", " << dGridCentroidYToExtCRSY(nYPar) << "}" << endl;
1316 return;
1317 }
1318
1319 // OK, append the cell details
1320 pPtiVGridParProfile->push_back(CGeom2DIPoint(nXPar, nYPar));
1321 pPtVExtCRSParProfile->push_back(CGeom2DPoint(dGridCentroidXToExtCRSX(nXPar), dGridCentroidYToExtCRSY(nYPar)));
1322 }
1323}
Geometry class used to represent 2D point objects with integer coordinates.
Definition 2di_point.h:29
Geometry class used to represent 2D point objects with floating-point coordinates.
Definition 2d_point.h:27
double dGetY(void) const
Returns the CGeom2DPoint object's double Y coordinate.
Definition 2d_point.cpp:46
double dGetX(void) const
Returns the CGeom2DPoint object's double X coordinate.
Definition 2d_point.cpp:40
Geometry class used to represent coast profile objects.
Definition profile.h:35
int nGetCoastPoint(void) const
Returns the coast point at which the profile starts.
Definition profile.cpp:79
int nGetNumCellsInProfile(void) const
Returns the number of cells in the profile.
Definition profile.cpp:517
CGeom2DPoint * pPtGetPointInProfile(int const)
Returns a single point in the profile.
Definition profile.cpp:349
bool bOKIncStartAndEndOfCoast(void) const
Returns true if this is a problem-free profile (however it could be a start-of-coast or an end-of-coa...
Definition profile.cpp:246
int nGetCoastID(void) const
Returns the profile's coast ID.
Definition profile.cpp:67
int nGetProfileSize(void) const
Returns the number of points in the profile.
Definition profile.cpp:342
vector< CGeom2DIPoint > * pPtiVGetCellsInProfile(void)
Returns all cells in the profile.
Definition profile.cpp:496
int m_nLogFileDetail
Definition simulation.h:591
double dLookUpErosionPotential(double const) const
The erosion potential lookup: it returns a value for erosion potential given a value of Depth Over DB...
double m_dThisIterSWL
Definition simulation.h:748
CGeomRasterGrid * m_pRasterGrid
Pointer to the raster grid object.
int m_nXGridSize
The size of the grid in the x direction.
Definition simulation.h:462
ofstream LogStream
vector< CRWCoast > m_VCoast
The coastline objects.
double m_dFineErodibilityNormalized
Relative erodibility of fine unconsolidated beach sediment, normalized.
Definition simulation.h:834
double m_dThisIterActualPlatformErosionCoarseCons
Definition simulation.h:886
vector< CGeomCoastPolygon * > m_pVCoastPolygon
int nDoAllShorePlatFormErosion(void)
Does platform erosion on all coastlines by first calculating platform erosion on coastline-normal pro...
int m_nYGridSize
The size of the grid in the y direction.
Definition simulation.h:465
vector< double > m_VdErosionPotential
For erosion potential lookup.
void ConstructParallelProfile(int const, int const, int const, int const, int const, vector< CGeom2DIPoint > *const, vector< CGeom2DIPoint > *, vector< CGeom2DPoint > *)
Constructs a parallel coastline-normal profile.
int nSaveParProfile(int const, CGeomProfile const *, int const, int const, int const, vector< double > const *, vector< double > const *, vector< double > const *, vector< double > const *, vector< double > const *, vector< double > const *, vector< double > const *, vector< CGeom2DIPoint > *const, vector< double > const *) const
Save a coastline-normal parallel profile.
static double dGetDistanceBetween(CGeom2DPoint const *, CGeom2DPoint const *)
Returns the distance (in external CRS) between two points.
double m_dCoarseErodibilityNormalized
Relative erodibility of coarse unconsolidated beach sediment, normalized.
Definition simulation.h:840
vector< double > m_VdDepthOverDB
For erosion potential lookup.
void FillInBeachProtectionHoles(void)
Fills in 'holes' in the beach protection i.e. orphan cells which get omitted because of rounding prob...
double m_dTotPotentialPlatformErosionBetweenProfiles
Total potential platform erosion between profiles.
Definition simulation.h:960
double m_dDepositionCoarseDiff
Definition simulation.h:950
unsigned long m_ulThisIterNumActualPlatformErosionCells
Definition simulation.h:641
int nCalcPotentialPlatformErosionBetweenProfiles(int const, CGeomProfile *, int const)
Calculates potential platform erosion on cells to one side of a given coastline-normal profile,...
double m_dDepositionSandDiff
Definition simulation.h:946
int nSaveProfile(int const, CGeomProfile const *, int const, vector< double > const *, vector< double > const *, vector< double > const *, vector< double > const *, vector< double > const *, vector< double > const *, vector< double > const *, vector< CGeom2DIPoint > *const, vector< double > const *) const
Save a coastline-normal profile.
double m_dThisIterPotentialPlatformErosion
Definition simulation.h:874
vector< double > dVSmoothProfileSlope(vector< double > *) const
Does running-mean smoothing of the slope of a coastline-normal profile.
double m_dDepthOverDBMax
Definition simulation.h:954
double m_dSandErodibilityNormalized
Relative erodibility of sand unconsolidated beach sediment, normalized.
Definition simulation.h:837
double m_dR
Coast platform resistance to erosion R, see Walkden & Hall, 2011.
Definition simulation.h:807
double m_dThisIterActualPlatformErosionSandCons
Definition simulation.h:882
double dGridCentroidYToExtCRSY(int const) const
Given the integer Y-axis ordinate of a cell in the raster grid CRS, returns the external CRS Y-axis o...
Definition gis_utils.cpp:70
double m_dTotPotentialPlatformErosionOnProfiles
Total potential platform erosion on profiles.
Definition simulation.h:957
int nCalcPotentialPlatformErosionOnProfile(int const, CGeomProfile *)
Calculates potential (i.e. unconstrained by available sediment) erosional lowering of the shore platf...
void DoActualPlatformErosionOnCell(int const, int const)
Calculates actual (constrained by available sediment) erosion of the consolidated shore platform on a...
double m_dThisIterFineSedimentToSuspension
Definition simulation.h:914
void FillPotentialPlatformErosionHoles(void)
Fills in 'holes' in the potential platform erosion i.e. orphan cells which get omitted because of rou...
unsigned long m_ulThisIterNumPotentialPlatformErosionCells
Definition simulation.h:637
default_random_engine m_Rand[NUMBER_OF_RNGS]
The c++11 random number generators.
unsigned long m_ulTotPotentialPlatformErosionOnProfiles
Definition simulation.h:657
double m_dCellArea
Area of a cell (in external CRS units)
Definition simulation.h:692
unsigned long m_ulTotPotentialPlatformErosionBetweenProfiles
Definition simulation.h:661
bool bIsWithinValidGrid(int const, int const) const
Checks whether the supplied point (an x-y pair, in the grid CRS) is within the raster grid,...
unsigned long m_ulIter
The number of the current iteration (time step)
Definition simulation.h:618
double dGridCentroidXToExtCRSX(int const) const
Given the integer X-axis ordinate of a cell in the raster grid CRS, returns the external CRS X-axis o...
Definition gis_utils.cpp:62
double dCalcBeachProtectionFactor(int const, int const, double const)
Calculates the (inverse) beach protection factor as in SCAPE: 0 is fully protected,...
bool m_bOutputProfileData
Output profile data?
Definition simulation.h:337
bool bCreateErosionPotentialLookUp(vector< double > *, vector< double > *, vector< double > *)
Creates a look-up table for erosion potential, given depth over DB.
double m_dThisIterActualPlatformErosionFineCons
Definition simulation.h:878
int m_nProfileSmoothWindow
Definition simulation.h:495
vector< bool > m_bConsChangedThisIter
bool m_bOutputParallelProfileData
Output parallel profile data?
Definition simulation.h:340
This file contains global definitions for CoastalME.
int const NO_NONZERO_THICKNESS_LAYERS
Definition cme.h:767
int const INT_NODATA
Definition cme.h:474
T tMin(T a, T b)
Definition cme.h:1251
double const TOLERANCE
Definition cme.h:811
int const RTN_ERR_NO_TOP_LAYER
Definition cme.h:738
string const ERR
Definition cme.h:890
int const DIRECTION_DOWNCOAST
Definition cme.h:504
int const SOUTH_EAST
Definition cme.h:498
double const DEPTH_OVER_DB_INCREMENT
Definition cme.h:803
int const LOG_FILE_MIDDLE_DETAIL
Definition cme.h:489
bool bFPIsEqual(const T d1, const T d2, const T dEpsilon)
Definition cme.h:1284
int const SOUTH_WEST
Definition cme.h:500
T tMax(T a, T b)
Definition cme.h:1240
int const NORTH_WEST
Definition cme.h:502
int const LOG_FILE_HIGH_DETAIL
Definition cme.h:490
string const WARN
Definition cme.h:891
double const SEDIMENT_ELEV_TOLERANCE
Definition cme.h:813
int const SOUTH
Definition cme.h:499
int const LOG_FILE_ALL
Definition cme.h:491
int const EAST
Definition cme.h:497
int const RTN_OK
Definition cme.h:692
int const NORTH_EAST
Definition cme.h:496
int const DIRECTION_UPCOAST
Definition cme.h:505
double const DBL_NODATA
Definition cme.h:822
double const BEACH_PROTECTION_HB_RATIO
Definition cme.h:799
int const NORTH
Definition cme.h:495
int const WEST
Definition cme.h:501
Contains CRWCoast definitions.
void hermite_cubic_spline_value(int const nn, double *const xn, double *const fn, double *const dn, int const n, double *const x, double *f, double *d, double *s, double *t)
This is part of a C++ library from http://people.sc.fsu.edu/~jburkardt/cpp_src/hermite_cubic/hermite_...
Definitions of some routines from the hermite_cubic library.
double dGetInterpolatedValue(vector< double > const *pVdXdata, vector< double > const *pVdYdata, double dX, bool bExtrapolate)
Definitions of routines which return interpolated value at x from parallel arrays.
Contains CSimulation definitions.