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
15This file is part of CoastalME, the Coastal Modelling Environment.
16
17CoastalME 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
19This 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
21You 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 if (bDownCoast)
113 pProfile = m_VCoast[nCoast].pGetProfileWithDownCoastSeq(nn);
114 else
115 pProfile = m_VCoast[nCoast].pGetProfileWithUpCoastSeq(nn);
116
117 int const nRet = nCalcPotentialPlatformErosionOnProfile(nCoast, pProfile);
118 if (nRet != RTN_OK)
119 return nRet;
120 }
121
122 // Calculate potential platform erosion between the coastline-normal profiles. Do this in down-coast sequence
123 for (int nn = 0; nn < nNumProfiles - 1; nn++)
124 {
125 CGeomProfile* pProfile = m_VCoast[nCoast].pGetProfileWithDownCoastSeq(nn);
126
127 // Calculate potential erosion for sea cells between this profile and the next profile (or up to the edge of the grid) on these cells
129 if (nRet != RTN_OK)
130 return nRet;
131
133 if (nRet != RTN_OK)
134 return nRet;
135 }
136 }
137
138 // Swap direction for next timestep
139 bDownCoast = ! bDownCoast;
140
141 // Fills in 'holes' in the potential platform erosion i.e. orphan cells which get omitted because of rounding problems
143
144 // Do the same for beach protection
146
147 // Finally calculate actual platform erosion on all sea cells (both on profiles, and between profiles)
148 for (int nX = 0; nX < m_nXGridSize; nX++)
149 {
150 for (int nY = 0; nY < m_nYGridSize; nY++)
151 {
152 if (m_pRasterGrid->m_Cell[nX][nY].bPotentialPlatformErosion())
153 // 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
155 }
156 }
157
159 {
160 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;
161
163 }
164
165 return RTN_OK;
166}
167
168//===============================================================================================================================
170//===============================================================================================================================
172{
173 // Only work on this profile if it is problem-free TODO 024 Or if it has just hit dry land?
174 if (! pProfile->bOKIncStartAndEndOfCoast()) // || (pProfile->nGetProblemCode() == PROFILE_DRYLAND))
175 return RTN_OK;
176
177 // Get the length of the profile (in cells) and the index of the coast point at which this profile starts
178 int const nProfSize = pProfile->nGetNumCellsInProfile();
179 int const nCoastPoint = pProfile->nGetCoastPoint();
180
181 // Get the breaking depth for this profile from the coastline point
182 double dDepthOfBreaking = m_VCoast[nCoast].dGetDepthOfBreaking(nCoastPoint);
183 if (bFPIsEqual(dDepthOfBreaking, DBL_NODATA, TOLERANCE))
184 // This profile is not in the active zone, so no platform erosion here
185 return RTN_OK;
186
187 if (bFPIsEqual(dDepthOfBreaking, 0.0, TOLERANCE))
188 {
189 // Safety check, altho' this shouldn't happen
191 LogStream << m_ulIter << ": depth of breaking is zero for profile " << pProfile->nGetCoastID() << " of coast " << nCoast << endl;
192
193 return RTN_OK;
194 }
195
196 // LogStream << m_ulIter << ": ON PROFILE nProfile = " << nProfile << " dDepthOfBreaking = " << dDepthOfBreaking << endl;
197
198 // Get the height of the associated breaking wave from the coast point: this height is used in beach protection calcs
199 double const dBreakingWaveHeight = m_VCoast[nCoast].dGetBreakingWaveHeight(nCoastPoint);
200
201 // Calculate the length of the profile in external CRS units
202 int const nSegments = pProfile->nGetProfileSize() - 1;
203 double dProfileLenXY = 0;
204 for (int nSeg = 0; nSeg < nSegments; nSeg++)
205 {
206 // Do once for every line segment
207 double const dSegStartX = pProfile->pPtGetPointInProfile(nSeg)->dGetX();
208 double const dSegStartY = pProfile->pPtGetPointInProfile(nSeg)->dGetY();
209 double const dSegEndX = pProfile->pPtGetPointInProfile(nSeg + 1)->dGetX(); // Is OK
210 double const dSegEndY = pProfile->pPtGetPointInProfile(nSeg + 1)->dGetY();
211
212 double const dSegLen = hypot(dSegStartX - dSegEndX, dSegStartY - dSegEndY);
213 dProfileLenXY += dSegLen;
214 }
215
216 // 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)
217 double const dSpacingXY = dProfileLenXY / (nProfSize - 1);
218
219 // 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)
220 // 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
221 vector<double> VdProfileZ(nProfSize, 0); // Initial (pre-erosion) elevation of both consolidated and unconsolidated sediment for cells 'under' the profile
222 vector<double> VdProfileDistXY(nProfSize, 0); // Along-profile distance measured from the coast, in external CRS units
223 vector<double> dVConsProfileZ(nProfSize, 0); // Initial (pre-erosion) elevation of consolidated sediment only for cells 'under' the profile
224 vector<double> dVConsZDiff(nProfSize, 0);
225 vector<double> dVConsSlope(nProfSize, 0);
226
227 for (int i = 0; i < nProfSize; i++)
228 {
229 int const nX = pProfile->pPtiVGetCellsInProfile()->at(i).nGetX();
230 int const nY = pProfile->pPtiVGetCellsInProfile()->at(i).nGetY();
231
232 // Get the number of the highest layer with non-zero thickness
233 int const nTopLayer = m_pRasterGrid->m_Cell[nX][nY].nGetTopNonZeroLayerAboveBasement();
234
235 // Safety check
236 if (nTopLayer == INT_NODATA)
238
239 if (nTopLayer == NO_NONZERO_THICKNESS_LAYERS)
240 // TODO 025 We are down to basement
241 return RTN_OK;
242
243 // Get the elevation for consolidated sediment only on this cell
244 dVConsProfileZ[i] = m_pRasterGrid->m_Cell[nX][nY].dGetConsSedTopForLayerAboveBasement(nTopLayer);
245
246 // Get the elevation for both consolidated and unconsolidated sediment on this cell
247 VdProfileZ[i] = m_pRasterGrid->m_Cell[nX][nY].dGetSedimentTopElev();
248
249 // And store the X-Y plane distance from the start of the profile
250 VdProfileDistXY[i] = i * dSpacingXY;
251 }
252
253 for (int i = 0; i < nProfSize - 1; i++)
254 {
255 // For the consolidated-only profile, get the Z differences (already in external CRS units)
256 dVConsZDiff[i] = dVConsProfileZ[i] - dVConsProfileZ[i + 1];
257
258 // 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
259 dVConsSlope[i] = dVConsZDiff[i] / dSpacingXY;
260 }
261
262 // Sort out the final value
263 dVConsSlope[nProfSize - 1] = dVConsSlope[nProfSize - 2];
264
266 {
267 // Smooth the vector of slopes for the consolidated-only profile
268 dVConsSlope = dVSmoothProfileSlope(&dVConsSlope);
269 }
270
271 vector<double> dVProfileDepthOverDB(nProfSize, 0); // Depth over wave breaking depth at the coastline-normal sample points
272 vector<double> dVProfileErosionPotential(nProfSize, 0); // Erosion potential at the coastline-normal sample points
273
274 // Calculate the erosion potential along this profile using the shape function
275 double dTotalErosionPotential = 0;
276 for (int i = 0; i < nProfSize; i++)
277 {
278 // 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)
279 dVProfileDepthOverDB[i] = m_dThisIterSWL - VdProfileZ[i];
280 dVProfileDepthOverDB[i] /= dDepthOfBreaking;
281
282 // Constrain dDepthOverDB[i] to be between 0 (can get small -ve values due to rounding errors) and m_dDepthOverDBMax
283 dVProfileDepthOverDB[i] = tMax(dVProfileDepthOverDB[i], 0.0);
284 dVProfileDepthOverDB[i] = tMin(dVProfileDepthOverDB[i], m_dDepthOverDBMax);
285
286 // And then use the look-up table to find the value of erosion potential at this point on the profile
287 dVProfileErosionPotential[i] = dLookUpErosionPotential(dVProfileDepthOverDB[i]);
288
289 // If erosion potential (a -ve value) is tiny, set it to zero
290 if (dVProfileErosionPotential[i] > -SEDIMENT_ELEV_TOLERANCE)
291 dVProfileErosionPotential[i] = 0;
292
293 // Keep track of the total erosion potential for this profile
294 dTotalErosionPotential += dVProfileErosionPotential[i];
295 }
296
297 // 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
298 for (int i = 0; i < nProfSize; i++)
299 {
300 if (dTotalErosionPotential < 0)
301 dVProfileErosionPotential[i] /= (-dTotalErosionPotential);
302 }
303
304 vector<double> dVRecessionXY(nProfSize, 0);
305 vector<double> dVSCAPEXY(nProfSize, 0);
306
307 // Calculate recession at every point on the coastline-normal profile
308 for (int i = 0; i < nProfSize; i++)
309 {
310 // dRecession = dForce * (dBeachProtection / dR) * dErosionPotential * dSlope * dTime
311 // where:
312 // dVRecession [m] is the landward migration distance defined in the profile relative (XY) CRS
313 // dForce is given by Equation 4 in Walkden & Hall, 2005
314 // dVBeachProtection [1] is beach protection factor [1, 0] = [no protection, fully protected]. (This is calculated later, see dCalcBeachProtectionFactor())
315 // dVR [m^(9/4)s^(2/3)] is the material strength and some hydrodynamic constant
316 // dVProfileErosionPotential [?] is the erosion potential at each point along the profile
317 // dVSlope [1] is the along-profile slope
318 // m_dTimeStep * 3600 [s] is the time interval in seconds
319 //
320 // dRecession is horizontal recession (along the XY direction):
321 //
322 // dVRecessionXY[i] = (dForce * dVBeachProtection[i] * dVErosionPotentialFunc[i] * dVSlope[i] * m_dTimeStep * 3600) / dVR[i]
323 //
324 // 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
325 dVRecessionXY[i] = tMin(m_VCoast[nCoast].dGetWaveEnergyAtBreaking(nCoastPoint) * dVProfileErosionPotential[i] * dVConsSlope[i] / m_dR, 0.0);
326 dVSCAPEXY[i] = VdProfileDistXY[i] - dVRecessionXY[i];
327 }
328
329 vector<double> dVChangeElevZ(nProfSize, 0);
330
331 // 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
332 for (int i = 1; i < nProfSize - 1; i++)
333 {
334 // Vertical lowering dZ = dXY * tan(a), where tan(a) is the slope of the SCAPE profile in the XY direction
335 double dSCAPEHorizDist = dVSCAPEXY[i + 1] - dVSCAPEXY[i];
336 double dSCAPEVertDist = dVConsProfileZ[i] - dVConsProfileZ[i + 1];
337 double dSCAPESlope = dSCAPEVertDist / dSCAPEHorizDist;
338 double dDeltaZ = dVRecessionXY[i] * dSCAPESlope;
339 // 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
340 if (dSCAPESlope > 1)
341 {
342 dDeltaZ = 0;
343 }
344
345 int const nX = pProfile->pPtiVGetCellsInProfile()->at(i).nGetX();
346 int const nY = pProfile->pPtiVGetCellsInProfile()->at(i).nGetY();
347
348 // Store the local slope of the consolidated sediment, this is just for output display purposes
349 m_pRasterGrid->m_Cell[nX][nY].SetLocalConsSlope(dVConsSlope[i]);
350
351 // dDeltaZ is zero or -ve: if dDeltaZ is zero then do nothing, if -ve then remove some sediment from this cell
352 if (dDeltaZ < 0)
353 {
354 // If there has already been potential erosion on this cell, then it must be a shared line segment (i.e. has co-incident profiles)
355 double dPrevPotentialErosion = -m_pRasterGrid->m_Cell[nX][nY].dGetPotentialPlatformErosion();
356 if (dPrevPotentialErosion < 0)
357 {
358 // Average the two values
359 // LogStream << m_ulIter << ": [" << nX << "][" << nY << "] under profile " << nProfile << " has previous potential platform erosion = " << dPrevPotentialErosion << endl;
360 dDeltaZ = ((dDeltaZ + dPrevPotentialErosion) / 2);
361 }
362
363 // Constrain the lowering so we don't get negative slopes or +ve erosion amounts (dDeltaZ must be -ve), this is implicit in SCAPE
364 dDeltaZ = tMax(dDeltaZ, -dVConsZDiff[i]);
365 dDeltaZ = tMin(dDeltaZ, 0.0);
366 dVChangeElevZ[i] = dDeltaZ;
367
368 // Set the potential (unconstrained) erosion for this cell, is a +ve value
369 m_pRasterGrid->m_Cell[nX][nY].SetPotentialPlatformErosion(-dDeltaZ);
370
371 // Update this-timestep totals
373 m_dThisIterPotentialPlatformErosion -= dDeltaZ; // Since dDeltaZ is a -ve value
374// assert(isfinite(m_dThisIterPotentialPlatformErosion));
375// assert(m_dThisIterPotentialPlatformErosion >= 0);
376
377 // Increment the check values
380 }
381
382 // Finally, calculate the beach protection factor, this will be used in estimating actual (supply-limited) erosion
383 double dBeachProtectionFactor = dCalcBeachProtectionFactor(nX, nY, dBreakingWaveHeight);
384 m_pRasterGrid->m_Cell[nX][nY].SetBeachProtectionFactor(dBeachProtectionFactor);
385 }
386
387 // If desired, save this coastline-normal profile data for checking purposes
389 {
390 int nRet = nSaveProfile(nCoast, pProfile, nProfSize, &VdProfileDistXY, &dVConsProfileZ, &dVProfileDepthOverDB, &dVProfileErosionPotential, &dVConsSlope, &dVRecessionXY, &dVChangeElevZ, pProfile->pPtiVGetCellsInProfile(), &dVSCAPEXY);
391 if (nRet != RTN_OK)
392 return nRet;
393 }
394
395 return RTN_OK;
396}
397
398//===============================================================================================================================
400//===============================================================================================================================
401int CSimulation::nCalcPotentialPlatformErosionBetweenProfiles(int const nCoast, CGeomProfile* pProfile, int const nDirection)
402{
403 // Only work on this profile if it is problem-free
404 if (! pProfile->bOKIncStartAndEndOfCoast())
405 return RTN_OK;
406
407 int const nProfSize = pProfile->nGetNumCellsInProfile();
408 int const nCoastProfileStart = pProfile->nGetCoastPoint();
409 int const nProfileStartX = pProfile->pPtiVGetCellsInProfile()->at(0).nGetX();
410 int const nProfileStartY = pProfile->pPtiVGetCellsInProfile()->at(0).nGetY();
411 int const nCoastMax = m_VCoast[nCoast].nGetCoastlineSize();
412 int nDistFromProfile = 0;
413 int nParCoastXLast = nProfileStartX;
414 int nParCoastYLast = nProfileStartY;
415
416 // 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
417 while (true)
418 {
419 // Increment the distance from the start coast-normal profile
420 nDistFromProfile++;
421
422 // Start the parallel profile nDistFromProfile cells along the coastline from the coastline-normal profile, direction depending on nDirection
423 int nThisPointOnCoast = nCoastProfileStart;
424 if (nDirection == DIRECTION_DOWNCOAST)
425 nThisPointOnCoast += nDistFromProfile;
426 else
427 nThisPointOnCoast -= nDistFromProfile;
428
429 // Have we reached the beginning of the coast?
430 if ((nDirection == DIRECTION_UPCOAST) && (nThisPointOnCoast < 0))
431 {
432// 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;
433
434 break;
435 }
436
437 // Have we reached the end of the coast?
438 if ((nDirection == DIRECTION_DOWNCOAST) && (nThisPointOnCoast >= nCoastMax))
439 {
440 // 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;
441
442 break;
443 }
444
445 // LogStream << m_ulIter << ": from profile " << nProfile << ", doing potential platform erosion " << (nDirection == DIRECTION_DOWNCOAST ? "down" : "up") << "-coast, dist from profile = " << nDistFromProfile << endl;
446
447 double dDepthOfBreaking = m_VCoast[nCoast].dGetDepthOfBreaking(nThisPointOnCoast);
448 if (bFPIsEqual(dDepthOfBreaking, DBL_NODATA, TOLERANCE))
449 {
450 // 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
451 // if (m_nLogFileDetail == LOG_FILE_ALL)
452 // 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;
453
454 continue;
455 }
456
457// LogStream << m_ulIter << ": BETWEEN PROFILES " << (nDirection == DIRECTION_DOWNCOAST ? "down" : "up") << "-coast from profile " << nProfile << " nThisPointOnCoast = " << nThisPointOnCoast << " dDepthOfBreaking = " << dDepthOfBreaking << " nParProfSize = " << nParProfSize << endl;
458
459 // All is OK, so get the grid coordinates of this point, which is the coastline start point for the parallel profile
460 int const nParCoastX = m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(nThisPointOnCoast)->nGetX();
461 int const nParCoastY = m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(nThisPointOnCoast)->nGetY();
462
463 if ((nParCoastX == nParCoastXLast) && (nParCoastY == nParCoastYLast))
464 {
465 // Should not happen, but could do due to rounding errors
467 LogStream << WARN << m_ulIter << ": rounding problem on coast " << nCoast << " profile " << pProfile->nGetCoastID() << " at [" << nParCoastX << "][" << nParCoastY << "]" << endl;
468
469 // So move on to the next point along the coastline in this direction
470 continue;
471 }
472
473 // Is this coastline start point the start point of an adjacent coastline-normal vector?
474 if (m_pRasterGrid->m_Cell[nParCoastX][nParCoastY].bIsProfile())
475 {
476// 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;
477 break;
478 }
479
480 // 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
481 double const dBreakingWaveHeight = m_VCoast[nCoast].dGetBreakingWaveHeight(nThisPointOnCoast);
482
483 // OK, now construct a parallel profile
484 vector<CGeom2DIPoint> PtiVGridParProfile; // Integer coords (grid CRS) of cells under the parallel profile
485 vector<CGeom2DPoint> PtVExtCRSParProfile; // coordinates (external CRS) of cells under the parallel profile
486
487 ConstructParallelProfile(nProfileStartX, nProfileStartY, nParCoastX, nParCoastY, nProfSize, pProfile->pPtiVGetCellsInProfile(), &PtiVGridParProfile, &PtVExtCRSParProfile);
488
489 int const nParProfSize = static_cast<int>(PtiVGridParProfile.size());
490 // 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
491 if (nParProfSize < 3)
492 {
493 // 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
494 nParCoastXLast = nParCoastX;
495 nParCoastYLast = nParCoastY;
496 // LogStream << m_ulIter << ": parallel profile abandoned since too short, starts at [" << nParCoastX << "][" << nParCoastY << "] coastline point " << nThisPointOnCoast << ", length = " << nParProfSize << endl;
497 continue;
498 }
499
500 // This parallel profile is OK, so calculate potential erosion along it. First calculate the length of the parallel profile in external CRS units
501 double const dParProfileLenXY = dGetDistanceBetween(&PtVExtCRSParProfile[0], &PtVExtCRSParProfile[nParProfSize - 1]);
502
503 // 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)
504 double dParSpacingXY = dParProfileLenXY / (nParProfSize - 1);
505
506 // Safety check
507 if (bFPIsEqual(dParSpacingXY, 0.0, TOLERANCE))
508 dParSpacingXY = TOLERANCE;
509 // LogStream << "dParSpacingXY = " << dParSpacingXY << endl;
510
511 vector<double> dVParProfileZ(nParProfSize, 0); // Initial (pre-erosion) elevation of both consolidated and unconsolidated sediment for cells 'under' the parallel profile
512 vector<double> dVParProfileDistXY(nParProfSize, 0); // Along-profile distance measured from the coast, in external CRS units
513 vector<double> dVParConsProfileZ(nParProfSize, 0); // Initial (pre-erosion) elevation of consolidated sediment only for cells 'under' the parallel profile
514 vector<double> dVParConsZDiff(nParProfSize, 0);
515 vector<double> dVParConsSlope(nParProfSize, 0);
516
517 for (int i = 0; i < nParProfSize; i++)
518 {
519 int const nXPar = PtiVGridParProfile[i].nGetX();
520 int const nYPar = PtiVGridParProfile[i].nGetY();
521
522 // Is this a sea cell?
523 if (! m_pRasterGrid->m_Cell[nXPar][nYPar].bIsInundated())
524 {
525 // It isn't so move along, nothing to do here
526 // LogStream << m_ulIter << " : [" << nXPar << "][" << nYPar << "] is not inundated" << endl;
527 continue;
528 }
529
530 // Is this cell in a polygon?
531 int nPolyID = m_pRasterGrid->m_Cell[nXPar][nYPar].nGetPolygonID();
532 if (nPolyID == INT_NODATA)
533 {
534 // It isn't. This can happen at the seaward end of polygons TODO 026 Is it a problem?
535 // LogStream << m_ulIter << " : [" << nXPar << "][" << nYPar << "] = {" << dGridCentroidXToExtCRSX(nXPar) << ", " << dGridCentroidYToExtCRSY(nYPar) << "} is not in a polygon" << endl;
536 continue;
537 }
538
539 // Get the number of the highest layer with non-zero thickness
540 int const nTopLayer = m_pRasterGrid->m_Cell[nXPar][nYPar].nGetTopNonZeroLayerAboveBasement();
541
542 // Safety check
543 if (nTopLayer == INT_NODATA)
545
546 if (nTopLayer == NO_NONZERO_THICKNESS_LAYERS)
547 // TODO 025 We are down to basement
548 return RTN_OK;
549
550 // Get the elevation for consolidated sediment only on this cell
551 dVParConsProfileZ[i] = m_pRasterGrid->m_Cell[nXPar][nYPar].dGetConsSedTopForLayerAboveBasement(nTopLayer);
552
553 // Get the elevation for both consolidated and unconsolidated sediment on this cell
554 dVParProfileZ[i] = m_pRasterGrid->m_Cell[nXPar][nYPar].dGetSedimentTopElev();
555
556 // And store the X-Y plane distance from the start of the profile
557 dVParProfileDistXY[i] = i * dParSpacingXY;
558 }
559
560 for (int i = 0; i < nParProfSize - 1; i++)
561 {
562 // For the consolidated-only profile, get the Z differences (already in external CRS units)
563 dVParConsZDiff[i] = dVParConsProfileZ[i] - dVParConsProfileZ[i + 1];
564
565 // 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
566 dVParConsSlope[i] = dVParConsZDiff[i] / dParSpacingXY;
567 }
568
569 // Sort out the final slope value
570 dVParConsSlope[nParProfSize - 1] = dVParConsSlope[nParProfSize - 2];
571
573 {
574 // Smooth the vector of slopes for the consolidated-only profile
575 dVParConsSlope = dVSmoothProfileSlope(&dVParConsSlope);
576 }
577
578 // Initialize the parallel profile vector with depth / m_dWaveBreakingDepth
579 vector<double> dVParProfileDepthOverDB(nParProfSize, 0); // Depth / wave breaking depth at the parallel profile sample points
580 vector<double> dVParProfileErosionPotential(nParProfSize, 0); // Erosion potential at the parallel profile sample points
581
582 // Calculate the erosion potential along this profile using the shape function which we read in earlier
583 double dTotalErosionPotential = 0;
584
585 // Safety check TODO 061 Is this safety check to depth of breaking a reasonable thing to do?
586 if (dDepthOfBreaking <= 0.0)
587 dDepthOfBreaking = 1e-10;
588
589 for (int i = 0; i < nParProfSize; i++)
590 {
591 // 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)
592 dVParProfileDepthOverDB[i] = m_dThisIterSWL - dVParProfileZ[i];
593 dVParProfileDepthOverDB[i] /= dDepthOfBreaking;
594
595 // Constrain dDepthOverDB[i] to be between 0 (can get small -ve due to rounding errors) and m_dDepthOverDBMax
596 dVParProfileDepthOverDB[i] = tMax(dVParProfileDepthOverDB[i], 0.0);
597 dVParProfileDepthOverDB[i] = tMin(dVParProfileDepthOverDB[i], m_dDepthOverDBMax);
598
599 // And then use the look-up table to find the value of erosion potential at this point on the profile
600 dVParProfileErosionPotential[i] = dLookUpErosionPotential(dVParProfileDepthOverDB[i]);
601
602 // If erosion potential (a -ve value) is tiny, set it to zero
603 if (dVParProfileErosionPotential[i] > -SEDIMENT_ELEV_TOLERANCE)
604 dVParProfileErosionPotential[i] = 0;
605
606 // Keep track of the total erosion potential for this profile
607 dTotalErosionPotential += dVParProfileErosionPotential[i];
608 }
609
610 // 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
611 for (int i = 0; i < nParProfSize; i++)
612 {
613 if (dTotalErosionPotential < 0)
614 dVParProfileErosionPotential[i] /= (-dTotalErosionPotential);
615 }
616
617 vector<double> dVParRecessionXY(nParProfSize, 0);
618 vector<double> dVParSCAPEXY(nParProfSize, 0);
619
620 // Calculate recession at every point on the parallel profile
621 for (int i = 0; i < nParProfSize; i++)
622 {
623 // dRecession = dForce * (dBeachProtection / dR) * dErosionPotential * dSlope * dTime
624 // where:
625 // dVRecession [m] is the landward migration distance defined in the profile relative (XY) CRS
626 // dForce is given by Equation 4 in Walkden & Hall, 2005
627 // dVBeachProtection [1] is beach protection factor [1, 0] = [no protection, fully protected] (This is calculated later, see dCalcBeachProtectionFactor())
628 // dVR [m^(9/4)s^(2/3)] is the material strength and some hydrodynamic constant
629 // dVProfileErosionPotential [?] is the erosion potential at each point along the profile
630 // dVSlope [1] is the along-profile slope
631 // m_dTimeStep * 3600 [s] is the time interval in seconds
632 //
633 // dRecession is horizontal recession (along the XY direction):
634 //
635 // dVRecessionXY[i] = (dForce * dVBeachProtection[i] * dVErosionPotentialFunc[i] * dVSlope[i] * m_dTimeStep * 3600) / dVR[i]
636 //
637 //
638 // 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
639 dVParRecessionXY[i] = tMin(m_VCoast[nCoast].dGetWaveEnergyAtBreaking(nThisPointOnCoast) * dVParProfileErosionPotential[i] * dVParConsSlope[i] / m_dR, 0.0);
640 dVParSCAPEXY[i] = dVParProfileDistXY[i] - dVParRecessionXY[i];
641
642 // 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;
643 }
644
645 vector<double> dVParDeltaZ(nParProfSize, 0);
646
647 // 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
648 for (int i = 1; i < nParProfSize - 1; i++)
649 {
650 // Vertical lowering dZ = dXY * tan(a), where tan(a) is the slope of the SCAPE profile in the XY direction
651 double dSCAPEHorizDist = dVParSCAPEXY[i + 1] - dVParSCAPEXY[i];
652
653 // Safety check
654 if (bFPIsEqual(dSCAPEHorizDist, 0.0, TOLERANCE))
655 continue;
656
657 double dSCAPEVertDist = dVParConsProfileZ[i] - dVParConsProfileZ[i + 1];
658 double dSCAPESlope = dSCAPEVertDist / dSCAPEHorizDist;
659 double dDeltaZ = dVParRecessionXY[i] * dSCAPESlope;
660 // 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
661 if (dSCAPESlope > 1)
662 {
663 dDeltaZ = 0;
664 }
665
666 int const nXPar = PtiVGridParProfile[i].nGetX();
667 int const nYPar = PtiVGridParProfile[i].nGetY();
668
669 // Store the local slope of the consolidated sediment, this is just for output display purposes
670 m_pRasterGrid->m_Cell[nXPar][nYPar].SetLocalConsSlope(dVParConsSlope[i]);
671
672 // dDeltaZ is zero or -ve: if dDeltaZ is zero then do nothing, if -ve then remove some sediment from this cell
673 if (dDeltaZ < 0)
674 {
675 // Has this cell already been eroded during this timestep?
676 if (m_pRasterGrid->m_Cell[nXPar][nYPar].bPotentialPlatformErosion())
677 {
678 // It has
679 double const dPrevPotentialErosion = -m_pRasterGrid->m_Cell[nXPar][nYPar].dGetPotentialPlatformErosion();
680
681 // 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;
682
683 // Use the larger of the two -ve values
684 dDeltaZ = tMin(dPrevPotentialErosion, dDeltaZ);
685
686 // Adjust this-timestep totals, since this cell has already been eroded
688 m_dThisIterPotentialPlatformErosion += dPrevPotentialErosion; // Since dPrevPotentialErosion is +ve
689 // assert(isfinite(m_dThisIterPotentialPlatformErosion));
690 // assert(m_dThisIterPotentialPlatformErosion >= 0);
691
692 // And also adjust the check values
694 m_dTotPotentialPlatformErosionBetweenProfiles += dPrevPotentialErosion; // Since -ve
695 }
696
697 // Constrain the lowering so we don't get negative slopes or +ve erosion amounts (dDeltaZ must be -ve), this is implicit in SCAPE
698 dDeltaZ = tMax(dDeltaZ, -dVParConsZDiff[i]);
699 dDeltaZ = tMin(dDeltaZ, 0.0);
700 dVParDeltaZ[i] = dDeltaZ;
701
702 // Set the potential (unconstrained) erosion for this cell, it is a +ve value
703 m_pRasterGrid->m_Cell[nXPar][nYPar].SetPotentialPlatformErosion(-dDeltaZ);
704// LogStream << "[" << nXPar << "][" << nYPar << "] = {" << dGridCentroidXToExtCRSX(nXPar) << ", " << dGridCentroidYToExtCRSY(nYPar) << "} has potential platform erosion = " << -dDeltaZ << endl;
705
706 // Update this-timestep totals
708 m_dThisIterPotentialPlatformErosion -= dDeltaZ; // Since dDeltaZ is a -ve value
709// assert(isfinite(m_dThisIterPotentialPlatformErosion));
710// assert(m_dThisIterPotentialPlatformErosion >= 0);
711
712 // Increment the check values
714 m_dTotPotentialPlatformErosionBetweenProfiles -= dDeltaZ; // Since -ve
715 }
716
717 // Finally, calculate the beach protection factor, this will be used in estimating actual (supply-limited) erosion
718 double const dBeachProtectionFactor = dCalcBeachProtectionFactor(nXPar, nYPar, dBreakingWaveHeight);
719 m_pRasterGrid->m_Cell[nXPar][nYPar].SetBeachProtectionFactor(dBeachProtectionFactor);
720 }
721
722 // If desired, save this parallel coastline-normal profile for checking purposes
724 {
725 int const nRet = nSaveParProfile(nCoast, pProfile, nParProfSize, nDirection, nDistFromProfile, &dVParProfileDistXY, &dVParConsProfileZ, &dVParProfileDepthOverDB, &dVParProfileErosionPotential, &dVParConsSlope, &dVParRecessionXY, &dVParDeltaZ, pProfile->pPtiVGetCellsInProfile(), &dVParSCAPEXY);
726 if (nRet != RTN_OK)
727 return nRet;
728 }
729
730 // Update for next time round the loop
731 nParCoastXLast = nParCoastX;
732 nParCoastYLast = nParCoastY;
733 }
734
735 return RTN_OK;
736}
737
738//===============================================================================================================================
740//===============================================================================================================================
741void CSimulation::DoActualPlatformErosionOnCell(int const nX, int const nY)
742{
743// LogStream << m_ulIter << ": doing platform erosion on cell [" << nX << "][" << nY << "] = {" << dGridCentroidXToExtCRSX(nX) << ", " << dGridCentroidYToExtCRSY(nY) << "}" << endl;
744
745 // Get the beach protection factor, which quantifies the extent to which unconsolidated sediment on the shore platform (beach) protects the shore platform
746 double const dBeachProtectionFactor = m_pRasterGrid->m_Cell[nX][nY].dGetBeachProtectionFactor();
747 if (bFPIsEqual(dBeachProtectionFactor, 0.0, TOLERANCE))
748 // The beach is sufficiently thick to prevent any platform erosion (or we are down to basement)
749 return;
750
751 // Get the potential depth of potential erosion, considering beach protection
752 double dThisPotentialErosion = m_pRasterGrid->m_Cell[nX][nY].dGetPotentialPlatformErosion() * dBeachProtectionFactor;
753
754 // We will be eroding the topmost layer that has non-zero thickness
755 int nThisLayer = m_pRasterGrid->m_Cell[nX][nY].nGetTopNonZeroLayerAboveBasement();
756
757 // Safety check
758 if (nThisLayer == INT_NODATA)
759 {
760 cerr << ERR << "no sediment layer in DoActualPlatformErosionOnCell()" << endl;
761 return;
762 }
763
764 if (nThisLayer == NO_NONZERO_THICKNESS_LAYERS)
765 // No layer with non-zero thickness left, we are down to basement
766 return;
767
768 // OK, we have a layer that can be eroded so find out how much consolidated sediment we have available on this cell
769 double dExistingAvailableFine = m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nThisLayer)->pGetConsolidatedSediment()->dGetFineDepth();
770 double dExistingAvailableSand = m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nThisLayer)->pGetConsolidatedSediment()->dGetSandDepth();
771 double dExistingAvailableCoarse = m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nThisLayer)->pGetConsolidatedSediment()->dGetCoarseDepth();
772
773 // Now partition the total lowering for this cell between the three size fractions: do this by relative erodibility
774 int nFineWeight = (dExistingAvailableFine > 0 ? 1 : 0);
775 int nSandWeight = (dExistingAvailableSand > 0 ? 1 : 0);
776 int nCoarseWeight = (dExistingAvailableCoarse > 0 ? 1 : 0);
777
778 double dTotErodibility = (nFineWeight * m_dFineErodibilityNormalized) + (nSandWeight * m_dSandErodibilityNormalized) + (nCoarseWeight * m_dCoarseErodibilityNormalized);
779 double dTotActualErosion = 0;
780 double dSandEroded = 0;
781 double dCoarseEroded = 0;
782
783 if (nFineWeight)
784 {
785 // Erode some fine-sized consolidated sediment
786 double dFineLowering = (m_dFineErodibilityNormalized * dThisPotentialErosion) / dTotErodibility;
787
788 // Make sure we don't get -ve amounts left on the cell
789 double dFineEroded = tMin(dExistingAvailableFine, dFineLowering);
790 double dRemaining = dExistingAvailableFine - dFineEroded;
791
792 dTotActualErosion += dFineEroded;
793
794 // Set the value for this layer
795 m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nThisLayer)->pGetConsolidatedSediment()->SetFineDepth(dRemaining);
796
797 // And set the changed-this-timestep switch
798 m_bConsChangedThisIter[nThisLayer] = true;
799
800 // And increment the per-timestep total, also add to the suspended sediment load
803 }
804
805 if (nSandWeight)
806 {
807 // Erode some sand-sized consolidated sediment
808 double dSandLowering = (m_dSandErodibilityNormalized * dThisPotentialErosion) / dTotErodibility;
809
810 // Make sure we don't get -ve amounts left on the source cell
811 dSandEroded = tMin(dExistingAvailableSand, dSandLowering);
812 double dRemaining = dExistingAvailableSand - dSandEroded;
813
814 dTotActualErosion += dSandEroded;
815
816 // Set the new value of sand consolidated sediment depth for this layer
817 m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nThisLayer)->pGetConsolidatedSediment()->SetSandDepth(dRemaining);
818
819 // And add this to the depth of sand unconsolidated sediment for this layer
820 m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nThisLayer)->pGetUnconsolidatedSediment()->AddSandDepth(dSandEroded);
821
822 // Set the changed-this-timestep switch
823 m_bConsChangedThisIter[nThisLayer] = true;
824
825 // And increment the per-timestep total
827 }
828
829 if (nCoarseWeight)
830 {
831 // Erode some coarse-sized consolidated sediment
832 double dCoarseLowering = (m_dCoarseErodibilityNormalized * dThisPotentialErosion) / dTotErodibility;
833
834 // Make sure we don't get -ve amounts left on the source cell
835 dCoarseEroded = tMin(dExistingAvailableCoarse, dCoarseLowering);
836 double dRemaining = dExistingAvailableCoarse - dCoarseEroded;
837
838 dTotActualErosion += dCoarseEroded;
839
840 // Set the new value of coarse consolidated sediment depth for this layer
841 m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nThisLayer)->pGetConsolidatedSediment()->SetCoarseDepth(dRemaining);
842
843 // And add this to the depth of coarse unconsolidated sediment for this layer
844 m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nThisLayer)->pGetUnconsolidatedSediment()->AddCoarseDepth(dCoarseEroded);
845
846 // Set the changed-this-timestep switch
847 m_bConsChangedThisIter[nThisLayer] = true;
848
849 // And increment the per-timestep total
851 }
852
853 // Did we erode anything?
854 if (dTotActualErosion > 0)
855 {
856 // We did, so set the actual erosion value for this cell
857 m_pRasterGrid->m_Cell[nX][nY].SetActualPlatformErosion(dTotActualErosion);
858
859 // Recalculate the elevation of every layer
860 m_pRasterGrid->m_Cell[nX][nY].CalcAllLayerElevsAndD50();
861
862 // And update the cell's sea depth
863 m_pRasterGrid->m_Cell[nX][nY].SetSeaDepth();
864
865 // Update per-timestep totals
867
868 // 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)
869 int nPolyID = m_pRasterGrid->m_Cell[nX][nY].nGetPolygonID();
870 if (nPolyID == INT_NODATA)
871 {
872 // Can get occasional problems with polygon rasterization near the coastline, so also search the eight adjacent cells
873 array<int, 8> nDirection = {NORTH, NORTH_EAST, EAST, SOUTH_EAST, SOUTH, SOUTH_WEST, WEST, NORTH_WEST};
874 shuffle(nDirection.begin(), nDirection.end(), m_Rand[0]);
875
876 for (int n = 0; n < 8; n++)
877 {
878 int nXAdj;
879 int nYAdj;
880
881 if (nDirection[n] == NORTH)
882 {
883 nXAdj = nX;
884 nYAdj = nY - 1;
885 if (nYAdj >= 0)
886 {
887 nPolyID = m_pRasterGrid->m_Cell[nXAdj][nYAdj].nGetPolygonID();
888 if (nPolyID != INT_NODATA)
889 break;
890 }
891 }
892 else if (nDirection[n] == NORTH_EAST)
893 {
894 nXAdj = nX + 1;
895 nYAdj = nY - 1;
896 if ((nXAdj < m_nXGridSize) && (nYAdj >= 0))
897 {
898 nPolyID = m_pRasterGrid->m_Cell[nXAdj][nYAdj].nGetPolygonID();
899 if (nPolyID != INT_NODATA)
900 break;
901 }
902 }
903 else if (nDirection[n] == EAST)
904 {
905 nXAdj = nX + 1;
906 nYAdj = nY;
907 if (nXAdj < m_nXGridSize)
908 {
909 nPolyID = m_pRasterGrid->m_Cell[nXAdj][nYAdj].nGetPolygonID();
910 if (nPolyID != INT_NODATA)
911 break;
912 }
913 }
914 else if (nDirection[n] == SOUTH_EAST)
915 {
916 nXAdj = nX + 1;
917 nYAdj = nY + 1;
918 if ((nXAdj < m_nXGridSize) && (nYAdj < m_nYGridSize))
919 {
920 nPolyID = m_pRasterGrid->m_Cell[nXAdj][nYAdj].nGetPolygonID();
921 if (nPolyID != INT_NODATA)
922 break;
923 }
924 }
925 else if (nDirection[n] == SOUTH)
926 {
927 nXAdj = nX;
928 nYAdj = nY + 1;
929 if (nYAdj < m_nYGridSize)
930 {
931 nPolyID = m_pRasterGrid->m_Cell[nXAdj][nYAdj].nGetPolygonID();
932 if (nPolyID != INT_NODATA)
933 break;
934 }
935 }
936 else if (nDirection[n] == SOUTH_WEST)
937 {
938 nXAdj = nX - 1;
939 nYAdj = nY + 1;
940 if ((nXAdj >= 0) && (nXAdj < m_nXGridSize))
941 {
942 nPolyID = m_pRasterGrid->m_Cell[nXAdj][nYAdj].nGetPolygonID();
943 if (nPolyID != INT_NODATA)
944 break;
945 }
946 }
947 else if (nDirection[n] == WEST)
948 {
949 nXAdj = nX - 1;
950 nYAdj = nY;
951 if (nXAdj >= 0)
952 {
953 nPolyID = m_pRasterGrid->m_Cell[nXAdj][nYAdj].nGetPolygonID();
954 if (nPolyID != INT_NODATA)
955 break;
956 }
957 }
958 else if (nDirection[n] == NORTH_WEST)
959 {
960 nXAdj = nX - 1;
961 nYAdj = nY - 1;
962 if ((nXAdj >= 0) && (nYAdj >= 0))
963 {
964 nPolyID = m_pRasterGrid->m_Cell[nXAdj][nYAdj].nGetPolygonID();
965 if (nPolyID != INT_NODATA)
966 break;
967 }
968 }
969 }
970 }
971
972 if (nPolyID != INT_NODATA)
973 {
974 // Add this to the polygon's total of unconsolidated sand/coarse sediment, to be deposited or moved later. These values are +ve (deposition)
975 m_pVCoastPolygon[nPolyID]->AddPlatformErosionUnconsSand(dSandEroded);
976 m_pVCoastPolygon[nPolyID]->AddPlatformErosionUnconsCoarse(dCoarseEroded);
977 }
978 else
979 {
980 // Uh-oh, we have a problem
982 LogStream << m_ulIter << ": " << WARN << "platform erosion on cell [" << nX << "][" << nY << "] = {" << dGridCentroidXToExtCRSX(nX) << ", " << dGridCentroidYToExtCRSY(nY) << "} but this is not in a polygon" << endl;
983
984 // m_dDepositionSandDiff and m_dDepositionCoarseDiff are both +ve
985 m_dDepositionSandDiff += dSandEroded;
986 m_dDepositionCoarseDiff += dCoarseEroded;
987 }
988 }
989}
990
991//===============================================================================================================================
993//===============================================================================================================================
994bool CSimulation::bCreateErosionPotentialLookUp(vector<double>* VdDepthOverDBIn, vector<double>* VdErosionPotentialIn, vector<double>* VdErosionPotentialFirstDerivIn)
995{
996 // Set up a temporary vector to hold the incremental DepthOverDB values
997 vector<double> VdDepthOverDB;
998 double dTempDOverDB = 0;
999
1000 while (dTempDOverDB <= 1.1) // Arbitrary max value, we will adjust this later
1001 {
1002 VdDepthOverDB.push_back(dTempDOverDB); // These are the incremental sample values of DepthOverDB
1003 dTempDOverDB += DEPTH_OVER_DB_INCREMENT;
1004
1005 m_VdErosionPotential.push_back(0); // This will hold the corresponding value of erosion potential for each sample point
1006 }
1007
1008 int nSize = static_cast<int>(VdDepthOverDB.size());
1009 vector<double> VdDeriv(nSize, 0); // First derivative at the sample points: calculated by the spline function but not subsequently used
1010 vector<double> VdDeriv2(nSize, 0.); // Second derivative at the sample points, ditto
1011 vector<double> VdDeriv3(nSize, 0.); // Third derivative at the sample points, ditto
1012
1013 // 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
1014 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]));
1015
1016 // Tidy the erosion potential look-up data: cut off values (after the first) for which erosion potential is no longer -ve
1017 int nLastVal = -1;
1018
1019 for (int n = 1; n < nSize - 1; n++)
1020 if (m_VdErosionPotential[n] > 0)
1021 {
1022 nLastVal = n;
1023 break;
1024 }
1025
1026 if (nLastVal > 0)
1027 {
1028 // 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)
1029 m_dDepthOverDBMax = VdDepthOverDB[nLastVal];
1030 m_VdErosionPotential.erase(m_VdErosionPotential.begin() + nLastVal + 1, m_VdErosionPotential.end());
1031 m_VdErosionPotential.back() = 0;
1032 }
1033
1034 else
1035 // Erosion potential is unbounded, i.e. it is still -ve when we have reached the end of the look-up vector
1036 return false;
1037
1038 // All OK
1039 return true;
1040}
1041
1042//===============================================================================================================================
1044//===============================================================================================================================
1045double CSimulation::dLookUpErosionPotential(double const dDepthOverDB) const
1046{
1047 // If dDepthOverDB exceeds the maximum value which we calculated earlier, erosion potential is zero
1048 if (dDepthOverDB > m_dDepthOverDBMax)
1049 return 0;
1050
1051 // 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
1052 double dErosionPotential = dGetInterpolatedValue(&m_VdDepthOverDB, &m_VdErosionPotential, dDepthOverDB, false);
1053
1054 return dErosionPotential;
1055}
1056
1057//===============================================================================================================================
1059//===============================================================================================================================
1060double CSimulation::dCalcBeachProtectionFactor(int const nX, int const nY, double const dBreakingWaveHeight)
1061{
1062 // Safety check
1063 if (bFPIsEqual(dBreakingWaveHeight, DBL_NODATA, TOLERANCE))
1064 return 0;
1065
1066 // We are considering the unconsolidated sediment (beach) of the topmost layer that has non-zero thickness
1067 int nThisLayer = m_pRasterGrid->m_Cell[nX][nY].nGetTopNonZeroLayerAboveBasement();
1068
1069 // Safety check
1070 if (nThisLayer == INT_NODATA)
1071 {
1072 cerr << ERR << "no sediment layer in dCalcBeachProtectionFactor()" << endl;
1073 return 0;
1074 }
1075
1076 if (nThisLayer == NO_NONZERO_THICKNESS_LAYERS)
1077 // There are no layers with non-zero thickness left (i.e. we are down to basement) so no beach protection
1078 return 0;
1079
1080 // 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
1081 double dBeachDepth = m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nThisLayer)->dGetUnconsolidatedThickness();
1082 double dMaxPenetrationDepth = BEACH_PROTECTION_HB_RATIO * dBreakingWaveHeight;
1083 double dFactor = 0;
1084
1085 if (dMaxPenetrationDepth > 0)
1086 dFactor = tMax(1 - (dBeachDepth / dMaxPenetrationDepth), 0.0);
1087
1088 // LogStream << m_ulIter << ": cell[" << nX << "][" << nY << "] has beach protection factor = " << dFactor << endl;
1089
1090 return dFactor;
1091}
1092
1093//===============================================================================================================================
1095//===============================================================================================================================
1097{
1098 for (int nX = 0; nX < m_nXGridSize; nX++)
1099 {
1100 for (int nY = 0; nY < m_nYGridSize; nY++)
1101 {
1102 if ((m_pRasterGrid->m_Cell[nX][nY].bIsInContiguousSea()) && (bFPIsEqual(m_pRasterGrid->m_Cell[nX][nY].dGetBeachProtectionFactor(), DBL_NODATA, TOLERANCE)))
1103 {
1104 // This is a sea cell, and it has an initialized beach protection value. So look at its N-S and W-E neighbours
1105 int nXTmp;
1106 int nYTmp;
1107 int nAdjacent = 0;
1108 double dBeachProtection = 0;
1109
1110 // North
1111 nXTmp = nX;
1112 nYTmp = nY - 1;
1113 if ((bIsWithinValidGrid(nXTmp, nYTmp)) && (! bFPIsEqual(m_pRasterGrid->m_Cell[nXTmp][nYTmp].dGetBeachProtectionFactor(), DBL_NODATA, TOLERANCE)))
1114 {
1115 nAdjacent++;
1116 dBeachProtection += m_pRasterGrid->m_Cell[nXTmp][nYTmp].dGetBeachProtectionFactor();
1117 }
1118
1119 // East
1120 nXTmp = nX + 1;
1121 nYTmp = nY;
1122 if ((bIsWithinValidGrid(nXTmp, nYTmp)) && (! bFPIsEqual(m_pRasterGrid->m_Cell[nXTmp][nYTmp].dGetBeachProtectionFactor(), DBL_NODATA, TOLERANCE)))
1123 {
1124 nAdjacent++;
1125 dBeachProtection += m_pRasterGrid->m_Cell[nXTmp][nYTmp].dGetBeachProtectionFactor();
1126 }
1127
1128 // South
1129 nXTmp = nX;
1130 nYTmp = nY + 1;
1131 if ((bIsWithinValidGrid(nXTmp, nYTmp)) && (! bFPIsEqual(m_pRasterGrid->m_Cell[nXTmp][nYTmp].dGetBeachProtectionFactor(), DBL_NODATA, TOLERANCE)))
1132 {
1133 nAdjacent++;
1134 dBeachProtection += m_pRasterGrid->m_Cell[nXTmp][nYTmp].dGetBeachProtectionFactor();
1135 }
1136
1137 // West
1138 nXTmp = nX - 1;
1139 nYTmp = nY;
1140 if ((bIsWithinValidGrid(nXTmp, nYTmp)) && (! bFPIsEqual(m_pRasterGrid->m_Cell[nXTmp][nYTmp].dGetBeachProtectionFactor(), DBL_NODATA, TOLERANCE)))
1141 {
1142 nAdjacent++;
1143 dBeachProtection += m_pRasterGrid->m_Cell[nXTmp][nYTmp].dGetBeachProtectionFactor();
1144 }
1145
1146 // 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
1147 if (nAdjacent == 4)
1148 {
1149 m_pRasterGrid->m_Cell[nX][nY].SetBeachProtectionFactor(dBeachProtection / 4);
1150 }
1151 }
1152 }
1153 }
1154}
1155
1156//===============================================================================================================================
1158//===============================================================================================================================
1160{
1161 for (int nX = 0; nX < m_nXGridSize; nX++)
1162 {
1163 for (int nY = 0; nY < m_nYGridSize; nY++)
1164 {
1165 if ((m_pRasterGrid->m_Cell[nX][nY].bIsInContiguousSea()) && (bFPIsEqual(m_pRasterGrid->m_Cell[nX][nY].dGetPotentialPlatformErosion(), 0.0, TOLERANCE)))
1166 {
1167 // This is a sea cell, it has a zero potential platform erosion value. So look at its N-S and W-E neighbours
1168 int nXTmp;
1169 int nYTmp;
1170 int nAdjacent = 0;
1171 double dPotentialPlatformErosion = 0;
1172
1173 // North
1174 nXTmp = nX;
1175 nYTmp = nY - 1;
1176 if ((bIsWithinValidGrid(nXTmp, nYTmp)) && (! bFPIsEqual(m_pRasterGrid->m_Cell[nXTmp][nYTmp].dGetPotentialPlatformErosion(), 0.0, TOLERANCE)))
1177 {
1178 nAdjacent++;
1179 dPotentialPlatformErosion += m_pRasterGrid->m_Cell[nXTmp][nYTmp].dGetPotentialPlatformErosion();
1180 }
1181
1182 // East
1183 nXTmp = nX + 1;
1184 nYTmp = nY;
1185 if ((bIsWithinValidGrid(nXTmp, nYTmp)) && (! bFPIsEqual(m_pRasterGrid->m_Cell[nXTmp][nYTmp].dGetPotentialPlatformErosion(), 0.0, TOLERANCE)))
1186 {
1187 nAdjacent++;
1188 dPotentialPlatformErosion += m_pRasterGrid->m_Cell[nXTmp][nYTmp].dGetPotentialPlatformErosion();
1189 }
1190
1191 // South
1192 nXTmp = nX;
1193 nYTmp = nY + 1;
1194 if ((bIsWithinValidGrid(nXTmp, nYTmp)) && (! bFPIsEqual(m_pRasterGrid->m_Cell[nXTmp][nYTmp].dGetPotentialPlatformErosion(), 0.0, TOLERANCE)))
1195 {
1196 nAdjacent++;
1197 dPotentialPlatformErosion += m_pRasterGrid->m_Cell[nXTmp][nYTmp].dGetPotentialPlatformErosion();
1198 }
1199
1200 // West
1201 nXTmp = nX - 1;
1202 nYTmp = nY;
1203 if ((bIsWithinValidGrid(nXTmp, nYTmp)) && (! bFPIsEqual(m_pRasterGrid->m_Cell[nXTmp][nYTmp].dGetPotentialPlatformErosion(), 0.0, TOLERANCE)))
1204 {
1205 nAdjacent++;
1206 dPotentialPlatformErosion += m_pRasterGrid->m_Cell[nXTmp][nYTmp].dGetPotentialPlatformErosion();
1207 }
1208
1209 // 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
1210 if (nAdjacent == 4)
1211 {
1212 double dThisPotentialPlatformErosion = dPotentialPlatformErosion / 4;
1213
1214 m_pRasterGrid->m_Cell[nX][nY].SetPotentialPlatformErosion(dThisPotentialPlatformErosion);
1215
1216 // Update this-timestep totals
1218 m_dThisIterPotentialPlatformErosion += dThisPotentialPlatformErosion;
1219 // assert(isfinite(m_dThisIterPotentialPlatformErosion));
1220
1221 // Increment the check values
1223 m_dTotPotentialPlatformErosionBetweenProfiles += dThisPotentialPlatformErosion;
1224 }
1225 }
1226 }
1227 }
1228}
1229
1230//===============================================================================================================================
1232//===============================================================================================================================
1233void 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)
1234{
1235 // 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
1236 int nXOffset = nParCoastX - nProfileStartX;
1237 int nYOffset = nParCoastY - nProfileStartY;
1238
1239 // Append co-ord values for the temporary profile
1240 for (int nProfileStartPoint = 0; nProfileStartPoint < nProfSize; nProfileStartPoint++)
1241 {
1242 // Get the grid coordinates of the cell which is this distance seaward, from the coastline-normal profile
1243 int nXProf = pPtViGridProfile->at(nProfileStartPoint).nGetX();
1244 int nYProf = pPtViGridProfile->at(nProfileStartPoint).nGetY();
1245
1246 // Now calculate the grid coordinates of this cell, which is potentially in the parallel profile
1247 int nXPar = nXProf + nXOffset;
1248 int nYPar = nYProf + nYOffset;
1249
1250 // Is this cell within the grid? If not, cut short the profile
1251 if (! bIsWithinValidGrid(nXPar, nYPar))
1252 {
1253 // LogStream << "NOT WITHIN GRID [" << nXPar << "][" << nYPar << "]" << endl;
1254 return;
1255 }
1256
1257 // Have we hit an adjacent coastline-normal profile? If so, cut short
1258 if (m_pRasterGrid->m_Cell[nXPar][nYPar].bIsProfile())
1259 {
1260 // LogStream << "HIT PROFILE " << m_pRasterGrid->m_Cell[nXPar][nYPar].nGetProfileID() << " at [" << nXPar << "][" << nYPar << "] = {" << dGridCentroidXToExtCRSX(nXPar) << ", " << dGridCentroidYToExtCRSY(nYPar) << "}" << endl;
1261 return;
1262 }
1263
1264 // OK, append the cell details
1265 pPtiVGridParProfile->push_back(CGeom2DIPoint(nXPar, nYPar));
1266 pPtVExtCRSParProfile->push_back(CGeom2DPoint(dGridCentroidXToExtCRSX(nXPar), dGridCentroidYToExtCRSY(nYPar)));
1267 }
1268}
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:78
int nGetNumCellsInProfile(void) const
Returns the number of cells in the profile.
Definition profile.cpp:489
CGeom2DPoint * pPtGetPointInProfile(int const)
Returns a single point in the profile.
Definition profile.cpp:332
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:231
int nGetCoastID(void) const
Returns the profile's coast ID.
Definition profile.cpp:66
int nGetProfileSize(void) const
Returns the number of points in the profile.
Definition profile.cpp:325
vector< CGeom2DIPoint > * pPtiVGetCellsInProfile(void)
Returns all cells in the profile.
Definition profile.cpp:475
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:530
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
The still water level for this timestep (this includes tidal changes and any long-term SWL change)
Definition simulation.h:667
CGeomRasterGrid * m_pRasterGrid
Pointer to the raster grid object.
int m_nXGridSize
The size of the grid in the x direction.
Definition simulation.h:431
ofstream LogStream
vector< CRWCoast > m_VCoast
The coastline objects.
default_random_engine m_Rand[NRNG]
The c++11 random number generators.
double m_dFineErodibilityNormalized
Relative erodibility of fine unconsolidated beach sediment, normalized.
Definition simulation.h:751
double m_dThisIterActualPlatformErosionCoarseCons
Total actual platform erosion (coarse consolidated sediment) for this iteration (depth in m)
Definition simulation.h:793
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:434
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:757
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:850
double m_dDepositionCoarseDiff
Error term: if we are unable to deposit enough unconslidated coarse on polygon(s),...
Definition simulation.h:841
unsigned long m_ulThisIterNumActualPlatformErosionCells
The number of grid cells on which actual platform erosion occurs, for this iteration.
Definition simulation.h:574
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
Error term: if we are unable to deposit enough unconslidated sand on polygon(s), this is held over to...
Definition simulation.h:838
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
Total potential platform erosion (all size classes of consolidated sediment) for this iteration (dept...
Definition simulation.h:784
vector< double > dVSmoothProfileSlope(vector< double > *) const
Does running-mean smoothing of the slope of a coastline-normal profile.
double m_dDepthOverDBMax
Maximum value of deoth over DB, is used in erosion potential look-up function.
Definition simulation.h:844
double m_dSandErodibilityNormalized
Relative erodibility of sand unconsolidated beach sediment, normalized.
Definition simulation.h:754
double m_dR
Coast platform resistance to erosion R, see Walkden & Hall, 2011.
Definition simulation.h:724
double m_dThisIterActualPlatformErosionSandCons
Total actual platform erosion (sand consolidated sediment) for this iteration (depth in m)
Definition simulation.h:790
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:71
double m_dTotPotentialPlatformErosionOnProfiles
Total potential platform erosion on profiles.
Definition simulation.h:847
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
Total fine unconsolidated sediment in suspension for this iteration (depth in m)
Definition simulation.h:814
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
The number of grid cells on which potential platform erosion occurs, for this iteration.
Definition simulation.h:571
unsigned long m_ulTotPotentialPlatformErosionOnProfiles
The number of cells on which on-profile average potential shore platform erosion occurs.
Definition simulation.h:586
double m_dCellArea
Area of a cell (in external CRS units)
Definition simulation.h:616
unsigned long m_ulTotPotentialPlatformErosionBetweenProfiles
The number of cells on which between-profile average potential shore platform erosion occurs.
Definition simulation.h:589
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:553
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:317
bool bCreateErosionPotentialLookUp(vector< double > *, vector< double > *, vector< double > *)
Creates a look-up table for erosion potential, given depth over DB.
double m_dThisIterActualPlatformErosionFineCons
Total actual platform erosion (fine consolidated sediment) for this iteration (depth in m)
Definition simulation.h:787
int m_nProfileSmoothWindow
The size of the window used for running-mean coast-normal profile smoothing (must be odd)
Definition simulation.h:449
vector< bool > m_bConsChangedThisIter
One element per layer: has the consolidated sediment of this layer been changed during this iteration...
bool m_bOutputParallelProfileData
Output parallel profile data?
Definition simulation.h:320
vector< CGeomCoastPolygon * > m_pVCoastPolygon
Pointers to coast polygon objects, in down-coast sequence TODO 044 Will need to use global polygon ID...
This file contains global definitions for CoastalME.
int const NO_NONZERO_THICKNESS_LAYERS
Definition cme.h:652
int const INT_NODATA
Definition cme.h:362
T tMin(T a, T b)
Definition cme.h:1136
double const TOLERANCE
Definition cme.h:698
int const RTN_ERR_NO_TOP_LAYER
Definition cme.h:623
string const ERR
Definition cme.h:775
int const DIRECTION_DOWNCOAST
Definition cme.h:392
int const SOUTH_EAST
Definition cme.h:386
double const DEPTH_OVER_DB_INCREMENT
Definition cme.h:690
int const LOG_FILE_MIDDLE_DETAIL
Definition cme.h:377
bool bFPIsEqual(const T d1, const T d2, const T dEpsilon)
Definition cme.h:1176
int const SOUTH_WEST
Definition cme.h:388
T tMax(T a, T b)
Definition cme.h:1123
int const NORTH_WEST
Definition cme.h:390
int const LOG_FILE_HIGH_DETAIL
Definition cme.h:378
string const WARN
Definition cme.h:776
double const SEDIMENT_ELEV_TOLERANCE
Definition cme.h:699
int const SOUTH
Definition cme.h:387
int const LOG_FILE_ALL
Definition cme.h:379
int const EAST
Definition cme.h:385
int const RTN_OK
Definition cme.h:577
int const NORTH_EAST
Definition cme.h:384
int const DIRECTION_UPCOAST
Definition cme.h:393
double const DBL_NODATA
Definition cme.h:707
double const BEACH_PROTECTION_HB_RATIO
Definition cme.h:686
int const NORTH
Definition cme.h:383
int const WEST
Definition cme.h:389
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.