CoastalME (Coastal Modelling Environment)
Simulates the long-term behaviour of complex coastlines
Loading...
Searching...
No Matches
do_beach_sediment_movement.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 <cfloat>
29
30#include <iostream>
31using std::cout;
32using std::endl;
33
34#include <string>
35using std::to_string;
36
37#include <algorithm>
38using std::stable_sort;
39
40#include "cme.h"
41#include "simulation.h"
42#include "coast.h"
43
44//===============================================================================================================================
46//===============================================================================================================================
47bool bPolygonAndAdjCompare(const vector<int>& nVLeft, const vector<int>& nVRight)
48{
49 // Each row (vector) of this vector-of-vectors is:
50 // 0: This-polygon global ID
51 // 1: This-polygon coast ID (in down-coast seq when sorted)
52 // 2: This-polygon down-coast (true) or up-coast (false) sediment movement
53 // 3 and subsequent: down-coast seqs of down-coast adjacent polygons (if sediment movement is down-coast) or up-coast adjacent polygons (if sediment movement is up-coast)
54
55 bool bDownCoast = nVLeft[2];
56
57 // For safety, check that the LHS polygon has at least one adjacent polygon (it should have, apart from the bad situation where just one big polygon is created)
58 if ((nVLeft.size() >= 4) && (nVRight.size() >= 4))
59 {
60 // Sort out polygon-to-polygon dependencies. We need to put 'target' polygons after 'source' polygons, so that the source is processed before the target. So is the RHS polygon among the adjacent polygons of the LHS polygon?
61
62 bool bFound = false;
63 for (unsigned int n = 3; n < nVLeft.size(); n++)
64 {
65 if (nVLeft[n] == nVRight[1])
66 bFound = true;
67 }
68
69 if (bFound)
70 {
71 // Yes, the RHS polygon is among the adjacent polygons of the LHS polygon, so uncons sediment movement is from the LHS polygon to the RHS polygon i.e. downcoast
72 if (bDownCoast)
73 // Keep the existing sequence
74 return true;
75 else
76 // Swap them
77 return false;
78 }
79
80 // Is the LHS polygon among the adjacent polygons of the RHS polygon?
81 bFound = false;
82 for (unsigned int n = 3; n < nVRight.size(); n++)
83 {
84 if (nVRight[n] == nVLeft[1])
85 bFound = true;
86 }
87
88 if (bFound)
89 {
90 // Yes, the LHS polygon is among the adjacent polygons of the RHS polygon, so uncons sediment movement is from the RHS polygon to the LHS polygon i.e. upcoast
91 if (bDownCoast)
92 // Swap them
93 return false;
94 else
95 // Keep the existing sequence
96 return true;
97 }
98
99 }
100
101 // Neither polygon has the other polygon amongst its list of adjacent polygons
102 if (nVLeft[1] < nVRight[1])
103 {
104 // The LHS polygon has a lower coast ID than the RHS polygon, this if fine if uncons sediment movement is down-coast
105 if (bDownCoast)
106 // Keep the existing sequence
107 return true;
108 else
109 // Swap them
110 return false;
111 }
112 else
113 {
114 // The LHS polygon has a higher coast ID than the RHS polygon, this if fine if uncons sediment movement is up-coast
115 if (bDownCoast)
116 // Swap them
117 return false;
118 else
119 // Keep the existing sequence
120 return true;
121 }
122
123 // Default return value, should never get here
124 return true;
125}
126
127//===============================================================================================================================
129//===============================================================================================================================
131{
132 for (int nCoast = 0; nCoast < static_cast<int>(m_VCoast.size()); nCoast++)
133 {
134 int nRet;
135
137 LogStream << m_ulIter << ": Calculating unconsolidated sediment transport" << endl;
138
139 // Update the values of pre-existing unconsolidated sediment, for all three size classes, to include unconsolidated sediment derived from platform erosion, cliff collapse, and sediment input events
141
143 {
146 }
147
148 // Now route actually-eroded sand/coarse sediment to adjacent polygons, or off-grid. Sort polygons first
149 // Each row (vector) of this vector-of-vectors is:
150 // 0: This-polygon global ID
151 // 1: This-polygon coast ID (in down-coast seq when sorted)
152 // 2: This-polygon down-coast (true) or up-coast (false) sediment movement
153 // 3 and subsequent: down-coast seqs of down-coast (if sediment movement is down-coast) or up-coast (if sediment movement is up-coast) adjacent polygons
154 vector<vector<int> > nVVPolyAndAdjacent;
155 vector<int> nVPolyAndAdj;
156 for (int nn = 0; nn < m_VCoast[nCoast].nGetNumPolygons(); nn++)
157 {
158 CGeomCoastPolygon const* pPolygon = m_VCoast[nCoast].pGetPolygon(nn);
159 nVPolyAndAdj.clear();
160
161 // The first [0] nVPolyAndAdj array item is the polygon's global ID
162 nVPolyAndAdj.push_back(pPolygon->nGetGlobalID());
163
164 // The second [1] nVPolyAndAdj array item is the polygon's down-coast ID
165 nVPolyAndAdj.push_back(pPolygon->nGetCoastID());
166
167 if (pPolygon->bDownCoastThisIter())
168 {
169 // Sediment is leaving this polygon in a down-coast direction: so set this as the third [2] nVPolyAndAdj array item
170 nVPolyAndAdj.push_back(true);
171
172 // Fourth [3] and subsequent nVPolyAndAdj array items are the down-coast seqs of adjacent down-coast polygons
173 for (int nAdj = 0; nAdj < pPolygon->nGetNumDownCoastAdjacentPolygons(); nAdj++)
174 {
175 // Save the coast ID of each down-coast adjacent polygon
176 int nAdjPolyID = pPolygon->nGetDownCoastAdjacentPolygon(nAdj);
177 nVPolyAndAdj.push_back(nAdjPolyID);
178 }
179 }
180 else
181 {
182 // Sediment is leaving this polygon in an up-coast direction: so set this as the third [2] nVPolyAndAdj array item
183 nVPolyAndAdj.push_back(false);
184
185 // Fourth [3] and susequent nVPolyAndAdj array items are the down-coast IDs of adjacent up-coast polygons
186 for (int nAdj = 0; nAdj < pPolygon->nGetNumUpCoastAdjacentPolygons(); nAdj++)
187 {
188 // Save the coast ID of each up-coast adjacent polygon
189 int nAdjPolyID = pPolygon->nGetUpCoastAdjacentPolygon(nAdj);
190 nVPolyAndAdj.push_back(nAdjPolyID);
191 }
192 }
193
194 // Save this 'row'
195 nVVPolyAndAdjacent.push_back(nVPolyAndAdj);
196 }
197
199 WritePolygonUnsortedSequence(nCoast, nVVPolyAndAdjacent);
200
201 // OK, now sort the array using bPolygonAndAdjCompare(), so that 'target' polygons are processed after 'source' polygons
202 sort(nVVPolyAndAdjacent.begin(), nVVPolyAndAdjacent.end(), bPolygonAndAdjCompare);
203
204 // And check for circularities i.e. where poly X -> poly Y -> poly X. Note that we only look for two-way circularities. i.e. we ignore poly A -> poly B -> Poly C -> poly A patterns. These are probably pretty rare, however
205 vector<int> VnSourcePolyDownCoastSeq;
206 for (int n = 0; n < static_cast<int>(nVVPolyAndAdjacent.size()); n++)
207 {
208 for (int m = 0; m < static_cast<int>(nVVPolyAndAdjacent[n].size()); m++)
209 {
210 if (m == 1)
211 VnSourcePolyDownCoastSeq.push_back(nVVPolyAndAdjacent[n][m]); // This-polygon down-coast seq
212
213 else if (m >= 3)
214 {
215 // Check for circularities
216 vector<int>::iterator it = find(VnSourcePolyDownCoastSeq.begin(), VnSourcePolyDownCoastSeq.end(), nVVPolyAndAdjacent[n][m]);
217 if (it != VnSourcePolyDownCoastSeq.end())
218 {
219 // Uh-oh: this polygon is in the list of previously-processed source polygons. So store the coast ID numbers of the polygons with circularity
220 CGeomCoastPolygon* pPoly = m_VCoast[nCoast].pGetPolygon(nVVPolyAndAdjacent[n][1]);
221 pPoly->AddCircularity(*it);
222
223 pPoly = m_VCoast[nCoast].pGetPolygon(*it);
224 pPoly->AddCircularity(nVVPolyAndAdjacent[n][m]);
225 }
226 }
227 }
228 }
229
231 WritePolygonSortedSequence(nCoast, nVVPolyAndAdjacent);
232
233 int nNumPolygons = m_VCoast[nCoast].nGetNumPolygons();
234
235 // Now process all polygons and do the actual (supply-limited) unconsolidated sediment movement
236 for (int n = 0; n < nNumPolygons; n++)
237 {
238 int nPolygon = nVVPolyAndAdjacent[n][1];
239 CGeomCoastPolygon* pPolygon = m_VCoast[nCoast].pGetPolygon(nPolygon);
240
241 // // DEBUG CODE =====================
242 // int nUpCoastProfile = pPolygon->nGetUpCoastProfile();
243 // CGeomProfile* pUpCoastProfile = m_VCoast[nCoast].pGetProfile(nUpCoastProfile);
244 // int nDownCoastProfile = pPolygon->nGetDownCoastProfile();
245 // CGeomProfile* pDownCoastProfile = m_VCoast[nCoast].pGetProfile(nDownCoastProfile);
246 // int nNumUpCoastCell = pUpCoastProfile->nGetNumCellsInProfile();
247 // int nNumDownCoastCell = pDownCoastProfile->nGetNumCellsInProfile();
248 // LogStream << "pUpCoastProfile->nGetNumCellsInProfile() = " << nNumUpCoastCell << " pDownCoastProfile->nGetNumCellsInProfile() = " << nNumDownCoastCell << endl;
249 // // DEBUG CODE =====================
250
251
252 // // DEBUG CODE ============================================================================================================================================
253 // // Get total depths of sand consolidated and unconsolidated for every cell
254 // if (m_ulIter == 5)
255 // {
256 // double dTmpSandUncons = 0;
257 // for (int nX1 = 0; nX1 < m_nXGridSize; nX1++)
258 // {
259 // for (int nY1 = 0; nY1 < m_nYGridSize; nY1++)
260 // {
261 // dTmpSandUncons += m_pRasterGrid->m_Cell[nX1][nY1].dGetTotUnconsSand();
262 // }
263 // }
264 //
265 // LogStream << endl;
266 // LogStream << "*****************************" << endl;
267 // LogStream << m_ulIter << ": before beach movement on nPoly = " << nPoly << " TOTAL UNCONSOLIDATED SAND ON ALL CELLS = " << dTmpSandUncons * m_dCellArea << endl;
268 // }
269 // // DEBUG CODE ============================================================================================================================================
270
271 // Do deposition first: does this polygon have coarse deposition?
272 double dCoarseDepositionTarget = pPolygon->dGetToDoBeachDepositionUnconsCoarse();
273
274 if (dCoarseDepositionTarget > 0)
275 {
276 // It does, first tho', if we have some coarse sediment which we were unable to deposit on the previously-processed polygon (which could be the last-processed polygon of the previous timestep), then add this in
278 {
279 // We had some coarse unconsolidated sediment which we were unable to deoosit on the last polygon (which could have been the last polygon of the previous iteration). So add it to the total to be deposited here
281 LogStream << m_ulIter << ": nPoly = " << nPolygon << " dCoarseDepositionTarget was = " << dCoarseDepositionTarget * m_dCellArea << " adding m_dDepositionCoarseDiff = " << m_dDepositionCoarseDiff * m_dCellArea;
282
283 dCoarseDepositionTarget += m_dDepositionCoarseDiff;
285
287 LogStream << " dCoarseDepositionTarget now = " << dCoarseDepositionTarget << endl;
288 }
289
290 // OK, do deposition of coarse sediment: calculate a net increase in depth of coarse-sized unconsolidated sediment on the cells within the polygon. Note that some cells may decrease in elevation (i.e. have some coarse-sized sediment erosion) however
291 double dCoarseDeposited = 0;
292 nRet = nDoUnconsDepositionOnPolygon(nCoast, pPolygon, TEXTURE_COARSE, dCoarseDepositionTarget, dCoarseDeposited);
293 if (nRet != RTN_OK)
294 return nRet;
295
296 double dCoarseNotDeposited = dCoarseDepositionTarget - dCoarseDeposited;
297 if (dCoarseNotDeposited > 0)
298 {
299 m_dDepositionCoarseDiff += dCoarseNotDeposited;
300 }
301 }
302
303 // Does this polygon have sand deposition?
304 double dSandDepositionTarget = pPolygon->dGetToDoBeachDepositionUnconsSand();
305
306 if (dSandDepositionTarget > 0)
307 {
308 // It does, first tho', if we have some sand sediment which we were unable to deposit on the previously-processed polygon (which could be the last-processed polygon of the previous timestep), then add this in
310 {
311 // We had some sand unconsolidated sediment which we were unable to deoosit on the last polygon (which could have been the last polygon of the previous iteration). So add it to the total to be deposited here
313 LogStream << m_ulIter << ": nPolygon = " << nPolygon << " dSandDepositionTarget was = " << dSandDepositionTarget * m_dCellArea << " adding m_dDepositionSandDiff = " << m_dDepositionSandDiff * m_dCellArea;
314
315 dSandDepositionTarget += m_dDepositionSandDiff;
317
319 LogStream << " dSandDepositionTarget now = " << dSandDepositionTarget << endl;
320 }
321
322 // Now do deposition of sand sediment: calculate a net increase in depth of sand-sized unconsolidated sediment on the cells within the polygon. Note that some cells may decrease in elevation (i.e. have some sand-sized sediment erosion) however
323 double dSandDeposited = 0;
324 nRet = nDoUnconsDepositionOnPolygon(nCoast, pPolygon, TEXTURE_SAND, dSandDepositionTarget, dSandDeposited);
325 if (nRet != RTN_OK)
326 return nRet;
327
328 double dSandNotDeposited = dSandDepositionTarget - dSandDeposited;
329 if (dSandNotDeposited > 0)
330 {
331 m_dDepositionSandDiff += dSandNotDeposited;
332 }
333
334 // // DEBUG CODE #####################
335 // if (m_ulIter == 5)
336 // {
337 // LogStream << m_ulIter << ": after sand deposition on nPoly = " << nPoly << " dSandDepositionTarget = " << dSandDepositionTarget * m_dCellArea << " dSandDeposited = " << dSandDeposited * m_dCellArea << " dSandNotDeposited = " << dSandNotDeposited * m_dCellArea << " m_dDepositionSandDiff = " << m_dDepositionSandDiff * m_dCellArea << endl;
338 //
339 // double dTmpSandUncons = 0;
340 // for (int nX1 = 0; nX1 < m_nXGridSize; nX1++)
341 // {
342 // for (int nY1 = 0; nY1 < m_nYGridSize; nY1++)
343 // {
344 // dTmpSandUncons += m_pRasterGrid->m_Cell[nX1][nY1].dGetTotUnconsSand();
345 // }
346 // }
347 //
348 // LogStream << m_ulIter << ": after sand deposition on nPoly = " << nPoly << " TOTAL UNCONSOLIDATED SAND ON ALL CELLS = " << dTmpSandUncons * m_dCellArea << endl;
349 // }
350 // // DEBUG CODE #####################
351 }
352
353 // Now do erosion
354 double dPotentialErosion = -pPolygon->dGetPotentialErosion();
355 if (dPotentialErosion > 0)
356 {
357 // There is some erosion on this polygon: process this in the sequence fine, sand, coarse. Is there any fine sediment on this polygon?
358 double dExistingUnconsFine = pPolygon->dGetPreExistingUnconsFine();
359
360 if (dExistingUnconsFine > 0)
361 {
362 // Yes there is, so crudely partition this potential value for this size class by erodibility, the result will almost always be much greater than actual (supply limited) erosion
363 double dFinePotentialErosion = dPotentialErosion * m_dFineErodibilityNormalized;
364
365 // Now reduce this further, by considering the total depth of fine sediment on the polygon
366 double dFineErosionTarget = tMin(dFinePotentialErosion, dExistingUnconsFine);
367
368 // OK, do the supply-limited erosion of fine sediment
369 double dFineEroded = 0;
370 nRet = nDoUnconsErosionOnPolygon(nCoast, pPolygon, TEXTURE_FINE, dFineErosionTarget, dFineEroded);
371 if (nRet != RTN_OK)
372 return nRet;
373
374 if (dFineEroded > 0)
375 {
376 // We eroded some fine sediment, so add to the this-iteration total. Note that total this gets added in to the suspended load elsewhere, so no need to do it here
377 m_dThisIterBeachErosionFine += dFineEroded;
378
379 // Also add to the suspended load
381
382 // Store the amount of unconsolidated fine beach sediment eroded for this polygon
383 pPolygon->SetBeachErosionUnconsFine(-dFineEroded);
384 }
385 }
386
387 // Is there any sand-sized sediment on this polygon?
388 double dExistingUnconsSand = pPolygon->dGetPreExistingUnconsSand();
389 double dSandEroded = 0;
390 if (dExistingUnconsSand > 0)
391 {
392 // There is: so crudely partition this potential value for this size class by erodibility, the result will almost always be much greater than actual (supply limited) erosion
393 double dSandPotentialErosion = dPotentialErosion * m_dSandErodibilityNormalized;
394
395 // Now reduce this further, by considering the total depth of sand sediment on the polygon
396 double dSandErosionTarget = tMin(dSandPotentialErosion, dExistingUnconsSand);
397
398 // OK, do the supply-limited erosion of sand sediment
399 nRet = nDoUnconsErosionOnPolygon(nCoast, pPolygon, TEXTURE_SAND, dSandErosionTarget, dSandEroded);
400 if (nRet != RTN_OK)
401 return nRet;
402
403 if (dSandEroded > 0)
404 {
405 // We eroded some sand sediment, so add to the this-iteration total
406 m_dThisIterBeachErosionSand += dSandEroded;
407
408 // Store the amount eroded for this polygon
409 pPolygon->SetBeachErosionUnconsSand(-dSandEroded);
410 }
411
412 // // DEBUG CODE #####################
413 // if (m_ulIter == 5)
414 // {
415 // LogStream << m_ulIter << ": nPoly = " << nPoly << " dSandErosionTarget = " << dSandErosionTarget * m_dCellArea << " m_dDepositionSandDiff = " << m_dDepositionSandDiff * m_dCellArea << " dSandEroded = " << dSandEroded * m_dCellArea << " m_dThisIterBeachErosionSand = " << m_dThisIterBeachErosionSand * m_dCellArea << endl;
416 //
417 // double dTmpSandUncons = 0;
418 // for (int nX1 = 0; nX1 < m_nXGridSize; nX1++)
419 // {
420 // for (int nY1 = 0; nY1 < m_nYGridSize; nY1++)
421 // {
422 // dTmpSandUncons += m_pRasterGrid->m_Cell[nX1][nY1].dGetTotUnconsSand();
423 // }
424 // }
425 //
426 // LogStream << m_ulIter << ": after sand erosion on nPoly = " << nPoly << " TOTAL UNCONSOLIDATED SAND ON ALL CELLS = " << dTmpSandUncons * m_dCellArea << endl;
427 // }
428 // // DEBUG CODE #####################
429 }
430
431 // Is there any coarse sediment on this polygon?
432 double dExistingUnconsCoarse = pPolygon->dGetPreExistingUnconsCoarse();
433 double dCoarseEroded = 0;
434 if (dExistingUnconsCoarse > 0)
435 {
436 // There is: so crudely partition this potential value for this size class by erodibility, the result will almost always be much greater than actual (supply limited) erosion
437 double dCoarsePotentialErosion = dPotentialErosion * m_dCoarseErodibilityNormalized;
438
439 // Now reduce this further, by considering the total depth of coarse sediment on the polygon
440 double dCoarseErosionTarget = tMin(dCoarsePotentialErosion, dExistingUnconsCoarse);
441
442 // OK, do the supply-limited erosion of coarse sediment
443 nRet = nDoUnconsErosionOnPolygon(nCoast, pPolygon, TEXTURE_COARSE, dCoarseErosionTarget, dCoarseEroded);
444 if (nRet != RTN_OK)
445 return nRet;
446
447 if (dCoarseEroded > 0)
448 {
449 // We eroded some coarse sediment, so add to the this-iteration toal
450 m_dThisIterBeachErosionCoarse += dCoarseEroded;
451
452 // Store the amount eroded for this polygon
453 pPolygon->SetBeachErosionUnconsCoarse(-dCoarseEroded);
454 }
455 }
456
457 // OK we now have the actual values of sediment eroded from this polygon, so next determine where this eroded sand and coarse sediment goes (have to consider fine sediment too, because this goes off-grid on grid-edge polygons). Only do this if some sand or coarse was eroded on this polygon
458 if ((dSandEroded + dCoarseEroded) > 0)
459 {
460 if (pPolygon->bDownCoastThisIter())
461 {
462 // Moving eroded sediment down-coast
463 int nNumAdjPoly = pPolygon->nGetNumDownCoastAdjacentPolygons();
464 for (int nn = 0; nn < nNumAdjPoly; nn++)
465 {
466 int nAdjPoly = pPolygon->nGetDownCoastAdjacentPolygon(nn);
467
468 // if (m_nLogFileDetail >= LOG_FILE_MIDDLE_DETAIL)
469 // LogStream << m_ulIter << ": polygon " << nPoly << " moves sediment down-coast to polygon " << nAdjPoly << endl;
470
471 if (nAdjPoly == INT_NODATA)
472 {
473 // Sediment is leaving the grid
474 if (pPolygon->bIsCoastStartPolygon())
475 {
476 // Error: uncons sediment movement is down-coast and off-edge, but this polygon is at the up-coast end of the coastline
478 LogStream << m_ulIter << ": " << ERR << "in sediment export. Unconsolidated sediment movement is DOWN-COAST, and sediment is leaving the grid, but polygon " << nPolygon << " is at the up-coast end of the coastline. This will result in mass balance problems." << endl;
479 }
480 else if (pPolygon->bIsCoastEndPolygon())
481 {
482 // This is the polygon at the down-coast end of the coastline, and uncons sediment movement is down-coast. Decide what to do based on the user setting m_nUnconsSedimentHandlingAtGridEdges
484 {
485 // Closed grid edges: no uncons sediment moves off-grid, nothing is removed from this polygon, so cannot adjust sediment export
487 LogStream << m_ulIter << ": when adjusting sediment export, polygon " << nPolygon << " is at the down-coast end of the coastline, and actual sediment movement is DOWN-COAST. Since grid edges are closed, no sand or coarse unconsolidated sediment goes off-grid so cannot adjust sediment export. This will result in mass balance problems." << endl;
488 }
489
491 {
492 // Open grid edges, so this sediment goes off-grid
493 m_dThisIterLeftGridUnconsSand += dSandEroded;
494 m_dThisIterLeftGridUnconsCoarse += dCoarseEroded;
495
496 // // DEBUG CODE ##################
497 // if (m_ulIter == 5)
498 // {
499 // LogStream << m_ulIter << ": nPoly = " << nPoly << " LOST FROM GRID = " << dSandEroded * m_dCellArea << endl;
500 // }
501 // // DEBUG CODE ##################
502 }
503
505 {
506 // Re-circulating grid edges, so adjust the sediment exported to the polygon at the up-coast end of this coastline
507 int nOtherEndPoly = 0;
508 CGeomCoastPolygon* pOtherEndPoly = m_VCoast[nCoast].pGetPolygon(nOtherEndPoly);
509
510 if (dSandEroded > 0)
511 {
512 // Add to the still-to-do total of unconsolidated sand to be deposited on the polygon at the up-coast end of this coastline
513 pOtherEndPoly->AddToDoBeachDepositionUnconsSand(dSandEroded);
514 }
515
516 if (dCoarseEroded > 0)
517 {
518 // Add to the still-to-do total of unconsolidated coarse sediment to be deposited on the polygon at the up-coast end of this coastline
519 pOtherEndPoly->AddToDoBeachDepositionUnconsCoarse(dCoarseEroded);
520 }
521 }
522 }
523 }
524 else
525 {
526 // This polygon is not at the grid edge
527 CGeomCoastPolygon* pAdjPolygon = m_VCoast[nCoast].pGetPolygon(nAdjPoly);
528 double dBoundaryShare = pPolygon->dGetDownCoastAdjacentPolygonBoundaryShare(nn);
529
530 if (dSandEroded > 0)
531 {
532 // if (m_ulIter == 5)
533 // LogStream << m_ulIter << ": B polygon not at grid edge nPoly = " << nPoly << " nAdjPoly = " << nAdjPoly << ", dGetToDoBeachDepositionUnconsSand() on nAdjPoly is = " << pAdjPolygon->dGetToDoBeachDepositionUnconsSand() * m_dCellArea << endl;
534
535 // Add to the still-to-do total of unconsolidated sand to be deposited on the adjacent polygon
536 pAdjPolygon->AddToDoBeachDepositionUnconsSand(dSandEroded * dBoundaryShare);
537
538 // if (m_ulIter == 5)
539 // LogStream << m_ulIter << ": B after nAdjPoly = " << nAdjPoly << " AddToDoBeachDepositionUnconsSand(" << dSandEroded * dBoundaryShare * m_dCellArea << ") dGetToDoBeachDepositionUnconsSand() now = " << pAdjPolygon->dGetToDoBeachDepositionUnconsSand() * m_dCellArea << endl;
540 }
541
542 if (dCoarseEroded > 0)
543 {
544 // if (m_nLogFileDetail >= LOG_FILE_ALL)
545 // LogStream << m_ulIter << ": polygon = " << nPoly << " adjacent polygon = " << nAdjPoly << ", beach deposition 1 of uncons coarse was = " << pAdjPolygon->dGetToDoBeachDepositionUnconsCoarse() * m_dCellArea;
546
547 // Add to the still-to-do total of unconsolidated coarse sediment to be deposited on the adjacent polygon
548 pAdjPolygon->AddToDoBeachDepositionUnconsCoarse(dCoarseEroded * dBoundaryShare);
549
550 // if (m_nLogFileDetail >= LOG_FILE_ALL)
551 // LogStream << " after AddToDoBeachDepositionUnconsCoarse(" << dCoarseEroded * dBoundaryShare << ") beach deposition 1 of uncons coarse now = " << pAdjPolygon->dGetToDoBeachDepositionUnconsCoarse() * m_dCellArea << endl;
552 }
553 }
554 }
555
556 // if (m_nLogFileDetail >= LOG_FILE_ALL)
557 // LogStream << m_ulIter << ": 1 uncons sand eroded = " << dSandEroded * m_dCellArea << " 1 uncons coarse eroded = " << dCoarseEroded * m_dCellArea << endl;
558 }
559 else
560 {
561 // Moving eroded sediment up-coast
562 int nNumAdjPoly = pPolygon->nGetNumUpCoastAdjacentPolygons();
563 for (int nn = 0; nn < nNumAdjPoly; nn++)
564 {
565 int nAdjPoly = pPolygon->nGetUpCoastAdjacentPolygon(nn);
566 // if (m_nLogFileDetail >= LOG_FILE_ALL)
567 // LogStream << m_ulIter << ": polygon " << nPoly << " moves sediment up-coast to polygon " << nAdjPoly << endl;
568
569 if (nAdjPoly == INT_NODATA)
570 {
571 // Sediment is leaving the grid
572 if (pPolygon->bIsCoastEndPolygon())
573 {
574 // Error: uncons sediment movement is down-coast and off-edge, but this polygon is at the up-coast end of the coastline
576 LogStream << m_ulIter << ": " << ERR << "in sediment export. Unconsolidated sediment movement is UP-COAST, and sediment is leaving the grid, but polygon " << nPolygon << " is at the down-coast end of the coastline. This will result in mass balance problems." << endl;
577
578 }
579 else if (pPolygon->bIsCoastStartPolygon())
580 {
581 // This is the polygon at the up-coast end of the coastline, and uncons sediment movement is up-coast. Decide what to do based on the user setting m_nUnconsSedimentHandlingAtGridEdges
583 {
584 // Closed grid edges: no uncons sediment moves off-grid, nothing is removed from this polygon, so cannot adjust sediment export
586 LogStream << m_ulIter << ": when adjusting sediment export, polygon " << nPolygon << " is at the up-coast end of the coastline, and actual sediment movement is UP-COAST. Since grid edges are closed, no sand or coarse unconsolidated sediment goes off-grid so cannot adjust sediment export" << endl;
587 }
588
590 {
591 // Open grid edges, so this sediment goes off-grid
592 m_dThisIterLeftGridUnconsSand += dSandEroded;
593 m_dThisIterLeftGridUnconsCoarse += dCoarseEroded;
594 }
595
597 {
598 // Re-circulating grid edges, so adjust the sediment exported to the polygon at the up-coast end of this coastline TODO 016 Check whether this causes mass balance problems, depending on the sequence of polygon processing
599 int nOtherEndPoly = 0;
600 CGeomCoastPolygon* pOtherEndPoly = m_VCoast[nCoast].pGetPolygon(nOtherEndPoly);
601
602 if (dSandEroded > 0)
603 {
604 // Add to the still-to-do total of unconsolidated sand to be deposited on the polygon at the up-coast end of this coastline
605 pOtherEndPoly->AddToDoBeachDepositionUnconsSand(dSandEroded);
606 }
607
608 if (dCoarseEroded > 0)
609 {
610 // Add to the still-to-do total of unconsolidated coarse sediment to be deposited on the polygon at the up-coast end of this coastline
611 pOtherEndPoly->AddToDoBeachDepositionUnconsCoarse(dCoarseEroded);
612 }
613 }
614 }
615 }
616 else
617 {
618 // This polygon is not at the grid edge
619 CGeomCoastPolygon* pAdjPolygon = m_VCoast[nCoast].pGetPolygon(nAdjPoly);
620 double dBoundaryShare = pPolygon->dGetUpCoastAdjacentPolygonBoundaryShare(nn);
621
622 if (dSandEroded > 0)
623 {
624 // if (m_ulIter == 5)
625 // LogStream << m_ulIter << ": A polygon not at grid edge nPoly = " << nPoly << " nAdjPoly = " << nAdjPoly << ", dGetToDoBeachDepositionUnconsSand() on nAdjPoly is = " << pAdjPolygon->dGetToDoBeachDepositionUnconsSand() * m_dCellArea << endl;
626
627 // Add to the still-to-do total of unconsolidated sand to be deposited on the the adjacent polygon
628 pAdjPolygon->AddToDoBeachDepositionUnconsSand(dSandEroded * dBoundaryShare);
629
630 // if (m_ulIter == 5)
631 // LogStream << m_ulIter << ": A after nAdjPoly = " << nAdjPoly << " AddToDoBeachDepositionUnconsSand(" << dSandEroded * dBoundaryShare * m_dCellArea << ") dGetToDoBeachDepositionUnconsSand() now = " << pAdjPolygon->dGetToDoBeachDepositionUnconsSand() * m_dCellArea << endl;
632 }
633
634 if (dCoarseEroded > 0)
635 {
636 // if (m_ulIter == 5)
637 // LogStream << m_ulIter << ": polygon not at grid edge nPoly = " << nPoly << " nAdjPoly = " << nAdjPoly << ", beach deposition of uncons coarse was = " << pAdjPolygon->dGetToDoBeachDepositionUnconsCoarse() * m_dCellArea << endl;
638
639 // Add to the still-to-do total of unconsolidated coarse sediment to be deposited on the adjacent polygon
640 pAdjPolygon->AddToDoBeachDepositionUnconsCoarse(+dCoarseEroded * dBoundaryShare);
641
642 // if (m_ulIter == 5)
643 // LogStream << " After AddToDoBeachDepositionUnconsCoarse(" << dCoarseEroded * dBoundaryShare << ") uncons coarse now = " << pAdjPolygon->dGetToDoBeachDepositionUnconsCoarse() * m_dCellArea << endl;
644 }
645 }
646 }
647 }
648 }
649
650 // if (m_nLogFileDetail >= LOG_FILE_ALL)
651 // LogStream << m_ulIter << ": sand eroded on poly = " << dSandEroded * m_dCellArea << " coarse eroded on poly = " << dCoarseEroded * m_dCellArea << endl;
652
653 } // if (dPotentialErosion > 0)
654
655 // // DEBUG CODE ============================================================================================================================================
656 // // Get total depths of unconsolidated sand for every cell
657 // if (m_ulIter == 5)
658 // {
659 // double dTmpSandUncons = 0;
660 // for (int nX1 = 0; nX1 < m_nXGridSize; nX1++)
661 // {
662 // for (int nY1 = 0; nY1 < m_nYGridSize; nY1++)
663 // {
664 // dTmpSandUncons += m_pRasterGrid->m_Cell[nX1][nY1].dGetTotUnconsSand();
665 // }
666 // }
667 //
668 // LogStream << endl;
669 // LogStream << m_ulIter << ": TOTAL UNCONSOLIDATED SAND ON ALL CELLS after beach movement on nPoly = " << nPoly << " dTmpSandUncons = " << dTmpSandUncons * m_dCellArea << " (dTmpSandUncons - m_dStartIterUnconsSandAllCells) = " << (dTmpSandUncons - m_dStartIterUnconsSandAllCells) * m_dCellArea << endl;
670 //
671 // // Now get the total in all still-to-do fields of all polygons
672 // double dToDoTot = 0;
673 //
674 // for (int nn = 0; nn < nPolygons; nn++)
675 // {
676 // CGeomCoastPolygon* pThisPolygon = m_VCoast[nCoast].pGetPolygon(nn);
677 // dToDoTot += pThisPolygon->dGetToDoBeachDepositionUnconsSand();
678 // }
679 //
680 // LogStream << endl << m_ulIter << ": dToDoTot = " << dToDoTot * m_dCellArea << endl;
681 // LogStream << m_ulIter << ": dTmpSandUncons + dToDoTot = " << (dTmpSandUncons + dToDoTot) * m_dCellArea << endl << endl;
682 //
683 // LogStream << m_ulIter << ": m_dThisIterLeftGridUnconsSand = " << m_dThisIterLeftGridUnconsSand * m_dCellArea << endl;
684 //
685 // LogStream << "*****************************" << endl;
686 // }
687 // // DEBUG CODE ============================================================================================================================================
688
689 } // for (int n = 0; n < nNumPolygons; n++)
690
691 // OK we have processed all polygons, But if there are adjacent-polygon circularities (i.e. Polygon A -> Polygon B -> Polygon A) then we may have some still-to-do deposition on at least one polygon. So look through all polygons and check their still-to-do lists
692 int nPolygons = m_VCoast[nCoast].nGetNumPolygons();
693// for (int nn = 0; nn < nPolygons; nn++)
694 for (int nn = nPolygons-1; nn >= 0; nn--)
695 {
696 int nThisPoly = nVVPolyAndAdjacent[nn][1];
697 CGeomCoastPolygon* pThisPolygon = m_VCoast[nCoast].pGetPolygon(nThisPoly);
698
699 double dSandToDepositOnPoly = pThisPolygon->dGetToDoBeachDepositionUnconsSand();
700 if (dSandToDepositOnPoly > 0)
701 {
702 // There is some still-to-do deposition of sand sediment on this polygon: calculate a net increase in depth of sand-sized unconsolidated sediment on the cells within the polygon. Note that some cells may decrease in elevation (i.e. have some sand-sized sediment erosion) however
703 double dSandDeposited = 0;
704 nRet = nDoUnconsDepositionOnPolygon(nCoast, pThisPolygon, TEXTURE_SAND, dSandToDepositOnPoly, dSandDeposited);
705 if (nRet != RTN_OK)
706 return nRet;
707
708 double dSandNotDeposited = dSandToDepositOnPoly - dSandDeposited;
709 if (dSandNotDeposited > 0)
710 m_dDepositionSandDiff += dSandNotDeposited;
711
713 LogStream << m_ulIter << ": re-processing nThisPoly = " << nThisPoly << " dSandDeposited = " << dSandDeposited * m_dCellArea << " dSandNotDeposited = " << dSandNotDeposited * m_dCellArea << " m_dDepositionSandDiff = " << m_dDepositionSandDiff * m_dCellArea << endl;
714 }
715
716 double dCoarseToDepositOnPoly = pThisPolygon->dGetToDoBeachDepositionUnconsCoarse();
717 if (dCoarseToDepositOnPoly > 0)
718 {
719 // There is some still-to-do deposition of coarse sediment on this polygon: calculate a net increase in depth of coarse-sized unconsolidated sediment on the cells within the polygon. Note that some cells may decrease in elevation (i.e. have some coarse-sized sediment erosion) however
720 double dCoarseDeposited = 0;
721 nRet = nDoUnconsDepositionOnPolygon(nCoast, pThisPolygon, TEXTURE_COARSE, dCoarseToDepositOnPoly, dCoarseDeposited);
722 if (nRet != RTN_OK)
723 return nRet;
724
725 double dCoarseNotDeposited = dCoarseToDepositOnPoly - dCoarseDeposited;
726 if (dCoarseNotDeposited > 0)
727 m_dDepositionCoarseDiff += dCoarseNotDeposited;
728
730 LogStream << m_ulIter << ": re-processing nThisPoly = " << nThisPoly << " dCoarseDeposited = " << dCoarseDeposited * m_dCellArea << " dCoarseNotDeposited = " << dCoarseNotDeposited * m_dCellArea << " m_dDepositionCoarseDiff = " << m_dDepositionCoarseDiff * m_dCellArea << endl;
731 }
732 }
733
735 WritePolygonActualMovement(nCoast, nVVPolyAndAdjacent);
736 }
737
738 return RTN_OK;
739}
740
741//===============================================================================================================================
743//===============================================================================================================================
745{
746 int nNumPolygons = m_VCoast[nCoast].nGetNumPolygons();
747
748 for (int nPoly = 0; nPoly < nNumPolygons; nPoly++)
749 {
750 CGeomCoastPolygon* pPolygon = m_VCoast[nCoast].pGetPolygon(nPoly);
751
752 // Only include unconsolidated fine sediment from sediment input events, don't include any unconsolidated fine sediment from platform erosion and cliff collapse since these have gone to suspension
753 double dFine = pPolygon->dGetSedimentInputUnconsFine();
754 pPolygon->SetPreExistingUnconsFine(dFine);
755
756 // Include unconsolidated sand sediment derived from platform erosion, cliff collapse, and sediment input events
758 pPolygon->SetPreExistingUnconsSand(dSand);
759
760 // Include unconsolidated coarse sediment derived from platform erosion, cliff collapse, and sediment input events
762 pPolygon->SetPreExistingUnconsCoarse(dCoarse);
763 }
764}
Geometry class used for coast polygon objects.
bool bIsCoastStartPolygon(void) const
Is this polygon the coast-start polygon?
double dGetSedimentInputUnconsSand(void) const
Get the value of sand sediment on the polygon derived from sediment input events(s)
double dGetPotentialErosion(void) const
Returns this timestep's total change in depth of unconsolidated sediment (all size classes) due to be...
double dGetCliffCollapseUnconsSandDeposition(void) const
Get the this-iteration total of unconsolidated sand sediment deposited from cliff collapse on this po...
bool bIsCoastEndPolygon(void) const
Is this polygon the coast-end polygon?
void SetPreExistingUnconsFine(double const)
Set the value of pre-existing unconsolidated fine sediment stored on this polygon.
double dGetPreExistingUnconsSand(void) const
Get the value of pre-existing unconsolidated sand sediment stored on this polygon.
void AddToDoBeachDepositionUnconsSand(double const)
Adds a depth (in m) of sand-sized unconsolidated sediment to this timestep's still-to-do deposition o...
void SetPreExistingUnconsSand(double const)
Set the value of pre-existing unconsolidated sand sediment stored on this polygon.
double dGetUpCoastAdjacentPolygonBoundaryShare(int const) const
Gets the boundary shares for all up-coast adjacent polygons.
int nGetUpCoastAdjacentPolygon(int const) const
Gets a single up-coast adjacent polygon.
double dGetPlatformErosionUnconsCoarse(void) const
Get the this-iteration total of unconsolidated coarse sediment derived from shore platform erosion on...
double dGetSedimentInputUnconsFine(void) const
Get the value of fine sediment on the polygon derived from sediment input events(s)
int nGetNumUpCoastAdjacentPolygons(void) const
Gets all up-coast adjacent polygons.
int nGetGlobalID(void) const
Get the global ID.
double dGetCliffCollapseUnconsCoarseDeposition(void) const
Get the this-iteration total of unconsolidated coarse sediment deposited from cliff collapse on this ...
double dGetDownCoastAdjacentPolygonBoundaryShare(int const) const
Gets the boundary shares for all down-coast adjacent polygons.
void SetBeachErosionUnconsFine(double const)
Sets a value (must be < 0) for this timestep's erosion of fine unconsolidated sediment (beach redistr...
double dGetPreExistingUnconsFine(void) const
Get the value of pre-existing unconsolidated fine sediment stored on this polygon.
void AddToDoBeachDepositionUnconsCoarse(double const)
Adds a depth (in m) of coarse unconsolidated sediment to this timestep's still-to-do deposition of un...
int nGetDownCoastAdjacentPolygon(int const) const
Gets a single down-coast adjacent polygon.
int nGetNumDownCoastAdjacentPolygons(void) const
Gets all down-coast adjacent polygons.
double dGetToDoBeachDepositionUnconsSand(void) const
Returns this timestep's still-to-do deposition of sand-sized unconsolidated sediment (from beach redi...
void SetPreExistingUnconsCoarse(double const)
Set the value of pre-existing unconsolidated coarse sediment stored on this polygon.
double dGetPlatformErosionUnconsSand(void) const
Get the this-iteration total of unconsolidated sand sediment derived from shore platform erosion on t...
double dGetPreExistingUnconsCoarse(void) const
Get the value of pre-existing unconsolidated coarse sediment stored on this polygon.
void SetBeachErosionUnconsSand(double const)
Sets a value (must be < 0) for this timestep's erosion of sand-sized unconsolidated sediment (beach r...
double dGetSedimentInputUnconsCoarse(void) const
Get the value of coarse sediment on the polygon derived from sediment input events(s)
bool bDownCoastThisIter(void) const
Is sediment movement on this polygon downcoast this iteration?
int nGetCoastID(void) const
Get the coast ID, this is the same as the down-coast sequence of polygons.
void AddCircularity(int const)
Add a circularity to this polygon.
void SetBeachErosionUnconsCoarse(double const)
Sets a value (must be < 0) for this timestep's erosion of coarse unconsolidated sediment (beach redis...
double dGetToDoBeachDepositionUnconsCoarse(void) const
Returns this timestep's still-to-do deposition of coarse unconsolidated sediment (from beach redistri...
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:531
ofstream LogStream
double m_dThisIterBeachErosionCoarse
Total actual beach erosion (coarse unconsolidated sediment) for this iteration (depth in m)
Definition simulation.h:809
vector< CRWCoast > m_VCoast
The coastline objects.
double m_dFineErodibilityNormalized
Relative erodibility of fine unconsolidated beach sediment, normalized.
Definition simulation.h:752
void WritePolygonSedimentBeforeMovement(int const)
Writes to the log file a table showing per-polygon totals of stored unconsolidated beach sediment pri...
void WritePolygonSortedSequence(int const, vector< vector< int > > &)
Writes to the log file a table showing the sorted sequence of polygon processing, and any circulariti...
int m_nUnconsSedimentHandlingAtGridEdges
How sediment which moves off an edge of the grid is handled. Possible values are GRID_EDGE_CLOSED,...
Definition simulation.h:486
double m_dCoarseErodibilityNormalized
Relative erodibility of coarse unconsolidated beach sediment, normalized.
Definition simulation.h:758
double m_dDepositionCoarseDiff
Error term: if we are unable to deposit enough unconslidated coarse on polygon(s),...
Definition simulation.h:845
int nDoAllActualBeachErosionAndDeposition(void)
Does between-polygon and within-polygon actual (supply-limited) redistribution of transported beach s...
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:842
void WritePolygonPotentialErosion(int const)
Writes to the log file a table showing per-polygon potential erosion of all size classes of unconsoli...
void WritePolygonActualMovement(int const, vector< vector< int > > const &)
Writes to the log file a table showing per-polygon actual movement of unconsolidated beach sediment.
int nDoUnconsDepositionOnPolygon(int const, CGeomCoastPolygon *, int const, double, double &)
Deposits unconsolidated beach sediment (sand or coarse) on the cells within a polygon....
double m_dSandErodibilityNormalized
Relative erodibility of sand unconsolidated beach sediment, normalized.
Definition simulation.h:755
double m_dThisIterBeachErosionSand
Total actual beach erosion (sand unconsolidated sediment) for this iteration (depth in m)
Definition simulation.h:806
double m_dThisIterFineSedimentToSuspension
Total fine unconsolidated sediment in suspension for this iteration (depth in m)
Definition simulation.h:818
double m_dThisIterBeachErosionFine
Total actual beach erosion (fine unconsolidated sediment) for this iteration (depth in m)
Definition simulation.h:803
void AllPolygonsUpdateStoredUncons(int const)
Before simulating beach erosion, update the per-polygon values of pre-existing unconsolidated sedimen...
int nDoUnconsErosionOnPolygon(int const, CGeomCoastPolygon *, int const, double const, double &)
Erodes unconsolidated beach sediment of one texture class on the cells within a polygon....
double m_dCellArea
Area of a cell (in external CRS units)
Definition simulation.h:617
double m_dThisIterLeftGridUnconsCoarse
Total coarse unconsolidated sediment lost from the grid this iteration (depth in m)
Definition simulation.h:830
unsigned long m_ulIter
The number of the current iteration (time step)
Definition simulation.h:554
void WritePolygonUnsortedSequence(int const, vector< vector< int > > &)
Writes to the log file a table showing the unsorted sequence of polygon processing.
double m_dThisIterLeftGridUnconsSand
Total sand unconsolidated sediment lost from the grid this iteration (depth in m)
Definition simulation.h:827
STL iterator class.
This file contains global definitions for CoastalME.
int const INT_NODATA
Definition cme.h:365
T tMin(T a, T b)
Definition cme.h:1138
string const ERR
Definition cme.h:777
int const TEXTURE_COARSE
Definition cme.h:406
int const LOG_FILE_MIDDLE_DETAIL
Definition cme.h:380
int const GRID_EDGE_CLOSED
Definition cme.h:663
int const GRID_EDGE_RECIRCULATE
Definition cme.h:665
double const MASS_BALANCE_TOLERANCE
Definition cme.h:701
int const LOG_FILE_HIGH_DETAIL
Definition cme.h:381
int const TEXTURE_FINE
Definition cme.h:404
int const RTN_OK
Definition cme.h:580
int const GRID_EDGE_OPEN
Definition cme.h:664
int const TEXTURE_SAND
Definition cme.h:405
Contains CRWCoast definitions.
bool bPolygonAndAdjCompare(const vector< int > &nVLeft, const vector< int > &nVRight)
Function used to sort polygons before doing the polygon-to-polygon source-target pattern....
Contains CSimulation definitions.