CoastalME (Coastal Modelling Environment)
Simulates the long-term behaviour of complex coastlines
Loading...
Searching...
No Matches
do_cliff_collapse.cpp
Go to the documentation of this file.
1
12
13/* ==============================================================================================================================
14
15 This file is part of CoastalME, the Coastal Modelling Environment.
16
17 CoastalME is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22
23==============================================================================================================================*/
24#include <assert.h>
25
26#include <cmath>
27
28#include <iostream>
29using std::cerr;
30// using std::cout;
31using std::endl;
32using std::ios;
33
34#include "cme.h"
35#include "simulation.h"
36#include "cliff.h"
37#include "coast_landform.h"
38#include "2d_point.h"
39
40//===============================================================================================================================
42//===============================================================================================================================
44{
46 LogStream << m_ulIter << ": Calculating cliff collapse" << endl;
47
48 int nRet;
49
50 // First go along each coastline and update the total wave energy which it has experienced
51 for (int i = 0; i < static_cast<int>(m_VCoast.size()); i++)
52 {
53 for (int j = 0; j < m_VCoast[i].nGetCoastlineSize(); j++)
54 {
55 CACoastLandform* pCoastLandform = m_VCoast[i].pGetCoastLandform(j);
56
57 // First get wave energy for the coastal landform object
58 double const dWaveHeightAtCoast = m_VCoast[i].dGetCoastWaveHeight(j);
59
60 // If the waves at this point are off-shore, then do nothing, just move to next coast point
61 if (bFPIsEqual(dWaveHeightAtCoast, DBL_NODATA, TOLERANCE))
62 continue;
63
64 // OK we have on-shore waves so get the previously-calculated wave energy
65 double const dWaveEnergy = m_VCoast[i].dGetWaveEnergyAtBreaking(j);
66 // assert(isfinite(dWaveEnergy));
67
68 // And save the accumulated value
69 pCoastLandform->IncTotAccumWaveEnergy(dWaveEnergy);
70
71 // Now, check the notch elevation
72 int const nX = m_VCoast[i].pPtiGetCellMarkedAsCoastline(j)->nGetX();
73 int const nY = m_VCoast[i].pPtiGetCellMarkedAsCoastline(j)->nGetY();
74 int const nCat = pCoastLandform->nGetLandFormCategory();
75 double const dTopElev = m_pRasterGrid->m_Cell[nX][nY].dGetSedimentTopElev();
76
77 if ((nCat == LF_CAT_CLIFF) || (nCat == LF_SUBCAT_CLIFF_ON_COASTLINE) || (nCat == LF_SUBCAT_CLIFF_INLAND))
78 {
79 CRWCliff* pCliff = reinterpret_cast<CRWCliff*>(pCoastLandform);
80 double const dNotchElev = pCliff->dGetNotchBaseElev();
81
82 // Is the notch elevation above the top surface of the sediment?
83 if (dNotchElev > dTopElev)
84 {
85 // It is, so reduce the notch elevation, to be the same as the sediment top surface
86 LogStream << m_ulIter << ": cliff notch elevation reduced at [" << nX << "][" << nY << "], sediment top elevation = " << dTopElev << ", dNotchElev was " << dNotchElev << ", dNotchElev is now " << dTopElev - m_dNotchBaseBelowSWL << endl;
87
88 pCliff->SetNotchBaseElev(dTopElev - m_dNotchBaseBelowSWL);
89 }
90 }
91
92 // // DEBUG CODE ==============
93 // if ((j > 20) && (j <= 30))
94 // {
95 // string strCat;
96 // if (nCat == LF_CAT_HINTERLAND)
97 // strCat = "hinterland";
98 // else if (nCat == LF_CAT_SEA)
99 // strCat = "sea";
100 // else if (nCat == LF_CAT_CLIFF)
101 // strCat = "cliff";
102 // else if (nCat == LF_CAT_DRIFT)
103 // strCat = "drift";
104 // else if (nCat == LF_CAT_INTERVENTION)
105 // strCat = "intervention";
106 // else if (nCat == LF_SUBCAT_CLIFF_ON_COASTLINE)
107 // strCat = "cliff on coastline";
108 // else if (nCat == LF_SUBCAT_CLIFF_INLAND)
109 // strCat = "cliff inland";
110 // else if (nCat == LF_SUBCAT_DRIFT_MIXED)
111 // strCat = "drift mixed";
112 // else if (nCat == LF_SUBCAT_DRIFT_TALUS)
113 // strCat = "drift talus";
114 // else if (nCat == LF_SUBCAT_DRIFT_BEACH)
115 // strCat = "drift beach";
116 // else
117 // strCat = "unknown";
118 //
119 // // LogStream << m_ulIter << ": [" << nX << "][" << nY << "] '" << strCat << "' dWaveEnergy = " << dWaveEnergy << " dGetTotAccumWaveEnergy() = " << pCoastLandform->dGetTotAccumWaveEnergy() << endl;
120 //
121 // LogStream << m_ulIter << ": [" << nX << "][" << nY << "] '" << strCat << "' dNotchElev = " << dNotchElev << " dTopElev = " << dTopElev << " m_dInitialMeanSWL = " << m_dInitialMeanSWL << " m_dThisIterMeanSWL = " << m_dThisIterMeanSWL << " m_dThisIterSWL = " << m_dThisIterSWL << endl;
122 // }
123 // // DEBUG CODE =============
124
125 // Now simulate how the coastal landform responds to this wave energy
126 int const nCategory = pCoastLandform->nGetLandFormCategory();
127
128 if (nCategory == LF_CAT_CLIFF)
129 {
130 // This is a cliff
131 CRWCliff* pCliff = reinterpret_cast<CRWCliff*>(pCoastLandform);
132
133 // Calculate this-timestep cliff notch erosion (is a length in external CRS units). Only consolidated sediment can have a cliff notch
134 double const dNotchExtension = dWaveEnergy / m_dCliffErosionResistance;
135
136 // Deepen the cliff object's erosional notch as a result of wave energy during this timestep. Note that notch deepening may be constrained, since this-timestep notch extension cannot exceed the length (i.e. cellside minus notch depth) of sediment remaining on the cell
137 pCliff->DeepenErosionalNotch(dNotchExtension);
138
139 // OK, is the notch now extended enough to cause collapse (either because the overhang is greater than the threshold overhang, or because there is no sediment remaining)?
141 {
142 // // DEBUG CODE ============================================================================================================================================
143 // // Get total depths of sand consolidated and unconsolidated for every cell
144 // if (m_ulIter == 5)
145 // {
146 // double dTmpSandCons = 0;
147 // double dTmpSandUncons = 0;
148 // for (int nX1 = 0; nX1 < m_nXGridSize; nX1++)
149 // {
150 // for (int nY1 = 0; nY1 < m_nYGridSize; nY1++)
151 // {
152 // dTmpSandCons += m_pRasterGrid->m_Cell[nX1][nY1].dGetTotConsSandThickConsiderNotch();
153 //
154 // dTmpSandUncons += m_pRasterGrid->m_Cell[nX1][nY1].dGetTotUnconsSand();
155 // }
156 // }
157 //
158 // // Get the cliff cell's grid coords
159 // int nXCliff = pCliff->pPtiGetCellMarkedAsLF()->nGetX();
160 // int nYCliff = pCliff->pPtiGetCellMarkedAsLF()->nGetY();
161 //
162 // // Get this cell's polygon
163 // int nPoly = m_pRasterGrid->m_Cell[nXCliff][nYCliff].nGetPolygonID();
164 //
165 // LogStream << endl;
166 // LogStream << "*****************************" << endl;
167 // LogStream << m_ulIter << ": before cliff collapse on nPoly = " << nPoly << " total consolidated sand = " << dTmpSandCons * m_dCellArea << " total unconsolidated sand = " << dTmpSandUncons * m_dCellArea << endl;
168 // }
169 // // DEBUG CODE ============================================================================================================================================
170
171 // It is ready to collapse
172 double dCliffElevPreCollapse = 0;
173 double dCliffElevPostCollapse = 0;
174 double dFineCollapse = 0;
175 double dSandCollapse = 0;
176 double dCoarseCollapse = 0;
177
178 // So do the cliff collapse
179 nRet = nDoCliffCollapse(i, pCliff, dFineCollapse, dSandCollapse, dCoarseCollapse, dCliffElevPreCollapse, dCliffElevPostCollapse);
180
181 if (nRet != RTN_OK)
182 {
184 LogStream << m_ulIter << ": " << WARN << "problem with cliff collapse, continuing however" << endl;
185 }
186
187 // Deposit all sand and/or coarse sediment derived from this cliff collapse as unconsolidated sediment (talus)
188 nRet = nDoCliffCollapseDeposition(i, pCliff, dSandCollapse, dCoarseCollapse, dCliffElevPreCollapse, dCliffElevPostCollapse);
189
190 if (nRet != RTN_OK)
191 return nRet;
192
193 // // DEBUG CODE ============================================================================================================================================
194 // // Get total depths of sand consolidated and unconsolidated for every cell
195 // if (m_ulIter == 5)
196 // {
197 // double dTmpSandCons = 0;
198 // double dTmpSandUncons = 0;
199 // for (int nX1 = 0; nX1 < m_nXGridSize; nX1++)
200 // {
201 // for (int nY1 = 0; nY1 < m_nYGridSize; nY1++)
202 // {
203 // dTmpSandCons += m_pRasterGrid->m_Cell[nX1][nY1].dGetTotConsSandThickConsiderNotch();
204 //
205 // dTmpSandUncons += m_pRasterGrid->m_Cell[nX1][nY1].dGetTotUnconsSand();
206 // }
207 // }
208 //
209 // // Get the cliff cell's grid coords
210 // int nXCliff = pCliff->pPtiGetCellMarkedAsLF()->nGetX();
211 // int nYCliff = pCliff->pPtiGetCellMarkedAsLF()->nGetY();
212 //
213 // // Get this cell's polygon
214 // int nPoly = m_pRasterGrid->m_Cell[nXCliff][nYCliff].nGetPolygonID();
215 //
216 // LogStream << endl;
217 // LogStream << "*****************************" << endl;
218 // LogStream << m_ulIter << ": after cliff collapse on nPoly = " << nPoly << " total consolidated sand = " << dTmpSandCons * m_dCellArea << " total unconsolidated sand = " << dTmpSandUncons * m_dCellArea << endl;
219 // LogStream << m_ulIter << ": total consolidated sand lost this iteration = " << (m_dStartIterConsSandAllCells - dTmpSandCons) * m_dCellArea << endl;
220 // LogStream << m_ulIter << ": total unconsolidated sand added this iteration = " << (dTmpSandUncons - m_dStartIterUnconsSandAllCells) * m_dCellArea << endl;
221 //
222 // double dTmpAllPolySandErosion = 0;
223 // double dTmpAllPolySandDeposition = 0;
224 // for (unsigned int n = 0; n < m_pVCoastPolygon.size(); n++)
225 // {
226 // double dTmpSandErosion = m_pVCoastPolygon[n]->dGetCliffCollapseErosionSand() * m_dCellArea ;
227 // double dTmpSandDeposition = m_pVCoastPolygon[n]->dGetCliffCollapseUnconsSandDeposition() * m_dCellArea ;
228 //
229 // LogStream << m_ulIter << ": polygon = " << m_pVCoastPolygon[n]->nGetPolygonCoastID() << " sand erosion = " << dTmpSandErosion << " sand deposition = " << dTmpSandDeposition << endl;
230 //
231 // dTmpAllPolySandErosion += dTmpSandErosion;
232 // dTmpAllPolySandDeposition += dTmpSandDeposition;
233 // }
234 //
235 // LogStream << "-------------------------------------------" << endl;
236 // LogStream << m_ulIter << ": all polygons, sand erosion = " << dTmpAllPolySandErosion << " sand deposition = " << dTmpAllPolySandDeposition << endl;
237 // LogStream << "*****************************" << endl;
238 // }
239 // // DEBUG CODE ============================================================================================================================================
240 }
241 }
242 }
243 }
244
247
248 return RTN_OK;
249}
250
251//===============================================================================================================================
253//===============================================================================================================================
254int CSimulation::nDoCliffCollapse(int const nCoast, CRWCliff* pCliff, double& dFineCollapse, double& dSandCollapse, double& dCoarseCollapse, double& dPreCollapseCliffElev, double& dPostCollapseCliffElev)
255{
256 // Get the cliff cell's grid coords
257 int const nX = pCliff->pPtiGetCellMarkedAsLF()->nGetX();
258 int const nY = pCliff->pPtiGetCellMarkedAsLF()->nGetY();
259
260 // Get this cell's polygon
261 int const nPoly = m_pRasterGrid->m_Cell[nX][nY].nGetPolygonID();
262
263 if (nPoly == INT_NODATA)
264 {
265 // This cell isn't in a polygon
266 LogStream << m_ulIter << ": " << WARN << "in nDoCliffCollapse(), [" << nX << "][" << nY << "] = {" << dGridCentroidXToExtCRSX(nX) << ", " << dGridCentroidYToExtCRSY(nY) << "} is not in a polygon" << endl;
267
269 }
270
271 CGeomCoastPolygon* pPolygon = m_VCoast[nCoast].pGetPolygon(nPoly);
272
273 double const dOrigCliffTopElev = m_pRasterGrid->m_Cell[nX][nY].dGetSedimentTopElev();
274
275 // Get the elevation of the base of the notch from the cliff object
276 double const dNotchElev = pCliff->dGetNotchBaseElev();
277
278 // Get the index of the layer containing the notch (layer 0 being just above basement)
279 int const nNotchLayer = m_pRasterGrid->m_Cell[nX][nY].nGetLayerAtElev(dNotchElev);
280
281 // Safety checks
282 if (nNotchLayer == ELEV_IN_BASEMENT)
283 {
284 LogStream << m_ulIter << ": " << WARN << "in nDoCliffCollapse(), [" << nX << "][" << nY << "] nNotchLayer is in basement" << endl;
285 return RTN_ERR_CLIFFNOTCH;
286 }
287 else if (nNotchLayer == ELEV_ABOVE_SEDIMENT_TOP)
288 {
289 LogStream << m_ulIter << ": " << WARN << "in nDoCliffCollapse(), [" << nX << "][" << nY << "] has nNotchLayer above sediment top" << endl;
290 return RTN_ERR_CLIFFNOTCH;
291 }
292 else if (nNotchLayer < 0)
293 {
294 LogStream << m_ulIter << ": " << WARN << "in nDoCliffCollapse(), [" << nX << "][" << nY << "] = {" << dGridCentroidXToExtCRSX(nX) << ", " << dGridCentroidYToExtCRSY(nY) << "} notch layer = " << nNotchLayer << ", dNotchElev = " << dNotchElev << " m_dNotchBaseBelowSWL = " << m_dNotchBaseBelowSWL << " dOrigCliffTopElev = " << dOrigCliffTopElev << endl;
295 return RTN_ERR_CLIFFNOTCH;
296 }
297
298 // Notch layer is OK, so flag the coastline cliff object as having collapsed
299 pCliff->SetCliffCollapsed();
300
301 int const nTopLayer = m_pRasterGrid->m_Cell[nX][nY].nGetTopLayerAboveBasement();
302
303 // Safety check
304 if (nTopLayer == INT_NODATA)
305 {
306 LogStream << m_ulIter << ": " << WARN << "in nDoCliffCollapse(), [" << nX << "][" << nY << "] nTopLayer = " << nTopLayer << endl;
307
309 }
310
311 // Set the base of the collapse (see above)
312 pCliff->SetNotchBaseElev(dNotchElev);
313
314 // Set flags to say that the top layer has changed
315 m_bConsChangedThisIter[nTopLayer] = true;
316 m_bUnconsChangedThisIter[nTopLayer] = true;
317
318 // Get the pre-collapse cliff elevation
319 dPreCollapseCliffElev = m_pRasterGrid->m_Cell[nX][nY].dGetSedimentTopElev();
320
321 // Now calculate the vertical depth of sediment lost in this cliff collapse. In CoastalME, all depth equivalents are assumed to be a depth upon the whole of a cell i.e. upon the area of a whole cell. So to keep the depth of cliff collapse consistent with all other depth equivalents, weight it by the fraction of the cell's area which is being removed
322 double dAvailable = 0;
323 double dFineConsLost = 0;
324 double dFineUnconsLost = 0;
325 double dSandConsLost = 0;
326 double dSandUnconsLost = 0;
327 double dCoarseConsLost = 0;
328 double dCoarseUnconsLost = 0;
329
330 // Now update the cell's sediment. If there are sediment layers above the notched layer, we must remove sediment from the whole depth of each layer
331 for (int n = nTopLayer; n > nNotchLayer; n--)
332 {
333 // Start with the unconsolidated sediment
334 dAvailable = m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(n)->pGetUnconsolidatedSediment()->dGetFineDepth() - m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(n)->pGetUnconsolidatedSediment()->dGetNotchFineLost();
335
336 if (dAvailable > 0)
337 {
338 dFineCollapse += dAvailable;
339 dFineUnconsLost += dAvailable;
340 m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(n)->pGetUnconsolidatedSediment()->SetFineDepth(0);
341 m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(n)->pGetUnconsolidatedSediment()->SetNotchFineLost(0);
342 }
343
344 dAvailable = m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(n)->pGetUnconsolidatedSediment()->dGetSandDepth() - m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(n)->pGetUnconsolidatedSediment()->dGetNotchSandLost();
345
346 if (dAvailable > 0)
347 {
348 dSandCollapse += dAvailable;
349 dSandUnconsLost += dAvailable;
350 m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(n)->pGetUnconsolidatedSediment()->SetSandDepth(0);
351 m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(n)->pGetUnconsolidatedSediment()->SetNotchSandLost(0);
352 }
353
354 dAvailable = m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(n)->pGetUnconsolidatedSediment()->dGetCoarseDepth() - m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(n)->pGetUnconsolidatedSediment()->dGetNotchCoarseLost();
355
356 if (dAvailable > 0)
357 {
358 dCoarseCollapse += dAvailable;
359 dCoarseUnconsLost += dAvailable;
360 m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(n)->pGetUnconsolidatedSediment()->SetCoarseDepth(0);
361 m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(n)->pGetUnconsolidatedSediment()->SetNotchCoarseLost(0);
362 }
363
364 // Now get the consolidated sediment
365 dAvailable = m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(n)->pGetConsolidatedSediment()->dGetFineDepth() - m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(n)->pGetConsolidatedSediment()->dGetNotchFineLost();
366
367 if (dAvailable > 0)
368 {
369 dFineCollapse += dAvailable;
370 dFineConsLost += dAvailable;
371 m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(n)->pGetConsolidatedSediment()->SetFineDepth(0);
372 m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(n)->pGetConsolidatedSediment()->SetNotchFineLost(0);
373 }
374
375 dAvailable = m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(n)->pGetConsolidatedSediment()->dGetSandDepth() - m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(n)->pGetConsolidatedSediment()->dGetNotchSandLost();
376
377 if (dAvailable > 0)
378 {
379 dSandCollapse += dAvailable;
380 dSandConsLost += dAvailable;
381 m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(n)->pGetConsolidatedSediment()->SetSandDepth(0);
382 m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(n)->pGetConsolidatedSediment()->SetNotchSandLost(0);
383 }
384
385 dAvailable = m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(n)->pGetConsolidatedSediment()->dGetCoarseDepth() - m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(n)->pGetConsolidatedSediment()->dGetNotchCoarseLost();
386
387 if (dAvailable > 0)
388 {
389 dCoarseCollapse += dAvailable;
390 dCoarseConsLost += dAvailable;
391 m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(n)->pGetConsolidatedSediment()->SetCoarseDepth(0);
392 m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(n)->pGetConsolidatedSediment()->SetNotchCoarseLost(0);
393 }
394 }
395
396 // Now sort out the sediment lost from the consolidated layer into which the erosional notch was incised
397 double const dNotchLayerTop = m_pRasterGrid->m_Cell[nX][nY].dCalcLayerElev(nNotchLayer);
398 double const dNotchLayerThickness = m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nNotchLayer)->dGetTotalThickness();
399 double const dNotchLayerFracRemoved = (dNotchLayerTop - dNotchElev) / dNotchLayerThickness;
400
401 // Sort out the notched layer's sediment, both consolidated and unconsolidated, for this cell. First the unconsolidated sediment
402 double dFineDepth = m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nNotchLayer)->pGetUnconsolidatedSediment()->dGetFineDepth();
403 dAvailable = dFineDepth - m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nNotchLayer)->pGetUnconsolidatedSediment()->dGetNotchFineLost();
404
405 if (dAvailable > 0)
406 {
407 // Some unconsolidated fine sediment is available for collapse
408 double const dLost = dAvailable * dNotchLayerFracRemoved;
409 dFineCollapse += dLost;
410 dFineUnconsLost += dLost;
411 m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nNotchLayer)->pGetUnconsolidatedSediment()->SetFineDepth(dFineDepth - dLost);
412 m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nNotchLayer)->pGetUnconsolidatedSediment()->SetNotchFineLost(0);
413 }
414
415 double dSandDepth = m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nNotchLayer)->pGetUnconsolidatedSediment()->dGetSandDepth();
416 dAvailable = dSandDepth - m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nNotchLayer)->pGetUnconsolidatedSediment()->dGetNotchSandLost();
417
418 if (dAvailable > 0)
419 {
420 // Some unconsolidated sand sediment is available for collapse
421 double const dLost = dAvailable * dNotchLayerFracRemoved;
422 dSandCollapse += dLost;
423 dSandUnconsLost += dLost;
424 m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nNotchLayer)->pGetUnconsolidatedSediment()->SetSandDepth(dSandDepth - dLost);
425 m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nNotchLayer)->pGetUnconsolidatedSediment()->SetNotchSandLost(0);
426 }
427
428 double dCoarseDepth = m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nNotchLayer)->pGetUnconsolidatedSediment()->dGetCoarseDepth();
429 dAvailable = dCoarseDepth - m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nNotchLayer)->pGetUnconsolidatedSediment()->dGetNotchCoarseLost();
430
431 if (dAvailable > 0)
432 {
433 // Some unconsolidated coarse sediment is available for collapse
434 double const dLost = dAvailable * dNotchLayerFracRemoved;
435 dCoarseCollapse += dLost;
436 dCoarseUnconsLost += dLost;
437 m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nNotchLayer)->pGetUnconsolidatedSediment()->SetCoarseDepth(dCoarseDepth - dLost);
438 m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nNotchLayer)->pGetUnconsolidatedSediment()->SetNotchCoarseLost(0);
439 }
440
441 // Now do the consolidated sediment
442 dFineDepth = m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nNotchLayer)->pGetConsolidatedSediment()->dGetFineDepth();
443 dAvailable = dFineDepth - m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nNotchLayer)->pGetConsolidatedSediment()->dGetNotchFineLost();
444
445 if (dAvailable > 0)
446 {
447 // Some consolidated fine sediment is available for collapse
448 double const dLost = dAvailable * dNotchLayerFracRemoved;
449 dFineCollapse += dLost;
450 dFineConsLost += dLost;
451 m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nNotchLayer)->pGetConsolidatedSediment()->SetFineDepth(dFineDepth - dLost);
452 m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nNotchLayer)->pGetConsolidatedSediment()->SetNotchFineLost(0);
453 }
454
455 dSandDepth = m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nNotchLayer)->pGetConsolidatedSediment()->dGetSandDepth();
456 dAvailable = dSandDepth - m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nNotchLayer)->pGetConsolidatedSediment()->dGetNotchSandLost();
457
458 if (dAvailable > 0)
459 {
460 // Some consolidated sand sediment is available for collapse
461 double const dLost = dAvailable * dNotchLayerFracRemoved;
462 dSandCollapse += dLost;
463 dSandConsLost += dLost;
464 m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nNotchLayer)->pGetConsolidatedSediment()->SetSandDepth(dSandDepth - dLost);
465 m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nNotchLayer)->pGetConsolidatedSediment()->SetNotchSandLost(0);
466 }
467
468 dCoarseDepth = m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nNotchLayer)->pGetConsolidatedSediment()->dGetCoarseDepth();
469 dAvailable = dCoarseDepth - m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nNotchLayer)->pGetConsolidatedSediment()->dGetNotchCoarseLost();
470
471 if (dAvailable > 0)
472 {
473 // Some consolidated coarse sediment is available for collapse
474 double const dLost = dAvailable * dNotchLayerFracRemoved;
475 dCoarseCollapse += dLost;
476 dCoarseConsLost += dLost;
477 m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nNotchLayer)->pGetConsolidatedSediment()->SetCoarseDepth(dCoarseDepth - dLost);
478 m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nNotchLayer)->pGetConsolidatedSediment()->SetNotchCoarseLost(0);
479 }
480
481 // Update the cell's totals for cliff collapse erosion
482 m_pRasterGrid->m_Cell[nX][nY].IncrCliffCollapseErosion(dFineCollapse, dSandCollapse, dCoarseCollapse);
483
484 // Update the cell's layer elevations and d50
485 m_pRasterGrid->m_Cell[nX][nY].CalcAllLayerElevsAndD50();
486
487 // Get the post-collapse cliff elevation
488 dPostCollapseCliffElev = m_pRasterGrid->m_Cell[nX][nY].dGetSedimentTopElev();
489
491 LogStream << m_ulIter << ": cliff collapse at [" << nX << "][" << nY << "], original cliff elevation = " << dOrigCliffTopElev << ", new cliff elevation = " << dPostCollapseCliffElev << ", change in elevation = " << dOrigCliffTopElev - dPostCollapseCliffElev << endl;
492
493 // And update the cell's sea depth
494 m_pRasterGrid->m_Cell[nX][nY].SetSeaDepth();
495
496 // LogStream << m_ulIter << ": cell [" << nX << "][" << nY << "] after removing sediment, dGetVolEquivSedTopElev() = " << m_pRasterGrid->m_Cell[nX][nY].dGetVolEquivSedTopElev() << ", dGetSedimentTopElev() = " << m_pRasterGrid->m_Cell[nX][nY].dGetSedimentTopElev() << endl << endl;
497
498 // Update this-polygon totals: add to the depths of cliff collapse erosion for this polygon
499 pPolygon->AddCliffCollapseErosionFine(dFineCollapse);
500 pPolygon->AddCliffCollapseToSuspensionFine(dFineCollapse);
501 pPolygon->AddCliffCollapseErosionSand(dSandCollapse);
502 pPolygon->AddCliffCollapseErosionCoarse(dCoarseCollapse);
503
504 // And update the this-timestep totals and the grand totals for collapse
505 // m_nNThisIterCliffCollapse++;
506 // m_nNTotCliffCollapse++;
507
508 // Add to this-iteration totals
511
512 // Also add to the total suspended load. Note that this addition to the suspended load has not yet been added to all cells, this happens in nUpdateGrid()
513 m_dThisIterFineSedimentToSuspension += (dFineConsLost + dFineUnconsLost);
514
519
520 return RTN_OK;
521}
522
523//===============================================================================================================================
525//===============================================================================================================================
526int CSimulation::nDoCliffCollapseDeposition(int const nCoast, CRWCliff const* pCliff, double const dSandFromCollapse, double const dCoarseFromCollapse, double const dPreCollapseCliffElev, double const dPostCollapseCliffElev)
527{
528 // Check: is there some sand- or coarse-sized sediment to deposit?
529 if ((dSandFromCollapse + dCoarseFromCollapse) < SEDIMENT_ELEV_TOLERANCE)
530 return RTN_OK;
531
532 // LogStream << "\tdSandFromCollapse = " << dSandFromCollapse << " dCoarseFromCollapse = " << dCoarseFromCollapse << endl;
533
534 // OK, we have some sand- and/or coarse-sized sediment to deposit
535 int const nStartPoint = pCliff->nGetPointOnCoast();
536 int const nCoastSize = m_VCoast[nCoast].nGetCoastlineSize();
537
538 // Get the cliff cell's grid coords
539 int const nXCliff = pCliff->pPtiGetCellMarkedAsLF()->nGetX();
540 int const nYCliff = pCliff->pPtiGetCellMarkedAsLF()->nGetY();
541
542 // Get this cell's polygon
543 int const nPoly = m_pRasterGrid->m_Cell[nXCliff][nYCliff].nGetPolygonID();
544
545 if (nPoly == INT_NODATA)
546 {
547 // This cell isn't in a polygon
548 LogStream << m_ulIter << " : in nDoCliffCollapse(), [" << nXCliff << "][" << nYCliff << "] = {" << dGridCentroidXToExtCRSX(nXCliff) << ", " << dGridCentroidYToExtCRSY(nYCliff) << "} is not in a polygon" << endl;
549
551 }
552
553 CGeomCoastPolygon* pPolygon = m_VCoast[nCoast].pGetPolygon(nPoly);
554
555 // OK, now set up the planview sequence talus deposition. First we deposit to create a Dean profile starting from the cliff collapse cell. Then we deposit along two profiles which start from the coast cells on either side of the cliff collapse cell, and then on two profiles starting on the next two "outside" coast cells, etc. However, we do have a "preferred" talus width
557
558 // The default talus collapse width must be an odd number of cells in width i.e. centred on the cliff collapse cell (but only if we are not at the end of the coast)
559 if ((nTalusWidthInCells % 2) == 0)
560 nTalusWidthInCells++;
561
562 // This holds the valid coast start points for each cliff collapse Dean profile
563 vector<int> VnTalusProfileCoastStartPoint(nCoastSize);
564
565 // This is the coast start point for the first Dean profile
566 VnTalusProfileCoastStartPoint[0] = nStartPoint;
567 int nn = 1;
568 int nSigned = 1;
569 int nCount = 1;
570
571 do
572 {
573 int nTmpPoint;
574
575 if ((nCount % 2) != 0)
576 nTmpPoint = nStartPoint + nSigned;
577 else
578 {
579 nTmpPoint = nStartPoint - nSigned;
580 nSigned++;
581 }
582
583 // Is this start point valid?
584 if ((nTmpPoint < 0) || (nTmpPoint > (nCoastSize - 1)))
585 {
586 // No, it is outside the grid, so find another
587 nCount++;
588 continue;
589 }
590 else
591 {
592 // It is valid
593 VnTalusProfileCoastStartPoint[nn] = nTmpPoint;
594 nn++;
595 nCount++;
596 }
597 } while (nn < nCoastSize);
598
599 bool bHitFirstCoastPoint = false;
600 bool bHitLastCoastPoint = false;
601
602 double dTotSandToDepositAllProfiles = dSandFromCollapse; // Note that this can increase, if we get erosion because Dean profile is lower than profile at a point
603 double dTotCoarseToDepositAllProfiles = dCoarseFromCollapse; // Note that this can increase, if we get erosion because Dean profile is lower than profile at a point
604 double dTotSandDepositedAllProfiles = 0;
605 double dTotCoarseDepositedAllProfiles = 0;
606
607 // Process each deposition profile
608 for (int nDepProfile = 0; nDepProfile < nCoastSize; nDepProfile++)
609 {
610 bool bDoSandDepositionOnThisProfile = false;
611 bool bSandDepositionCompletedOnThisProfile = false;
612 bool bDoCoarseDepositionOnThisProfile = false;
613 bool bCoarseDepositionCompletedOnThisProfile = false;
614
615 int const nRemainingProfiles = tMax(1, nTalusWidthInCells - nDepProfile);
616
617 // This is the minimum planview length (in cells) of the Dean profile. The initial length will be increased later if we can't deposit sufficient talus
618 int nTalusProfileLenInCells = nConvertMetresToNumCells(m_dCliffTalusMinDepositionLength);
619
620 // Calculate the target amount to be deposited on each talus profile, assuming the "preferred" talus width
621 double dTargetSandToDepositOnThisProfile = (dTotSandToDepositAllProfiles - dTotSandDepositedAllProfiles) / nRemainingProfiles;
622 double dTargetCoarseToDepositOnThisProfile = (dTotCoarseToDepositAllProfiles - dTotCoarseDepositedAllProfiles) / nRemainingProfiles;
623
624 // Use this to make sure that, if we have both sand and coarse to deposit, we don't drop all the sand on a cell and then be unable to deposit any coarse
625 double dSandProp = 0.5;
626 double dCoarseProp = 1 - dSandProp;
627
628 if (dTargetSandToDepositOnThisProfile + dTargetCoarseToDepositOnThisProfile > 0)
629 {
630 dSandProp = dTargetSandToDepositOnThisProfile / (dTargetSandToDepositOnThisProfile + dTargetCoarseToDepositOnThisProfile);
631 dCoarseProp = 1 - dSandProp;
632 }
633
634 double dSandDepositedOnThisProfile = 0;
635 double dCoarseDepositedOnThisProfile = 0;
636
637 if (dTotSandToDepositAllProfiles > 0)
638 {
639 bDoSandDepositionOnThisProfile = true;
640
641 if (bFPIsEqual(dTotSandToDepositAllProfiles - dTotSandDepositedAllProfiles, 0.0, MASS_BALANCE_TOLERANCE))
642 bSandDepositionCompletedOnThisProfile = true;
643 }
644
645 else
646 bSandDepositionCompletedOnThisProfile = true;
647
648 if (dTotCoarseToDepositAllProfiles > 0)
649 {
650 bDoCoarseDepositionOnThisProfile = true;
651
652 if (bFPIsEqual(dTotCoarseToDepositAllProfiles - dTotCoarseDepositedAllProfiles, 0.0, MASS_BALANCE_TOLERANCE))
653 bCoarseDepositionCompletedOnThisProfile = true;
654 }
655
656 else
657 bCoarseDepositionCompletedOnThisProfile = true;
658
659 if (bSandDepositionCompletedOnThisProfile && bCoarseDepositionCompletedOnThisProfile)
660 {
661 // LogStream << m_ulIter << ": break 2 for cliff collapse at [" << nXCliff << "][" << nYCliff << "] nStartPoint = " << nStartPoint << " nDepProfile = " << nDepProfile << endl << "\tdTargetSandToDepositOnThisProfile = " << dTargetSandToDepositOnThisProfile << " dSandDepositedOnThisProfile = " << dSandDepositedOnThisProfile << " dTotSandToDepositAllProfiles = " << dTotSandToDepositAllProfiles << " dTotSandDepositedAllProfiles = " << dTotSandDepositedAllProfiles << endl << "\tdTargetCoarseToDepositOnThisProfile = " << dTargetCoarseToDepositOnThisProfile << " dCoarseDepositedOnThisProfile = " << dCoarseDepositedOnThisProfile << " dTotCoarseToDepositAllProfiles = " << dTotCoarseToDepositAllProfiles << " dTotCoarseDepositedAllProfiles = " << dTotCoarseDepositedAllProfiles << endl;
662
663 break;
664 }
665
666 // Get the start point of this cliff collapse deposition profile
667 int const nThisPoint = VnTalusProfileCoastStartPoint[nDepProfile];
668
669 // Are we at the start or end of the coast?
670 if (nThisPoint == 0)
671 bHitFirstCoastPoint = true;
672
673 if (nThisPoint == nCoastSize - 1)
674 bHitLastCoastPoint = true;
675
676 CGeom2DPoint PtStart;
677 CGeom2DPoint PtEnd;
678
679 // Make the start of the deposition profile the cliff cell that is marked as coast (not the cell under the smoothed vector coast, they may well be different)
680 PtStart.SetX(dGridCentroidXToExtCRSX(m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(nThisPoint)->nGetX()));
681 PtStart.SetY(dGridCentroidYToExtCRSY(m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(nThisPoint)->nGetY()));
682
683 // Set the initial fraction of cliff height, this will be increased (max is one) if we can't deposit sufficient talus
684 double dCliffHeightFrac = m_dMinCliffTalusHeightFrac;
685
686 bool bJustDepositWhatWeCan = false;
687
688 // The initial seaward offset, in cells. This will be increased if we can't deposit sufficient talus
689 int nSeawardOffset = 1;
690
691 // Process this profile
692 do
693 {
694 if (bJustDepositWhatWeCan || (bSandDepositionCompletedOnThisProfile && bCoarseDepositionCompletedOnThisProfile))
695 {
696 // LogStream << m_ulIter << ": break 3 for cliff collapse at [" << nXCliff << "][" << nYCliff << "] nStartPoint = " << nStartPoint << " nThisPoint = " << nThisPoint << endl << "\tnSeawardOffset = " << nSeawardOffset << " dCliffHeightFrac = " << dCliffHeightFrac << " nDepProfile = " << nDepProfile << endl << "\tbJustDepositWhatWeCan = " << bJustDepositWhatWeCan << "\tdTargetSandToDepositOnThisProfile = " << dTargetSandToDepositOnThisProfile << " dSandDepositedOnThisProfile = " << dSandDepositedOnThisProfile << " dTotSandToDepositAllProfiles = " << dTotSandToDepositAllProfiles << " dTotSandDepositedAllProfiles = " << dTotSandDepositedAllProfiles << endl << "\tdTargetCoarseToDepositOnThisProfile = " << dTargetCoarseToDepositOnThisProfile << " dCoarseDepositedOnThisProfile = " << dCoarseDepositedOnThisProfile << " dTotCoarseToDepositAllProfiles = " << dTotCoarseToDepositAllProfiles << " dTotCoarseDepositedAllProfiles = " << dTotCoarseDepositedAllProfiles << endl;
697
698 break;
699 }
700
701 // Need to deposit more on this profile: increase the seaward offset each time round the loop
702 nSeawardOffset++;
703
704 // Has the seaward offset reached the arbitrary limit?
705 if (nSeawardOffset >= MAX_SEAWARD_OFFSET_FOR_CLIFF_TALUS)
706 {
707 // It has, so if cliff height is not at the maximum, then try again with a larger fraction of cliff height
708 if (dCliffHeightFrac < 1)
709 {
710 dCliffHeightFrac += CLIFF_COLLAPSE_HEIGHT_INCREMENT;
711
712 // Reset seaward offset
713 nSeawardOffset = 1;
714 }
715
716 else
717 {
718 // Cliff height has reached the limit, is the talus length also at its arbitrary limit?
719 if (nTalusProfileLenInCells >= MAX_CLIFF_TALUS_LENGTH)
720 {
721 // The talus length is also at this limit, so there is nothing more we can increase on this profile. Just deposit what we can and move on to the next profile
722 bJustDepositWhatWeCan = true;
723 }
724
725 else
726 {
727 // The talus length is not at its limit, so try again with an increased talus length
728 nTalusProfileLenInCells += CLIFF_COLLAPSE_LENGTH_INCREMENT;
729
730 // Reset seaward offset
731 nSeawardOffset = 1;
732
733 // Set cliff height to exactly one
734 dCliffHeightFrac = 1;
735 }
736 }
737 }
738
739 if (bHitFirstCoastPoint && bHitLastCoastPoint)
740 {
741 // Uh-oh, we've reached both ends of the coast (!) and we can't increase anything any more
742 LogStream << m_ulIter << ": unable to deposit sufficient unconsolidated talus from cliff collapse at [" << nXCliff << "][" << nYCliff << "] nStartPoint = " << nStartPoint << " nThisPoint = " << nThisPoint << endl << "\tnSeawardOffset = " << nSeawardOffset << " dCliffHeightFrac = " << dCliffHeightFrac << " nDepProfile = " << nDepProfile << endl << "\tdTargetSandToDepositOnThisProfile = " << dTargetSandToDepositOnThisProfile << " dSandDepositedOnThisProfile = " << dSandDepositedOnThisProfile << " dTotSandToDepositAllProfiles = " << dTotSandToDepositAllProfiles << " dTotSandDepositedAllProfiles = " << dTotSandDepositedAllProfiles << endl << "\tdTargetCoarseToDepositOnThisProfile = " << dTargetCoarseToDepositOnThisProfile << " dCoarseDepositedOnThisProfile = " << dCoarseDepositedOnThisProfile << " dTotCoarseToDepositAllProfiles = " << dTotCoarseToDepositAllProfiles << " dTotCoarseDepositedAllProfiles = " << dTotCoarseDepositedAllProfiles << endl;
743
745 }
746
747 // Now construct a deposition collapse profile from the start point, it is one cell longer than the specified length because it includes the cliff point in the profile. Calculate its length in external CRS units, the way it is done here is approximate but probably OK
748 double const dThisProfileLength = (nTalusProfileLenInCells + nSeawardOffset + 1) * m_dCellSide;
749
750 // Get the end point of this coastline-normal line
751 CGeom2DIPoint PtiEnd; // In grid CRS
752 int const nRtn = nGetCoastNormalEndPoint(nCoast, nThisPoint, nCoastSize, &PtStart, dThisProfileLength, &PtEnd, &PtiEnd, false);
753
754 // Safety check
756 {
757 LogStream << m_ulIter << ": unable to deposit sufficient unconsolidated talus from cliff collapse, could not find a solution for the end point of the Dean profile" << endl;
758
759 return nRtn;
760 }
761
762 // Safety check
763 if (PtStart == PtEnd)
764 {
765 // This would give a zero-length profile, and a zero-divide error during rasterization. So just move on to the next profile
766 break;
767 }
768
769 // OK, both the start and end points of this deposition profile are within the grid
770 // LogStream << m_ulIter << ": nWidthDistSigned = " << nWidthDistSigned << " cliff collapse profile from " << PtStart.dGetX() << ", " << PtStart.dGetY() << " to " << PtEnd.dGetX() << ", " << PtEnd.dGetY() << " with length (inc. cliff point) = " << dThisProfileLength << endl;
771
772 vector<CGeom2DPoint> VTmpProfile;
773 VTmpProfile.push_back(PtStart);
774 VTmpProfile.push_back(PtEnd);
775 vector<CGeom2DIPoint> VCellsUnderProfile;
776
777 // Now get the raster cells under this profile
778 RasterizeCliffCollapseProfile(&VTmpProfile, &VCellsUnderProfile);
779
780 int const nRasterProfileLength = static_cast<int>(VCellsUnderProfile.size());
781
782 // Check now, for the case where the profile is very short
783 if (nRasterProfileLength - nSeawardOffset < 3)
784 {
785 // Can't do anything with this very short profile, since (nRasterProfileLength - nSeawardOffset - 2) later will give zero or -ve dInc. So just move on to the next profile
786 break;
787 }
788
789 else if (nRasterProfileLength - nSeawardOffset == 3)
790 {
791 // Can't increase offset any more, or get zero divide with (nRasterProfileLength - nSeawardOffset - 2) later. So just deposit what we can and then move on to the next profile
792 bJustDepositWhatWeCan = true;
793 }
794
795 vector<double> dVProfileNow(nRasterProfileLength, 0);
796 vector<bool> bVProfileValid(nRasterProfileLength, true);
797
798 // LogStream << m_ulIter << ": for cliff collapse at [" << nXCliff << "][" << nYCliff << "] nStartPoint = " << nStartPoint << " nDepProfile = " << nDepProfile << endl << "\tnRasterProfileLength = " << nRasterProfileLength << " nSeawardOffset = " << nSeawardOffset << " nRasterProfileLength - nSeawardOffset - 2 = " << nRasterProfileLength - nSeawardOffset - 2 << endl;
799
800 // Calculate the existing elevation for all points along the deposition profile
801 for (int n = 0; n < nRasterProfileLength; n++)
802 {
803 int const nX = VCellsUnderProfile[n].nGetX();
804 int const nY = VCellsUnderProfile[n].nGetY();
805
806 dVProfileNow[n] = m_pRasterGrid->m_Cell[nX][nY].dGetSedimentTopElev();
807
808 // Don't allow cliff collapse talus onto intervention cells TODO 078 Is this realistic? Should it change with different types on intervention?
809 if (bIsInterventionCell(nX, nY))
810 bVProfileValid[n] = false;
811 }
812
813 // Now calculate the elevation of the talus top at the shoreline
814 double const dCliffHeight = dPreCollapseCliffElev - dPostCollapseCliffElev;
815 double const dTalusTopElev = dPostCollapseCliffElev + (dCliffHeight * dCliffHeightFrac);
816
817 // LogStream << "Elevations: cliff top = " << dPreCollapseCliffElev << " cliff base = " << dPostCollapseCliffElev << " talus top = " << dTalusTopElev << endl;
818
819 // if (dPreCollapseCliffElev < dPostCollapseCliffElev)
820 // LogStream << "*** ERROR, cliff top is lower than cliff base" << endl;
821
822 // Next calculate the talus slope length in external CRS units, this is approximate but probably OK
823 double const dTalusSlopeLength = dThisProfileLength - ((nSeawardOffset - 1) * m_dCellSide);
824
825 // If user has not supplied a value for m_dCliffDepositionA, then solve for dA so that the elevations at end of the existing profile, and at the end of the Dean equilibrium profile, are the same
826 double dA = 0;
827
830
831 else
832 dA = (dTalusTopElev - dVProfileNow[nRasterProfileLength - 1]) / pow(dTalusSlopeLength, DEAN_POWER);
833
834 // assert((nRasterProfileLength - nSeawardOffset - 2) > 0);
835 double const dInc = dTalusSlopeLength / (nRasterProfileLength - nSeawardOffset - 2);
836 vector<double> dVDeanProfile(nRasterProfileLength);
837
838 // Calculate the Dean equilibrium profile of the talus h(y) = A * y^(2/3) where h(y) is the distance below the talus-top elevation (the highest point in the Dean profile) at a distance y from the cliff (the landward start of the profile)
839 CalcDeanProfile(&dVDeanProfile, dInc, dTalusTopElev, dA, true, nSeawardOffset, dTalusTopElev);
840
841 // Get the total difference in elevation between the two profiles (Dean profile - present profile). Since we want the Dean profile to be higher than the present profile, a good result is a +ve number
842 double const dTotElevDiff = dSubtractProfiles(&dVDeanProfile, &dVProfileNow, &bVProfileValid);
843
844 // // DEBUG CODE -----------------------------------------------------
845 // LogStream << endl;
846 // LogStream << "dTalusSlopeLength = " << dTalusSlopeLength << " dA = " << dA << endl;
847 // LogStream << "dDistFromTalusStart - dInc = " << dDistFromTalusStart - dInc << " dThisProfileLength - nSeawardOffset - 2 = " << dThisProfileLength - nSeawardOffset - 2 << endl;
848 // LogStream << "Profile now (inc. cliff cell) = ";
849 // for (int n = 0; n < nRasterProfileLength; n++)
850 // {
851 // int
852 // nX = VCellsUnderProfile[n].nGetX(),
853 // nY = VCellsUnderProfile[n].nGetY();
854 // dVProfileNow[n] = m_pRasterGrid->m_Cell[nX][nY].dGetSedimentTopElev();
855 // LogStream << dVProfileNow[n] << " ";
856 // }
857 // LogStream << endl;
858 // LogStream << "Dean equilibrium profile (inc. cliff cell) = ";
859 // for (int n = 0; n < nRasterProfileLength; n++)
860 // {
861 // LogStream << dVDeanProfile[n] << " ";
862 // }
863 // LogStream << endl;
864 // LogStream << "Difference (inc. cliff cell) = ";
865 // for (int n = 0; n < nRasterProfileLength; n++)
866 // {
867 // LogStream << dVDeanProfile[n] - dVProfileNow[n] << " ";
868 // }
869 // LogStream << endl;
870 // // DEBUG CODE -----------------------------------------------------
871
872 // If we are not in a "just deposit what we can" situation, then for this planview profile, does the Dean equilibrium profile allow us to deposit all the talus sediment which we need to get rid of?
873 if (! bJustDepositWhatWeCan && (dTotElevDiff < (dTargetSandToDepositOnThisProfile + dTargetCoarseToDepositOnThisProfile)))
874 {
875 // No it doesn't, so try again with a larger seaward offset and/or a longer Dean profile length
876 // LogStream << m_ulIter << ": bJustDepositWhatWeCan = " << bJustDepositWhatWeCan << " nSeawardOffset = " << nSeawardOffset << " dTotElevDiff = " << dTotElevDiff << endl;
877
878 continue;
879 }
880
881 // OK, now process all cells in this profile, including the first one (which is where the cliff collapse occurred)
882 for (int n = 0; n < nRasterProfileLength; n++)
883 {
884 // Are we depositing sand talus sediment on this profile?
885 if (bDoSandDepositionOnThisProfile)
886 {
887 if (bFPIsEqual(dTargetSandToDepositOnThisProfile - dSandDepositedOnThisProfile, 0.0, MASS_BALANCE_TOLERANCE))
888 bSandDepositionCompletedOnThisProfile = true;
889
890 else
891 bSandDepositionCompletedOnThisProfile = false;
892 }
893
894 // Are we depositing coarse talus sediment on this profile?
895 if (bDoCoarseDepositionOnThisProfile)
896 {
897 if (bFPIsEqual(dTargetCoarseToDepositOnThisProfile - dCoarseDepositedOnThisProfile, 0.0, MASS_BALANCE_TOLERANCE))
898 bCoarseDepositionCompletedOnThisProfile = true;
899
900 else
901 bCoarseDepositionCompletedOnThisProfile = false;
902 }
903
904 // If we have deposited enough, then break out of the loop
905 if (bSandDepositionCompletedOnThisProfile && bCoarseDepositionCompletedOnThisProfile)
906 {
907 // LogStream << m_ulIter << ": break 1 for cliff collapse at [" << nXCliff << "][" << nYCliff << "] nStartPoint = " << nStartPoint << " nThisPoint = " << nThisPoint << endl << "\tbJustDepositWhatWeCan = " << bJustDepositWhatWeCan << " nSeawardOffset = " << nSeawardOffset << " dCliffHeightFrac = " << dCliffHeightFrac << " nDepProfile = " << nDepProfile << endl << "\tdTargetSandToDepositOnThisProfile = " << dTargetSandToDepositOnThisProfile << " dSandDepositedOnThisProfile = " << dSandDepositedOnThisProfile << " dTotSandToDepositAllProfiles = " << dTotSandToDepositAllProfiles << " dTotSandDepositedAllProfiles = " << dTotSandDepositedAllProfiles << endl << "\tdTargetCoarseToDepositOnThisProfile = " << dTargetCoarseToDepositOnThisProfile << " dCoarseDepositedOnThisProfile = " << dCoarseDepositedOnThisProfile << " dTotCoarseToDepositAllProfiles = " << dTotCoarseToDepositAllProfiles << " dTotCoarseDepositedAllProfiles = " << dTotCoarseDepositedAllProfiles << endl;
908
909 break;
910 }
911
912 // Nope, we still have some talus left to deposit
913 int const nX = VCellsUnderProfile[n].nGetX();
914 int const nY = VCellsUnderProfile[n].nGetY();
915
916 // Don't allow cliff collapse talus onto intervention cells TODO 078 Is this realistic? Should it change with different types on intervention?
917 if (bIsInterventionCell(nX, nY))
918 continue;
919
920 int const nTopLayer = m_pRasterGrid->m_Cell[nX][nY].nGetTopNonZeroLayerAboveBasement();
921
922 // Safety check
923 if (nTopLayer == INT_NODATA)
925
926 if (nTopLayer == NO_NONZERO_THICKNESS_LAYERS)
927 {
928 // TODO 021 Improve this
929 cerr << "All layers have zero thickness" << endl;
931 }
932
933 // Only do deposition on this cell if its elevation is below the Dean elevation
934 if (dVDeanProfile[n] > dVProfileNow[n])
935 {
936 // At this point along the profile, the Dean profile is higher than the present profile. So we can deposit some sediment on this cell
937 double dSandToDeposit = 0;
938
939 if (bDoSandDepositionOnThisProfile)
940 {
941 dSandToDeposit = (dVDeanProfile[n] - dVProfileNow[n]) * dSandProp;
942 dSandToDeposit = tMin(dSandToDeposit, (dTargetSandToDepositOnThisProfile - dSandDepositedOnThisProfile), (dTotSandToDepositAllProfiles - dTotSandDepositedAllProfiles));
943
944 m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nTopLayer)->pGetUnconsolidatedSediment()->AddSandDepth(dSandToDeposit);
945
946 // Set the changed-this-timestep switch
947 m_bUnconsChangedThisIter[nTopLayer] = true;
948
949 dSandDepositedOnThisProfile += dSandToDeposit;
950 dTotSandDepositedAllProfiles += dSandToDeposit;
951 }
952
953 double dCoarseToDeposit = 0;
954
955 if (bDoCoarseDepositionOnThisProfile)
956 {
957 dCoarseToDeposit = (dVDeanProfile[n] - dVProfileNow[n]) * dCoarseProp;
958 dCoarseToDeposit = tMin(dCoarseToDeposit, (dTargetCoarseToDepositOnThisProfile - dCoarseDepositedOnThisProfile), (dTotCoarseToDepositAllProfiles - dTotCoarseDepositedAllProfiles));
959
960 m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nTopLayer)->pGetUnconsolidatedSediment()->AddCoarseDepth(dCoarseToDeposit);
961
962 // Set the changed-this-timestep switch
963 m_bUnconsChangedThisIter[nTopLayer] = true;
964
965 dCoarseDepositedOnThisProfile += dCoarseToDeposit;
966 dTotCoarseDepositedAllProfiles += dCoarseToDeposit;
967 }
968
969 // Now update the cell's layer elevations
970 m_pRasterGrid->m_Cell[nX][nY].CalcAllLayerElevsAndD50();
971
972 // Update the cell's sea depth
973 m_pRasterGrid->m_Cell[nX][nY].SetSeaDepth();
974
975 // Update the cell's talus deposition, and total talus deposition, values
976 m_pRasterGrid->m_Cell[nX][nY].AddSandTalusDeposition(dSandToDeposit);
977 m_pRasterGrid->m_Cell[nX][nY].AddCoarseTalusDeposition(dCoarseToDeposit);
978
979 // And set the landform category
980 CRWCellLandform* pLandform = m_pRasterGrid->m_Cell[nX][nY].pGetLandform();
981 int const nCat = pLandform->nGetLFCategory();
982
985 }
986
987 else if (dVDeanProfile[n] < dVProfileNow[n])
988 {
989 // Here, the Dean profile is lower than the existing profile, so we must remove some sediment from this cell TODO 075 What if bedrock sticks above Dean profile?
990 double const dThisLowering = dVProfileNow[n] - dVDeanProfile[n];
991
992 // Find out how much sediment we have available on this cell
993 double const dExistingAvailableFine = m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nTopLayer)->pGetUnconsolidatedSediment()->dGetFineDepth();
994 double const dExistingAvailableSand = m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nTopLayer)->pGetUnconsolidatedSediment()->dGetSandDepth();
995 double const dExistingAvailableCoarse = m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nTopLayer)->pGetUnconsolidatedSediment()->dGetCoarseDepth();
996
997 // Now partition the total lowering for this cell between the three size fractions: do this by relative erodibility
998 int const nFineWeight = (dExistingAvailableFine > 0 ? 1 : 0);
999 int const nSandWeight = (dExistingAvailableSand > 0 ? 1 : 0);
1000 int const nCoarseWeight = (dExistingAvailableCoarse > 0 ? 1 : 0);
1001
1002 double const dTotErodibility = (nFineWeight * m_dFineErodibilityNormalized) + (nSandWeight * m_dSandErodibilityNormalized) + (nCoarseWeight * m_dCoarseErodibilityNormalized);
1003
1004 if (nFineWeight)
1005 {
1006 // Erode some fine-sized sediment
1007 double const dFineLowering = (m_dFineErodibilityNormalized * dThisLowering) / dTotErodibility;
1008
1009 // Make sure we don't get -ve amounts left on the cell
1010 double const dFine = tMin(dExistingAvailableFine, dFineLowering);
1011 double const dRemaining = dExistingAvailableFine - dFine;
1012
1013 // Set the value for this layer
1014 m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nTopLayer)->pGetUnconsolidatedSediment()->SetFineDepth(dRemaining);
1015
1016 // And set the changed-this-timestep switch
1017 m_bUnconsChangedThisIter[nTopLayer] = true;
1018
1019 // And increment the per-timestep total for fine sediment eroded during cliff collapse deposition (note that this gets added in to the suspended load elsewhere, so no need to do it here)
1021
1022 // LogStream << m_ulIter << ": FINE erosion during cliff collapse talus deposition = " << dFine * m_dCellArea << endl;
1023
1024 // Also add to the suspended load
1026 }
1027
1028 if (nSandWeight)
1029 {
1030 // Erode some sand-sized sediment
1031 double const dSandLowering = (m_dSandErodibilityNormalized * dThisLowering) / dTotErodibility;
1032
1033 // Make sure we don't get -ve amounts left on the source cell
1034 double const dSandToErode = tMin(dExistingAvailableSand, dSandLowering);
1035 double const dRemaining = dExistingAvailableSand - dSandToErode;
1036
1037 // Set the value for this layer
1038 m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nTopLayer)->pGetUnconsolidatedSediment()->SetSandDepth(dRemaining);
1039
1040 // Set the changed-this-timestep switch
1041 m_bUnconsChangedThisIter[nTopLayer] = true;
1042
1043 // And increment the per-timestep total for sand sediment eroded during cliff collapse deposition
1045
1046 // Increase the all-profiles and this-profile sand deposition targets
1047 dTargetSandToDepositOnThisProfile += dSandToErode;
1048 dTotSandToDepositAllProfiles += dSandToErode;
1049
1050 // LogStream << m_ulIter << ": SAND erosion during cliff collapse talus deposition = " << dSandToErode * m_dCellArea << endl;
1051
1052 // Store the depth of sand sediment eroded during Dean profile deposition of sand cliff collapse talus
1053 pPolygon->AddCliffCollapseSandErodedDeanProfile(dSandToErode);
1054 }
1055
1056 if (nCoarseWeight)
1057 {
1058 // Erode some coarse-sized sediment
1059 double const dCoarseLowering = (m_dCoarseErodibilityNormalized * dThisLowering) / dTotErodibility;
1060
1061 // Make sure we don't get -ve amounts left on the source cell
1062 double const dCoarseToErode = tMin(dExistingAvailableCoarse, dCoarseLowering);
1063 double const dRemaining = dExistingAvailableCoarse - dCoarseToErode;
1064
1065 // Set the value for this layer
1066 m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nTopLayer)->pGetUnconsolidatedSediment()->SetCoarseDepth(dRemaining);
1067
1068 // Set the changed-this-timestep switch
1069 m_bUnconsChangedThisIter[nTopLayer] = true;
1070
1071 // And increment the per-timestep total for coarse sediment eroded during cliff collapse deposition
1073
1074 // Increase the all-profiles and this-profile coarse deposition targets
1075 dTargetCoarseToDepositOnThisProfile += dCoarseToErode;
1076 dTotCoarseToDepositAllProfiles += dCoarseToErode;
1077
1078 // LogStream << m_ulIter << ": COARSE erosion during cliff collapse talus deposition = " << dCoarseToErode * m_dCellArea << endl;
1079
1080 // Store the depth of coarse sediment eroded during Dean profile deposition of coarse cliff collapse talus
1081 pPolygon->AddCliffCollapseCoarseErodedDeanProfile(dCoarseToErode);
1082 }
1083
1084 // for this cell, recalculate the elevation of every layer
1085 m_pRasterGrid->m_Cell[nX][nY].CalcAllLayerElevsAndD50();
1086
1087 // And update the cell's sea depth
1088 m_pRasterGrid->m_Cell[nX][nY].SetSeaDepth();
1089 }
1090 } // All cells in this profile
1091
1092 // OK we have either processed all cells in this profile, or we have deposited enough talus sediment on this profile
1093 break;
1094 } while (true); // The seaward offset etc. loop
1095
1096 // LogStream << m_ulIter << ": left seaward offset loop for cliff collapse at [" << nXCliff << "][" << nYCliff << "] nStartPoint = " << nStartPoint << " nThisPoint = " << nThisPoint << endl << "\tnSeawardOffset = " << nSeawardOffset << " dCliffHeightFrac = " << dCliffHeightFrac << " nDepProfile = " << nDepProfile << " bJustDepositWhatWeCan = " << bJustDepositWhatWeCan << endl << "\tdTargetSandToDepositOnThisProfile = " << dTargetSandToDepositOnThisProfile << " dSandDepositedOnThisProfile = " << dSandDepositedOnThisProfile << " dTotSandToDepositAllProfiles = " << dTotSandToDepositAllProfiles << " dTotSandDepositedAllProfiles = " << dTotSandDepositedAllProfiles << endl << "\tdTargetCoarseToDepositOnThisProfile = " << dTargetCoarseToDepositOnThisProfile << " dCoarseDepositedOnThisProfile = " << dCoarseDepositedOnThisProfile << " dTotCoarseToDepositAllProfiles = " << dTotCoarseToDepositAllProfiles << " dTotCoarseDepositedAllProfiles = " << dTotCoarseDepositedAllProfiles << endl;
1097
1098 // Have we deposited enough for this cliff collapse?
1099 if (bDoSandDepositionOnThisProfile)
1100 {
1101 if (bFPIsEqual(dTotSandToDepositAllProfiles - dTotSandDepositedAllProfiles, 0.0, MASS_BALANCE_TOLERANCE))
1102 bSandDepositionCompletedOnThisProfile = true;
1103 }
1104
1105 if (bDoCoarseDepositionOnThisProfile)
1106 {
1107 if (bFPIsEqual(dTotCoarseToDepositAllProfiles - dTotCoarseDepositedAllProfiles, 0.0, MASS_BALANCE_TOLERANCE))
1108 bCoarseDepositionCompletedOnThisProfile = true;
1109 }
1110
1111 if (bSandDepositionCompletedOnThisProfile && bCoarseDepositionCompletedOnThisProfile)
1112 {
1113 // LogStream << m_ulIter << ": bSandDepositionCompletedOnThisProfile && bCoarseDepositionCompletedOnThisProfile for cliff collapse at [" << nXCliff << "][" << nYCliff << "] nStartPoint = " << nStartPoint << " nThisPoint = " << nThisPoint << endl << "\tnbJustDepositWhatWeCan = " << bJustDepositWhatWeCan << " SeawardOffset = " << nSeawardOffset << " dCliffHeightFrac = " << dCliffHeightFrac << " nDepProfile = " << nDepProfile << endl << "\tdTargetSandToDepositOnThisProfile = " << dTargetSandToDepositOnThisProfile << " dSandDepositedOnThisProfile = " << dSandDepositedOnThisProfile << " dTotSandToDepositAllProfiles = " << dTotSandToDepositAllProfiles << " dTotSandDepositedAllProfiles = " << dTotSandDepositedAllProfiles << endl << "\tdTargetCoarseToDepositOnThisProfile = " << dTargetCoarseToDepositOnThisProfile << " dCoarseDepositedOnThisProfile = " << dCoarseDepositedOnThisProfile << " dTotCoarseToDepositAllProfiles = " << dTotCoarseToDepositAllProfiles << " dTotCoarseDepositedAllProfiles = " << dTotCoarseDepositedAllProfiles << endl;
1114 }
1115 } // Process each deposition profile
1116
1117 // Safety check for sand sediment
1118 if (! bFPIsEqual((dTotSandToDepositAllProfiles - dTotSandDepositedAllProfiles), 0.0, MASS_BALANCE_TOLERANCE))
1119 LogStream << ERR << m_ulIter << ": non-zero dTotSandToDepositAllProfiles = " << dTotSandToDepositAllProfiles << endl;
1120
1121 // Ditto for coarse sediment
1122 if (! bFPIsEqual((dTotCoarseToDepositAllProfiles - dTotCoarseDepositedAllProfiles), 0.0, MASS_BALANCE_TOLERANCE))
1123 LogStream << ERR << m_ulIter << ": non-zero dTotCoarseToDepositAllProfiles = " << dTotCoarseToDepositAllProfiles << endl;
1124
1125 // Store the total depths of cliff collapse deposition for this polygon
1126 pPolygon->AddCliffCollapseUnconsSandDeposition(dTotSandDepositedAllProfiles);
1127 pPolygon->AddCliffCollapseUnconsCoarseDeposition(dTotCoarseDepositedAllProfiles);
1128
1129 // Increment this-timestep totals for cliff collapse deposition
1130 m_dThisIterUnconsSandCliffDeposition += dTotSandDepositedAllProfiles;
1131 m_dThisIterUnconsCoarseCliffDeposition += dTotCoarseDepositedAllProfiles;
1132
1133 // LogStream << endl;
1134 // LogStream << "\tdTotSandToDepositAllProfiles = " << dTotSandToDepositAllProfiles << " dTotSandDepositedAllProfiles = " << dTotSandDepositedAllProfiles << endl;
1135 // LogStream << "\tdTotCoarseToDepositAllProfiles = " << dTotCoarseToDepositAllProfiles << " dTotCoarseDepositedAllProfiles = " << dTotCoarseDepositedAllProfiles << endl;
1136 // LogStream << endl << "****************************************" << endl << endl;
1137
1138 return RTN_OK;
1139}
1140
1141//===============================================================================================================================
1143//===============================================================================================================================
1144void CSimulation::RasterizeCliffCollapseProfile(vector<CGeom2DPoint> const* pVPointsIn, vector<CGeom2DIPoint>* pVIPointsOut) const
1145{
1146 pVIPointsOut->clear();
1147
1148 // The start point of the normal is the centroid of a coastline cell. Convert from the external CRS to grid CRS
1149 double const dXStart = dExtCRSXToGridX(pVPointsIn->at(0).dGetX());
1150 double const dYStart = dExtCRSYToGridY(pVPointsIn->at(0).dGetY());
1151
1152 // The end point of the normal, again convert from the external CRS to grid CRS. Note too that it could be off the grid
1153 double const dXEnd = dExtCRSXToGridX(pVPointsIn->at(1).dGetX());
1154 double const dYEnd = dExtCRSYToGridY(pVPointsIn->at(1).dGetY());
1155
1156 // Interpolate between cells by a simple DDA line algorithm, see http://en.wikipedia.org/wiki/Digital_differential_analyzer_(graphics_algorithm) Note that Bresenham's algorithm gave occasional gaps
1157 double dXInc = dXEnd - dXStart;
1158 double dYInc = dYEnd - dYStart;
1159 double const dLength = tMax(tAbs(dXInc), tAbs(dYInc));
1160
1161 dXInc /= dLength;
1162 dYInc /= dLength;
1163
1164 double dX = dXStart;
1165 double dY = dYStart;
1166
1167 // Process each interpolated point
1168 int const nLength = nRound(dLength);
1169
1170 for (int m = 0; m <= nLength; m++)
1171 {
1172 int nX = nRound(dX);
1173 int nY = nRound(dY);
1174
1175 // Make sure the interpolated point is within the raster grid (can get this kind of problem due to rounding)
1176 if (! bIsWithinValidGrid(nX, nY))
1177 KeepWithinValidGrid(nRound(dXStart), nRound(dYStart), nX, nY);
1178
1179 // This point is fine, so append it to the output vector
1180 pVIPointsOut->push_back(CGeom2DIPoint(nX, nY)); // In raster grid coordinates
1181
1182 // And increment for next time
1183 dX += dXInc;
1184 dY += dYInc;
1185 }
1186}
Contains CGeom2DPoint definitions.
Abstract class, used as a base class for landform objects on the coastline.
int nGetPointOnCoast(void) const
Get the point on the coast on which this coast landform sits.
int nGetLandFormCategory(void) const
Get the landform category.
void IncTotAccumWaveEnergy(double const)
Increment total accumulated wave energy.
CGeom2DIPoint * pPtiGetCellMarkedAsLF(void) const
Get the grid coordinates of the cell on which this coast landform sits.
Geometry class used to represent 2D point objects with integer coordinates.
Definition 2di_point.h:29
int nGetY(void) const
Returns the CGeom2DIPoint object's integer Y coordinate.
Definition 2di_point.cpp:55
int nGetX(void) const
Returns the CGeom2DIPoint object's integer X coordinate.
Definition 2di_point.cpp:49
Geometry class used to represent 2D point objects with floating-point coordinates.
Definition 2d_point.h:27
void SetY(double const)
The double parameter sets a value for the CGeom2DIPoint object's Y coordinate.
Definition 2d_point.cpp:65
void SetX(double const)
The double parameter sets a value for the CGeom2DIPoint object's X coordinate.
Definition 2d_point.cpp:59
Geometry class used for coast polygon objects.
void AddCliffCollapseUnconsCoarseDeposition(double const)
Add to the this-iteration total of unconsolidated coarse sediment deposited from cliff collapse on th...
void AddCliffCollapseToSuspensionFine(double const)
Add to the this-iteration total of unconsolidated fine sediment from cliff collapse which goes to sus...
void AddCliffCollapseUnconsSandDeposition(double const)
Add to the this-iteration total of unconsolidated sand sediment deposited from cliff collapse on this...
void AddCliffCollapseErosionCoarse(double const)
Add to the this-iteration total of unconsolidated coarse sediment from cliff collapse on this polygon...
void AddCliffCollapseSandErodedDeanProfile(double const)
Add to the this-iteration total of unconsolidated sand sediment eroded during deposition of cliff col...
void AddCliffCollapseErosionFine(double const)
Add to the this-iteration total of unconsolidated fine sediment eroded from cliff collapse on this po...
void AddCliffCollapseCoarseErodedDeanProfile(double const)
Add to the this-iteration total of unconsolidated coarse sediment eroded during deposition of cliff c...
void AddCliffCollapseErosionSand(double const)
Add to the this-iteration total of unconsolidated sand sediment from cliff collapse on this polygon,...
Real-world class used to represent the landform of a cell.
int nGetLFCategory(void) const
Get the landform category.
void SetLFSubCategory(int const)
Set the both the landform sub-category, and the landform category.
Real-world class used to represent the 'cliff' category of coastal landform object.
Definition cliff.h:33
bool bReadyToCollapse(double const) const
Returns true if the horizontal depth of the erosional notch exceeds the critical notch overhang.
Definition cliff.cpp:102
void DeepenErosionalNotch(double const)
Increases the XY-plane length (in external CRS units) of the erosional notch, measured inland from th...
Definition cliff.cpp:112
double dGetNotchBaseElev(void) const
Returns the elevation of the base of the erosional notch.
Definition cliff.cpp:72
void SetNotchBaseElev(double const)
Sets the elevation of the base of the erosional notch.
Definition cliff.cpp:78
void SetCliffCollapsed(void)
Flags the cliff as having collapsed.
Definition cliff.cpp:66
double m_dCliffDepositionPlanviewWidth
Planview width of cliff collapse talus (m)
Definition simulation.h:919
int m_nLogFileDetail
The level of detail in the log file output. Can be LOG_FILE_LOW_DETAIL, LOG_FILE_MIDDLE_DETAIL,...
Definition simulation.h:574
double m_dNotchDepthAtCollapse
Notch overhang (i.e. length of horizontal incision) to initiate collapse (m)
Definition simulation.h:910
CGeomRasterGrid * m_pRasterGrid
Pointer to the raster grid object.
void RasterizeCliffCollapseProfile(vector< CGeom2DPoint > const *, vector< CGeom2DIPoint > *) const
Given the start and end points of a cliff-collapse normal profile, returns an output vector of cells ...
int nDoCliffCollapseDeposition(int const, CRWCliff const *, double const, double const, double const, double const)
Redistributes the sand-sized and coarse-sized sediment from a cliff collapse onto the foreshore,...
ofstream LogStream
vector< CRWCoast > m_VCoast
The coastline objects.
double m_dFineErodibilityNormalized
Relative erodibility of fine unconsolidated beach sediment, normalized.
Definition simulation.h:796
double m_dThisIterCliffCollapseFineErodedDuringDeposition
Total fine sediment eroded during Dean profile deposition of talus following cliff collapse (depth in...
Definition simulation.h:877
double m_dCliffTalusMinDepositionLength
Planview length of cliff deposition talus (m)
Definition simulation.h:922
double m_dCoarseErodibilityNormalized
Relative erodibility of coarse unconsolidated beach sediment, normalized.
Definition simulation.h:802
void KeepWithinValidGrid(int &, int &) const
double m_dThisIterCliffCollapseErosionCoarseUncons
This-iteration total of coarse unconsolidated sediment produced by cliff collapse (m^3)
Definition simulation.h:934
double m_dThisIterCliffCollapseErosionFineUncons
This-iteration total of fine unconsolidated sediment produced by cliff collapse (m^3)
Definition simulation.h:928
static double dSubtractProfiles(vector< double > const *, vector< double > const *, vector< bool > const *)
Calculate the total elevation difference between every point in two elevation profiles (first profile...
Definition utils.cpp:2605
double m_dNotchBaseBelowSWL
Notch base below SWL (m)
Definition simulation.h:913
double m_dSandErodibilityNormalized
Relative erodibility of sand unconsolidated beach sediment, normalized.
Definition simulation.h:799
double m_dCliffErosionResistance
Resistance of cliff to notch erosion.
Definition simulation.h:907
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:78
int nConvertMetresToNumCells(double const) const
Given a length in m, this returns the rounded equivalent number of cells.
double m_dThisIterUnconsCoarseCliffDeposition
This-iteration total of coarse unconsolidated sediment deposited due to cliff collapse (m^3)
Definition simulation.h:949
double m_dThisIterUnconsSandCliffDeposition
This-iteration total of sand unconsolidated sediment deposited due to cliff collapse (m^3)
Definition simulation.h:946
int nGetCoastNormalEndPoint(int const, int const, int const, CGeom2DPoint const *, double const, CGeom2DPoint *, CGeom2DIPoint *, bool const)
Finds the end point of a coastline-normal line, given the start point on the vector coastline....
double m_dMinCliffTalusHeightFrac
Minimum height of the landward end of cliff collapse talus, as a fraction of cliff elevation.
Definition simulation.h:925
double dExtCRSXToGridX(double const) const
double m_dThisIterFineSedimentToSuspension
Total fine unconsolidated sediment in suspension for this iteration (depth in m)
Definition simulation.h:862
int nDoAllWaveEnergyToCoastLandforms(void)
Update accumulated wave energy in coastal landform objects.
double m_dThisIterCliffCollapseSandErodedDuringDeposition
Total sand sediment eroded during Dean profile deposition of talus following cliff collapse (depth in...
Definition simulation.h:880
double m_dCliffDepositionA
Scale parameter A for cliff deposition (m^(1/3)), may be zero for auto-calculation.
Definition simulation.h:916
int nDoCliffCollapse(int const, CRWCliff *, double &, double &, double &, double &, double &)
Simulates cliff collapse on a single cliff object, which happens when when a notch (incised into a co...
vector< bool > m_bUnconsChangedThisIter
One element per layer: has the consolidated sediment of this layer been changed during this iteration...
double m_dThisIterCliffCollapseErosionFineCons
This-iteration total of fine consolidated sediment produced by cliff collapse (m^3)
Definition simulation.h:937
double m_dCellArea
Area of a cell (in external CRS units)
Definition simulation.h:661
double dExtCRSYToGridY(double const) const
Transforms a Y-axis ordinate in the external CRS to the equivalent Y-axis ordinate in the raster grid...
bool bIsWithinValidGrid(int const, int const) const
double m_dThisIterCliffCollapseErosionSandCons
This-iteration total of sand consolidated sediment produced by cliff collapse (m^3)
Definition simulation.h:940
double m_dThisIterCliffCollapseErosionSandUncons
This-iteration total of sand unconsolidated sediment produced by cliff collapse (m^3)
Definition simulation.h:931
unsigned long m_ulIter
The number of the current iteration (time step)
Definition simulation.h:598
double dGridCentroidXToExtCRSX(int const) const
Definition gis_utils.cpp:68
double m_dCellSide
Length of a cell side (in external CRS units)
Definition simulation.h:658
bool bIsInterventionCell(int const, int const) const
Returns true if the cell is an intervention.
Definition utils.cpp:2954
double m_dThisIterCliffCollapseCoarseErodedDuringDeposition
Total coarse sediment eroded during Dean profile deposition of talus following cliff collapse (depth ...
Definition simulation.h:883
double m_dThisIterCliffCollapseErosionCoarseCons
This-iteration total of coarse consolidated sediment produced by cliff collapse (m^3)
Definition simulation.h:943
static void CalcDeanProfile(vector< double > *, double const, double const, double const, bool const, int const, double const)
Calculates a Dean equilibrium profile h(y) = A * y^(2/3) where h(y) is the distance below the highest...
Definition utils.cpp:2564
vector< bool > m_bConsChangedThisIter
One element per layer: has the consolidated sediment of this layer been changed during this iteration...
Contains CRWCliff definitions.
This file contains global definitions for CoastalME.
int const NO_NONZERO_THICKNESS_LAYERS
Definition cme.h:778
int const INT_NODATA
Definition cme.h:476
T tMin(T a, T b)
Definition cme.h:1265
int const RTN_ERR_CLIFFNOTCH
Definition cme.h:730
double const TOLERANCE
Definition cme.h:823
int const RTN_ERR_NO_TOP_LAYER
Definition cme.h:738
int const LF_SUBCAT_CLIFF_ON_COASTLINE
Definition cme.h:548
int const ELEV_ABOVE_SEDIMENT_TOP
Definition cme.h:777
int const LF_CAT_SEDIMENT_INPUT
Definition cme.h:538
string const ERR
Definition cme.h:902
int const LF_CAT_SEDIMENT_INPUT_SUBMERGED
Definition cme.h:539
int const MAX_SEAWARD_OFFSET_FOR_CLIFF_TALUS
Definition cme.h:478
int const LOG_FILE_MIDDLE_DETAIL
Definition cme.h:491
bool bFPIsEqual(const T d1, const T d2, const T dEpsilon)
Definition cme.h:1303
double const MASS_BALANCE_TOLERANCE
Definition cme.h:826
T tMax(T a, T b)
Definition cme.h:1252
double const CLIFF_COLLAPSE_HEIGHT_INCREMENT
Definition cme.h:831
int const MAX_CLIFF_TALUS_LENGTH
Definition cme.h:477
int const LF_SUBCAT_DRIFT_TALUS
Definition cme.h:553
int const LF_SUBCAT_CLIFF_INLAND
Definition cme.h:549
int const RTN_ERR_CLIFF_NOT_IN_POLYGON
Definition cme.h:761
string const WARN
Definition cme.h:903
double const SEDIMENT_ELEV_TOLERANCE
Definition cme.h:825
int const CLIFF_COLLAPSE_LENGTH_INCREMENT
Definition cme.h:798
int const LOG_FILE_ALL
Definition cme.h:493
int const RTN_OK
Definition cme.h:694
double const DBL_NODATA
Definition cme.h:834
int const RTN_ERR_CLIFFDEPOSIT
Definition cme.h:731
double const DEAN_POWER
Definition cme.h:817
int const LF_CAT_SEDIMENT_INPUT_NOT_SUBMERGED
Definition cme.h:540
int const RTN_ERR_NO_SOLUTION_FOR_ENDPOINT
Definition cme.h:721
int const ELEV_IN_BASEMENT
Definition cme.h:776
int const LF_CAT_CLIFF
Definition cme.h:543
T tAbs(T a)
Definition cme.h:1277
Contains CACoastLandform definitions.
Contains CSimulation definitions.
int nRound(double const d)
Version of the above that returns an int.