diff --git a/BUILDING.md b/BUILDING.md
index 0ccc9a7f4..806b00afa 100644
--- a/BUILDING.md
+++ b/BUILDING.md
@@ -1,42 +1,42 @@
-# Building CoastalME from source
-
-
-Build requirements
---------------------------------------------------------------------------------
-
-The minimum requirements to build CoastalME are:
-
-- CMake >= 3.16, and an associated build system (make, ninja, Visual Studio, etc.)
-- GDAL >= 2.1
-- C++11
-- F2008 compiler
-
-
-CMake (CoastalME versions >= 3.5.0)
---------------------------------------------------------------------------------
-
-Since version 3.5.0, CoastalME can be built using the CMake build system.
-With the CMake build system you can compile and install CoastalME on more or less any
-platform. After unpacking the source distribution archive (or cloning the repository)
-step into the source tree:
-
- cd CoastalME-{VERSION}
-
-Create a build directory and step into it:
-
-
- mkdir build
- cd build
-
-From the build directory you can now configure CMake, build and install the binaries:
-
-
- cmake ..
- cmake --build .
- cmake --build . --target install
-
-Note:
-
- For a minimal build, add these options to the initial ``cmake`` command: ``...``.
- To enable specific DEBUG drivers, add ``....`` or ``...``.
+# Building CoastalME from source
+
+
+Build requirements
+--------------------------------------------------------------------------------
+
+The minimum requirements to build CoastalME are:
+
+- CMake >= 3.16, and an associated build system (make, ninja, Visual Studio, etc.)
+- GDAL >= 2.1
+- C++11
+- F2008 compiler
+
+
+CMake (CoastalME versions >= 3.5.0)
+--------------------------------------------------------------------------------
+
+Since version 3.5.0, CoastalME can be built using the CMake build system.
+With the CMake build system you can compile and install CoastalME on more or less any
+platform. After unpacking the source distribution archive (or cloning the repository)
+step into the source tree:
+
+ cd CoastalME-{VERSION}
+
+Create a build directory and step into it:
+
+
+ mkdir build
+ cd build
+
+From the build directory you can now configure CMake, build and install the binaries:
+
+
+ cmake ..
+ cmake --build .
+ cmake --build . --target install
+
+Note:
+
+ For a minimal build, add these options to the initial ``cmake`` command: ``...``.
+ To enable specific DEBUG drivers, add ``....`` or ``...``.
\ No newline at end of file
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
index 83589b77c..1c661eb9e 100644
--- a/CODE_OF_CONDUCT.md
+++ b/CODE_OF_CONDUCT.md
@@ -1,135 +1,135 @@
-# Code of Conduct
-
-This code of conduct governs how we behave in any CoastalME forum or event and
-whenever we will be judged by our actions. We expect it to be honored by everyone
-who participates in the CoastalME community formally or informally, or claims any
-affiliation with the project.
-
-Introduction
--------------
-
-This code of conduct governs how we behave in any CoastalME forum or event and
-whenever we will be judged by our actions. We expect it to be honored by
-everyone who participates in the CoastalME community formally or informally, or
-claims any affiliation with the CoastalME project.
-
-It applies to in-person events (such as conferences and related social events),
-IRC, public and private mailing lists, the issue tracker, the wiki, blogs,
-Twitter, and any other forums which the community uses for communication and
-interactions.
-
-This code is not exhaustive or complete. It serves to distill our common
-understanding of a collaborative, shared environment and goals. We expect it to
-be followed in spirit as much as in the letter, so that it can enrich all of
-us and the technical communities in which we participate.
-
-Diversity Statement
--------------------
-
-CoastalME welcomes and encourages participation by everyone. We are committed to
-being a community that everyone feels good about joining, and we will always
-work to treat everyone well. No matter how you identify yourself or how others
-perceive you: we welcome you.
-Specific Guidelines
-
-We strive to:
-
-- Be open.
-
- We invite anyone to participate in our community. We preferably use public
- methods of communication for project-related messages, unless discussing
- something sensitive. This applies to messages for help or project-related
- support, too; not only is a public support request much more likely to result
- in an answer to a question, it also makes sure that any inadvertent mistakes
- made by people answering will be more easily detected and corrected.
-
-- Be empathetic, welcoming, friendly, and patient.
-
- We work together to resolve conflict, assume good intentions, and do our best
- to act in an empathetic fashion. We may all experience some frustration from
- time to time, but we do not allow frustration to turn into a personal attack.
- A community where people feel uncomfortable or threatened is not a productive
- one. Note that we have a multi-cultural, multi-lingual community and some of
- us are non-native speakers. We should be respectful when dealing with other
- community members as well as with people outside our community.
-
-- Be collaborative.
-
- Our work will be used by other people, and in turn we will depend on the work
- of others. When we make something for the benefit of CoastalME, we are willing to
- explain to others how it works, so that they can build on the work to make it
- even better. Any decision we make will affect users and colleagues, and we
- take those consequences seriously when making decisions.
-
-- Be inquisitive.
-
- Nobody knows everything! Asking questions early avoids many problems later,
- so questions are encouraged, though they may be directed to the appropriate
- forum. Those who are asked should be responsive and helpful, within the
- context of our shared goal of improving CoastalME.
-
-- Be careful in the words that we choose.
-
- Whether we are participating as professionals or volunteers, we value
- professionalism in all interactions, and take responsibility for our own
- speech. Be kind to others. Do not insult or put down other participants.
-
-- Be concise.
-
- Keep in mind that what you write once will be read by hundreds of persons.
- Writing a short email means people can understand the conversation as
- efficiently as possible. Short emails should always strive to be empathetic,
- welcoming, friendly and patient. When a long explanation is necessary,
- consider adding a summary.
-
- Try to bring new ideas to a conversation so that each mail adds something
- unique to the thread, keeping in mind that the rest of the thread still
- contains the other messages with arguments that have already been made.
-
- Try to stay on topic, especially in discussions that are already fairly large.
-
-- Step down considerately.
-
- Members of every project come and go. When somebody leaves or disengages
- from the project they should tell people they are leaving and take the proper
- steps to ensure that others can pick up where they left off. In doing so,
- they should remain respectful of those who continue to participate in the
- project and should not misrepresent the project's goals or achievements.
- Likewise, community members should respect any individual's choice to leave
- the project.
-
-Anti-Harassment
----------------
-
-Harassment and other exclusionary behavior are not acceptable.
-This includes, but is not limited to:
-
-- Personal insults or discriminatory jokes and language, especially those using racist or sexist terms.
-- Offensive comments, excessive or unnecessary profanity.
-- Intimidation, violent threats or demands.
-- Sustained disruption of sessions or events.
-- Stalking, harassing photography or recording.
-- Unwelcome physical contact or sexual attention.
-- Repeated harassment of others. In general, if someone asks you to stop, then stop.
-- Posting (or threatening to post) other people's personally identifying information ("doxing").
-- Sharing private content, such as emails sent privately or non-publicly, or unlogged forums such as IRC channel history.
-- Advocating for, or encouraging, any of the above behavior.
-
-Reporting Guidelines
---------------------
-
-If you believe someone is breaking this code of conduct, you may reply to them,
-and point to this code of conduct. Such messages may be in public or in private,
-whatever is most appropriate. Assume good faith; it is more likely that
-participants are unaware of their bad behavior than that they intentionally try
-to degrade the quality of the discussion. Should there be difficulties in
-dealing with the situation, you may report your concerns to event staff, a forum
-leader or the CoastalME Board. Serious or persistent offenders may be expelled from
-the event or forum by event organizers or forum leaders.
-
-To privately email the code of conduct committee leadership use coc@osgeo.org.
-
-Credits
--------
-
+# Code of Conduct
+
+This code of conduct governs how we behave in any CoastalME forum or event and
+whenever we will be judged by our actions. We expect it to be honored by everyone
+who participates in the CoastalME community formally or informally, or claims any
+affiliation with the project.
+
+Introduction
+-------------
+
+This code of conduct governs how we behave in any CoastalME forum or event and
+whenever we will be judged by our actions. We expect it to be honored by
+everyone who participates in the CoastalME community formally or informally, or
+claims any affiliation with the CoastalME project.
+
+It applies to in-person events (such as conferences and related social events),
+IRC, public and private mailing lists, the issue tracker, the wiki, blogs,
+Twitter, and any other forums which the community uses for communication and
+interactions.
+
+This code is not exhaustive or complete. It serves to distill our common
+understanding of a collaborative, shared environment and goals. We expect it to
+be followed in spirit as much as in the letter, so that it can enrich all of
+us and the technical communities in which we participate.
+
+Diversity Statement
+-------------------
+
+CoastalME welcomes and encourages participation by everyone. We are committed to
+being a community that everyone feels good about joining, and we will always
+work to treat everyone well. No matter how you identify yourself or how others
+perceive you: we welcome you.
+Specific Guidelines
+
+We strive to:
+
+- Be open.
+
+ We invite anyone to participate in our community. We preferably use public
+ methods of communication for project-related messages, unless discussing
+ something sensitive. This applies to messages for help or project-related
+ support, too; not only is a public support request much more likely to result
+ in an answer to a question, it also makes sure that any inadvertent mistakes
+ made by people answering will be more easily detected and corrected.
+
+- Be empathetic, welcoming, friendly, and patient.
+
+ We work together to resolve conflict, assume good intentions, and do our best
+ to act in an empathetic fashion. We may all experience some frustration from
+ time to time, but we do not allow frustration to turn into a personal attack.
+ A community where people feel uncomfortable or threatened is not a productive
+ one. Note that we have a multi-cultural, multi-lingual community and some of
+ us are non-native speakers. We should be respectful when dealing with other
+ community members as well as with people outside our community.
+
+- Be collaborative.
+
+ Our work will be used by other people, and in turn we will depend on the work
+ of others. When we make something for the benefit of CoastalME, we are willing to
+ explain to others how it works, so that they can build on the work to make it
+ even better. Any decision we make will affect users and colleagues, and we
+ take those consequences seriously when making decisions.
+
+- Be inquisitive.
+
+ Nobody knows everything! Asking questions early avoids many problems later,
+ so questions are encouraged, though they may be directed to the appropriate
+ forum. Those who are asked should be responsive and helpful, within the
+ context of our shared goal of improving CoastalME.
+
+- Be careful in the words that we choose.
+
+ Whether we are participating as professionals or volunteers, we value
+ professionalism in all interactions, and take responsibility for our own
+ speech. Be kind to others. Do not insult or put down other participants.
+
+- Be concise.
+
+ Keep in mind that what you write once will be read by hundreds of persons.
+ Writing a short email means people can understand the conversation as
+ efficiently as possible. Short emails should always strive to be empathetic,
+ welcoming, friendly and patient. When a long explanation is necessary,
+ consider adding a summary.
+
+ Try to bring new ideas to a conversation so that each mail adds something
+ unique to the thread, keeping in mind that the rest of the thread still
+ contains the other messages with arguments that have already been made.
+
+ Try to stay on topic, especially in discussions that are already fairly large.
+
+- Step down considerately.
+
+ Members of every project come and go. When somebody leaves or disengages
+ from the project they should tell people they are leaving and take the proper
+ steps to ensure that others can pick up where they left off. In doing so,
+ they should remain respectful of those who continue to participate in the
+ project and should not misrepresent the project's goals or achievements.
+ Likewise, community members should respect any individual's choice to leave
+ the project.
+
+Anti-Harassment
+---------------
+
+Harassment and other exclusionary behavior are not acceptable.
+This includes, but is not limited to:
+
+- Personal insults or discriminatory jokes and language, especially those using racist or sexist terms.
+- Offensive comments, excessive or unnecessary profanity.
+- Intimidation, violent threats or demands.
+- Sustained disruption of sessions or events.
+- Stalking, harassing photography or recording.
+- Unwelcome physical contact or sexual attention.
+- Repeated harassment of others. In general, if someone asks you to stop, then stop.
+- Posting (or threatening to post) other people's personally identifying information ("doxing").
+- Sharing private content, such as emails sent privately or non-publicly, or unlogged forums such as IRC channel history.
+- Advocating for, or encouraging, any of the above behavior.
+
+Reporting Guidelines
+--------------------
+
+If you believe someone is breaking this code of conduct, you may reply to them,
+and point to this code of conduct. Such messages may be in public or in private,
+whatever is most appropriate. Assume good faith; it is more likely that
+participants are unaware of their bad behavior than that they intentionally try
+to degrade the quality of the discussion. Should there be difficulties in
+dealing with the situation, you may report your concerns to event staff, a forum
+leader or the CoastalME Board. Serious or persistent offenders may be expelled from
+the event or forum by event organizers or forum leaders.
+
+To privately email the code of conduct committee leadership use coc@osgeo.org.
+
+Credits
+-------
+
CoastalME re-uses the `OSGeo Code of Conduct `__
\ No newline at end of file
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index d2d3a4041..824ac64c9 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,36 +1,36 @@
-# How to contribute?
-
-There are several ways for developers and users to contribute to CoastalME:
-
-- [Contributing code](#contributing-code)
-- [Filing high-quality reports](#filing-high-quality-reports)
-- [Improving documentation](#improving-documentation)
-- [Credits](#credits)
-
-## Contributing code
-
-Minor changes to CoastalME, such as bug fixes, may be made by opening a GitHub pull request.
-
-Major changes should be discussed on the [CoastalME Discussions](https://github.com/apayo/CoastalME/discussions/19#discussion-7445785) and may require the drafting of a RFC (request for comment) document.
-
-CoastalME's policy on substantial code additions is documented at [rfc_process.md](/development/rfc_process.md).
-
-## Filing high-quality issue reports
-
-Using the GitHub [issue reports](https://github.com/apayo/CoastalME/issues) at the Master repository.
-
-## Improving documentation
-
-CoastalME's documentation includes C++ [API documentation](https://codedocs.xyz/apayo/CoastalME/) built automatically from source comments using Doxygen and [CodeDocx.XYZ](https://codedocs.xyz) files containing manually-edited content.
-
-To be correctly parsed, the documentation should follow the [Doxygen block documentation style](https://doxygen.nl/manual/docblocks.html#specialblock)
-
- /*! \brief Brief description.
- * Brief description continued.
- *
- * Detailed description starts here.
- */
-
-## Credits
-
+# How to contribute?
+
+There are several ways for developers and users to contribute to CoastalME:
+
+- [Contributing code](#contributing-code)
+- [Filing high-quality reports](#filing-high-quality-reports)
+- [Improving documentation](#improving-documentation)
+- [Credits](#credits)
+
+## Contributing code
+
+Minor changes to CoastalME, such as bug fixes, may be made by opening a GitHub pull request.
+
+Major changes should be discussed on the [CoastalME Discussions](https://github.com/apayo/CoastalME/discussions/19#discussion-7445785) and may require the drafting of a RFC (request for comment) document.
+
+CoastalME's policy on substantial code additions is documented at [rfc_process.md](/development/rfc_process.md).
+
+## Filing high-quality issue reports
+
+Using the GitHub [issue reports](https://github.com/apayo/CoastalME/issues) at the Master repository.
+
+## Improving documentation
+
+CoastalME's documentation includes C++ [API documentation](https://codedocs.xyz/apayo/CoastalME/) built automatically from source comments using Doxygen and [CodeDocx.XYZ](https://codedocs.xyz) files containing manually-edited content.
+
+To be correctly parsed, the documentation should follow the [Doxygen block documentation style](https://doxygen.nl/manual/docblocks.html#specialblock)
+
+ /*! \brief Brief description.
+ * Brief description continued.
+ *
+ * Detailed description starts here.
+ */
+
+## Credits
+
This section has been largely inspired by https://github.com/OSGeo/gdal
\ No newline at end of file
diff --git a/LICENSE.md b/LICENSE.md
index 8566c3cc9..d929fb5e0 100644
--- a/LICENSE.md
+++ b/LICENSE.md
@@ -1,78 +1,78 @@
-
-# CoastalME Licensing
-
-This file attempts to include all licenses that apply within the CoastalME
-source tree, in particular any that are supposed to be exposed to the end user
-for credit requirements for instance. The contents of this file can be
-displayed from CostalME GitHub Master repository with filename LICENSE.MD
-
-- [CoastalME General](#coastalme-general)
-- [GDAL-OGR General](#gdal-ogr-general)
-- [CSHORE General](#cshore-general)
-
-
-## CoastalME General
-
-The text shown below should be added to all source code.
-
-
- This file is part of CoastalME, the Coastal Modelling Environment.
-
- 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.
-
- 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.
-
- 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.
-
-https://github.com/apayo/CoastalME
-
-## GDAL-OGR General
-
-In general GDAL/OGR is licensed under an MIT style license with the
-following terms:
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the "Software"),
-to deal in the Software without restriction, including without limitation
-the rights to use, copy, modify, merge, publish, distribute, sublicense,
-and/or sell copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included
-in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-DEALINGS IN THE SOFTWARE.
-
-https://github.com/OSGeo/gdal
-
-## CSHORE General
-
-MIT License
-
-Copyright (c) Microsoft Corporation.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE
-
+
+# CoastalME Licensing
+
+This file attempts to include all licenses that apply within the CoastalME
+source tree, in particular any that are supposed to be exposed to the end user
+for credit requirements for instance. The contents of this file can be
+displayed from CostalME GitHub Master repository with filename LICENSE.MD
+
+- [CoastalME General](#coastalme-general)
+- [GDAL-OGR General](#gdal-ogr-general)
+- [CSHORE General](#cshore-general)
+
+
+## CoastalME General
+
+The text shown below should be added to all source code.
+
+
+ This file is part of CoastalME, the Coastal Modelling Environment.
+
+ 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.
+
+ 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.
+
+ 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.
+
+https://github.com/apayo/CoastalME
+
+## GDAL-OGR General
+
+In general GDAL/OGR is licensed under an MIT style license with the
+following terms:
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+https://github.com/OSGeo/gdal
+
+## CSHORE General
+
+MIT License
+
+Copyright (c) Microsoft Corporation.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE
+
https://github.com/erdc/cshore
\ No newline at end of file
diff --git a/TO_DO_LIST.md b/TO_DO_LIST.md
index f42c643bc..32295d033 100644
--- a/TO_DO_LIST.md
+++ b/TO_DO_LIST.md
@@ -1,118 +1,118 @@
-# TO DO LIST
-
-089 is max (also using github permalinks to code lines)
-
-## Table of contents
-- [Documentation]{#documentation)
-- [User input](#user-input)
-- [Error handling](#error-handling)
-- [Theory/Efficiency](#theory-efficiency)
-- [Output](#output)
-- [Completed](#completed)
-
-## Documentation
-- TODO 001 [Add more information about all classes]
-- TODO 007 [Need more info re. setup and surge from Manuel]
-
-## User input
-- TODO 000 [Should user input be split in two main files]
-- TODO 011 Should this constant be a user input?
- [1](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/cme.h#L600-L602)
- [2](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/simulation.cpp#L211)
- [3](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/simulation.cpp#L371)
-- TODO 036 [Read in changed deep water wave values](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/init_grid.cpp#L177)
-- TODO 030 [Do we also need to be able to input landform sub-categories?] [code](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/gis_raster.cpp#L750)
-- TODO 027 [Sort out GDAL problem with raster reference units](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/gis_raster.cpp#L537)
-- TODO 022 [Get intervention update working](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/do_intervention.cpp#L32)
-- TODO 042 [Should we have a smallest valid input for KLS in the CERC equation?] [code](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/read_input.cpp#L2378-L2380)
-- TODO 045 [Method of getting depth of closure value needs to be a user input] [code](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/simulation.h#L771)
-- TODO 049 [Handle other command line parameters e.g. path to .ini file, path to datafile](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/utils.cpp#L125)
-- TODO 035 [Also handle other EPSG for vector spatial reference systems](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/gis_vector.cpp#L492)
-- TODO 054 [Choose more files to omit from "usual" raster output]
-- TODO 069 [Enable ability to represent intervention structures which have their foundation embedded in consolidated sediment. In other words, with the elevation of the base of the intervention structure *below* the top of all consolidated sediment layers. Will need some sanity checking of elevations]
-- TODO 071 [If the user input file format is changed, write a Python script to convert from the old file format to the new]
-- TODO 083 [Get all three kinds of sediment input events working correctly]
-
-## Error handling
-- TODO 038 [Do better error handling if insufficient memory]
-- TODO 004 [Improve error handling of situation where we have a valid shadow zone but cannot find a neighbouring cell which is 'under' the coastline](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/calc_shadow_zones.cpp#L490)
-- TODO 006 [Check GDALGridCreate() with only start-of-coast or an end-of-coast profiles](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/calc_waves.cpp#L214)
-- TODO 009 [Decide what to do when we have eroded down to basement](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/calc_waves.cpp#L214)
-- TODO 017 [Extra safety check needed, make sure that each point is within valid grid](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/do_beach_within_polygon.cpp#L146)
-- TODO 018 [Improve situation where new landwards point on parallel profile is not within the raster grid](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/do_beach_within_polygon.cpp#L222) [2](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/do_beach_within_polygon.cpp#L394)
-- TODO 019 [Improve situation where Dean profile has a near-zero elevation difference](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/do_beach_within_polygon.cpp#L286) [2](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/do_beach_within_polygon.cpp#L394)
-- TODO 020 [Check calculation of elevation of coast point of Dean parallel profile](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/do_beach_within_polygon.cpp#L949) [2](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/do_beach_within_polygon.cpp#L1435)
-- TODO 021 [Improve situation where all layers have zero thickness](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/do_cliff_collapse.cpp#L819)
-- TODO 025 [Improve situation where this point has only zero thickness layers](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/do_shore_platform_erosion.cpp#L195) [2](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/do_shore_platform_erosion.cpp#L508)
-- TODO 026 [Check situation where cell in parallel profile is not in a polygon](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/do_shore_platform_erosion.cpp#L495)
-- TODO 028 [Give a warning if raster input layer has several bands](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/gis_raster.cpp#L605)
-- TODO 038 [Do better error handling if insufficient memory](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/gis_raster.cpp#L71)
-- TODO 053 [Improve handling of situation where landward elevation of profile is -ve](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/calc_waves.cpp#L1581)
-- TODO 055 [Maybe add a safety check?]
-- TODO 080 [Do we get -ve breaking wave heights here?]
-- TODO 084 [Improve handling of situation where consecutive profile points are same distance from shoreline]
-
-## Theory/Efficiency
-- TODO 002 [Do we really need D50 for drift landform class? What do we need for drift?](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/assign_landforms.cpp#L346)
-- TODO 005 [Maybe give every coast point a value for end-of-profile wave height and direction instead of for deep water wave height and direction](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/calc_waves.cpp#L58)
-- TODO 010 [Do we also need to update the active zone cells?](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/calc_waves.cpp#L1828)
-- TODO 012 [Change finding of adjacent polygons, and calculation of the length of shared normals, when we make polygon seaward length determined by depth of closure](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/create_polygons.cpp#L504)
-- TODO 013 [Change calculation (need user input?) of coastline smoothing convexity threshold](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/create_profiles.cpp#L119)
-- TODO 014 [Profile spacing, vould try gradually increasing the profile spacing with increasing concavity, and decreasing the profile spacing with increasing convexity](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/create_profiles.cpp#L396)
-- TODO 016 [Check mass balance for recirculating unconsolidated sediment option](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/do_beach_sediment_movement.cpp#L539)
-- TODO 023 [Only calculate shore platform erosion if cell is in a polygon](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/do_shore_platform_erosion.cpp#L51)
-- TODO 024 [Should we calculate platform erosion on a profile that has hit dry land?](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/do_shore_platform_erosion.cpp#L124)
-- TODO 044 [Implement estuaries. Before we can do this, we will need to deal with multiple coastlines. Will need to get working where profile hits another profile which belongs to a different coast object.](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/create_profiles.cpp#L1478) [2](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/create_profiles.cpp#L1537)
-- TODO 037 [Need more info on nFindIndex](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/interpolate.cpp#L103-L121)
-- TODO 051 [Implement other ways of calculating depth of closure, see TODO 045](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/utils.cpp#L2482-L2493)
-- TODO 056 [Check this please Andres]
-- TODO 059 [Implement dune landform class]
-- TODO 060 [Remove 'magic numbers' from code here]
-- TODO 061 [Is this safety check to depth of breaking a reasonable thing to do?]
-- TODO 066 [Should this be for all layers? Check]
-- TODO 067 [Is this ever non-zero? Check]
-- TODO 070 [Change CShore to use allocatable arrays (https://fortran-lang.org/en/learn/best_practices/allocatable_arrays/) so that the number of points in the CShore output profiles can either be a user input, or determined by e.g. the physical length of the profile]
-- TODO 075 [What if bedrock protrudes above Dean profile?]
-- TODO 076 [When doing parallel profiles, start from the profile which is closest to a right angle with the coast]
-- TODO 077 [As traverse between the bounding profiles creating parallel profiles, gradually change the parallel profile orientation based on distance weighting of two bounding profiles]
-- TODO 078 [At present, we don't allow cliff collapse onto interventions. Is this realistic? Should it change with different types of intervention?]
-- TODO 089 [Why do we get patches of sediment in the sea?]
- TODO 086 [Try alternatives to GDALGridCreate(), e.g. https://gts.sourceforge.net/index.html, https://doc.cgal.org/latest/Triangulation_2/index.html#Chapter_2D_Triangulations]
- TODO 088 [In (almost) all whole-grid loops, immediately continue if cell is hinterland (but not when calculating cliff collapse)]
-
-## Output
-- TODO 065 [Get GPKG output working]
-- TODO 063 [Add NetCDF support, see https://trac.osgeo.org/gdal/wiki/NetCDF]
-- TODO 064 [Add support for grids that are not oriented N-S and W-E, but are still rectangular (will need to add a transformation in the reading and writing process, the first to bring it to the local base and the second to save it in global coordinates)]
-- TODO 031 [Get raster slice output working with multiple slices](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/gis_raster.cpp#L1122-L1125)
-- TODO 032 [Improve output scaling for DBL_NODATA situation](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/gis_raster.cpp#L1617)
-- TODO 033 [Also test and configure (e.g. by passing open() options) other vector output file formats](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/gis_utils.cpp#L893)
-- TODO 034 [Also test and configure (e.g. by passing open() options) other raster output file formats](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/gis_utils.cpp#L1642)
-- TODO 043 [When outputting profiles, how do we deal with randomness of profile spacing (since profile location is determined by curvature)?]
-- TODO 052 [Improve saving of profiles and parallel profiles]
-- TODO 062 [Show end-of-iteration number of cells with sediment somewhere]
-- TODO 068 [Only show output in log file that is relevant to processes being simulated]
-- TODO 074 [Output history of what landforms are on a particular cell or cells. User inputs cell(s), how?]
-- TODO 082 [Also show m_dStartIterUnconsFineAllCells etc. in log file]
-
-## Completed
-- TODO 003 [Make coastline curvature moving window size a user input DONE in 1.1.22]
-- TODO 046 [Why is cliff collapse eroded during deposition (three size classes) no longer calculated? DONE IN 1.1.22]
-- TODO 058 [Dave to check this DONE in 1.1.22]
-- TODO 039 [Rewrite reading of multiple random number seeds DONE in 1.2.1, 8 Nov 2024]
-- TODO 041 [Read in SWL per-timestep]
-- BUG 002 [Useless output e.g. clay layers even if no clay input DONE in 1.1.21]
-- BUG 003 [Use mean SWL for elevations of Dean profiles DONE in 1.2.1, 27 Nov 2024]
-- BUG 004 [Don't smooth intervention coastline DONE 1.2.1, 27 Nov 2024]
-- TODO 073 [If output dir does not exist, then create it (ask user first) DONE 1.2.2, 28 Nov 2024]
-- TODO 047 [Where is the GDAL description for the deep water wave stations vector file? DONE 1.2.3, 2 Dec 2024]
-- TODO 048 [Where is the GDAL description for the flood input locations point or vector file? DONE 1.2.3, 2 Dec 2024]
-- TODO 027 [Sort out GDAL problem with raster reference units DONE 1.2.3, 2 Dec 2024]
-- TODO 079 [Do sanity checking on wave and tide input DONE 1.2.3, 2 Dec 2024]
-- TODO 072 [CShore crashes occasionally, is it because of -ve Z values here? DONE 1.2.3, 2 Dec 2024]
-- TODO 050 [Update for recent versions of Windows DONE 1.2.3, 2 Dec 2024]
-- TODO 037 [Need more info on nFindIndex() DONE 1.2.3, 2 Dec 2024]
-- [Improve coast normals DONE 1.2.3, 20 Dec 2024]
-- TODO 057 [Check this please Manuel DONE 1.2.4, 4 Jan 2025]
-- TODO 087 [Is there a problem if profile is not long enough for user-input depth of closure? DONE 1.3.0 2 Feb 2025]
-
+# TO DO LIST
+
+089 is max (also using github permalinks to code lines)
+
+## Table of contents
+- [Documentation]{#documentation)
+- [User input](#user-input)
+- [Error handling](#error-handling)
+- [Theory/Efficiency](#theory-efficiency)
+- [Output](#output)
+- [Completed](#completed)
+
+## Documentation
+- TODO 001 [Add more information about all classes]
+- TODO 007 [Need more info re. setup and surge from Manuel]
+
+## User input
+- TODO 000 [Should user input be split in two main files]
+- TODO 011 Should this constant be a user input?
+ [1](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/cme.h#L600-L602)
+ [2](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/simulation.cpp#L211)
+ [3](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/simulation.cpp#L371)
+- TODO 036 [Read in changed deep water wave values](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/init_grid.cpp#L177)
+- TODO 030 [Do we also need to be able to input landform sub-categories?] [code](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/gis_raster.cpp#L750)
+- TODO 027 [Sort out GDAL problem with raster reference units](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/gis_raster.cpp#L537)
+- TODO 022 [Get intervention update working](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/do_intervention.cpp#L32)
+- TODO 042 [Should we have a smallest valid input for KLS in the CERC equation?] [code](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/read_input.cpp#L2378-L2380)
+- TODO 045 [Method of getting depth of closure value needs to be a user input] [code](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/simulation.h#L771)
+- TODO 049 [Handle other command line parameters e.g. path to .ini file, path to datafile](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/utils.cpp#L125)
+- TODO 035 [Also handle other EPSG for vector spatial reference systems](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/gis_vector.cpp#L492)
+- TODO 054 [Choose more files to omit from "usual" raster output]
+- TODO 069 [Enable ability to represent intervention structures which have their foundation embedded in consolidated sediment. In other words, with the elevation of the base of the intervention structure *below* the top of all consolidated sediment layers. Will need some sanity checking of elevations]
+- TODO 071 [If the user input file format is changed, write a Python script to convert from the old file format to the new]
+- TODO 083 [Get all three kinds of sediment input events working correctly]
+
+## Error handling
+- TODO 038 [Do better error handling if insufficient memory]
+- TODO 004 [Improve error handling of situation where we have a valid shadow zone but cannot find a neighbouring cell which is 'under' the coastline](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/calc_shadow_zones.cpp#L490)
+- TODO 006 [Check GDALGridCreate() with only start-of-coast or an end-of-coast profiles](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/calc_waves.cpp#L214)
+- TODO 009 [Decide what to do when we have eroded down to basement](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/calc_waves.cpp#L214)
+- TODO 017 [Extra safety check needed, make sure that each point is within valid grid](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/do_beach_within_polygon.cpp#L146)
+- TODO 018 [Improve situation where new landwards point on parallel profile is not within the raster grid](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/do_beach_within_polygon.cpp#L222) [2](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/do_beach_within_polygon.cpp#L394)
+- TODO 019 [Improve situation where Dean profile has a near-zero elevation difference](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/do_beach_within_polygon.cpp#L286) [2](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/do_beach_within_polygon.cpp#L394)
+- TODO 020 [Check calculation of elevation of coast point of Dean parallel profile](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/do_beach_within_polygon.cpp#L949) [2](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/do_beach_within_polygon.cpp#L1435)
+- TODO 021 [Improve situation where all layers have zero thickness](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/do_cliff_collapse.cpp#L819)
+- TODO 025 [Improve situation where this point has only zero thickness layers](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/do_shore_platform_erosion.cpp#L195) [2](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/do_shore_platform_erosion.cpp#L508)
+- TODO 026 [Check situation where cell in parallel profile is not in a polygon](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/do_shore_platform_erosion.cpp#L495)
+- TODO 028 [Give a warning if raster input layer has several bands](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/gis_raster.cpp#L605)
+- TODO 038 [Do better error handling if insufficient memory](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/gis_raster.cpp#L71)
+- TODO 053 [Improve handling of situation where landward elevation of profile is -ve](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/calc_waves.cpp#L1581)
+- TODO 055 [Maybe add a safety check?]
+- TODO 080 [Do we get -ve breaking wave heights here?]
+- TODO 084 [Improve handling of situation where consecutive profile points are same distance from shoreline]
+
+## Theory/Efficiency
+- TODO 002 [Do we really need D50 for drift landform class? What do we need for drift?](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/assign_landforms.cpp#L346)
+- TODO 005 [Maybe give every coast point a value for end-of-profile wave height and direction instead of for deep water wave height and direction](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/calc_waves.cpp#L58)
+- TODO 010 [Do we also need to update the active zone cells?](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/calc_waves.cpp#L1828)
+- TODO 012 [Change finding of adjacent polygons, and calculation of the length of shared normals, when we make polygon seaward length determined by depth of closure](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/create_polygons.cpp#L504)
+- TODO 013 [Change calculation (need user input?) of coastline smoothing convexity threshold](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/create_profiles.cpp#L119)
+- TODO 014 [Profile spacing, vould try gradually increasing the profile spacing with increasing concavity, and decreasing the profile spacing with increasing convexity](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/create_profiles.cpp#L396)
+- TODO 016 [Check mass balance for recirculating unconsolidated sediment option](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/do_beach_sediment_movement.cpp#L539)
+- TODO 023 [Only calculate shore platform erosion if cell is in a polygon](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/do_shore_platform_erosion.cpp#L51)
+- TODO 024 [Should we calculate platform erosion on a profile that has hit dry land?](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/do_shore_platform_erosion.cpp#L124)
+- TODO 044 [Implement estuaries. Before we can do this, we will need to deal with multiple coastlines. Will need to get working where profile hits another profile which belongs to a different coast object.](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/create_profiles.cpp#L1478) [2](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/create_profiles.cpp#L1537)
+- TODO 037 [Need more info on nFindIndex](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/interpolate.cpp#L103-L121)
+- TODO 051 [Implement other ways of calculating depth of closure, see TODO 045](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/utils.cpp#L2482-L2493)
+- TODO 056 [Check this please Andres]
+- TODO 059 [Implement dune landform class]
+- TODO 060 [Remove 'magic numbers' from code here]
+- TODO 061 [Is this safety check to depth of breaking a reasonable thing to do?]
+- TODO 066 [Should this be for all layers? Check]
+- TODO 067 [Is this ever non-zero? Check]
+- TODO 070 [Change CShore to use allocatable arrays (https://fortran-lang.org/en/learn/best_practices/allocatable_arrays/) so that the number of points in the CShore output profiles can either be a user input, or determined by e.g. the physical length of the profile]
+- TODO 075 [What if bedrock protrudes above Dean profile?]
+- TODO 076 [When doing parallel profiles, start from the profile which is closest to a right angle with the coast]
+- TODO 077 [As traverse between the bounding profiles creating parallel profiles, gradually change the parallel profile orientation based on distance weighting of two bounding profiles]
+- TODO 078 [At present, we don't allow cliff collapse onto interventions. Is this realistic? Should it change with different types of intervention?]
+- TODO 089 [Why do we get patches of sediment in the sea?]
+ TODO 086 [Try alternatives to GDALGridCreate(), e.g. https://gts.sourceforge.net/index.html, https://doc.cgal.org/latest/Triangulation_2/index.html#Chapter_2D_Triangulations]
+ TODO 088 [In (almost) all whole-grid loops, immediately continue if cell is hinterland (but not when calculating cliff collapse)]
+
+## Output
+- TODO 065 [Get GPKG output working]
+- TODO 063 [Add NetCDF support, see https://trac.osgeo.org/gdal/wiki/NetCDF]
+- TODO 064 [Add support for grids that are not oriented N-S and W-E, but are still rectangular (will need to add a transformation in the reading and writing process, the first to bring it to the local base and the second to save it in global coordinates)]
+- TODO 031 [Get raster slice output working with multiple slices](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/gis_raster.cpp#L1122-L1125)
+- TODO 032 [Improve output scaling for DBL_NODATA situation](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/gis_raster.cpp#L1617)
+- TODO 033 [Also test and configure (e.g. by passing open() options) other vector output file formats](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/gis_utils.cpp#L893)
+- TODO 034 [Also test and configure (e.g. by passing open() options) other raster output file formats](https://github.com/coastalme/coastalme/blob/730a0be2274de02125681ab3e14424dbbfadbaeb/src/gis_utils.cpp#L1642)
+- TODO 043 [When outputting profiles, how do we deal with randomness of profile spacing (since profile location is determined by curvature)?]
+- TODO 052 [Improve saving of profiles and parallel profiles]
+- TODO 062 [Show end-of-iteration number of cells with sediment somewhere]
+- TODO 068 [Only show output in log file that is relevant to processes being simulated]
+- TODO 074 [Output history of what landforms are on a particular cell or cells. User inputs cell(s), how?]
+- TODO 082 [Also show m_dStartIterUnconsFineAllCells etc. in log file]
+
+## Completed
+- TODO 003 [Make coastline curvature moving window size a user input DONE in 1.1.22]
+- TODO 046 [Why is cliff collapse eroded during deposition (three size classes) no longer calculated? DONE IN 1.1.22]
+- TODO 058 [Dave to check this DONE in 1.1.22]
+- TODO 039 [Rewrite reading of multiple random number seeds DONE in 1.2.1, 8 Nov 2024]
+- TODO 041 [Read in SWL per-timestep]
+- BUG 002 [Useless output e.g. clay layers even if no clay input DONE in 1.1.21]
+- BUG 003 [Use mean SWL for elevations of Dean profiles DONE in 1.2.1, 27 Nov 2024]
+- BUG 004 [Don't smooth intervention coastline DONE 1.2.1, 27 Nov 2024]
+- TODO 073 [If output dir does not exist, then create it (ask user first) DONE 1.2.2, 28 Nov 2024]
+- TODO 047 [Where is the GDAL description for the deep water wave stations vector file? DONE 1.2.3, 2 Dec 2024]
+- TODO 048 [Where is the GDAL description for the flood input locations point or vector file? DONE 1.2.3, 2 Dec 2024]
+- TODO 027 [Sort out GDAL problem with raster reference units DONE 1.2.3, 2 Dec 2024]
+- TODO 079 [Do sanity checking on wave and tide input DONE 1.2.3, 2 Dec 2024]
+- TODO 072 [CShore crashes occasionally, is it because of -ve Z values here? DONE 1.2.3, 2 Dec 2024]
+- TODO 050 [Update for recent versions of Windows DONE 1.2.3, 2 Dec 2024]
+- TODO 037 [Need more info on nFindIndex() DONE 1.2.3, 2 Dec 2024]
+- [Improve coast normals DONE 1.2.3, 20 Dec 2024]
+- TODO 057 [Check this please Manuel DONE 1.2.4, 4 Jan 2025]
+- TODO 087 [Is there a problem if profile is not long enough for user-input depth of closure? DONE 1.3.0 2 Feb 2025]
+
diff --git a/cme.ini b/cme.ini
index 61dcba4db..4060e515f 100644
--- a/cme.ini
+++ b/cme.ini
@@ -2,7 +2,7 @@
;
; Initialization file for CoastalME
;
-; Copyright (C) 2024 David Favis-Mortlock and Andres Payo
+; Copyright (C) 2025 David Favis-Mortlock and Andres Payo
;
;=====================================================================================================================
;
@@ -17,10 +17,11 @@
; Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
;
;======================================================================================================================
-Input data file (path and name) : /Users/wilfchun/Documents/GitHub/CoastalME/CoastalME_data_local/CSE/Thorpness/in/thorpness.yaml
+Input data file (path and name) : in/test_suite/minimal_cons_wave_angle_230/minimal.dat
;======================================================================================================================
-Path for output :/Users/wilfchun/Documents/GitHub/CoastalME/CoastalME_data_local/CSE/Thorpness/out/
+
+Path for output : out/test_suite/minimal_cons_wave_angle_230/
;======================================================================================================================
diff --git a/src/cell.h b/src/cell.h
index d7139ec4a..9ce3c31e3 100644
--- a/src/cell.h
+++ b/src/cell.h
@@ -1,438 +1,438 @@
-/*!
- \class CGeomCell
- \brief Geometry class for the cell objects which comprise the raster grid
- \details TODO 001 This is a more detailed description of the CGeomCell class.
- \author David Favis-Mortlock
- \author Andres Payo
- \date 2025
- \copyright GNU General Public License
- \file cell.h
- \brief Contains CGeomCell definitions
-
-*/
-
-#ifndef CELL_H
-#define CELL_H
-/* ===============================================================================================================================
- This file is part of CoastalME, the Coastal Modelling Environment.
-
- 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.
-
- 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.
-
- 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.
-===============================================================================================================================*/
-#include
-using std::vector;
-
-#include "cell_landform.h"
-#include "cell_layer.h"
-#include "cme.h"
-#include "raster_grid.h"
-
-class CGeomRasterGrid; // Forward declaration
-
-class CGeomCell
-{
- friend class CSimulation;
-
- private:
- //! Switch to indicate if this is a sea cell, contiguous with other sea cells
- bool m_bInContiguousSea;
-
- //! Switch to indicate that this cell is in the contiguous runup flood area
- bool m_bInContiguousFlood;
-
- //! Switch to indicate that this cell is in the active zone
- bool m_bIsInActiveZone;
-
- //! Is this cell a cliff toe?
- bool m_bCliffToe;
-
- //! Switch to indicate that this cell is 'under' a runup flood line TODO 007 Finish surge and runup stuff
- bool m_bFloodLine;
-
- //! Switch to indicate that this cell is 'under' a runup wave flood line TODO 007 Finish surge and runup stuff
- bool m_bWaveFlood;
-
- // //! TODO 007 Finish surge and runup stuff
- // bool m_bCheckCell;
-
- //! TODO 007 Finish surge and runup stuff
- bool m_bCheckFloodCell;
-
- //! Switch to show this cell is 'under' a shadow boundary
- bool m_bShadowBoundary;
-
- //! Switch to show that this cell could be the start of a coastline
- bool m_bPossibleCoastStartCell;
-
- //! TODO 007 Finish surge and runup stuff
- bool m_bPossibleFloodStartCell;
-
- //! TODO 007 Finish surge and runup stuff
- bool m_bFloodBySetupSurge;
-
- //! TODO 007 Finish surge and runup stuff
- bool m_bFloodBySetupSurgeRunup;
-
- //! If this cell is an edge (or bounding box) cell, this specifies the edge
- int m_nBoundingBoxEdge;
-
- //! If this cell is 'under' a coastline, this is the ID number of the coast
- int m_nCoastlineID;
-
- //! If this cell is 'under' a coast-normal profile, this is the ID number of the profile
- int m_nProfileID;
-
- //! If this cell is 'under' a coast-normal profile, this is the ID number of the profile's coast
- int m_nProfileCoastID;
-
- //! If this cell is within a polygon, this is the ID of the polygon
- int m_nPolygonID;
-
- //! If this cell is within a polygon, this is the ID number of the polygon's coast
- int m_nPolygonCoastID;
-
- //! If this cell is 'under' a coastline normal, this is the number of the normal
- int m_nCoastlineNormal;
-
- //! If this cell is within a shadow zone, this is the ID number of the shadow zone
- int m_nShadowZoneNumber;
-
- //! If this cell is within a downdrift zone, this is the ID number of the downdrift zone
- int m_nDownDriftZoneNumber;
-
- //! Used in erosion calculations, stored here for display purposes
- double m_dLocalConsSlope;
-
- //! Elevation of basement surface (m)
- double m_dBasementElevation;
-
- //! Slope at this cell (degrees or unitless)
- double m_dSlopeForCliffToe;
-
- //! Depth of still water (m), is zero if not inundated
- double m_dSeaDepth;
-
- //! Total depth of still water (m) since beginning of simulation (used to calc average)
- double m_dTotSeaDepth;
-
- //! Wave height (m)
- double m_dWaveHeight;
-
- //! Total wave height (m) (used to calc average)
- double m_dTotWaveHeight;
-
- //! Wave orientation
- double m_dWaveAngle;
-
- //! Wave period (s)
- double m_dWavePeriod;
-
- //! Total wave orientation (used to calc average)
- double m_dTotWaveAngle;
-
- //! Wave height if this is a deep water cell
- double m_dDeepWaterWaveHeight;
-
- //! Wave orientation if this is a deep water cell
- double m_dDeepWaterWaveAngle;
-
- //! Wave period if this is a deep water cell
- double m_dDeepWaterWavePeriod;
-
- //! Only meaningful if in zone of platform erosion. 0 = fully protected; 1 = ! no protection
- double m_dBeachProtectionFactor;
-
- //! Suspended sediment as depth equivalent (m)
- double m_dSuspendedSediment;
-
- //! Total depth of suspended sediment (m) since simulation start (used to calc average)
- double m_dTotSuspendedSediment;
-
- //! Depth of sediment on the shore platform that could be eroded this timestep, if no supply-limitation
- double m_dPotentialPlatformErosionThisIter;
-
- //! Total depth of sediment eroded from the shore platform, if no supply-limitation
- double m_dTotPotentialPlatformErosion;
-
- //! Depth of sediment actually eroded from the shore platform this timestep
- double m_dActualPlatformErosionThisIter;
-
- //! Total depth of sediment actually eroded from the shore platform
- double m_dTotActualPlatformErosion;
-
- //! Depth of fine sediment (consolidated and unconsolidated) removed via cliff collapse this timestep
- double m_dCliffCollapseFineThisIter;
-
- //! Depth of sand sediment (consolidated and unconsolidated) removed via cliff collapse this timestep
- double m_dCliffCollapseSandThisIter;
-
- //! Depth of coarse sediment (consolidated and unconsolidated) removed via cliff collapse this timestep
- double m_dCliffCollapseCoarseThisIter;
-
- //! Total depth of fine sediment (consolidated and unconsolidated) removed via cliff collapse
- double m_dTotFineCliffCollapse;
-
- //! Total depth of sand sediment (consolidated and unconsolidated) removed via cliff collapse
- double m_dTotSandCliffCollapse;
-
- //! Total depth of coarse sediment (consolidated and unconsolidated) removed via cliff collapse
- double m_dTotCoarseCliffCollapse;
-
- //! Depth of unconsolidated sand sediment deposited as a result of cliff collapse this timestep
- double m_dTalusSandDepositionThisIter;
-
- //! Total depth of unconsolidated sand sediment deposited as a result of cliff collapse
- double m_dTotTalusSandDeposition;
-
- //! Depth of unconsolidated coarse sediment deposited as a result of cliff collapse this timestep
- double m_dTalusCoarseDepositionThisIter;
-
- //! Total depth of unconsolidated coarse sediment deposited as a result of cliff collapse
- double m_dTotTalusCoarseDeposition;
-
- //! Depth of sand-sized cliff collapse talus moved to unconsolidated sediment this timestep
- double m_dSandTalusToUnconsThisIter;
-
- //! Total depth of sand-sized cliff collapse talus moved to unconsolidated sediment
- double m_dTotSandTalusToUncons;
-
- //! Depth of coarse-sized cliff collapse talus moved to unconsolidated sediment this timestep
- double m_dCoarseTalusToUnconsThisIter;
-
- //! Total depth of coarse-sized cliff collapse talus moved to unconsolidated sediment
- double m_dTotCoarseTalusToUncons;
-
- //! Depth of unconsolidated beach sediment that could be eroded this timestep, if no supply-limitation
- double m_dPotentialBeachErosionThisIter;
-
- //! Total depth of unconsolidated beach sediment eroded; if no supply-limitation
- double m_dTotPotentialBeachErosion;
-
- //! Depth of unconsolidated beach sediment actually eroded this timestep
- double m_dActualBeachErosionThisIter;
-
- //! Total depth of unconsolidated beach sediment actually eroded
- double m_dTotActualBeachErosion;
-
- //! Depth of unconsolidated beach sediment deposited this timestep
- double m_dBeachDepositionThisIter;
-
- //! Total depth of unconsolidated beach sediment deposited
- double m_dTotBeachDeposition;
-
- //! d50 of unconsolidated sediment on top layer with unconsolidated sediment depth > 0
- double m_dUnconsD50;
-
- //! Height of intervention structure
- double m_dInterventionHeight;
-
- //! This cell's landform data
- CRWCellLandform m_Landform;
-
- // Initialize these as empty vectors
-
- //! Cell sediment layers NOT including the basement. Layer 0 is the lowest
- vector m_VLayerAboveBasement;
-
- //! Number of layer-top elevations (inc. that of the basement, which is m_VdAllHorizonTopElev[0]) size 1 greater than size of m_VLayerAboveBasement
- vector m_VdAllHorizonTopElev;
-
- protected:
- public:
- static CGeomRasterGrid *m_pGrid;
-
- CGeomCell();
- ~CGeomCell(void);
-
- void SetInContiguousSea(void);
- bool bIsInContiguousSea(void) const;
-
- void SetInContiguousFlood(void);
- void UnSetInContiguousFlood(void);
- void SetFloodBySetupSurge(void);
- bool bIsFloodBySetupSurge(void) const;
- void SetFloodBySetupSurgeRunup(void);
- bool bIsFloodBySetupSurgeRunup(void) const;
- bool bIsInContiguousSeaFlood(void) const;
-
- void SetInActiveZone(bool const);
- bool bIsInActiveZone(void) const;
- bool bPotentialPlatformErosion(void) const;
- bool bActualPlatformErosion(void) const;
- void SetAsCoastline(int const);
- bool bIsCoastline(void) const;
- int nGetCoastline(void) const;
- void SetAsFloodline(bool const);
- bool bIsFloodline(void) const;
-
- void SetAsCliffToe(bool const);
- bool bIsCliffToe(void) const;
-
- int nGetProfileID(void) const;
- bool bIsProfile(void) const;
- int nGetProfileCoastID(void) const;
- void SetCoastAndProfileID(int const, int const);
-
- void SetShadowZoneBoundary(void);
- bool bIsShadowZoneBoundary(void) const;
-
- void SetBoundingBoxEdge(int const);
- int nGetBoundingBoxEdge(void) const;
- bool bIsBoundingBoxEdge(void) const;
-
- void SetPossibleCoastStartCell(void);
- bool bIsPossibleCoastStartCell(void) const;
-
- void SetPossibleFloodStartCell(void);
- bool bIsPossibleFloodStartCell(void) const;
-
- int nGetPolygonID(void) const;
- int nGetPolygonCoastID(void) const;
- void SetCoastAndPolygonID(int const, int const);
-
- CRWCellLandform* pGetLandform(void);
-
- void SetWaveFlood(void);
- bool bElevLessThanSWL(void) const;
-
- void SetCheckCell(void);
- bool bIsCellCheck(void) const;
-
- void SetCheckFloodCell(void);
- void UnSetCheckFloodCell(void);
- bool bIsCellFloodCheck(void) const;
-
- void SetLocalConsSlope(double const);
- double dGetConsSedSlope(void) const;
-
- void SetSlopeForCliffToe(double const);
- double dGetSlopeForCliffToe(void) const;
-
- bool bIsInundated(void);
- double dGetThisIterSWL(void) const;
- double dGetThisIterTotWaterLevel(void) const; // Not used TODO 007 Finish surge and runup stuff
- void SetSeaDepth(void);
- double dGetSeaDepth(void) const;
- void InitCell(void);
- double dGetTotSeaDepth(void) const;
-
- void SetWaveHeight(double const);
- double dGetWaveHeight(void) const;
- double dGetTotWaveHeight(void) const;
- void SetWaveAngle(double const);
- double dGetWaveAngle(void) const;
- double dGetTotWaveAngle(void) const;
-
- void SetCellDeepWaterWaveHeight(double const);
- double dGetCellDeepWaterWaveHeight(void) const;
- void SetCellDeepWaterWaveAngle(double const);
- double dGetCellDeepWaterWaveAngle(void) const;
- void SetCellDeepWaterWavePeriod(double const);
- double dGetCellDeepWaterWavePeriod(void) const;
-
- void SetWaveValuesToDeepWaterWaveValues(void);
-
- void SetBeachProtectionFactor(double const);
- double dGetBeachProtectionFactor(void) const;
-
- void SetSuspendedSediment(double const);
- void AddSuspendedSediment(double const);
- double dGetSuspendedSediment(void) const;
- double dGetTotSuspendedSediment(void) const;
-
- int nGetTopNonZeroLayerAboveBasement(void) const;
- int nGetNumOfTopLayerAboveBasement(void) const;
-
- int nGetNumLayers(void) const;
- double dGetConsSedTopElevForLayerAboveBasement(int const) const;
- CRWCellLayer* pGetLayerAboveBasement(int const);
- void AppendLayers(int const);
- void CalcAllLayerElevsAndD50(void);
- int nGetLayerAtElev(double const) const;
- double dCalcLayerElev(const int);
-
- double dGetConsFineDepthAllLayers(void) const;
- double dGetUnconsFineDepthAllLayers(void) const;
- double dGetConsSandDepthAllLayers(void) const;
- double dGetUnconsSandDepthAllLayers(void) const;
- double dGetConsCoarseDepthAllLayers(void) const;
- double dGetUnconsCoarseDepthAllLayers(void) const;
-
- double dGetAllConsDepthAllLayers(void) const;
- double dGetAllUnconsDepthAllLayers(void) const;
- double dGetAllSedDepthAllLayers(void) const;
-
- double dGetTalusDepth(void) const;
-
- void SetBasementElev(double const);
- double dGetBasementElev(void) const;
- bool bBasementElevIsMissingValue(void) const;
- double dGetAllSedTopElevOmitTalus(void) const;
- double dGetAllSedTopElevIncTalus(void);
- double dGetTopElevIncSea(void);
- double dGetConsSedTopElevOmitTalus(void) const;
- double dGetConsSedTopElevIncTalus(void);
-
- void SetPotentialPlatformErosion(double const);
- double dGetPotentialPlatformErosion(void) const;
- double dGetTotPotentialPlatformErosion(void) const;
-
- void SetActualPlatformErosion(double const);
- double dGetActualPlatformErosion(void) const;
- double dGetTotActualPlatformErosion(void) const;
-
- void IncrCliffCollapseErosion(double const, double const, double const);
- double dGetThisIterCliffCollapseErosionFine(void) const;
- double dGetThisIterCliffCollapseErosionSand(void) const;
- double dGetThisIterCliffCollapseErosionCoarse(void) const;
- double dGetTotCliffCollapseFine(void) const;
- double dGetTotCliffCollapseSand(void) const;
- double dGetTotCliffCollapseCoarse(void) const;
-
- void AddSandTalusDeposition(double const);
- double dGetThisIterCliffCollapseSandTalusDeposition(void) const;
- double dGetTotSandTalusDeposition(void) const;
- void AddCoarseTalusDeposition(double const);
- double dGetThisIterCliffCollapseCoarseTalusDeposition(void) const;
- double dGetTotCoarseTalusDeposition(void) const;
-
- void AddSandTalusToUncons(double const);
- double dGetThisIterSandTalusToUncons(void);
- double dGetTotSandTalusToUncons(void);
- void AddCoarseTalusToUncons(double const);
- double dGetThisIterCoarseTalusToUncons(void);
- double dGetTotCoarseTalusToUncons(void);
-
- void SetPotentialBeachErosion(double const);
- double dGetPotentialBeachErosion(void) const;
- double dGetTotPotentialBeachErosion(void) const;
- void SetActualBeachErosion(double const);
- double dGetActualBeachErosion(void) const;
- double dGetTotActualBeachErosion(void) const;
- // bool bActualBeachErosionThisIter(void) const;
-
- void IncrBeachDeposition(double const);
- double dGetBeachDeposition(void) const;
- double dGetTotBeachDeposition(void) const;
- // bool bBeachDepositionThisIter(void) const;
-
- bool bBeachErosionOrDepositionThisIter(void) const;
-
- double dGetUnconsD50(void) const;
-
- int nGetInterventionClass(void) const;
- void SetInterventionHeight(double const);
- double dGetInterventionHeight(void) const;
- double dGetInterventionTopElev(void) const;
-
- void SetShadowZoneNumber(int const);
- int nGetShadowZoneNumber(void) const;
- bool bIsinThisShadowZone(int const) const;
- bool bIsinAnyShadowZone(void) const;
- void SetDownDriftZoneNumber(int const);
- int nGetDownDriftZoneNumber(void) const;
-};
-#endif // CELL_H
+/*!
+ \class CGeomCell
+ \brief Geometry class for the cell objects which comprise the raster grid
+ \details TODO 001 This is a more detailed description of the CGeomCell class.
+ \author David Favis-Mortlock
+ \author Andres Payo
+ \date 2025
+ \copyright GNU General Public License
+ \file cell.h
+ \brief Contains CGeomCell definitions
+
+*/
+
+#ifndef CELL_H
+#define CELL_H
+/* ===============================================================================================================================
+ This file is part of CoastalME, the Coastal Modelling Environment.
+
+ 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.
+
+ 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.
+
+ 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.
+===============================================================================================================================*/
+#include
+using std::vector;
+
+#include "cell_landform.h"
+#include "cell_layer.h"
+#include "cme.h"
+#include "raster_grid.h"
+
+class CGeomRasterGrid; // Forward declaration
+
+class CGeomCell
+{
+ friend class CSimulation;
+
+ private:
+ //! Switch to indicate if this is a sea cell, contiguous with other sea cells
+ bool m_bInContiguousSea;
+
+ //! Switch to indicate that this cell is in the contiguous runup flood area
+ bool m_bInContiguousFlood;
+
+ //! Switch to indicate that this cell is in the active zone
+ bool m_bIsInActiveZone;
+
+ //! Is this cell a cliff toe?
+ bool m_bCliffToe;
+
+ //! Switch to indicate that this cell is 'under' a runup flood line TODO 007 Finish surge and runup stuff
+ bool m_bFloodLine;
+
+ //! Switch to indicate that this cell is 'under' a runup wave flood line TODO 007 Finish surge and runup stuff
+ bool m_bWaveFlood;
+
+ // //! TODO 007 Finish surge and runup stuff
+ // bool m_bCheckCell;
+
+ //! TODO 007 Finish surge and runup stuff
+ bool m_bCheckFloodCell;
+
+ //! Switch to show this cell is 'under' a shadow boundary
+ bool m_bShadowBoundary;
+
+ //! Switch to show that this cell could be the start of a coastline
+ bool m_bPossibleCoastStartCell;
+
+ //! TODO 007 Finish surge and runup stuff
+ bool m_bPossibleFloodStartCell;
+
+ //! TODO 007 Finish surge and runup stuff
+ bool m_bFloodBySetupSurge;
+
+ //! TODO 007 Finish surge and runup stuff
+ bool m_bFloodBySetupSurgeRunup;
+
+ //! If this cell is an edge (or bounding box) cell, this specifies the edge
+ int m_nBoundingBoxEdge;
+
+ //! If this cell is 'under' a coastline, this is the ID number of the coast
+ int m_nCoastlineID;
+
+ //! If this cell is 'under' a coast-normal profile, this is the ID number of the profile
+ int m_nProfileID;
+
+ //! If this cell is 'under' a coast-normal profile, this is the ID number of the profile's coast
+ int m_nProfileCoastID;
+
+ //! If this cell is within a polygon, this is the ID of the polygon
+ int m_nPolygonID;
+
+ //! If this cell is within a polygon, this is the ID number of the polygon's coast
+ int m_nPolygonCoastID;
+
+ //! If this cell is 'under' a coastline normal, this is the number of the normal
+ int m_nCoastlineNormal;
+
+ //! If this cell is within a shadow zone, this is the ID number of the shadow zone
+ int m_nShadowZoneNumber;
+
+ //! If this cell is within a downdrift zone, this is the ID number of the downdrift zone
+ int m_nDownDriftZoneNumber;
+
+ //! Used in erosion calculations, stored here for display purposes
+ double m_dLocalConsSlope;
+
+ //! Elevation of basement surface (m)
+ double m_dBasementElevation;
+
+ //! Slope at this cell (degrees or unitless)
+ double m_dSlopeForCliffToe;
+
+ //! Depth of still water (m), is zero if not inundated
+ double m_dSeaDepth;
+
+ //! Total depth of still water (m) since beginning of simulation (used to calc average)
+ double m_dTotSeaDepth;
+
+ //! Wave height (m)
+ double m_dWaveHeight;
+
+ //! Total wave height (m) (used to calc average)
+ double m_dTotWaveHeight;
+
+ //! Wave orientation
+ double m_dWaveAngle;
+
+ //! Wave period (s)
+ double m_dWavePeriod;
+
+ //! Total wave orientation (used to calc average)
+ double m_dTotWaveAngle;
+
+ //! Wave height if this is a deep water cell
+ double m_dDeepWaterWaveHeight;
+
+ //! Wave orientation if this is a deep water cell
+ double m_dDeepWaterWaveAngle;
+
+ //! Wave period if this is a deep water cell
+ double m_dDeepWaterWavePeriod;
+
+ //! Only meaningful if in zone of platform erosion. 0 = fully protected; 1 = ! no protection
+ double m_dBeachProtectionFactor;
+
+ //! Suspended sediment as depth equivalent (m)
+ double m_dSuspendedSediment;
+
+ //! Total depth of suspended sediment (m) since simulation start (used to calc average)
+ double m_dTotSuspendedSediment;
+
+ //! Depth of sediment on the shore platform that could be eroded this timestep, if no supply-limitation
+ double m_dPotentialPlatformErosionThisIter;
+
+ //! Total depth of sediment eroded from the shore platform, if no supply-limitation
+ double m_dTotPotentialPlatformErosion;
+
+ //! Depth of sediment actually eroded from the shore platform this timestep
+ double m_dActualPlatformErosionThisIter;
+
+ //! Total depth of sediment actually eroded from the shore platform
+ double m_dTotActualPlatformErosion;
+
+ //! Depth of fine sediment (consolidated and unconsolidated) removed via cliff collapse this timestep
+ double m_dCliffCollapseFineThisIter;
+
+ //! Depth of sand sediment (consolidated and unconsolidated) removed via cliff collapse this timestep
+ double m_dCliffCollapseSandThisIter;
+
+ //! Depth of coarse sediment (consolidated and unconsolidated) removed via cliff collapse this timestep
+ double m_dCliffCollapseCoarseThisIter;
+
+ //! Total depth of fine sediment (consolidated and unconsolidated) removed via cliff collapse
+ double m_dTotFineCliffCollapse;
+
+ //! Total depth of sand sediment (consolidated and unconsolidated) removed via cliff collapse
+ double m_dTotSandCliffCollapse;
+
+ //! Total depth of coarse sediment (consolidated and unconsolidated) removed via cliff collapse
+ double m_dTotCoarseCliffCollapse;
+
+ //! Depth of unconsolidated sand sediment deposited as a result of cliff collapse this timestep
+ double m_dTalusSandDepositionThisIter;
+
+ //! Total depth of unconsolidated sand sediment deposited as a result of cliff collapse
+ double m_dTotTalusSandDeposition;
+
+ //! Depth of unconsolidated coarse sediment deposited as a result of cliff collapse this timestep
+ double m_dTalusCoarseDepositionThisIter;
+
+ //! Total depth of unconsolidated coarse sediment deposited as a result of cliff collapse
+ double m_dTotTalusCoarseDeposition;
+
+ //! Depth of sand-sized cliff collapse talus moved to unconsolidated sediment this timestep
+ double m_dSandTalusToUnconsThisIter;
+
+ //! Total depth of sand-sized cliff collapse talus moved to unconsolidated sediment
+ double m_dTotSandTalusToUncons;
+
+ //! Depth of coarse-sized cliff collapse talus moved to unconsolidated sediment this timestep
+ double m_dCoarseTalusToUnconsThisIter;
+
+ //! Total depth of coarse-sized cliff collapse talus moved to unconsolidated sediment
+ double m_dTotCoarseTalusToUncons;
+
+ //! Depth of unconsolidated beach sediment that could be eroded this timestep, if no supply-limitation
+ double m_dPotentialBeachErosionThisIter;
+
+ //! Total depth of unconsolidated beach sediment eroded; if no supply-limitation
+ double m_dTotPotentialBeachErosion;
+
+ //! Depth of unconsolidated beach sediment actually eroded this timestep
+ double m_dActualBeachErosionThisIter;
+
+ //! Total depth of unconsolidated beach sediment actually eroded
+ double m_dTotActualBeachErosion;
+
+ //! Depth of unconsolidated beach sediment deposited this timestep
+ double m_dBeachDepositionThisIter;
+
+ //! Total depth of unconsolidated beach sediment deposited
+ double m_dTotBeachDeposition;
+
+ //! d50 of unconsolidated sediment on top layer with unconsolidated sediment depth > 0
+ double m_dUnconsD50;
+
+ //! Height of intervention structure
+ double m_dInterventionHeight;
+
+ //! This cell's landform data
+ CRWCellLandform m_Landform;
+
+ // Initialize these as empty vectors
+
+ //! Cell sediment layers NOT including the basement. Layer 0 is the lowest
+ vector m_VLayerAboveBasement;
+
+ //! Number of layer-top elevations (inc. that of the basement, which is m_VdAllHorizonTopElev[0]) size 1 greater than size of m_VLayerAboveBasement
+ vector m_VdAllHorizonTopElev;
+
+ protected:
+ public:
+ static CGeomRasterGrid *m_pGrid;
+
+ CGeomCell();
+ ~CGeomCell(void);
+
+ void SetInContiguousSea(void);
+ bool bIsInContiguousSea(void) const;
+
+ void SetInContiguousFlood(void);
+ void UnSetInContiguousFlood(void);
+ void SetFloodBySetupSurge(void);
+ bool bIsFloodBySetupSurge(void) const;
+ void SetFloodBySetupSurgeRunup(void);
+ bool bIsFloodBySetupSurgeRunup(void) const;
+ bool bIsInContiguousSeaFlood(void) const;
+
+ void SetInActiveZone(bool const);
+ bool bIsInActiveZone(void) const;
+ bool bPotentialPlatformErosion(void) const;
+ bool bActualPlatformErosion(void) const;
+ void SetAsCoastline(int const);
+ bool bIsCoastline(void) const;
+ int nGetCoastline(void) const;
+ void SetAsFloodline(bool const);
+ bool bIsFloodline(void) const;
+
+ void SetAsCliffToe(bool const);
+ bool bIsCliffToe(void) const;
+
+ int nGetProfileID(void) const;
+ bool bIsProfile(void) const;
+ int nGetProfileCoastID(void) const;
+ void SetCoastAndProfileID(int const, int const);
+
+ void SetShadowZoneBoundary(void);
+ bool bIsShadowZoneBoundary(void) const;
+
+ void SetBoundingBoxEdge(int const);
+ int nGetBoundingBoxEdge(void) const;
+ bool bIsBoundingBoxEdge(void) const;
+
+ void SetPossibleCoastStartCell(void);
+ bool bIsPossibleCoastStartCell(void) const;
+
+ void SetPossibleFloodStartCell(void);
+ bool bIsPossibleFloodStartCell(void) const;
+
+ int nGetPolygonID(void) const;
+ int nGetPolygonCoastID(void) const;
+ void SetCoastAndPolygonID(int const, int const);
+
+ CRWCellLandform* pGetLandform(void);
+
+ void SetWaveFlood(void);
+ bool bElevLessThanSWL(void) const;
+
+ void SetCheckCell(void);
+ bool bIsCellCheck(void) const;
+
+ void SetCheckFloodCell(void);
+ void UnSetCheckFloodCell(void);
+ bool bIsCellFloodCheck(void) const;
+
+ void SetLocalConsSlope(double const);
+ double dGetConsSedSlope(void) const;
+
+ void SetSlopeForCliffToe(double const);
+ double dGetSlopeForCliffToe(void) const;
+
+ bool bIsInundated(void);
+ double dGetThisIterSWL(void) const;
+ double dGetThisIterTotWaterLevel(void) const; // Not used TODO 007 Finish surge and runup stuff
+ void SetSeaDepth(void);
+ double dGetSeaDepth(void) const;
+ void InitCell(void);
+ double dGetTotSeaDepth(void) const;
+
+ void SetWaveHeight(double const);
+ double dGetWaveHeight(void) const;
+ double dGetTotWaveHeight(void) const;
+ void SetWaveAngle(double const);
+ double dGetWaveAngle(void) const;
+ double dGetTotWaveAngle(void) const;
+
+ void SetCellDeepWaterWaveHeight(double const);
+ double dGetCellDeepWaterWaveHeight(void) const;
+ void SetCellDeepWaterWaveAngle(double const);
+ double dGetCellDeepWaterWaveAngle(void) const;
+ void SetCellDeepWaterWavePeriod(double const);
+ double dGetCellDeepWaterWavePeriod(void) const;
+
+ void SetWaveValuesToDeepWaterWaveValues(void);
+
+ void SetBeachProtectionFactor(double const);
+ double dGetBeachProtectionFactor(void) const;
+
+ void SetSuspendedSediment(double const);
+ void AddSuspendedSediment(double const);
+ double dGetSuspendedSediment(void) const;
+ double dGetTotSuspendedSediment(void) const;
+
+ int nGetTopNonZeroLayerAboveBasement(void) const;
+ int nGetNumOfTopLayerAboveBasement(void) const;
+
+ int nGetNumLayers(void) const;
+ double dGetConsSedTopElevForLayerAboveBasement(int const) const;
+ CRWCellLayer* pGetLayerAboveBasement(int const);
+ void AppendLayers(int const);
+ void CalcAllLayerElevsAndD50(void);
+ int nGetLayerAtElev(double const) const;
+ double dCalcLayerElev(const int);
+
+ double dGetConsFineDepthAllLayers(void) const;
+ double dGetUnconsFineDepthAllLayers(void) const;
+ double dGetConsSandDepthAllLayers(void) const;
+ double dGetUnconsSandDepthAllLayers(void) const;
+ double dGetConsCoarseDepthAllLayers(void) const;
+ double dGetUnconsCoarseDepthAllLayers(void) const;
+
+ double dGetAllConsDepthAllLayers(void) const;
+ double dGetAllUnconsDepthAllLayers(void) const;
+ double dGetAllSedDepthAllLayers(void) const;
+
+ double dGetTalusDepth(void) const;
+
+ void SetBasementElev(double const);
+ double dGetBasementElev(void) const;
+ bool bBasementElevIsMissingValue(void) const;
+ double dGetAllSedTopElevOmitTalus(void) const;
+ double dGetAllSedTopElevIncTalus(void);
+ double dGetTopElevIncSea(void);
+ double dGetConsSedTopElevOmitTalus(void) const;
+ double dGetConsSedTopElevIncTalus(void);
+
+ void SetPotentialPlatformErosion(double const);
+ double dGetPotentialPlatformErosion(void) const;
+ double dGetTotPotentialPlatformErosion(void) const;
+
+ void SetActualPlatformErosion(double const);
+ double dGetActualPlatformErosion(void) const;
+ double dGetTotActualPlatformErosion(void) const;
+
+ void IncrCliffCollapseErosion(double const, double const, double const);
+ double dGetThisIterCliffCollapseErosionFine(void) const;
+ double dGetThisIterCliffCollapseErosionSand(void) const;
+ double dGetThisIterCliffCollapseErosionCoarse(void) const;
+ double dGetTotCliffCollapseFine(void) const;
+ double dGetTotCliffCollapseSand(void) const;
+ double dGetTotCliffCollapseCoarse(void) const;
+
+ void AddSandTalusDeposition(double const);
+ double dGetThisIterCliffCollapseSandTalusDeposition(void) const;
+ double dGetTotSandTalusDeposition(void) const;
+ void AddCoarseTalusDeposition(double const);
+ double dGetThisIterCliffCollapseCoarseTalusDeposition(void) const;
+ double dGetTotCoarseTalusDeposition(void) const;
+
+ void AddSandTalusToUncons(double const);
+ double dGetThisIterSandTalusToUncons(void);
+ double dGetTotSandTalusToUncons(void);
+ void AddCoarseTalusToUncons(double const);
+ double dGetThisIterCoarseTalusToUncons(void);
+ double dGetTotCoarseTalusToUncons(void);
+
+ void SetPotentialBeachErosion(double const);
+ double dGetPotentialBeachErosion(void) const;
+ double dGetTotPotentialBeachErosion(void) const;
+ void SetActualBeachErosion(double const);
+ double dGetActualBeachErosion(void) const;
+ double dGetTotActualBeachErosion(void) const;
+ // bool bActualBeachErosionThisIter(void) const;
+
+ void IncrBeachDeposition(double const);
+ double dGetBeachDeposition(void) const;
+ double dGetTotBeachDeposition(void) const;
+ // bool bBeachDepositionThisIter(void) const;
+
+ bool bBeachErosionOrDepositionThisIter(void) const;
+
+ double dGetUnconsD50(void) const;
+
+ int nGetInterventionClass(void) const;
+ void SetInterventionHeight(double const);
+ double dGetInterventionHeight(void) const;
+ double dGetInterventionTopElev(void) const;
+
+ void SetShadowZoneNumber(int const);
+ int nGetShadowZoneNumber(void) const;
+ bool bIsinThisShadowZone(int const) const;
+ bool bIsinAnyShadowZone(void) const;
+ void SetDownDriftZoneNumber(int const);
+ int nGetDownDriftZoneNumber(void) const;
+};
+#endif // CELL_H
diff --git a/src/cme.cpp b/src/cme.cpp
index 52b6b3086..8c87462e2 100644
--- a/src/cme.cpp
+++ b/src/cme.cpp
@@ -1,52 +1,52 @@
-/*!
- \file cme.cpp
- \brief The start-up routine for CoastalME
- \details TODO 001 A more detailed description of this routine
- \author David Favis-Mortlock
- \author Andres Payo
- \date 2025
- \copyright GNU General Public License
-*/
-
-/* ===============================================================================================================================
- This file is part of CoastalME, the Coastal Modelling Environment.
-
- 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.
-
- 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.
-
- 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.
-===============================================================================================================================*/
-#include
-
-#include "simulation.h"
-
-// #include // Include this to check for first appearance in NaN when debugging (comment out, otherwise)
-
-//===============================================================================================================================
-//! CoastalME's main function
-//===============================================================================================================================
-int main(int argc, char const* argv[])
-{
- // This is to check for first appearance of NaN when debugging (comment out, otherwise)
- // #ifdef __APPLE__
- // #else
- // feenableexcept(FE_INVALID | FE_OVERFLOW);
- // #endif
-
- // Enable the use of UTF-8 symbols in CoastalME output
- setlocale(LC_ALL, "en_GB.UTF-8");
-
- // Create a CSimulation object
- CSimulation* pSimulation = new CSimulation;
-
- // Run the simulation and then check how it ends
- int const nRtn = pSimulation->nDoSimulation(argc, argv);
- pSimulation->DoSimulationEnd(nRtn);
-
- // Get rid of the CSimulation object and close files
- delete pSimulation;
-
- // Go back to the OS
- return nRtn;
-}
+/*!
+ \file cme.cpp
+ \brief The start-up routine for CoastalME
+ \details TODO 001 A more detailed description of this routine
+ \author David Favis-Mortlock
+ \author Andres Payo
+ \date 2025
+ \copyright GNU General Public License
+*/
+
+/* ===============================================================================================================================
+ This file is part of CoastalME, the Coastal Modelling Environment.
+
+ 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.
+
+ 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.
+
+ 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.
+===============================================================================================================================*/
+#include
+
+#include "simulation.h"
+
+// #include // Include this to check for first appearance in NaN when debugging (comment out, otherwise)
+
+//===============================================================================================================================
+//! CoastalME's main function
+//===============================================================================================================================
+int main(int argc, char const* argv[])
+{
+ // This is to check for first appearance of NaN when debugging (comment out, otherwise)
+ // #ifdef __APPLE__
+ // #else
+ // feenableexcept(FE_INVALID | FE_OVERFLOW);
+ // #endif
+
+ // Enable the use of UTF-8 symbols in CoastalME output
+ setlocale(LC_ALL, "en_GB.UTF-8");
+
+ // Create a CSimulation object
+ CSimulation* pSimulation = new CSimulation;
+
+ // Run the simulation and then check how it ends
+ int const nRtn = pSimulation->nDoSimulation(argc, argv);
+ pSimulation->DoSimulationEnd(nRtn);
+
+ // Get rid of the CSimulation object and close files
+ delete pSimulation;
+
+ // Go back to the OS
+ return nRtn;
+}
diff --git a/src/cme.h b/src/cme.h
index 7a01354ce..dfab0178a 100644
--- a/src/cme.h
+++ b/src/cme.h
@@ -1,1276 +1,1276 @@
-/*!
- \mainpage
- \section intro_sec Introduction
-
- CoastalME (Coastal Modelling Environment) simulates the long-term behaviour of a coast. This initial version considers only simple soft cliff cross-shore effects. However, development of CoastalME is ongoing. Watch this space!\n\n
-
- CoastalME was devised and constructed by Andres Payo Garcia (British Geological Survey: agarcia@bgs.ac.uk) and David Favis-Mortlock (British Geological Survey: dfm1@bgs.ac.uk). We are very grateful to the following for support, assistance, and inspiration: Tom Ashby, Manuel Cobos Budia, Wilf Chun, Mark Dickson, Jim W. Hall, Martin D. Hurst, Matthew Ives, Robert J. Nicholls, Ian Townend, and Mike
- J.A. Walkden.\n\n
-
- See https://github.com/coastalme/coastalme for the stable release version, and the unstable development version, of the source code.\n
- \n
- From Shingle Street\n
- To Orford Ness\n
- The waves maraud,\n
- The winds oppress,\n
- The earth can’t help\n
- But acquiesce\n
- For this is east\n
- And east means loss,\n
- A lessening shore, receding ground,\n
- Three feet gone last year, four feet this\n
- Where land runs out and nothing’s sound.\n
- Nothing lasts long on Shingle Street.\n
- \n
- By Blake Morrison (2018). See https://www.penguin.co.uk/books/419911/shingle-street-by-morrison-blake/9780701188771\n
-
- \section install_sec Installing CoastalME
-
- \subsection install_step1 Obtaining the source code
-
- CoastalME builds easily using Linux. If you wish to run CoastalME on Windows, then we currently recommend using the Windows Subsystem Linux (WSL) software to do this.
-
- Create a local copy of the github repository, for example by downloading a zipfile, then unpacking it or cloning. We suggest unpacking it to something like "/home/YOUR NAME/Projects/CoastalME/", this is then your CoastalME folder.
-
- git clone https://github.com/coastalme/coastalme
-
- \subsection install_step2 Building CoastalME
-
- In a terminal window (i.e. at a command-line prompt) move to the CoastalME folder.
-
- Then move to the the src folder
-
- cd CoastalME/src
-
- and run run_cmake.sh
-
- ./run_cmake.sh
-
- If you get a "Permission denied" message: -bash: ./run_cmake.sh: Permission denied you will have to grant executable permission using chmod a+x run_cmake.sh, chmod a+x cshore/make_cshore.sh and then
- ./run_cmake.sh
-
- This will build CShore, look for GDAL, and write the CMake files. If you see error messages about missing software (for example, telling you that CMake cannot be found or is too old, or GDAL cannot be found or is too old) then you need to install or update the software that is causing the problem.
-
- Next, run
-
- make install
-
- This will create an executable file called cme in the CoastalME folder.
-
- \section run_sec Running CoastalME
-
- \subsection run_step1 Specifying the input file
-
- Edit cme.ini to tell CoastalME which input file to read (for example, in/test_suite/minimal_wave_angle_230/minimal.dat).
-
- \subsection run_step2 Running CoastalME
-
- Leave the src folder, and run cme
-
- cd ..
- ./cme
-
- Output will appear in the "Path for output" folder.
-
- \subsection run_step3 Running CoastalME's test suite
-
- To check that your installation is running correctly, you can run a suite of pre-defined tests by running the following commands:
-
- chmod a+x run_test_suite.sh
- ./run_test_suite.sh
-
- The `chmod` comand ensures that you have permission to execute the run_test_suite.sh file.
-
- \subsection run_step4 Managing CoastalME's output
-
- Once you have CoastalME (CME) up and running, you can reduce the quantity of output (it can be overwhelming!) in several ways.
-
- Change "Content of log file" in the CME input file for any of the test suite runs (the name of this input file is listed in cme.ini, both are simple text files). If you set "Content of log file" to zero, then CME won't output a log file; setting it to 4 (all output) is really only useful to developers.
-
- Change "GIS vector files to output" and "GIS vector files to output" in the CME input file. These are both set to "all" in the test suite files on GitHub. Instead of "all" you can list the space-separated codes for only the GIS output that you want to see. A list of CME GIS output codes is in codes.txt.
-
- Enjoy!
-
- \file cme.h
- \brief This file contains global definitions for CoastalME
-*/
-
-/*
- NOTE Before releasing a new version, do a pre-release build to check for memory leaks with -fsanitize options enabled (see CMakeLists.txt) then run ./cme 2> sanitize.txt NOT UNDER DEBUG (i.e. not using gdb)
-
- TODOLIST
- ***********************************************************************************************************
- DOCUMENTATION
- TODO 001 Add more Doxygen information about all classes
- TODO 007 We now have setup and surge info from CShore (thanks to Manuel). But what shall we do with this info? "The variable VdWaveSetupSurge() represents the sea level rise due to wave effects (setup) and storm surge. CSHORE calculates them together and they can’t be separated. That’s what the VdWaveSetupSurge variable is. That’s why you saw my initial efforts to try to separate both variables from CSHORE commented out, which is impossible. What is possible is to get the RunUp from CSHORE, but since it uses an empirical formula for that, I finally decided to calculate it separately. To your question about whether you should remove VdStormSurge, the answer is yes. I left it because I still intend at some point to extract the cross-shore transport from CSHORE and balance it in CME with the longshore and cross-shore transports without needing the Dean profile. From my point of view, this would be even more realistic, though at first it will surely drive us crazy."
-
- USER INPUT
- TODO 000 Should user input be split in two main files: one for frequently-changed things, one for rarely-changed things? If so, what should go into each file ('testing only' OK, but what else?)
- TODO 011 Should this constant be a user input? If so, TODO 071
- TODO 036 Read in changed deep water wave values (need TODO 071)
- TODO 022 Get intervention update working (need TODO 071)
- TODO 042 Should we have a smallest valid input for KLS in the CERC equation?
- TODO 045 Method of getting depth of closure value needs to be a user input (need TODO 071)
- TODO 049 Handle other command line parameters e.g. path to .ini file, path to datafile
- TODO 035 Also handle other EPSG for vector spatial reference systems
- TODO 054 Choose more files to omit from "usual" raster output
- TODO 069 Enable ability to represent intervention structures which have their foundation embedded in consolidated sediment. In other words, with the elevation of the base of the intervention structure *below* the top of all consolidated sediment layers. Will need some sanity checking of elevations
- TODO 071 If the user input file format is changed, write a Python script to convert from the old file format to the new
- TODO 083 Get all three kinds of sediment input events working correctly
-
- ERROR HANDLING
- TODO 038 Do better error handling if insufficient memory
- TODO 004 Improve error handling of situation where we have a valid shadow zone but cannot find a neighbouring cell which is 'under' the coastline
- TODO 006 Check GDALGridCreate() with only start-of-coast or an end-of-coast profiles
- TODO 009 Decide what to do when we have eroded down to basement
- TODO 017 Extra safety check needed, make sure that each point is within valid grid
- TODO 018 Improve situation where new landwards point on parallel profile is not within the raster grid
- TODO 019 Improve situation where Dean profile has a near-zero elevation difference
- TODO 020 Check calculation of elevation of coast point of Dean parallel profile
- TODO 021 Improve situation where all layers have zero thickness
- TODO 025 Improve situation where this point has only zero thickness layers
- TODO 026 Check situation where cell in parallel profile is not in a polygon
- TODO 028 Give a warning if raster input layer has several bands
- TODO 053 Improve handling of situation where landward elevation of profile is -ve
- TODO 055 Maybe add a safety check here?
- TODO 080 Do we get -ve breaking wave heights here?
- TODO 084 Improve handling of situation where consecutive profile points are same distance from shoreline
-
- THEORY/EFFICIENCY
- TODO 002 Do we really need D50 for drift landform class? What do we need for drift?
- TODO 005 Maybe give every coast point a value for end-of-profile wave height and direction instead of for deep water wave height and direction
- TODO 010 Do we also need to update the active zone cells?
- TODO 012 Change finding of adjacent polygons, and calculation of the length of shared normals, when we make polygon seaward length determined by depth of closure
- TODO 013 Change calculation (need user input?) of coastline smoothing convexity threshold
- TODO 014 Profile spacing, could try gradually increasing the profile spacing with increasing concavity, and decreasing the profile spacing with increasing convexity
- TODO 016 Check mass balance for recirculating unconsolidated sediment option
- TODO 023 Only calculate shore platform erosion if cell is in a polygon
- TODO 024 Should we calculate platform erosion on a profile that has hit dry land?
- TODO 044 Implement estuaries
- TODO 051 Implement other ways of calculating depth of closure, see TODO 045
- TODO 056 Check this please Andres
- TODO 059 Implement dune landform class
- TODO 060 Remove 'magic numbers' from code here
- TODO 061 Is this safety check to depth of breaking a reasonable thing to do?
- TODO 066 Should this be for all layers? Check
- TODO 067 Suspended fine sediment never decreases i.e. no suspended fine sediment ever leaves the grid. Is this OK?
- TODO 070 Change CShore to use allocatable arrays (https://fortran-lang.org/en/learn/best_practices/allocatable_arrays/) so that the number of points in the CShore output profiles can either be a user input, or determined by e.g. the physical length of the profile. At present, max is NN = 1000 in cshore_wrapper.f03
- TODO 075 What if bedrock sticks above Dean profile?
- TODO 076 When doing parallel profiles, start from the profile which is closest to a right angle with the coast
- TODO 077 As traverse between the bounding profiles creating parallel profiles, gradually change the parallel profile orientation based on distance weighting of two bounding profiles
- TODO 078 At present, we don't allow cliff collapse onto interventions. Is this realistic? Should it be different for different types on intervention?
- TODO 089 Why do we get patches of sediment in the sea?
- TODO 086 Try these as a more efficient replacement for GDALGridCreate(): https://github.com/delfrrr/delaunator-cpp https://www.cs.cmu.edu/~quake/triangle.html https://github.com/greenm01/poly2tri https://gts.sourceforge.net/index.html
- TODO 088 In (almost) all whole-grid loops, immediately continue if cell is hinterland (but not when calculating cliff collapse)
- TODO 090 At present, sediment cannot move from a given coastline polygon to a polygon belonging to another coastline. Is this always true?
- TODO 092 If we have only fine sediment, the surface formed as the coast recedes inland is dead level (because fine sediment goes to suspension, and hence the Dean profile stuff does not operate). This causes problems with profile creation and CShore. Need to impose a small slope here somehow
- TODO 093 There are a number of cell attributes that are really only useful for debugging. To keep memory usage down on release versions, need to flag these attributes and their methods so that they are included only in debug versions
- TODO 094 Problems with sediment recirculation when large volumes of sedimentare introduced at the input end of the coast: need to spread this input sediment over the whole of the grid-end polygon
- TODO 095 Parallel profiles seem to create "streaks" of above-water sediment, these streaks interfere with subsequent profile creation (profiles which hit steaks arte marked as invalid). Investigate this
- TODO 096 It is OK to specify OGRFieldDefn objects as const in recent versions (e.g. 14.2) of g++, but in older versions of g++ (e.g. 12.2) have problems with const here. Maybe make the const a pre-processor condion?
-
- OUTPUT
- TODO 065 Get GPKG output working: GDAL 3.9.1 does not yet implement this correctly. Currently is OK for vector output (but is very slow), not yet working for raster output
- TODO 063 Add NetCDF support, see https://trac.osgeo.org/gdal/wiki/NetCDF
- TODO 064 Add support for grids that are not oriented N-S and W-E, but which are still rectangular. See https://gdal.org/en/stable/tutorials/geotransforms_tut.html
- TODO 031 Get raster slice output working with multiple slices
- TODO 032 Improve output scaling for DBL_NODATA situation
- TODO 033 Also test and configure (e.g. by passing open() options) other vector output file formats
- TODO 034 Also test and configure (e.g. by passing open() options) other raster output file formats
- TODO 043 When outputting profiles, how do we deal with randomness of profile spacing (since profile location is determined by curvature)?
- TODO 052 Improve saving of profiles and parallel profiles
- TODO 062 Show end-of-iteration number of cells with sediment somewhere
- TODO 068 Only show output in log file that is relevant to processes being simulated
- TODO 074 Output history of what landforms are on a particular cell or cells. User inputs cell(s), how?
- TODO 082 Also show m_dStartIterUnconsFineAllCells etc. in log file
-
- 096 is max
-
- COMPLETED
- TODO 003 Make coastline curvature moving window size a user input DONE in 1.1.22
- TODO 046 Why is cliff collapse eroded during deposition (three size classes) no longer calculated? DONE IN 1.1.22
- TODO 058 Dave to check this DONE in 1.1.22
- TODO 039 Rewrite reading of multiple random number seeds DONE in 1.2.1, 8 Nov 2024
- TODO 041 Read in SWL per-timestep
- BUG 002 Useless output e.g. clay layers even if no clay input DONE in 1.1.21
- BUG 003 Use mean SWL for elevations of Dean profiles DONE in 1.2.1, 27 Nov 2024
- BUG 004 Don't smooth intervention coastline DONE 1.2.1, 27 Nov 2024
- TODO 073 If output dir does not exist, then create it (ask user first) DONE 1.2.2, 28 Nov 2024
- TODO 047 Where is the GDAL description for the deep water wave stations vector file? DONE 1.2.3, 2 Dec 2024
- TODO 048 Where is the GDAL description for the flood input locations point or vector file? DONE 1.2.3, 2 Dec 2024
- TODO 027 Sort out GDAL problem with raster reference units DONE 1.2.3, 2 Dec 2024
- TODO 079 Do sanity checking on wave and tide input DONE 1.2.3, 2 Dec 2024
- TODO 072 CShore crashes occasionally, is it because of -ve Z values here? DONE 1.2.3, 2 Dec 2024
- TODO 050 Update for recent versions of Windows DONE 1.2.3, 2 Dec 2024
- TODO 037 Need more info on nFindIndex() DONE 1.2.3, 2 Dec 2024 Improve coast normals DONE 1.2.3, 20 Dec 2024
- TODO 057 Check this please Manuel DONE 1.2.4, 4 Jan 2025
- TODO 087 Is there a problem if profile is not long enough for user-input depth of closure? DONE 1.3.0 2 Feb 2025
-*/
-
-#ifndef CME_H
-#define CME_H
-/* ===============================================================================================================================
- This file is part of CoastalME, the Coastal Modelling Environment.
-
- 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.
-
- 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.
-
- 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.
-===============================================================================================================================*/
-#include
-
-#include
-using std::string;
-
-#include
-using std::ostringstream;
-
-#include
-using std::ostream;
-
-#include
-
-//===================================================== platform-specific stuff =================================================
-#ifdef _WIN32
- #define access _access
- #define F_OK 0 // Test for file existence
-#endif
-
-#ifdef _MSC_VER
- // MS Visual C++ compiler, byte order is IEEE little-endian
- #ifdef _DEBUG
- #include // useful
- #endif
-
- // clock_t is a signed long: see
- long const CLOCK_T_MIN = LONG_MIN;
- double const CLOCK_T_RANGE = static_cast(LONG_MAX) - static_cast(CLOCK_T_MIN);
-
- #ifdef _M_ALPHA
- string const PLATFORM = "MS Visual C++ for Alpha";
- #elif defined _M_IX86
- string const PLATFORM = "MS Visual C++ for Intel x86";
- #elif defined _M_MPPC
- string const PLATFORM = "MS Visual C++ for Power PC";
- #elif defined _M_MRX000
- string const PLATFORM = "MS Visual C++ for MIPS";
- #else
- string const PLATFORM = "MS Visual C++ for unknown CPU";
- #endif
-
-#elif defined __GNUG__
- // GNU compiler
- #ifndef CPU
- #error "CPU not defined"
- #else
- #ifdef x86
- // Intel x86, byte order is little-endian
- string const PLATFORM = "GNU Compiler for Intel x86";
- // clock_t is an unsigned long: see
- unsigned long const CLOCK_T_MIN = 0;
- double const CLOCK_T_RANGE = static_cast(ULONG_MAX);
- #elif defined rs6000
- // IBM RS-6000, byte order is big-endian
- string const PLATFORM = "GNU complier for IBM RS-6000";
- // clock_t is a signed long: see NEED TO CHECK
- long const CLOCK_T_MIN = LONG_MIN;
- double const CLOCK_T_RANGE = static_cast(LONG_MAX) - static_cast(CLOCK_T_MIN);
- #elif defined ultrasparc
- // Sun UltraSparc, byte order is big-endian
- string const PLATFORM = "GNU compiler for Sun UltraSPARC";
- // clock_t is a signed long: see
- long const CLOCK_T_MIN = LONG_MIN;
- double const CLOCK_T_RANGE = static_cast(LONG_MAX) - static_cast(CLOCK_T_MIN);
- #else
- // Something else
- string const PLATFORM = "GNU compiler for unknown CPU";
- // clock_t is a signed long: NEED TO CHECK
- long const CLOCK_T_MIN = LONG_MIN;
- double const CLOCK_T_RANGE = static_cast(LONG_MAX) - static_cast(CLOCK_T_MIN);
- #endif
- #endif
-
-#elif defined __clang__
- // Clang compiler
- #ifndef CPU
- #error "CPU not defined"
- #else
- #ifdef x86
- // Intel x86, byte order is little-endian
- string const PLATFORM = "Clang compiler for Intel x86";
- // clock_t is an unsigned long: see
- unsigned long const CLOCK_T_MIN = 0;
- double const CLOCK_T_RANGE = static_cast(ULONG_MAX);
- #else
- // Something else
- string const PLATFORM = "Clang compiler for unknown CPU";
- // clock_t is a signed long: NEED TO CHECK
- long const CLOCK_T_MIN = LONG_MIN;
- double const CLOCK_T_RANGE = static_cast(LONG_MAX) - static_cast(CLOCK_T_MIN);
- #endif
- #endif
-
-#elif defined __MINGW32__
- // Minimalist GNU for Windows
- // #define __USE_MINGW_ANSI_STDIO 1 // Fix long doubles output problem,
- // see http://stackoverflow.com/questions/7134547/gcc-printf-and-long-double-leads-to-wrong-output-c-type-conversion-messes-u
- #define WEXITSTATUS(x) ((x) & 0xff)
-
-#elif defined __HP_aCC
- // HP-UX aCC, byte order is big-endian, can be either 32-bit or 64-bit
- string const PLATFORM = "HP-UX aC++";
- // clock_t is an unsigned long: see
- unsigned long const CLOCK_T_MIN = 0;
- #ifdef __ia64
- // However, clock_t is a 32-bit unsigned long and we are using 64-bit unsigned longs here
- double const CLOCK_T_RANGE = 4294967295UL; // crude, improve
- #else
- double const CLOCK_T_RANGE = static_cast(ULONG_MAX);
- #endif
-#endif
-
-// TODO: Check
-// #if defined(WIN32)
-// #define STRCASECMP(a, b) (_stricmp(a, b))
-// #define STRNCASECMP(a, b, n) (_strnicmp(a, b, n))
-// #else
-// /** Alias for strcasecmp() */
-// #define STRCASECMP(a, b) (strcasecmp(a, b))
-// /** Alias for strncasecmp() */
-// #define STRNCASECMP(a, b, n) (strncasecmp(a, b, n))
-// //# endif
-// /** Alias for strncasecmp() == 0 */
-// #define EQUALN(a, b, n) (STRNCASECMP(a, b, n) == 0)
-// /** Alias for strcasecmp() == 0 */
-// #define EQUAL(a, b) (STRCASECMP(a, b) == 0)
-// #endif
-
-//===================================================== hard-wired constants ====================================================
-char const COLON = ':';
-char const COMMA = ',';
-char const DASH = '-';
-char const PATH_SEPARATOR = '/'; // Works for Windows too!
-char const QUOTE1 = ';';
-char const QUOTE2 = '#';
-char const SLASH = '/';
-char const SPACE = ' ';
-char const TILDE = '~';
-
-// TESTING options
-bool const ACCEPT_TRUNCATED_PROFILES = true;
-bool const CREATE_SHADOW_ZONE_IF_HITS_GRID_EDGE = true; // If shadow line tracing hits grid edge, create shadow zone?
-bool const SAVE_CSHORE_OUTPUT = true; // #ifdef CSHORE_FILE_INOUT || CSHORE_BOTH, append all CShore output files to a whole-run master
-bool const USE_DEEP_WATER_FOR_SHADOW_LINE = true; // Use deep water wave orientation in determining shadow line orientation?
-
-// Not likely that user will need to change these
-int const NUMBER_OF_RNGS = 2; // Number of random number generators
-int const SAVEMAX = 100000; // Maximum number of saves of spatial output
-int const BUF_SIZE = 2048; // Max length (inc. terminating NULL) of any C-type string
-int const CAPE_POINT_MIN_SPACING = 10; // In cells: for shadow zone stuff, cape points must not be closer than this
-int const CLOCK_CHECK_ITERATION = 5000; // If have done this many timesteps then reset the CPU time running total
-int const COAST_LENGTH_MAX = 100; // For safety check when tracing coast
-int const COAST_LENGTH_MIN_X_PROF_SPACE = 20; // Ignore very short coasts less than this x profile spacing
-
-//! The size of the arrays output by CShore. If this is changed, then must also set the same value on line 12 of cshore_wrapper.f03 (integer, parameter :: NN = 1000, NL = 1) and recompile CShore. Eventually we should move to dynamically allocated arrays TODO 070
-int const CSHOREARRAYOUTSIZE = 1000;
-
-int const FLOOD_FILL_START_OFFSET = 2; // In cells: cell-by-cell fill starts this distance inside polygon
-int const GRID_MARGIN = 10; // Ignore this many along-coast grid-edge points re. shadow zone calcs
-int const INT_NODATA = -9999; // CME's internal NODATA value for ints
-int const MAX_LEN_SHADOW_LINE_TO_IGNORE = 200; // In cells: if can't find cell-by-cell fill start point, continue if short shadow line
-int const MAX_NUM_PREV_ORIENTATION_VALUES = 10; // Max length of deque used in tracing shadow boundary
-int const MAX_NUM_SHADOW_ZONES = 10; // Consider at most this number of shadow zones
-int const MIN_INLAND_OFFSET_UNCONS_EROSION = 5; // Used in estimation of beach erosion
-int const MIN_PARALLEL_PROFILE_SIZE = 3; // In cells: min size for valid unconsolidated sediment parallel profile
-int const MIN_PROFILE_SIZE = 3; // In cells: min size for valid unconsolidated sediment profile
-int const DEFAULT_PROFILE_SPACING = 15; // In cells: profile creation does not work well if profiles are too closely spaced
-int const SAVGOL_POLYNOMIAL_MAX_ORDER = 6; // Maximum order of Savitzky-Golay smoothing polynomial
-
-// Log file detail level
-int const NO_LOG_FILE = 0;
-int const LOG_FILE_LOW_DETAIL = 1;
-int const LOG_FILE_MIDDLE_DETAIL = 2;
-int const LOG_FILE_HIGH_DETAIL = 3;
-int const LOG_FILE_ALL = 4;
-
-// Direction codes
-int const NO_DIRECTION = 0;
-int const NORTH = 1;
-int const NORTH_EAST = 2;
-int const EAST = 3;
-int const SOUTH_EAST = 4;
-int const SOUTH = 5;
-int const SOUTH_WEST = 6;
-int const WEST = 7;
-int const NORTH_WEST = 8;
-
-int const DIRECTION_DOWNCOAST = 0; // Down-coast, i.e. along the coast so that the index of coastline points INCREASES
-int const DIRECTION_UPCOAST = 1; // Up-coast, i.e. along the coast so that the index of coastline points DECREASES
-
-// Handedness codes, these show which side the sea is on when travelling down-coast (i.e. in the direction in which coastline point numbers INCREASE)
-int const NULL_HANDED = -1;
-int const RIGHT_HANDED = 0;
-int const LEFT_HANDED = 1;
-
-// Sediment texture codes
-int const TEXTURE_FINE = 0;
-int const TEXTURE_SAND = 1;
-int const TEXTURE_COARSE = 2;
-
-// Time unit codes
-int const TIME_UNKNOWN = -1;
-int const TIME_HOURS = 0;
-int const TIME_DAYS = 1;
-int const TIME_MONTHS = 2;
-int const TIME_YEARS = 3;
-
-// Intervention input and output codes
-int const IO_INTERVENTION_NONE = 0;
-int const IO_INTERVENTION_STRUCT = 1;
-int const IO_INTERVENTION_NON_STRUCT = 2;
-
-// Landform category codes
-int const LF_UNKNOWN = 0;
-int const LF_HINTERLAND = 1;
-int const LF_SEA = 2;
-int const LF_CLIFF_ON_COASTLINE = 6;
-int const LF_CLIFF_INLAND = 7;
-int const LF_DRIFT_TALUS = 9;
-int const LF_DRIFT_BEACH = 10;
-int const LF_DRIFT_DUNES = 11; // TODO 059 Implement dune landform class
-int const LF_INTERVENTION_STRUCT = 12;
-int const LF_INTERVENTION_NON_STRUCT = 13;
-int const LF_ISLAND = 14; // Not yet implemented
-int const LF_SEDIMENT_INPUT_UNCONSOLIDATED = 18;
-int const LF_SEDIMENT_INPUT_CONSOLIDATED = 19;
-
-// GIS raster input codes
-int const FINE_CONS_RASTER = 1;
-int const SAND_CONS_RASTER = 2;
-int const COARSE_CONS_RASTER = 3;
-int const FINE_UNCONS_RASTER = 4;
-int const SAND_UNCONS_RASTER = 5;
-int const COARSE_UNCONS_RASTER = 6;
-int const SUSP_SED_RASTER = 7;
-int const LANDFORM_RASTER = 8;
-int const INTERVENTION_CLASS_RASTER = 9;
-int const INTERVENTION_HEIGHT_RASTER = 10;
-
-// GIS vector data type codes
-int const VEC_FIELD_DATA_ANY = 0;
-int const VEC_FIELD_DATA_INT = 1;
-int const VEC_FIELD_DATA_REAL = 2;
-int const VEC_FIELD_DATA_STRING = 3;
-int const VEC_FIELD_DATA_OTHER = 4;
-
-// GIS vector geometry codes
-int const VEC_GEOMETRY_POINT = 1;
-int const VEC_GEOMETRY_LINE = 2;
-int const VEC_GEOMETRY_POLYGON = 3;
-int const VEC_GEOMETRY_OTHER = 4;
-
-// GIS vector input codes and constraints
-int const DEEP_WATER_WAVE_STATIONS_VEC = 1;
-int const DEEP_WATER_WAVE_STATIONS_MAX_LAYER = 1;
-int const DEEP_WATER_WAVE_STATIONS_POINT_GEOMETRY = VEC_GEOMETRY_POINT;
-int const SEDIMENT_INPUT_EVENT_LOCATION_VEC = 2;
-int const SEDIMENT_INPUT_EVENT_LOCATION_MAX_LAYER = 1;
-int const SEDIMENT_INPUT_EVENT_LOCATION_POINT_GEOMETRY = VEC_GEOMETRY_POINT;
-int const FLOOD_LOCATION_POINT_GEOMETRY = VEC_GEOMETRY_POINT;
-int const SEDIMENT_INPUT_EVENT_LOCATION_LINE_GEOMETRY = VEC_GEOMETRY_LINE;
-int const FLOOD_LOCATION_VEC = 3;
-int const FLOOD_LOCATION_MAX_LAYER = 1;
-
-// GIS raster output codes
-
-int const RASTER_PLOT_ACTIVE_ZONE = 1;
-int const RASTER_PLOT_ACTUAL_BEACH_EROSION = 2;
-int const RASTER_PLOT_ACTUAL_PLATFORM_EROSION = 3;
-int const RASTER_PLOT_AVG_SEA_DEPTH = 4;
-int const RASTER_PLOT_AVG_SUSPENDED_SEDIMENT = 5;
-int const RASTER_PLOT_AVG_WAVE_HEIGHT = 6;
-int const RASTER_PLOT_AVG_WAVE_ORIENTATION = 7;
-int const RASTER_PLOT_BASEMENT_ELEVATION = 8;
-int const RASTER_PLOT_BEACH_DEPOSITION = 9;
-int const RASTER_PLOT_BEACH_MASK = 10;
-int const RASTER_PLOT_BEACH_PROTECTION = 11;
-int const RASTER_PLOT_CLIFF_COLLAPSE_DEPOSITION_COARSE = 12;
-int const RASTER_PLOT_CLIFF_COLLAPSE_DEPOSITION_SAND = 13;
-int const RASTER_PLOT_CLIFF_COLLAPSE_EROSION_COARSE = 14;
-int const RASTER_PLOT_CLIFF_COLLAPSE_EROSION_FINE = 15;
-int const RASTER_PLOT_CLIFF_COLLAPSE_EROSION_SAND = 16;
-#ifdef _DEBUG
-int const RASTER_PLOT_CLIFF_COLLAPSE_TIMESTEP = 17;
-#endif
-int const RASTER_PLOT_CLIFF_NOTCH_ALL = 18;
-int const RASTER_PLOT_CLIFF_TOE = 19;
-int const RASTER_PLOT_COARSE_CONSOLIDATED_SEDIMENT = 20;
-int const RASTER_PLOT_COARSE_UNCONSOLIDATED_SEDIMENT = 21;
-int const RASTER_PLOT_COAST = 22;
-int const RASTER_PLOT_DEEP_WATER_WAVE_HEIGHT = 23;
-int const RASTER_PLOT_DEEP_WATER_WAVE_ORIENTATION = 24;
-int const RASTER_PLOT_DEEP_WATER_WAVE_PERIOD = 25;
-int const RASTER_PLOT_FINE_CONSOLIDATED_SEDIMENT = 26;
-int const RASTER_PLOT_FINE_UNCONSOLIDATED_SEDIMENT = 27;
-int const RASTER_PLOT_INTERVENTION_CLASS = 28;
-int const RASTER_PLOT_INTERVENTION_HEIGHT = 29;
-int const RASTER_PLOT_INUNDATION_MASK = 30;
-int const RASTER_PLOT_LANDFORM = 31;
-int const RASTER_PLOT_NORMAL_PROFILE = 32;
-int const RASTER_PLOT_TOP_ELEV_INC_SEA = 33;
-int const RASTER_PLOT_POLYGON = 34;
-int const RASTER_PLOT_POLYGON_GAIN_OR_LOSS = 35;
-int const RASTER_PLOT_POLYGON_UPDRIFT_OR_DOWNDRIFT = 36;
-int const RASTER_PLOT_POTENTIAL_BEACH_EROSION = 37;
-int const RASTER_PLOT_POTENTIAL_PLATFORM_EROSION = 38;
-int const RASTER_PLOT_POTENTIAL_PLATFORM_EROSION_MASK = 39;
-int const RASTER_PLOT_SAND_CONSOLIDATED_SEDIMENT = 40;
-int const RASTER_PLOT_SAND_UNCONSOLIDATED_SEDIMENT = 41;
-int const RASTER_PLOT_SEA_DEPTH = 42;
-int const RASTER_PLOT_SEDIMENT_INPUT = 43;
-int const RASTER_PLOT_SED_TOP_INC_TALUS_ELEV = 44;
-int const RASTER_PLOT_SETUP_SURGE_FLOOD_MASK = 45;
-int const RASTER_PLOT_SETUP_SURGE_RUNUP_FLOOD_MASK = 46;
-int const RASTER_PLOT_SHADOW_DOWNDRIFT_ZONE = 47;
-int const RASTER_PLOT_SHADOW_ZONE = 48;
-int const RASTER_PLOT_SLICE = 49;
-int const RASTER_PLOT_SLOPE_FOR_CLIFF_TOE = 50;
-int const RASTER_PLOT_CONS_SED_SLOPE = 51;
-int const RASTER_PLOT_SUSPENDED_SEDIMENT = 52;
-int const RASTER_PLOT_TALUS = 53;
-int const RASTER_PLOT_TOTAL_ACTUAL_BEACH_EROSION = 54;
-int const RASTER_PLOT_TOTAL_ACTUAL_PLATFORM_EROSION = 55;
-int const RASTER_PLOT_TOTAL_BEACH_DEPOSITION = 56;
-int const RASTER_PLOT_TOTAL_CLIFF_COLLAPSE_DEPOSITION_COARSE = 57;
-int const RASTER_PLOT_TOTAL_CLIFF_COLLAPSE_DEPOSITION_SAND = 58;
-int const RASTER_PLOT_TOTAL_CLIFF_COLLAPSE_EROSION_COARSE = 59;
-int const RASTER_PLOT_TOTAL_CLIFF_COLLAPSE_EROSION_FINE = 60;
-int const RASTER_PLOT_TOTAL_CLIFF_COLLAPSE_EROSION_SAND = 61;
-int const RASTER_PLOT_TOTAL_POTENTIAL_BEACH_EROSION = 62;
-int const RASTER_PLOT_TOTAL_POTENTIAL_PLATFORM_EROSION = 63;
-int const RASTER_PLOT_WAVE_FLOOD_LINE = 64;
-int const RASTER_PLOT_WAVE_HEIGHT = 65;
-int const RASTER_PLOT_WAVE_ORIENTATION = 66;
-
-// GIS vector output codes
-// int const VECTOR_PLOT_FLOOD_SWL_SETUP_LINE = 19;
-int const VECTOR_PLOT_AVG_WAVE_ANGLE_AND_HEIGHT = 1;
-int const VECTOR_PLOT_BREAKING_WAVE_HEIGHT = 2;
-int const VECTOR_PLOT_CLIFF_EDGE = 3;
-int const VECTOR_PLOT_CLIFF_NOTCH_ACTIVE = 4;
-int const VECTOR_PLOT_COAST = 5;
-int const VECTOR_PLOT_COAST_CURVATURE = 6;
-int const VECTOR_PLOT_COAST_SWL_HIGHEST = 7;
-int const VECTOR_PLOT_COAST_SWL_LOWEST = 8;
-int const VECTOR_PLOT_DEEP_WATER_WAVE_ANGLE_AND_HEIGHT = 9;
-int const VECTOR_PLOT_DOWNDRIFT_ZONE_BOUNDARY = 10;
-int const VECTOR_PLOT_FLOOD_LINE = 11;
-int const VECTOR_PLOT_INVALID_NORMALS = 12;
-int const VECTOR_PLOT_MEAN_WAVE_ENERGY = 13;
-int const VECTOR_PLOT_NORMALS = 14;
-int const VECTOR_PLOT_POLYGON_BOUNDARY = 15;
-int const VECTOR_PLOT_POLYGON_NODES = 16;
-int const VECTOR_PLOT_RUN_UP = 17;
-int const VECTOR_PLOT_SHADOW_ZONE_BOUNDARY = 18;
-int const VECTOR_PLOT_STORM_SURGE = 19;
-int const VECTOR_PLOT_WAVE_ANGLE_AND_HEIGHT = 20;
-int const VECTOR_PLOT_WAVE_ENERGY_SINCE_COLLAPSE = 21;
-int const VECTOR_PLOT_WAVE_SETUP = 22;
-int const VECTOR_PLOT_WAVE_TRANSECT_POINTS = 23;
-// int const VECTOR_PLOT_FLOOD_SWL_SETUP_SURGE_LINE = 24;
-// int const VECTOR_PLOT_FLOOD_SWL_SETUP_SURGE_RUNUP_LINE = 25;
-
-// Return codes
-int const RTN_OK = 0;
-int const RTN_HELP_ONLY = 1;
-int const RTN_CHECK_ONLY = 2;
-int const RTN_USER_ABORT = 3;
-int const RTN_ERR_BADPARAM = 4;
-int const RTN_ERR_INI = 5;
-int const RTN_ERR_CMEDIR = 6;
-int const RTN_ERR_RUNDATA = 7;
-int const RTN_ERR_SCAPE_SHAPE_FUNCTION_FILE = 8;
-int const RTN_ERR_TIDEDATAFILE = 9;
-int const RTN_ERR_LOGFILE = 10;
-int const RTN_ERR_OUTFILE = 11;
-int const RTN_ERR_TSFILE = 12;
-int const RTN_ERR_DEMFILE = 13;
-int const RTN_ERR_RASTER_FILE_READ = 14;
-int const RTN_ERR_VECTOR_FILE_READ = 15;
-int const RTN_ERR_MEMALLOC = 16;
-int const RTN_ERR_RASTER_GIS_OUT_FORMAT = 17;
-int const RTN_ERR_VECTOR_GIS_OUT_FORMAT = 18;
-int const RTN_ERR_TEXT_FILE_WRITE = 19;
-int const RTN_ERR_RASTER_FILE_WRITE = 20;
-int const RTN_ERR_VECTOR_FILE_WRITE = 21;
-int const RTN_ERR_TIMESERIES_FILE_WRITE = 22;
-int const RTN_ERR_LINETOGRID = 23;
-int const RTN_ERR_PROFILE_SPACING = 24;
-// 25 is now missing
-int const RTN_ERR_PROFILE_ENDPOINT_IS_INLAND = 26;
-int const RTN_ERR_NO_SOLUTION_FOR_ENDPOINT = 27;
-int const RTN_ERR_PROFILE_END_INSUFFICIENT_DEPTH = 28;
-int const RTN_ERR_NO_PROFILES_1 = 29;
-int const RTN_ERR_NO_PROFILES_2 = 30;
-int const RTN_ERR_NOSEACELLS = 31;
-int const RTN_ERR_GRID_TO_LINE = 32;
-int const RTN_ERR_NO_COAST = 34;
-int const RTN_ERR_PROFILE_WRITE = 35;
-int const RTN_ERR_TIME_UNITS = 36;
-int const RTN_ERR_CLIFF_NOTCH = 37;
-int const RTN_ERR_CLIFF_CANNOT_DEPOSIT_ALL = 38;
-int const RTN_ERR_BAD_INDEX = 39;
-int const RTN_ERR_EDGE_OF_GRID = 40;
-int const RTN_ERR_NO_SEAWARD_END_OF_PROFILE_BEACH_EROSION = 42;
-int const RTN_ERR_NO_SEAWARD_END_OF_PROFILE_UPCOAST_BEACH_DEPOSITION = 43;
-int const RTN_ERR_NO_SEAWARD_END_OF_PROFILE_DOWNCOAST_BEACH_DEPOSITION = 44;
-int const RTN_ERR_LANDFORM_TO_GRID = 45;
-int const RTN_ERR_NO_TOP_LAYER = 46;
-int const RTN_ERR_NO_ADJACENT_POLYGON = 47;
-int const RTN_ERR_BAD_MULTILINE = 48;
-int const RTN_ERR_CANNOT_INSERT_POINT = 49;
-int const RTN_ERR_CANNOT_ASSIGN_COASTAL_LANDFORM = 50;
-int const RTN_ERR_SHADOW_ZONE_FLOOD_FILL_NOGRID = 51;
-int const RTN_ERR_SHADOW_ZONE_FLOOD_START_POINT = 52;
-int const RTN_ERR_CSHORE_EMPTY_PROFILE = 53;
-int const RTN_ERR_CSHORE_FILE_INPUT = 54;
-int const RTN_ERR_READING_CSHORE_FILE_OUTPUT = 55;
-int const RTN_ERR_WAVE_INTERPOLATION_LOOKUP = 56;
-int const RTN_ERR_GRIDCREATE = 57;
-int const RTN_ERR_COAST_CANT_FIND_EDGE_CELL = 58;
-int const RTN_ERR_CSHORE_ERROR = 59;
-int const RTN_ERR_NO_CELL_UNDER_COASTLINE = 60;
-int const RTN_ERR_OPEN_DEEP_WATER_WAVE_DATA = 61;
-int const RTN_ERR_READING_DEEP_WATER_WAVE_DATA = 62;
-int const RTN_ERR_BOUNDING_BOX = 63;
-int const RTN_ERR_READING_SEDIMENT_INPUT_EVENT = 64;
-int const RTN_ERR_SEDIMENT_INPUT_EVENT = 65;
-int const RTN_ERR_SEDIMENT_INPUT_EVENT_LOCATION = 66;
-int const RTN_ERR_WAVESTATION_LOCATION = 67;
-int const RTN_ERR_FLOOD_LOCATION = 68;
-int const RTN_ERR_CLIFF_NOT_IN_POLYGON = 69;
-int const RTN_ERR_CELL_MARKED_PROFILE_COAST_BUT_NOT_PROFILE = 70;
-int const RTN_ERR_TRACING_FLOOD = 71;
-int const RTN_ERR_NO_START_FINISH_POINTS_TRACING_COAST = 72;
-int const RTN_ERR_NO_VALID_COAST = 73;
-int const RTN_ERR_REPEATING_WHEN_TRACING_COAST = 74;
-int const RTN_ERR_ZERO_LENGTH_COAST = 75;
-int const RTN_ERR_COAST_TOO_SMALL = 77;
-int const RTN_ERR_IGNORING_COAST = 78;
-int const RTN_ERR_TOO_LONG_TRACING_COAST = 79;
-int const RTN_ERR_CELL_NOT_FOUND_IN_HIT_PROFILE_DIFFERENT_COASTS = 80;
-int const RTN_ERR_POINT_NOT_FOUND_IN_MULTILINE_DIFFERENT_COASTS = 81;
-int const RTN_ERR_CELL_NOT_FOUND_IN_HIT_PROFILE = 82;
-int const RTN_ERR_CELL_IN_POLY_BUT_NO_POLY_COAST = 83;
-int const RTN_ERR_CLIFF_TALUS_TO_UNCONS = 84;
-int const RTN_ERR_UNKNOWN = 999;
-
-// Elevation and 'slice' codes
-int const ELEV_IN_BASEMENT = -1;
-int const ELEV_ABOVE_SEDIMENT_TOP = -2;
-int const NO_NONZERO_THICKNESS_LAYERS = -3;
-
-// Vector smoothing codes
-int const SMOOTH_NONE = 0;
-int const SMOOTH_RUNNING_MEAN = 1;
-int const SMOOTH_SAVITZKY_GOLAY = 2;
-
-// Grid-edge boundary treatment for unconsolidated sediment movement
-int const GRID_EDGE_CLOSED = 0;
-int const GRID_EDGE_OPEN = 1;
-int const GRID_EDGE_RECIRCULATE = 2;
-
-// Model for wave propagation
-int const WAVE_MODEL_COVE = 0;
-int const WAVE_MODEL_CSHORE = 1;
-
-// Equation for estimating erosion of unconsolidated sediment
-int const UNCONS_SEDIMENT_EQUATION_CERC = 0;
-int const UNCONS_SEDIMENT_EQUATION_KAMPHUIS = 1;
-
-int const CLIFF_COLLAPSE_LENGTH_INCREMENT = 10; // Increment the planview length of the cliff talus Dean profile, if we have not been able to deposit enough
-int const PROFILE_CHECK_DIST_FROM_COAST = 20; // TEST TODO Used in checking shoreline-normal profiles for intersection
-int const GAP_BETWEEN_DIFFERENT_COAST_PROFILES = 30; // In cells, is the gap between profile ends belonging to different coasts
-
-int const NUM_DAYS_FOR_MEAN_HIGH_WATER_CALC = 30; // Number of days to average daily high water elevation
-
-int const NO_RUNUP_EQUATION = 0; // Runup not considered
-int const RUNUP_EQUATION_NIELSEN_HANSLOW = 1; // Runup equation is Nielsen, P. & Hanslow, D. J. 1991. Wave Runup Distributions on Natural Beaches. Journal of Coastal Research, 7, 1139-1152. *** & DHI (2004) ???
-int const RUNUP_EQUATION_MASE = 2; // Runup equation is Mase, H. 1989. Random Wave Runup Height on Gentle Slope. Journal of Waterway, Port, Coastal, and Ocean Engineering, 115, 649-661.
-int const RUNUP_EQUATION_STOCKDON = 3; // Runup equation is Stockdon, H. F., Holman, R. A., Howd, P. A. & Sallenger JR, A. H. 2006. Empirical parameterization of setup, swash, and runup. Coastal Engineering, 53, 573-588.
-
-unsigned long const MASK = 0xfffffffful;
-unsigned long const SEDIMENT_INPUT_EVENT_ERROR = -1;
-unsigned long const UNSIGNED_LONG_NODATA = 9999;
-
-double const PI = 3.141592653589793238462643;
-
-double const D50_FINE_DEFAULT = 0.0625; // In mm
-double const D50_SAND_DEFAULT = 0.42; // In mm
-double const D50_COARSE_DEFAULT = 19.0; // In mm
-
-double const BEACH_PROTECTION_HB_RATIO = 0.23; // The beach protection factor is this times breaking depth
-double const WALKDEN_HALL_PARAM_1 = 3.25; // First parameter in Equation 4 from Walkden & Hall, 2005
-double const WALKDEN_HALL_PARAM_2 = 1.50; // Second parameter in Equation 4 from Walkden & Hall, 2005
-
-double const DEPTH_OVER_DB_INCREMENT = 0.001; // Depth over DB increment for erosion potential look-up function
-double const INVERSE_DEPTH_OVER_DB_INCREMENT = 1000; // Inverse of the above
-double const DEAN_POWER = 2.0 / 3.0; // Dean profile exponent
-
-// TODO 011 Let the user define these CShore input parameters
-double const CSHORE_FRICTION_FACTOR = 0.015; // Friction factor for CShore model
-double const CSHORE_SURGE_LEVEL = 0.0; // TODO 007
-
-double const TOLERANCE = 1e-7; // For bFPIsEqual, if too small (e.g. 1e-10), get spurious "rounding" errors
-double const SED_ELEV_TOLERANCE = 1e-5; // Used to compare depth-equivalent sediment amounts in bFPIsEqual and elsewhere
-double const MASS_BALANCE_TOLERANCE = 1e-5; // For bFPIsEqual, used to compare for mass balance checks
-double const STRAIGHT_COAST_MAX_DETAILED_CURVATURE = -5;
-double const STRAIGHT_COAST_MAX_SMOOTH_CURVATURE = -1;
-double const MIN_LENGTH_OF_SHADOW_ZONE_LINE = 10; // Used in shadow line tracing
-double const MAX_LAND_LENGTH_OF_SHADOW_ZONE_LINE = 5; // Used in shadow line tracing
-double const CLIFF_COLLAPSE_HEIGHT_INCREMENT = 0.1; // Increment the fractional height of the cliff talus Dean profile, if we have not been able to deposit enough
-double const INTERVENTION_PROFILE_SPACING_FACTOR = 0.5; // Profile spacing on interventions works better if it is smaller than profile spacing on coastline
-
-double const CLIFF_NOTCH_CUTOFF_DISTANCE = 2; // Cut-off SWL distance (m), measured downwards from the cliff notch apex: below this there is no notch incision
-double const DBL_NODATA = -9999;
-
-string const PROGRAM_NAME = "Coastal Modelling Environment (CoastalME) version 1.4.0 (11 Nov 2025)";
-string const PROGRAM_NAME_SHORT = "CME";
-string const CME_INI = "cme.ini";
-
-string const COPYRIGHT = "(C) 2025 Andres Payo and David Favis-Mortlock";
-string const LINE = "-------------------------------------------------------------------------------";
-string const DISCLAIMER1 = "This program is distributed in the hope that it will be useful, but WITHOUT ANY";
-string const DISCLAIMER2 = "WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A";
-string const DISCLAIMER3 = "PARTICULAR PURPOSE. See the GNU General Public License for more details. You";
-string const DISCLAIMER4 = "should have received a copy of the GNU General Public License along with this";
-string const DISCLAIMER5 = "program; if not, contact the Free Software Foundation, Inc., 675 Mass Ave,";
-string const DISCLAIMER6 = "Cambridge, MA 02139, USA.";
-
-string const ABOUT = "simulates the long-term behaviour of a coast. This initial version considers only simple soft cliff cross-shore effects";
-string const THANKS = "Many thanks to:\n\tTom Ashby\n\tManuel Cobos Budia\n\tWilf Chun\n\tMark Dickson\n\tJim W. Hall\n\tMartin D. Hurst\n\tMatthew Ives\n\tRobert J. Nicholls\n\tIan Townend\n\tMike J.A. Walkden";
-string const GDAL_DRIVERS = "GDAL drivers";
-
-string const USAGE = "Usage: cme [OPTION]...";
-string const USAGE1 = " --gdal List GDAL drivers";
-string const USAGE2 = " --about Information about this program";
-string const USAGE3 = " --help Display this text";
-string const USAGE4 = " --home=DIRECTORY Specify the location of the .ini file etc.";
-string const USAGE5 = " --datafile=FILE Specify the location and name of the main datafile";
-string const USAGE6 = " --yaml Use YAML format for the main datafile";
-
-string const START_NOTICE = "- Started on ";
-string const INITIALIZING_NOTICE = "- Initializing";
-string const READING_FILE_LOCATIONS = " - Reading file locations: ";
-string const READING_RUN_DATA = " - Reading run data file: ";
-string const READING_BASEMENT = " - Reading basement DEM: ";
-string const READING_RASTER_FILES = " - Reading raster GIS files";
-string const READING_LANDFORM_FILE = " - Landform class: ";
-string const READING_INTERVENTION_CLASS_FILE = " - Intervention class: ";
-string const READING_INTERVENTION_HEIGHT_FILE = " - Intervention height: ";
-string const READING_SUSPENDED_SEDIMENT_FILE = " - Suspended sediment: ";
-string const READING_UNCONS_FINE_SEDIMENT_FILE = " - Unconsolidated fine sediment (layer ";
-string const READING_UNCONS_SAND_SEDIMENT_FILE = " - Unconsolidated sand sediment (layer ";
-string const READING_UNCONS_COARSE_SEDIMENT_FILE = " - Unconsolidated coarse sediment (layer ";
-string const READING_CONS_FINE_SEDIMENT_FILE = " - Consolidated fine sediment (layer ";
-string const READING_CONS_SAND_SEDIMENT_FILE = " - Consolidated sand sediment (layer ";
-string const READING_CONS_COARSE_SEDIMENT_FILE = " - Consolidated coarse sediment (layer ";
-string const READING_VECTOR_FILES = " - Reading vector GIS files";
-string const READING_DEEP_WATER_WAVE_FILE = " - Deep water wave values: ";
-string const READING_SED_INPUT_EVENT_FILE = " - Sediment input event values: ";
-string const READING_FLOOD_LOCATION = " - Characteristic locations for flood: ";
-string const READING_SCAPE_SHAPE_FUNCTION_FILE = " - Reading SCAPE shape function file";
-string const READING_TIDE_DATA_FILE = " - Reading tide data file: ";
-string const ALLOCATE_MEMORY = " - Allocating memory for raster grid";
-string const ADD_LAYERS = " - Adding sediment layers to raster grid";
-string const INITIALIZING_FINAL = " - Finishing initialization";
-string const RUN_NOTICE = "- Running simulation";
-string const SIMULATING = "\r - Simulating ";
-string const FINAL_OUTPUT = "- Writing final output";
-string const SEND_EMAIL = " - Sending email to ";
-string const RUN_END_NOTICE = "Run ended at ";
-string const PRESS_KEY = "Press any key to continue...";
-
-string const ERROR_NOTICE = " with error code ";
-string const EMAIL_ERROR = "Could not send email";
-
-string const SCAPE_DIR = "scape/";
-string const SCAPE_SHAPE_FUNCTION_FILE = "ShapeFunction.dat";
-string const EROSION_POTENTIAL_LOOKUP_FILE = "ErosionPotential.csv";
-
-string const CSHORE_DIR = "cshore/";
-string const CSHORE_INFILE = "infile";
-
-string const ERR = "*** ERROR ";
-string const WARN = "WARNING ";
-string const NOTE = " Note ";
-
-string const MASS_BALANCE_ERROR = "MASS BALANCE ERROR";
-
-string const PER_ITER_HEAD1 = "<-----ELAPSED----><--SEA-><----POTENTIAL---><-----------ACTUAL-----------><-----POTENTIAL-----><------------ACTUAL-------------><-----------ACTUAL------------><--SEDIMENT--><---CLIFF COLLAPSE--->";
-
-string const PER_ITER_HEAD2 = " TIME DEPTH PLATFORM EROSION PLATFORM EROSION BEACH EROSION BEACH EROSION BEACH DEPOSITION INPUT EVENT EROSION DEPOSITION SED";
-
-string const PER_ITER_HEAD3 = "Time Hours Years Avg % Sea All Erod % Sea All Erod <--sea avg-> % Sea All Erod % Sea All Erod <--sea avg-> % Sea All Depos <--sea--> <-coast avg-><--sea-->";
-
-string const PER_ITER_HEAD4 = "Step Area Sea Area Area Sea Area F S C Area Sea Area Area Sea Area F S C Area Sea Area S C F S C F S C S C F";
-
-string const PER_ITER_HEAD5 = " Avg Avg Avg Avg Avg Avg Avg Avg Avg";
-
-string const PER_ITER_HEAD = "PER-ITERATION RESULTS =============================================================================================================================================================================================";
-
-string const PER_ITER_CSV_HEAD = "Timestep,Hours, Years, AvgSeaDepth_m, PotPlatformErosion_PctSeaArea, PotPlatformErosion_AllAvg_mm, PotPlatformErosion_ErodAvg_mm, ActPlatformErosion_PctSeaArea, ActPlatformErosion_AllAvg_mm, ActPlatformErosion_ErodAvg_mm, ActPlatformErosion_Fine_mm, ActPlatformErosion_Sand_mm, ActPlatformErosion_Coarse_mm, PotBeachErosion_PctSeaArea, PotBeachErosion_AllAvg_mm, PotBeachErosion_ErodAvg_mm, ActBeachErosion_PctSeaArea, ActBeachErosion_AllAvg_mm, ActBeachErosion_ErodAvg_mm, ActBeachErosion_Fine_mm, ActBeachErosion_Sand_mm, ActBeachErosion_Coarse_mm, BeachDeposition_PctSeaArea, BeachDeposition_AllAvg_mm, BeachDeposition_DepAvg_mm, BeachDeposition_Sand_mm, BeachDeposition_Coarse_mm, SedimentInput_Fine, SedimentInput_Sand, SedimentInput_Coarse, CliffCollapse_Fine_mm, CliffCollapse_Sand_mm, CliffCollapse_Coarse_mm, CliffDeposition_Sand_mm, CliffDeposition_Coarse_mm, SuspendedSediment_mm, GISEvents";
-
-string const ENDHYDROLOGYHEAD = "END OF SIMULATION: HYDROLOGY ======================================================================================================================================================================================";
-string const ENDSEDIMENTHEAD = "END OF SIMULATION: SEDIMENT MOVEMENT ==============================================================================================================================================================================";
-string const PERFORMHEAD = "END OF SIMULATION: PERFORMANCE ====================================================================================================================================================================================";
-
-string const OUTEXT = ".out";
-string const LOGEXT = ".log";
-string const CSVEXT = ".csv";
-
-string const DEEP_WATER_WAVE_STATION_ID = "id";
-string const SEDIMENT_INPUT_EVENT_LOCATION_ID = "id";
-string const FLOOD_LOCATION_ID = "id";
-
-// GIS raster output user codes
-string const RASTER_ACTIVE_ZONE_CODE = "active_zone";
-string const RASTER_ACTIVE_ZONE_NAME = "active_zone";
-string const RASTER_ACTUAL_BEACH_EROSION_CODE = "actual_beach_erosion";
-string const RASTER_ACTUAL_BEACH_EROSION_NAME = "actual_beach_erosion";
-string const RASTER_ACTUAL_PLATFORM_EROSION_CODE = "actual_platform_erosion";
-string const RASTER_ACTUAL_PLATFORM_EROSION_NAME = "actual_platform_erosion";
-string const RASTER_ALL_OUTPUT_CODE = "all";
-string const RASTER_AVG_SEA_DEPTH_CODE = "avg_sea_depth";
-string const RASTER_AVG_SEA_DEPTH_NAME = "avg_sea_depth";
-string const RASTER_AVG_SUSP_SED_CODE = "avg_susp_sed";
-string const RASTER_AVG_SUSP_SED_NAME = "avg_susp_sed";
-string const RASTER_AVG_WAVE_HEIGHT_CODE = "avg_wave_height";
-string const RASTER_AVG_WAVE_HEIGHT_NAME = "avg_wave_height";
-string const RASTER_AVG_WAVE_ORIENTATION_CODE = "avg_wave_orientation";
-string const RASTER_AVG_WAVE_ORIENTATION_NAME = "avg_wave_orientation";
-string const RASTER_BASEMENT_ELEVATION_CODE = "basement_elevation";
-string const RASTER_BASEMENT_ELEVATION_NAME = "basement_elevation";
-string const RASTER_BEACH_DEPOSITION_CODE = "beach_deposition";
-string const RASTER_BEACH_DEPOSITION_NAME = "beach_deposition";
-string const RASTER_BEACH_MASK_CODE = "beach_mask";
-string const RASTER_BEACH_MASK_NAME = "beach_mask";
-string const RASTER_BEACH_PROTECTION_CODE = "beach_protection";
-string const RASTER_BEACH_PROTECTION_NAME = "beach_protection";
-string const RASTER_CLIFF_COLLAPSE_DEPOSITION_COARSE_CODE = "cliff_collapse_talus_deposition_coarse";
-string const RASTER_CLIFF_COLLAPSE_DEPOSITION_COARSE_NAME = "cliff_collapse_talus_deposition_coarse";
-string const RASTER_CLIFF_COLLAPSE_DEPOSITION_SAND_CODE = "cliff_collapse_talus_deposition_sand";
-string const RASTER_CLIFF_COLLAPSE_DEPOSITION_SAND_NAME = "cliff_collapse_talus_deposition_sand";
-string const RASTER_CLIFF_COLLAPSE_EROSION_COARSE_CODE = "cliff_collapse_erosion_coarse";
-string const RASTER_CLIFF_COLLAPSE_EROSION_COARSE_NAME = "cliff_collapse_erosion_coarse";
-string const RASTER_CLIFF_COLLAPSE_EROSION_FINE_CODE = "cliff_collapse_erosion_fine";
-string const RASTER_CLIFF_COLLAPSE_EROSION_FINE_NAME = "cliff_collapse_erosion_fine";
-string const RASTER_CLIFF_COLLAPSE_EROSION_SAND_CODE = "cliff_collapse_erosion_sand";
-string const RASTER_CLIFF_COLLAPSE_EROSION_SAND_NAME = "cliff_collapse_erosion_sand";
-string const RASTER_CLIFF_COLLAPSE_TIMESTEP_CODE = "cliff_collapse_timestep";
-string const RASTER_CLIFF_COLLAPSE_TIMESTEP_NAME = "cliff_collapse_timestep_all";
-string const RASTER_CLIFF_NOTCH_ALL_CODE = "cliff_notch_all";
-string const RASTER_CLIFF_NOTCH_ALL_NAME = "cliff_notch_all";
-string const RASTER_CLIFF_TOE_NAME = "cliff_toe"; // Note no code for this, because is chosen by m_bCliffToeLocate in input file
-string const RASTER_COARSE_CONS_CODE = "cons_sed_coarse";
-string const RASTER_COARSE_CONS_NAME = "cons_sed_coarse";
-string const RASTER_COARSE_UNCONS_CODE = "uncons_sed_coarse";
-string const RASTER_COARSE_UNCONS_NAME = "uncons_sed_coarse";
-string const RASTER_COAST_CODE = "rcoast";
-string const RASTER_COAST_NAME = "rcoast";
-string const RASTER_COAST_NORMAL_CODE = "rcoast_normal";
-string const RASTER_COAST_NORMAL_NAME = "rcoast_normal";
-string const RASTER_DEEP_WATER_WAVE_HEIGHT_CODE = "deep_water_wave_height";
-string const RASTER_DEEP_WATER_WAVE_HEIGHT_NAME = "deep_water_wave_height";
-string const RASTER_DEEP_WATER_WAVE_ORIENTATION_CODE = "deep_water_wave_orientation";
-string const RASTER_DEEP_WATER_WAVE_ORIENTATION_NAME = "deep_water_wave_orientation";
-string const RASTER_DEEP_WATER_WAVE_PERIOD_CODE = "deep_water_wave_period";
-string const RASTER_DEEP_WATER_WAVE_PERIOD_NAME = "deep_water_wave_period";
-string const RASTER_FINE_CONS_CODE = "cons_sed_fine";
-string const RASTER_FINE_CONS_NAME = "cons_sed_fine";
-string const RASTER_FINE_UNCONS_CODE = "uncons_sed_fine";
-string const RASTER_FINE_UNCONS_NAME = "uncons_sed_fine";
-string const RASTER_INTERVENTION_CLASS_CODE = "intervention_class";
-string const RASTER_INTERVENTION_CLASS_NAME = "intervention_class";
-string const RASTER_INTERVENTION_HEIGHT_CODE = "intervention_height";
-string const RASTER_INTERVENTION_HEIGHT_NAME = "intervention_height";
-string const RASTER_INUNDATION_MASK_CODE = "inundation_mask";
-string const RASTER_INUNDATION_MASK_NAME = "inundation_mask";
-string const RASTER_LANDFORM_CODE = "landform_class";
-string const RASTER_LANDFORM_NAME = "landform_class";
-string const RASTER_POLYGON_CODE = "polygon_raster";
-string const RASTER_POLYGON_GAIN_OR_LOSS_CODE = "polygon_gain_or_loss";
-string const RASTER_POLYGON_GAIN_OR_LOSS_NAME = "polygon_gain_or_loss";
-string const RASTER_POLYGON_NAME = "polygon_raster";
-string const RASTER_POLYGON_UPDRIFT_OR_DOWNDRIFT_CODE = "polygon_updrift_or_downdrift";
-string const RASTER_POLYGON_UPDRIFT_OR_DOWNDRIFT_NAME = "polygon_updrift_or_downdrift";
-string const RASTER_POTENTIAL_BEACH_EROSION_CODE = "potential_beach_erosion";
-string const RASTER_POTENTIAL_BEACH_EROSION_NAME = "potential_beach_erosion";
-string const RASTER_POTENTIAL_PLATFORM_EROSION_CODE = "potential_platform_erosion";
-string const RASTER_POTENTIAL_PLATFORM_EROSION_MASK_CODE = "potential_platform_erosion_mask";
-string const RASTER_POTENTIAL_PLATFORM_EROSION_MASK_NAME = "potential_platform_erosion_mask";
-string const RASTER_POTENTIAL_PLATFORM_EROSION_NAME = "potential_platform_erosion";
-string const RASTER_SAND_CONS_CODE = "cons_sed_sand";
-string const RASTER_SAND_CONS_NAME = "cons_sed_sand";
-string const RASTER_SAND_UNCONS_CODE = "uncons_sed_sand";
-string const RASTER_SAND_UNCONS_NAME = "uncons_sed_sand";
-string const RASTER_SEA_DEPTH_CODE = "sea_depth";
-string const RASTER_SEA_DEPTH_NAME = "sea_depth";
-string const RASTER_SEDIMENT_INPUT_EVENT_CODE = "sediment_input_total";
-string const RASTER_SEDIMENT_INPUT_EVENT_NAME = "sediment_input_total";
-string const RASTER_SEDIMENT_TOP_CODE = "sediment_top_elevation";
-string const RASTER_SEDIMENT_TOP_ELEVATION_NAME = "sediment_top_elevation";
-string const RASTER_SETUP_SURGE_FLOOD_MASK_CODE = "flood_setup_surge_mask";
-string const RASTER_SETUP_SURGE_FLOOD_MASK_NAME = "flood_setup_surge_mask";
-string const RASTER_SETUP_SURGE_RUNUP_FLOOD_MASK_CODE = "flood_setup_surge_runup_mask";
-string const RASTER_SETUP_SURGE_RUNUP_FLOOD_MASK_NAME = "flood_setup_surge_runup_mask";
-string const RASTER_SHADOW_DOWNDRIFT_ZONE_CODE = "shadow_downdrift_zones";
-string const RASTER_SHADOW_DOWNDRIFT_ZONE_NAME = "shadow_downdrift_zones";
-string const RASTER_SHADOW_ZONE_CODE = "shadow_zones";
-string const RASTER_SHADOW_ZONE_NAME = "shadow_zones";
-string const RASTER_SLICE_CODE = "slice";
-string const RASTER_SLICE_NAME = "slice";
-string const RASTER_SLOPE_FOR_CLIFF_TOE_NAME = "toe_slope"; // Note no code for this, because is chosen by m_bCliffToeLocate in input file
-string const RASTER_SLOPE_OF_CONSOLIDATED_SEDIMENT_CODE = "cons_sediment_slope";
-string const RASTER_SLOPE_OF_CONSOLIDATED_SEDIMENT_NAME = "cons_sediment_slope";
-string const RASTER_SUSP_SED_CODE = "susp_sed";
-string const RASTER_SUSP_SED_NAME = "susp_sed";
-string const RASTER_TALUS_CODE = "talus";
-string const RASTER_TALUS_NAME = "talus";
-string const RASTER_TOP_ELEVATION_INC_SEA_CODE = "top_elevation";
-string const RASTER_TOP_ELEVATION_INC_SEA_NAME = "top_elevation_inc_sea";
-string const RASTER_TOTAL_ACTUAL_BEACH_EROSION_CODE = "total_actual_beach_erosion";
-string const RASTER_TOTAL_ACTUAL_BEACH_EROSION_NAME = "total_actual_beach_erosion";
-string const RASTER_TOTAL_ACTUAL_PLATFORM_EROSION_CODE = "total_actual_platform_erosion";
-string const RASTER_TOTAL_ACTUAL_PLATFORM_EROSION_NAME = "total_actual_platform_erosion";
-string const RASTER_TOTAL_BEACH_DEPOSITION_CODE = "total_beach_deposition";
-string const RASTER_TOTAL_BEACH_DEPOSITION_NAME = "total_beach_deposition";
-string const RASTER_TOTAL_CLIFF_COLLAPSE_DEPOSITION_COARSE_CODE = "total_cliff_collapse_talus_deposition_coarse";
-string const RASTER_TOTAL_CLIFF_COLLAPSE_DEPOSITION_COARSE_NAME = "total_cliff_collapse_talus_deposition_coarse";
-string const RASTER_TOTAL_CLIFF_COLLAPSE_DEPOSITION_SAND_CODE = "total_cliff_collapse_talus_deposition_sand";
-string const RASTER_TOTAL_CLIFF_COLLAPSE_DEPOSITION_SAND_NAME = "total_cliff_collapse_talus_deposition_sand";
-string const RASTER_TOTAL_CLIFF_COLLAPSE_EROSION_COARSE_CODE = "total_cliff_collapse_erosion_coarse";
-string const RASTER_TOTAL_CLIFF_COLLAPSE_EROSION_COARSE_NAME = "total_cliff_collapse_erosion_coarse";
-string const RASTER_TOTAL_CLIFF_COLLAPSE_EROSION_FINE_CODE = "total_cliff_collapse_erosion_fine";
-string const RASTER_TOTAL_CLIFF_COLLAPSE_EROSION_FINE_NAME = "total_cliff_collapse_erosion_fine";
-string const RASTER_TOTAL_CLIFF_COLLAPSE_EROSION_SAND_CODE = "total_cliff_collapse_erosion_sand";
-string const RASTER_TOTAL_CLIFF_COLLAPSE_EROSION_SAND_NAME = "total_cliff_collapse_erosion_sand";
-string const RASTER_TOTAL_POTENTIAL_BEACH_EROSION_CODE = "total_potential_beach_erosion";
-string const RASTER_TOTAL_POTENTIAL_BEACH_EROSION_NAME = "total_potential_beach_erosion";
-string const RASTER_TOTAL_POTENTIAL_PLATFORM_EROSION_CODE = "total_potential_platform_erosion";
-string const RASTER_TOTAL_POTENTIAL_PLATFORM_EROSION_NAME = "total_potential_platform_erosion";
-string const RASTER_USUAL_OUTPUT_CODE = "usual";
-string const RASTER_WAVE_FLOOD_LINE_CODE = "wave_flood_line";
-string const RASTER_WAVE_FLOOD_LINE_NAME = "wave_flood_line";
-string const RASTER_WAVE_HEIGHT_CODE = "wave_height";
-string const RASTER_WAVE_HEIGHT_NAME = "wave_height";
-string const RASTER_WAVE_ORIENTATION_CODE = "wave_orientation";
-string const RASTER_WAVE_ORIENTATION_NAME = "wave_orientation";
-string const RASTER_WAVE_PERIOD_CODE = "wave_period";
-string const RASTER_WAVE_PERIOD_NAME = "wave_period";
-
-// GIS raster output titles
-string const RASTER_PLOT_ACTIVE_ZONE_TITLE = "Active zone";
-string const RASTER_PLOT_ACTUAL_BEACH_EROSION_TITLE = "Actual (constrained) beach erosion depth";
-string const RASTER_PLOT_ACTUAL_PLATFORM_EROSION_TITLE = "Actual (constrained) shore platform erosion depth";
-string const RASTER_PLOT_AVG_SEA_DEPTH_TITLE = "Average sea depth";
-string const RASTER_PLOT_AVG_SUSPENDED_SEDIMENT_TITLE = "Average depth of suspended sediment";
-string const RASTER_PLOT_AVG_WAVE_HEIGHT_TITLE = "Average wave height";
-string const RASTER_PLOT_AVG_WAVE_ORIENTATION_TITLE = "Average wave orientation";
-string const RASTER_PLOT_BASEMENT_ELEVATION_TITLE = "Basement elevation";
-string const RASTER_PLOT_BEACH_DEPOSITION_TITLE = "Beach deposition depth";
-string const RASTER_PLOT_BEACH_MASK_TITLE = "Beach mask";
-string const RASTER_PLOT_BEACH_PROTECTION_TITLE = "Beach protection factor";
-string const RASTER_PLOT_CLIFF_COLLAPSE_DEPOSITION_COARSE_TITLE = "Depth of coarse talus from cliff collapse";
-string const RASTER_PLOT_CLIFF_COLLAPSE_DEPOSITION_SAND_TITLE = "Depth of sand talus from cliff collapse";
-string const RASTER_PLOT_CLIFF_COLLAPSE_EROSION_COARSE_TITLE = "Cliff collapse depth of erosion, coarse sediment";
-string const RASTER_PLOT_CLIFF_COLLAPSE_EROSION_FINE_TITLE = "Cliff collapse depth of erosion, fine sediment";
-string const RASTER_PLOT_CLIFF_COLLAPSE_EROSION_SAND_TITLE = "Cliff collapse depth of erosion, sand sediment";
-#ifdef _DEBUG
-string const RASTER_PLOT_CLIFF_COLLAPSE_TIMESTEP_TITLE = "Timestep at which cliff collapse occurred";
-#endif
-string const RASTER_PLOT_CLIFF_NOTCH_ALL_TITLE = "All cliff notch incision";
-string const RASTER_PLOT_CLIFF_TOE_TITLE = "Cliff toe cells";
-string const RASTER_PLOT_COARSE_CONSOLIDATED_SEDIMENT_TITLE = "Consolidated coarse sediment depth";
-string const RASTER_PLOT_COARSE_UNCONSOLIDATED_SEDIMENT_TITLE = "Unconsolidated coarse sediment depth";
-string const RASTER_PLOT_COAST_TITLE = "Rasterized coastline";
-string const RASTER_PLOT_DEEP_WATER_WAVE_HEIGHT_TITLE = "Deep water wave height";
-string const RASTER_PLOT_DEEP_WATER_WAVE_ORIENTATION_TITLE = "Deep water wave orientation";
-string const RASTER_PLOT_DEEP_WATER_WAVE_PERIOD_TITLE = "Deep water wave period";
-string const RASTER_PLOT_FINE_CONSOLIDATED_SEDIMENT_TITLE = "Consolidated fine sediment depth";
-string const RASTER_PLOT_FINE_UNCONSOLIDATED_SEDIMENT_TITLE = "Unconsolidated fine sediment depth";
-string const RASTER_PLOT_INTERVENTION_CLASS_TITLE = "Intervention class";
-string const RASTER_PLOT_INTERVENTION_HEIGHT_TITLE = "Intervention height";
-string const RASTER_PLOT_INUNDATION_MASK_TITLE = "Inundated area mask";
-string const RASTER_PLOT_LANDFORM_TITLE = "Landform class";
-string const RASTER_PLOT_NORMAL_PROFILE_TITLE = "Rasterized normal profiles";
-string const RASTER_PLOT_POLYGON_GAIN_OR_LOSS_TITLE = "Polygon gain or loss of unconsolidated sediment";
-string const RASTER_PLOT_POLYGON_TITLE = "Rasterized polygon boundaries";
-string const RASTER_PLOT_POLYGON_UPDRIFT_OR_DOWNDRIFT_TITLE = "Polygon updrift or downdrift movement of unconsolidated sediment";
-string const RASTER_PLOT_POTENTIAL_BEACH_EROSION_TITLE = "Potential (unconstrained) beach erosion depth";
-string const RASTER_PLOT_POTENTIAL_PLATFORM_EROSION_MASK_TITLE = "Potential (unconstrained) shore platform erosion binary mask";
-string const RASTER_PLOT_POTENTIAL_PLATFORM_EROSION_TITLE = "Potential (unconstrained) shore platform erosion depth";
-string const RASTER_PLOT_SAND_CONSOLIDATED_SEDIMENT_TITLE = "Consolidated sand sediment depth";
-string const RASTER_PLOT_SAND_UNCONSOLIDATED_SEDIMENT_TITLE = "Unconsolidated sand sediment depth";
-string const RASTER_PLOT_SEA_DEPTH_TITLE = "Sea depth";
-string const RASTER_PLOT_SEDIMENT_INPUT_EVENT_TITLE = "Sediment input event(s) since last GIS save";
-string const RASTER_PLOT_SED_TOP_INC_TALUS_ELEV_TITLE = "Elevation of sediment top inc talus";
-string const RASTER_PLOT_SETUP_SURGE_FLOOD_MASK_TITLE = "Mask of setup-surge flood";
-string const RASTER_PLOT_SETUP_SURGE_RUNUP_FLOOD_MASK_TITLE = "Mask of setup-surge-runup flood";
-string const RASTER_PLOT_SHADOW_DOWNDRIFT_ZONE_TITLE = "Downdrift of wave shadow zones";
-string const RASTER_PLOT_SHADOW_ZONE_TITLE = "Wave shadow zones";
-string const RASTER_PLOT_SLICE_TITLE = "Slice though layers at elevation = ";
-string const RASTER_PLOT_SLOPE_FOR_CLIFF_TOE_TITLE = "Slope";
-string const RASTER_PLOT_CONS_SED_SLOPE_TITLE = "Local slope of consolidated sediment";
-string const RASTER_PLOT_SUSPENDED_SEDIMENT_TITLE = "Suspended sediment depth";
-string const RASTER_PLOT_TALUS_TITLE = "Talus from cliff collapse";
-string const RASTER_PLOT_TOP_ELEV_INC_SEA_TITLE = "Topmost elevation (sediment plus intervention plus se";
-string const RASTER_PLOT_TOTAL_ACTUAL_BEACH_EROSION_TITLE = "Total actual (constrained) beach erosion depth";
-string const RASTER_PLOT_TOTAL_ACTUAL_PLATFORM_EROSION_TITLE = "Total actual (constrained) shore platform erosion depth";
-string const RASTER_PLOT_TOTAL_BEACH_DEPOSITION_TITLE = "Total beach deposition depth";
-string const RASTER_PLOT_TOTAL_CLIFF_COLLAPSE_DEPOSITION_COARSE_TITLE = "Total depth of coarse talus from cliff collapse";
-string const RASTER_PLOT_TOTAL_CLIFF_COLLAPSE_DEPOSITION_SAND_TITLE = "Total depth of sand talus from cliff collapse";
-string const RASTER_PLOT_TOTAL_CLIFF_COLLAPSE_EROSION_COARSE_TITLE = "Total of cliff collapse erosion depth, coarse";
-string const RASTER_PLOT_TOTAL_CLIFF_COLLAPSE_EROSION_FINE_TITLE = "Total of cliff collapse erosion depth, fine";
-string const RASTER_PLOT_TOTAL_CLIFF_COLLAPSE_EROSION_SAND_TITLE = "Total of cliff collapse erosion depth, sand";
-string const RASTER_PLOT_TOTAL_POTENTIAL_BEACH_EROSION_TITLE = "Total potential (unconstrained) beach erosion depth";
-string const RASTER_PLOT_TOTAL_POTENTIAL_PLATFORM_EROSION_TITLE = "Total potential (unconstrained) shore platform erosion depth";
-string const RASTER_PLOT_WAVE_FLOOD_LINE_TITLE = "Wave flood line";
-string const RASTER_PLOT_WAVE_HEIGHT_TITLE = "Wave height";
-string const RASTER_PLOT_WAVE_ORIENTATION_TITLE = "Wave orientation";
-
-// GIS vector output user codes
-string const VECTOR_ALL_OUTPUT_CODE = "all";
-string const VECTOR_ALL_RIVER_FLOOD_OUTPUT_CODE = "all";
-string const VECTOR_AVG_WAVE_ANGLE_AND_HEIGHT_CODE = "avg_wave_angle";
-string const VECTOR_AVG_WAVE_ANGLE_AND_HEIGHT_NAME = "avg_wave_angle";
-string const VECTOR_BREAKING_WAVE_HEIGHT_CODE = "breaking_wave_height";
-string const VECTOR_BREAKING_WAVE_HEIGHT_NAME = "breaking_wave_height";
-string const VECTOR_CLIFF_EDGE_CODE = "cliff_edge";
-string const VECTOR_CLIFF_EDGE_NAME = "cliff_edge";
-string const VECTOR_CLIFF_NOTCH_ACTIVE_CODE = "cliff_notch_active";
-string const VECTOR_CLIFF_NOTCH_ACTIVE_NAME = "cliff_notch_active";
-string const VECTOR_COAST_CODE = "coast";
-string const VECTOR_COAST_CURVATURE_CODE = "coast_curvature";
-string const VECTOR_COAST_CURVATURE_NAME = "coast_curvature";
-string const VECTOR_COAST_NAME = "coast";
-string const VECTOR_COAST_SWL_HIGHEST_NAME = "coast_SWL_highest";
-string const VECTOR_COAST_SWL_LOWEST_NAME = "coast_SWL_lowest";
-string const VECTOR_DEEP_WATER_WAVE_ANGLE_AND_HEIGHT_CODE = "deep_water_wave_angle";
-string const VECTOR_DEEP_WATER_WAVE_ANGLE_AND_HEIGHT_NAME = "deep_water_wave_angle";
-string const VECTOR_DOWNDRIFT_ZONE_BOUNDARY_CODE = "downdrift_boundary";
-string const VECTOR_DOWNDRIFT_ZONE_BOUNDARY_NAME = "downdrift_boundary";
-string const VECTOR_FLOOD_LINE_CODE = "flood_line";
-string const VECTOR_FLOOD_LINE_NAME = "flood_line";
-string const VECTOR_FLOOD_SWL_SETUP_LINE_CODE = "setup";
-string const VECTOR_FLOOD_SWL_SETUP_LINE_NAME = "setup";
-string const VECTOR_FLOOD_SWL_SETUP_SURGE_LINE_CODE = "setup_surge";
-string const VECTOR_FLOOD_SWL_SETUP_SURGE_LINE_NAME = "setup_surge";
-string const VECTOR_FLOOD_SWL_SETUP_SURGE_RUNUP_LINE_CODE = "setup_surge_runup";
-string const VECTOR_FLOOD_SWL_SETUP_SURGE_RUNUP_LINE_NAME = "setup_surge_runup";
-string const VECTOR_INVALID_NORMALS_CODE = "invalid_normals";
-string const VECTOR_INVALID_NORMALS_NAME = "invalid_normals";
-string const VECTOR_MEAN_WAVE_ENERGY_CODE = "mean_wave_energy";
-string const VECTOR_MEAN_WAVE_ENERGY_NAME = "mean_wave_energy";
-string const VECTOR_NORMALS_CODE = "normals";
-string const VECTOR_NORMALS_NAME = "normals";
-string const VECTOR_POLYGON_BOUNDARY_CODE = "polygon";
-string const VECTOR_POLYGON_BOUNDARY_NAME = "polygon";
-string const VECTOR_POLYGON_NODE_CODE = "polygon_node";
-string const VECTOR_POLYGON_NODE_NAME = "polygon_node";
-string const VECTOR_RUN_UP_CODE = "run_up";
-string const VECTOR_RUN_UP_NAME = "run_up";
-string const VECTOR_SHADOW_ZONE_BOUNDARY_CODE = "shadow_boundary";
-string const VECTOR_SHADOW_ZONE_BOUNDARY_NAME = "shadow_boundary";
-string const VECTOR_STORM_SURGE_CODE = "storm_surge";
-string const VECTOR_STORM_SURGE_NAME = "storm_surge";
-string const VECTOR_USUAL_OUTPUT_CODE = "usual";
-string const VECTOR_WAVE_ANGLE_AND_HEIGHT_CODE = "wave_angle";
-string const VECTOR_WAVE_ANGLE_AND_HEIGHT_NAME = "wave_angle";
-string const VECTOR_WAVE_ENERGY_SINCE_COLLAPSE_CODE = "wave_energy";
-string const VECTOR_WAVE_ENERGY_SINCE_COLLAPSE_NAME = "wave_energy";
-string const VECTOR_WAVE_SETUP_CODE = "wave_setup";
-string const VECTOR_WAVE_SETUP_NAME = "wave_setup";
-string const VECTOR_WAVE_TRANSECT_POINTS_CODE = "wave_transect_points";
-string const VECTOR_WAVE_TRANSECT_POINTS_NAME = "wave_transect_points";
-
-// GIS vector output titles
-string const VECTOR_PLOT_AVG_WAVE_ANGLE_AND_HEIGHT_TITLE = "Average wave orientation and height";
-string const VECTOR_PLOT_BREAKING_WAVE_HEIGHT_TITLE = "Breaking wave height";
-string const VECTOR_PLOT_CLIFF_EDGE_TITLE = "Cliff edge";
-string const VECTOR_PLOT_CLIFF_NOTCH_ACTIVE_TITLE = "Active cliff notch incision";
-string const VECTOR_PLOT_COAST_CURVATURE_TITLE = "Coastline curvature";
-string const VECTOR_PLOT_COAST_SWL_HIGHEST_TITLE = "Coastline at highest SWL";
-string const VECTOR_PLOT_COAST_SWL_LOWEST_TITLE = "Coastline at lowest SWL";
-string const VECTOR_PLOT_COAST_TITLE = "Coastline";
-string const VECTOR_PLOT_DEEP_WATER_WAVE_ANGLE_AND_HEIGHT_TITLE = "Deep water wave orientation and height";
-string const VECTOR_PLOT_DOWNDRIFT_ZONE_BOUNDARY_TITLE = "Downdrift zone boundary";
-string const VECTOR_PLOT_FLOOD_LINE_TITLE = "Flood ";
-string const VECTOR_PLOT_FLOOD_SWL_SETUP_LINE_TITLE = "SWL-Setup line";
-string const VECTOR_PLOT_FLOOD_SWL_SETUP_SURGE_LINE_TITLE = "SWL-Setup-Surge line";
-string const VECTOR_PLOT_FLOOD_SWL_SETUP_SURGE_RUNUP_LINE_TITLE = "SWL-Setup-Surge-Runup line";
-string const VECTOR_PLOT_INVALID_NORMALS_TITLE = "INVALID coastline-normal profiles";
-string const VECTOR_PLOT_MEAN_WAVE_ENERGY_TITLE = "Mean wave energy";
-string const VECTOR_PLOT_NORMALS_TITLE = "Coastline-normal profiles";
-string const VECTOR_PLOT_POLYGON_BOUNDARY_TITLE = "Polygons";
-string const VECTOR_PLOT_POLYGON_NODES_TITLE = "Polygon nodes";
-string const VECTOR_PLOT_RUN_UP_TITLE = "Run up";
-string const VECTOR_PLOT_SHADOW_ZONE_BOUNDARY_TITLE = "Shadow zone boundary";
-string const VECTOR_PLOT_STORM_SURGE_TITLE = "Storm surge";
-string const VECTOR_PLOT_WAVE_ANGLE_AND_HEIGHT_TITLE = "Wave orientation and height";
-string const VECTOR_PLOT_WAVE_ENERGY_SINCE_COLLAPSE_TITLE = "Wave energy since collapse";
-string const VECTOR_PLOT_WAVE_SETUP_TITLE = "Wave setup";
-string const VECTOR_PLOT_WAVE_TRANSECT_POINTS_TITLE = "Wave transect points (real and synthetic)";
-
-// Time series codes
-string const TIME_SERIES_BEACH_CHANGE_NET_CODE = "beach_change_net";
-string const TIME_SERIES_BEACH_CHANGE_NET_NAME = "beach_change_net";
-string const TIME_SERIES_BEACH_DEPOSITION_CODE = "beach_deposition";
-string const TIME_SERIES_BEACH_DEPOSITION_NAME = "beach_deposition";
-string const TIME_SERIES_BEACH_EROSION_CODE = "beach_erosion";
-string const TIME_SERIES_BEACH_EROSION_NAME = "beach_erosion";
-string const TIME_SERIES_CLIFF_COLLAPSE_DEPOSITION_CODE = "cliff_collapse_deposition";
-string const TIME_SERIES_CLIFF_COLLAPSE_DEPOSITION_NAME = "cliff_collapse_deposition";
-string const TIME_SERIES_CLIFF_COLLAPSE_EROSION_CODE = "cliff_collapse_erosion";
-string const TIME_SERIES_CLIFF_COLLAPSE_EROSION_NAME = "cliff_collapse_erosion";
-string const TIME_SERIES_CLIFF_COLLAPSE_NET_CODE = "cliff_collapse_net";
-string const TIME_SERIES_CLIFF_COLLAPSE_NET_NAME = "cliff_collapse_net";
-string const TIME_SERIES_CLIFF_NOTCH_ELEV_CODE = "cliff_notch";
-string const TIME_SERIES_CLIFF_NOTCH_ELEV_NAME = "cliff_notch";
-string const TIME_SERIES_FLOOD_SETUP_SURGE_CODE = "flood_setup_surge";
-string const TIME_SERIES_FLOOD_SETUP_SURGE_NAME = "flood_setup_surge";
-string const TIME_SERIES_FLOOD_SETUP_SURGE_RUNUP_CODE = "flood_setup_surge_runup";
-string const TIME_SERIES_FLOOD_SETUP_SURGE_RUNUP_NAME = "flood_setup_surge_runup";
-string const TIME_SERIES_PLATFORM_EROSION_CODE = "platform_erosion";
-string const TIME_SERIES_PLATFORM_EROSION_NAME = "platform_erosion";
-string const TIME_SERIES_SEA_AREA_CODE = "sea_area";
-string const TIME_SERIES_SEA_AREA_NAME = "sea_area";
-string const TIME_SERIES_SUSPENDED_SEDIMENT_CODE = "suspended";
-string const TIME_SERIES_SUSPENDED_SEDIMENT_NAME = "suspended_sediment";
-string const TIME_SERIES_SWL_CODE = "SWL";
-string const TIME_SERIES_SWL_NAME = "SWL";
-
-// CShore stuff
-string const WAVE_ENERGY_FLUX = "wave_energy_flux";
-string const WAVE_HEIGHT_X_FILENAME = "wave_height_x.csv";
-string const WAVE_HEIGHT_Y_FILENAME = "wave_height_y.csv";
-string const ACTIVE_ZONE_FILENAME = "activezone.csv";
-
-//================================================ Globally-available functions =================================================
-template
-T tMax(T a, T b)
-{
- return ((a > b) ? a : b);
-}
-
-template
-T tMax(T a, T b, T c)
-{
- T max = (a < b) ? b : a;
- return ((max < c) ? c : max);
-}
-
-template
-T tMin(T a, T b)
-{
- return ((a < b) ? a : b);
-}
-
-template
-T tMin(T a, T b, T c)
-{
- return (a < b ? (a < c ? a : c) : (b < c ? b : c));
-}
-
-template
-T tAbs(T a)
-{
- // From a posting dated 18 Nov 93 by rmartin@rcmcon.com (Robert Martin), archived in cpp_tips
- return ((a < 0) ? -a : a);
-}
-
-// template
-// bool bIsBetween(T a, T b, T c)
-// {
-// // Assumes b > c
-// return ((a >= b) && (a <= c));
-// }
-
-template
-string strDblToStr(const T &t)
-{
- // From http://stackoverflow.com/questions/2125880/convert-float-to-stdstring-in-c
- ostringstream os;
- os << t;
- return os.str();
-}
-
-// ==============================================================================================================================
-// For comparison of two floating-point numbers, with a specified accuracy
-// ==============================================================================================================================
-template
-bool bFPIsEqual(const T d1, const T d2, const T dEpsilon)
-{
- // Since the accuracy of floating-point numbers varies with their magnitude, we must compare them by using an accuracy threshold which is relative to the magnitude of the two numbers being compared. This is a blend of an example from Knuth's 'The Art of Computer Programming. Volume 1. Fundamental Algorithms' and a posting dated 18 Nov 93 by rmartin@rcmcon.com (Robert Martin), archived in cpp_tips
-
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wfloat-equal"
-
- if ((0 == d1) && (tAbs(d2) < dEpsilon))
- return true;
- else if ((0 == d2) && (tAbs(d1) < dEpsilon))
- return true;
- else
- return ((tAbs(d1 - d2) < (dEpsilon * tAbs(d1))) ? true : false);
-
-#pragma GCC diagnostic pop
-}
-
-#ifndef DOXYGEN_SHOULD_SKIP_THIS
-// Definitions are in utilsglobal.cpp
-double dRound(double const);
-int nRound(double const);
-// bool bIsWhole(double const);
-bool bIsStringValidDouble(string &);
-bool bIsStringValidInt(string &);
-
-struct FillToWidth
-{
- FillToWidth(char f, int w) : chFill(f), nWidth(w) {}
- char chFill;
- int nWidth;
-};
-
-//! Struct to hold wave data for a single transect/profile
-struct TransectWaveData
-{
- std::vector VdX;
- std::vector VdY;
- std::vector VdHeightX;
- std::vector VdHeightY;
- std::vector VbBreaking;
- int nCoastID;
- int nProfileID;
- bool bIsGridEdge;
-};
-
-ostream &operator<<(ostream &, const FillToWidth &);
-
-// string strDbl(double const, int const);
-string strDblRight(double const, int const, int const, bool const = true);
-string strIntRight(int const, int const);
-string strCentre(const char *, int const);
-string strCentre(const string &, int const);
-string strRight(const string &, int const);
-string strRight(const char *, int const);
-string strLeft(const string &, int const);
-string strLeft(const char *, int const);
-string strRightPerCent(double const, double const, int const, int const,
- bool const = true);
-#endif
-
-//================================================= debugging stuff =============================================================
-// #define CLOCKCHECK // Uncomment to check CPU clock rollover settings
-
-#endif // CME_H
+/*!
+ \mainpage
+ \section intro_sec Introduction
+
+ CoastalME (Coastal Modelling Environment) simulates the long-term behaviour of a coast. This initial version considers only simple soft cliff cross-shore effects. However, development of CoastalME is ongoing. Watch this space!\n\n
+
+ CoastalME was devised and constructed by Andres Payo Garcia (British Geological Survey: agarcia@bgs.ac.uk) and David Favis-Mortlock (British Geological Survey: dfm1@bgs.ac.uk). We are very grateful to the following for support, assistance, and inspiration: Tom Ashby, Manuel Cobos Budia, Wilf Chun, Mark Dickson, Jim W. Hall, Martin D. Hurst, Matthew Ives, Robert J. Nicholls, Ian Townend, and Mike
+ J.A. Walkden.\n\n
+
+ See https://github.com/coastalme/coastalme for the stable release version, and the unstable development version, of the source code.\n
+ \n
+ From Shingle Street\n
+ To Orford Ness\n
+ The waves maraud,\n
+ The winds oppress,\n
+ The earth can’t help\n
+ But acquiesce\n
+ For this is east\n
+ And east means loss,\n
+ A lessening shore, receding ground,\n
+ Three feet gone last year, four feet this\n
+ Where land runs out and nothing’s sound.\n
+ Nothing lasts long on Shingle Street.\n
+ \n
+ By Blake Morrison (2018). See https://www.penguin.co.uk/books/419911/shingle-street-by-morrison-blake/9780701188771\n
+
+ \section install_sec Installing CoastalME
+
+ \subsection install_step1 Obtaining the source code
+
+ CoastalME builds easily using Linux. If you wish to run CoastalME on Windows, then we currently recommend using the Windows Subsystem Linux (WSL) software to do this.
+
+ Create a local copy of the github repository, for example by downloading a zipfile, then unpacking it or cloning. We suggest unpacking it to something like "/home/YOUR NAME/Projects/CoastalME/", this is then your CoastalME folder.
+
+ git clone https://github.com/coastalme/coastalme
+
+ \subsection install_step2 Building CoastalME
+
+ In a terminal window (i.e. at a command-line prompt) move to the CoastalME folder.
+
+ Then move to the the src folder
+
+ cd CoastalME/src
+
+ and run run_cmake.sh
+
+ ./run_cmake.sh
+
+ If you get a "Permission denied" message: -bash: ./run_cmake.sh: Permission denied you will have to grant executable permission using chmod a+x run_cmake.sh, chmod a+x cshore/make_cshore.sh and then
+ ./run_cmake.sh
+
+ This will build CShore, look for GDAL, and write the CMake files. If you see error messages about missing software (for example, telling you that CMake cannot be found or is too old, or GDAL cannot be found or is too old) then you need to install or update the software that is causing the problem.
+
+ Next, run
+
+ make install
+
+ This will create an executable file called cme in the CoastalME folder.
+
+ \section run_sec Running CoastalME
+
+ \subsection run_step1 Specifying the input file
+
+ Edit cme.ini to tell CoastalME which input file to read (for example, in/test_suite/minimal_wave_angle_230/minimal.dat).
+
+ \subsection run_step2 Running CoastalME
+
+ Leave the src folder, and run cme
+
+ cd ..
+ ./cme
+
+ Output will appear in the "Path for output" folder.
+
+ \subsection run_step3 Running CoastalME's test suite
+
+ To check that your installation is running correctly, you can run a suite of pre-defined tests by running the following commands:
+
+ chmod a+x run_test_suite.sh
+ ./run_test_suite.sh
+
+ The `chmod` comand ensures that you have permission to execute the run_test_suite.sh file.
+
+ \subsection run_step4 Managing CoastalME's output
+
+ Once you have CoastalME (CME) up and running, you can reduce the quantity of output (it can be overwhelming!) in several ways.
+
+ Change "Content of log file" in the CME input file for any of the test suite runs (the name of this input file is listed in cme.ini, both are simple text files). If you set "Content of log file" to zero, then CME won't output a log file; setting it to 4 (all output) is really only useful to developers.
+
+ Change "GIS vector files to output" and "GIS vector files to output" in the CME input file. These are both set to "all" in the test suite files on GitHub. Instead of "all" you can list the space-separated codes for only the GIS output that you want to see. A list of CME GIS output codes is in codes.txt.
+
+ Enjoy!
+
+ \file cme.h
+ \brief This file contains global definitions for CoastalME
+*/
+
+/*
+ NOTE Before releasing a new version, do a pre-release build to check for memory leaks with -fsanitize options enabled (see CMakeLists.txt) then run ./cme 2> sanitize.txt NOT UNDER DEBUG (i.e. not using gdb)
+
+ TODOLIST
+ ***********************************************************************************************************
+ DOCUMENTATION
+ TODO 001 Add more Doxygen information about all classes
+ TODO 007 We now have setup and surge info from CShore (thanks to Manuel). But what shall we do with this info? "The variable VdWaveSetupSurge() represents the sea level rise due to wave effects (setup) and storm surge. CSHORE calculates them together and they can’t be separated. That’s what the VdWaveSetupSurge variable is. That’s why you saw my initial efforts to try to separate both variables from CSHORE commented out, which is impossible. What is possible is to get the RunUp from CSHORE, but since it uses an empirical formula for that, I finally decided to calculate it separately. To your question about whether you should remove VdStormSurge, the answer is yes. I left it because I still intend at some point to extract the cross-shore transport from CSHORE and balance it in CME with the longshore and cross-shore transports without needing the Dean profile. From my point of view, this would be even more realistic, though at first it will surely drive us crazy."
+
+ USER INPUT
+ TODO 000 Should user input be split in two main files: one for frequently-changed things, one for rarely-changed things? If so, what should go into each file ('testing only' OK, but what else?)
+ TODO 011 Should this constant be a user input? If so, TODO 071
+ TODO 036 Read in changed deep water wave values (need TODO 071)
+ TODO 022 Get intervention update working (need TODO 071)
+ TODO 042 Should we have a smallest valid input for KLS in the CERC equation?
+ TODO 045 Method of getting depth of closure value needs to be a user input (need TODO 071)
+ TODO 049 Handle other command line parameters e.g. path to .ini file, path to datafile
+ TODO 035 Also handle other EPSG for vector spatial reference systems
+ TODO 054 Choose more files to omit from "usual" raster output
+ TODO 069 Enable ability to represent intervention structures which have their foundation embedded in consolidated sediment. In other words, with the elevation of the base of the intervention structure *below* the top of all consolidated sediment layers. Will need some sanity checking of elevations
+ TODO 071 If the user input file format is changed, write a Python script to convert from the old file format to the new
+ TODO 083 Get all three kinds of sediment input events working correctly
+
+ ERROR HANDLING
+ TODO 038 Do better error handling if insufficient memory
+ TODO 004 Improve error handling of situation where we have a valid shadow zone but cannot find a neighbouring cell which is 'under' the coastline
+ TODO 006 Check GDALGridCreate() with only start-of-coast or an end-of-coast profiles
+ TODO 009 Decide what to do when we have eroded down to basement
+ TODO 017 Extra safety check needed, make sure that each point is within valid grid
+ TODO 018 Improve situation where new landwards point on parallel profile is not within the raster grid
+ TODO 019 Improve situation where Dean profile has a near-zero elevation difference
+ TODO 020 Check calculation of elevation of coast point of Dean parallel profile
+ TODO 021 Improve situation where all layers have zero thickness
+ TODO 025 Improve situation where this point has only zero thickness layers
+ TODO 026 Check situation where cell in parallel profile is not in a polygon
+ TODO 028 Give a warning if raster input layer has several bands
+ TODO 053 Improve handling of situation where landward elevation of profile is -ve
+ TODO 055 Maybe add a safety check here?
+ TODO 080 Do we get -ve breaking wave heights here?
+ TODO 084 Improve handling of situation where consecutive profile points are same distance from shoreline
+
+ THEORY/EFFICIENCY
+ TODO 002 Do we really need D50 for drift landform class? What do we need for drift?
+ TODO 005 Maybe give every coast point a value for end-of-profile wave height and direction instead of for deep water wave height and direction
+ TODO 010 Do we also need to update the active zone cells?
+ TODO 012 Change finding of adjacent polygons, and calculation of the length of shared normals, when we make polygon seaward length determined by depth of closure
+ TODO 013 Change calculation (need user input?) of coastline smoothing convexity threshold
+ TODO 014 Profile spacing, could try gradually increasing the profile spacing with increasing concavity, and decreasing the profile spacing with increasing convexity
+ TODO 016 Check mass balance for recirculating unconsolidated sediment option
+ TODO 023 Only calculate shore platform erosion if cell is in a polygon
+ TODO 024 Should we calculate platform erosion on a profile that has hit dry land?
+ TODO 044 Implement estuaries
+ TODO 051 Implement other ways of calculating depth of closure, see TODO 045
+ TODO 056 Check this please Andres
+ TODO 059 Implement dune landform class
+ TODO 060 Remove 'magic numbers' from code here
+ TODO 061 Is this safety check to depth of breaking a reasonable thing to do?
+ TODO 066 Should this be for all layers? Check
+ TODO 067 Suspended fine sediment never decreases i.e. no suspended fine sediment ever leaves the grid. Is this OK?
+ TODO 070 Change CShore to use allocatable arrays (https://fortran-lang.org/en/learn/best_practices/allocatable_arrays/) so that the number of points in the CShore output profiles can either be a user input, or determined by e.g. the physical length of the profile. At present, max is NN = 1000 in cshore_wrapper.f03
+ TODO 075 What if bedrock sticks above Dean profile?
+ TODO 076 When doing parallel profiles, start from the profile which is closest to a right angle with the coast
+ TODO 077 As traverse between the bounding profiles creating parallel profiles, gradually change the parallel profile orientation based on distance weighting of two bounding profiles
+ TODO 078 At present, we don't allow cliff collapse onto interventions. Is this realistic? Should it be different for different types on intervention?
+ TODO 089 Why do we get patches of sediment in the sea?
+ TODO 086 Try these as a more efficient replacement for GDALGridCreate(): https://github.com/delfrrr/delaunator-cpp https://www.cs.cmu.edu/~quake/triangle.html https://github.com/greenm01/poly2tri https://gts.sourceforge.net/index.html
+ TODO 088 In (almost) all whole-grid loops, immediately continue if cell is hinterland (but not when calculating cliff collapse)
+ TODO 090 At present, sediment cannot move from a given coastline polygon to a polygon belonging to another coastline. Is this always true?
+ TODO 092 If we have only fine sediment, the surface formed as the coast recedes inland is dead level (because fine sediment goes to suspension, and hence the Dean profile stuff does not operate). This causes problems with profile creation and CShore. Need to impose a small slope here somehow
+ TODO 093 There are a number of cell attributes that are really only useful for debugging. To keep memory usage down on release versions, need to flag these attributes and their methods so that they are included only in debug versions
+ TODO 094 Problems with sediment recirculation when large volumes of sedimentare introduced at the input end of the coast: need to spread this input sediment over the whole of the grid-end polygon
+ TODO 095 Parallel profiles seem to create "streaks" of above-water sediment, these streaks interfere with subsequent profile creation (profiles which hit steaks arte marked as invalid). Investigate this
+ TODO 096 It is OK to specify OGRFieldDefn objects as const in recent versions (e.g. 14.2) of g++, but in older versions of g++ (e.g. 12.2) have problems with const here. Maybe make the const a pre-processor condion?
+
+ OUTPUT
+ TODO 065 Get GPKG output working: GDAL 3.9.1 does not yet implement this correctly. Currently is OK for vector output (but is very slow), not yet working for raster output
+ TODO 063 Add NetCDF support, see https://trac.osgeo.org/gdal/wiki/NetCDF
+ TODO 064 Add support for grids that are not oriented N-S and W-E, but which are still rectangular. See https://gdal.org/en/stable/tutorials/geotransforms_tut.html
+ TODO 031 Get raster slice output working with multiple slices
+ TODO 032 Improve output scaling for DBL_NODATA situation
+ TODO 033 Also test and configure (e.g. by passing open() options) other vector output file formats
+ TODO 034 Also test and configure (e.g. by passing open() options) other raster output file formats
+ TODO 043 When outputting profiles, how do we deal with randomness of profile spacing (since profile location is determined by curvature)?
+ TODO 052 Improve saving of profiles and parallel profiles
+ TODO 062 Show end-of-iteration number of cells with sediment somewhere
+ TODO 068 Only show output in log file that is relevant to processes being simulated
+ TODO 074 Output history of what landforms are on a particular cell or cells. User inputs cell(s), how?
+ TODO 082 Also show m_dStartIterUnconsFineAllCells etc. in log file
+
+ 096 is max
+
+ COMPLETED
+ TODO 003 Make coastline curvature moving window size a user input DONE in 1.1.22
+ TODO 046 Why is cliff collapse eroded during deposition (three size classes) no longer calculated? DONE IN 1.1.22
+ TODO 058 Dave to check this DONE in 1.1.22
+ TODO 039 Rewrite reading of multiple random number seeds DONE in 1.2.1, 8 Nov 2024
+ TODO 041 Read in SWL per-timestep
+ BUG 002 Useless output e.g. clay layers even if no clay input DONE in 1.1.21
+ BUG 003 Use mean SWL for elevations of Dean profiles DONE in 1.2.1, 27 Nov 2024
+ BUG 004 Don't smooth intervention coastline DONE 1.2.1, 27 Nov 2024
+ TODO 073 If output dir does not exist, then create it (ask user first) DONE 1.2.2, 28 Nov 2024
+ TODO 047 Where is the GDAL description for the deep water wave stations vector file? DONE 1.2.3, 2 Dec 2024
+ TODO 048 Where is the GDAL description for the flood input locations point or vector file? DONE 1.2.3, 2 Dec 2024
+ TODO 027 Sort out GDAL problem with raster reference units DONE 1.2.3, 2 Dec 2024
+ TODO 079 Do sanity checking on wave and tide input DONE 1.2.3, 2 Dec 2024
+ TODO 072 CShore crashes occasionally, is it because of -ve Z values here? DONE 1.2.3, 2 Dec 2024
+ TODO 050 Update for recent versions of Windows DONE 1.2.3, 2 Dec 2024
+ TODO 037 Need more info on nFindIndex() DONE 1.2.3, 2 Dec 2024 Improve coast normals DONE 1.2.3, 20 Dec 2024
+ TODO 057 Check this please Manuel DONE 1.2.4, 4 Jan 2025
+ TODO 087 Is there a problem if profile is not long enough for user-input depth of closure? DONE 1.3.0 2 Feb 2025
+*/
+
+#ifndef CME_H
+#define CME_H
+/* ===============================================================================================================================
+ This file is part of CoastalME, the Coastal Modelling Environment.
+
+ 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.
+
+ 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.
+
+ 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.
+===============================================================================================================================*/
+#include
+
+#include
+using std::string;
+
+#include
+using std::ostringstream;
+
+#include
+using std::ostream;
+
+#include
+
+//===================================================== platform-specific stuff =================================================
+#ifdef _WIN32
+ #define access _access
+ #define F_OK 0 // Test for file existence
+#endif
+
+#ifdef _MSC_VER
+ // MS Visual C++ compiler, byte order is IEEE little-endian
+ #ifdef _DEBUG
+ #include // useful
+ #endif
+
+ // clock_t is a signed long: see
+ long const CLOCK_T_MIN = LONG_MIN;
+ double const CLOCK_T_RANGE = static_cast(LONG_MAX) - static_cast(CLOCK_T_MIN);
+
+ #ifdef _M_ALPHA
+ string const PLATFORM = "MS Visual C++ for Alpha";
+ #elif defined _M_IX86
+ string const PLATFORM = "MS Visual C++ for Intel x86";
+ #elif defined _M_MPPC
+ string const PLATFORM = "MS Visual C++ for Power PC";
+ #elif defined _M_MRX000
+ string const PLATFORM = "MS Visual C++ for MIPS";
+ #else
+ string const PLATFORM = "MS Visual C++ for unknown CPU";
+ #endif
+
+#elif defined __GNUG__
+ // GNU compiler
+ #ifndef CPU
+ #error "CPU not defined"
+ #else
+ #ifdef x86
+ // Intel x86, byte order is little-endian
+ string const PLATFORM = "GNU Compiler for Intel x86";
+ // clock_t is an unsigned long: see
+ unsigned long const CLOCK_T_MIN = 0;
+ double const CLOCK_T_RANGE = static_cast(ULONG_MAX);
+ #elif defined rs6000
+ // IBM RS-6000, byte order is big-endian
+ string const PLATFORM = "GNU complier for IBM RS-6000";
+ // clock_t is a signed long: see NEED TO CHECK
+ long const CLOCK_T_MIN = LONG_MIN;
+ double const CLOCK_T_RANGE = static_cast(LONG_MAX) - static_cast(CLOCK_T_MIN);
+ #elif defined ultrasparc
+ // Sun UltraSparc, byte order is big-endian
+ string const PLATFORM = "GNU compiler for Sun UltraSPARC";
+ // clock_t is a signed long: see
+ long const CLOCK_T_MIN = LONG_MIN;
+ double const CLOCK_T_RANGE = static_cast(LONG_MAX) - static_cast(CLOCK_T_MIN);
+ #else
+ // Something else
+ string const PLATFORM = "GNU compiler for unknown CPU";
+ // clock_t is a signed long: NEED TO CHECK
+ long const CLOCK_T_MIN = LONG_MIN;
+ double const CLOCK_T_RANGE = static_cast(LONG_MAX) - static_cast(CLOCK_T_MIN);
+ #endif
+ #endif
+
+#elif defined __clang__
+ // Clang compiler
+ #ifndef CPU
+ #error "CPU not defined"
+ #else
+ #ifdef x86
+ // Intel x86, byte order is little-endian
+ string const PLATFORM = "Clang compiler for Intel x86";
+ // clock_t is an unsigned long: see
+ unsigned long const CLOCK_T_MIN = 0;
+ double const CLOCK_T_RANGE = static_cast(ULONG_MAX);
+ #else
+ // Something else
+ string const PLATFORM = "Clang compiler for unknown CPU";
+ // clock_t is a signed long: NEED TO CHECK
+ long const CLOCK_T_MIN = LONG_MIN;
+ double const CLOCK_T_RANGE = static_cast(LONG_MAX) - static_cast(CLOCK_T_MIN);
+ #endif
+ #endif
+
+#elif defined __MINGW32__
+ // Minimalist GNU for Windows
+ // #define __USE_MINGW_ANSI_STDIO 1 // Fix long doubles output problem,
+ // see http://stackoverflow.com/questions/7134547/gcc-printf-and-long-double-leads-to-wrong-output-c-type-conversion-messes-u
+ #define WEXITSTATUS(x) ((x) & 0xff)
+
+#elif defined __HP_aCC
+ // HP-UX aCC, byte order is big-endian, can be either 32-bit or 64-bit
+ string const PLATFORM = "HP-UX aC++";
+ // clock_t is an unsigned long: see
+ unsigned long const CLOCK_T_MIN = 0;
+ #ifdef __ia64
+ // However, clock_t is a 32-bit unsigned long and we are using 64-bit unsigned longs here
+ double const CLOCK_T_RANGE = 4294967295UL; // crude, improve
+ #else
+ double const CLOCK_T_RANGE = static_cast(ULONG_MAX);
+ #endif
+#endif
+
+// TODO: Check
+// #if defined(WIN32)
+// #define STRCASECMP(a, b) (_stricmp(a, b))
+// #define STRNCASECMP(a, b, n) (_strnicmp(a, b, n))
+// #else
+// /** Alias for strcasecmp() */
+// #define STRCASECMP(a, b) (strcasecmp(a, b))
+// /** Alias for strncasecmp() */
+// #define STRNCASECMP(a, b, n) (strncasecmp(a, b, n))
+// //# endif
+// /** Alias for strncasecmp() == 0 */
+// #define EQUALN(a, b, n) (STRNCASECMP(a, b, n) == 0)
+// /** Alias for strcasecmp() == 0 */
+// #define EQUAL(a, b) (STRCASECMP(a, b) == 0)
+// #endif
+
+//===================================================== hard-wired constants ====================================================
+char const COLON = ':';
+char const COMMA = ',';
+char const DASH = '-';
+char const PATH_SEPARATOR = '/'; // Works for Windows too!
+char const QUOTE1 = ';';
+char const QUOTE2 = '#';
+char const SLASH = '/';
+char const SPACE = ' ';
+char const TILDE = '~';
+
+// TESTING options
+bool const ACCEPT_TRUNCATED_PROFILES = true;
+bool const CREATE_SHADOW_ZONE_IF_HITS_GRID_EDGE = true; // If shadow line tracing hits grid edge, create shadow zone?
+bool const SAVE_CSHORE_OUTPUT = true; // #ifdef CSHORE_FILE_INOUT || CSHORE_BOTH, append all CShore output files to a whole-run master
+bool const USE_DEEP_WATER_FOR_SHADOW_LINE = true; // Use deep water wave orientation in determining shadow line orientation?
+
+// Not likely that user will need to change these
+int const NUMBER_OF_RNGS = 2; // Number of random number generators
+int const SAVEMAX = 100000; // Maximum number of saves of spatial output
+int const BUF_SIZE = 2048; // Max length (inc. terminating NULL) of any C-type string
+int const CAPE_POINT_MIN_SPACING = 10; // In cells: for shadow zone stuff, cape points must not be closer than this
+int const CLOCK_CHECK_ITERATION = 5000; // If have done this many timesteps then reset the CPU time running total
+int const COAST_LENGTH_MAX = 100; // For safety check when tracing coast
+int const COAST_LENGTH_MIN_X_PROF_SPACE = 20; // Ignore very short coasts less than this x profile spacing
+
+//! The size of the arrays output by CShore. If this is changed, then must also set the same value on line 12 of cshore_wrapper.f03 (integer, parameter :: NN = 1000, NL = 1) and recompile CShore. Eventually we should move to dynamically allocated arrays TODO 070
+int const CSHOREARRAYOUTSIZE = 1000;
+
+int const FLOOD_FILL_START_OFFSET = 2; // In cells: cell-by-cell fill starts this distance inside polygon
+int const GRID_MARGIN = 10; // Ignore this many along-coast grid-edge points re. shadow zone calcs
+int const INT_NODATA = -9999; // CME's internal NODATA value for ints
+int const MAX_LEN_SHADOW_LINE_TO_IGNORE = 200; // In cells: if can't find cell-by-cell fill start point, continue if short shadow line
+int const MAX_NUM_PREV_ORIENTATION_VALUES = 10; // Max length of deque used in tracing shadow boundary
+int const MAX_NUM_SHADOW_ZONES = 10; // Consider at most this number of shadow zones
+int const MIN_INLAND_OFFSET_UNCONS_EROSION = 5; // Used in estimation of beach erosion
+int const MIN_PARALLEL_PROFILE_SIZE = 3; // In cells: min size for valid unconsolidated sediment parallel profile
+int const MIN_PROFILE_SIZE = 3; // In cells: min size for valid unconsolidated sediment profile
+int const DEFAULT_PROFILE_SPACING = 15; // In cells: profile creation does not work well if profiles are too closely spaced
+int const SAVGOL_POLYNOMIAL_MAX_ORDER = 6; // Maximum order of Savitzky-Golay smoothing polynomial
+
+// Log file detail level
+int const NO_LOG_FILE = 0;
+int const LOG_FILE_LOW_DETAIL = 1;
+int const LOG_FILE_MIDDLE_DETAIL = 2;
+int const LOG_FILE_HIGH_DETAIL = 3;
+int const LOG_FILE_ALL = 4;
+
+// Direction codes
+int const NO_DIRECTION = 0;
+int const NORTH = 1;
+int const NORTH_EAST = 2;
+int const EAST = 3;
+int const SOUTH_EAST = 4;
+int const SOUTH = 5;
+int const SOUTH_WEST = 6;
+int const WEST = 7;
+int const NORTH_WEST = 8;
+
+int const DIRECTION_DOWNCOAST = 0; // Down-coast, i.e. along the coast so that the index of coastline points INCREASES
+int const DIRECTION_UPCOAST = 1; // Up-coast, i.e. along the coast so that the index of coastline points DECREASES
+
+// Handedness codes, these show which side the sea is on when travelling down-coast (i.e. in the direction in which coastline point numbers INCREASE)
+int const NULL_HANDED = -1;
+int const RIGHT_HANDED = 0;
+int const LEFT_HANDED = 1;
+
+// Sediment texture codes
+int const TEXTURE_FINE = 0;
+int const TEXTURE_SAND = 1;
+int const TEXTURE_COARSE = 2;
+
+// Time unit codes
+int const TIME_UNKNOWN = -1;
+int const TIME_HOURS = 0;
+int const TIME_DAYS = 1;
+int const TIME_MONTHS = 2;
+int const TIME_YEARS = 3;
+
+// Intervention input and output codes
+int const IO_INTERVENTION_NONE = 0;
+int const IO_INTERVENTION_STRUCT = 1;
+int const IO_INTERVENTION_NON_STRUCT = 2;
+
+// Landform category codes
+int const LF_UNKNOWN = 0;
+int const LF_HINTERLAND = 1;
+int const LF_SEA = 2;
+int const LF_CLIFF_ON_COASTLINE = 6;
+int const LF_CLIFF_INLAND = 7;
+int const LF_DRIFT_TALUS = 9;
+int const LF_DRIFT_BEACH = 10;
+int const LF_DRIFT_DUNES = 11; // TODO 059 Implement dune landform class
+int const LF_INTERVENTION_STRUCT = 12;
+int const LF_INTERVENTION_NON_STRUCT = 13;
+int const LF_ISLAND = 14; // Not yet implemented
+int const LF_SEDIMENT_INPUT_UNCONSOLIDATED = 18;
+int const LF_SEDIMENT_INPUT_CONSOLIDATED = 19;
+
+// GIS raster input codes
+int const FINE_CONS_RASTER = 1;
+int const SAND_CONS_RASTER = 2;
+int const COARSE_CONS_RASTER = 3;
+int const FINE_UNCONS_RASTER = 4;
+int const SAND_UNCONS_RASTER = 5;
+int const COARSE_UNCONS_RASTER = 6;
+int const SUSP_SED_RASTER = 7;
+int const LANDFORM_RASTER = 8;
+int const INTERVENTION_CLASS_RASTER = 9;
+int const INTERVENTION_HEIGHT_RASTER = 10;
+
+// GIS vector data type codes
+int const VEC_FIELD_DATA_ANY = 0;
+int const VEC_FIELD_DATA_INT = 1;
+int const VEC_FIELD_DATA_REAL = 2;
+int const VEC_FIELD_DATA_STRING = 3;
+int const VEC_FIELD_DATA_OTHER = 4;
+
+// GIS vector geometry codes
+int const VEC_GEOMETRY_POINT = 1;
+int const VEC_GEOMETRY_LINE = 2;
+int const VEC_GEOMETRY_POLYGON = 3;
+int const VEC_GEOMETRY_OTHER = 4;
+
+// GIS vector input codes and constraints
+int const DEEP_WATER_WAVE_STATIONS_VEC = 1;
+int const DEEP_WATER_WAVE_STATIONS_MAX_LAYER = 1;
+int const DEEP_WATER_WAVE_STATIONS_POINT_GEOMETRY = VEC_GEOMETRY_POINT;
+int const SEDIMENT_INPUT_EVENT_LOCATION_VEC = 2;
+int const SEDIMENT_INPUT_EVENT_LOCATION_MAX_LAYER = 1;
+int const SEDIMENT_INPUT_EVENT_LOCATION_POINT_GEOMETRY = VEC_GEOMETRY_POINT;
+int const FLOOD_LOCATION_POINT_GEOMETRY = VEC_GEOMETRY_POINT;
+int const SEDIMENT_INPUT_EVENT_LOCATION_LINE_GEOMETRY = VEC_GEOMETRY_LINE;
+int const FLOOD_LOCATION_VEC = 3;
+int const FLOOD_LOCATION_MAX_LAYER = 1;
+
+// GIS raster output codes
+
+int const RASTER_PLOT_ACTIVE_ZONE = 1;
+int const RASTER_PLOT_ACTUAL_BEACH_EROSION = 2;
+int const RASTER_PLOT_ACTUAL_PLATFORM_EROSION = 3;
+int const RASTER_PLOT_AVG_SEA_DEPTH = 4;
+int const RASTER_PLOT_AVG_SUSPENDED_SEDIMENT = 5;
+int const RASTER_PLOT_AVG_WAVE_HEIGHT = 6;
+int const RASTER_PLOT_AVG_WAVE_ORIENTATION = 7;
+int const RASTER_PLOT_BASEMENT_ELEVATION = 8;
+int const RASTER_PLOT_BEACH_DEPOSITION = 9;
+int const RASTER_PLOT_BEACH_MASK = 10;
+int const RASTER_PLOT_BEACH_PROTECTION = 11;
+int const RASTER_PLOT_CLIFF_COLLAPSE_DEPOSITION_COARSE = 12;
+int const RASTER_PLOT_CLIFF_COLLAPSE_DEPOSITION_SAND = 13;
+int const RASTER_PLOT_CLIFF_COLLAPSE_EROSION_COARSE = 14;
+int const RASTER_PLOT_CLIFF_COLLAPSE_EROSION_FINE = 15;
+int const RASTER_PLOT_CLIFF_COLLAPSE_EROSION_SAND = 16;
+#ifdef _DEBUG
+int const RASTER_PLOT_CLIFF_COLLAPSE_TIMESTEP = 17;
+#endif
+int const RASTER_PLOT_CLIFF_NOTCH_ALL = 18;
+int const RASTER_PLOT_CLIFF_TOE = 19;
+int const RASTER_PLOT_COARSE_CONSOLIDATED_SEDIMENT = 20;
+int const RASTER_PLOT_COARSE_UNCONSOLIDATED_SEDIMENT = 21;
+int const RASTER_PLOT_COAST = 22;
+int const RASTER_PLOT_DEEP_WATER_WAVE_HEIGHT = 23;
+int const RASTER_PLOT_DEEP_WATER_WAVE_ORIENTATION = 24;
+int const RASTER_PLOT_DEEP_WATER_WAVE_PERIOD = 25;
+int const RASTER_PLOT_FINE_CONSOLIDATED_SEDIMENT = 26;
+int const RASTER_PLOT_FINE_UNCONSOLIDATED_SEDIMENT = 27;
+int const RASTER_PLOT_INTERVENTION_CLASS = 28;
+int const RASTER_PLOT_INTERVENTION_HEIGHT = 29;
+int const RASTER_PLOT_INUNDATION_MASK = 30;
+int const RASTER_PLOT_LANDFORM = 31;
+int const RASTER_PLOT_NORMAL_PROFILE = 32;
+int const RASTER_PLOT_TOP_ELEV_INC_SEA = 33;
+int const RASTER_PLOT_POLYGON = 34;
+int const RASTER_PLOT_POLYGON_GAIN_OR_LOSS = 35;
+int const RASTER_PLOT_POLYGON_UPDRIFT_OR_DOWNDRIFT = 36;
+int const RASTER_PLOT_POTENTIAL_BEACH_EROSION = 37;
+int const RASTER_PLOT_POTENTIAL_PLATFORM_EROSION = 38;
+int const RASTER_PLOT_POTENTIAL_PLATFORM_EROSION_MASK = 39;
+int const RASTER_PLOT_SAND_CONSOLIDATED_SEDIMENT = 40;
+int const RASTER_PLOT_SAND_UNCONSOLIDATED_SEDIMENT = 41;
+int const RASTER_PLOT_SEA_DEPTH = 42;
+int const RASTER_PLOT_SEDIMENT_INPUT = 43;
+int const RASTER_PLOT_SED_TOP_INC_TALUS_ELEV = 44;
+int const RASTER_PLOT_SETUP_SURGE_FLOOD_MASK = 45;
+int const RASTER_PLOT_SETUP_SURGE_RUNUP_FLOOD_MASK = 46;
+int const RASTER_PLOT_SHADOW_DOWNDRIFT_ZONE = 47;
+int const RASTER_PLOT_SHADOW_ZONE = 48;
+int const RASTER_PLOT_SLICE = 49;
+int const RASTER_PLOT_SLOPE_FOR_CLIFF_TOE = 50;
+int const RASTER_PLOT_CONS_SED_SLOPE = 51;
+int const RASTER_PLOT_SUSPENDED_SEDIMENT = 52;
+int const RASTER_PLOT_TALUS = 53;
+int const RASTER_PLOT_TOTAL_ACTUAL_BEACH_EROSION = 54;
+int const RASTER_PLOT_TOTAL_ACTUAL_PLATFORM_EROSION = 55;
+int const RASTER_PLOT_TOTAL_BEACH_DEPOSITION = 56;
+int const RASTER_PLOT_TOTAL_CLIFF_COLLAPSE_DEPOSITION_COARSE = 57;
+int const RASTER_PLOT_TOTAL_CLIFF_COLLAPSE_DEPOSITION_SAND = 58;
+int const RASTER_PLOT_TOTAL_CLIFF_COLLAPSE_EROSION_COARSE = 59;
+int const RASTER_PLOT_TOTAL_CLIFF_COLLAPSE_EROSION_FINE = 60;
+int const RASTER_PLOT_TOTAL_CLIFF_COLLAPSE_EROSION_SAND = 61;
+int const RASTER_PLOT_TOTAL_POTENTIAL_BEACH_EROSION = 62;
+int const RASTER_PLOT_TOTAL_POTENTIAL_PLATFORM_EROSION = 63;
+int const RASTER_PLOT_WAVE_FLOOD_LINE = 64;
+int const RASTER_PLOT_WAVE_HEIGHT = 65;
+int const RASTER_PLOT_WAVE_ORIENTATION = 66;
+
+// GIS vector output codes
+// int const VECTOR_PLOT_FLOOD_SWL_SETUP_LINE = 19;
+int const VECTOR_PLOT_AVG_WAVE_ANGLE_AND_HEIGHT = 1;
+int const VECTOR_PLOT_BREAKING_WAVE_HEIGHT = 2;
+int const VECTOR_PLOT_CLIFF_EDGE = 3;
+int const VECTOR_PLOT_CLIFF_NOTCH_ACTIVE = 4;
+int const VECTOR_PLOT_COAST = 5;
+int const VECTOR_PLOT_COAST_CURVATURE = 6;
+int const VECTOR_PLOT_COAST_SWL_HIGHEST = 7;
+int const VECTOR_PLOT_COAST_SWL_LOWEST = 8;
+int const VECTOR_PLOT_DEEP_WATER_WAVE_ANGLE_AND_HEIGHT = 9;
+int const VECTOR_PLOT_DOWNDRIFT_ZONE_BOUNDARY = 10;
+int const VECTOR_PLOT_FLOOD_LINE = 11;
+int const VECTOR_PLOT_INVALID_NORMALS = 12;
+int const VECTOR_PLOT_MEAN_WAVE_ENERGY = 13;
+int const VECTOR_PLOT_NORMALS = 14;
+int const VECTOR_PLOT_POLYGON_BOUNDARY = 15;
+int const VECTOR_PLOT_POLYGON_NODES = 16;
+int const VECTOR_PLOT_RUN_UP = 17;
+int const VECTOR_PLOT_SHADOW_ZONE_BOUNDARY = 18;
+int const VECTOR_PLOT_STORM_SURGE = 19;
+int const VECTOR_PLOT_WAVE_ANGLE_AND_HEIGHT = 20;
+int const VECTOR_PLOT_WAVE_ENERGY_SINCE_COLLAPSE = 21;
+int const VECTOR_PLOT_WAVE_SETUP = 22;
+int const VECTOR_PLOT_WAVE_TRANSECT_POINTS = 23;
+// int const VECTOR_PLOT_FLOOD_SWL_SETUP_SURGE_LINE = 24;
+// int const VECTOR_PLOT_FLOOD_SWL_SETUP_SURGE_RUNUP_LINE = 25;
+
+// Return codes
+int const RTN_OK = 0;
+int const RTN_HELP_ONLY = 1;
+int const RTN_CHECK_ONLY = 2;
+int const RTN_USER_ABORT = 3;
+int const RTN_ERR_BADPARAM = 4;
+int const RTN_ERR_INI = 5;
+int const RTN_ERR_CMEDIR = 6;
+int const RTN_ERR_RUNDATA = 7;
+int const RTN_ERR_SCAPE_SHAPE_FUNCTION_FILE = 8;
+int const RTN_ERR_TIDEDATAFILE = 9;
+int const RTN_ERR_LOGFILE = 10;
+int const RTN_ERR_OUTFILE = 11;
+int const RTN_ERR_TSFILE = 12;
+int const RTN_ERR_DEMFILE = 13;
+int const RTN_ERR_RASTER_FILE_READ = 14;
+int const RTN_ERR_VECTOR_FILE_READ = 15;
+int const RTN_ERR_MEMALLOC = 16;
+int const RTN_ERR_RASTER_GIS_OUT_FORMAT = 17;
+int const RTN_ERR_VECTOR_GIS_OUT_FORMAT = 18;
+int const RTN_ERR_TEXT_FILE_WRITE = 19;
+int const RTN_ERR_RASTER_FILE_WRITE = 20;
+int const RTN_ERR_VECTOR_FILE_WRITE = 21;
+int const RTN_ERR_TIMESERIES_FILE_WRITE = 22;
+int const RTN_ERR_LINETOGRID = 23;
+int const RTN_ERR_PROFILE_SPACING = 24;
+// 25 is now missing
+int const RTN_ERR_PROFILE_ENDPOINT_IS_INLAND = 26;
+int const RTN_ERR_NO_SOLUTION_FOR_ENDPOINT = 27;
+int const RTN_ERR_PROFILE_END_INSUFFICIENT_DEPTH = 28;
+int const RTN_ERR_NO_PROFILES_1 = 29;
+int const RTN_ERR_NO_PROFILES_2 = 30;
+int const RTN_ERR_NOSEACELLS = 31;
+int const RTN_ERR_GRID_TO_LINE = 32;
+int const RTN_ERR_NO_COAST = 34;
+int const RTN_ERR_PROFILE_WRITE = 35;
+int const RTN_ERR_TIME_UNITS = 36;
+int const RTN_ERR_CLIFF_NOTCH = 37;
+int const RTN_ERR_CLIFF_CANNOT_DEPOSIT_ALL = 38;
+int const RTN_ERR_BAD_INDEX = 39;
+int const RTN_ERR_EDGE_OF_GRID = 40;
+int const RTN_ERR_NO_SEAWARD_END_OF_PROFILE_BEACH_EROSION = 42;
+int const RTN_ERR_NO_SEAWARD_END_OF_PROFILE_UPCOAST_BEACH_DEPOSITION = 43;
+int const RTN_ERR_NO_SEAWARD_END_OF_PROFILE_DOWNCOAST_BEACH_DEPOSITION = 44;
+int const RTN_ERR_LANDFORM_TO_GRID = 45;
+int const RTN_ERR_NO_TOP_LAYER = 46;
+int const RTN_ERR_NO_ADJACENT_POLYGON = 47;
+int const RTN_ERR_BAD_MULTILINE = 48;
+int const RTN_ERR_CANNOT_INSERT_POINT = 49;
+int const RTN_ERR_CANNOT_ASSIGN_COASTAL_LANDFORM = 50;
+int const RTN_ERR_SHADOW_ZONE_FLOOD_FILL_NOGRID = 51;
+int const RTN_ERR_SHADOW_ZONE_FLOOD_START_POINT = 52;
+int const RTN_ERR_CSHORE_EMPTY_PROFILE = 53;
+int const RTN_ERR_CSHORE_FILE_INPUT = 54;
+int const RTN_ERR_READING_CSHORE_FILE_OUTPUT = 55;
+int const RTN_ERR_WAVE_INTERPOLATION_LOOKUP = 56;
+int const RTN_ERR_GRIDCREATE = 57;
+int const RTN_ERR_COAST_CANT_FIND_EDGE_CELL = 58;
+int const RTN_ERR_CSHORE_ERROR = 59;
+int const RTN_ERR_NO_CELL_UNDER_COASTLINE = 60;
+int const RTN_ERR_OPEN_DEEP_WATER_WAVE_DATA = 61;
+int const RTN_ERR_READING_DEEP_WATER_WAVE_DATA = 62;
+int const RTN_ERR_BOUNDING_BOX = 63;
+int const RTN_ERR_READING_SEDIMENT_INPUT_EVENT = 64;
+int const RTN_ERR_SEDIMENT_INPUT_EVENT = 65;
+int const RTN_ERR_SEDIMENT_INPUT_EVENT_LOCATION = 66;
+int const RTN_ERR_WAVESTATION_LOCATION = 67;
+int const RTN_ERR_FLOOD_LOCATION = 68;
+int const RTN_ERR_CLIFF_NOT_IN_POLYGON = 69;
+int const RTN_ERR_CELL_MARKED_PROFILE_COAST_BUT_NOT_PROFILE = 70;
+int const RTN_ERR_TRACING_FLOOD = 71;
+int const RTN_ERR_NO_START_FINISH_POINTS_TRACING_COAST = 72;
+int const RTN_ERR_NO_VALID_COAST = 73;
+int const RTN_ERR_REPEATING_WHEN_TRACING_COAST = 74;
+int const RTN_ERR_ZERO_LENGTH_COAST = 75;
+int const RTN_ERR_COAST_TOO_SMALL = 77;
+int const RTN_ERR_IGNORING_COAST = 78;
+int const RTN_ERR_TOO_LONG_TRACING_COAST = 79;
+int const RTN_ERR_CELL_NOT_FOUND_IN_HIT_PROFILE_DIFFERENT_COASTS = 80;
+int const RTN_ERR_POINT_NOT_FOUND_IN_MULTILINE_DIFFERENT_COASTS = 81;
+int const RTN_ERR_CELL_NOT_FOUND_IN_HIT_PROFILE = 82;
+int const RTN_ERR_CELL_IN_POLY_BUT_NO_POLY_COAST = 83;
+int const RTN_ERR_CLIFF_TALUS_TO_UNCONS = 84;
+int const RTN_ERR_UNKNOWN = 999;
+
+// Elevation and 'slice' codes
+int const ELEV_IN_BASEMENT = -1;
+int const ELEV_ABOVE_SEDIMENT_TOP = -2;
+int const NO_NONZERO_THICKNESS_LAYERS = -3;
+
+// Vector smoothing codes
+int const SMOOTH_NONE = 0;
+int const SMOOTH_RUNNING_MEAN = 1;
+int const SMOOTH_SAVITZKY_GOLAY = 2;
+
+// Grid-edge boundary treatment for unconsolidated sediment movement
+int const GRID_EDGE_CLOSED = 0;
+int const GRID_EDGE_OPEN = 1;
+int const GRID_EDGE_RECIRCULATE = 2;
+
+// Model for wave propagation
+int const WAVE_MODEL_COVE = 0;
+int const WAVE_MODEL_CSHORE = 1;
+
+// Equation for estimating erosion of unconsolidated sediment
+int const UNCONS_SEDIMENT_EQUATION_CERC = 0;
+int const UNCONS_SEDIMENT_EQUATION_KAMPHUIS = 1;
+
+int const CLIFF_COLLAPSE_LENGTH_INCREMENT = 10; // Increment the planview length of the cliff talus Dean profile, if we have not been able to deposit enough
+int const PROFILE_CHECK_DIST_FROM_COAST = 20; // TEST TODO Used in checking shoreline-normal profiles for intersection
+int const GAP_BETWEEN_DIFFERENT_COAST_PROFILES = 30; // In cells, is the gap between profile ends belonging to different coasts
+
+int const NUM_DAYS_FOR_MEAN_HIGH_WATER_CALC = 30; // Number of days to average daily high water elevation
+
+int const NO_RUNUP_EQUATION = 0; // Runup not considered
+int const RUNUP_EQUATION_NIELSEN_HANSLOW = 1; // Runup equation is Nielsen, P. & Hanslow, D. J. 1991. Wave Runup Distributions on Natural Beaches. Journal of Coastal Research, 7, 1139-1152. *** & DHI (2004) ???
+int const RUNUP_EQUATION_MASE = 2; // Runup equation is Mase, H. 1989. Random Wave Runup Height on Gentle Slope. Journal of Waterway, Port, Coastal, and Ocean Engineering, 115, 649-661.
+int const RUNUP_EQUATION_STOCKDON = 3; // Runup equation is Stockdon, H. F., Holman, R. A., Howd, P. A. & Sallenger JR, A. H. 2006. Empirical parameterization of setup, swash, and runup. Coastal Engineering, 53, 573-588.
+
+unsigned long const MASK = 0xfffffffful;
+unsigned long const SEDIMENT_INPUT_EVENT_ERROR = -1;
+unsigned long const UNSIGNED_LONG_NODATA = 9999;
+
+double const PI = 3.141592653589793238462643;
+
+double const D50_FINE_DEFAULT = 0.0625; // In mm
+double const D50_SAND_DEFAULT = 0.42; // In mm
+double const D50_COARSE_DEFAULT = 19.0; // In mm
+
+double const BEACH_PROTECTION_HB_RATIO = 0.23; // The beach protection factor is this times breaking depth
+double const WALKDEN_HALL_PARAM_1 = 3.25; // First parameter in Equation 4 from Walkden & Hall, 2005
+double const WALKDEN_HALL_PARAM_2 = 1.50; // Second parameter in Equation 4 from Walkden & Hall, 2005
+
+double const DEPTH_OVER_DB_INCREMENT = 0.001; // Depth over DB increment for erosion potential look-up function
+double const INVERSE_DEPTH_OVER_DB_INCREMENT = 1000; // Inverse of the above
+double const DEAN_POWER = 2.0 / 3.0; // Dean profile exponent
+
+// TODO 011 Let the user define these CShore input parameters
+double const CSHORE_FRICTION_FACTOR = 0.015; // Friction factor for CShore model
+double const CSHORE_SURGE_LEVEL = 0.0; // TODO 007
+
+double const TOLERANCE = 1e-7; // For bFPIsEqual, if too small (e.g. 1e-10), get spurious "rounding" errors
+double const SED_ELEV_TOLERANCE = 1e-5; // Used to compare depth-equivalent sediment amounts in bFPIsEqual and elsewhere
+double const MASS_BALANCE_TOLERANCE = 1e-5; // For bFPIsEqual, used to compare for mass balance checks
+double const STRAIGHT_COAST_MAX_DETAILED_CURVATURE = -5;
+double const STRAIGHT_COAST_MAX_SMOOTH_CURVATURE = -1;
+double const MIN_LENGTH_OF_SHADOW_ZONE_LINE = 10; // Used in shadow line tracing
+double const MAX_LAND_LENGTH_OF_SHADOW_ZONE_LINE = 5; // Used in shadow line tracing
+double const CLIFF_COLLAPSE_HEIGHT_INCREMENT = 0.1; // Increment the fractional height of the cliff talus Dean profile, if we have not been able to deposit enough
+double const INTERVENTION_PROFILE_SPACING_FACTOR = 0.5; // Profile spacing on interventions works better if it is smaller than profile spacing on coastline
+
+double const CLIFF_NOTCH_CUTOFF_DISTANCE = 2; // Cut-off SWL distance (m), measured downwards from the cliff notch apex: below this there is no notch incision
+double const DBL_NODATA = -9999;
+
+string const PROGRAM_NAME = "Coastal Modelling Environment (CoastalME) version 1.4.0 (11 Nov 2025)";
+string const PROGRAM_NAME_SHORT = "CME";
+string const CME_INI = "cme.ini";
+
+string const COPYRIGHT = "(C) 2025 Andres Payo and David Favis-Mortlock";
+string const LINE = "-------------------------------------------------------------------------------";
+string const DISCLAIMER1 = "This program is distributed in the hope that it will be useful, but WITHOUT ANY";
+string const DISCLAIMER2 = "WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A";
+string const DISCLAIMER3 = "PARTICULAR PURPOSE. See the GNU General Public License for more details. You";
+string const DISCLAIMER4 = "should have received a copy of the GNU General Public License along with this";
+string const DISCLAIMER5 = "program; if not, contact the Free Software Foundation, Inc., 675 Mass Ave,";
+string const DISCLAIMER6 = "Cambridge, MA 02139, USA.";
+
+string const ABOUT = "simulates the long-term behaviour of a coast. This initial version considers only simple soft cliff cross-shore effects";
+string const THANKS = "Many thanks to:\n\tTom Ashby\n\tManuel Cobos Budia\n\tWilf Chun\n\tMark Dickson\n\tJim W. Hall\n\tMartin D. Hurst\n\tMatthew Ives\n\tRobert J. Nicholls\n\tIan Townend\n\tMike J.A. Walkden";
+string const GDAL_DRIVERS = "GDAL drivers";
+
+string const USAGE = "Usage: cme [OPTION]...";
+string const USAGE1 = " --gdal List GDAL drivers";
+string const USAGE2 = " --about Information about this program";
+string const USAGE3 = " --help Display this text";
+string const USAGE4 = " --home=DIRECTORY Specify the location of the .ini file etc.";
+string const USAGE5 = " --datafile=FILE Specify the location and name of the main datafile";
+string const USAGE6 = " --yaml Use YAML format for the main datafile";
+
+string const START_NOTICE = "- Started on ";
+string const INITIALIZING_NOTICE = "- Initializing";
+string const READING_FILE_LOCATIONS = " - Reading file locations: ";
+string const READING_RUN_DATA = " - Reading run data file: ";
+string const READING_BASEMENT = " - Reading basement DEM: ";
+string const READING_RASTER_FILES = " - Reading raster GIS files";
+string const READING_LANDFORM_FILE = " - Landform class: ";
+string const READING_INTERVENTION_CLASS_FILE = " - Intervention class: ";
+string const READING_INTERVENTION_HEIGHT_FILE = " - Intervention height: ";
+string const READING_SUSPENDED_SEDIMENT_FILE = " - Suspended sediment: ";
+string const READING_UNCONS_FINE_SEDIMENT_FILE = " - Unconsolidated fine sediment (layer ";
+string const READING_UNCONS_SAND_SEDIMENT_FILE = " - Unconsolidated sand sediment (layer ";
+string const READING_UNCONS_COARSE_SEDIMENT_FILE = " - Unconsolidated coarse sediment (layer ";
+string const READING_CONS_FINE_SEDIMENT_FILE = " - Consolidated fine sediment (layer ";
+string const READING_CONS_SAND_SEDIMENT_FILE = " - Consolidated sand sediment (layer ";
+string const READING_CONS_COARSE_SEDIMENT_FILE = " - Consolidated coarse sediment (layer ";
+string const READING_VECTOR_FILES = " - Reading vector GIS files";
+string const READING_DEEP_WATER_WAVE_FILE = " - Deep water wave values: ";
+string const READING_SED_INPUT_EVENT_FILE = " - Sediment input event values: ";
+string const READING_FLOOD_LOCATION = " - Characteristic locations for flood: ";
+string const READING_SCAPE_SHAPE_FUNCTION_FILE = " - Reading SCAPE shape function file";
+string const READING_TIDE_DATA_FILE = " - Reading tide data file: ";
+string const ALLOCATE_MEMORY = " - Allocating memory for raster grid";
+string const ADD_LAYERS = " - Adding sediment layers to raster grid";
+string const INITIALIZING_FINAL = " - Finishing initialization";
+string const RUN_NOTICE = "- Running simulation";
+string const SIMULATING = "\r - Simulating ";
+string const FINAL_OUTPUT = "- Writing final output";
+string const SEND_EMAIL = " - Sending email to ";
+string const RUN_END_NOTICE = "Run ended at ";
+string const PRESS_KEY = "Press any key to continue...";
+
+string const ERROR_NOTICE = " with error code ";
+string const EMAIL_ERROR = "Could not send email";
+
+string const SCAPE_DIR = "scape/";
+string const SCAPE_SHAPE_FUNCTION_FILE = "ShapeFunction.dat";
+string const EROSION_POTENTIAL_LOOKUP_FILE = "ErosionPotential.csv";
+
+string const CSHORE_DIR = "cshore/";
+string const CSHORE_INFILE = "infile";
+
+string const ERR = "*** ERROR ";
+string const WARN = "WARNING ";
+string const NOTE = " Note ";
+
+string const MASS_BALANCE_ERROR = "MASS BALANCE ERROR";
+
+string const PER_ITER_HEAD1 = "<-----ELAPSED----><--SEA-><----POTENTIAL---><-----------ACTUAL-----------><-----POTENTIAL-----><------------ACTUAL-------------><-----------ACTUAL------------><--SEDIMENT--><---CLIFF COLLAPSE--->";
+
+string const PER_ITER_HEAD2 = " TIME DEPTH PLATFORM EROSION PLATFORM EROSION BEACH EROSION BEACH EROSION BEACH DEPOSITION INPUT EVENT EROSION DEPOSITION SED";
+
+string const PER_ITER_HEAD3 = "Time Hours Years Avg % Sea All Erod % Sea All Erod <--sea avg-> % Sea All Erod % Sea All Erod <--sea avg-> % Sea All Depos <--sea--> <-coast avg-><--sea-->";
+
+string const PER_ITER_HEAD4 = "Step Area Sea Area Area Sea Area F S C Area Sea Area Area Sea Area F S C Area Sea Area S C F S C F S C S C F";
+
+string const PER_ITER_HEAD5 = " Avg Avg Avg Avg Avg Avg Avg Avg Avg";
+
+string const PER_ITER_HEAD = "PER-ITERATION RESULTS =============================================================================================================================================================================================";
+
+string const PER_ITER_CSV_HEAD = "Timestep,Hours, Years, AvgSeaDepth_m, PotPlatformErosion_PctSeaArea, PotPlatformErosion_AllAvg_mm, PotPlatformErosion_ErodAvg_mm, ActPlatformErosion_PctSeaArea, ActPlatformErosion_AllAvg_mm, ActPlatformErosion_ErodAvg_mm, ActPlatformErosion_Fine_mm, ActPlatformErosion_Sand_mm, ActPlatformErosion_Coarse_mm, PotBeachErosion_PctSeaArea, PotBeachErosion_AllAvg_mm, PotBeachErosion_ErodAvg_mm, ActBeachErosion_PctSeaArea, ActBeachErosion_AllAvg_mm, ActBeachErosion_ErodAvg_mm, ActBeachErosion_Fine_mm, ActBeachErosion_Sand_mm, ActBeachErosion_Coarse_mm, BeachDeposition_PctSeaArea, BeachDeposition_AllAvg_mm, BeachDeposition_DepAvg_mm, BeachDeposition_Sand_mm, BeachDeposition_Coarse_mm, SedimentInput_Fine, SedimentInput_Sand, SedimentInput_Coarse, CliffCollapse_Fine_mm, CliffCollapse_Sand_mm, CliffCollapse_Coarse_mm, CliffDeposition_Sand_mm, CliffDeposition_Coarse_mm, SuspendedSediment_mm, GISEvents";
+
+string const ENDHYDROLOGYHEAD = "END OF SIMULATION: HYDROLOGY ======================================================================================================================================================================================";
+string const ENDSEDIMENTHEAD = "END OF SIMULATION: SEDIMENT MOVEMENT ==============================================================================================================================================================================";
+string const PERFORMHEAD = "END OF SIMULATION: PERFORMANCE ====================================================================================================================================================================================";
+
+string const OUTEXT = ".out";
+string const LOGEXT = ".log";
+string const CSVEXT = ".csv";
+
+string const DEEP_WATER_WAVE_STATION_ID = "id";
+string const SEDIMENT_INPUT_EVENT_LOCATION_ID = "id";
+string const FLOOD_LOCATION_ID = "id";
+
+// GIS raster output user codes
+string const RASTER_ACTIVE_ZONE_CODE = "active_zone";
+string const RASTER_ACTIVE_ZONE_NAME = "active_zone";
+string const RASTER_ACTUAL_BEACH_EROSION_CODE = "actual_beach_erosion";
+string const RASTER_ACTUAL_BEACH_EROSION_NAME = "actual_beach_erosion";
+string const RASTER_ACTUAL_PLATFORM_EROSION_CODE = "actual_platform_erosion";
+string const RASTER_ACTUAL_PLATFORM_EROSION_NAME = "actual_platform_erosion";
+string const RASTER_ALL_OUTPUT_CODE = "all";
+string const RASTER_AVG_SEA_DEPTH_CODE = "avg_sea_depth";
+string const RASTER_AVG_SEA_DEPTH_NAME = "avg_sea_depth";
+string const RASTER_AVG_SUSP_SED_CODE = "avg_susp_sed";
+string const RASTER_AVG_SUSP_SED_NAME = "avg_susp_sed";
+string const RASTER_AVG_WAVE_HEIGHT_CODE = "avg_wave_height";
+string const RASTER_AVG_WAVE_HEIGHT_NAME = "avg_wave_height";
+string const RASTER_AVG_WAVE_ORIENTATION_CODE = "avg_wave_orientation";
+string const RASTER_AVG_WAVE_ORIENTATION_NAME = "avg_wave_orientation";
+string const RASTER_BASEMENT_ELEVATION_CODE = "basement_elevation";
+string const RASTER_BASEMENT_ELEVATION_NAME = "basement_elevation";
+string const RASTER_BEACH_DEPOSITION_CODE = "beach_deposition";
+string const RASTER_BEACH_DEPOSITION_NAME = "beach_deposition";
+string const RASTER_BEACH_MASK_CODE = "beach_mask";
+string const RASTER_BEACH_MASK_NAME = "beach_mask";
+string const RASTER_BEACH_PROTECTION_CODE = "beach_protection";
+string const RASTER_BEACH_PROTECTION_NAME = "beach_protection";
+string const RASTER_CLIFF_COLLAPSE_DEPOSITION_COARSE_CODE = "cliff_collapse_talus_deposition_coarse";
+string const RASTER_CLIFF_COLLAPSE_DEPOSITION_COARSE_NAME = "cliff_collapse_talus_deposition_coarse";
+string const RASTER_CLIFF_COLLAPSE_DEPOSITION_SAND_CODE = "cliff_collapse_talus_deposition_sand";
+string const RASTER_CLIFF_COLLAPSE_DEPOSITION_SAND_NAME = "cliff_collapse_talus_deposition_sand";
+string const RASTER_CLIFF_COLLAPSE_EROSION_COARSE_CODE = "cliff_collapse_erosion_coarse";
+string const RASTER_CLIFF_COLLAPSE_EROSION_COARSE_NAME = "cliff_collapse_erosion_coarse";
+string const RASTER_CLIFF_COLLAPSE_EROSION_FINE_CODE = "cliff_collapse_erosion_fine";
+string const RASTER_CLIFF_COLLAPSE_EROSION_FINE_NAME = "cliff_collapse_erosion_fine";
+string const RASTER_CLIFF_COLLAPSE_EROSION_SAND_CODE = "cliff_collapse_erosion_sand";
+string const RASTER_CLIFF_COLLAPSE_EROSION_SAND_NAME = "cliff_collapse_erosion_sand";
+string const RASTER_CLIFF_COLLAPSE_TIMESTEP_CODE = "cliff_collapse_timestep";
+string const RASTER_CLIFF_COLLAPSE_TIMESTEP_NAME = "cliff_collapse_timestep_all";
+string const RASTER_CLIFF_NOTCH_ALL_CODE = "cliff_notch_all";
+string const RASTER_CLIFF_NOTCH_ALL_NAME = "cliff_notch_all";
+string const RASTER_CLIFF_TOE_NAME = "cliff_toe"; // Note no code for this, because is chosen by m_bCliffToeLocate in input file
+string const RASTER_COARSE_CONS_CODE = "cons_sed_coarse";
+string const RASTER_COARSE_CONS_NAME = "cons_sed_coarse";
+string const RASTER_COARSE_UNCONS_CODE = "uncons_sed_coarse";
+string const RASTER_COARSE_UNCONS_NAME = "uncons_sed_coarse";
+string const RASTER_COAST_CODE = "rcoast";
+string const RASTER_COAST_NAME = "rcoast";
+string const RASTER_COAST_NORMAL_CODE = "rcoast_normal";
+string const RASTER_COAST_NORMAL_NAME = "rcoast_normal";
+string const RASTER_DEEP_WATER_WAVE_HEIGHT_CODE = "deep_water_wave_height";
+string const RASTER_DEEP_WATER_WAVE_HEIGHT_NAME = "deep_water_wave_height";
+string const RASTER_DEEP_WATER_WAVE_ORIENTATION_CODE = "deep_water_wave_orientation";
+string const RASTER_DEEP_WATER_WAVE_ORIENTATION_NAME = "deep_water_wave_orientation";
+string const RASTER_DEEP_WATER_WAVE_PERIOD_CODE = "deep_water_wave_period";
+string const RASTER_DEEP_WATER_WAVE_PERIOD_NAME = "deep_water_wave_period";
+string const RASTER_FINE_CONS_CODE = "cons_sed_fine";
+string const RASTER_FINE_CONS_NAME = "cons_sed_fine";
+string const RASTER_FINE_UNCONS_CODE = "uncons_sed_fine";
+string const RASTER_FINE_UNCONS_NAME = "uncons_sed_fine";
+string const RASTER_INTERVENTION_CLASS_CODE = "intervention_class";
+string const RASTER_INTERVENTION_CLASS_NAME = "intervention_class";
+string const RASTER_INTERVENTION_HEIGHT_CODE = "intervention_height";
+string const RASTER_INTERVENTION_HEIGHT_NAME = "intervention_height";
+string const RASTER_INUNDATION_MASK_CODE = "inundation_mask";
+string const RASTER_INUNDATION_MASK_NAME = "inundation_mask";
+string const RASTER_LANDFORM_CODE = "landform_class";
+string const RASTER_LANDFORM_NAME = "landform_class";
+string const RASTER_POLYGON_CODE = "polygon_raster";
+string const RASTER_POLYGON_GAIN_OR_LOSS_CODE = "polygon_gain_or_loss";
+string const RASTER_POLYGON_GAIN_OR_LOSS_NAME = "polygon_gain_or_loss";
+string const RASTER_POLYGON_NAME = "polygon_raster";
+string const RASTER_POLYGON_UPDRIFT_OR_DOWNDRIFT_CODE = "polygon_updrift_or_downdrift";
+string const RASTER_POLYGON_UPDRIFT_OR_DOWNDRIFT_NAME = "polygon_updrift_or_downdrift";
+string const RASTER_POTENTIAL_BEACH_EROSION_CODE = "potential_beach_erosion";
+string const RASTER_POTENTIAL_BEACH_EROSION_NAME = "potential_beach_erosion";
+string const RASTER_POTENTIAL_PLATFORM_EROSION_CODE = "potential_platform_erosion";
+string const RASTER_POTENTIAL_PLATFORM_EROSION_MASK_CODE = "potential_platform_erosion_mask";
+string const RASTER_POTENTIAL_PLATFORM_EROSION_MASK_NAME = "potential_platform_erosion_mask";
+string const RASTER_POTENTIAL_PLATFORM_EROSION_NAME = "potential_platform_erosion";
+string const RASTER_SAND_CONS_CODE = "cons_sed_sand";
+string const RASTER_SAND_CONS_NAME = "cons_sed_sand";
+string const RASTER_SAND_UNCONS_CODE = "uncons_sed_sand";
+string const RASTER_SAND_UNCONS_NAME = "uncons_sed_sand";
+string const RASTER_SEA_DEPTH_CODE = "sea_depth";
+string const RASTER_SEA_DEPTH_NAME = "sea_depth";
+string const RASTER_SEDIMENT_INPUT_EVENT_CODE = "sediment_input_total";
+string const RASTER_SEDIMENT_INPUT_EVENT_NAME = "sediment_input_total";
+string const RASTER_SEDIMENT_TOP_CODE = "sediment_top_elevation";
+string const RASTER_SEDIMENT_TOP_ELEVATION_NAME = "sediment_top_elevation";
+string const RASTER_SETUP_SURGE_FLOOD_MASK_CODE = "flood_setup_surge_mask";
+string const RASTER_SETUP_SURGE_FLOOD_MASK_NAME = "flood_setup_surge_mask";
+string const RASTER_SETUP_SURGE_RUNUP_FLOOD_MASK_CODE = "flood_setup_surge_runup_mask";
+string const RASTER_SETUP_SURGE_RUNUP_FLOOD_MASK_NAME = "flood_setup_surge_runup_mask";
+string const RASTER_SHADOW_DOWNDRIFT_ZONE_CODE = "shadow_downdrift_zones";
+string const RASTER_SHADOW_DOWNDRIFT_ZONE_NAME = "shadow_downdrift_zones";
+string const RASTER_SHADOW_ZONE_CODE = "shadow_zones";
+string const RASTER_SHADOW_ZONE_NAME = "shadow_zones";
+string const RASTER_SLICE_CODE = "slice";
+string const RASTER_SLICE_NAME = "slice";
+string const RASTER_SLOPE_FOR_CLIFF_TOE_NAME = "toe_slope"; // Note no code for this, because is chosen by m_bCliffToeLocate in input file
+string const RASTER_SLOPE_OF_CONSOLIDATED_SEDIMENT_CODE = "cons_sediment_slope";
+string const RASTER_SLOPE_OF_CONSOLIDATED_SEDIMENT_NAME = "cons_sediment_slope";
+string const RASTER_SUSP_SED_CODE = "susp_sed";
+string const RASTER_SUSP_SED_NAME = "susp_sed";
+string const RASTER_TALUS_CODE = "talus";
+string const RASTER_TALUS_NAME = "talus";
+string const RASTER_TOP_ELEVATION_INC_SEA_CODE = "top_elevation";
+string const RASTER_TOP_ELEVATION_INC_SEA_NAME = "top_elevation_inc_sea";
+string const RASTER_TOTAL_ACTUAL_BEACH_EROSION_CODE = "total_actual_beach_erosion";
+string const RASTER_TOTAL_ACTUAL_BEACH_EROSION_NAME = "total_actual_beach_erosion";
+string const RASTER_TOTAL_ACTUAL_PLATFORM_EROSION_CODE = "total_actual_platform_erosion";
+string const RASTER_TOTAL_ACTUAL_PLATFORM_EROSION_NAME = "total_actual_platform_erosion";
+string const RASTER_TOTAL_BEACH_DEPOSITION_CODE = "total_beach_deposition";
+string const RASTER_TOTAL_BEACH_DEPOSITION_NAME = "total_beach_deposition";
+string const RASTER_TOTAL_CLIFF_COLLAPSE_DEPOSITION_COARSE_CODE = "total_cliff_collapse_talus_deposition_coarse";
+string const RASTER_TOTAL_CLIFF_COLLAPSE_DEPOSITION_COARSE_NAME = "total_cliff_collapse_talus_deposition_coarse";
+string const RASTER_TOTAL_CLIFF_COLLAPSE_DEPOSITION_SAND_CODE = "total_cliff_collapse_talus_deposition_sand";
+string const RASTER_TOTAL_CLIFF_COLLAPSE_DEPOSITION_SAND_NAME = "total_cliff_collapse_talus_deposition_sand";
+string const RASTER_TOTAL_CLIFF_COLLAPSE_EROSION_COARSE_CODE = "total_cliff_collapse_erosion_coarse";
+string const RASTER_TOTAL_CLIFF_COLLAPSE_EROSION_COARSE_NAME = "total_cliff_collapse_erosion_coarse";
+string const RASTER_TOTAL_CLIFF_COLLAPSE_EROSION_FINE_CODE = "total_cliff_collapse_erosion_fine";
+string const RASTER_TOTAL_CLIFF_COLLAPSE_EROSION_FINE_NAME = "total_cliff_collapse_erosion_fine";
+string const RASTER_TOTAL_CLIFF_COLLAPSE_EROSION_SAND_CODE = "total_cliff_collapse_erosion_sand";
+string const RASTER_TOTAL_CLIFF_COLLAPSE_EROSION_SAND_NAME = "total_cliff_collapse_erosion_sand";
+string const RASTER_TOTAL_POTENTIAL_BEACH_EROSION_CODE = "total_potential_beach_erosion";
+string const RASTER_TOTAL_POTENTIAL_BEACH_EROSION_NAME = "total_potential_beach_erosion";
+string const RASTER_TOTAL_POTENTIAL_PLATFORM_EROSION_CODE = "total_potential_platform_erosion";
+string const RASTER_TOTAL_POTENTIAL_PLATFORM_EROSION_NAME = "total_potential_platform_erosion";
+string const RASTER_USUAL_OUTPUT_CODE = "usual";
+string const RASTER_WAVE_FLOOD_LINE_CODE = "wave_flood_line";
+string const RASTER_WAVE_FLOOD_LINE_NAME = "wave_flood_line";
+string const RASTER_WAVE_HEIGHT_CODE = "wave_height";
+string const RASTER_WAVE_HEIGHT_NAME = "wave_height";
+string const RASTER_WAVE_ORIENTATION_CODE = "wave_orientation";
+string const RASTER_WAVE_ORIENTATION_NAME = "wave_orientation";
+string const RASTER_WAVE_PERIOD_CODE = "wave_period";
+string const RASTER_WAVE_PERIOD_NAME = "wave_period";
+
+// GIS raster output titles
+string const RASTER_PLOT_ACTIVE_ZONE_TITLE = "Active zone";
+string const RASTER_PLOT_ACTUAL_BEACH_EROSION_TITLE = "Actual (constrained) beach erosion depth";
+string const RASTER_PLOT_ACTUAL_PLATFORM_EROSION_TITLE = "Actual (constrained) shore platform erosion depth";
+string const RASTER_PLOT_AVG_SEA_DEPTH_TITLE = "Average sea depth";
+string const RASTER_PLOT_AVG_SUSPENDED_SEDIMENT_TITLE = "Average depth of suspended sediment";
+string const RASTER_PLOT_AVG_WAVE_HEIGHT_TITLE = "Average wave height";
+string const RASTER_PLOT_AVG_WAVE_ORIENTATION_TITLE = "Average wave orientation";
+string const RASTER_PLOT_BASEMENT_ELEVATION_TITLE = "Basement elevation";
+string const RASTER_PLOT_BEACH_DEPOSITION_TITLE = "Beach deposition depth";
+string const RASTER_PLOT_BEACH_MASK_TITLE = "Beach mask";
+string const RASTER_PLOT_BEACH_PROTECTION_TITLE = "Beach protection factor";
+string const RASTER_PLOT_CLIFF_COLLAPSE_DEPOSITION_COARSE_TITLE = "Depth of coarse talus from cliff collapse";
+string const RASTER_PLOT_CLIFF_COLLAPSE_DEPOSITION_SAND_TITLE = "Depth of sand talus from cliff collapse";
+string const RASTER_PLOT_CLIFF_COLLAPSE_EROSION_COARSE_TITLE = "Cliff collapse depth of erosion, coarse sediment";
+string const RASTER_PLOT_CLIFF_COLLAPSE_EROSION_FINE_TITLE = "Cliff collapse depth of erosion, fine sediment";
+string const RASTER_PLOT_CLIFF_COLLAPSE_EROSION_SAND_TITLE = "Cliff collapse depth of erosion, sand sediment";
+#ifdef _DEBUG
+string const RASTER_PLOT_CLIFF_COLLAPSE_TIMESTEP_TITLE = "Timestep at which cliff collapse occurred";
+#endif
+string const RASTER_PLOT_CLIFF_NOTCH_ALL_TITLE = "All cliff notch incision";
+string const RASTER_PLOT_CLIFF_TOE_TITLE = "Cliff toe cells";
+string const RASTER_PLOT_COARSE_CONSOLIDATED_SEDIMENT_TITLE = "Consolidated coarse sediment depth";
+string const RASTER_PLOT_COARSE_UNCONSOLIDATED_SEDIMENT_TITLE = "Unconsolidated coarse sediment depth";
+string const RASTER_PLOT_COAST_TITLE = "Rasterized coastline";
+string const RASTER_PLOT_DEEP_WATER_WAVE_HEIGHT_TITLE = "Deep water wave height";
+string const RASTER_PLOT_DEEP_WATER_WAVE_ORIENTATION_TITLE = "Deep water wave orientation";
+string const RASTER_PLOT_DEEP_WATER_WAVE_PERIOD_TITLE = "Deep water wave period";
+string const RASTER_PLOT_FINE_CONSOLIDATED_SEDIMENT_TITLE = "Consolidated fine sediment depth";
+string const RASTER_PLOT_FINE_UNCONSOLIDATED_SEDIMENT_TITLE = "Unconsolidated fine sediment depth";
+string const RASTER_PLOT_INTERVENTION_CLASS_TITLE = "Intervention class";
+string const RASTER_PLOT_INTERVENTION_HEIGHT_TITLE = "Intervention height";
+string const RASTER_PLOT_INUNDATION_MASK_TITLE = "Inundated area mask";
+string const RASTER_PLOT_LANDFORM_TITLE = "Landform class";
+string const RASTER_PLOT_NORMAL_PROFILE_TITLE = "Rasterized normal profiles";
+string const RASTER_PLOT_POLYGON_GAIN_OR_LOSS_TITLE = "Polygon gain or loss of unconsolidated sediment";
+string const RASTER_PLOT_POLYGON_TITLE = "Rasterized polygon boundaries";
+string const RASTER_PLOT_POLYGON_UPDRIFT_OR_DOWNDRIFT_TITLE = "Polygon updrift or downdrift movement of unconsolidated sediment";
+string const RASTER_PLOT_POTENTIAL_BEACH_EROSION_TITLE = "Potential (unconstrained) beach erosion depth";
+string const RASTER_PLOT_POTENTIAL_PLATFORM_EROSION_MASK_TITLE = "Potential (unconstrained) shore platform erosion binary mask";
+string const RASTER_PLOT_POTENTIAL_PLATFORM_EROSION_TITLE = "Potential (unconstrained) shore platform erosion depth";
+string const RASTER_PLOT_SAND_CONSOLIDATED_SEDIMENT_TITLE = "Consolidated sand sediment depth";
+string const RASTER_PLOT_SAND_UNCONSOLIDATED_SEDIMENT_TITLE = "Unconsolidated sand sediment depth";
+string const RASTER_PLOT_SEA_DEPTH_TITLE = "Sea depth";
+string const RASTER_PLOT_SEDIMENT_INPUT_EVENT_TITLE = "Sediment input event(s) since last GIS save";
+string const RASTER_PLOT_SED_TOP_INC_TALUS_ELEV_TITLE = "Elevation of sediment top inc talus";
+string const RASTER_PLOT_SETUP_SURGE_FLOOD_MASK_TITLE = "Mask of setup-surge flood";
+string const RASTER_PLOT_SETUP_SURGE_RUNUP_FLOOD_MASK_TITLE = "Mask of setup-surge-runup flood";
+string const RASTER_PLOT_SHADOW_DOWNDRIFT_ZONE_TITLE = "Downdrift of wave shadow zones";
+string const RASTER_PLOT_SHADOW_ZONE_TITLE = "Wave shadow zones";
+string const RASTER_PLOT_SLICE_TITLE = "Slice though layers at elevation = ";
+string const RASTER_PLOT_SLOPE_FOR_CLIFF_TOE_TITLE = "Slope";
+string const RASTER_PLOT_CONS_SED_SLOPE_TITLE = "Local slope of consolidated sediment";
+string const RASTER_PLOT_SUSPENDED_SEDIMENT_TITLE = "Suspended sediment depth";
+string const RASTER_PLOT_TALUS_TITLE = "Talus from cliff collapse";
+string const RASTER_PLOT_TOP_ELEV_INC_SEA_TITLE = "Topmost elevation (sediment plus intervention plus se";
+string const RASTER_PLOT_TOTAL_ACTUAL_BEACH_EROSION_TITLE = "Total actual (constrained) beach erosion depth";
+string const RASTER_PLOT_TOTAL_ACTUAL_PLATFORM_EROSION_TITLE = "Total actual (constrained) shore platform erosion depth";
+string const RASTER_PLOT_TOTAL_BEACH_DEPOSITION_TITLE = "Total beach deposition depth";
+string const RASTER_PLOT_TOTAL_CLIFF_COLLAPSE_DEPOSITION_COARSE_TITLE = "Total depth of coarse talus from cliff collapse";
+string const RASTER_PLOT_TOTAL_CLIFF_COLLAPSE_DEPOSITION_SAND_TITLE = "Total depth of sand talus from cliff collapse";
+string const RASTER_PLOT_TOTAL_CLIFF_COLLAPSE_EROSION_COARSE_TITLE = "Total of cliff collapse erosion depth, coarse";
+string const RASTER_PLOT_TOTAL_CLIFF_COLLAPSE_EROSION_FINE_TITLE = "Total of cliff collapse erosion depth, fine";
+string const RASTER_PLOT_TOTAL_CLIFF_COLLAPSE_EROSION_SAND_TITLE = "Total of cliff collapse erosion depth, sand";
+string const RASTER_PLOT_TOTAL_POTENTIAL_BEACH_EROSION_TITLE = "Total potential (unconstrained) beach erosion depth";
+string const RASTER_PLOT_TOTAL_POTENTIAL_PLATFORM_EROSION_TITLE = "Total potential (unconstrained) shore platform erosion depth";
+string const RASTER_PLOT_WAVE_FLOOD_LINE_TITLE = "Wave flood line";
+string const RASTER_PLOT_WAVE_HEIGHT_TITLE = "Wave height";
+string const RASTER_PLOT_WAVE_ORIENTATION_TITLE = "Wave orientation";
+
+// GIS vector output user codes
+string const VECTOR_ALL_OUTPUT_CODE = "all";
+string const VECTOR_ALL_RIVER_FLOOD_OUTPUT_CODE = "all";
+string const VECTOR_AVG_WAVE_ANGLE_AND_HEIGHT_CODE = "avg_wave_angle";
+string const VECTOR_AVG_WAVE_ANGLE_AND_HEIGHT_NAME = "avg_wave_angle";
+string const VECTOR_BREAKING_WAVE_HEIGHT_CODE = "breaking_wave_height";
+string const VECTOR_BREAKING_WAVE_HEIGHT_NAME = "breaking_wave_height";
+string const VECTOR_CLIFF_EDGE_CODE = "cliff_edge";
+string const VECTOR_CLIFF_EDGE_NAME = "cliff_edge";
+string const VECTOR_CLIFF_NOTCH_ACTIVE_CODE = "cliff_notch_active";
+string const VECTOR_CLIFF_NOTCH_ACTIVE_NAME = "cliff_notch_active";
+string const VECTOR_COAST_CODE = "coast";
+string const VECTOR_COAST_CURVATURE_CODE = "coast_curvature";
+string const VECTOR_COAST_CURVATURE_NAME = "coast_curvature";
+string const VECTOR_COAST_NAME = "coast";
+string const VECTOR_COAST_SWL_HIGHEST_NAME = "coast_SWL_highest";
+string const VECTOR_COAST_SWL_LOWEST_NAME = "coast_SWL_lowest";
+string const VECTOR_DEEP_WATER_WAVE_ANGLE_AND_HEIGHT_CODE = "deep_water_wave_angle";
+string const VECTOR_DEEP_WATER_WAVE_ANGLE_AND_HEIGHT_NAME = "deep_water_wave_angle";
+string const VECTOR_DOWNDRIFT_ZONE_BOUNDARY_CODE = "downdrift_boundary";
+string const VECTOR_DOWNDRIFT_ZONE_BOUNDARY_NAME = "downdrift_boundary";
+string const VECTOR_FLOOD_LINE_CODE = "flood_line";
+string const VECTOR_FLOOD_LINE_NAME = "flood_line";
+string const VECTOR_FLOOD_SWL_SETUP_LINE_CODE = "setup";
+string const VECTOR_FLOOD_SWL_SETUP_LINE_NAME = "setup";
+string const VECTOR_FLOOD_SWL_SETUP_SURGE_LINE_CODE = "setup_surge";
+string const VECTOR_FLOOD_SWL_SETUP_SURGE_LINE_NAME = "setup_surge";
+string const VECTOR_FLOOD_SWL_SETUP_SURGE_RUNUP_LINE_CODE = "setup_surge_runup";
+string const VECTOR_FLOOD_SWL_SETUP_SURGE_RUNUP_LINE_NAME = "setup_surge_runup";
+string const VECTOR_INVALID_NORMALS_CODE = "invalid_normals";
+string const VECTOR_INVALID_NORMALS_NAME = "invalid_normals";
+string const VECTOR_MEAN_WAVE_ENERGY_CODE = "mean_wave_energy";
+string const VECTOR_MEAN_WAVE_ENERGY_NAME = "mean_wave_energy";
+string const VECTOR_NORMALS_CODE = "normals";
+string const VECTOR_NORMALS_NAME = "normals";
+string const VECTOR_POLYGON_BOUNDARY_CODE = "polygon";
+string const VECTOR_POLYGON_BOUNDARY_NAME = "polygon";
+string const VECTOR_POLYGON_NODE_CODE = "polygon_node";
+string const VECTOR_POLYGON_NODE_NAME = "polygon_node";
+string const VECTOR_RUN_UP_CODE = "run_up";
+string const VECTOR_RUN_UP_NAME = "run_up";
+string const VECTOR_SHADOW_ZONE_BOUNDARY_CODE = "shadow_boundary";
+string const VECTOR_SHADOW_ZONE_BOUNDARY_NAME = "shadow_boundary";
+string const VECTOR_STORM_SURGE_CODE = "storm_surge";
+string const VECTOR_STORM_SURGE_NAME = "storm_surge";
+string const VECTOR_USUAL_OUTPUT_CODE = "usual";
+string const VECTOR_WAVE_ANGLE_AND_HEIGHT_CODE = "wave_angle";
+string const VECTOR_WAVE_ANGLE_AND_HEIGHT_NAME = "wave_angle";
+string const VECTOR_WAVE_ENERGY_SINCE_COLLAPSE_CODE = "wave_energy";
+string const VECTOR_WAVE_ENERGY_SINCE_COLLAPSE_NAME = "wave_energy";
+string const VECTOR_WAVE_SETUP_CODE = "wave_setup";
+string const VECTOR_WAVE_SETUP_NAME = "wave_setup";
+string const VECTOR_WAVE_TRANSECT_POINTS_CODE = "wave_transect_points";
+string const VECTOR_WAVE_TRANSECT_POINTS_NAME = "wave_transect_points";
+
+// GIS vector output titles
+string const VECTOR_PLOT_AVG_WAVE_ANGLE_AND_HEIGHT_TITLE = "Average wave orientation and height";
+string const VECTOR_PLOT_BREAKING_WAVE_HEIGHT_TITLE = "Breaking wave height";
+string const VECTOR_PLOT_CLIFF_EDGE_TITLE = "Cliff edge";
+string const VECTOR_PLOT_CLIFF_NOTCH_ACTIVE_TITLE = "Active cliff notch incision";
+string const VECTOR_PLOT_COAST_CURVATURE_TITLE = "Coastline curvature";
+string const VECTOR_PLOT_COAST_SWL_HIGHEST_TITLE = "Coastline at highest SWL";
+string const VECTOR_PLOT_COAST_SWL_LOWEST_TITLE = "Coastline at lowest SWL";
+string const VECTOR_PLOT_COAST_TITLE = "Coastline";
+string const VECTOR_PLOT_DEEP_WATER_WAVE_ANGLE_AND_HEIGHT_TITLE = "Deep water wave orientation and height";
+string const VECTOR_PLOT_DOWNDRIFT_ZONE_BOUNDARY_TITLE = "Downdrift zone boundary";
+string const VECTOR_PLOT_FLOOD_LINE_TITLE = "Flood ";
+string const VECTOR_PLOT_FLOOD_SWL_SETUP_LINE_TITLE = "SWL-Setup line";
+string const VECTOR_PLOT_FLOOD_SWL_SETUP_SURGE_LINE_TITLE = "SWL-Setup-Surge line";
+string const VECTOR_PLOT_FLOOD_SWL_SETUP_SURGE_RUNUP_LINE_TITLE = "SWL-Setup-Surge-Runup line";
+string const VECTOR_PLOT_INVALID_NORMALS_TITLE = "INVALID coastline-normal profiles";
+string const VECTOR_PLOT_MEAN_WAVE_ENERGY_TITLE = "Mean wave energy";
+string const VECTOR_PLOT_NORMALS_TITLE = "Coastline-normal profiles";
+string const VECTOR_PLOT_POLYGON_BOUNDARY_TITLE = "Polygons";
+string const VECTOR_PLOT_POLYGON_NODES_TITLE = "Polygon nodes";
+string const VECTOR_PLOT_RUN_UP_TITLE = "Run up";
+string const VECTOR_PLOT_SHADOW_ZONE_BOUNDARY_TITLE = "Shadow zone boundary";
+string const VECTOR_PLOT_STORM_SURGE_TITLE = "Storm surge";
+string const VECTOR_PLOT_WAVE_ANGLE_AND_HEIGHT_TITLE = "Wave orientation and height";
+string const VECTOR_PLOT_WAVE_ENERGY_SINCE_COLLAPSE_TITLE = "Wave energy since collapse";
+string const VECTOR_PLOT_WAVE_SETUP_TITLE = "Wave setup";
+string const VECTOR_PLOT_WAVE_TRANSECT_POINTS_TITLE = "Wave transect points (real and synthetic)";
+
+// Time series codes
+string const TIME_SERIES_BEACH_CHANGE_NET_CODE = "beach_change_net";
+string const TIME_SERIES_BEACH_CHANGE_NET_NAME = "beach_change_net";
+string const TIME_SERIES_BEACH_DEPOSITION_CODE = "beach_deposition";
+string const TIME_SERIES_BEACH_DEPOSITION_NAME = "beach_deposition";
+string const TIME_SERIES_BEACH_EROSION_CODE = "beach_erosion";
+string const TIME_SERIES_BEACH_EROSION_NAME = "beach_erosion";
+string const TIME_SERIES_CLIFF_COLLAPSE_DEPOSITION_CODE = "cliff_collapse_deposition";
+string const TIME_SERIES_CLIFF_COLLAPSE_DEPOSITION_NAME = "cliff_collapse_deposition";
+string const TIME_SERIES_CLIFF_COLLAPSE_EROSION_CODE = "cliff_collapse_erosion";
+string const TIME_SERIES_CLIFF_COLLAPSE_EROSION_NAME = "cliff_collapse_erosion";
+string const TIME_SERIES_CLIFF_COLLAPSE_NET_CODE = "cliff_collapse_net";
+string const TIME_SERIES_CLIFF_COLLAPSE_NET_NAME = "cliff_collapse_net";
+string const TIME_SERIES_CLIFF_NOTCH_ELEV_CODE = "cliff_notch";
+string const TIME_SERIES_CLIFF_NOTCH_ELEV_NAME = "cliff_notch";
+string const TIME_SERIES_FLOOD_SETUP_SURGE_CODE = "flood_setup_surge";
+string const TIME_SERIES_FLOOD_SETUP_SURGE_NAME = "flood_setup_surge";
+string const TIME_SERIES_FLOOD_SETUP_SURGE_RUNUP_CODE = "flood_setup_surge_runup";
+string const TIME_SERIES_FLOOD_SETUP_SURGE_RUNUP_NAME = "flood_setup_surge_runup";
+string const TIME_SERIES_PLATFORM_EROSION_CODE = "platform_erosion";
+string const TIME_SERIES_PLATFORM_EROSION_NAME = "platform_erosion";
+string const TIME_SERIES_SEA_AREA_CODE = "sea_area";
+string const TIME_SERIES_SEA_AREA_NAME = "sea_area";
+string const TIME_SERIES_SUSPENDED_SEDIMENT_CODE = "suspended";
+string const TIME_SERIES_SUSPENDED_SEDIMENT_NAME = "suspended_sediment";
+string const TIME_SERIES_SWL_CODE = "SWL";
+string const TIME_SERIES_SWL_NAME = "SWL";
+
+// CShore stuff
+string const WAVE_ENERGY_FLUX = "wave_energy_flux";
+string const WAVE_HEIGHT_X_FILENAME = "wave_height_x.csv";
+string const WAVE_HEIGHT_Y_FILENAME = "wave_height_y.csv";
+string const ACTIVE_ZONE_FILENAME = "activezone.csv";
+
+//================================================ Globally-available functions =================================================
+template
+T tMax(T a, T b)
+{
+ return ((a > b) ? a : b);
+}
+
+template
+T tMax(T a, T b, T c)
+{
+ T max = (a < b) ? b : a;
+ return ((max < c) ? c : max);
+}
+
+template
+T tMin(T a, T b)
+{
+ return ((a < b) ? a : b);
+}
+
+template
+T tMin(T a, T b, T c)
+{
+ return (a < b ? (a < c ? a : c) : (b < c ? b : c));
+}
+
+template
+T tAbs(T a)
+{
+ // From a posting dated 18 Nov 93 by rmartin@rcmcon.com (Robert Martin), archived in cpp_tips
+ return ((a < 0) ? -a : a);
+}
+
+// template
+// bool bIsBetween(T a, T b, T c)
+// {
+// // Assumes b > c
+// return ((a >= b) && (a <= c));
+// }
+
+template
+string strDblToStr(const T &t)
+{
+ // From http://stackoverflow.com/questions/2125880/convert-float-to-stdstring-in-c
+ ostringstream os;
+ os << t;
+ return os.str();
+}
+
+// ==============================================================================================================================
+// For comparison of two floating-point numbers, with a specified accuracy
+// ==============================================================================================================================
+template
+bool bFPIsEqual(const T d1, const T d2, const T dEpsilon)
+{
+ // Since the accuracy of floating-point numbers varies with their magnitude, we must compare them by using an accuracy threshold which is relative to the magnitude of the two numbers being compared. This is a blend of an example from Knuth's 'The Art of Computer Programming. Volume 1. Fundamental Algorithms' and a posting dated 18 Nov 93 by rmartin@rcmcon.com (Robert Martin), archived in cpp_tips
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+
+ if ((0 == d1) && (tAbs(d2) < dEpsilon))
+ return true;
+ else if ((0 == d2) && (tAbs(d1) < dEpsilon))
+ return true;
+ else
+ return ((tAbs(d1 - d2) < (dEpsilon * tAbs(d1))) ? true : false);
+
+#pragma GCC diagnostic pop
+}
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+// Definitions are in utilsglobal.cpp
+double dRound(double const);
+int nRound(double const);
+// bool bIsWhole(double const);
+bool bIsStringValidDouble(string &);
+bool bIsStringValidInt(string &);
+
+struct FillToWidth
+{
+ FillToWidth(char f, int w) : chFill(f), nWidth(w) {}
+ char chFill;
+ int nWidth;
+};
+
+//! Struct to hold wave data for a single transect/profile
+struct TransectWaveData
+{
+ std::vector VdX;
+ std::vector VdY;
+ std::vector VdHeightX;
+ std::vector VdHeightY;
+ std::vector VbBreaking;
+ int nCoastID;
+ int nProfileID;
+ bool bIsGridEdge;
+};
+
+ostream &operator<<(ostream &, const FillToWidth &);
+
+// string strDbl(double const, int const);
+string strDblRight(double const, int const, int const, bool const = true);
+string strIntRight(int const, int const);
+string strCentre(const char *, int const);
+string strCentre(const string &, int const);
+string strRight(const string &, int const);
+string strRight(const char *, int const);
+string strLeft(const string &, int const);
+string strLeft(const char *, int const);
+string strRightPerCent(double const, double const, int const, int const,
+ bool const = true);
+#endif
+
+//================================================= debugging stuff =============================================================
+// #define CLOCKCHECK // Uncomment to check CPU clock rollover settings
+
+#endif // CME_H
diff --git a/src/configuration.cpp b/src/configuration.cpp
index 219f5c76c..01b60b775 100644
--- a/src/configuration.cpp
+++ b/src/configuration.cpp
@@ -1,458 +1,458 @@
-/*!
-
- \file configuration.cpp
- \brief Implementation of unified configuration class for CoastalME
- \details Provides default values and initialization for simulation parameters
- \author David Favis-Mortlock
- \author Andres Payo
- \date 2025
- \copyright GNU General Public License
-
-*/
-
-/* ==============================================================================================================================
-
- This file is part of CoastalME, the Coastal Modelling Environment.
-
- 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.
-
- 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.
-
- 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.
-
-==============================================================================================================================*/
-#include "cme.h"
-#include "configuration.h"
-// #include "simulation.h"
-#include
-#include
-#include
-
-//===============================================================================================================================
-//! Constructor
-//===============================================================================================================================
-CConfiguration::CConfiguration()
-{
- InitializeDefaults();
-}
-
-//===============================================================================================================================
-//! Destructor
-//===============================================================================================================================
-CConfiguration::~CConfiguration()
-{
-}
-
-//===============================================================================================================================
-//! Initialize all parameters with default values
-//===============================================================================================================================
-void CConfiguration::InitializeDefaults()
-{
- // Run Information
- m_strRunName = "cme";
- m_nLogFileDetail = 1;
- m_bCSVPerTimestepResults = true;
-
- // Simulation timing
- m_strStartDateTime = "00-00-00 01/01/2000";
- m_strDuration = "1 hour";
- m_strTimestep = "1 hour";
- m_vecSaveTimes.clear();
- m_nRandomSeed = 0;
- m_bUseSystemTimeForSeed = true;
-
- // GIS Output
- m_nMaxSaveDigits = 3;
- m_strSaveDigitsMode = "sequential";
- m_vecRasterFiles.clear();
- m_vecRasterFiles.push_back("");
- m_strRasterFormat = "";
- m_bWorldFile = false;
- m_bScaleValues = false;
- m_vecSliceElevations.clear();
- m_vecVectorFiles.clear();
- m_vecVectorFiles.push_back("");
- m_strVectorFormat = "ESRI Shapefile";
- m_vecTimeSeriesFiles.clear();
- m_vecTimeSeriesFiles.push_back("");
-
- // Grid and Coastline
- m_nCoastlineSmoothing = 0;
- m_nCoastlineSmoothingWindow = 7;
- m_nPolynomialOrder = 4;
- m_strOmitGridEdges = "";
- m_nProfileSmoothingWindow = 0;
- m_dMaxLocalSlope = 1.0;
- m_dMaxBeachElevation = 10.0;
-
- // Layers and Files
- m_nNumLayers = 1;
- m_strBasementDEMFile = "";
- m_vecUnconsFineFiles.clear();
- m_vecUnconsSandFiles.clear();
- m_vecUnconsCoarseFiles.clear();
- m_vecConsFineFiles.clear();
- m_vecConsSandFiles.clear();
- m_vecConsCoarseFiles.clear();
- m_strSuspendedSedFile = "";
- m_strLandformFile = "";
- m_strInterventionClassFile = "";
- m_strInterventionHeightFile = "";
-
- // Hydrology
- m_nWavePropagationModel = 1; // CShore
- m_dSeawaterDensity = 1029.0;
- m_dInitialWaterLevel = 0.0;
- // m_dFinalWaterLevel = 0.0;
- m_bHasFinalWaterLevel = false;
-
- m_strWaveHeightTimeSeries = "";
- m_strWaveStationDataFile = "";
- m_dDeepWaterWaveHeight = 1.0;
- m_dDeepWaterWaveOrientation = 270.0;
- m_dWavePeriod = 10.0;
-
- m_strTideDataFile = "";
- m_dBreakingWaveRatio = 0.8;
-
- // Sediment and Erosion
- m_bCoastPlatformErosion = true;
- m_dPlatformErosionResistance = 2e6;
- m_bBeachSedimentTransport = true;
- m_nBeachTransportAtEdges = 1; // open
- m_nBeachErosionEquation = 0; // CERC
- m_dFineMedianSize = 0.0;
- m_dSandMedianSize = 0.0;
- m_dCoarseMedianSize = 0.0;
- m_dSedimentDensity = 2650.0;
- m_dBeachSedimentPorosity = 0.4;
- m_dFineErosivity = 1.0;
- m_dSandErosivity = 0.7;
- m_dCoarseErosivity = 0.3;
- m_dTransportKLS = 0.4;
- m_dKamphuis = 5.0;
- m_dBermHeight = 0.25;
-
- // Cliff parameters
- m_bCliffCollapse = true;
- m_dCliffErosionResistance = 2.5e8;
- m_dNotchOverhang = 0.5;
- m_dNotchBase = 0.3;
- m_dCliffDepositionA = 0.0;
- m_dTalusWidth = 15.0;
- m_dMinTalusLength = 10.0;
- m_dMinTalusHeight = 0.5;
-
- // Flood parameters
- m_bFloodInput = false;
- m_strFloodCoastline = "";
- m_strRunupEquation = 0;
- m_strFloodLocations = "";
- m_strFloodInputLocation = "";
-
- // Sediment input parameters
- m_bSedimentInput = false;
- m_strSedimentInputLocation = "";
- m_strSedimentInputType = "";
- m_strSedimentInputDetails = "";
-
- // Physics and Geometry
- m_dGravitationalAcceleration = 9.81;
- m_dNormalSpacing = 0.0;
- m_dRandomFactor = 0.25;
- m_dNormalLength = 130.0;
- m_dStartDepthRatio = 30.0;
- m_dSyntheticTransectSpacing = 5.0;
-
- // Profile and Output Options
- m_bSaveProfileData = false;
- m_vecProfileNumbers.clear();
- m_vecProfileTimesteps.clear();
- m_bSaveParallelProfiles = false;
- m_bOutputErosionPotential = false;
- m_nCurvatureWindow = 11;
-
- // Cliff Edge Processing
- m_nCliffEdgeSmoothing = 1;
- m_nCliffEdgeSmoothingWindow = 33;
- m_nCliffEdgePolynomialOrder = 4;
- m_dCliffSlopeLimit = 0.3;
-}
-
-//===============================================================================================================================
-//! Get raster files with keyword expansion support
-//===============================================================================================================================
-vector CConfiguration::GetRasterFiles() const
-{
- // Case 11: Raster GIS files to output - expand "all" and "usual" keywords
- vector expandedFiles;
-
- for (string const &fileSpec : m_vecRasterFiles)
- {
- string fileSpecLower = fileSpec;
- std::transform(fileSpecLower.begin(), fileSpecLower.end(),
- fileSpecLower.begin(), ::tolower);
-
- if (fileSpecLower == "all")
- {
- // Add all possible raster outputs (Case 11 "all" mode)
- expandedFiles.insert(expandedFiles.end(),
- {"suspended_sediment",
- "avg_suspended_sediment",
- "fine_uncons",
- "fine_cons",
- "sand_uncons",
- "sand_cons",
- "coarse_uncons",
- "coarse_cons",
- "sediment_top_elevation",
- "top_elevation",
- "sea_depth",
- "wave_height",
- "wave_orientation",
- "wave_period",
- "potential_platform_erosion",
- "actual_platform_erosion",
- "total_potential_platform_erosion",
- "total_actual_platform_erosion",
- "potential_beach_erosion",
- "actual_beach_erosion",
- "total_potential_beach_erosion",
- "total_actual_beach_erosion",
- "beach_deposition",
- "total_beach_deposition",
- "landform",
- "local_cons_sediment_slope",
- "slope",
- "cliff",
- "avg_sea_depth",
- "avg_wave_height",
- "avg_wave_orientation",
- "beach_protection",
- "basement_elevation",
- "coastline",
- "coast_normal",
- "active_zone",
- "cliff_collapse",
- "total_cliff_collapse",
- "cliff_collapse_deposition",
- "total_cliff_collapse_deposition",
- "polygon",
- "potential_platform_erosion_mask",
- "sea_mask",
- "beach_mask",
- "shadow_zone_codes",
- "deep_water_wave_angle",
- "deep_water_wave_height",
- "deep_water_wave_period",
- "polygon_uncons_sediment_up_or_down_drift",
- "polygon_uncons_sediment_gain_or_loss"});
- }
- else if (fileSpecLower == "usual")
- {
- // Add usual/standard raster outputs (Case 11 "usual" mode)
- expandedFiles.insert(expandedFiles.end(),
- {"suspended_sediment",
- "avg_suspended_sediment",
- "fine_uncons",
- "fine_cons",
- "sand_uncons",
- "sand_cons",
- "coarse_uncons",
- "coarse_cons",
- "sediment_top_elevation",
- "top_elevation",
- "sea_depth",
- "wave_height",
- "wave_orientation",
- "potential_platform_erosion",
- "actual_platform_erosion",
- "total_potential_platform_erosion",
- "total_actual_platform_erosion",
- "potential_beach_erosion",
- "actual_beach_erosion",
- "total_potential_beach_erosion",
- "total_actual_beach_erosion",
- "beach_deposition",
- "total_beach_deposition",
- "landform",
- "local_cons_sediment_slope",
- "slope",
- "avg_wave_height",
- "avg_wave_orientation",
- "beach_protection",
- "basement_elevation",
- "active_zone",
- "cliff_collapse",
- "total_cliff_collapse",
- "cliff_collapse_deposition",
- "total_cliff_collapse_deposition",
- "polygon",
- "shadow_zone_codes",
- "polygon_uncons_sediment_up_or_down_drift",
- "polygon_uncons_sediment_gain_or_loss",
- "coast_normal",
- "coastline",
- "fine_uncons",
- "fine_cons",
- "sand_uncons",
- "sand_cons",
- "coarse_uncons",
- "coarse_cons"});
- }
- else if (fileSpecLower == "cmetools")
- {
- // Add usual/standard raster outputs (Case 11 "usual" mode)
- expandedFiles.insert(expandedFiles.end(),
- {"fine_uncons",
- "fine_cons",
- "sand_uncons",
- "sand_cons",
- "coarse_uncons",
- "coarse_cons",
- "top_elevation",
- "sea_depth",
- "wave_height",
- "total_actual_platform_erosion",
- "total_actual_beach_erosion",
- "total_beach_deposition",
- "landform",
- "basement_elevation",
- "active_zone",
- "cliff_collapse",
- "total_cliff_collapse",
- "cliff_collapse_deposition",
- "total_cliff_collapse_deposition",
- "polygon",
- "coast_normal",
- "coastline"});
- }
- else if (fileSpecLower == "" or fileSpecLower == "none")
- {
- return expandedFiles;
- }
- else
- {
- // Regular file specification - add as-is
- expandedFiles.push_back(fileSpec);
- }
- }
-
- return expandedFiles;
-}
-
-//===============================================================================================================================
-//! Get vector files with keyword expansion support
-//===============================================================================================================================
-vector CConfiguration::GetVectorFiles() const
-{
- // Case 16: Vector GIS files to output - expand "all" and "usual" keywords
- vector expandedFiles;
-
- for (string const &fileSpec : m_vecVectorFiles)
- {
- string fileSpecLower = fileSpec;
- std::transform(fileSpecLower.begin(), fileSpecLower.end(),
- fileSpecLower.begin(), ::tolower);
-
- if (fileSpecLower == "all")
- {
- // Add all possible vector outputs (Case 16 "all" mode)
- expandedFiles.insert(expandedFiles.end(), {"coast", "cliff_edge", "wave_angle", "normals", "invalid_normals", "avg_wave_angle", "wave_energy", "mean_wave_energy", "breaking_wave_height", "coast_curvature", "polygon_node", "polygon", "cliff_notch", "wave_transect_points", "shadow_boundary", "downdrift_boundary", "deep_water_wave_angle", "wave_setup", "storm_surge", "run_up", "flood_line"});
- }
- else if (fileSpecLower == "usual")
- {
- // Add usual/standard vector outputs (Case 16 "usual" mode)
- expandedFiles.insert(
- expandedFiles.end(),
- {"coast", "cliff_edge", "wave_angle", "normals", "invalid_normals",
- "avg_wave_angle", "wave_energy", "mean_wave_energy",
- "breaking_wave_height", "polygon", "cliff_notch",
- "shadow_boundary", "downdrift_boundary", "deep_water_wave_angle"});
- }
- else if (fileSpecLower == "" or fileSpecLower == "none")
- {
- return expandedFiles;
- }
- else
- {
- // Regular file specification - add as-is
- expandedFiles.push_back(fileSpec);
- }
- }
-
- return expandedFiles;
-}
-//===============================================================================================================================
-
-//! Get time series files with keyword expansion support
-//===============================================================================================================================
-vector CConfiguration::GetTimeSeriesFiles() const
-{
- // Case 18: Timeseries files to output - expand "all" and "usual" keywords
- vector expandedFiles;
-
- for (string const &fileSpec : m_vecVectorFiles)
- {
- string fileSpecLower = fileSpec;
- std::transform(fileSpecLower.begin(), fileSpecLower.end(),
- fileSpecLower.begin(), ::tolower);
-
- if (fileSpecLower == "all")
- {
- // Add all possible vector outputs (Case 16 "all" mode)
- expandedFiles.insert(expandedFiles.end(), {"wave_setup", "wave_runup", "beach_change_net", "beach_deposition", "beach_erosion", "cliff_collapse_deposition", "cliff_collapse_erosion", "cliff_collapse_net", "platform_erosion", "sea_area", "suspended", "water_level"});
- }
- else if (fileSpecLower == "" or fileSpecLower == "none")
- {
- return expandedFiles;
- }
- else
- {
- // Regular file specification - add as-is
- expandedFiles.push_back(fileSpec);
- }
- }
-
- return expandedFiles;
-}
-
-//! Get time series files with keyword expansion support
-//===============================================================================================================================
-vector CConfiguration::GetFloodFiles() const
-{
- // Case 18: Timeseries files to output - expand "all" and "usual" keywords
- vector expandedFiles;
-
- for (string const &fileSpec : m_vecVectorFiles)
- {
- string fileSpecLower = fileSpec;
- std::transform(fileSpecLower.begin(), fileSpecLower.end(),
- fileSpecLower.begin(), ::tolower);
-
- if (fileSpecLower == "all")
- {
- // Add all possible vector outputs (Case 16 "all" mode)
- expandedFiles.insert(expandedFiles.end(), {});
- }
- else if (fileSpecLower == "" or fileSpecLower == "none")
- {
- return expandedFiles;
- }
- else
- {
- // Regular file specification - add as-is
- expandedFiles.push_back(fileSpec);
- }
- }
-
- return expandedFiles;
-}
-
-string CConfiguration::GetOmitGridEdges() const
-{
- // This needs to be lower case
- std::string my_text{m_strOmitGridEdges};
- std::transform(my_text.begin(), my_text.end(), my_text.begin(), ::tolower);
- return my_text;
-}
+/*!
+
+ \file configuration.cpp
+ \brief Implementation of unified configuration class for CoastalME
+ \details Provides default values and initialization for simulation parameters
+ \author David Favis-Mortlock
+ \author Andres Payo
+ \date 2025
+ \copyright GNU General Public License
+
+*/
+
+/* ==============================================================================================================================
+
+ This file is part of CoastalME, the Coastal Modelling Environment.
+
+ 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.
+
+ 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.
+
+ 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.
+
+==============================================================================================================================*/
+#include "cme.h"
+#include "configuration.h"
+// #include "simulation.h"
+#include
+#include
+#include
+
+//===============================================================================================================================
+//! Constructor
+//===============================================================================================================================
+CConfiguration::CConfiguration()
+{
+ InitializeDefaults();
+}
+
+//===============================================================================================================================
+//! Destructor
+//===============================================================================================================================
+CConfiguration::~CConfiguration()
+{
+}
+
+//===============================================================================================================================
+//! Initialize all parameters with default values
+//===============================================================================================================================
+void CConfiguration::InitializeDefaults()
+{
+ // Run Information
+ m_strRunName = "cme";
+ m_nLogFileDetail = 1;
+ m_bCSVPerTimestepResults = true;
+
+ // Simulation timing
+ m_strStartDateTime = "00-00-00 01/01/2000";
+ m_strDuration = "1 hour";
+ m_strTimestep = "1 hour";
+ m_vecSaveTimes.clear();
+ m_nRandomSeed = 0;
+ m_bUseSystemTimeForSeed = true;
+
+ // GIS Output
+ m_nMaxSaveDigits = 3;
+ m_strSaveDigitsMode = "sequential";
+ m_vecRasterFiles.clear();
+ m_vecRasterFiles.push_back("");
+ m_strRasterFormat = "";
+ m_bWorldFile = false;
+ m_bScaleValues = false;
+ m_vecSliceElevations.clear();
+ m_vecVectorFiles.clear();
+ m_vecVectorFiles.push_back("");
+ m_strVectorFormat = "ESRI Shapefile";
+ m_vecTimeSeriesFiles.clear();
+ m_vecTimeSeriesFiles.push_back("");
+
+ // Grid and Coastline
+ m_nCoastlineSmoothing = 0;
+ m_nCoastlineSmoothingWindow = 7;
+ m_nPolynomialOrder = 4;
+ m_strOmitGridEdges = "";
+ m_nProfileSmoothingWindow = 0;
+ m_dMaxLocalSlope = 1.0;
+ m_dMaxBeachElevation = 10.0;
+
+ // Layers and Files
+ m_nNumLayers = 1;
+ m_strBasementDEMFile = "";
+ m_vecUnconsFineFiles.clear();
+ m_vecUnconsSandFiles.clear();
+ m_vecUnconsCoarseFiles.clear();
+ m_vecConsFineFiles.clear();
+ m_vecConsSandFiles.clear();
+ m_vecConsCoarseFiles.clear();
+ m_strSuspendedSedFile = "";
+ m_strLandformFile = "";
+ m_strInterventionClassFile = "";
+ m_strInterventionHeightFile = "";
+
+ // Hydrology
+ m_nWavePropagationModel = 1; // CShore
+ m_dSeawaterDensity = 1029.0;
+ m_dInitialWaterLevel = 0.0;
+ // m_dFinalWaterLevel = 0.0;
+ m_bHasFinalWaterLevel = false;
+
+ m_strWaveHeightTimeSeries = "";
+ m_strWaveStationDataFile = "";
+ m_dDeepWaterWaveHeight = 1.0;
+ m_dDeepWaterWaveOrientation = 270.0;
+ m_dWavePeriod = 10.0;
+
+ m_strTideDataFile = "";
+ m_dBreakingWaveRatio = 0.8;
+
+ // Sediment and Erosion
+ m_bCoastPlatformErosion = true;
+ m_dPlatformErosionResistance = 2e6;
+ m_bBeachSedimentTransport = true;
+ m_nBeachTransportAtEdges = 1; // open
+ m_nBeachErosionEquation = 0; // CERC
+ m_dFineMedianSize = 0.0;
+ m_dSandMedianSize = 0.0;
+ m_dCoarseMedianSize = 0.0;
+ m_dSedimentDensity = 2650.0;
+ m_dBeachSedimentPorosity = 0.4;
+ m_dFineErosivity = 1.0;
+ m_dSandErosivity = 0.7;
+ m_dCoarseErosivity = 0.3;
+ m_dTransportKLS = 0.4;
+ m_dKamphuis = 5.0;
+ m_dBermHeight = 0.25;
+
+ // Cliff parameters
+ m_bCliffCollapse = true;
+ m_dCliffErosionResistance = 2.5e8;
+ m_dNotchOverhang = 0.5;
+ m_dNotchBase = 0.3;
+ m_dCliffDepositionA = 0.0;
+ m_dTalusWidth = 15.0;
+ m_dMinTalusLength = 10.0;
+ m_dMinTalusHeight = 0.5;
+
+ // Flood parameters
+ m_bFloodInput = false;
+ m_strFloodCoastline = "";
+ m_strRunupEquation = 0;
+ m_strFloodLocations = "";
+ m_strFloodInputLocation = "";
+
+ // Sediment input parameters
+ m_bSedimentInput = false;
+ m_strSedimentInputLocation = "";
+ m_strSedimentInputType = "";
+ m_strSedimentInputDetails = "";
+
+ // Physics and Geometry
+ m_dGravitationalAcceleration = 9.81;
+ m_dNormalSpacing = 0.0;
+ m_dRandomFactor = 0.25;
+ m_dNormalLength = 130.0;
+ m_dStartDepthRatio = 30.0;
+ m_dSyntheticTransectSpacing = 5.0;
+
+ // Profile and Output Options
+ m_bSaveProfileData = false;
+ m_vecProfileNumbers.clear();
+ m_vecProfileTimesteps.clear();
+ m_bSaveParallelProfiles = false;
+ m_bOutputErosionPotential = false;
+ m_nCurvatureWindow = 11;
+
+ // Cliff Edge Processing
+ m_nCliffEdgeSmoothing = 1;
+ m_nCliffEdgeSmoothingWindow = 33;
+ m_nCliffEdgePolynomialOrder = 4;
+ m_dCliffSlopeLimit = 0.3;
+}
+
+//===============================================================================================================================
+//! Get raster files with keyword expansion support
+//===============================================================================================================================
+vector CConfiguration::GetRasterFiles() const
+{
+ // Case 11: Raster GIS files to output - expand "all" and "usual" keywords
+ vector expandedFiles;
+
+ for (string const &fileSpec : m_vecRasterFiles)
+ {
+ string fileSpecLower = fileSpec;
+ std::transform(fileSpecLower.begin(), fileSpecLower.end(),
+ fileSpecLower.begin(), ::tolower);
+
+ if (fileSpecLower == "all")
+ {
+ // Add all possible raster outputs (Case 11 "all" mode)
+ expandedFiles.insert(expandedFiles.end(),
+ {"suspended_sediment",
+ "avg_suspended_sediment",
+ "fine_uncons",
+ "fine_cons",
+ "sand_uncons",
+ "sand_cons",
+ "coarse_uncons",
+ "coarse_cons",
+ "sediment_top_elevation",
+ "top_elevation",
+ "sea_depth",
+ "wave_height",
+ "wave_orientation",
+ "wave_period",
+ "potential_platform_erosion",
+ "actual_platform_erosion",
+ "total_potential_platform_erosion",
+ "total_actual_platform_erosion",
+ "potential_beach_erosion",
+ "actual_beach_erosion",
+ "total_potential_beach_erosion",
+ "total_actual_beach_erosion",
+ "beach_deposition",
+ "total_beach_deposition",
+ "landform",
+ "local_cons_sediment_slope",
+ "slope",
+ "cliff",
+ "avg_sea_depth",
+ "avg_wave_height",
+ "avg_wave_orientation",
+ "beach_protection",
+ "basement_elevation",
+ "coastline",
+ "coast_normal",
+ "active_zone",
+ "cliff_collapse",
+ "total_cliff_collapse",
+ "cliff_collapse_deposition",
+ "total_cliff_collapse_deposition",
+ "polygon",
+ "potential_platform_erosion_mask",
+ "sea_mask",
+ "beach_mask",
+ "shadow_zone_codes",
+ "deep_water_wave_angle",
+ "deep_water_wave_height",
+ "deep_water_wave_period",
+ "polygon_uncons_sediment_up_or_down_drift",
+ "polygon_uncons_sediment_gain_or_loss"});
+ }
+ else if (fileSpecLower == "usual")
+ {
+ // Add usual/standard raster outputs (Case 11 "usual" mode)
+ expandedFiles.insert(expandedFiles.end(),
+ {"suspended_sediment",
+ "avg_suspended_sediment",
+ "fine_uncons",
+ "fine_cons",
+ "sand_uncons",
+ "sand_cons",
+ "coarse_uncons",
+ "coarse_cons",
+ "sediment_top_elevation",
+ "top_elevation",
+ "sea_depth",
+ "wave_height",
+ "wave_orientation",
+ "potential_platform_erosion",
+ "actual_platform_erosion",
+ "total_potential_platform_erosion",
+ "total_actual_platform_erosion",
+ "potential_beach_erosion",
+ "actual_beach_erosion",
+ "total_potential_beach_erosion",
+ "total_actual_beach_erosion",
+ "beach_deposition",
+ "total_beach_deposition",
+ "landform",
+ "local_cons_sediment_slope",
+ "slope",
+ "avg_wave_height",
+ "avg_wave_orientation",
+ "beach_protection",
+ "basement_elevation",
+ "active_zone",
+ "cliff_collapse",
+ "total_cliff_collapse",
+ "cliff_collapse_deposition",
+ "total_cliff_collapse_deposition",
+ "polygon",
+ "shadow_zone_codes",
+ "polygon_uncons_sediment_up_or_down_drift",
+ "polygon_uncons_sediment_gain_or_loss",
+ "coast_normal",
+ "coastline",
+ "fine_uncons",
+ "fine_cons",
+ "sand_uncons",
+ "sand_cons",
+ "coarse_uncons",
+ "coarse_cons"});
+ }
+ else if (fileSpecLower == "cmetools")
+ {
+ // Add usual/standard raster outputs (Case 11 "usual" mode)
+ expandedFiles.insert(expandedFiles.end(),
+ {"fine_uncons",
+ "fine_cons",
+ "sand_uncons",
+ "sand_cons",
+ "coarse_uncons",
+ "coarse_cons",
+ "top_elevation",
+ "sea_depth",
+ "wave_height",
+ "total_actual_platform_erosion",
+ "total_actual_beach_erosion",
+ "total_beach_deposition",
+ "landform",
+ "basement_elevation",
+ "active_zone",
+ "cliff_collapse",
+ "total_cliff_collapse",
+ "cliff_collapse_deposition",
+ "total_cliff_collapse_deposition",
+ "polygon",
+ "coast_normal",
+ "coastline"});
+ }
+ else if (fileSpecLower == "" or fileSpecLower == "none")
+ {
+ return expandedFiles;
+ }
+ else
+ {
+ // Regular file specification - add as-is
+ expandedFiles.push_back(fileSpec);
+ }
+ }
+
+ return expandedFiles;
+}
+
+//===============================================================================================================================
+//! Get vector files with keyword expansion support
+//===============================================================================================================================
+vector CConfiguration::GetVectorFiles() const
+{
+ // Case 16: Vector GIS files to output - expand "all" and "usual" keywords
+ vector expandedFiles;
+
+ for (string const &fileSpec : m_vecVectorFiles)
+ {
+ string fileSpecLower = fileSpec;
+ std::transform(fileSpecLower.begin(), fileSpecLower.end(),
+ fileSpecLower.begin(), ::tolower);
+
+ if (fileSpecLower == "all")
+ {
+ // Add all possible vector outputs (Case 16 "all" mode)
+ expandedFiles.insert(expandedFiles.end(), {"coast", "cliff_edge", "wave_angle", "normals", "invalid_normals", "avg_wave_angle", "wave_energy", "mean_wave_energy", "breaking_wave_height", "coast_curvature", "polygon_node", "polygon", "cliff_notch", "wave_transect_points", "shadow_boundary", "downdrift_boundary", "deep_water_wave_angle", "wave_setup", "storm_surge", "run_up", "flood_line"});
+ }
+ else if (fileSpecLower == "usual")
+ {
+ // Add usual/standard vector outputs (Case 16 "usual" mode)
+ expandedFiles.insert(
+ expandedFiles.end(),
+ {"coast", "cliff_edge", "wave_angle", "normals", "invalid_normals",
+ "avg_wave_angle", "wave_energy", "mean_wave_energy",
+ "breaking_wave_height", "polygon", "cliff_notch",
+ "shadow_boundary", "downdrift_boundary", "deep_water_wave_angle"});
+ }
+ else if (fileSpecLower == "" or fileSpecLower == "none")
+ {
+ return expandedFiles;
+ }
+ else
+ {
+ // Regular file specification - add as-is
+ expandedFiles.push_back(fileSpec);
+ }
+ }
+
+ return expandedFiles;
+}
+//===============================================================================================================================
+
+//! Get time series files with keyword expansion support
+//===============================================================================================================================
+vector CConfiguration::GetTimeSeriesFiles() const
+{
+ // Case 18: Timeseries files to output - expand "all" and "usual" keywords
+ vector expandedFiles;
+
+ for (string const &fileSpec : m_vecVectorFiles)
+ {
+ string fileSpecLower = fileSpec;
+ std::transform(fileSpecLower.begin(), fileSpecLower.end(),
+ fileSpecLower.begin(), ::tolower);
+
+ if (fileSpecLower == "all")
+ {
+ // Add all possible vector outputs (Case 16 "all" mode)
+ expandedFiles.insert(expandedFiles.end(), {"wave_setup", "wave_runup", "beach_change_net", "beach_deposition", "beach_erosion", "cliff_collapse_deposition", "cliff_collapse_erosion", "cliff_collapse_net", "platform_erosion", "sea_area", "suspended", "water_level"});
+ }
+ else if (fileSpecLower == "" or fileSpecLower == "none")
+ {
+ return expandedFiles;
+ }
+ else
+ {
+ // Regular file specification - add as-is
+ expandedFiles.push_back(fileSpec);
+ }
+ }
+
+ return expandedFiles;
+}
+
+//! Get time series files with keyword expansion support
+//===============================================================================================================================
+vector CConfiguration::GetFloodFiles() const
+{
+ // Case 18: Timeseries files to output - expand "all" and "usual" keywords
+ vector expandedFiles;
+
+ for (string const &fileSpec : m_vecVectorFiles)
+ {
+ string fileSpecLower = fileSpec;
+ std::transform(fileSpecLower.begin(), fileSpecLower.end(),
+ fileSpecLower.begin(), ::tolower);
+
+ if (fileSpecLower == "all")
+ {
+ // Add all possible vector outputs (Case 16 "all" mode)
+ expandedFiles.insert(expandedFiles.end(), {});
+ }
+ else if (fileSpecLower == "" or fileSpecLower == "none")
+ {
+ return expandedFiles;
+ }
+ else
+ {
+ // Regular file specification - add as-is
+ expandedFiles.push_back(fileSpec);
+ }
+ }
+
+ return expandedFiles;
+}
+
+string CConfiguration::GetOmitGridEdges() const
+{
+ // This needs to be lower case
+ std::string my_text{m_strOmitGridEdges};
+ std::transform(my_text.begin(), my_text.end(), my_text.begin(), ::tolower);
+ return my_text;
+}
diff --git a/src/configuration.h b/src/configuration.h
index e63ad2fed..30469722b 100644
--- a/src/configuration.h
+++ b/src/configuration.h
@@ -1,1013 +1,1013 @@
-/*!
-
- \file configuration.h
- \brief Unified configuration class for CoastalME simulation parameters
- \details Provides a single interface for accessing simulation parameters
- regardless of input format (.dat or YAML)
- \author David Favis-Mortlock
- \author Andres Payo
- \date 2025
- \copyright GNU General Public License
-
-*/
-
-/* ==============================================================================================================================
-
- This file is part of CoastalME, the Coastal Modelling Environment.
-
- 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.
-
- 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.
-
- 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.
-
-==============================================================================================================================*/
-#ifndef CONFIGURATION_H
-#define CONFIGURATION_H
-
-#include
-#include
-#include
-#include
-
-using std::string;
-using std::vector;
-
-//! Unified configuration class for CoastalME simulation parameters
-class CConfiguration
-{
- private:
- // Run Information
- string m_strRunName;
- int m_nLogFileDetail;
- bool m_bCSVPerTimestepResults;
-
- // Simulation timing
- string m_strStartDateTime;
- string m_strDuration;
- string m_strTimestep;
- vector m_vecSaveTimes;
- int m_nRandomSeed;
- bool m_bUseSystemTimeForSeed;
-
- // GIS Output
- int m_nMaxSaveDigits;
- string m_strSaveDigitsMode;
- vector m_vecRasterFiles;
- string m_strRasterFormat;
- bool m_bWorldFile;
- bool m_bScaleValues;
- vector m_vecSliceElevations;
- vector m_vecVectorFiles;
- string m_strVectorFormat;
- vector m_vecTimeSeriesFiles;
-
- // Grid and Coastline
- int m_nCoastlineSmoothing;
- int m_nCoastlineSmoothingWindow;
- int m_nPolynomialOrder;
- string m_strOmitGridEdges;
- int m_nProfileSmoothingWindow;
- double m_dMaxLocalSlope;
- double m_dMaxBeachElevation;
-
- // Layers and Files
- int m_nNumLayers;
- string m_strBasementDEMFile;
- vector m_vecUnconsFineFiles;
- vector m_vecUnconsSandFiles;
- vector m_vecUnconsCoarseFiles;
- vector m_vecConsFineFiles;
- vector m_vecConsSandFiles;
- vector m_vecConsCoarseFiles;
- string m_strSuspendedSedFile;
- string m_strLandformFile;
- string m_strInterventionClassFile;
- string m_strInterventionHeightFile;
-
- // Hydrology
- int m_nWavePropagationModel;
- double m_dSeawaterDensity;
- double m_dInitialWaterLevel;
- double m_dFinalWaterLevel;
- bool m_bHasFinalWaterLevel;
-
- // Waves
- string m_strWaveHeightTimeSeries;
- string m_strWaveStationDataFile;
- double m_dDeepWaterWaveHeight;
- double m_dDeepWaterWaveOrientation;
- double m_dWavePeriod;
-
- // tides
- string m_strTideDataFile;
- double m_dBreakingWaveRatio;
-
- // Sediment and Erosion
- bool m_bCoastPlatformErosion;
- double m_dPlatformErosionResistance;
- bool m_bBeachSedimentTransport;
- int m_nBeachTransportAtEdges;
- int m_nBeachErosionEquation;
- double m_dFineMedianSize;
- double m_dSandMedianSize;
- double m_dCoarseMedianSize;
- double m_dSedimentDensity;
- double m_dBeachSedimentPorosity;
- double m_dFineErosivity;
- double m_dSandErosivity;
- double m_dCoarseErosivity;
- double m_dTransportKLS;
- double m_dKamphuis;
- double m_dBermHeight;
-
- // Cliff parameters
- bool m_bCliffCollapse;
- double m_dCliffErosionResistance;
- double m_dNotchOverhang;
- double m_dNotchBase;
- double m_dCliffDepositionA;
- double m_dTalusWidth;
- double m_dMinTalusLength;
- double m_dMinTalusHeight;
-
- // Flood parameters
- bool m_bFloodInput;
- string m_strFloodCoastline;
- int m_strRunupEquation;
- string m_strFloodLocations;
- string m_strFloodInputLocation;
- vector m_vecFloodFiles;
-
- // Sediment input parameters
- bool m_bSedimentInput;
- string m_strSedimentInputLocation;
- string m_strSedimentInputType;
- string m_strSedimentInputDetails;
-
- // Physics and Geometry
- double m_dGravitationalAcceleration;
- double m_dNormalSpacing;
- double m_dRandomFactor;
- double m_dNormalLength;
- double m_dStartDepthRatio;
- double m_dSyntheticTransectSpacing;
-
- // Profile and Output Options
- bool m_bSaveProfileData;
- vector m_vecProfileNumbers;
- vector m_vecProfileTimesteps;
- bool m_bSaveParallelProfiles;
- bool m_bOutputErosionPotential;
- int m_nCurvatureWindow;
-
- // Cliff Edge Processing
- int m_nCliffEdgeSmoothing;
- int m_nCliffEdgeSmoothingWindow;
- int m_nCliffEdgePolynomialOrder;
- double m_dCliffSlopeLimit;
-
- public:
- CConfiguration();
- ~CConfiguration();
-
- // Setters for all parameters
- void SetRunName(string const &str)
- {
- m_strRunName = str;
- }
- void SetLogFileDetail(int n)
- {
- m_nLogFileDetail = n;
- }
- void SetCSVPerTimestepResults(bool b)
- {
- m_bCSVPerTimestepResults = b;
- }
- void SetStartDateTime(string const &str)
- {
- m_strStartDateTime = str;
- }
- void SetDuration(string const &str)
- {
- m_strDuration = str;
- }
- void SetTimestep(string const &str)
- {
- m_strTimestep = str;
- }
- void SetSaveTimes(vector const &vec)
- {
- m_vecSaveTimes = vec;
- }
- void SetRandomSeed(int n)
- {
- m_nRandomSeed = n;
- m_bUseSystemTimeForSeed = false;
- }
- void UseSystemTimeForSeed()
- {
- m_bUseSystemTimeForSeed = false;
- }
-
- void SetMaxSaveDigits(int n)
- {
- m_nMaxSaveDigits = n;
- }
- void SetSaveDigitsMode(string const &str)
- {
- m_strSaveDigitsMode = str;
- }
- void SetRasterFiles(vector const &vec)
- {
- m_vecRasterFiles = vec;
- }
- void SetRasterFormat(string const &str)
- {
- m_strRasterFormat = str;
- }
- void SetWorldFile(bool b)
- {
- m_bWorldFile = b;
- }
- void SetScaleValues(bool b)
- {
- m_bScaleValues = b;
- }
- void SetSliceElevations(vector const &vec)
- {
- m_vecSliceElevations = vec;
- }
- void SetVectorFiles(vector const &vec)
- {
- m_vecVectorFiles = vec;
- }
- void SetVectorFormat(string const &str)
- {
- m_strVectorFormat = str;
- }
- void SetTimeSeriesFiles(vector const &vec)
- {
- m_vecTimeSeriesFiles = vec;
- }
-
- void SetCoastlineSmoothing(int n)
- {
- m_nCoastlineSmoothing = n;
- }
- void SetCoastlineSmoothingWindow(int n)
- {
- m_nCoastlineSmoothingWindow = n;
- }
- void SetPolynomialOrder(int n)
- {
- m_nPolynomialOrder = n;
- }
- void SetOmitGridEdges(string const &str)
- {
- m_strOmitGridEdges = str;
- }
- void SetProfileSmoothingWindow(int n)
- {
- m_nProfileSmoothingWindow = n;
- }
- void SetMaxLocalSlope(double d)
- {
- m_dMaxLocalSlope = d;
- }
- void SetMaxBeachElevation(double d)
- {
- m_dMaxBeachElevation = d;
- }
- void SetNumLayers(int n)
- {
- m_nNumLayers = n;
- }
- void SetBasementDEMFile(string const &str)
- {
- m_strBasementDEMFile = str;
- }
- void SetUnconsFineFiles(vector const &vec)
- {
- m_vecUnconsFineFiles = vec;
- }
- void SetUnconsSandFiles(vector const &vec)
- {
- m_vecUnconsSandFiles = vec;
- }
- void SetUnconsCoarseFiles(vector const &vec)
- {
- m_vecUnconsCoarseFiles = vec;
- }
- void SetConsFineFiles(vector const &vec)
- {
- m_vecConsFineFiles = vec;
- }
- void SetConsSandFiles(vector const &vec)
- {
- m_vecConsSandFiles = vec;
- }
- void SetConsCoarseFiles(vector const &vec)
- {
- m_vecConsCoarseFiles = vec;
- }
- void SetSuspendedSedFile(string const &str)
- {
- m_strSuspendedSedFile = str;
- }
- void SetLandformFile(string const &str)
- {
- m_strLandformFile = str;
- }
- void SetInterventionClassFile(string const &str)
- {
- m_strInterventionClassFile = str;
- }
- void SetInterventionHeightFile(string const &str)
- {
- m_strInterventionHeightFile = str;
- }
-
- void SetWavePropagationModel(int n)
- {
- m_nWavePropagationModel = n;
- }
- void SetSeawaterDensity(double d)
- {
- m_dSeawaterDensity = d;
- }
- void SetInitialWaterLevel(double d)
- {
- m_dInitialWaterLevel = d;
- }
- void SetFinalWaterLevel(double d)
- {
- m_dFinalWaterLevel = d;
- m_bHasFinalWaterLevel = true;
- }
-
- // Wave height Data
- void SetWaveHeightTimeSeries(string const &str)
- {
- m_strWaveHeightTimeSeries = str;
- }
- void SetWaveStationDataFile(string const &str)
- {
- m_strWaveStationDataFile = str;
- }
- void SetDeepWaterWaveHeight(double d)
- {
- m_dDeepWaterWaveHeight = d;
- }
- void SetDeepWaterWaveOrientation(double d)
- {
- m_dDeepWaterWaveOrientation = d;
- }
- void SetWavePeriod(double d)
- {
- m_dWavePeriod = d;
- }
-
- void SetTideDataFile(string const &str)
- {
- m_strTideDataFile = str;
- }
- void SetBreakingWaveRatio(double d)
- {
- m_dBreakingWaveRatio = d;
- }
-
- // Additional setters for comprehensive YAML support
- void SetCoastPlatformErosion(bool b)
- {
- m_bCoastPlatformErosion = b;
- }
- void SetPlatformErosionResistance(double d)
- {
- m_dPlatformErosionResistance = d;
- }
- void SetBeachSedimentTransport(bool b)
- {
- m_bBeachSedimentTransport = b;
- }
- void SetBeachTransportAtEdges(int n)
- {
- m_nBeachTransportAtEdges = n;
- }
- void SetBeachErosionEquation(int n)
- {
- m_nBeachErosionEquation = n;
- }
- void SetFineMedianSize(double d)
- {
- m_dFineMedianSize = d;
- }
- void SetSandMedianSize(double d)
- {
- m_dSandMedianSize = d;
- }
- void SetCoarseMedianSize(double d)
- {
- m_dCoarseMedianSize = d;
- }
- void SetSedimentDensity(double d)
- {
- m_dSedimentDensity = d;
- }
- void SetBeachSedimentPorosity(double d)
- {
- m_dBeachSedimentPorosity = d;
- }
- void SetFineErosivity(double d)
- {
- m_dFineErosivity = d;
- }
- void SetSandErosivity(double d)
- {
- m_dSandErosivity = d;
- }
- void SetCoarseErosivity(double d)
- {
- m_dCoarseErosivity = d;
- }
- void SetTransportKLS(double d)
- {
- m_dTransportKLS = d;
- }
- void SetKamphuis(double d)
- {
- m_dKamphuis = d;
- }
- void SetBermHeight(double d)
- {
- m_dBermHeight = d;
- }
-
- void SetCliffCollapse(bool b)
- {
- m_bCliffCollapse = b;
- }
- void SetCliffErosionResistance(double d)
- {
- m_dCliffErosionResistance = d;
- }
- void SetNotchOverhang(double d)
- {
- m_dNotchOverhang = d;
- }
- void SetNotchBase(double d)
- {
- m_dNotchBase = d;
- }
- void SetCliffDepositionA(double d)
- {
- m_dCliffDepositionA = d;
- }
- void SetTalusWidth(double d)
- {
- m_dTalusWidth = d;
- }
- void SetMinTalusLength(double d)
- {
- m_dMinTalusLength = d;
- }
- void SetMinTalusHeight(double d)
- {
- m_dMinTalusHeight = d;
- }
-
- void SetFloodInput(bool b)
- {
- m_bFloodInput = b;
- }
- void SetFloodFiles(vector v)
- {
- m_vecFloodFiles = v;
- }
- void SetFloodCoastline(string const &str)
- {
- m_strFloodCoastline = str;
- }
- void SetRunupEquation(string const &str)
- {
- if (str == "" or str == " ")
- {
- m_strRunupEquation = 0;
- }
- else
- {
- m_strRunupEquation = std::stoi(str);
- }
- }
- void SetFloodLocations(string const &str)
- {
- m_strFloodLocations = str;
- }
- void SetFloodInputLocation(string const &str)
- {
- m_strFloodInputLocation = str;
- }
-
- void SetSedimentInput(bool b)
- {
- m_bSedimentInput = b;
- }
- void SetSedimentInputLocation(string const &str)
- {
- m_strSedimentInputLocation = str;
- }
- void SetSedimentInputType(string const &str)
- {
- m_strSedimentInputType = str;
- }
- void SetSedimentInputDetails(string const &str)
- {
- m_strSedimentInputDetails = str;
- }
-
- void SetGravitationalAcceleration(double d)
- {
- m_dGravitationalAcceleration = d;
- }
- void SetNormalSpacing(double d)
- {
- m_dNormalSpacing = d;
- }
- void SetRandomFactor(double d)
- {
- m_dRandomFactor = d;
- }
- void SetNormalLength(double d)
- {
- m_dNormalLength = d;
- }
- void SetStartDepthRatio(double d)
- {
- m_dStartDepthRatio = d;
- }
- void SetSyntheticTransectSpacing(double d)
- {
- m_dSyntheticTransectSpacing = d;
- }
-
- void SetSaveProfileData(bool b)
- {
- m_bSaveProfileData = b;
- }
- void SetProfileNumbers(vector const &vec)
- {
- m_vecProfileNumbers = vec;
- }
- void SetProfileTimesteps(vector const &vec)
- {
- m_vecProfileTimesteps = vec;
- }
- void SetSaveParallelProfiles(bool b)
- {
- m_bSaveParallelProfiles = b;
- }
- void SetOutputErosionPotential(bool b)
- {
- m_bOutputErosionPotential = b;
- }
- void SetCurvatureWindow(int n)
- {
- m_nCurvatureWindow = n;
- }
-
- void SetCliffEdgeSmoothing(int n)
- {
- m_nCliffEdgeSmoothing = n;
- }
- void SetCliffEdgeSmoothingWindow(int n)
- {
- m_nCliffEdgeSmoothingWindow = n;
- }
- void SetCliffEdgePolynomialOrder(int n)
- {
- m_nCliffEdgePolynomialOrder = n;
- }
- void SetCliffSlopeLimit(double d)
- {
- m_dCliffSlopeLimit = d;
- }
-
- // Getters for all parameters
- string GetRunName() const
- {
- return m_strRunName;
- }
- int GetLogFileDetail() const
- {
- return m_nLogFileDetail;
- }
- bool GetCSVPerTimestepResults() const
- {
- return m_bCSVPerTimestepResults;
- }
- string GetStartDateTime() const
- {
- return m_strStartDateTime;
- }
- string GetDuration() const
- {
- return m_strDuration;
- }
- string GetTimestep() const
- {
- return m_strTimestep;
- }
- vector GetSaveTimes() const
- {
- return m_vecSaveTimes;
- }
- int GetRandomSeed() const
- {
- return m_nRandomSeed;
- }
- bool UseSystemTimeForRandomSeed() const
- {
- return m_bUseSystemTimeForSeed;
- }
-
- int GetMaxSaveDigits() const
- {
- return m_nMaxSaveDigits;
- }
- string GetSaveDigitsMode() const
- {
- return m_strSaveDigitsMode;
- }
- vector GetRasterFiles() const;
- string GetRasterFormat() const
- {
- return m_strRasterFormat;
- }
- bool GetWorldFile() const
- {
- return m_bWorldFile;
- }
- bool GetScaleValues() const
- {
- return m_bScaleValues;
- }
- vector GetSliceElevations() const
- {
- return m_vecSliceElevations;
- }
- vector GetVectorFiles() const;
- string GetVectorFormat() const
- {
- return m_strVectorFormat;
- }
- vector GetTimeSeriesFiles() const;
-
- int GetCoastlineSmoothing() const
- {
- return m_nCoastlineSmoothing;
- }
- int GetCoastlineSmoothingWindow() const
- {
- return m_nCoastlineSmoothingWindow;
- }
- int GetPolynomialOrder() const
- {
- return m_nPolynomialOrder;
- }
- string GetOmitGridEdges() const;
- int GetProfileSmoothingWindow() const
- {
- return m_nProfileSmoothingWindow;
- }
- double GetMaxLocalSlope() const
- {
- return m_dMaxLocalSlope;
- }
- double GetMaxBeachElevation() const
- {
- return m_dMaxBeachElevation;
- }
-
- int GetNumLayers() const
- {
- return m_nNumLayers;
- }
- string GetBasementDEMFile() const
- {
- return m_strBasementDEMFile;
- }
- vector GetUnconsFineFiles() const
- {
- return m_vecUnconsFineFiles;
- }
- vector GetUnconsSandFiles() const
- {
- return m_vecUnconsSandFiles;
- }
- vector GetUnconsCoarseFiles() const
- {
- return m_vecUnconsCoarseFiles;
- }
- vector GetConsFineFiles() const
- {
- return m_vecConsFineFiles;
- }
- vector GetConsSandFiles() const
- {
- return m_vecConsSandFiles;
- }
- vector GetConsCoarseFiles() const
- {
- return m_vecConsCoarseFiles;
- }
- string GetSuspendedSedFile() const
- {
- return m_strSuspendedSedFile;
- }
- string GetLandformFile() const
- {
- return m_strLandformFile;
- }
- string GetInterventionClassFile() const
- {
- return m_strInterventionClassFile;
- }
- string GetInterventionHeightFile() const
- {
- return m_strInterventionHeightFile;
- }
-
- int GetWavePropagationModel() const
- {
- return m_nWavePropagationModel;
- }
- double GetSeawaterDensity() const
- {
- return m_dSeawaterDensity;
- }
- double GetInitialWaterLevel() const
- {
- return m_dInitialWaterLevel;
- }
- double GetFinalWaterLevel() const
- {
- return m_dFinalWaterLevel;
- }
- bool HasFinalWaterLevel() const
- {
- return m_bHasFinalWaterLevel;
- }
-
- // Wave data configuration getters (Cases 37-40)
- string GetWaveHeightTimeSeries() const
- {
- return m_strWaveHeightTimeSeries;
- }
- string GetWaveStationDataFile() const
- {
- return m_strWaveStationDataFile;
- }
- double GetDeepWaterWaveHeight() const
- {
- return m_dDeepWaterWaveHeight;
- }
- double GetDeepWaterWaveOrientation() const
- {
- return m_dDeepWaterWaveOrientation;
- }
- double GetWavePeriod() const
- {
- return m_dWavePeriod;
- }
-
- string GetTideDataFile() const
- {
- return m_strTideDataFile;
- }
- double GetBreakingWaveRatio() const
- {
- return m_dBreakingWaveRatio;
- }
-
- // Sediment and Erosion parameters
- bool GetCoastPlatformErosion() const
- {
- return m_bCoastPlatformErosion;
- }
- double GetPlatformErosionResistance() const
- {
- return m_dPlatformErosionResistance;
- }
- bool GetBeachSedimentTransport() const
- {
- return m_bBeachSedimentTransport;
- }
- int GetBeachTransportAtEdges() const
- {
- return m_nBeachTransportAtEdges;
- }
- int GetBeachErosionEquation() const
- {
- return m_nBeachErosionEquation;
- }
- double GetFineMedianSize() const
- {
- return m_dFineMedianSize;
- }
- double GetSandMedianSize() const
- {
- return m_dSandMedianSize;
- }
- double GetCoarseMedianSize() const
- {
- return m_dCoarseMedianSize;
- }
- double GetSedimentDensity() const
- {
- return m_dSedimentDensity;
- }
- double GetBeachSedimentPorosity() const
- {
- return m_dBeachSedimentPorosity;
- }
- double GetFineErosivity() const
- {
- return m_dFineErosivity;
- }
- double GetSandErosivity() const
- {
- return m_dSandErosivity;
- }
- double GetCoarseErosivity() const
- {
- return m_dCoarseErosivity;
- }
- double GetTransportKLS() const
- {
- return m_dTransportKLS;
- }
- double GetKamphuis() const
- {
- return m_dKamphuis;
- }
- double GetBermHeight() const
- {
- return m_dBermHeight;
- }
-
- // Cliff parameters
- bool GetCliffCollapse() const
- {
- return m_bCliffCollapse;
- }
- double GetCliffErosionResistance() const
- {
- return m_dCliffErosionResistance;
- }
- double GetNotchOverhang() const
- {
- return m_dNotchOverhang;
- }
- double GetNotchBase() const
- {
- return m_dNotchBase;
- }
- double GetCliffDepositionA() const
- {
- return m_dCliffDepositionA;
- }
- double GetTalusWidth() const
- {
- return m_dTalusWidth;
- }
- double GetMinTalusLength() const
- {
- return m_dMinTalusLength;
- }
- double GetMinTalusHeight() const
- {
- return m_dMinTalusHeight;
- }
-
- // Flood parameters
- bool GetFloodInput() const
- {
- return m_bFloodInput;
- }
- vector GetFloodFiles() const;
-
- string GetFloodCoastline() const
- {
- return m_strFloodCoastline;
- }
- int GetRunupEquation() const
- {
- return m_strRunupEquation;
- }
- string GetFloodLocations() const
- {
- return m_strFloodLocations;
- }
- string GetFloodInputLocation() const
- {
- return m_strFloodInputLocation;
- }
-
- // Sediment Input parameters
- bool GetSedimentInput() const
- {
- return m_bSedimentInput;
- }
- string GetSedimentInputLocation() const
- {
- return m_strSedimentInputLocation;
- }
- string GetSedimentInputType() const
- {
- return m_strSedimentInputType;
- }
- string GetSedimentInputDetails() const
- {
- return m_strSedimentInputDetails;
- }
-
- // Physics and Geometry parameters
- double GetGravitationalAcceleration() const
- {
- return m_dGravitationalAcceleration;
- }
- double GetNormalSpacing() const
- {
- return m_dNormalSpacing;
- }
- double GetRandomFactor() const
- {
- return m_dRandomFactor;
- }
- double GetNormalLength() const
- {
- return m_dNormalLength;
- }
- double GetStartDepthRatio() const
- {
- return m_dStartDepthRatio;
- }
- double GetSyntheticTransectSpacing() const
- {
- return m_dSyntheticTransectSpacing;
- }
-
- // Profile and Output Options
- bool GetSaveProfileData() const
- {
- return m_bSaveProfileData;
- }
- vector GetProfileNumbers() const
- {
- return m_vecProfileNumbers;
- }
- vector GetProfileTimesteps() const
- {
- return m_vecProfileTimesteps;
- }
- bool GetSaveParallelProfiles() const
- {
- return m_bSaveParallelProfiles;
- }
- bool GetOutputErosionPotential() const
- {
- return m_bOutputErosionPotential;
- }
- int GetCurvatureWindow() const
- {
- return m_nCurvatureWindow;
- }
-
- // Cliff Edge Processing
- int GetCliffEdgeSmoothing() const
- {
- return m_nCliffEdgeSmoothing;
- }
- int GetCliffEdgeSmoothingWindow() const
- {
- return m_nCliffEdgeSmoothingWindow;
- }
- int GetCliffEdgePolynomialOrder() const
- {
- return m_nCliffEdgePolynomialOrder;
- }
- double GetCliffSlopeLimit() const
- {
- return m_dCliffSlopeLimit;
- }
- // Initialize with default values
- void InitializeDefaults();
-};
-#endif //CONFIGURATION_H
+/*!
+
+ \file configuration.h
+ \brief Unified configuration class for CoastalME simulation parameters
+ \details Provides a single interface for accessing simulation parameters
+ regardless of input format (.dat or YAML)
+ \author David Favis-Mortlock
+ \author Andres Payo
+ \date 2025
+ \copyright GNU General Public License
+
+*/
+
+/* ==============================================================================================================================
+
+ This file is part of CoastalME, the Coastal Modelling Environment.
+
+ 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.
+
+ 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.
+
+ 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.
+
+==============================================================================================================================*/
+#ifndef CONFIGURATION_H
+#define CONFIGURATION_H
+
+#include
+#include
+#include
+#include
+
+using std::string;
+using std::vector;
+
+//! Unified configuration class for CoastalME simulation parameters
+class CConfiguration
+{
+ private:
+ // Run Information
+ string m_strRunName;
+ int m_nLogFileDetail;
+ bool m_bCSVPerTimestepResults;
+
+ // Simulation timing
+ string m_strStartDateTime;
+ string m_strDuration;
+ string m_strTimestep;
+ vector m_vecSaveTimes;
+ int m_nRandomSeed;
+ bool m_bUseSystemTimeForSeed;
+
+ // GIS Output
+ int m_nMaxSaveDigits;
+ string m_strSaveDigitsMode;
+ vector m_vecRasterFiles;
+ string m_strRasterFormat;
+ bool m_bWorldFile;
+ bool m_bScaleValues;
+ vector m_vecSliceElevations;
+ vector m_vecVectorFiles;
+ string m_strVectorFormat;
+ vector m_vecTimeSeriesFiles;
+
+ // Grid and Coastline
+ int m_nCoastlineSmoothing;
+ int m_nCoastlineSmoothingWindow;
+ int m_nPolynomialOrder;
+ string m_strOmitGridEdges;
+ int m_nProfileSmoothingWindow;
+ double m_dMaxLocalSlope;
+ double m_dMaxBeachElevation;
+
+ // Layers and Files
+ int m_nNumLayers;
+ string m_strBasementDEMFile;
+ vector m_vecUnconsFineFiles;
+ vector m_vecUnconsSandFiles;
+ vector m_vecUnconsCoarseFiles;
+ vector m_vecConsFineFiles;
+ vector m_vecConsSandFiles;
+ vector m_vecConsCoarseFiles;
+ string m_strSuspendedSedFile;
+ string m_strLandformFile;
+ string m_strInterventionClassFile;
+ string m_strInterventionHeightFile;
+
+ // Hydrology
+ int m_nWavePropagationModel;
+ double m_dSeawaterDensity;
+ double m_dInitialWaterLevel;
+ double m_dFinalWaterLevel;
+ bool m_bHasFinalWaterLevel;
+
+ // Waves
+ string m_strWaveHeightTimeSeries;
+ string m_strWaveStationDataFile;
+ double m_dDeepWaterWaveHeight;
+ double m_dDeepWaterWaveOrientation;
+ double m_dWavePeriod;
+
+ // tides
+ string m_strTideDataFile;
+ double m_dBreakingWaveRatio;
+
+ // Sediment and Erosion
+ bool m_bCoastPlatformErosion;
+ double m_dPlatformErosionResistance;
+ bool m_bBeachSedimentTransport;
+ int m_nBeachTransportAtEdges;
+ int m_nBeachErosionEquation;
+ double m_dFineMedianSize;
+ double m_dSandMedianSize;
+ double m_dCoarseMedianSize;
+ double m_dSedimentDensity;
+ double m_dBeachSedimentPorosity;
+ double m_dFineErosivity;
+ double m_dSandErosivity;
+ double m_dCoarseErosivity;
+ double m_dTransportKLS;
+ double m_dKamphuis;
+ double m_dBermHeight;
+
+ // Cliff parameters
+ bool m_bCliffCollapse;
+ double m_dCliffErosionResistance;
+ double m_dNotchOverhang;
+ double m_dNotchBase;
+ double m_dCliffDepositionA;
+ double m_dTalusWidth;
+ double m_dMinTalusLength;
+ double m_dMinTalusHeight;
+
+ // Flood parameters
+ bool m_bFloodInput;
+ string m_strFloodCoastline;
+ int m_strRunupEquation;
+ string m_strFloodLocations;
+ string m_strFloodInputLocation;
+ vector m_vecFloodFiles;
+
+ // Sediment input parameters
+ bool m_bSedimentInput;
+ string m_strSedimentInputLocation;
+ string m_strSedimentInputType;
+ string m_strSedimentInputDetails;
+
+ // Physics and Geometry
+ double m_dGravitationalAcceleration;
+ double m_dNormalSpacing;
+ double m_dRandomFactor;
+ double m_dNormalLength;
+ double m_dStartDepthRatio;
+ double m_dSyntheticTransectSpacing;
+
+ // Profile and Output Options
+ bool m_bSaveProfileData;
+ vector m_vecProfileNumbers;
+ vector m_vecProfileTimesteps;
+ bool m_bSaveParallelProfiles;
+ bool m_bOutputErosionPotential;
+ int m_nCurvatureWindow;
+
+ // Cliff Edge Processing
+ int m_nCliffEdgeSmoothing;
+ int m_nCliffEdgeSmoothingWindow;
+ int m_nCliffEdgePolynomialOrder;
+ double m_dCliffSlopeLimit;
+
+ public:
+ CConfiguration();
+ ~CConfiguration();
+
+ // Setters for all parameters
+ void SetRunName(string const &str)
+ {
+ m_strRunName = str;
+ }
+ void SetLogFileDetail(int n)
+ {
+ m_nLogFileDetail = n;
+ }
+ void SetCSVPerTimestepResults(bool b)
+ {
+ m_bCSVPerTimestepResults = b;
+ }
+ void SetStartDateTime(string const &str)
+ {
+ m_strStartDateTime = str;
+ }
+ void SetDuration(string const &str)
+ {
+ m_strDuration = str;
+ }
+ void SetTimestep(string const &str)
+ {
+ m_strTimestep = str;
+ }
+ void SetSaveTimes(vector const &vec)
+ {
+ m_vecSaveTimes = vec;
+ }
+ void SetRandomSeed(int n)
+ {
+ m_nRandomSeed = n;
+ m_bUseSystemTimeForSeed = false;
+ }
+ void UseSystemTimeForSeed()
+ {
+ m_bUseSystemTimeForSeed = false;
+ }
+
+ void SetMaxSaveDigits(int n)
+ {
+ m_nMaxSaveDigits = n;
+ }
+ void SetSaveDigitsMode(string const &str)
+ {
+ m_strSaveDigitsMode = str;
+ }
+ void SetRasterFiles(vector const &vec)
+ {
+ m_vecRasterFiles = vec;
+ }
+ void SetRasterFormat(string const &str)
+ {
+ m_strRasterFormat = str;
+ }
+ void SetWorldFile(bool b)
+ {
+ m_bWorldFile = b;
+ }
+ void SetScaleValues(bool b)
+ {
+ m_bScaleValues = b;
+ }
+ void SetSliceElevations(vector const &vec)
+ {
+ m_vecSliceElevations = vec;
+ }
+ void SetVectorFiles(vector const &vec)
+ {
+ m_vecVectorFiles = vec;
+ }
+ void SetVectorFormat(string const &str)
+ {
+ m_strVectorFormat = str;
+ }
+ void SetTimeSeriesFiles(vector const &vec)
+ {
+ m_vecTimeSeriesFiles = vec;
+ }
+
+ void SetCoastlineSmoothing(int n)
+ {
+ m_nCoastlineSmoothing = n;
+ }
+ void SetCoastlineSmoothingWindow(int n)
+ {
+ m_nCoastlineSmoothingWindow = n;
+ }
+ void SetPolynomialOrder(int n)
+ {
+ m_nPolynomialOrder = n;
+ }
+ void SetOmitGridEdges(string const &str)
+ {
+ m_strOmitGridEdges = str;
+ }
+ void SetProfileSmoothingWindow(int n)
+ {
+ m_nProfileSmoothingWindow = n;
+ }
+ void SetMaxLocalSlope(double d)
+ {
+ m_dMaxLocalSlope = d;
+ }
+ void SetMaxBeachElevation(double d)
+ {
+ m_dMaxBeachElevation = d;
+ }
+ void SetNumLayers(int n)
+ {
+ m_nNumLayers = n;
+ }
+ void SetBasementDEMFile(string const &str)
+ {
+ m_strBasementDEMFile = str;
+ }
+ void SetUnconsFineFiles(vector const &vec)
+ {
+ m_vecUnconsFineFiles = vec;
+ }
+ void SetUnconsSandFiles(vector const &vec)
+ {
+ m_vecUnconsSandFiles = vec;
+ }
+ void SetUnconsCoarseFiles(vector const &vec)
+ {
+ m_vecUnconsCoarseFiles = vec;
+ }
+ void SetConsFineFiles(vector const &vec)
+ {
+ m_vecConsFineFiles = vec;
+ }
+ void SetConsSandFiles(vector const &vec)
+ {
+ m_vecConsSandFiles = vec;
+ }
+ void SetConsCoarseFiles(vector const &vec)
+ {
+ m_vecConsCoarseFiles = vec;
+ }
+ void SetSuspendedSedFile(string const &str)
+ {
+ m_strSuspendedSedFile = str;
+ }
+ void SetLandformFile(string const &str)
+ {
+ m_strLandformFile = str;
+ }
+ void SetInterventionClassFile(string const &str)
+ {
+ m_strInterventionClassFile = str;
+ }
+ void SetInterventionHeightFile(string const &str)
+ {
+ m_strInterventionHeightFile = str;
+ }
+
+ void SetWavePropagationModel(int n)
+ {
+ m_nWavePropagationModel = n;
+ }
+ void SetSeawaterDensity(double d)
+ {
+ m_dSeawaterDensity = d;
+ }
+ void SetInitialWaterLevel(double d)
+ {
+ m_dInitialWaterLevel = d;
+ }
+ void SetFinalWaterLevel(double d)
+ {
+ m_dFinalWaterLevel = d;
+ m_bHasFinalWaterLevel = true;
+ }
+
+ // Wave height Data
+ void SetWaveHeightTimeSeries(string const &str)
+ {
+ m_strWaveHeightTimeSeries = str;
+ }
+ void SetWaveStationDataFile(string const &str)
+ {
+ m_strWaveStationDataFile = str;
+ }
+ void SetDeepWaterWaveHeight(double d)
+ {
+ m_dDeepWaterWaveHeight = d;
+ }
+ void SetDeepWaterWaveOrientation(double d)
+ {
+ m_dDeepWaterWaveOrientation = d;
+ }
+ void SetWavePeriod(double d)
+ {
+ m_dWavePeriod = d;
+ }
+
+ void SetTideDataFile(string const &str)
+ {
+ m_strTideDataFile = str;
+ }
+ void SetBreakingWaveRatio(double d)
+ {
+ m_dBreakingWaveRatio = d;
+ }
+
+ // Additional setters for comprehensive YAML support
+ void SetCoastPlatformErosion(bool b)
+ {
+ m_bCoastPlatformErosion = b;
+ }
+ void SetPlatformErosionResistance(double d)
+ {
+ m_dPlatformErosionResistance = d;
+ }
+ void SetBeachSedimentTransport(bool b)
+ {
+ m_bBeachSedimentTransport = b;
+ }
+ void SetBeachTransportAtEdges(int n)
+ {
+ m_nBeachTransportAtEdges = n;
+ }
+ void SetBeachErosionEquation(int n)
+ {
+ m_nBeachErosionEquation = n;
+ }
+ void SetFineMedianSize(double d)
+ {
+ m_dFineMedianSize = d;
+ }
+ void SetSandMedianSize(double d)
+ {
+ m_dSandMedianSize = d;
+ }
+ void SetCoarseMedianSize(double d)
+ {
+ m_dCoarseMedianSize = d;
+ }
+ void SetSedimentDensity(double d)
+ {
+ m_dSedimentDensity = d;
+ }
+ void SetBeachSedimentPorosity(double d)
+ {
+ m_dBeachSedimentPorosity = d;
+ }
+ void SetFineErosivity(double d)
+ {
+ m_dFineErosivity = d;
+ }
+ void SetSandErosivity(double d)
+ {
+ m_dSandErosivity = d;
+ }
+ void SetCoarseErosivity(double d)
+ {
+ m_dCoarseErosivity = d;
+ }
+ void SetTransportKLS(double d)
+ {
+ m_dTransportKLS = d;
+ }
+ void SetKamphuis(double d)
+ {
+ m_dKamphuis = d;
+ }
+ void SetBermHeight(double d)
+ {
+ m_dBermHeight = d;
+ }
+
+ void SetCliffCollapse(bool b)
+ {
+ m_bCliffCollapse = b;
+ }
+ void SetCliffErosionResistance(double d)
+ {
+ m_dCliffErosionResistance = d;
+ }
+ void SetNotchOverhang(double d)
+ {
+ m_dNotchOverhang = d;
+ }
+ void SetNotchBase(double d)
+ {
+ m_dNotchBase = d;
+ }
+ void SetCliffDepositionA(double d)
+ {
+ m_dCliffDepositionA = d;
+ }
+ void SetTalusWidth(double d)
+ {
+ m_dTalusWidth = d;
+ }
+ void SetMinTalusLength(double d)
+ {
+ m_dMinTalusLength = d;
+ }
+ void SetMinTalusHeight(double d)
+ {
+ m_dMinTalusHeight = d;
+ }
+
+ void SetFloodInput(bool b)
+ {
+ m_bFloodInput = b;
+ }
+ void SetFloodFiles(vector v)
+ {
+ m_vecFloodFiles = v;
+ }
+ void SetFloodCoastline(string const &str)
+ {
+ m_strFloodCoastline = str;
+ }
+ void SetRunupEquation(string const &str)
+ {
+ if (str == "" or str == " ")
+ {
+ m_strRunupEquation = 0;
+ }
+ else
+ {
+ m_strRunupEquation = std::stoi(str);
+ }
+ }
+ void SetFloodLocations(string const &str)
+ {
+ m_strFloodLocations = str;
+ }
+ void SetFloodInputLocation(string const &str)
+ {
+ m_strFloodInputLocation = str;
+ }
+
+ void SetSedimentInput(bool b)
+ {
+ m_bSedimentInput = b;
+ }
+ void SetSedimentInputLocation(string const &str)
+ {
+ m_strSedimentInputLocation = str;
+ }
+ void SetSedimentInputType(string const &str)
+ {
+ m_strSedimentInputType = str;
+ }
+ void SetSedimentInputDetails(string const &str)
+ {
+ m_strSedimentInputDetails = str;
+ }
+
+ void SetGravitationalAcceleration(double d)
+ {
+ m_dGravitationalAcceleration = d;
+ }
+ void SetNormalSpacing(double d)
+ {
+ m_dNormalSpacing = d;
+ }
+ void SetRandomFactor(double d)
+ {
+ m_dRandomFactor = d;
+ }
+ void SetNormalLength(double d)
+ {
+ m_dNormalLength = d;
+ }
+ void SetStartDepthRatio(double d)
+ {
+ m_dStartDepthRatio = d;
+ }
+ void SetSyntheticTransectSpacing(double d)
+ {
+ m_dSyntheticTransectSpacing = d;
+ }
+
+ void SetSaveProfileData(bool b)
+ {
+ m_bSaveProfileData = b;
+ }
+ void SetProfileNumbers(vector const &vec)
+ {
+ m_vecProfileNumbers = vec;
+ }
+ void SetProfileTimesteps(vector const &vec)
+ {
+ m_vecProfileTimesteps = vec;
+ }
+ void SetSaveParallelProfiles(bool b)
+ {
+ m_bSaveParallelProfiles = b;
+ }
+ void SetOutputErosionPotential(bool b)
+ {
+ m_bOutputErosionPotential = b;
+ }
+ void SetCurvatureWindow(int n)
+ {
+ m_nCurvatureWindow = n;
+ }
+
+ void SetCliffEdgeSmoothing(int n)
+ {
+ m_nCliffEdgeSmoothing = n;
+ }
+ void SetCliffEdgeSmoothingWindow(int n)
+ {
+ m_nCliffEdgeSmoothingWindow = n;
+ }
+ void SetCliffEdgePolynomialOrder(int n)
+ {
+ m_nCliffEdgePolynomialOrder = n;
+ }
+ void SetCliffSlopeLimit(double d)
+ {
+ m_dCliffSlopeLimit = d;
+ }
+
+ // Getters for all parameters
+ string GetRunName() const
+ {
+ return m_strRunName;
+ }
+ int GetLogFileDetail() const
+ {
+ return m_nLogFileDetail;
+ }
+ bool GetCSVPerTimestepResults() const
+ {
+ return m_bCSVPerTimestepResults;
+ }
+ string GetStartDateTime() const
+ {
+ return m_strStartDateTime;
+ }
+ string GetDuration() const
+ {
+ return m_strDuration;
+ }
+ string GetTimestep() const
+ {
+ return m_strTimestep;
+ }
+ vector GetSaveTimes() const
+ {
+ return m_vecSaveTimes;
+ }
+ int GetRandomSeed() const
+ {
+ return m_nRandomSeed;
+ }
+ bool UseSystemTimeForRandomSeed() const
+ {
+ return m_bUseSystemTimeForSeed;
+ }
+
+ int GetMaxSaveDigits() const
+ {
+ return m_nMaxSaveDigits;
+ }
+ string GetSaveDigitsMode() const
+ {
+ return m_strSaveDigitsMode;
+ }
+ vector GetRasterFiles() const;
+ string GetRasterFormat() const
+ {
+ return m_strRasterFormat;
+ }
+ bool GetWorldFile() const
+ {
+ return m_bWorldFile;
+ }
+ bool GetScaleValues() const
+ {
+ return m_bScaleValues;
+ }
+ vector GetSliceElevations() const
+ {
+ return m_vecSliceElevations;
+ }
+ vector GetVectorFiles() const;
+ string GetVectorFormat() const
+ {
+ return m_strVectorFormat;
+ }
+ vector GetTimeSeriesFiles() const;
+
+ int GetCoastlineSmoothing() const
+ {
+ return m_nCoastlineSmoothing;
+ }
+ int GetCoastlineSmoothingWindow() const
+ {
+ return m_nCoastlineSmoothingWindow;
+ }
+ int GetPolynomialOrder() const
+ {
+ return m_nPolynomialOrder;
+ }
+ string GetOmitGridEdges() const;
+ int GetProfileSmoothingWindow() const
+ {
+ return m_nProfileSmoothingWindow;
+ }
+ double GetMaxLocalSlope() const
+ {
+ return m_dMaxLocalSlope;
+ }
+ double GetMaxBeachElevation() const
+ {
+ return m_dMaxBeachElevation;
+ }
+
+ int GetNumLayers() const
+ {
+ return m_nNumLayers;
+ }
+ string GetBasementDEMFile() const
+ {
+ return m_strBasementDEMFile;
+ }
+ vector GetUnconsFineFiles() const
+ {
+ return m_vecUnconsFineFiles;
+ }
+ vector GetUnconsSandFiles() const
+ {
+ return m_vecUnconsSandFiles;
+ }
+ vector GetUnconsCoarseFiles() const
+ {
+ return m_vecUnconsCoarseFiles;
+ }
+ vector GetConsFineFiles() const
+ {
+ return m_vecConsFineFiles;
+ }
+ vector GetConsSandFiles() const
+ {
+ return m_vecConsSandFiles;
+ }
+ vector GetConsCoarseFiles() const
+ {
+ return m_vecConsCoarseFiles;
+ }
+ string GetSuspendedSedFile() const
+ {
+ return m_strSuspendedSedFile;
+ }
+ string GetLandformFile() const
+ {
+ return m_strLandformFile;
+ }
+ string GetInterventionClassFile() const
+ {
+ return m_strInterventionClassFile;
+ }
+ string GetInterventionHeightFile() const
+ {
+ return m_strInterventionHeightFile;
+ }
+
+ int GetWavePropagationModel() const
+ {
+ return m_nWavePropagationModel;
+ }
+ double GetSeawaterDensity() const
+ {
+ return m_dSeawaterDensity;
+ }
+ double GetInitialWaterLevel() const
+ {
+ return m_dInitialWaterLevel;
+ }
+ double GetFinalWaterLevel() const
+ {
+ return m_dFinalWaterLevel;
+ }
+ bool HasFinalWaterLevel() const
+ {
+ return m_bHasFinalWaterLevel;
+ }
+
+ // Wave data configuration getters (Cases 37-40)
+ string GetWaveHeightTimeSeries() const
+ {
+ return m_strWaveHeightTimeSeries;
+ }
+ string GetWaveStationDataFile() const
+ {
+ return m_strWaveStationDataFile;
+ }
+ double GetDeepWaterWaveHeight() const
+ {
+ return m_dDeepWaterWaveHeight;
+ }
+ double GetDeepWaterWaveOrientation() const
+ {
+ return m_dDeepWaterWaveOrientation;
+ }
+ double GetWavePeriod() const
+ {
+ return m_dWavePeriod;
+ }
+
+ string GetTideDataFile() const
+ {
+ return m_strTideDataFile;
+ }
+ double GetBreakingWaveRatio() const
+ {
+ return m_dBreakingWaveRatio;
+ }
+
+ // Sediment and Erosion parameters
+ bool GetCoastPlatformErosion() const
+ {
+ return m_bCoastPlatformErosion;
+ }
+ double GetPlatformErosionResistance() const
+ {
+ return m_dPlatformErosionResistance;
+ }
+ bool GetBeachSedimentTransport() const
+ {
+ return m_bBeachSedimentTransport;
+ }
+ int GetBeachTransportAtEdges() const
+ {
+ return m_nBeachTransportAtEdges;
+ }
+ int GetBeachErosionEquation() const
+ {
+ return m_nBeachErosionEquation;
+ }
+ double GetFineMedianSize() const
+ {
+ return m_dFineMedianSize;
+ }
+ double GetSandMedianSize() const
+ {
+ return m_dSandMedianSize;
+ }
+ double GetCoarseMedianSize() const
+ {
+ return m_dCoarseMedianSize;
+ }
+ double GetSedimentDensity() const
+ {
+ return m_dSedimentDensity;
+ }
+ double GetBeachSedimentPorosity() const
+ {
+ return m_dBeachSedimentPorosity;
+ }
+ double GetFineErosivity() const
+ {
+ return m_dFineErosivity;
+ }
+ double GetSandErosivity() const
+ {
+ return m_dSandErosivity;
+ }
+ double GetCoarseErosivity() const
+ {
+ return m_dCoarseErosivity;
+ }
+ double GetTransportKLS() const
+ {
+ return m_dTransportKLS;
+ }
+ double GetKamphuis() const
+ {
+ return m_dKamphuis;
+ }
+ double GetBermHeight() const
+ {
+ return m_dBermHeight;
+ }
+
+ // Cliff parameters
+ bool GetCliffCollapse() const
+ {
+ return m_bCliffCollapse;
+ }
+ double GetCliffErosionResistance() const
+ {
+ return m_dCliffErosionResistance;
+ }
+ double GetNotchOverhang() const
+ {
+ return m_dNotchOverhang;
+ }
+ double GetNotchBase() const
+ {
+ return m_dNotchBase;
+ }
+ double GetCliffDepositionA() const
+ {
+ return m_dCliffDepositionA;
+ }
+ double GetTalusWidth() const
+ {
+ return m_dTalusWidth;
+ }
+ double GetMinTalusLength() const
+ {
+ return m_dMinTalusLength;
+ }
+ double GetMinTalusHeight() const
+ {
+ return m_dMinTalusHeight;
+ }
+
+ // Flood parameters
+ bool GetFloodInput() const
+ {
+ return m_bFloodInput;
+ }
+ vector GetFloodFiles() const;
+
+ string GetFloodCoastline() const
+ {
+ return m_strFloodCoastline;
+ }
+ int GetRunupEquation() const
+ {
+ return m_strRunupEquation;
+ }
+ string GetFloodLocations() const
+ {
+ return m_strFloodLocations;
+ }
+ string GetFloodInputLocation() const
+ {
+ return m_strFloodInputLocation;
+ }
+
+ // Sediment Input parameters
+ bool GetSedimentInput() const
+ {
+ return m_bSedimentInput;
+ }
+ string GetSedimentInputLocation() const
+ {
+ return m_strSedimentInputLocation;
+ }
+ string GetSedimentInputType() const
+ {
+ return m_strSedimentInputType;
+ }
+ string GetSedimentInputDetails() const
+ {
+ return m_strSedimentInputDetails;
+ }
+
+ // Physics and Geometry parameters
+ double GetGravitationalAcceleration() const
+ {
+ return m_dGravitationalAcceleration;
+ }
+ double GetNormalSpacing() const
+ {
+ return m_dNormalSpacing;
+ }
+ double GetRandomFactor() const
+ {
+ return m_dRandomFactor;
+ }
+ double GetNormalLength() const
+ {
+ return m_dNormalLength;
+ }
+ double GetStartDepthRatio() const
+ {
+ return m_dStartDepthRatio;
+ }
+ double GetSyntheticTransectSpacing() const
+ {
+ return m_dSyntheticTransectSpacing;
+ }
+
+ // Profile and Output Options
+ bool GetSaveProfileData() const
+ {
+ return m_bSaveProfileData;
+ }
+ vector GetProfileNumbers() const
+ {
+ return m_vecProfileNumbers;
+ }
+ vector GetProfileTimesteps() const
+ {
+ return m_vecProfileTimesteps;
+ }
+ bool GetSaveParallelProfiles() const
+ {
+ return m_bSaveParallelProfiles;
+ }
+ bool GetOutputErosionPotential() const
+ {
+ return m_bOutputErosionPotential;
+ }
+ int GetCurvatureWindow() const
+ {
+ return m_nCurvatureWindow;
+ }
+
+ // Cliff Edge Processing
+ int GetCliffEdgeSmoothing() const
+ {
+ return m_nCliffEdgeSmoothing;
+ }
+ int GetCliffEdgeSmoothingWindow() const
+ {
+ return m_nCliffEdgeSmoothingWindow;
+ }
+ int GetCliffEdgePolynomialOrder() const
+ {
+ return m_nCliffEdgePolynomialOrder;
+ }
+ double GetCliffSlopeLimit() const
+ {
+ return m_dCliffSlopeLimit;
+ }
+ // Initialize with default values
+ void InitializeDefaults();
+};
+#endif //CONFIGURATION_H
diff --git a/src/create_profiles.cpp b/src/create_profiles.cpp
index 018d7ae04..2a9da1ac9 100644
--- a/src/create_profiles.cpp
+++ b/src/create_profiles.cpp
@@ -1,2285 +1,2285 @@
-/*!
- \file create_profiles.cpp
- \brief Creates profiles which are approximately normal to the coastline, these will become inter-polygon boundaries
- \details TODO 001 A more detailed description of these routines.
- \author David Favis-Mortlock
- \author Andres Payo
- \date 2025
- \copyright GNU General Public License
-*/
-
-/* ==============================================================================================================================
- This file is part of CoastalME, the Coastal Modelling Environment.
-
- 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.
-
- 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.
-
- 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.
-==============================================================================================================================*/
-#include
-
-#include
-#include
-
-#include
-using std::cerr;
-using std::endl;
-using std::ios;
-
-#include
-using std::find;
-using std::sort;
-
-#include
-using std::make_pair;
-using std::pair;
-
-#include
-using std::normal_distribution;
-
-#include "cme.h"
-#include "simulation.h"
-#include "coast.h"
-#include "2d_point.h"
-#include "2di_point.h"
-
-namespace
-{
-//===============================================================================================================================
-//! Function used to sort coastline curvature values when locating start points of normal profiles
-//===============================================================================================================================
-bool bCurvaturePairCompareDescending(const pair& prLeft, const pair& prRight)
-{
- // Sort in descending order (i.e. most concave first)
- return prLeft.second > prRight.second;
-}
-} // namespace
-
-//===============================================================================================================================
-//! Create coastline-normal profiles for all coastlines. The first profiles are created 'around' the most concave bits of coast. Also create 'special' profiles at the start and end of the coast, and put these onto the raster grid
-//===============================================================================================================================
-int CSimulation::nCreateAllProfiles(void)
-{
- if (m_nLogFileDetail >= LOG_FILE_MIDDLE_DETAIL)
- LogStream << endl << m_ulIter << ": Creating profiles" << endl;
-
- for (unsigned int nCoast = 0; nCoast < m_VCoast.size(); nCoast++)
- {
- int nProfile = 0;
- int const nCoastSize = m_VCoast[nCoast].nGetCoastlineSize();
-
- // Create a bool vector to mark coast points which have been searched
- vector bVCoastPointDone(nCoastSize, false);
-
- // Now create a vector of pairs: the first value of the pair is the coastline point, the second is the coastline's curvature at that point
- vector> prVCurvature;
-
- for (int nCoastPoint = 0; nCoastPoint < nCoastSize; nCoastPoint++)
- {
- double dCurvature;
-
- int const nCat = m_VCoast[nCoast].pGetCoastLandform(nCoastPoint)->nGetLandFormCategory();
- if ((nCat != LF_INTERVENTION_STRUCT) && (nCat != LF_INTERVENTION_NON_STRUCT))
- {
- // Not an intervention coast point, so store the smoothed curvature
- dCurvature = m_VCoast[nCoast].dGetSmoothCurvature(nCoastPoint);
- }
- else
- {
- // This is an intervention coast point, which is likely to have some sharp angles. So store the detailed curvature
- dCurvature = m_VCoast[nCoast].dGetDetailedCurvature(nCoastPoint);
- }
-
- prVCurvature.push_back(make_pair(nCoastPoint, dCurvature));
- }
-
- // Sort this pair vector in descending order, so that the most convex curvature points are first
- sort(prVCurvature.begin(), prVCurvature.end(), bCurvaturePairCompareDescending);
-
- // // DEBUG CODE =======================================================================================================================
- // for (int n = 0; n < prVCurvature.size(); n++)
- // {
- // LogStream << prVCurvature[n].first << "\t" << prVCurvature[n].second << endl;
- // }
- // LogStream << endl << endl;
- // // DEBUG CODE =======================================================================================================================
-
- // And mark points at and near the start and end of the coastline so that they don't get searched (will be creating 'special' start- and end-of-coast profiles at these end points later)
- for (int n = 0; n < m_nCoastNormalSpacing; n++)
- {
- if (n < nCoastSize)
- bVCoastPointDone[n] = true;
-
- int const m = nCoastSize - n - 1;
-
- if (m >= 0)
- bVCoastPointDone[m] = true;
- }
-
- // Now locate the start points for all coastline-normal profiles (except the grid-edge ones), at points of maximum convexity. Then create the profiles
- LocateAndCreateProfiles(nCoast, nProfile, &bVCoastPointDone, &prVCurvature);
-
- // Did we fail to create any normal profiles? If so, quit
- if (nProfile < 0)
- {
- string strErr = ERR + "timestep " + strDblToStr(m_ulIter) + ": could not create profiles for coastline " + strDblToStr(nCoast);
-
- if (m_ulIter == 1)
- strErr += ". Check the SWL";
-
- strErr += "\n";
-
- cerr << strErr;
- LogStream << strErr;
-
- return RTN_ERR_NO_PROFILES_1;
- }
-
- // Locate and create a 'special' profile at the grid edge, first at the beginning of the coastline. Then put this onto the raster grid
- int nRet = nLocateAndCreateGridEdgeProfile(true, nCoast, nProfile);
-
- if (nRet != RTN_OK)
- return nRet;
-
- // Locate a second 'special' profile at the grid edge, this time at end of the coastline. Then put this onto the raster grid
- nRet = nLocateAndCreateGridEdgeProfile(false, nCoast, ++nProfile);
-
- if (nRet != RTN_OK)
- return nRet;
-
- // Insert pointers to profiles at coastline points in the profile-all-coastpoint index
- m_VCoast[nCoast].InsertProfilesInProfileCoastPointIndex();
-
- // // DEBUG CODE ===================================================================================================
- // LogStream << endl << "===========================================================================================" << endl;
- // LogStream << "PROFILES BEFORE ADDING BEFORE- AND AFTER-PROFILE NUMBERS" << endl;
- // int nNumProfiles = m_VCoast[nCoast].nGetNumProfiles();
- // for (int nn = 0; nn < nNumProfiles; nn++)
- // {
- // CGeomProfile* pProfile = m_VCoast[nCoast].pGetProfile(nn);
- //
- // LogStream << nn << " nCoastID = " << pProfile->nGetProfileID() << " nGlobalID = " << pProfile->nGetProfileID() << " nGetCoastPoint = " << pProfile->nGetCoastPoint() << " pGetUpCoastAdjacentProfile = " << pProfile->pGetUpCoastAdjacentProfile() << " pGetDownCoastAdjacentProfile = " << pProfile->pGetDownCoastAdjacentProfile() << endl;
- // }
- // LogStream << "===================================================================================================" << endl << endl;
- // // DEBUG CODE ===================================================================================================
-
- CGeomProfile* pLastProfile;
- CGeomProfile* pThisProfile;
-
- // Go along the coastline and give each profile the number of the adjacent up-coast profile and the adjacent down-coast profile
- for (int nCoastPoint = 0; nCoastPoint < nCoastSize; nCoastPoint++)
- {
- if (m_VCoast[nCoast].bIsProfileAtCoastPoint(nCoastPoint))
- {
- pThisProfile = m_VCoast[nCoast].pGetProfileAtCoastPoint(nCoastPoint);
- // nThisProfile = pThisProfile->nGetProfileID();
-
- if (nCoastPoint == 0)
- {
- pThisProfile->SetUpCoastAdjacentProfile(NULL);
-
- // LogStream << "nCoastPoint = " << nCoastPoint << " ThisProfile = " << nThisProfile << " ThisProfile UpCoast = " << pThisProfile->pGetUpCoastAdjacentProfile() << " ThisProfile DownCoast = " << pThisProfile->pGetDownCoastAdjacentProfile() << endl;
-
- pLastProfile = pThisProfile;
- // nLastProfile = nThisProfile;
- continue;
- }
-
- pLastProfile->SetDownCoastAdjacentProfile(pThisProfile);
- pThisProfile->SetUpCoastAdjacentProfile(pLastProfile);
-
- if (nCoastPoint == nCoastSize - 1)
- pThisProfile->SetDownCoastAdjacentProfile(NULL);
-
- pLastProfile = pThisProfile;
- }
- }
-
- // And create an index to this coast's profiles in along-coastline sequence
- m_VCoast[nCoast].CreateProfileDownCoastIndex();
-
- // // DEBUG CODE =======================================================================================================================
- // for (int n = 0; n < m_VCoast[nCoast].nGetNumProfiles(); n++)
- // {
- // CGeomProfile* pProfile = m_VCoast[nCoast].pGetProfileWithDownCoastSeq(n);
- // CGeomProfile* pUpCoastProfile = pProfile->pGetUpCoastAdjacentProfile();
- // CGeomProfile* pDownCoastProfile = pProfile->pGetDownCoastAdjacentProfile();
- // int nUpCoastProfile = INT_NODATA;
- // int nDownCoastProfile = INT_NODATA;
- // if (pUpCoastProfile != 0)
- // nUpCoastProfile = pUpCoastProfile->nGetProfileID();
- // if (pDownCoastProfile != 0)
- // nDownCoastProfile = pDownCoastProfile->nGetProfileID();
- // LogStream << "nCoastID = " << pProfile->nGetProfileID() << "\t up-coast profile = " << nUpCoastProfile << "\t down-coast profile = " << nDownCoastProfile << endl;
- // }
- // LogStream << endl;
- // // DEBUG CODE =======================================================================================================================
-
- // // DEBUG CODE =======================================================================================================================
- // int nProf = 0;
- // for (int n = 0; n < nCoastSize; n++)
- // {
- // // LogStream << n << "\t";
- //
- // // LogStream << m_VCoast[nCoast].dGetDetailedCurvature(n) << "\t";
- // //
- // // LogStream << m_VCoast[nCoast].dGetSmoothCurvature(n) << "\t";
- // //
- // // if (m_VCoast[nCoast].pGetCoastLandform(n)->nGetLandFormCategory() == LF_INTERVENTION)
- // // LogStream << "I\t";
- //
- // if (m_VCoast[nCoast].bIsProfileAtCoastPoint(n))
- // {
- // CGeomProfile* pProfile = m_VCoast[nCoast].pGetProfileAtCoastPoint(n);
- //
- // LogStream << "profile " << pProfile->nGetProfileID() << " at coast point " << n << " adjacent up-coast profile = " << pProfile->pGetUpCoastAdjacentProfile() << " adjacent down-coast profile = " << pProfile->pGetDownCoastAdjacentProfile() << endl;
- //
- // nProf++;
- // }
- // }
- // LogStream << endl;
- // LogStream << "nProf = " << nProf << endl;
- // // DEBUG CODE =======================================================================================================================
-
- // // DEBUG CODE =======================================================================================================================
- // LogStream << "=====================" << endl;
- // for (int n = 0; n < m_VCoast[nCoast].nGetNumProfiles(); n++)
- // {
- // CGeomProfile* pProfile = m_VCoast[nCoast].pGetProfileWithDownCoastSeq(n);
- // int nStartPoint = pProfile->nGetCoastPoint();
- //
- // LogStream << n << "\t nCoastID = " << pProfile->nGetProfileID() << "\tnStartPoint = " << nStartPoint << endl;
- // }
- // LogStream << endl;
- // LogStream << "=====================" << endl;
- // // DEBUG CODE =======================================================================================================================
- }
-
- return RTN_OK;
-}
-
-//===============================================================================================================================
-//! For a single coastline, locate the start points for all coastline-normal profiles (except the grid-edge profiles). Then create the profiles
-//===============================================================================================================================
-void CSimulation::LocateAndCreateProfiles(int const nCoast, int& nProfile, vector* pbVCoastPointDone, vector> const* prVCurvature)
-{
- int const nCoastSize = m_VCoast[nCoast].nGetCoastlineSize();
-
- // Work along the vector of curvature pairs starting at the convex end
- for (int n = nCoastSize - 1; n >= 0;
- n--)
- {
- // Have we searched all the coastline points?
- int nStillToSearch = 0;
-
- for (int m = 0; m < nCoastSize; m++)
- if (! pbVCoastPointDone->at(m))
- nStillToSearch++;
-
- if (nStillToSearch == 0)
- // OK we are done here
- return;
-
- // This convex point on the coastline is a potential location for a normal
- int const nNormalPoint = prVCurvature->at(n).first;
-
- // Ignore each end of the coastline
- if ((nNormalPoint == 0) || (nNormalPoint == nCoastSize - 1))
- continue;
-
- // TODO 089 When choosing locations for profiles, do coast first then interventions
-
- if (! pbVCoastPointDone->at(nNormalPoint))
- {
- // We have not already searched this coast point. Is it an intervention coast point?
- bool bIntervention = false;
-
- int const nCat = m_VCoast[nCoast].pGetCoastLandform(nNormalPoint)->nGetLandFormCategory();
- if ((nCat == LF_INTERVENTION_STRUCT) || (nCat == LF_INTERVENTION_NON_STRUCT))
- {
- // It is an intervention
- bIntervention = true;
- }
-
- CGeom2DIPoint const PtiThis = *m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(nNormalPoint);
-
- // Create a profile here
- int const nRet = nCreateProfile(nCoast, nCoastSize, nNormalPoint, nProfile, bIntervention, &PtiThis);
-
- // // DEBUG CODE =================
- // LogStream << "After nCreateProfile() ===========" << endl;
- // CGeomProfile* pProfile = m_VCoast[nCoast].pGetProfile(nProfile);
- // LogStream << pProfile->nGetProfileID() << "\t";
- //
- // int nPointsInProfile = pProfile->nGetProfileSize();
- //
- // for (int nPoint = 0; nPoint < nPointsInProfile; nPoint++)
- // {
- // CGeom2DPoint Pt = *pProfile->pPtGetPointInProfile(nPoint);
- // LogStream << " {" << Pt.dGetX() << ", " << Pt.dGetY() << "}";
- // }
- // LogStream << endl << "===========" << endl;
- // // DEBUG CODE =================
-
- // Mark this coast point as searched
- pbVCoastPointDone->at(nNormalPoint) = true;
-
- if (nRet != RTN_OK)
- {
- // This potential profile is no good (has hit coast, or hit dry land, etc.) so forget about it
- // LogStream << "Profile is no good" << endl;
- continue;
- }
-
- // // DEBUG CODE ===================================================================================================
- // LogStream << endl << "===========================================================================================" << endl;
- // LogStream << "PROFILES JUST AFTER CREATION" << endl;
- // int nNumProfiles = m_VCoast[nCoast].nGetNumProfiles();
- // for (int nn = 0; nn < nNumProfiles; nn++)
- // {
- // CGeomProfile* pProfile = m_VCoast[nCoast].pGetProfile(nn);
- //
- // LogStream << nn << " nCoastID = " << pProfile->nGetProfileID() << " nGlobalID = " << pProfile->nGetProfileID() << " nGetCoastPoint = " << pProfile->nGetCoastPoint() << " pGetUpCoastAdjacentProfile = " << pProfile->pGetUpCoastAdjacentProfile() << " pGetDownCoastAdjacentProfile = " << pProfile->pGetDownCoastAdjacentProfile() << endl;
- // }
- // LogStream << "===================================================================================================" << endl << endl;
- // // DEBUG CODE ===================================================================================================
- //
- // // DEBUG CODE ===================================================================================================
- // LogStream << "++++++++++++++++++++++" << endl;
- // LogStream << endl << "Just created profile " << nProfile << endl;
- // int nProf = 0;
- // for (int nnn = 0; nnn < nCoastSize; nnn++)
- // {
- // if (m_VCoast[nCoast].bIsProfileAtCoastPoint(nnn))
- // {
- // CGeomProfile* pProfile = m_VCoast[nCoast].pGetProfileAtCoastPoint(nnn);
- //
- // LogStream << "profile " << pProfile->nGetProfileID() << " at coast point " << nnn << " adjacent up-coast profile = " << pProfile->pGetUpCoastAdjacentProfile() << " adjacent down-coast profile = " << pProfile->pGetDownCoastAdjacentProfile() << endl;
- //
- // nProf++;
- // }
- // }
- // LogStream << endl;
- // LogStream << "nProf = " << nProf << endl;
- // LogStream << "++++++++++++++++++++++" << endl;
- // // DEBUG CODE ===================================================================================================
-
- // CGeom2DPoint PtThis = *m_VCoast[nCoast].pPtGetCoastlinePointExtCRS(nNormalPoint);
- // if (m_nLogFileDetail >= LOG_FILE_ALL)
- // LogStream << m_ulIter << ": \tcoast " << nCoast << " profile " << nProfile << " created at coast point " << nNormalPoint << " [" << PtiThis.nGetX() << "][" << PtiThis.nGetY() << "] = {" << PtThis.dGetX() << ", " << PtThis.dGetY() << "} (smoothed curvature = " << m_VCoast[nCoast].dGetSmoothCurvature(nNormalPoint) << ", detailed curvature = " << m_VCoast[nCoast].dGetDetailedCurvature(nNormalPoint) << ")" << endl;
-
- // // DEBUG CODE =================================================================================
- // if (m_pRasterGrid->m_Cell[PtiThis.nGetX()][PtiThis.nGetY()].bIsCoastline())
- // LogStream << m_ulIter << ": cell[" << PtiThis.nGetX() << "][" << PtiThis.nGetY() << "] IS coastline, coast number = " << m_pRasterGrid->m_Cell[PtiThis.nGetX()][PtiThis.nGetY()].nGetCoastline() << endl;
- // else
- // LogStream << m_ulIter << ": ******* cell[" << PtiThis.nGetX() << "][" << PtiThis.nGetY() << "] IS NOT coastline" << endl;
- // // DEBUG CODE =================================================================================
-
- // This profile is fine
- nProfile++;
-
- // We need to mark points on either side of this profile so that we don't get profiles which are too close together. However best-placed profiles on narrow intervention structures may need to be quite closes
- double dNumToMark = m_nCoastNormalSpacing;
-
- if (bIntervention)
- dNumToMark = m_nCoastNormalInterventionSpacing;
-
- // If we have a random factor for profile spacing, then modify the profile spacing
- if (m_dCoastNormalRandSpacingFactor > 0)
- {
- // Draw a sample from the unit normal distribution using random number generator 0
- double const dRand = m_dGetFromUnitNormalDist(m_Rand[0]);
-
- double const dTmp = dRand * m_dCoastNormalRandSpacingFactor * dNumToMark;
- dNumToMark += dTmp;
-
- // Make sure number to mark is not too small or too big TODO 011
- if (bIntervention)
- {
- dNumToMark = tMin(dNumToMark, m_nCoastNormalInterventionSpacing * 0.75);
- dNumToMark = tMax(dNumToMark, m_nCoastNormalInterventionSpacing * 1.25);
- }
-
- else
- {
- dNumToMark = tMin(dNumToMark, m_nCoastNormalSpacing * 0.75);
- dNumToMark = tMax(dNumToMark, m_nCoastNormalSpacing * 1.25);
- }
-
- // TODO 014 Assume that the above is the profile spacing on straight bits of coast. Try gradually increasing the profile spacing with increasing concavity, and decreasing the profile spacing with increasing convexity. Could use a Michaelis-Menten S-curve relationship for this i.e.
- // double fReN = pow(NowCell[nX][nY].dGetReynolds(m_dNu), m_dDepN);
- // double fC1 = m_dC1Laminar - ((m_dC1Diff * fReN) / (fReN + m_dReMidN));
- }
-
- // Mark points on either side of the profile
- for (int m = 1; m < dNumToMark; m++)
- {
- int nTmpPoint = nNormalPoint + m;
-
- if (nTmpPoint < nCoastSize)
- pbVCoastPointDone->at(nTmpPoint) = true;
-
- nTmpPoint = nNormalPoint - m;
-
- if (nTmpPoint >= 0)
- pbVCoastPointDone->at(nTmpPoint) = true;
- }
- }
- }
-}
-
-//===============================================================================================================================
-//! Creates a single coastline-normal profile (which may be an intervention profile)
-//===============================================================================================================================
-int CSimulation::nCreateProfile(int const nCoast, int const nCoastSize, int const nProfileStartPoint, int const nProfile, bool const bIntervention, CGeom2DIPoint const* pPtiStart)
-{
- // OK, we have flagged the start point of this new coastline-normal profile, so create it. Make the start of the profile the centroid of the actual cell that is marked as coast (not the cell under the smoothed vector coast, they may well be different)
- CGeom2DPoint PtStart; // In external CRS
- PtStart.SetX(dGridCentroidXToExtCRSX(pPtiStart->nGetX()));
- PtStart.SetY(dGridCentroidYToExtCRSY(pPtiStart->nGetY()));
-
- CGeom2DPoint PtEnd; // In external CRS
- CGeom2DIPoint PtiEnd; // In grid CRS
- int const nRet = nGetCoastNormalEndPoint(nCoast, nProfileStartPoint, nCoastSize, &PtStart, m_dCoastNormalLength, &PtEnd, &PtiEnd, bIntervention);
- if (nRet == RTN_ERR_NO_SOLUTION_FOR_ENDPOINT)
- {
- // Could not solve end-point equation, so forget about this profile
- return nRet;
- }
-
- int const nXEnd = PtiEnd.nGetX();
- int const nYEnd = PtiEnd.nGetY();
-
- // Safety check: is the end point in the contiguous sea?
- if (! m_pRasterGrid->m_Cell[nXEnd][nYEnd].bIsInContiguousSea())
- {
- // if (m_nLogFileDetail >= LOG_FILE_ALL)
- // LogStream << m_ulIter << ": coast " << nCoast << ", possible profile with start point " << nProfileStartPoint << " has inland end point at [" << nXEnd << "][" << nYEnd << "] = {" << dGridCentroidXToExtCRSX(nXEnd) << ", " << dGridCentroidYToExtCRSY(nYEnd) << "}, ignoring" << endl;
-
- return RTN_ERR_PROFILE_ENDPOINT_IS_INLAND;
- }
-
- // Safety check: is the water depth at the end point less than the depth of closure?
- if (m_pRasterGrid->m_Cell[nXEnd][nYEnd].dGetSeaDepth() < m_dDepthOfClosure)
- {
- // if (m_nLogFileDetail >= LOG_FILE_ALL)
- // LogStream << m_ulIter << ": coast " << nCoast << ", possible profile with start point " << nProfileStartPoint << " is too short for depth of closure " << m_dDepthOfClosure << " at end point [" << nXEnd << "][" << nYEnd << "] = {" << dGridCentroidXToExtCRSX(nXEnd) << ", " << dGridCentroidYToExtCRSY(nYEnd) << "}, ignoring" << endl;
-
- return RTN_ERR_PROFILE_END_INSUFFICIENT_DEPTH;
- }
-
- // No problems, so create the new profile
- CGeomProfile* pProfile = new CGeomProfile(nCoast, nProfileStartPoint, nProfile, bIntervention);
-
- // And create the profile's coastline-normal vector. Only two points (start and end points, both external CRS) are stored
- vector VNormal;
- VNormal.push_back(PtStart);
- VNormal.push_back(PtEnd);
-
- // Set the start and end points (external CRS) of the profile
- pProfile->SetPointsInProfile(&VNormal);
-
- // Create the profile's CGeomMultiLine then set nProfile as the only co-incident profile of the only line segment
- pProfile->AppendLineSegment();
- pProfile->AppendCoincidentProfileToLineSegments(make_pair(nProfile, 0));
-
- // Save the profile, note that several fields in the profile are still blank
- m_VCoast[nCoast].AppendProfile(pProfile);
-
- // // DEBUG CODE =================
- // LogStream << "in nCreateProfile() ===========" << endl;
- // // CGeomProfile* pProfile = m_VCoast[nCoast].pGetProfile(nProfile);
- // LogStream << pProfile->nGetProfileID() << "\t";
- //
- // int nPointsInProfile = pProfile->nGetProfileSize();
- //
- // for (int nPoint = 0; nPoint < nPointsInProfile; nPoint++)
- // {
- // CGeom2DPoint Pt = *pProfile->pPtGetPointInProfile(nPoint);
- // LogStream << " {" << Pt.dGetX() << ", " << Pt.dGetY() << "}";
- // }
- // LogStream << endl << "===========" << endl;
- // // DEBUG CODE =================
-
- // assert(pProfile->nGetProfileSize() > 0);
-
- LogStream << m_ulIter << ": \tcoast " << nCoast << " profile " << nProfile << " created at coast point " << nProfileStartPoint << " from [" << pPtiStart->nGetX() << "][" << pPtiStart->nGetY() << "] = {" << PtStart.dGetX() << ", " << PtStart.dGetY() << "} to [" << PtiEnd.nGetX() << "][" << PtiEnd.nGetY() << "] = {" << PtEnd.dGetX() << ", " << PtEnd.dGetY() << "}" << (pProfile->bIsIntervention() ? ", from intervention" : "") << endl;
-
- return RTN_OK;
-}
-
-//===============================================================================================================================
-//! Creates a 'special' profile at each end of a coastline, at the edge of the raster grid. This profile is not necessarily normal to the coastline since it goes along the grid's edge
-//===============================================================================================================================
-int CSimulation::nLocateAndCreateGridEdgeProfile(bool const bCoastStart, int const nCoast, int& nProfile)
-{
- int const nCoastSize = m_VCoast[nCoast].nGetCoastlineSize();
- int const nHandedness = m_VCoast[nCoast].nGetSeaHandedness();
- int const nProfileLen = nRound(m_dCoastNormalLength / m_dCellSide); // Profile length in grid CRS
- int nProfileStartEdge;
-
- CGeom2DIPoint PtiProfileStart; // In grid CRS
- vector VPtiNormalPoints; // In grid CRS
-
- if (bCoastStart)
- {
- // At start of coast
- PtiProfileStart = *m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(0); // Grid CRS
- nProfileStartEdge = m_VCoast[nCoast].nGetStartEdge();
- }
- else
- {
- // At end of coast
- PtiProfileStart = *m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(nCoastSize - 1); // Grid CRS
- nProfileStartEdge = m_VCoast[nCoast].nGetEndEdge();
- }
-
- VPtiNormalPoints.push_back(PtiProfileStart);
-
- // Find the start cell in the list of edge cells
- auto it = find(m_VEdgeCell.begin(), m_VEdgeCell.end(), PtiProfileStart);
-
- if (it == m_VEdgeCell.end())
- {
- // Not found. This can happen because of rounding problems, i.e. the cell which was stored as the first cell of the raster coastline
- if (m_nLogFileDetail >= LOG_FILE_MIDDLE_DETAIL)
- LogStream << m_ulIter << ": " << ERR << " when constructing start-of-coast profile, [" << PtiProfileStart.nGetX() << "][" << PtiProfileStart.nGetY() << "] = {" << dGridCentroidXToExtCRSX(PtiProfileStart.nGetX()) << ", " << dGridCentroidYToExtCRSY(PtiProfileStart.nGetY()) << "} not found in list of edge cells" << endl;
-
- return RTN_ERR_COAST_CANT_FIND_EDGE_CELL;
- }
-
- // Found
- int nPos = static_cast(it - m_VEdgeCell.begin());
-
- // Now construct the edge profile, searching for edge cells
- for (int n = 0; n < nProfileLen; n++)
- {
- if (bCoastStart)
- {
- // At start of coast
- if (nHandedness == LEFT_HANDED)
- {
- // The list of edge cells is in clockwise sequence, go in this direction
- nPos++;
-
- if (nPos >= static_cast(m_VEdgeCell.size()))
- {
- // We've reached the end of the list of edge cells before the profile is long enough. OK, we can live with this
- break;
- }
- }
- else // Right-handed
- {
- // The list of edge cells is in clockwise sequence, go in the opposite direction
- nPos--;
-
- if (nPos < 0)
- {
- // We've reached the beginning of the list of edge cells before the profile is long enough. OK, we can live with this
- break;
- }
- }
- }
- else
- {
- // At end of coast
- if (nHandedness == LEFT_HANDED)
- {
- // The list of edge cells is in clockwise sequence, go in the opposite direction
- nPos--;
-
- if (nPos < 0)
- {
- // We've reached the beginning of the list of edge cells before the profile is long enough. OK, we can live with this
- break;
- }
- }
- else // Right-handed
- {
- // The list of edge cells is in clockwise sequence, go in this direction
- nPos++;
-
- if (nPos >= static_cast(m_VEdgeCell.size()))
- {
- // We've reached the end of the list of edge cells before the profile is long enough. OK, we can live with this
- break;
- }
- }
- }
-
- if (m_VEdgeCellEdge[nPos] != nProfileStartEdge)
- {
- // We've reached the end of a grid side before the profile is long enough. OK, we can live with this
- break;
- }
-
- // All OK, so append this grid-edge cell, making sure that there is no gap between this and the previously-appended cell (if there is, will get problems with cell-by-cell fill)
- AppendEnsureNoGap(&VPtiNormalPoints, &m_VEdgeCell[nPos]);
- }
-
- int nProfileStartPoint;
- CGeomProfile* pProfile;
- CGeom2DIPoint const PtiDummy(INT_NODATA, INT_NODATA);
-
- if (bCoastStart)
- {
- nProfileStartPoint = 0;
-
- // Create the new start-of-coast profile
- pProfile = new CGeomProfile(nCoast, nProfileStartPoint, nProfile, false);
-
- // Mark this as a start-of-coast profile
- pProfile->SetStartOfCoast(true);
- }
- else
- {
- nProfileStartPoint = nCoastSize - 1;
-
- // Create the new end-of-coast profile
- pProfile = new CGeomProfile(nCoast, nProfileStartPoint, nProfile, false);
-
- // Mark this as an end-of-coast profile
- pProfile->SetEndOfCoast(true);
- }
-
- // Create the list of cells 'under' this grid-edge profile. Note that more than two cells are stored
- for (unsigned int n = 0; n < VPtiNormalPoints.size(); n++)
- {
- int const nX = VPtiNormalPoints[n].nGetX();
- int const nY = VPtiNormalPoints[n].nGetY();
-
- // Mark each cell in the raster grid
- m_pRasterGrid->m_Cell[nX][nY].SetCoastAndProfileID(nCoast, nProfile);
-
- // Store the raster grid coordinates in the profile object
- pProfile->AppendCellInProfile(nX, nY);
-
- CGeom2DPoint const Pt(dGridCentroidXToExtCRSX(nX), dGridCentroidYToExtCRSY(nY)); // In external CRS
-
- // Store the external coordinates in the profile object. Note that for this grid-edge profile, the coordinates of the cells and the coordinates of points on the profile itself are identical, this is not the case for ordinary profiles
- pProfile->AppendPointInProfile(&Pt);
- }
-
- int const nEndX = VPtiNormalPoints.back().nGetX();
- int const nEndY = VPtiNormalPoints.back().nGetY();
-
- // Get the deep water wave height and orientation values at the end of the profile
- double const dDeepWaterWaveHeight = m_pRasterGrid->m_Cell[nEndX][nEndY].dGetCellDeepWaterWaveHeight();
- double const dDeepWaterWaveAngle = m_pRasterGrid->m_Cell[nEndX][nEndY].dGetCellDeepWaterWaveAngle();
- double const dDeepWaterWavePeriod = m_pRasterGrid->m_Cell[nEndX][nEndY].dGetCellDeepWaterWavePeriod();
-
- // And store them in this profile
- pProfile->SetProfileDeepWaterWaveHeight(dDeepWaterWaveHeight);
- pProfile->SetProfileDeepWaterWaveAngle(dDeepWaterWaveAngle);
- pProfile->SetProfileDeepWaterWavePeriod(dDeepWaterWavePeriod);
-
- // Create the profile's CGeomMultiLine then set nProfile as the only co-incident profile of the only line segment
- pProfile->AppendLineSegment();
- pProfile->AppendCoincidentProfileToLineSegments(make_pair(nProfile, 0));
-
- // Store the grid-edge profile
- m_VCoast[nCoast].AppendProfile(pProfile);
- m_VCoast[nCoast].SetProfileAtCoastPoint(nProfileStartPoint, pProfile);
-
- if (m_nLogFileDetail >= LOG_FILE_ALL)
- LogStream << m_ulIter << ": \tcoast " << nCoast << " grid-edge profile " << nProfile << " created at coast " << (bCoastStart ? "start" : "end") << " point " << (bCoastStart ? 0 : nCoastSize - 1) << ", from [" << PtiProfileStart.nGetX() << "][" << PtiProfileStart.nGetY() << "] = {" << dGridCentroidXToExtCRSX(PtiProfileStart.nGetX()) << ", " << dGridCentroidYToExtCRSY(PtiProfileStart.nGetY()) << "} to [" << VPtiNormalPoints.back().nGetX() << "][" << VPtiNormalPoints.back().nGetY() << "] = {" << dGridCentroidXToExtCRSX(VPtiNormalPoints.back().nGetX()) << ", " << dGridCentroidYToExtCRSY(VPtiNormalPoints.back().nGetY()) << "}" << endl;
-
- // assert(pProfile->nGetProfileSize() > 0);
-
- return RTN_OK;
-}
-
-//===============================================================================================================================
-//! Finds the end point of a coastline-normal line, given the start point on the vector coastline. If however the start point is on the grid edge (only applicable to cliff collapse [rofiles), then the end point is also on the grid edge, and the line joining the start and end points is not necessarily normal to the vector coast. All input coordinates are in the external CRS
-//===============================================================================================================================
-int CSimulation::nGetCoastNormalEndPoint(int const nCoast, int const nStartCoastPoint, int const nCoastSize, CGeom2DPoint const* pPtStart, double const dLineLength, CGeom2DPoint* pPtEnd, CGeom2DIPoint* pPtiEnd, bool const bIntervention)
-{
- int const AVGSIZE = 21; // TODO 011 This should be a user input
-
- double dXEnd1 = 0;
- double dXEnd2 = 0;
- double dYEnd1 = 0;
- double dYEnd2 = 0;
-
- CGeom2DPoint PtBefore;
- CGeom2DPoint PtAfter;
-
- if (bIntervention)
- {
- // This is an intervention profile, so just use one point on either side (coordinates in external CRS). TODO Note this this assumes that this intervention profile is not at the start or end of the coastline
- PtBefore = *m_VCoast[nCoast].pPtGetCoastlinePointExtCRS(nStartCoastPoint - 1);
- PtAfter = *m_VCoast[nCoast].pPtGetCoastlinePointExtCRS(nStartCoastPoint + 1);
- }
- else
- {
- // This is not an intervention profile. It could be a cliff collapse profile, which could be a grid-edge profile
- double const dXStart = pPtStart->dGetX();
- double const dYStart = pPtStart->dGetY();
-
- int const nXStart = nRound(dExtCRSXToGridX(dXStart));
- int const nYStart = nRound(dExtCRSYToGridY(dYStart));
- int const nLineLength = nConvertMetresToNumCells(dLineLength);
-
- // LogStream << nXStart << ", " << nYStart << endl;
- if ((nXStart == 0) || (nXStart == m_nXGridSize-1))
- {
- // Yes it is a grid-edge profile
- dXEnd1 = dGridXToExtCRSX(nXStart);
- dXEnd2 = dXEnd1;
-
- dYEnd1 = dGridYToExtCRSY(nYStart + nLineLength);
- dYEnd2 = dGridYToExtCRSY(nYStart - nLineLength);
- }
- else if ((nYStart == 0) || (nYStart == m_nYGridSize-1))
- {
- // Yes it is a grid-edge profile
- dYEnd1 = dGridYToExtCRSY(nYStart);
- dYEnd2 = dYEnd1;
-
- dXEnd1 = dGridXToExtCRSX(nXStart + nLineLength);
- dXEnd2 = dGridXToExtCRSX(nXStart - nLineLength);
- }
- else
- {
- // This is not a grid-edge profile, so put a maximum of AVGSIZE points before the start point into a vector
- vector VPtBeforeToAverage;
-
- for (int n = 1; n <= AVGSIZE; n++)
- {
- int const nPoint = nStartCoastPoint - n;
- if (nPoint < 0)
- break;
-
- VPtBeforeToAverage.push_back(*m_VCoast[nCoast].pPtGetCoastlinePointExtCRS(nPoint));
- }
-
- // Put a maximum of AVGSIZE points after the start point into a vector
- vector VPtAfterToAverage;
-
- for (int n = 1; n <= AVGSIZE; n++)
- {
- int const nPoint = nStartCoastPoint + n;
- if (nPoint > nCoastSize - 1)
- break;
-
- VPtAfterToAverage.push_back(*m_VCoast[nCoast].pPtGetCoastlinePointExtCRS(nPoint));
- }
-
- // Now average each of these vectors of points: results are in PtBefore and PtAfter (coordinates in external CRS)
- PtBefore = PtAverage(&VPtBeforeToAverage);
- PtAfter = PtAverage(&VPtAfterToAverage);
-
- // Get the y = a * x + b equation of the straight line linking the coastline points before and after 'this' coastline point. For this linking line, slope a = (y2 - y1) / (x2 - x1)
- double const dYDiff = PtAfter.dGetY() - PtBefore.dGetY();
- double const dXDiff = PtAfter.dGetX() - PtBefore.dGetX();
-
- if (bFPIsEqual(dYDiff, 0.0, TOLERANCE))
- {
- // The linking line runs W-E or E-W, so a straight line at right angles to this runs N-S or S-N. Calculate the two possible end points for this coastline-normal profile
- dXEnd1 = dXEnd2 = pPtStart->dGetX();
- dYEnd1 = pPtStart->dGetY() + dLineLength;
- dYEnd2 = pPtStart->dGetY() - dLineLength;
- }
- else if (bFPIsEqual(dXDiff, 0.0, TOLERANCE))
- {
- // The linking line runs N-S or S-N, so a straight line at right angles to this runs W-E or E-W. Calculate the two possible end points for this coastline-normal profile
- dYEnd1 = dYEnd2 = pPtStart->dGetY();
- dXEnd1 = pPtStart->dGetX() + dLineLength;
- dXEnd2 = pPtStart->dGetX() - dLineLength;
- }
- else
- {
- // The linking line runs neither W-E nor N-S so we have to work a bit harder to find the end-point of the coastline-normal profile
- double const dA = dYDiff / dXDiff;
-
- // Now calculate the equation of the straight line which is perpendicular to this linking line
- double const dAPerp = -1 / dA;
- double const dBPerp = pPtStart->dGetY() - (dAPerp * pPtStart->dGetX());
-
- // Calculate the end point of the profile: first do some substitution then rearrange as a quadratic equation i.e. in the form Ax^2 + Bx + C = 0 (see http://math.stackexchange.com/questions/228841/how-do-i-calculate-the-intersections-of-a-straight-line-and-a-circle)
- double const dQuadA = 1 + (dAPerp * dAPerp);
- double const dQuadB = 2 * ((dBPerp * dAPerp) - (dAPerp * pPtStart->dGetY()) - pPtStart->dGetX());
- double const dQuadC = ((pPtStart->dGetX() * pPtStart->dGetX()) + (pPtStart->dGetY() * pPtStart->dGetY()) + (dBPerp * dBPerp) - (2 * pPtStart->dGetY() * dBPerp) - (dLineLength * dLineLength));
-
- // Solve for x and y using the quadratic formula x = (−B ± sqrt(B^2 − 4AC)) / 2A
- double const dDiscriminant = (dQuadB * dQuadB) - (4 * dQuadA * dQuadC);
-
- if (dDiscriminant < 0)
- {
- LogStream << ERR << "timestep " << m_ulIter << ": discriminant < 0 when finding profile end point on coastline " << nCoast << ", from coastline point " << nStartCoastPoint << "), ignored" << endl;
- return RTN_ERR_NO_SOLUTION_FOR_ENDPOINT;
- }
-
- dXEnd1 = (-dQuadB + sqrt(dDiscriminant)) / (2 * dQuadA);
- dYEnd1 = (dAPerp * dXEnd1) + dBPerp;
- dXEnd2 = (-dQuadB - sqrt(dDiscriminant)) / (2 * dQuadA);
- dYEnd2 = (dAPerp * dXEnd2) + dBPerp;
- }
- }
- }
-
- // We have two possible solutions, so decide which of the two endpoints to use then create the profile end-point (coordinates in external CRS)
- int const nSeaHand = m_VCoast[nCoast].nGetSeaHandedness(); // Assumes handedness is either 0 or 1 (i.e. not -1)
- *pPtEnd = PtChooseEndPoint(nSeaHand, &PtBefore, &PtAfter, dXEnd1, dYEnd1, dXEnd2, dYEnd2);
-
- // Check that pPtiEnd is not off the grid. Note that pPtiEnd is not necessarily a cell centroid
- pPtiEnd->SetXY(nRound(dExtCRSXToGridX(pPtEnd->dGetX())), nRound(dExtCRSYToGridY(pPtEnd->dGetY())));
-
- if (! bIsWithinValidGrid(pPtiEnd))
- {
- // LogStream << m_ulIter << ": profile endpoint is outside grid [" << pPtiEnd->nGetX() << "][" << pPtiEnd->nGetY() << "] = {" << pPtEnd->dGetX() << ", " << pPtEnd->dGetY() << "}. The profile starts at coastline point " << nStartCoastPoint << " = {" << pPtStart->dGetX() << ", " << pPtStart->dGetY() << "}" << endl;
-
- // The end point is off the grid, so constrain it to be within the valid grid
- CGeom2DIPoint const PtiStart(nRound(dExtCRSXToGridX(pPtStart->dGetX())), nRound(dExtCRSYToGridY(pPtStart->dGetY())));
- KeepWithinValidGrid(&PtiStart, pPtiEnd);
-
- pPtEnd->SetX(dGridCentroidXToExtCRSX(pPtiEnd->nGetX()));
- pPtEnd->SetY(dGridCentroidYToExtCRSY(pPtiEnd->nGetY()));
-
- // LogStream << m_ulIter << ": \tcoast " << nCoast << " profile endpoint constrained to be within grid, is now [" << pPtiEnd->nGetX() << "][" << pPtiEnd->nGetY() << "] = {" << pPtEnd->dGetX() << ", " << pPtEnd->dGetY() << "}. The profile starts at coastline point " << nStartCoastPoint << " = {" << pPtStart->dGetX() << ", " << pPtStart->dGetY() << "}" << endl;
- }
-
- return RTN_OK;
-}
-
-//===============================================================================================================================
-//! Choose which end point to use for the coastline-normal profile
-//===============================================================================================================================
-CGeom2DPoint CSimulation::PtChooseEndPoint(int const nHand, CGeom2DPoint const* PtBefore, CGeom2DPoint const* PtAfter, double const dXEnd1, double const dYEnd1, double const dXEnd2, double const dYEnd2)
-{
- CGeom2DPoint PtChosen;
-
- // All coordinates here are in the external CRS, so the origin of the grid is the bottom left
- if (nHand == RIGHT_HANDED)
- {
- // The sea is to the right of the linking line. So which way is the linking line oriented? First check the N-S component
- if (PtAfter->dGetY() > PtBefore->dGetY())
- {
- // We are going S to N and the sea is to the right: the normal endpoint is to the E. We want the larger of the two x values
- if (dXEnd1 > dXEnd2)
- {
- PtChosen.SetX(dXEnd1);
- PtChosen.SetY(dYEnd1);
- }
- else
- {
- PtChosen.SetX(dXEnd2);
- PtChosen.SetY(dYEnd2);
- }
- }
- else if (PtAfter->dGetY() < PtBefore->dGetY())
- {
- // We are going N to S and the sea is to the right: the normal endpoint is to the W. We want the smaller of the two x values
- if (dXEnd1 < dXEnd2)
- {
- PtChosen.SetX(dXEnd1);
- PtChosen.SetY(dYEnd1);
- }
- else
- {
- PtChosen.SetX(dXEnd2);
- PtChosen.SetY(dYEnd2);
- }
- }
- else
- {
- // No N-S component i.e. the linking line is exactly W-E. So check the W-E component
- if (PtAfter->dGetX() > PtBefore->dGetX())
- {
- // We are going W to E and the sea is to the right: the normal endpoint is to the s. We want the smaller of the two y values
- if (dYEnd1 < dYEnd2)
- {
- PtChosen.SetX(dXEnd1);
- PtChosen.SetY(dYEnd1);
- }
- else
- {
- PtChosen.SetX(dXEnd2);
- PtChosen.SetY(dYEnd2);
- }
- }
- else // Do not check for (PtAfter->dGetX() == PtBefore->dGetX()), since this would mean the two points are co-incident
- {
- // We are going E to W and the sea is to the right: the normal endpoint is to the N. We want the larger of the two y values
- if (dYEnd1 > dYEnd2)
- {
- PtChosen.SetX(dXEnd1);
- PtChosen.SetY(dYEnd1);
- }
- else
- {
- PtChosen.SetX(dXEnd2);
- PtChosen.SetY(dYEnd2);
- }
- }
- }
- }
- else // nHand == LEFT_HANDED
- {
- // The sea is to the left of the linking line. So which way is the linking line oriented? First check the N-S component
- if (PtAfter->dGetY() > PtBefore->dGetY())
- {
- // We are going S to N and the sea is to the left: the normal endpoint is to the W. We want the smaller of the two x values
- if (dXEnd1 < dXEnd2)
- {
- PtChosen.SetX(dXEnd1);
- PtChosen.SetY(dYEnd1);
- }
- else
- {
- PtChosen.SetX(dXEnd2);
- PtChosen.SetY(dYEnd2);
- }
- }
- else if (PtAfter->dGetY() < PtBefore->dGetY())
- {
- // We are going N to S and the sea is to the left: the normal endpoint is to the E. We want the larger of the two x values
- if (dXEnd1 > dXEnd2)
- {
- PtChosen.SetX(dXEnd1);
- PtChosen.SetY(dYEnd1);
- }
- else
- {
- PtChosen.SetX(dXEnd2);
- PtChosen.SetY(dYEnd2);
- }
- }
- else
- {
- // No N-S component i.e. the linking line is exactly W-E. So check the W-E component
- if (PtAfter->dGetX() > PtBefore->dGetX())
- {
- // We are going W to E and the sea is to the left: the normal endpoint is to the N. We want the larger of the two y values
- if (dYEnd1 > dYEnd2)
- {
- PtChosen.SetX(dXEnd1);
- PtChosen.SetY(dYEnd1);
- }
- else
- {
- PtChosen.SetX(dXEnd2);
- PtChosen.SetY(dYEnd2);
- }
- }
- else // Do not check for (PtAfter->dGetX() == PtBefore->dGetX()), since this would mean the two points are co-incident
- {
- // We are going E to W and the sea is to the left: the normal endpoint is to the S. We want the smaller of the two y values
- if (dYEnd1 < dYEnd2)
- {
- PtChosen.SetX(dXEnd1);
- PtChosen.SetY(dYEnd1);
- }
- else
- {
- PtChosen.SetX(dXEnd2);
- PtChosen.SetY(dYEnd2);
- }
- }
- }
- }
-
- return PtChosen;
-}
-
-//===============================================================================================================================
-//! Checks all coastline-normal profiles for intersection, and modifies those that intersect
-//===============================================================================================================================
-void CSimulation::CheckForIntersectingProfiles(void)
-{
- LogStream << endl << m_ulIter << ": Checking for profile intersection" << endl;
-
- // Do once for every coastline object
- int const nCoastLines = static_cast(m_VCoast.size());
-
- for (int nCoast = 0; nCoast < nCoastLines; nCoast++)
- {
- int const nCoastSize = m_VCoast[nCoast].nGetCoastlineSize();
-
- // Do once for every profile, in along-coast sequence
- for (int nCoastPoint = 0; nCoastPoint < nCoastSize; nCoastPoint++)
- {
- if (! m_VCoast[nCoast].bIsProfileAtCoastPoint(nCoastPoint))
- continue;
-
- // There is a profile at this coast point
- CGeomProfile* pFirstProfile = m_VCoast[nCoast].pGetProfileAtCoastPoint(nCoastPoint);
- int const nFirstProfile = pFirstProfile->nGetProfileID();
-
- // Only check this profile if it is problem free, and is not a start- or end-of-coast profile. Continue checking if it has been truncated, however
- if (! pFirstProfile->bProfileOKIncTruncated())
- {
- // LogStream << m_ulIter << ": nCoastPoint = " << nCoastPoint << " pFirstProfile = " << pFirstProfile->nGetProfileID() << " is not OK (could be a start- or end-of-coast profile), abandoning" << endl;
- continue;
- }
-
- // OK we have found a first profile. Now go along the coast in alternate directions: first down-coast (in the direction of increasing coast point numbers) then up-coast
- for (int nDirection = DIRECTION_DOWNCOAST; nDirection <= DIRECTION_UPCOAST; nDirection++)
- {
- int nStartPoint;
-
- if (nDirection == DIRECTION_DOWNCOAST)
- nStartPoint = nCoastPoint + 1;
- else
- nStartPoint = nCoastPoint - 1;
-
- for (int nSecondCoastPoint = nStartPoint; (nDirection == DIRECTION_DOWNCOAST) ? nSecondCoastPoint < nCoastSize : nSecondCoastPoint >= 0; (nDirection == DIRECTION_DOWNCOAST) ? nSecondCoastPoint++ : nSecondCoastPoint--)
- // // In this direction, look at profiles which are increasingly close to the first profile
- // int nStartPoint;
- // if (nDirection == DIRECTION_DOWNCOAST)
- // nStartPoint = 0;
- // else
- // nStartPoint = nCoastSize - 1;
- //
- // for (int nSecondCoastPoint = nStartPoint; (nDirection == DIRECTION_DOWNCOAST) ? nSecondCoastPoint < nCoastPoint : nSecondCoastPoint > nCoastPoint; (nDirection == DIRECTION_DOWNCOAST) ? nSecondCoastPoint++ : nSecondCoastPoint--)
- {
- if (m_VCoast[nCoast].bIsProfileAtCoastPoint(nSecondCoastPoint))
- {
- // There is a profile at the second coast point, so get a pointer to it
- CGeomProfile* pSecondProfile = m_VCoast[nCoast].pGetProfileAtCoastPoint(nSecondCoastPoint);
- int const nSecondProfile = pSecondProfile->nGetProfileID();
-
- // LogStream << m_ulIter << ": " << (nDirection == DIRECTION_DOWNCOAST ? "down" : "up") << "-coast search, nCoastPoint = " << nCoastPoint << " nSecondCoastPoint = " << nSecondCoastPoint << " (profiles " << pFirstProfile->nGetProfileID() << " and " << pSecondProfile->nGetProfileID() << ")" << endl;
-
- // Only check this profile if it is problem free, and is not a start- or end-of-coast profile. Continue checking if it has been truncated, however
- if (! pSecondProfile->bProfileOKIncTruncated())
- {
- // LogStream << m_ulIter << ": second profile = " << pSecondProfile->nGetProfileID() << " is not OK (could be a start- or end-of-coast profile), abandoning" << endl;
- continue;
- }
-
- // Only check these two profiles for intersection if they are are not co-incident in the final line segment of both profiles (i.e. the profiles have not already intersected)
- if ((pFirstProfile->bFindProfileInCoincidentProfilesOfLastLineSegment(nSecondProfile)) || (pSecondProfile->bFindProfileInCoincidentProfilesOfLastLineSegment(nFirstProfile)))
- {
- // LogStream << m_ulIter << ": profiles " << pFirstProfile->nGetProfileID() << " and " << pSecondProfile->nGetProfileID() << " are are not co-incident in the final line segment of both profiles (i.e. the profiles have not already intersected), abandoning" << endl;
- continue;
- }
-
- // OK go for it
- int nProf1LineSeg = 0;
- int nProf2LineSeg = 0;
- double dIntersectX = 0;
- double dIntersectY = 0;
- double dAvgEndX = 0;
- double dAvgEndY = 0;
-
- if (bCheckForIntersection(pFirstProfile, pSecondProfile, nProf1LineSeg, nProf2LineSeg, dIntersectX, dIntersectY, dAvgEndX, dAvgEndY))
- {
- // The profiles intersect. Decide which profile to truncate, and which to retain
- int nPoint = -1;
-
- if (pFirstProfile->bIsIntervention())
- {
- LogStream << m_ulIter << ": profiles " << nFirstProfile << " and " << nSecondProfile << " intersect, truncate " << nFirstProfile << " since it is an intervention profile" << endl;
-
- // Truncate the first profile, since it is an intervention profile
- TruncateOneProfileRetainOtherProfile(nCoast, pFirstProfile, pSecondProfile, dIntersectX, dIntersectY, nProf1LineSeg, nProf2LineSeg, false);
- }
- else if (pSecondProfile->bIsIntervention())
- {
- LogStream << m_ulIter << ": profiles " << nFirstProfile << " and " << nSecondProfile << " intersect, truncate " << nSecondProfile << " since it is an intervention profile" << endl;
-
- // Truncate the second profile, since it is an intervention profile
- TruncateOneProfileRetainOtherProfile(nCoast, pSecondProfile, pFirstProfile, dIntersectX, dIntersectY, nProf2LineSeg, nProf1LineSeg, false);
- }
- // Is the point of intersection already present in the first profile (i.e. because there has already been an intersection at this point between the first profile and some other profile)?
- else if (pFirstProfile->bIsPointInProfile(dIntersectX, dIntersectY, nPoint))
- {
- LogStream << m_ulIter << ": \t coast " << nCoast << " profiles " << nFirstProfile << " and " << nSecondProfile << " intersect, but point {" << dIntersectX << ", " << dIntersectY << "} is already present in profile " << nFirstProfile << " as point " << nPoint << endl;
-
- // Truncate the second profile and merge it with the first profile
- TruncateOneProfileRetainOtherProfile(nCoast, pSecondProfile, pFirstProfile, dIntersectX, dIntersectY, nProf2LineSeg, nProf1LineSeg, true);
- }
- // Is the point of intersection already present in the second profile?
- else if (pSecondProfile->bIsPointInProfile(dIntersectX, dIntersectY, nPoint))
- {
- LogStream << m_ulIter << ": \tcoast " << nCoast << " profiles " << nFirstProfile << " and " << nSecondProfile << " intersect, but point {" << dIntersectX << ", " << dIntersectY << "} is already present in profile " << nSecondProfile << " as point " << nPoint << endl;
-
- // Truncate the first profile and merge it with the second profile
- TruncateOneProfileRetainOtherProfile(nCoast, pFirstProfile, pSecondProfile, dIntersectX, dIntersectY, nProf1LineSeg, nProf2LineSeg, true);
- }
- else
- {
- // The point of intersection is not already present in either profile, so get the number of line segments of each profile
- int const nFirstProfileLineSegments = pFirstProfile->nGetNumLineSegments();
- int const nSecondProfileLineSegments = pSecondProfile->nGetNumLineSegments();
-
- // assert(nProf1LineSeg < nFirstProfileLineSegments);
- // assert(nProf2LineSeg < nSecondProfileLineSegments);
-
- // Next check whether the point of intersection is on the final line segment of both profiles
- if ((nProf1LineSeg == (nFirstProfileLineSegments - 1)) && (nProf2LineSeg == (nSecondProfileLineSegments - 1)))
- {
- // Yes, the point of intersection is on the final line segment of both profiles, so merge the profiles seaward of the point of intersection
- MergeProfilesAtFinalLineSegments(nCoast, pFirstProfile, pSecondProfile, nFirstProfileLineSegments, nSecondProfileLineSegments, dIntersectX, dIntersectY, dAvgEndX, dAvgEndY);
-
- // LogStream << m_ulIter << ": " << ((nDirection == DIRECTION_DOWNCOAST) ? "down" : "up") << "-coast search, end-segment intersection between profiles " << nFirstProfile << " and " << nSecondProfile << " at [" << dIntersectX << ", " << dIntersectY << "] in line segment [" << nProf1LineSeg << "] of " << nFirstProfileLineSegments << " segments, and line segment [" << nProf2LineSeg << "] of " << nSecondProfileLineSegments << " segments, respectively" << endl;
-
- // // DEBUG CODE =============================================================================================
- // int nSizeTmp = pFirstProfile->nGetProfileSize();
- // CGeom2DPoint PtEndTmp = *pFirstProfile->pPtGetPointInProfile(nSizeTmp-1);
- //
- // LogStream << m_ulIter << ": end of first profile (" << nFirstProfile << ") is point " << nSizeTmp-1 << " at [" << dExtCRSXToGridX(PtEndTmp.dGetX()) << "][" << dExtCRSYToGridY(PtEndTmp.dGetY()) << "} = {" << PtEndTmp.dGetX() << ", " << PtEndTmp.dGetY() << "}" << endl;
- //
- // nSizeTmp = pSecondProfile->nGetProfileSize();
- // PtEndTmp = *pSecondProfile->pPtGetPointInProfile(nSizeTmp-1);
- //
- // LogStream << m_ulIter << ": end of second profile (" << nSecondProfile << ") is point " << nSizeTmp-1 << " at [" << dExtCRSXToGridX(PtEndTmp.dGetX()) << "][" << dExtCRSYToGridY(PtEndTmp.dGetY()) << "} = {" << PtEndTmp.dGetX() << ", " << PtEndTmp.dGetY() << "}" << endl;
- // // DEBUG CODE =============================================================================================
- }
- else
- {
- // The profiles intersect, but the point of intersection is not on the final line segment of both profiles. One of the profiles will be truncated, the other profile will be retained
- // LogStream << m_ulIter << ": " << ((nDirection == DIRECTION_DOWNCOAST) ? "down" : "up") << "-coast search, intersection (NOT both end segments) between profiles " << nFirstProfile << " and " << nSecondProfile << " at [" << dIntersectX << ", " << dIntersectY << "] in line segment [" << nProf1LineSeg << "] of " << nFirstProfileLineSegments << ", and line segment [" << nProf2LineSeg << "] of " << nSecondProfileLineSegments << ", respectively" << endl;
-
- // Decide which profile to truncate, and which to retain
- if (pFirstProfile->bIsIntervention())
- {
- // Truncate the first profile, since it is an intervention profile
- // LogStream << m_ulIter << ": pFirstProfile = " << pFirstProfile->nGetProfileID() << " pSecondProfile = " << pSecondProfile->nGetProfileID() << ", pFirstProfile is an intervention profile, so truncate pFirstProfile (" << pFirstProfile->nGetProfileID() << ")" << endl;
-
- TruncateOneProfileRetainOtherProfile(nCoast, pFirstProfile, pSecondProfile, dIntersectX, dIntersectY, nProf1LineSeg, nProf2LineSeg, false);
- }
- else if (pSecondProfile->bIsIntervention())
- {
- // Truncate the second profile, since it is an intervention profile
- // LogStream << m_ulIter << ": pFirstProfile = " << pFirstProfile->nGetProfileID() << " pSecondProfile = " << pSecondProfile->nGetProfileID() << ", pSecondProfile is an intervention profile, so truncate pSecondProfile (" << pSecondProfile->nGetProfileID() << ")" << endl;
-
- TruncateOneProfileRetainOtherProfile(nCoast, pSecondProfile, pFirstProfile, dIntersectX, dIntersectY, nProf2LineSeg, nProf1LineSeg, false);
- }
- else if (nFirstProfileLineSegments < nSecondProfileLineSegments)
- {
- // Truncate the first profile, since it has a smaller number of line segments
- // LogStream << m_ulIter << ": pFirstProfile = " << pFirstProfile->nGetProfileID() << " pSecondProfile = " << pSecondProfile->nGetProfileID() << ", pFirstProfile has a smaller number of line segments, so truncate pFirstProfile (" << pFirstProfile->nGetProfileID() << ")" << endl;
-
- TruncateOneProfileRetainOtherProfile(nCoast, pFirstProfile, pSecondProfile, dIntersectX, dIntersectY, nProf1LineSeg, nProf2LineSeg, false);
- }
- else if (nFirstProfileLineSegments > nSecondProfileLineSegments)
- {
- // Truncate the second profile, since it has a smaller number of line segments
- // LogStream << m_ulIter << ": pFirstProfile = " << pFirstProfile->nGetProfileID() << " pSecondProfile = " << pSecondProfile->nGetProfileID() << ", pSecondProfile has a smaller number of line segments, so truncate pSecondProfile (" << pSecondProfile->nGetProfileID() << ")" << endl;
-
- TruncateOneProfileRetainOtherProfile(nCoast, pSecondProfile, pFirstProfile, dIntersectX, dIntersectY, nProf2LineSeg, nProf1LineSeg, false);
- }
- else
- {
- // Both profiles have the same number of line segments, so choose randomly. Draw a sample from the unit normal distribution using random number generator 1
- double const dRand = m_dGetFromUnitNormalDist(m_Rand[0]);
-
- if (dRand >= 0.0)
- {
- // LogStream << m_ulIter << ": pFirstProfile = " << pFirstProfile->nGetProfileID() << " pSecondProfile = " << pSecondProfile->nGetProfileID() << ", same number of line segment, randomly truncate pFirstProfile" << endl;
-
- TruncateOneProfileRetainOtherProfile(nCoast, pFirstProfile, pSecondProfile, dIntersectX, dIntersectY, nProf1LineSeg, nProf2LineSeg, false);
- }
- else
- {
- // LogStream << m_ulIter << ": pFirstProfile = " << pFirstProfile->nGetProfileID() << " pSecondProfile = " << pSecondProfile->nGetProfileID() << ", same number of line segment, randomly truncate pSecondProfile" << endl;
-
- TruncateOneProfileRetainOtherProfile(nCoast, pSecondProfile, pFirstProfile, dIntersectX, dIntersectY, nProf2LineSeg, nProf1LineSeg, false);
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
-}
-
-//===============================================================================================================================
-//! Check all coastline-normal profiles and modify the profiles if they intersect, then mark valid profiles on the raster grid
-//===============================================================================================================================
-int CSimulation::nCheckAndMarkAllProfiles(void)
-{
- // Check to see which coastline-normal profiles intersect. Then modify intersecting profiles so that the sections of each profile seaward of the point of intersection are 'shared' i.e. are multi-lines. This creates the boundaries of the triangular polygons
- CheckForIntersectingProfiles();
-
- // Again check the normal profiles for insufficient length: is the water depth at the end point less than the depth of closure? We do this again because some profiles may have been shortened as a result of intersection. Do once for every coastline object
- for (unsigned int nCoast = 0; nCoast < m_VCoast.size(); nCoast++)
- {
- for (int n = 0; n < m_VCoast[nCoast].nGetNumProfiles(); n++)
- {
- CGeomProfile* pProfile = m_VCoast[nCoast].pGetProfileWithDownCoastSeq(n);
- int const nProfile = pProfile->nGetProfileID();
-
- if (pProfile->bProfileOK())
- {
- int const nSize = pProfile->nGetProfileSize();
-
- // Safety check
- if (nSize == 0)
- {
- // pProfile->SetTooShort(true);
- m_VCoast[nCoast].pGetProfile(nProfile)->SetTooShort(true);
- LogStream << "Profile " << nProfile << " is too short, size = " << nSize << endl;
- continue;
- }
-
- CGeom2DPoint const* pPtEnd = pProfile->pPtGetPointInProfile(nSize - 1);
- CGeom2DIPoint const PtiEnd = PtiExtCRSToGridRound(pPtEnd);
- int nXEnd = PtiEnd.nGetX();
- int nYEnd = PtiEnd.nGetY();
-
- // Safety checks: the point may be outside the grid, so keep it within the grid
- nXEnd = tMin(nXEnd, m_nXGridSize - 1);
- nYEnd = tMin(nYEnd, m_nYGridSize - 1);
- nXEnd = tMax(nXEnd, 0);
- nYEnd = tMax(nYEnd, 0);
-
- if (m_pRasterGrid->m_Cell[nXEnd][nYEnd].dGetSeaDepth() < m_dDepthOfClosure)
- {
- if (m_nLogFileDetail >= LOG_FILE_MIDDLE_DETAIL)
- LogStream << m_ulIter << ": coast " << nCoast << ", profile " << nProfile << " is invalid, is too short for depth of closure " << m_dDepthOfClosure << " at end point [" << nXEnd << "][" << nYEnd << "] = {" << pPtEnd->dGetX() << ", " << pPtEnd->dGetY() << "}, flagging as too short" << endl;
-
- // pProfile->SetTooShort(true);
- m_VCoast[nCoast].pGetProfile(nProfile)->SetTooShort(true);
- }
- }
- }
-
- // For this coast, put all valid coastline-normal profiles (apart from the profiles at the start and end of the coast, since they have already been done) onto the raster grid. But if the profile is not long enough, crosses a coastline, hits dry land, or hits another profile, then mark the profile as invalid
- int nValidProfiles = 0;
- MarkProfilesOnGrid(nCoast, nValidProfiles);
-
- if (nValidProfiles == 0)
- {
- // Problem! No valid profiles, so quit
- cerr << m_ulIter << ": " << ERR << "no coastline-normal profiles created" << endl;
- return RTN_ERR_NO_PROFILES_2;
- }
-
- // // DEBUG CODE ===========================================================================================================
- // if (m_ulIter == 109)
- // {
- // string strOutFile = m_strOutPath;
- // strOutFile += "00_profile_raster_";
- // strOutFile += to_string(m_ulIter);
- // strOutFile += ".tif";
- //
- // GDALDriver* pDriver = GetGDALDriverManager()->GetDriverByName("gtiff");
- // GDALDataset* pDataSet = pDriver->Create(strOutFile.c_str(), m_nXGridSize, m_nYGridSize, 1, GDT_Float64, m_papszGDALRasterOptions);
- // pDataSet->SetProjection(m_strGDALBasementDEMProjection.c_str());
- // pDataSet->SetGeoTransform(m_dGeoTransform);
- //
- // int nn = 0;
- // double* pdRaster = new double[m_nXGridSize * m_nYGridSize];
- // for (int nY = 0; nY < m_nYGridSize; nY++)
- // {
- // for (int nX = 0; nX < m_nXGridSize; nX++)
- // {
- // if (m_pRasterGrid->m_Cell[nX][nY].bIsCoastline())
- // pdRaster[nn] = -1;
- // else
- // {
- //
- // // pdRaster[nn] = m_pRasterGrid->m_Cell[nX][nY].nGetPolygonID();
- // pdRaster[nn] = m_pRasterGrid->m_Cell[nX][nY].nGetProfileID();
- // }
- //
- // nn++;
- // }
- // }
- //
- // GDALRasterBand* pBand = pDataSet->GetRasterBand(1);
- // pBand->SetNoDataValue(m_dMissingValue);
- // int nRet1 = pBand->RasterIO(GF_Write, 0, 0, m_nXGridSize, m_nYGridSize, pdRaster, m_nXGridSize, m_nYGridSize, GDT_Float64, 0, 0, NULL);
- //
- // if (nRet1 == CE_Failure)
- // return RTN_ERR_GRIDCREATE;
- //
- // GDALClose(pDataSet);
- // delete[] pdRaster;
- // }
- // // DEBUG CODE ===========================================================================================================
- }
-
- return RTN_OK;
-}
-
-//===============================================================================================================================
-//! Checks all line segments of a pair of coastline-normal profiles for intersection. If the lines intersect, returns true with the numbers of the line segments at which intersection occurs in nProfile1LineSegment and nProfile1LineSegment, the intersection point in dXIntersect and dYIntersect, and the 'average' seaward endpoint of the two intersecting profiles at dXAvgEnd and dYAvgEnd
-//===============================================================================================================================
-bool CSimulation::bCheckForIntersection(CGeomProfile* const pVProfile1, CGeomProfile* const pVProfile2, int& nProfile1LineSegment, int& nProfile2LineSegment, double& dXIntersect, double& dYIntersect, double& dXAvgEnd, double& dYAvgEnd)
-{
- // For both profiles, look at all line segments
- int const nProfile1NumSegments = pVProfile1->nGetNumLineSegments();
- int const nProfile2NumSegments = pVProfile2->nGetNumLineSegments();
- // nProfile1Size = pVProfile1->nGetProfileSize(),
- // nProfile2Size = pVProfile2->nGetProfileSize();
-
- // assert(nProfile1Size == nProfile1NumSegments+1);
- // assert(nProfile2Size == nProfile2NumSegments+1);
-
- for (int i = 0; i < nProfile1NumSegments; i++)
- {
- for (int j = 0; j < nProfile2NumSegments; j++)
- {
- // In external coordinates
- double const dX1 = pVProfile1->pPtVGetPoints()->at(i).dGetX();
- double const dY1 = pVProfile1->pPtVGetPoints()->at(i).dGetY();
- double const dX2 = pVProfile1->pPtVGetPoints()->at(i + 1).dGetX();
- double const dY2 = pVProfile1->pPtVGetPoints()->at(i + 1).dGetY();
-
- double const dX3 = pVProfile2->pPtVGetPoints()->at(j).dGetX();
- double const dY3 = pVProfile2->pPtVGetPoints()->at(j).dGetY();
- double const dX4 = pVProfile2->pPtVGetPoints()->at(j + 1).dGetX();
- double const dY4 = pVProfile2->pPtVGetPoints()->at(j + 1).dGetY();
-
- // Uses Cramer's Rule to solve the equations. Modified from code at http://stackoverflow.com/questions/563198/how-do-you-detect-where-two-line-segments-intersect (in turn based on Andre LeMothe's "Tricks of the Windows Game Programming Gurus")
- double const dDiffX1 = dX2 - dX1;
- double const dDiffY1 = dY2 - dY1;
- double const dDiffX2 = dX4 - dX3;
- double const dDiffY2 = dY4 - dY3;
-
- double dS = -999;
- double dT = -999;
- double dTmp = 0;
-
- dTmp = -dDiffX2 * dDiffY1 + dDiffX1 * dDiffY2;
-
- if (! bFPIsEqual(dTmp, 0.0, TOLERANCE))
- dS = (-dDiffY1 * (dX1 - dX3) + dDiffX1 * (dY1 - dY3)) / dTmp;
-
- dTmp = -dDiffX2 * dDiffY1 + dDiffX1 * dDiffY2;
-
- if (! bFPIsEqual(dTmp, 0.0, TOLERANCE))
- dT = (dDiffX2 * (dY1 - dY3) - dDiffY2 * (dX1 - dX3)) / dTmp;
-
- if (dS >= 0 && dS <= 1 && dT >= 0 && dT <= 1)
- {
- // Collision detected, calculate intersection coordinates
- dXIntersect = dX1 + (dT * dDiffX1);
- dYIntersect = dY1 + (dT * dDiffY1);
-
- // And calc the average end-point coordinates
- dXAvgEnd = (dX2 + dX4) / 2;
- dYAvgEnd = (dY2 + dY4) / 2;
-
- // Get the line segments at which intersection occurred
- nProfile1LineSegment = i;
- nProfile2LineSegment = j;
-
- // LogStream << "\t" << "INTERSECTION dX2 = " << dX2 << " dX4 = " << dX4 << " dY2 = " << dY2 << " dY4 = " << dY4 << endl;
- return true;
- }
- }
- }
-
- // No intersection
- return false;
-}
-
-//===============================================================================================================================
-//! For this coastline, marks all coastline-normal profiles (apart from the two 'special' ones at the start and end of the coast) onto the raster grid, i.e. rasterizes multi-line vector objects onto the raster grid. Note that this doesn't work if the vector has already been interpolated to fit on the grid i.e. if distances between vector points are just one cell apart
-//===============================================================================================================================
-void CSimulation::MarkProfilesOnGrid(int const nCoast, int& nValidProfiles)
-{
- // How many profiles on this coast?
- int const nProfiles = m_VCoast[nCoast].nGetNumProfiles();
-
- if (nProfiles == 0)
- {
- // This can happen if the coastline is very short, so just give a warning and carry on with the next coastline
- if (m_nLogFileDetail >= LOG_FILE_MIDDLE_DETAIL)
- LogStream << WARN << m_ulIter << ": coast " << nCoast << " has no profiles" << endl;
-
- return;
- }
-
- static bool bDownCoast = true;
-
- // Now do this for every profile, alternate between up-coast and down-coast directions
- for (int n = 0; n < nProfiles; n++)
- {
- CGeomProfile* pProfile;
-
- if (bDownCoast)
- pProfile = m_VCoast[nCoast].pGetProfileWithDownCoastSeq(n);
- else
- pProfile = m_VCoast[nCoast].pGetProfileWithUpCoastSeq(n);
-
- // Don't do this for the first and last profiles (i.e. the profiles at the start and end of the coast) since these are put onto the grid elsewhere
- if (pProfile->bIsGridEdge())
- continue;
-
- int const nProfile = pProfile->nGetProfileID();
-
- // If this profile has a problem, then forget about it
- // if (! pProfile->bProfileOK())
- // {
- // LogStream << m_ulIter << ": in MarkProfilesOnGrid() profile " << nProfile << " is not OK" << endl;
- // continue;
- // }
-
- int const nPoints = pProfile->nGetProfileSize();
-
- if (nPoints < 2)
- {
- // Need at least two points in the profile, so this profile is invalid: mark it
- m_VCoast[nCoast].pGetProfile(nProfile)->SetTooShort(true);
-
- if (m_nLogFileDetail >= LOG_FILE_MIDDLE_DETAIL)
- LogStream << m_ulIter << ": coast " << nCoast << ", profile " << nProfile << " is invalid, has only " << nPoints << " points" << endl;
-
- continue;
- }
-
- // OK, go for it: set up temporary vectors to hold the x-y coords (in grid CRS) of the cells which we will mark
- vector VCellsToMark;
- vector bVShared;
- bool bTooShort = false;
- bool bTruncatedSameCoast = false;
- bool bHitCoast = false;
- bool bHitLand = false;
- bool bHitIntervention = false;
- bool bHitAnotherProfile = false;
-
- CreateRasterizedProfile(nCoast, pProfile, &VCellsToMark, &bVShared, bTooShort, bTruncatedSameCoast, bHitCoast, bHitLand, bHitIntervention, bHitAnotherProfile);
-
- if ((bTruncatedSameCoast && (! ACCEPT_TRUNCATED_PROFILES)) || bTooShort || bHitCoast || bHitLand || bHitIntervention || bHitAnotherProfile || VCellsToMark.size() == 0)
- continue;
-
- // This profile is fine
- nValidProfiles++;
-
- for (unsigned int k = 0; k < VCellsToMark.size(); k++)
- {
- // Ignore duplicate points
- if ((k > 0) && (VCellsToMark[k] == m_VCoast[nCoast].pGetProfile(nProfile)->pPtiGetLastCellInProfile()))
- continue;
-
- // Mark each cell in the raster grid
- int const nXTmp = VCellsToMark[k].nGetX();
- int const nYTmp = VCellsToMark[k].nGetY();
- m_pRasterGrid->m_Cell[nXTmp][nYTmp].SetCoastAndProfileID(nCoast, nProfile);
-
- // Store the raster grid coordinates in the profile object
- m_VCoast[nCoast].pGetProfile(nProfile)->AppendCellInProfile(nXTmp, nYTmp);
-
- // Mark the shared (i.e. multi-line) parts of the profile (if any)
- // if (bVShared[k])
- // {
- // m_VCoast[nCoast].pGetProfile(nProfile)->AppendPointShared(true);
- // // LogStream << m_ulIter << ": profile " << j << " point " << k << " marked as shared" << endl;
- // }
- // else
- // {
- // m_VCoast[nCoast].pGetProfile(nProfile)->AppendPointShared(false);
- // // LogStream << m_ulIter << ": profile " << nProfile << " point " << k << " marked as NOT shared" << endl;
- // }
- }
-
- // Get the deep water wave height and orientation values at the end of the profile
- double const dDeepWaterWaveHeight = m_pRasterGrid->m_Cell[VCellsToMark.back().nGetX()][VCellsToMark.back().nGetY()].dGetCellDeepWaterWaveHeight();
- double const dDeepWaterWaveAngle = m_pRasterGrid->m_Cell[VCellsToMark.back().nGetX()][VCellsToMark.back().nGetY()].dGetCellDeepWaterWaveAngle();
- double const dDeepWaterWavePeriod = m_pRasterGrid->m_Cell[VCellsToMark.back().nGetX()][VCellsToMark.back().nGetY()].dGetCellDeepWaterWavePeriod();
-
- // And store them for this profile
- m_VCoast[nCoast].pGetProfile(nProfile)->SetProfileDeepWaterWaveHeight(dDeepWaterWaveHeight);
- m_VCoast[nCoast].pGetProfile(nProfile)->SetProfileDeepWaterWaveAngle(dDeepWaterWaveAngle);
- m_VCoast[nCoast].pGetProfile(nProfile)->SetProfileDeepWaterWavePeriod(dDeepWaterWavePeriod);
- }
-
- bDownCoast = ! bDownCoast;
-}
-
-//===============================================================================================================================
-//! Given a pointer to a coastline-normal profile, returns an output vector of cells which are 'under' every line segment of the profile. If there is a problem with the profile (e.g. a rasterized cell is dry land or coast, or the profile has to be truncated) then we pass this back as an error code
-//===============================================================================================================================
-void CSimulation::CreateRasterizedProfile(int const nCoast, CGeomProfile* pProfile, vector* pVIPointsOut, vector* pbVShared, bool& bTooShort, bool& bTruncatedSameCoast, bool& bHitCoast, bool& bHitLand, bool& bHitIntervention, bool& bHitAnotherProfile)
-{
- int const nProfile = pProfile->nGetProfileID();
- int nSeg = 0;
- int const nNumSegments = pProfile->nGetNumLineSegments();
-
- pVIPointsOut->clear();
-
- // LogStream << m_ulIter << ": in CreateRasterizedProfile() *pPtiStart for profile " << nProfile << " is [" << pPtiStart->nGetX() << "][" << pPtiStart->nGetY() << "]" << endl;
- int nXStartLast = INT_NODATA;
- int nYStartLast = INT_NODATA;
- int nXEndLast = INT_NODATA;
- int nYEndLast = INT_NODATA;
-
- // Do for every segment of this profile
- for (nSeg = 0; nSeg < nNumSegments; nSeg++)
- {
- // Do once for every line segment
- CGeom2DIPoint PtiSegStart;
-
- if (nSeg == 0)
- {
- // If this is the first segment, use the coastline start point to prevent external CRS to grid CRS rounding errors
- int const nCoastPoint = pProfile->nGetCoastPoint();
- PtiSegStart = m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(nCoastPoint);
- }
- else
- {
- CGeom2DPoint const* pPtSegStart = pProfile->pPtGetPointInProfile(nSeg);
-
- // Convert from the external CRS to grid CRS
- PtiSegStart = PtiExtCRSToGridRound(pPtSegStart);
- }
-
- CGeom2DPoint const* pPtSegEnd = pProfile->pPtGetPointInProfile(nSeg + 1); // This is OK
-
- // Convert from the external CRS to grid CRS
- CGeom2DIPoint const PtiSegEnd = PtiExtCRSToGridRound(pPtSegEnd);
-
- // Safety check
- if (PtiSegStart == PtiSegEnd)
- continue;
-
- int const nXStart = PtiSegStart.nGetX();
- int const nYStart = PtiSegStart.nGetY();
- int const nXEnd = PtiSegEnd.nGetX();
- int const nYEnd = PtiSegEnd.nGetY();
-
- bool bShared = false;
-
- if (pProfile->nGetNumCoincidentProfilesInLineSegment(nSeg) > 1)
- {
- bShared = true;
-
- // If this is the second or more of several coincident line segments (i.e. it has the same start and end points as the previous line segment) then ignore it
- if ((nXStart == nXStartLast) && (nYStart == nYStartLast) && (nXEnd == nXEndLast) && (nYEnd == nYEndLast))
- continue;
- }
-
- // 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
- double dXInc = nXEnd - nXStart;
- double dYInc = nYEnd - nYStart;
- double const dLength = tMax(tAbs(dXInc), tAbs(dYInc));
-
- dXInc /= dLength;
- dYInc /= dLength;
-
- double dX = nXStart;
- double dY = nYStart;
-
- // Process each interpolated point
- for (int m = 0; m <= nRound(dLength); m++)
- {
- int const nX = nRound(dX);
- int const nY = nRound(dY);
-
- // Do some checking of this interpolated point, but only if this is not a grid-edge profile (these profiles are always valid)
- if (! pProfile->bIsGridEdge())
- {
- // Is the interpolated point within the valid raster grid?
- if (! bIsWithinValidGrid(nX, nY))
- {
- // It is outside the valid grid, so mark this profile and quit the loop
- bTruncatedSameCoast = true;
-
- if (! ACCEPT_TRUNCATED_PROFILES)
- pProfile->SetTruncatedSameCoast(true);
-
- if (m_nLogFileDetail >= LOG_FILE_MIDDLE_DETAIL)
- LogStream << m_ulIter << ": profile " << nProfile << " is invalid, truncated at [" << nX << "][" << nY << "] = {" << dGridCentroidXToExtCRSX(nX) << ", " << dGridCentroidYToExtCRSY(nY) << "}" << endl;
-
- break;
- }
-
- // Check again: is this cell (or an adjacent cell: does not matter which) already marked as 'under' a profile?
- int nYTmp = nY+1;
- if (nY+1 >= m_nYGridSize)
- nYTmp = nY-1;
-
- if (m_pRasterGrid->m_Cell[nX][nY].bIsProfile() || m_pRasterGrid->m_Cell[nX][nYTmp].bIsProfile())
- {
- // This cell or an adjacent cell, is 'under' a profile, so now check if the profile belongs to another coast
- int const nHitProfileCoast1 = m_pRasterGrid->m_Cell[nX][nY].nGetProfileCoastID();
- int const nHitProfileCoast2 = m_pRasterGrid->m_Cell[nX][nYTmp].nGetProfileCoastID();
-
- if ((nHitProfileCoast1 == nCoast) || (nHitProfileCoast2 == nCoast))
- {
- // The profile belongs to the same coast, mark this profile as invalid
- bHitAnotherProfile = true;
- pProfile->SetHitAnotherProfile(true);
- return;
- }
- }
-
- // If this is the first line segment of the profile, then once we are clear of the coastline (when m > PROFILE_CHECK_DIST_FROM_COAST), check if this profile hits land at this interpolated point. NOTE Get problems here since if the coastline vector has been heavily smoothed, this can result is 'false positives' profiles marked as invalid which are not actually invalid, because the profile hits land when m = 0 or m = 1. This results in some cells being flagged as profile cells which are actually inland
- if (m > PROFILE_CHECK_DIST_FROM_COAST)
- {
- // Check this cell. Two diagonal(ish) raster lines can cross each other without any intersection, so must also test an adjacent cell for intersection (does not matter which adjacent cell)
- if ((m_pRasterGrid->m_Cell[nX][nY].bIsCoastline()) || (bIsWithinValidGrid(nX, nY + 1) && m_pRasterGrid->m_Cell[nX][nY + 1].bIsCoastline()))
- {
- // We've hit a coastline so set a switch and mark the profile, then quit
- bHitCoast = true;
- pProfile->SetHitCoast(true);
- int const nHitCoast = m_pRasterGrid->m_Cell[nX][nY].nGetCoastline();
-
- if (m_nLogFileDetail >= LOG_FILE_ALL)
- LogStream << m_ulIter << ": \tcoast " << nCoast << " profile " << nProfile << " is invalid, hit coast " << nHitCoast << " at [" << nX << "][" << nY << "] = {" << dGridCentroidXToExtCRSX(nX) << ", " << dGridCentroidYToExtCRSY(nY) << "}" << endl;
-
- return;
- }
-
- if (! m_pRasterGrid->m_Cell[nX][nY].bIsInContiguousSea())
- {
- // We've hit dry land, so set a switch and mark the profile
- bHitLand = true;
- pProfile->SetHitLand(true);
-
- LogStream << m_ulIter << ": \tcoast " << nCoast << " profile " << nProfile << " HIT LAND at [" << nX << "][" << nY << "] = {" << dGridCentroidXToExtCRSX(nX) << ", " << dGridCentroidYToExtCRSY(nY) << "}, elevation = " << m_pRasterGrid->m_Cell[nX][nY].dGetAllSedTopElevIncTalus() << ", SWL = " << m_dThisIterSWL << endl;
-
- return;
- }
-
- if (m_pRasterGrid->m_Cell[nX][nY].nGetInterventionClass() != INT_NODATA)
- {
- // We've hit an intervention, so set a switch and mark the profile
- bHitIntervention = true;
- pProfile->SetHitIntervention(true);
-
- LogStream << m_ulIter << ": \tcoast " << nCoast << " profile " << nProfile << " HIT INTERVENTION at [" << nX << "][" << nY << "] = {" << dGridCentroidXToExtCRSX(nX) << ", " << dGridCentroidYToExtCRSY(nY) << "}, elevation = " << m_pRasterGrid->m_Cell[nX][nY].dGetAllSedTopElevIncTalus() << ", SWL = " << m_dThisIterSWL << endl;
-
- return;
- }
- }
-
- // Now check to see if we hit another profile which is not a coincident normal to this normal
- if (m_pRasterGrid->m_Cell[nX][nY].bIsProfile())
- {
- // We've hit a raster cell which is already marked as 'under' a normal profile. Get the number of the profile which marked this cell, and the coast to hich this profile belongs
- int const nHitProfile = m_pRasterGrid->m_Cell[nX][nY].nGetProfileID();
- int const nHitProfileCoast = m_pRasterGrid->m_Cell[nX][nY].nGetProfileCoastID();
-
- // Do both profiles belong to the same coast?
- if (nCoast == nHitProfileCoast)
- {
- // Both profiles belong to the same coast. Is this the number of a coincident profile of this profile?
- if (! pProfile->bFindProfileInCoincidentProfilesOfLastLineSegment(nHitProfile))
- {
- // It isn't a coincident profile, so we have just hit an unrelated profile. Mark this profile as invalid and move on
- pProfile->SetHitAnotherProfile(true);
- bHitAnotherProfile = true;
-
- return;
- }
- }
- }
- }
-
- // Append this point to the output vector
- pVIPointsOut->push_back(CGeom2DIPoint(nX, nY)); // Is in raster grid coordinates
- pbVShared->push_back(bShared);
-
- // And increment for next time
- dX += dXInc;
- dY += dYInc;
- }
-
- nXStartLast = nXStart;
- nYStartLast = nYStart;
- nXEndLast = nXEnd;
- nYEndLast = nYEnd;
-
- if (bTruncatedSameCoast)
- break;
- }
-
- if (bTruncatedSameCoast)
- {
- if (nSeg < (nNumSegments - 1))
- // We are truncating the profile, so remove any line segments after this one
- pProfile->TruncateLineSegments(nSeg);
-
- // Shorten the vector input. Ignore CPPCheck errors here, since we know that pVIPointsOut is not empty
- int const nLastX = pVIPointsOut->at(pVIPointsOut->size() - 1).nGetX();
- int const nLastY = pVIPointsOut->at(pVIPointsOut->size() - 1).nGetY();
-
- pProfile->pPtGetPointInProfile(nSeg + 1)->SetX(dGridCentroidXToExtCRSX(nLastX));
- pProfile->pPtGetPointInProfile(nSeg + 1)->SetY(dGridCentroidYToExtCRSY(nLastY));
- }
-
- // // DEBUG CODE =====================================================================================
- // LogStream << "====================" << endl;
- // LogStream << m_ulIter << ": for profile " << nProfile << " pPtiStart = [" << pPtiStart->nGetX() << "][" << pPtiStart->nGetY() << "] pPtiEnd = [" << pPtiEnd->nGetX() << "][" << pPtiEnd->nGetY() << "] pVIPointsOut->size() = " << pVIPointsOut->size() << endl;
- // // for (int n = 0; n < static_cast(pVIPointsOut->size()); n++)
- // // LogStream << "\t[" << pVIPointsOut->at(n).nGetX() << "][" << pVIPointsOut->at(n).nGetY() << "]" << endl;
- // LogStream << "====================" << endl;
- // // DEBUG CODE =====================================================================================
-
- if (pVIPointsOut->size() < 3)
- {
- // Coastline-normal profiles cannot be very short (e.g. with less than 3 cells), since we cannot calculate along-profile slope properly for such short profiles
- bTooShort = true;
- pProfile->SetTooShort(true);
-
- if (m_nLogFileDetail >= LOG_FILE_MIDDLE_DETAIL)
- {
- // Ignore CPPCheck errors here, since we know that pVIPointsOut is not empty
- LogStream << m_ulIter << ": profile " << nProfile << " is invalid, is too short, only " << pVIPointsOut->size() << " points, HitLand?" << bHitLand << ". From [" << pVIPointsOut->at(0).nGetX() << "][" << pVIPointsOut->at(0).nGetY() << "] = {" << dGridCentroidXToExtCRSX(pVIPointsOut->at(0).nGetX()) << ", " << dGridCentroidYToExtCRSY(pVIPointsOut->at(0).nGetY()) << "} to [" << pVIPointsOut->at(pVIPointsOut->size() - 1).nGetX() << "][" << pVIPointsOut->at(pVIPointsOut->size() - 1).nGetY() << "] = {" << dGridCentroidXToExtCRSX(pVIPointsOut->at(pVIPointsOut->size() - 1).nGetX()) << ", " << dGridCentroidYToExtCRSY(pVIPointsOut->at(pVIPointsOut->size() - 1).nGetY()) << "}" << endl;
- }
- }
-}
-
-//===============================================================================================================================
-//! Merges two profiles which intersect at their final (most seaward) line segments, seaward of their point of intersection
-//===============================================================================================================================
-void CSimulation::MergeProfilesAtFinalLineSegments(int const nCoast, CGeomProfile* pFirstProfile, CGeomProfile* pSecondProfile, int const nFirstProfileLineSegments, int const nSecondProfileLineSegments, double const dIntersectX, double const dIntersectY, double const dAvgEndX, double const dAvgEndY)
-{
- // The point of intersection is on the final (most seaward) line segment of both profiles. Put together a vector of coincident profile numbers (with no duplicates) for both profiles
- int nCombinedLastSeg = 0;
- vector> prVCombinedProfilesCoincidentProfilesLastSeg;
-
- for (unsigned int n = 0; n < pFirstProfile->pprVGetPairedCoincidentProfilesForLineSegment(nFirstProfileLineSegments - 1)->size(); n++)
- {
- pair prTmp;
- prTmp.first = pFirstProfile->pprVGetPairedCoincidentProfilesForLineSegment(nFirstProfileLineSegments - 1)->at(n).first;
- prTmp.second = pFirstProfile->pprVGetPairedCoincidentProfilesForLineSegment(nFirstProfileLineSegments - 1)->at(n).second;
-
- bool bFound = false;
-
- for (unsigned int m = 0; m < prVCombinedProfilesCoincidentProfilesLastSeg.size(); m++)
- {
- if (prVCombinedProfilesCoincidentProfilesLastSeg[m].first == prTmp.first)
- {
- bFound = true;
- break;
- }
- }
-
- if (! bFound)
- {
- prVCombinedProfilesCoincidentProfilesLastSeg.push_back(prTmp);
- nCombinedLastSeg++;
- }
- }
-
- for (unsigned int n = 0; n < pSecondProfile->pprVGetPairedCoincidentProfilesForLineSegment(nSecondProfileLineSegments - 1)->size(); n++)
- {
- pair prTmp;
- prTmp.first = pSecondProfile->pprVGetPairedCoincidentProfilesForLineSegment(nSecondProfileLineSegments - 1)->at(n).first;
- prTmp.second = pSecondProfile->pprVGetPairedCoincidentProfilesForLineSegment(nSecondProfileLineSegments - 1)->at(n).second;
-
- bool bFound = false;
-
- for (unsigned int m = 0; m < prVCombinedProfilesCoincidentProfilesLastSeg.size(); m++)
- {
- if (prVCombinedProfilesCoincidentProfilesLastSeg[m].first == prTmp.first)
- {
- bFound = true;
- break;
- }
- }
-
- if (! bFound)
- {
- prVCombinedProfilesCoincidentProfilesLastSeg.push_back(prTmp);
- nCombinedLastSeg++;
- }
- }
-
- // Increment the number of each line segment
- for (int m = 0; m < nCombinedLastSeg; m++)
- prVCombinedProfilesCoincidentProfilesLastSeg[m].second++;
-
- vector> prVFirstProfileCoincidentProfilesLastSeg = *pFirstProfile->pprVGetPairedCoincidentProfilesForLineSegment(nFirstProfileLineSegments - 1);
- vector> prVSecondProfileCoincidentProfilesLastSeg = *pSecondProfile->pprVGetPairedCoincidentProfilesForLineSegment(nSecondProfileLineSegments - 1);
- int const nNumFirstProfileCoincidentProfilesLastSeg = static_cast(prVFirstProfileCoincidentProfilesLastSeg.size());
- int const nNumSecondProfileCoincidentProfilesLastSeg = static_cast(prVSecondProfileCoincidentProfilesLastSeg.size());
-
- // LogStream << m_ulIter << ": END-SEGMENT INTERSECTION between profiles " << nFirstProfile << " and " << nSecondProfile << " at line segment " << nFirstProfileLineSegments-1 << "/" << nFirstProfileLineSegments-1 << ", and line segment " << nSecondProfileLineSegments-1 << "/" << nSecondProfileLineSegments-1 << ", respectively. Both truncated at [" << dIntersectX << ", " << dIntersectY << "] then profiles {" << nFirstProfile << "} and {" << nSecondProfile << "} extended to [" << dAvgEndX << ", " << dAvgEndY << "]" << endl;
-
- // Truncate the first profile, and all co-incident profiles, at the point of intersection
- for (int n = 0; n < nNumFirstProfileCoincidentProfilesLastSeg; n++)
- {
- int const nThisProfile = prVFirstProfileCoincidentProfilesLastSeg[n].first;
- CGeomProfile* pThisProfile = m_VCoast[nCoast].pGetProfile(nThisProfile);
- int const nProfileLength = pThisProfile->nGetProfileSize();
-
- // This is the final line segment of the first 'main' profile. We are assuming that it is also the final line segment of all co-incident profiles. This is fine, altho' each profile may well have a different number of line segments landwards i.e. the number of the line segment may be different for each co-incident profile
- pThisProfile->SetPointInProfile(nProfileLength - 1, dIntersectX, dIntersectY);
- }
-
- // Truncate the second profile, and all co-incident profiles, at the point of intersection
- for (int n = 0; n < nNumSecondProfileCoincidentProfilesLastSeg; n++)
- {
- int const nThisProfile = prVSecondProfileCoincidentProfilesLastSeg[n].first;
- CGeomProfile* pThisProfile = m_VCoast[nCoast].pGetProfile(nThisProfile);
- int const nProfileLength = pThisProfile->nGetProfileSize();
-
- // This is the final line segment of the second 'main' profile. We are assuming that it is also the final line segment of all co-incident profiles. This is fine, altho' each profile may well have a different number of line segments landwards i.e. the number of the line segment may be different for each co-incident profile
- pThisProfile->SetPointInProfile(nProfileLength - 1, dIntersectX, dIntersectY);
- }
-
- // Append a new straight line segment to the existing line segment(s) of the first profile, and to all co-incident profiles
- for (int nThisLineSeg = 0; nThisLineSeg < nNumFirstProfileCoincidentProfilesLastSeg; nThisLineSeg++)
- {
- int const nThisProfile = prVFirstProfileCoincidentProfilesLastSeg[nThisLineSeg].first;
- CGeomProfile* pThisProfile = m_VCoast[nCoast].pGetProfile(nThisProfile);
-
- // Update this profile
- pThisProfile->AppendPointInProfile(dAvgEndX, dAvgEndY);
-
- // Append details of the combined profiles
- pThisProfile->AppendLineSegment();
-
- for (int m = 0; m < nCombinedLastSeg; m++)
- pThisProfile->AppendCoincidentProfileToLineSegments(prVCombinedProfilesCoincidentProfilesLastSeg[m]);
- }
-
- // Append a new straight line segment to the existing line segment(s) of the second profile, and to all co-incident profiles
- for (int nThisLineSeg = 0; nThisLineSeg < nNumSecondProfileCoincidentProfilesLastSeg; nThisLineSeg++)
- {
- int const nThisProfile = prVSecondProfileCoincidentProfilesLastSeg[nThisLineSeg].first;
- CGeomProfile* pThisProfile = m_VCoast[nCoast].pGetProfile(nThisProfile);
-
- // Update this profile
- pThisProfile->AppendPointInProfile(dAvgEndX, dAvgEndY);
-
- // Append details of the combined profiles
- pThisProfile->AppendLineSegment();
-
- for (int m = 0; m < nCombinedLastSeg; m++)
- pThisProfile->AppendCoincidentProfileToLineSegments(prVCombinedProfilesCoincidentProfilesLastSeg[m]);
- }
-
- // // DEBUG CODE ****************************************************************
- // int nFirstProfileLineSeg= pFirstProfile->nGetNumLineSegments();
- // int nSecondProfileLineSeg = pSecondProfile->nGetNumLineSegments();
- //
- // LogStream << "\tProfile {" << nFirstProfile << "} now has " << nFirstProfileLineSeg << " line segments" << endl;
- // for (int m = 0; m < nFirstProfileLineSeg; m++)
- // {
- // vector > prVCoincidentProfiles = *pFirstProfile->pprVGetPairedCoincidentProfilesForLineSegment(m);
- // LogStream << "\tCo-incident profiles and line segments for line segment " << m << " of profile {" << nFirstProfile << "} are {";
- // for (int nn = 0; nn < prVCoincidentProfiles.size(); nn++)
- // LogStream << " " << prVCoincidentProfiles[nn].first << "[" << prVCoincidentProfiles[nn].second << "] ";
- // LogStream << " }" << endl;
- // }
- // LogStream << "\tProfile {" << nSecondProfile << "} now has " << nSecondProfileLineSeg << " line segments" << endl;
- // for (int m = 0; m < nSecondProfileLineSeg; m++)
- // {
- // vector > prVCoincidentProfiles = *pSecondProfile->pprVGetPairedCoincidentProfilesForLineSegment(m);
- // LogStream << "\tCo-incident profiles and line segments for line segment " << m << " of profile {" << nSecondProfile << "} are {";
- // for (int nn = 0; nn < prVCoincidentProfiles.size(); nn++)
- // LogStream << " " << prVCoincidentProfiles[nn].first << "[" << prVCoincidentProfiles[nn].second << "] ";
- // LogStream << " }" << endl;
- // }
- // // DEBUG CODE ******************************************************************
-}
-
-//===============================================================================================================================
-//! Truncates one intersecting profile at the point of intersection, and retains the other profile
-//===============================================================================================================================
-void CSimulation::TruncateOneProfileRetainOtherProfile(int const nCoast, CGeomProfile* pProfileToTruncate, CGeomProfile* pProfileToRetain, double dIntersectX, double dIntersectY, int nProfileToTruncateIntersectLineSeg, int nProfileToRetainIntersectLineSeg, bool const bAlreadyPresent)
-{
- // // Occasionally, profiles cross each other, with the crossing not detected. So check for intersection between pProfileToTruncate and all profiles (starting from the last i.e. in reverse order) in all segments (starting from the last i.e. in reverse order) of pProfileToRetain's CGeomMultiLine
- // bool bFound = false;
- // int nNumSegProfRetain = pProfileToRetain->nGetNumLineSegments();
- // for (int nSeg = nNumSegProfRetain-1; nSeg >= 0; nSeg--)
- // {
- // if (bFound)
- // break;
- //
- // int nNumProfInSeg = pProfileToRetain->nGetNumCoincidentProfilesInLineSegment(nSeg);
- // for (int nProf = nNumProfInSeg-1; nProf >= 0; nProf--)
- // {
- // int nThisProf = pProfileToRetain->nGetCoincidentProfileForLineSegment(nSeg, nProf);
- // CGeomProfile* pThisProf = m_VCoast[nCoast].pGetProfile(nThisProf);
- //
- // int nProfToTruncLineSeg = 0;
- // int nThisProfLineSeg = 0;
- // double dTmpIntersectX = 0;
- // double dTmpIntersectY = 0;
- // double dAvgEndX = 0;
- // double dAvgEndY = 0;
- //
- // if (bCheckForIntersection(pProfileToTruncate, pThisProf, nProfToTruncLineSeg, nThisProfLineSeg, dTmpIntersectX, dTmpIntersectY, dAvgEndX, dAvgEndY))
- // {
- // // An intersection was found: so the profile with which pProfileToTruncate intersects becomes the new pProfileToRetain, and dIntersectX, dIntersectY, nProfileToTruncateIntersectLineSeg, and nProfileToRetainIntersectLineSeg are also changed
- // pProfileToRetain = pThisProf;
- // dIntersectX = dTmpIntersectX;
- // dIntersectY = dTmpIntersectY;
- // nProfileToRetainIntersectLineSeg = nThisProfLineSeg;
- // nProfileToTruncateIntersectLineSeg = nProfToTruncLineSeg;
- //
- // bFound = true;
- // break;
- // }
- // }
- // }
-
- // Insert the intersection point into the main retain-profile if it is not already in the profile, and do the same for all co-incident profiles of the main retain-profile. Also add details of the to-truncate profile (and all its coincident profiles) to every line segment of the main to-retain profile which is seaward of the point of intersection
- int const nRet = nInsertPointIntoProfilesIfNeededThenUpdate(nCoast, pProfileToRetain, dIntersectX, dIntersectY, nProfileToRetainIntersectLineSeg, pProfileToTruncate, nProfileToTruncateIntersectLineSeg, bAlreadyPresent);
-
- if (nRet != RTN_OK)
- {
- // LogStream << m_ulIter << ": error in nInsertPointIntoProfilesIfNeededThenUpdate()" << endl;
- return;
- }
-
- // Get all profile points of the main retain-profile seawards from the intersection point, and do the same for the corresponding line segments (including coincident profiles). This also includes details of the main to-truncate profile (and all its coincident profiles)
- vector PtVProfileLastPart;
- vector>> prVLineSegLastPart;
-
- if (bAlreadyPresent)
- {
- PtVProfileLastPart = pProfileToRetain->PtVGetThisPointAndAllAfter(nProfileToRetainIntersectLineSeg);
- prVLineSegLastPart = pProfileToRetain->prVVGetAllLineSegAfter(nProfileToRetainIntersectLineSeg);
- }
-
- else
- {
- PtVProfileLastPart = pProfileToRetain->PtVGetThisPointAndAllAfter(nProfileToRetainIntersectLineSeg + 1);
- prVLineSegLastPart = pProfileToRetain->prVVGetAllLineSegAfter(nProfileToRetainIntersectLineSeg + 1);
- }
-
- // assert(PtVProfileLastPart.size() > 1);
- // assert(prVLineSegLastPart.size() > 0);
-
- // Truncate the truncate-profile at the point of intersection, and do the same for all its co-incident profiles. Then append the profile points of the main to-retain profile seaward from the intersection point, and do the same for the corresponding line segments (including coincident profiles)
- TruncateProfileAndAppendNew(nCoast, pProfileToTruncate, nProfileToTruncateIntersectLineSeg, &PtVProfileLastPart, &prVLineSegLastPart);
-
- // assert(m_VCoast[nCoast].pGetProfile(nProfileToTruncate)->nGetProfileSize() > 1);
- // assert(pProfileToRetain->nGetNumLineSegments() > 0);
- // assert(m_VCoast[nCoast].pGetProfile(nProfileToTruncate)->nGetNumLineSegments() > 0);
-}
-
-//===============================================================================================================================
-//! Inserts an intersection point into the profile that is to be retained, if that point is not already present in the profile, then does the same for all co-incident profiles. Finally adds the numbers of the to-truncate profile (and all its coincident profiles) to the seaward line segments of the to-retain profile and all its coincident profiles
-//===============================================================================================================================
-int CSimulation::nInsertPointIntoProfilesIfNeededThenUpdate(int const nCoast, CGeomProfile* pProfileToRetain, double const dIntersectX, double const dIntersectY, int const nProfileToRetainIntersectLineSeg, CGeomProfile* pProfileToTruncate, int const nProfileToTruncateIntersectLineSeg, bool const bAlreadyPresent)
-{
- // // DEBUG CODE ****************************************************************
- // // Get the index numbers of all coincident profiles for the 'main' to-retain profile for the line segment in which intersection occurred
- // vector > prVRetainCoincidentProfilesCHECK1 = *m_VCoast[nCoast].pGetProfile(nMainProfile)->pprVGetPairedCoincidentProfilesForLineSegment(nProfileToRetainIntersectLineSeg);
- // int nNumRetainCoincidentCHECK1 = prVRetainCoincidentProfilesCHECK1.size();
- // for (int nn = 0; nn < nNumRetainCoincidentCHECK1; nn++)
- // {
- // int nThisProfile = prVRetainCoincidentProfilesCHECK1[nn].first;
- // LogStream << "\tBEFORE nInsertPointIntoProfilesIfNeededThenUpdate(): " << (nThisProfile == nMainProfile ? "MAIN" : "COINCIDENT") << " to-retain profile {" << nThisProfile << "} has " << m_VCoast[nCoast].pGetProfile(nThisProfile)->nGetProfileSize() << " points ";
- // for (int nn = 0; nn < m_VCoast[nCoast].pGetProfile(nThisProfile)->nGetProfileSize(); nn++)
- // LogStream << "[" << m_VCoast[nCoast].pGetProfile(nThisProfile)->pPtGetPointInProfile(nn)->dGetX() << ", " << m_VCoast[nCoast].pGetProfile(nThisProfile)->pPtGetPointInProfile(nn)->dGetY() << "] ";
- // LogStream << "), and " << m_VCoast[nCoast].pGetProfile(nThisProfile)->nGetNumLineSegments() << " line segments, co-incident profiles and their line segments are ";
- // for (int mm = 0; mm < m_VCoast[nCoast].pGetProfile(nThisProfile)->nGetNumLineSegments(); mm++)
- // {
- // vector > prVTmp = *m_VCoast[nCoast].pGetProfile(nThisProfile)->pprVGetPairedCoincidentProfilesForLineSegment(mm);
- // LogStream << "{ ";
- // for (int nn = 0; nn < m_VCoast[nCoast].pGetProfile(nThisProfile)->nGetNumCoincidentProfilesInLineSegment(mm); nn++)
- // LogStream << prVTmp[nn].first << "[" << prVTmp[nn].second << "] ";
- // LogStream << "} ";
- // }
- // LogStream << endl;
- //
- // for (int nPoint = 0; nPoint < m_VCoast[nCoast].pGetProfile(nThisProfile)->nGetProfileSize()-1; nPoint++)
- // {
- // CGeom2DPoint
- // Pt1 = *m_VCoast[nCoast].pGetProfile(nThisProfile)->pPtGetPointInProfile(nPoint),
- // Pt2 = *m_VCoast[nCoast].pGetProfile(nThisProfile)->pPtGetPointInProfile(nPoint+1);
- //
- // if (Pt1 == Pt2)
- // LogStream << m_ulIter << ": IDENTICAL POINTS before changes, in profile {" << nThisProfile << "} points = " << nPoint << " and " << nPoint+1 << endl;
- // }
- // }
- //
- // // Get the index numbers of all coincident profiles for the 'main' to-truncate profile for the line segment in which intersection occurred
- // vector > prVTruncateCoincidentProfilesCHECK1 = *m_VCoast[nCoast].pGetProfile(nProfileToTruncate)->pprVGetPairedCoincidentProfilesForLineSegment(nProfileToTruncateIntersectLineSeg);
- // int nNumTruncateCoincidentCHECK1 = prVTruncateCoincidentProfilesCHECK1.size();
- // for (int nn = 0; nn < nNumTruncateCoincidentCHECK1; nn++)
- // {
- // int nThisProfile = prVTruncateCoincidentProfilesCHECK1[nn].first;
- // LogStream << "\tBEFORE nInsertPointIntoProfilesIfNeededThenUpdate(): " << (nThisProfile == nProfileToTruncate ? "MAIN" : "COINCIDENT") << " to-truncate profile {" << nThisProfile << "} has " << m_VCoast[nCoast].pGetProfile(nThisProfile)->nGetProfileSize() << " points ";
- // for (int nn = 0; nn < m_VCoast[nCoast].pGetProfile(nThisProfile)->nGetProfileSize(); nn++)
- // LogStream << "[" << m_VCoast[nCoast].pGetProfile(nThisProfile)->pPtGetPointInProfile(nn)->dGetX() << ", " << m_VCoast[nCoast].pGetProfile(nThisProfile)->pPtGetPointInProfile(nn)->dGetY() << "] ";
- // LogStream << "), and " << m_VCoast[nCoast].pGetProfile(nThisProfile)->nGetNumLineSegments() << " line segments, co-incident profiles and their line segments are ";
- // for (int mm = 0; mm < m_VCoast[nCoast].pGetProfile(nThisProfile)->nGetNumLineSegments(); mm++)
- // {
- // vector > prVTmp = *m_VCoast[nCoast].pGetProfile(nThisProfile)->pprVGetPairedCoincidentProfilesForLineSegment(mm);
- // LogStream << "{ ";
- // for (int nn = 0; nn < m_VCoast[nCoast].pGetProfile(nThisProfile)->nGetNumCoincidentProfilesInLineSegment(mm); nn++)
- // LogStream << prVTmp[nn].first << "[" << prVTmp[nn].second << "] ";
- // LogStream << "} ";
- // }
- // LogStream << endl;
- //
- // for (int nPoint = 0; nPoint < m_VCoast[nCoast].pGetProfile(nThisProfile)->nGetProfileSize()-1; nPoint++)
- // {
- // CGeom2DPoint
- // Pt1 = *m_VCoast[nCoast].pGetProfile(nThisProfile)->pPtGetPointInProfile(nPoint),
- // Pt2 = *m_VCoast[nCoast].pGetProfile(nThisProfile)->pPtGetPointInProfile(nPoint+1);
- //
- // if (Pt1 == Pt2)
- // LogStream << m_ulIter << ": IDENTICAL POINTS before changes, in profile {" << nThisProfile << "} points = " << nPoint << " and " << nPoint+1 << endl;
- // }
- // }
- // // DEBUG CODE ******************************************************************
-
- int const nProfileToRetain = pProfileToRetain->nGetProfileID();
-
- // Get the index numbers of all coincident profiles for the 'main' to-retain profile for the line segment in which intersection occurs
- vector> prVCoincidentProfiles = *pProfileToRetain->pprVGetPairedCoincidentProfilesForLineSegment(nProfileToRetainIntersectLineSeg);
- int const nNumCoincident = static_cast(prVCoincidentProfiles.size());
- vector nLineSegAfterIntersect(nNumCoincident, -1); // The line segment after the point of intersection, for each co-incident profile
-
- // Do this for the main profile and all profiles which are co-incident for this line segment
- for (int nn = 0; nn < nNumCoincident; nn++)
- {
- int const nThisProfile = prVCoincidentProfiles[nn].first; // The number of this profile
- int const nThisLineSeg = prVCoincidentProfiles[nn].second; // The line segment of this profile
- CGeomProfile* pThisProfile = m_VCoast[nCoast].pGetProfile(nThisProfile);
-
- // Is the intersection point already present in the to-retain profile?
- if (! bAlreadyPresent)
- {
- // It is not already present, so insert it and also update the associated multi-line
- if (! pThisProfile->bInsertIntersection(dIntersectX, dIntersectY, nThisLineSeg))
- {
- // Error
- LogStream << WARN << m_ulIter << ": cannot insert a line segment after the final line segment (" << nThisLineSeg << ") for " << (nThisProfile == nProfileToRetain ? "main" : "co-incident") << " profile (" << nThisProfile << "), abandoning" << endl;
-
- return RTN_ERR_CANNOT_INSERT_POINT;
- }
-
- // LogStream << "\tIntersection point NOT already in " << (nThisProfile == nProfileToRetain ? "main" : "co-incident") << " profile {" << nThisProfile << "}, inserted it as point " << nThisLineSeg+1 << endl;
- }
-
- // Get the line segment after intersection
- nLineSegAfterIntersect[nn] = nThisLineSeg + 1;
- }
-
- // for (int nn = 0; nn < nNumCoincident; nn++)
- // LogStream << "\tFor profile " << prVCoincidentProfiles[nn].first << " line segment [" << nLineSegAfterIntersect[nn] << "] is immediately after the intersection point" << endl;
-
- // Get the coincident profiles for the to-truncate profile, at the line segment where intersection occurs
- vector> prVToTruncateCoincidentProfiles = *pProfileToTruncate->pprVGetPairedCoincidentProfilesForLineSegment(nProfileToTruncateIntersectLineSeg);
- int const nNumToTruncateCoincident = static_cast(prVToTruncateCoincidentProfiles.size());
-
- // Now add the number of the to-truncate profile, and all its coincident profiles, to all line segments which are seaward of the point of intersection. Do this for the main profile and all profiles which are co-incident for this line segment
- for (int nn = 0; nn < nNumCoincident; nn++)
- {
- int const nThisProfile = prVCoincidentProfiles[nn].first; // The number of this profile
- CGeomProfile* pThisProfile = m_VCoast[nCoast].pGetProfile(nThisProfile);
-
- // Get the number of line segments for this to-retain profile (will have just increased, if we just inserted a point)
- int const nNumLineSegs = pThisProfile->nGetNumLineSegments();
-
- // Do for all line segments seaward of the point of intersection
- for (int nLineSeg = nLineSegAfterIntersect[nn], nIncr = 0; nLineSeg < nNumLineSegs; nLineSeg++, nIncr++)
- {
- // // This can happen occasionally
- // if (nThisProfile == nProfileToTruncateIntersectLineSeg)
- // {
- // LogStream << "\t*** ERROR nThisProfile = " << nThisProfile << " nProfileToTruncateIntersectLineSeg = " << nProfileToTruncateIntersectLineSeg << ", ignoring" << endl;
- // pThisProfile->SetHitAnotherProfile(true);
- // continue;
- // }
-
- // Add the number of the to-truncate profile, and all its coincident profiles, to this line segment
- for (int m = 0; m < nNumToTruncateCoincident; m++)
- {
- int const nProfileToAdd = prVToTruncateCoincidentProfiles[m].first;
- int const nProfileToAddLineSeg = prVToTruncateCoincidentProfiles[m].second;
-
- // LogStream << "\tAdding " << (nProfileToAdd == nProfileToTruncateIntersectLineSeg ? "main" : "co-incident") << " truncate-profile " << nProfileToAdd << ", line segment [" << nProfileToAddLineSeg + nIncr << "] to line segment " << nLineSeg << " of " << (nThisProfile == nProfileToRetain ? "main" : "co-incident") << " to-retain profile " << nThisProfile << endl;
-
- pThisProfile->AddCoincidentProfileToExistingLineSegment(nLineSeg, nProfileToAdd, nProfileToAddLineSeg + nIncr);
- }
- }
- }
-
- // // DEBUG CODE ****************************************************************
- // Get the index numbers of all coincident profiles for the 'main' profile for the line segment in which intersection occurred
- // vector > prVCoincidentProfilesCHECK2 = *m_VCoast[nCoast].pGetProfile(nProfileToRetain)->pprVGetPairedCoincidentProfilesForLineSegment(nProfileToRetainIntersectLineSeg);
- // int nNumCoincidentCHECK2 = prVCoincidentProfilesCHECK2.size();
- // for (int nn = 0; nn < nNumCoincidentCHECK2; nn++)
- // {
- // int nThisProfile = prVCoincidentProfilesCHECK2[nn].first;
- // LogStream << "\tAFTER nInsertPointIntoProfilesIfNeededThenUpdate(): " << (nThisProfile == nProfileToRetain ? "MAIN" : "COINCIDENT") << " to-retain profile {" << nThisProfile << "} has " << m_VCoast[nCoast].pGetProfile(nThisProfile)->nGetProfileSize() << " points ";
- // for (int nn = 0; nn < m_VCoast[nCoast].pGetProfile(nThisProfile)->nGetProfileSize(); nn++)
- // LogStream << "[" << m_VCoast[nCoast].pGetProfile(nThisProfile)->pPtGetPointInProfile(nn)->dGetX() << ", " << m_VCoast[nCoast].pGetProfile(nThisProfile)->pPtGetPointInProfile(nn)->dGetY() << "] ";
- // LogStream << "), and " << m_VCoast[nCoast].pGetProfile(nThisProfile)->nGetNumLineSegments() << " line segments, co-incident profiles and their line segments are ";
- // for (int nLineSeg = 0; nLineSeg < m_VCoast[nCoast].pGetProfile(nThisProfile)->nGetNumLineSegments(); nLineSeg++)
- // {
- // vector > prVTmp = *m_VCoast[nCoast].pGetProfile(nThisProfile)->pprVGetPairedCoincidentProfilesForLineSegment(nLineSeg);
- // LogStream << "{ ";
- // for (int nn = 0; nn < m_VCoast[nCoast].pGetProfile(nThisProfile)->nGetNumCoincidentProfilesInLineSegment(nLineSeg); nn++)
- // LogStream << prVTmp[nn].first << "[" << prVTmp[nn].second << "] ";
- // LogStream << "} ";
- // }
- // LogStream << endl;
- //
- // for (int nPoint = 0; nPoint < m_VCoast[nCoast].pGetProfile(nThisProfile)->nGetProfileSize()-1; nPoint++)
- // {
- // CGeom2DPoint
- // Pt1 = *m_VCoast[nCoast].pGetProfile(nThisProfile)->pPtGetPointInProfile(nPoint),
- // Pt2 = *m_VCoast[nCoast].pGetProfile(nThisProfile)->pPtGetPointInProfile(nPoint+1);
- //
- // if (Pt1 == Pt2)
- // LogStream << m_ulIter << ": IDENTICAL POINTS before changes, in profile {" << nThisProfile << "} points = " << nPoint << " and " << nPoint+1 << endl;
- // }
- // }
- // // DEBUG CODE ******************************************************************
-
- return RTN_OK;
-}
-
-//===============================================================================================================================
-//! Truncate a profile at the point of intersection, and do the same for all its co-incident profiles
-//===============================================================================================================================
-void CSimulation::TruncateProfileAndAppendNew(int const nCoast, CGeomProfile* pProfileToRetain, int const nMainProfileIntersectLineSeg, vector