diff --git a/README.md b/README.md index 47470584..73c8bb41 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ This will take you to a server on the Surf Research Cloud, where we have eWaterC - [References](https://www.ewatercycle.org/projects/main/references.html) Projects counter: -- BSc projects: 9 +- BSc projects: 10 - MSc projects: 1 - PhD/PostDoc/Research projects: 1 diff --git a/book/_toc.yml b/book/_toc.yml index 1b5183dd..d2a909ff 100644 --- a/book/_toc.yml +++ b/book/_toc.yml @@ -176,7 +176,32 @@ parts: - file: thesis_projects/BSc/2026_Q4_BeauBuijtenhuijs_CEG/Report/z_Appendix_B.ipynb title: Appendix B - + - file: thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/BSc_JulianSteenhuisen.md + sections: + - file: thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Report/0_Voorwoord.ipynb + title: Voorwoord + - file: thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Report/1_Inleiding.ipynb + title: Inleiding + - file: thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Report/2_Literatuur_onderzoek.ipynb + title: Literatuur onderzoek + - file: thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Report/3_Opzet_van_het_onderzoek.ipynb + title: Opzet van het onderzoek + - file: thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Report/4_Het_model.ipynb + title: Het model + - file: thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Report/5_Droogte_analyse.ipynb + title: Droogte analyse + - file: thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Report/6_Toekomstige_klimaatscenarios.ipynb + title: Toekomstige Klimaatscenario's + - file: thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Report/7_Resultaten.ipynb + title: Resultaten + - file: thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Report/8_Conclusie_en_aanbevelingen.ipynb + title: Conclusie en aanbevelingen + - file: thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Report/9_Discussie.ipynb + title: Discussie + - file: thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Report/Bronnenlijst.ipynb + title: Bronnenlijst + - file: thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Report/Appendix_A.ipynb + title: "Appendix" - file: thesis_projects/BSc/2026_Q4_MaximedeBekker_CEG/BSc_MaximedeBekker.md sections: diff --git a/book/intro.md b/book/intro.md index ed0fc3f7..9143c1df 100644 --- a/book/intro.md +++ b/book/intro.md @@ -23,7 +23,7 @@ This will take you to a server on the Surf Research Cloud, where we have eWaterC - [References](https://www.ewatercycle.org/projects/main/references.html) Projects counter: -- BSc projects: 9 +- BSc projects: 10 - MSc projects: 1 - PhD/PostDoc/Research projects: 1 diff --git a/book/thesis_projects/BSc/2026_Q4_BeauBuijtenhuijs_CEG/Report/00_Abstract.ipynb b/book/thesis_projects/BSc/2026_Q4_BeauBuijtenhuijs_CEG/Report/00_Abstract.ipynb index 221f7815..c9aac300 100644 --- a/book/thesis_projects/BSc/2026_Q4_BeauBuijtenhuijs_CEG/Report/00_Abstract.ipynb +++ b/book/thesis_projects/BSc/2026_Q4_BeauBuijtenhuijs_CEG/Report/00_Abstract.ipynb @@ -5,7 +5,9 @@ "id": "ab01dd1d-b2dd-48f9-a08d-5094e97c2d75", "metadata": {}, "source": [ - "# Abstract" + "# Impact of Climate Change on the Okavango River: The impact of the future discharge on the water supply of Okavango Basin - Beau Buijtenhuijs\n", + "\n", + "## Abstract" ] }, { diff --git a/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/BSc_JulianSteenhuisen.md b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/BSc_JulianSteenhuisen.md new file mode 100644 index 00000000..11dea65d --- /dev/null +++ b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/BSc_JulianSteenhuisen.md @@ -0,0 +1,9 @@ +# Droogte in het Brokopondomeer - Julian Steenhuisen + + +## Abstract +Klimaatverandering wordt verwacht de hydrologische systemen wereldwijd aan te tasten. Dit onderzoek zal kijken naar de impact van klimaatverandering op de instroom van het Blommenstein stuwmeer voor de stroomgeneratie van de Afobakadam. De belangrijkste toevoer van het Blommensteinmeer, in de volksmond het Brokopondomeer genoemd, is de Surinamerivier met een stroomgebied dat zich volledig in de Amazone jungle bevindt. + +De Afobakadam in Suriname is verantwoordelijk voor de helft van de stroomvoorziening in het land, het verlagen of stilvallen van de stroomgeneratie zal het hele land verstoren. Dit onderzoek is uitgevoerd worden op het eWatercycle platform met een zelfgemaakt model en ERA5 forcing data om de instroom in het Brokopondomeer te relateren aan neerslag en verdamping van het stroomgebied. Deze instroom is in een eerste model berekend aan de hand van diepte, oppervlakte en verdampingsdata van het stuwmeer. De instroom is gemodelleerd om historische data te genereren waar het tweede model op gekalibreerd is om voorspellingen te kunnen doen voor de toekomst aan de hand van CMIP-data. Deze voorspellingen bestaan uit 3 klimaatscenario’s met ieder neerslag en verdamping verwachtingen gebaseerd op broeikaseffect simulaties. Deze CMIP-data is in model 2 gebruikt om afvoerhoeveelheden te verkrijgen tussen 2027 en 2100, welke vervolgens teruggerekend zijn naar waterhoogtes in het Brokopondomeer. + +In 2 klimaatscenario’s blijft het meer boven de kritische hoogte tot 2030 en de ander tot 2035. Dit is de waterhoogte waarop er niet genoeg vermogen geleverd kan worden. De zeer kritische hoogte wordt in 1 scenario in 2035 bereikt en door de andere 2 pas definitief bereikt in 2050. Hierna is het meer onbruikbaar in alle simulaties. Het is te concluderen dat het meer grote negatieve gevolgen zal ondervinden aan klimaatverandering als het watergebruik onveranderd blijft. \ No newline at end of file diff --git a/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/0_Voorwoord.ipynb b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/0_Voorwoord.ipynb new file mode 100644 index 00000000..211db0c7 --- /dev/null +++ b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/0_Voorwoord.ipynb @@ -0,0 +1,52 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "45d34ebc-9df5-450a-bb6d-6a4678d373c5", + "metadata": {}, + "source": [ + "# Voorwoord" + ] + }, + { + "cell_type": "markdown", + "id": "123752e4-efbe-44a6-90f5-c3598034ebf4", + "metadata": {}, + "source": [ + "Deze bachelor eindscriptie is geschreven aan de faculteit Civiele Techniek en Geowetenschappen aan de afdeling Watermanagement. \n", + "Het onderwerp van de scriptie is “Klimaatverandering in een riviergebied naar keuze”. Deze keuze is uiteindelijk gevallen op de Surinamerivier met als voornaamste reden familiebanden te hebben naar Suriname en daar afgelopen jaar voor het eerst op bezoek te zijn geweest. \n", + "\n", + "Allereerst wil ik Rolf Hut en Nick van de Giesen bedanken voor hun begeleiding van deze scriptie. \n", + "Rolf wil ik in het bijzonder bedanken voor de wekelijkse meetings en ondersteuning.\n", + "Dank aan Mark Melotto en Andre van der Veen voor het open houden en onderhouden van de servers waar de modellen op draaien. \n", + "\n", + "Ook dank aan Andre van der Veen en Kate Brauman voor het verschaffen en erop wijzen van data en databases waar informatie te vinden was over de onderzochte gebieden. \n", + "Als laatste wil ik mijn vrienden en familie bedanken voor hun steun tijdens de duur van dit project. \n", + "\n", + "Julian Steenhuisen\n", + "Delft, Mei 2026" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/1_Inleiding.ipynb b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/1_Inleiding.ipynb new file mode 100644 index 00000000..6b722850 --- /dev/null +++ b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/1_Inleiding.ipynb @@ -0,0 +1,65 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "4a48b37e-55cd-43b9-9bcd-f399ab36da2b", + "metadata": {}, + "source": [ + "# 1 Inleiding" + ] + }, + { + "cell_type": "markdown", + "id": "bb848e91-592a-41cc-bcb6-c58965c6e566", + "metadata": {}, + "source": [ + "In Suriname bevindt zich met 20 miljoen kubieke kilometer één van de grootste stuwmeren ter wereld, het Prof. dr. ir. W.J. van Blommensteinmeer stuwmeer (National Geospatial-Intelligence Agency, 2024). Het stuwmeer heeft als doel de Afobaka waterkrachtcentrale te voorzien van water om elektriciteit op te wekken voor de helft van Suriname en wordt in de volksmond ook wel het Brokopondo meer genoemd (Donk et al., 2018). Het stilvallen van deze dam door een te lage waterstand in het meer zou dus grote gevolgen hebben voor het hele land. \n", + "\n", + "De impact van de klimaatverandering op de regenval in Suriname is nog niet in kaart gebracht, hoewel de instroom van water van het grootste belang is voor de centrale. Om deze reden is de onderzoeksvraag van dit verslag als volgt;\n", + "\n", + "_Wat is het effect van klimaatverandering op de kritische hoogte in het Brokopondo stuwmeer zodat de Afobaka waterkrachtcentrale genoeg stroom kan leveren?_" + ] + }, + { + "cell_type": "markdown", + "id": "1922dff5-6e36-41cb-b137-05367e926f4e", + "metadata": {}, + "source": [ + "Deze vraag zal beantwoord worden aan de hand van een aantal deelvragen;\n", + "* Bij welke waterhoogte in het stuwmeer werkt de waterkrachtcentrale niet meer naar behoren?\n", + "* Hoe is de instroom in het meer afhankelijk van de regenval in het bovenstroomse gebied?\n", + "* Wat is de verwachte toename in droge periodes voor het stroomgebied van de Surinamerivier in hoeveelheid en aantal voor verschillende klimaatscenario’s?" + ] + }, + { + "cell_type": "markdown", + "id": "24305cb9-0f22-48f8-be29-eb3e6067d255", + "metadata": {}, + "source": [ + "Om tot een conclusie te komen zal dit onderzoek uitgevoerd worden met behulp van een literatuuronderzoek en twee modellen op het eWatercycle platform. Het literatuuronderzoek in hoofdstuk 2 zal uitgevoerd worden met als doel ten eerste een dieper begrip te krijgen van de gevolgen van regentijden. Ten tweede zal er gezocht worden naar eerder afgerond onderzoek voor onderbouwing van aannames in het opstellen van de kritische waterhoogte. \n", + "Hoofdstuk 3 bevat een uitleg over de opzet van het onderzoek en hoofdstuk 4 heeft een uitleg over de gebruikte modellen. In hoofdstuk 5 wordt de droogte analyse uitgelegd. De toekomstige klimaatscenario’s bevinden zich in hoofdstuk 6. De resultaten van de modellen zijn zichtbaar in hoofdstuk 7 en de interpretatie van deze resultaten worden in hoofdstuk 8 behandeld. Als laatste is er een discussie over de validatie van het rapport in hoofdstuk 9. " + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/2_Literatuur_onderzoek.ipynb b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/2_Literatuur_onderzoek.ipynb new file mode 100644 index 00000000..ed9631b6 --- /dev/null +++ b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/2_Literatuur_onderzoek.ipynb @@ -0,0 +1,121 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "4253538e-4e33-4b8c-9e49-3f138fdc5bfb", + "metadata": {}, + "source": [ + "# 2 Literatuuronderzoek" + ] + }, + { + "cell_type": "markdown", + "id": "f650c006-680e-4566-9fc8-3f3f6a899a02", + "metadata": {}, + "source": [ + "## 2.1 Omgevingsanalyse" + ] + }, + { + "cell_type": "markdown", + "id": "6bc8aac8-aca6-49b2-a4cb-2f1fca19dfab", + "metadata": {}, + "source": [ + "De Suriname rivier bevindt zich in het midden van Suriname en is de op drie na grootste rivier in het land, met een lengte van 480 kilometer en eindigt in de Atlantische oceaan. De Surinamerivier bestaat uit 2 delen, Boven-Suriname en Onder-Suriname, gescheiden door het Brokopondo stuwmeer. De Boven-Suriname rivier is met een stroomgebied van 7629 km2 de belangrijkste toevoer van het Blommenstein stuwmeer.\n", + "\n", + "Het stuwmeer is in 1958 is ontworpen en de Afobakadam is gebouwd in 1965 ter behoefte van electriciteitsgeneratie met een vermogen van 189 megawatt, door middel van 6 turbines (Donk et al., 2018). De dam heeft een hoogte van 54 meter ten opzichte van de Surinamerivier die erachter doorstroomd op een hoogte van 7 meter ten opzichte van zeeniveau (Donk et al., 2018). De opgewekte elektriciteit werd vanaf het einde van de bouw tot 2019 gebruikt door het aluminium verwerkingsbedrijf Suralco, die ook de dam hebben beheerd tot die tijd (Sterl et al., 2020). In 2019 is het overgedragen aan de Surinaamse overheid en sindsdien heeft het ongeveer de helft van alle stroom in Suriname opgewekt met een vereiste opwekking van 700,8 GWh/jaar (Republic of Suriname, 2019). Tussen 2014 en 2018 was de energievraag van Suriname gemiddeld 1323 GWh/jaar (Donk et al., 2018). \n", + "\n", + "In een rapport van een energieonderzoek in Suriname is gebleken dat er 2 belangrijke afvoer waardes zijn van het Brokopondomeer (Sterl et al., 2020). De gemiddelde historische afvoer, de mean, is 200 m3/s en de middelste historische afvoer, de median, is 144,7 m3/s. Bij deze gemiddelde afvoer hoort een gemiddelde waterhoogte van 45,5 meter. " + ] + }, + { + "cell_type": "markdown", + "id": "ae20c865-5d9c-4b5c-a06d-f522a8a31eb9", + "metadata": {}, + "source": [ + "
\n", + " \n", + "
Figuur 1: Kaart van Suriname met de Surinamerivier en het Brokopondo stuwmeer. Wikipedia contributers. (2023), CC BY 4.0.
\n", + "
" + ] + }, + { + "cell_type": "markdown", + "id": "e6b642f9-87ba-4f42-8f4d-76d05cdbb4cb", + "metadata": {}, + "source": [ + "
\n", + " \n", + "
Figuur 2: Weergave stroomgebied Boven-Suriname en de verbinding met Brokopondo stuwmeer. Donk et al. (2018), CC BY 4.0.
\n", + "
" + ] + }, + { + "cell_type": "markdown", + "id": "5a50151a-e243-4100-a08a-421340c5a439", + "metadata": {}, + "source": [ + "## 2.2 Kritische waterhoogte voor stroomgeneratie" + ] + }, + { + "cell_type": "markdown", + "id": "fb94127e-fc5a-4523-9a75-a13d14f81a60", + "metadata": {}, + "source": [ + "De kritische waterhoogte is de waterhoogte waarbij de Afobakadam niet genoeg stroom kan genereren ter behoefte van Suriname. Om te berekenen welke waterhoogte er nodig is in het meer is de volgende formule gebruikt (Lucius, 2025);\n", + "\n", + "$${Q_{power}} = \\frac{P_{Suriname}}{\\eta \\rho g \\Delta h}$$\n", + "

[1]\n", + " \n", + "Deze formule bevat de volgende variabelen;" + ] + }, + { + "cell_type": "markdown", + "id": "0cce7677-8167-44c6-bc8c-95837b1ec11b", + "metadata": {}, + "source": [ + "*Table 1: Variabelen kritische waterhoogte formule.*\n", + "\n", + "| **Variabelen** | **Omschrijving** | **Waarde** |\n", + "|----------------------|--------------------------------|--------------|\n", + "| $Q_{\\text{power}}$ | Afvoer van Afobakadam | 200 [m^3/s] |\n", + "| $P_{\\text{Suriname}}$| Opgewekte energie | 80 [MW] |\n", + "| $\\eta$ | Energie efficiëntie coëfficiënt| 0,95 [-] |\n", + "| $\\rho$ | Dichtheid water | 1000 [kg/m^3]|\n", + "| $g$ | Zwaartekrachtversnelling | 9,81 [m/s^2] |\n", + "| $\\Delta h$ | Valhoogte water | 42,92 [m] |" + ] + }, + { + "cell_type": "markdown", + "id": "72cc0bdf-ff08-4b57-80f0-8cb389725b47", + "metadata": {}, + "source": [ + "De Afobakadam bevat 6 waarvan 3 een capaciteit hebben van 33 MW en 3 een capaciteit van 30 MW wat de dam een totaal vermogen geeft van 189 MW (Hydro, 2021). De vereiste energieopwekking van 700,8 MWh/jaar betekent een output van 80 MW dus de dam zal op minder dan de helft van de maximale kracht hoeven te draaien. Met een efficiëntie van 95% en een historisch gemiddelde uitstroom van 200 m3/s van de dam kan de benodigde valhoogte van het water worden vastgesteld op 42,92 meter (Donk et al., 2018). De hoogte van de Surinamerivier aan de achterkant van de Afobakadam staat op 7 meter hoogte ten opzichte van zeeniveau (Google Earth, 2026). " + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/3_Opzet_van_het_onderzoek.ipynb b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/3_Opzet_van_het_onderzoek.ipynb new file mode 100644 index 00000000..2aef28b0 --- /dev/null +++ b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/3_Opzet_van_het_onderzoek.ipynb @@ -0,0 +1,81 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "feabc93a-a0fd-4234-880a-608733c5b5db", + "metadata": {}, + "source": [ + "# 3 Opzet van het onderzoek" + ] + }, + { + "cell_type": "markdown", + "id": "d87c65ed-cf5e-42c2-85d6-a047feefd14e", + "metadata": {}, + "source": [ + "In dit onderzoek is er een hydrologisch model opgesteld met als doel toekomstvoorspellingen te maken voor het Brokopondomeer. Dit model is gebouwd en uitgevoerd op het eWatercycle platform in de vorm van Jupyter notebooks. \n", + "\n", + "Een hydrologisch model bestaat uit een set formules waarin regen- en verdampingsdata van een gebied wordt omgezet naar een uitkomst, vaak in de vorm van dagelijkse afstroomdata in kubieke meter per seconde. Deze data afkomstig van het model moet vergeleken worden met geobserveerde data van de rivier om te controleren of het model correct werkt. Als dit niet het geval is kunnen er parameters binnen de formules aangepast worden, net zolang tot de uitkomst gewenst is. \n", + "\n", + "In het geval van dit onderzoek was er geen afstroomdata van de Surinamerivier beschikbaar als vergelijking. Als oplossing hiervoor zijn er metingen gebruikt van het oppervlakte en de diepte van het meer om een eerste model te maken. De twee modellen en hun onderdelen binnen het hydrologische systeem van het Brokopondomeer zijn weergegeven in figuur 3. Dit model berekent de outflow van de rivier op basis van de dieptemetingen en geeft een weergave van de verwachte historische waardes om te vergelijken. \n", + "\n", + "Op basis van die instroomwaardes kan vervolgens het tweede model gekalibreerd worden wat de instroom van het meer zal berekenen aan de hand van neerslag en verdampingsdata. Deze metingen zijn aanwezig over hele grote tijdsperiodes en bevatten ook toekomstvoorspellingen. Dit tweede model moet overeenkomen met de instroom van het eerste model om een acceptabele voorspelling te kunnen doen. \n", + "\n", + "De output van het tweede model zal vervolgens gebruikt worden om de waterhoogte van het meer te bepalen. Over deze hoogte kunnen dan conclusies getrokken worden of het te laag gaat staan in verschillende klimaatscenario’s. \n" + ] + }, + { + "cell_type": "markdown", + "id": "35cb9897-a99b-4524-9efa-a3a3d1ad32aa", + "metadata": {}, + "source": [ + "

\n", + " \n", + "
Figuur 3: Stappen van het onderzoek op chronologische volgorde van links naar rechts. \n", + "
\n", + "
" + ] + }, + { + "cell_type": "markdown", + "id": "84895cfe-4cbd-49db-aa2a-8775a93ccde9", + "metadata": {}, + "source": [ + "
\n", + " \n", + "
Figuur 4: Schematisering van het afstroomgebied en het meer.\n", + "
\n", + "
" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bd40ae18-04f2-4570-85bb-0f290c8612ac", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/4_Het_model.ipynb b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/4_Het_model.ipynb new file mode 100644 index 00000000..c30d6c93 --- /dev/null +++ b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/4_Het_model.ipynb @@ -0,0 +1,222 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "c0af08af-4784-45cf-99b5-cfbe40e7e724", + "metadata": {}, + "source": [ + "# 4 Het model" + ] + }, + { + "cell_type": "markdown", + "id": "cfcc049f-daec-4962-81db-dcaa32740c42", + "metadata": {}, + "source": [ + "## 4.1 Instroom model" + ] + }, + { + "cell_type": "markdown", + "id": "42f4de47-836f-4be1-9048-1a033a9e74a6", + "metadata": {}, + "source": [ + "Het model wat is gebruikt om de regenval en verdamping van het stroomgebied van de Suriname rivier te verhouden aan een instroom is zelf opgesteld. Het is gemaakt aan de hand van de volgende formule met de variabelen eronder in tabel 2; \n", + "\n", + "\n", + "$${Q_{in}} = \\frac{\\Delta s}{\\Delta t} + E * A + Q_{uit}$$\n", + "

[2]" + ] + }, + { + "cell_type": "markdown", + "id": "ae605fb3-4602-415f-a836-75bec3fc4488", + "metadata": {}, + "source": [ + "*Tabel 2: Parameters instroom model.*\n", + "\n", + "| **Variabelen** | **Omschrijving** | \n", + "|---------------------|------------------------------------------------|\n", + "| $Q_{\\text{in}}$ | afvoer van het stroomgebied in het meer [m^3/s]| \n", + "| $\\Delta s/ \\Delta h$| Opslagverandering van het meer [m^3/s] | \n", + "| $E$ | Verdamping [m/s] | \n", + "| $A$ | Oppervlakte meer [m^2] | \n", + "| $Q_{\\text{uit}}$ | afvoer uit het meer [m^3/s] | \n" + ] + }, + { + "cell_type": "markdown", + "id": "46a2efe5-8ff5-44cd-bbcf-ba58b0874cc4", + "metadata": {}, + "source": [ + "De gemiddelde afvoer uit het meer is eerder vastgesteld op 200 m3/s en de verdamping van het meer is ERA5 forcing data van het stroomgebied. \n", + "Om de opslagverandering van formule 2 te bepalen zijn volumegegevens van het meer nodig over langere periode. Voor deze volumegegevens zijn hoogtemetingen via een hoogte-volumeverhouding berekend. Deze verhouding is vastgesteld door Sterl et al als volgt (2020);\n", + "\n", + "$$H = 8 + 15* ln(V + 2)$$\n", + "

[3]\n", + "\n", + "De dieptemetingen zijn verkregen via de openbare DAHITI database, ontwikkeld door het Duitse Geodetisch onderzoeksinstituut van de technische universiteit van München (DGFI-TUM, 2025). De oppervlakte metingen zijn vriendelijk verschaft door Kate Brauman, die ze zelf van de GRDC database heeft verkregen. \n", + "\n", + "Het meest opvallende aan de uitkomst van dit model is dat de berekende uitstroom weinig datapunten heeft over een periode van 8 jaar. De diepte gegevens zijn bepaald met een gat van 5 of 21 dagen ertussen, met sommige uitschieters van 32 dagen. Dit is het geval omdat deze gegevens met satellieten verkregen zijn en deze over het meer vliegen eenmaal in de 5 of 21 dagen. De uitzonderingen zullen momenten zijn geweest waarop er geen duidelijk beeld beschikbaar was van het meer en een meting is overgeslagen. Het gevolg is dan dat ook de afvoer dezelfde gaten heeft tussen datapunten. \n" + ] + }, + { + "cell_type": "markdown", + "id": "24bb5a99-306e-4101-80f9-af3297dd3d64", + "metadata": {}, + "source": [ + "## 4.2 Bovenstrooms model" + ] + }, + { + "cell_type": "markdown", + "id": "5a94f94e-ef4e-49c0-a5d6-ae413853feff", + "metadata": {}, + "source": [ + "Het bovenstrooms model is gemaakt aan de hand van de volgende formule met bijbehorende variabelen; \n", + "\n", + "$${Q_{in}} = Q_{gw} + \\alpha *((P-E)*A)^{\\beta}$$\n", + "

[3]" + ] + }, + { + "cell_type": "markdown", + "id": "25007bd8-f305-4bbc-aa09-74cb658d01c0", + "metadata": {}, + "source": [ + "*Tabel 3: Parameters bovenstrooms model met gevonden waardes na kalibratie.*\n", + "\n", + "| **Variabelen** | **Omschrijving** | **Waarde**|\n", + "|-----------------|------------------------------------------------|-----------|\n", + "| $Q_{\\text{pin}}$| Afvoer van het stroomgebied in het meer [m^3/s]| |\n", + "| $Q_{\\text{gw}}$ | Opslagverandering van het meer [m^3/s] | 1,30978424|\n", + "| $\\alpha$ | Afvoerconstante [-] | 0,39171679|\n", + "| $P$ | Neerslag [m/s] | |\n", + "| $E$ | Verdamping [m/s] | |\n", + "| $A$ | Oppervlakte stroomgebied [m^2] | |\n", + "| $\\beta$ | Afvoerexponent [-] | 1,05045276|" + ] + }, + { + "cell_type": "markdown", + "id": "67e16d5b-708c-4192-892d-59168c2960bb", + "metadata": {}, + "source": [ + "Deze formule neemt als input dagelijkse verdampings- neerslag waardes van het stroomgebied van ERA5 forcing en produceert hiermee een modelafvoer van de Surinamerivier. \n", + "\n", + "De grondwater afvoer, ook wel baseflow genoemd, is aangenomen als een constante waarde. Hoewel deze mogelijk zal veranderen aan de hand van droge en natte seizoenen is dit niet naar voren gekomen in eerdere onderzoeken over de Surinamerivier. " + ] + }, + { + "cell_type": "markdown", + "id": "0e20ef21-72bc-4547-b744-9df4ec1e820a", + "metadata": {}, + "source": [ + "## 4.3 Kalibratie modellen" + ] + }, + { + "cell_type": "markdown", + "id": "1527dd88-2817-4463-a476-6708c9eb06c1", + "metadata": {}, + "source": [ + "De kalibratie is gedaan aan de hand van de Root Mean Square Error (RMSE) test, Nash-Sutcliffe Efficiency (NSE) test en de log(NSE) test. Deze testen hebben de afvoer van het tweede model vergeleken met het eerste model en een score gegeven. Deze score geeft weer hoeveel de modellen verschillen en geeft een manier om ze te beoordelen. \n", + "\n", + "Voor RMSE zijn de scores gerangschikt van hoog, het slechtst, naar laag, het best met 0 als perfecte score. NSE en log(NSE) hebben allebei een score van 1 als perfect en 0 als een waarde waarbij het model niet beter is dan een gemiddelde waarde aannemen voor de hele set. Een waarde dichterbij 1 zal dus een betere uitkomst geven dan in de buurt of zelfs onder 0. \n", + "\n", + "De RMSE test is als volgt; \n", + "\n", + "$$RMSE=\\sqrt{\\frac{1}{n}\\sum\\left(\\left(Q_o^t-Q_m^t\\right)^2\\right)}$$\n", + "

[4]

\n", + "\n", + "De NSE test is als volgt (Nash & Sutcliffe, 1970); \n", + "\n", + "$$NSE=1-\\frac{\\sum_{t=1}^{T}\\left(Q_o^t-Q_m^t\\right)^2}\n", + "{\\sum_{t=1}^{T}\\left(Q_o^t-\\overline{Q_o}\\right)^2}$$\n", + "

[5]

\n", + "\n", + "De log(NSE) test is als volgt (Nash & Sutcliffe, 1970); \n", + "\n", + "$$\\log(NSE)=1-\\frac{\\sum_{t=1}^{T}\\left(\\log(Q_o^t)-\\log(Q_m^t)\\right)^2}\n", + "{\\sum_{t=1}^{T}\\left(\\log(Q_o^t)-\\log(\\overline{Q_o})\\right)^2}$$\n", + "

[6]

\n", + "\n", + "De bijbehorende variabelen van de formules zijn zichtbaar in tabel 4; \n" + ] + }, + { + "cell_type": "markdown", + "id": "62658b2a-97a3-4596-990e-43dc4d3e1e17", + "metadata": {}, + "source": [ + "*Tabel 4: Variabelen RMSE, NSE en log(NSE) testen.*\n", + "\n", + "| **Variabelen**| **Omschrijving** |\n", + "|---------------|-----------------------------------|\n", + "| $Q_{o}^{t}$ | Geobserveerde instroom, model 1 |\n", + "| $Q_{m}^{t}$ | Gemodelleerde instroom, model 2 |\n", + "| $Q_{o}^{-}$ | Gemiddelde geobserveerde instroom |\n", + "| $n$ | Aantal vergeleken punten |" + ] + }, + { + "cell_type": "markdown", + "id": "ad2d41e9-0c8c-4143-9999-f25edc6937ad", + "metadata": {}, + "source": [ + "Voor het vinden van een goede set parameters is er gebruik gemaakt van de Latin Hypercube Sampling (LHS) methode in python. Deze methode geeft een random groep parameters binnen handmatig ingevoerde grenzen op een manier waarop zoveel mogelijk van de range gebruikt wordt van alle parameters. \n", + "\n", + "De 3 testen zullen elk uitgevoerd worden op parameter set en geven elk de 10 beste scores en de bijbehorende parameters. Dit is een aantal keer uitgevoerd met steeds kleinere grenzen, tot een acceptabele set parameters werd gegenereerd. Deze parameter set is weergegeven in tabel 3. \n", + "\n", + "Omdat model 1 afhankelijk is van de hoogtemetingen van het Brokopondo stuwmeer zijn deze beschikbaar voor ongeveer 2 keer in de maand in tegenstelling tot model 2 wat dagelijkse afvoerwaardes produceert. Dit zorgt ervoor dat er niet evenveel punten zijn om te vergelijken. Hiervoor zijn de standaard testen aangepast om gemiddelde waardes te nemen van model 2 tussen de tijdspunten van model 1 en deze te vergelijken met de eerstvolgende waarde van model 1. Dit zorgt voor mogelijke afwijkingen op specifieke momenten, maar het doel is om de kalibratie uit te voeren op basis van het volume van de afvoer van de Surinamerivier. De cumulatieve afvoer geeft de volumeverandering van het meer het beste weer. \n", + "\n", + "De resultaten van de kalibraties zijn te zien in figuren 5 en 6, met respectievelijk de dagelijkse instroom en de cumulatieve instroom in het Brokopondo meer. In 2022 was er grote regenval gemeten terwijl de waterhoogte niet is gestegen volgens de metingen. Dit zorgt voor een afwijking in de modellen in dat jaar, maar de cumulatieve waardes in de jaren eromheen volgen elkaar wel correct. \n" + ] + }, + { + "cell_type": "markdown", + "id": "f4730f12-f049-4477-ad3f-8cc984a3fe18", + "metadata": {}, + "source": [ + "
\n", + " \n", + "
Figuur 5: Afvoer van bovenstrooms en instroom model.\n", + "
\n", + "
" + ] + }, + { + "cell_type": "markdown", + "id": "ebc3debd-a3fd-43f9-85d5-8fdac8b32489", + "metadata": {}, + "source": [ + "
\n", + " \n", + "
Figuur 6: Cumulatieve afvoer Surinamerivier.\n", + "
\n", + "
" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/5_Droogte_analyse.ipynb b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/5_Droogte_analyse.ipynb new file mode 100644 index 00000000..e21e8621 --- /dev/null +++ b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/5_Droogte_analyse.ipynb @@ -0,0 +1,99 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "68bc990a-4f8c-4f28-be6f-c2a2258958ae", + "metadata": {}, + "source": [ + "# 5 Droogte analyse" + ] + }, + { + "cell_type": "markdown", + "id": "d93fba03-1f0e-464f-acb0-0b8ceac21407", + "metadata": {}, + "source": [ + "## 5.1 Eisen voor droogte" + ] + }, + { + "cell_type": "markdown", + "id": "7acf8fe8-a8b9-4387-9f45-ba6ceb4d79e8", + "metadata": {}, + "source": [ + "De minimale valhoogte van het Brokopondo meer om voldoende vermogen te leveren is eerder vastgesteld op 42.92 meter. Als de valhoogte onder deze waarde zal komen dan zal er niet snel een probleem komen maar er zal langzaam een vermogenstekort ontstaan. Als deze voor lange tijd aanhoudt dan zal de Surinaamse overheid maatregelen moeten treffen. \n", + "\n", + "In een artikel van de Parbode Xtra is gezegd dat Januari 2025 een zeer droge maand was voor het Brokopondomeer en volgens energiebedrijven het water 4,5 meter lager stond dan normaal (Saaki, F, 2025). In deze periode geven de hoogtemetingen een waterhoogte van 40,5 meter voor een maand. In deze bron is weergegeven dat als deze droge tijd langer zou aanhouden er extra generatoren ingeschakeld zouden moeten worden wat de overheid 25 tot 45 miljoen US-dollar per maand zou kosten (Saaki, F, 2025). Op het moment dat dit artikel werd gepubliceerd was er al een maand aan droogte en deze heeft in totaal 2 maanden aangehouden, met hoge kosten als gevolg. Het is te concluderen dat het Brokopondomeer dus maximaal een maand op een waterhoogte van 40,5 meter kan zitten voordat er maatregelen getroffen moeten worden. \n", + "\n", + "De waterhoogte van 42,92 meter wordt aangenomen als kritische hoogte en 40,5 meter wordt aangenomen als zeer kritische hoogte. " + ] + }, + { + "cell_type": "markdown", + "id": "9e4863da-f917-4a03-b4ff-98db24fba94a", + "metadata": {}, + "source": [ + "## 5.2 Bepalen droogte" + ] + }, + { + "cell_type": "markdown", + "id": "4a9c696a-9903-44b7-aa4c-45b72854ed52", + "metadata": {}, + "source": [ + "De uitkomst van het tweede model is de afvoer van de Suriname rivier in kubieke meter per seconde. Deze afvoer zal samen met de verdamping en de afvoer van de Afobakadam de hoogte van het meer bepalen volgens formule 7. \n", + "\n", + "$$L = L_t + \\frac{Q_{in} - Q_{uit}}{A} - E$$\n", + "

[7]

" + ] + }, + { + "cell_type": "markdown", + "id": "d7160f44-a492-4071-8f82-52bec2773fc8", + "metadata": {}, + "source": [ + "*Tabel 5: Variabelen hoogte formule.*\n", + "\n", + "| **Variabelen**| **Omschrijving** |\n", + "|---------------|---------------------------------------------|\n", + "| $L$ | Hoogte Brokopondomeer [m] |\n", + "| $L_{t}$ | Hoogte Brokopondomeer op vorige tijdstip [m]|\n", + "| $Q_{in}$ | Afvoer Suriname rivier [m3] |\n", + "| $Q_{uit}$ | Afvoer Brokopondomeer [m3] |\n", + "| $A$ | Oppervlakte [m2] |\n", + "| $E$ | Verdamping [m] |" + ] + }, + { + "cell_type": "markdown", + "id": "22a8a7a6-c99a-4dd4-88e3-d8b9e2f4e3c8", + "metadata": {}, + "source": [ + "De hoogte is op dagelijkse basis berekend en heeft een maximum van 48,5 meter. Dit is de hoogte waarop de spuikleppen historisch gezien zijn opengezet (Misiekaba-Kia, 2022). In het geval van hoog water is niet bekend wat er met het water gebeurt en zal ervan uit worden gegaan dat dit afgevoerd wordt naar de Surinamerivier zonder extra energie te genereren. \n", + "\n", + "De hoogteveranderingen in de toekomst zullen geanalyseerd worden door een droogte functie waarin de datum, het hoogtetekort en de tijdsduur van de droogte gezocht en gevisualiseerd worden. \n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/6_Toekomstige_klimaatscenarios.ipynb b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/6_Toekomstige_klimaatscenarios.ipynb new file mode 100644 index 00000000..d3f103a7 --- /dev/null +++ b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/6_Toekomstige_klimaatscenarios.ipynb @@ -0,0 +1,91 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "f954ca37-33a7-4acb-a122-3cca0178b2d2", + "metadata": {}, + "source": [ + "# 6 Toekomstige klimaatscenario's" + ] + }, + { + "cell_type": "markdown", + "id": "df9a0eea-bd34-43e6-aff5-3ad8f029c1df", + "metadata": {}, + "source": [ + "## 6.1 Verschillende klimaatscenario's " + ] + }, + { + "cell_type": "markdown", + "id": "e7c70ba8-bab1-4103-bce7-da62c6869797", + "metadata": {}, + "source": [ + "Om toekomstvoorspellingen van de waterhoogte te kunnen maken is er via het eWatercycle platform CMIP data gebruikt. Dit zijn neerslag en verdamping voorspellingen gebaseerd op klimaat simulaties met verschillende broeikas emissies. \n", + "\n", + "Dit rapport gebruikt 3 CMIP klimaatscenario’s (TU Delft, 2017); \n", + "\n", + "* SSP1-2.6; de duurzame route. Groene energie en menselijke gezondheid staat centraal. \n", + "* SSP2-4.5; de middenweg. De maatschappij gaat door zoals het is gegaan zonder grote veranderingen, goed of slecht. \n", + "* SSP5-8.5; de laagste route. Fossiele brandstoffen worden veel gebruikt en de wereld zal energie intensief draaien. \n", + "\n", + "SSP1-2.6 zal minder extreme weersomstandigheden hebben en de seizoenen zullen terugvallen in het bestaande ritme. SSP2-4.5 en SSP5-8.5 zullen meer extreme gevallen hebben in de toekomst, wat betekent meer droge en natte periodes in vergelijken met de gemiddelde waardes. \n", + "\n", + "Deze klimaatscenario’s zijn gekozen omdat ze de meest extreme gevallen weergeven en een middenweg om het te vergelijken. Het is beter om voor te bereiden op het ergste geval, Suriname is te veel afhankelijk van deze dam om geen voorzorgsmaatregelen te nemen. \n" + ] + }, + { + "cell_type": "markdown", + "id": "5a65689b-aeb1-4892-977a-b984c6089b10", + "metadata": {}, + "source": [ + "## 6.2 Historische en toekomstige instroom" + ] + }, + { + "cell_type": "markdown", + "id": "a59e7b76-44f6-4266-9e10-98f95bd12509", + "metadata": {}, + "source": [ + "De CMIP neerslag en verdamping simulaties worden gebruikt in de toekomst tussen 2027 en 2099. Om te controleren of deze gegevens een realistisch beeld gaven is er historische data tussen 2019 en 2025 vergeleken met ERA5 data. Deze bleken niet overeen te komen en om dit op te lossen is er quantile mapping gebruikt. \n", + "\n", + "Quantile mapping is een bias-correctie methode om de output van een model aan te passen naar de werkelijkheid, in dit geval wordt het gebruikt om CMIP op de ERA5 data te laten lijken. Cumulatief was de originele CMIP neerslag data maar een vijfde van de ERA5 data. De quantile mapping was toegepast met de focus op de hoeveelheid neerslag en het aantal natte dagen over een lange periode goed krijgen. Zoals eerder gezegd had ERA5 in 2022 een grote hoeveelheid neerslag meer dan de oppervlakte metingen lieten zien. Dit verschil is ook terug zien in de figuur 7 waar er toch nog een verschil zit halverwege de grafiek. \n", + "\n", + "De piek neerslag van de gecorrigeerde CMIP data is hoger dan ERA5. Dit is gebeurd om de lagere kans op middelmatige neerslag uit te balanceren en het neerslag volume dichter bij de werkelijkheid te brengen. \n" + ] + }, + { + "cell_type": "markdown", + "id": "9e6bcf21-79b1-4b92-abaa-34b21ea617c2", + "metadata": {}, + "source": [ + "
\n", + " \n", + "
Figuur 7: Cumulatieve kans op hoeveelheid neerslag ERA5, CMIP en CMIP gecorrigeerd met quantile mapping.\n", + "
\n", + "
" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/7_Resultaten.ipynb b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/7_Resultaten.ipynb new file mode 100644 index 00000000..4ae96411 --- /dev/null +++ b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/7_Resultaten.ipynb @@ -0,0 +1,117 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "ecd61075-72b1-4341-b322-744d2793436a", + "metadata": {}, + "source": [ + "# 7 Resultaten" + ] + }, + { + "cell_type": "markdown", + "id": "750db426-0582-4a3d-b38b-88a32da329f7", + "metadata": {}, + "source": [ + "De hoogtewaardes van het Brokopondomeer in de verschillende klimaatscenario’s is weergegeven in figuur 8 van 2027 tot 2060. Na dit jaar bereiken de alle hoogtemetingen een onrealistisch lage waarde van het meer. Volgens formule 3 zou het meer bij een hoogte van 25 praktisch gezien droog staan aangezien het op dat punt 90% van zijn volume zou zijn verloren in vergelijking met de gemiddelde historische hoogte. \n", + "\n", + "In figuur 8 is goed te zien dat het minst positieve klimaatscenario SSP5.8-5 heel snel onder de kritische waardes komt en ook niet meer erboven komt. Dit scenario geeft weer dat het Brokopondomeer nog voor 3 jaar gebruikt kan worden, tot 2030, waarna het water onder de kritische hoogte blijft.\n", + "\n", + "SSP1.2-6 heeft na 2032 de kritische hoogte al bereikt en na 2034 is dit scenario al onder de zeer kritische hoogte. Hierna blijft de hoogte schommelen tussen 35 en 40 meter tot 2050, voordat het naar beneden zakt en niet meer terug klimt. \n", + "\n", + "SSP2.4-5 blijft tot 2035 boven de kritische hoogte, voordat het grotendeels tussen de kritische en zeer kritische hoogte schommelt. Na 2051 zakt de waterhoogte langzaam naar beneden zonder terug te komen boven de zeer kritische hoogte. \n" + ] + }, + { + "cell_type": "markdown", + "id": "d52c9892-f19e-4cdf-8dd1-3bf15e0ea4d9", + "metadata": {}, + "source": [ + "
\n", + " \n", + "
Figuur 8: Hoogtevoorspellingen tussen 2027 en 2060 per klimaatscenario.\n", + "
\n", + "
" + ] + }, + { + "cell_type": "markdown", + "id": "142549d8-fb34-4010-b7f7-65da0f42111f", + "metadata": {}, + "source": [ + "De SSP5.8-5 heeft elk jaar zo veel neerslagtekort dat het waterniveau volgens het model bijna elk jaar gemiddeld lager ligt dan het jaar ervoor. In figuur 9 is dit te zien via het jaarlijkse hoogtetekort ten opzichte van de kritische hoogte. \n", + "\\\n", + "Ook is op te merken dat hoewel alle 3 de klimaatscenario’s onder de kritische waterhoogte vallen binnen 10 jaar er veel verschil zit in de hoeveelheid hoogtetekort. SSP1.2-6 heeft tussen 2031 en 2051 maar 1 jaar waarin het een lager hoogtetekort heeft dan SSP2.4-5. \n" + ] + }, + { + "cell_type": "markdown", + "id": "6a4a3457-0b62-4c75-8630-04e542e683c9", + "metadata": {}, + "source": [ + "
\n", + " \n", + "
Figuur 9: Hoogtetekort ten opzichte van de kritische hoogte in een jaar per klimaatscenario.\n", + "
\n", + "
" + ] + }, + { + "cell_type": "markdown", + "id": "6605c34f-3ad5-4b74-9384-0a1f348df70d", + "metadata": {}, + "source": [ + "Naast het hoogtetekort is de andere belangrijke factor het aantal droge dagen in een jaar. In figuren 10 en 11 staan het aantal droge dagen per scenario, voor de kritische en zeer kritische hoogtes respectievelijk. SSP1.2-6 en SSP5.8-5 stijgen voor 2033 naar een volledig jaar onder de kritische hoogte terwijl SSP2.4-5 pas na 2034 droge dagen krijgt en nog 2 keer terug gaat naar een hoogte boven het kritisch niveau. \n", + "\\\n", + "SSP1.2-6 en SSP2.4-5 hebben allebei meer dan 30 droge dagen bij de zeer kritische hoogte in elk jaar dat er droge dagen zijn. Dit is belangrijk in verband met de eerder gevonden kritische droge tijd van een maand. \n", + "\\\n", + "Er is te zien dat de 2 positievere scenario’s meer schommelen rondom de zeer kritische hoogte dan om de kritische hoogte met het aantal droge dagen. Alle scenario’s bereiken de zeer kritische hoogte niet meer na 2051. \n" + ] + }, + { + "cell_type": "markdown", + "id": "3742bd45-cabf-4f7a-b24d-a8d297d1594b", + "metadata": {}, + "source": [ + "
\n", + " \n", + "
Figuur 10: Aantal dagen waar het waterniveau onder de kritische hoogte ligt per klimaatscenario.\n", + "
\n", + "
" + ] + }, + { + "cell_type": "markdown", + "id": "f5af688f-4293-4690-946b-e6b67a57970b", + "metadata": {}, + "source": [ + "
\n", + " \n", + "
Figuur 11: Aantal dagen waar het waterniveau onder de zeer kritische hoogte ligt per klimaatscenario.\n", + "
\n", + "
" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/8_Conclusie_en_aanbevelingen.ipynb b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/8_Conclusie_en_aanbevelingen.ipynb new file mode 100644 index 00000000..2be3ccd5 --- /dev/null +++ b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/8_Conclusie_en_aanbevelingen.ipynb @@ -0,0 +1,49 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "21582d96-5f74-4dff-b257-2886f34d1ce6", + "metadata": {}, + "source": [ + "## 9 Discussie" + ] + }, + { + "cell_type": "markdown", + "id": "cdae93f5-fb75-4d8e-bd45-f59f0ea9bdd8", + "metadata": {}, + "source": [ + "Dit rapport had veel stappen om tot een eindantwoord te komen. Het zorgde voor een flinke uitdaging om het allemaal op elkaar aan te laten sluiten maar het is gelukt. \n", + "\\\n", + "De hoogte en oppervlakte data was alleen beschikbaar elke 5 of 21 dagen wat een groot verschil is met de dagelijkse instroom waar model 2 uiteindelijk mee moest werken. Dit is op zichzelf geen probleem maar het door de lage hoeveelheid metingen zorgt er wel voor dat de precisie van model 1 omlaag gaat. Aangezien model 2 werd gekalibreerd op model 1 moest er met gemiddeldes gewerkt worden, wat het rapport niet minder valideert maar er wel voor zorgt dat het model op kleinere tijdschaal veel minder betrouwbaar is. De conclusies zijn daarom getrokken op basis van jaarlijkse drogen dagen en niet op het precies aantal droge dagen. \n", + "\n", + "Zoals benoemd in hoofdstuk 3 en 4.2 is er een eigen model gemaakt om te gebruiken binnen het eWatercycle platform. Dit model is afhankelijk van formule 3 en is een redelijk versimpelde versie van de realiteit. Waar andere modellen binnen het platform grondvochtigheid en andere parameters gebruiken om een beter beeld te geven van het stroomgebied kijkt deze formule alleen naar hoeveel water er direct van de grond naar het meer gaat. Dit is gedaan om het project niet te over compliceren en het werkte goed genoeg om de aanname te kunnen maken. De overeenkomsten tussen de metingen en modellen waren groot genoeg om er mee te kunnen werken. \n", + "\n", + "Bij de vergelijking van de toekomstige CMIP data met de ERA5 data is er gezien dat ERA5 een grote piek had in neerslag in 2022 wat niet voor is gekomen in de CMIP. Deze piek is ook niet teruggevonden in de oppervlakte en hoogte metingen van het stuwmeer dus het is aangenomen als een uitzondering. Dit jaar is niet meegenomen in de kalibratie om te zorgen dat de modellen goed werken voor de meerderheid van de jaren. \n", + "\n", + "Als vervolg onderzoek is het een idee om te kijken naar meerdere scenario’s van verschillende afvoervolumes en zoeken of er een manier is om het waterpeil hoog te houden zonder dat er een stroomtekort is. Hiervoor zou er ook meer onderzoek moeten komen naar de benodigde stroomhoeveelheid op verschillende tijdstippen om te weten of het plan mogelijk is. \n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/9_Discussie.ipynb b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/9_Discussie.ipynb new file mode 100644 index 00000000..7811d30e --- /dev/null +++ b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/9_Discussie.ipynb @@ -0,0 +1,33 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "34854d63-8eaa-4072-bafe-3506956a0d81", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Appendix_A.ipynb b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Appendix_A.ipynb new file mode 100644 index 00000000..0e6a7743 --- /dev/null +++ b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Appendix_A.ipynb @@ -0,0 +1,75 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "889fc788-2675-463f-be3c-5d1bd69b61a4", + "metadata": {}, + "source": [ + "# Appendix " + ] + }, + { + "cell_type": "markdown", + "id": "3f730254-d252-4492-882a-e9bc47eea731", + "metadata": {}, + "source": [ + "_Achtergrond informatie over verschillende onderdelen dat niet goed in het rapport gezet kon worden._\n", + "\n", + "Voor de hoogtemetingen van het stuwmeer zijn metingen van DAHITI gebruikt. Deze metingen hebben grote gaten ertussen zitten. Aangezien model 2 dagelijkse metingen heeft en is gekalibreerd op basis van model 1 zijn dit ook de dagen waarover het gemiddelde is genomen om te vergelijken .In figuur 12 is weergegeven hoeveel tijd er tussen de metingen zat in dagen. " + ] + }, + { + "cell_type": "markdown", + "id": "e664c3e8-c325-4228-8830-1372a6c46f86", + "metadata": {}, + "source": [ + "
\n", + " \n", + "
Figuur 12: Tijd tussen DAHITI hoogtemetingen van het Brokopondomeer\n", + "
\n", + "
" + ] + }, + { + "cell_type": "markdown", + "id": "78e67a9f-0f68-4bfc-9363-9385b2624c1d", + "metadata": {}, + "source": [ + "Voor de verhouding tussen de hoogte en het volume van het stuwmeer is er gebruik gemaakt van een energierapport van Sterl et al. In dat rapport is er een rule curve gebruikt als versimpeling van de verhouding bij hoge waterstanden (Sterl et al., 2020). In het huidige rapport is er gebruik gemaakt van de meer accurate verhouding, de oranje lijn zichtbaar in figuur 13. " + ] + }, + { + "cell_type": "markdown", + "id": "53e53c12-c7f9-4ead-988e-4b5ec4d46bb5", + "metadata": {}, + "source": [ + "
\n", + " \n", + "
Figuur 13: Verhouding hoogte en volume Brokopondomeer. \n", + "
\n", + "
" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Bronnenlijst.ipynb b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Bronnenlijst.ipynb new file mode 100644 index 00000000..2a1f55b0 --- /dev/null +++ b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Bronnenlijst.ipynb @@ -0,0 +1,82 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "e6012c9e-e32c-43fd-9276-5c7cb230bc83", + "metadata": {}, + "source": [ + "# Bronnenlijst" + ] + }, + { + "cell_type": "markdown", + "id": "eb11088f-c89c-4488-90a2-424b984b4e40", + "metadata": {}, + "source": [ + "Algemeen Bureau voor de Statistiek. (2023). SURINAME Klimaatverandering Statistieken en Indicatoren. 52–60. https://www.undp.org/sites/g/files/zskgke326/files/2024-09/undp-sr-first-suriname-cc-report_climate-change-statistics-and-indicators.pdf\n", + "\n", + "DGFI-TUM. (2025). Database for Hydrological Time Series of Inland Waters (DAHITI). Dgfi.tum.de; Deutsches Geodätisches Forschungsinstitut. https://dahiti.dgfi.tum.de/en/\n", + "\n", + "Donk, P., Van Uytven, E., Willems, P., & Taylor, M. A. (2018). Assessment of the potential implications of a 1.5 °C versus higher global temperature rise for the Afobaka hydropower scheme in Suriname. Regional Environmental Change, 18(8), 2283–2295. https://doi.org/10.1007/s10113-018-1339-1\n", + "\n", + "Donk, P., Willems, P., & Nurmohamed, R. (2013, October 8). Modelling the impact of climate change on the hydropower potential of the Kabalebo river basin in Suriname. ResearchGate; unknown. https://www.researchgate.net/publication/273122803_Modelling_the_impact_of_climate_change_on_the_hydropower_potential_of_the_Kabalebo_river_basin_in_Suriname\n", + "\n", + "Extreem lage waterstand stuwmeer legt druk op energievoorziening. (2025). Surinametimes.com. https://www.surinametimes.com/artikel/extreem-lage-waterstand-stuwmeer-legt-druk-op-energievoorziening\n", + "\n", + "Google Earth. (2026). Google Earth; Google. https://earth.google.com/web/@4.98274945,-54.99073869,17.34025871a,775.9702658d,35y,0h,0t,0r/data=CgRCAggBOgMKATBCAggASg0I____________ARAA\n", + "\n", + "Hydro. (2021, July 6). Suriname studying possible modernization of 189-MW Afobaka hydro. Factor ThisTM. https://www.renewableenergyworld.com/hydro-power/dams-civil-structures/suriname-studying-possible-modernization-of-189-mw-afobaka-hydro/\n", + "\n", + "Lucius, Z. (2025). The Future of the Kariba Dam - Zoë Lucius — eWaterCycle projects. Ewatercycle.org. https://www.ewatercycle.org/projects/main/thesis_projects/BSc/2025_Q4_ZoeLucius_CEG/BSc_ZoeLucius.html\n", + "\n", + "Melotto, M., & Hut, R. (2022). Different Models — Getting Started With eWaterCycle. Ewatercycle.org. https://www.ewatercycle.org/getting-started/main/content/different_models.html\n", + "\n", + "Misiekaba-Kia, P. (2022). Starnieuws - Brokopondo nog steeds gekwetst na overstromingen 2022. Starnieuws.com. https://www.starnieuws.com/index.php/welcome/index/nieuwsitem/77759\n", + "\n", + "Nash, J. E., & Sutcliffe, J. V. (1970). River flow forecasting through conceptual models part I — A discussion of principles. Journal of Hydrology, 10, 3. https://doi.org/10.1016/0022-1694(70)90255-6\n", + "\n", + "National Geospatial-Intelligence Agency. (2024). Afobaka Dam, Suriname - Geographical Names, map, geographic coordinates. Geographic.org; National Geospatial-Intelligence Agency. https://geographic.org/geographic_names/name.php?uni=-1351582&fid=4449&c=suriname\n", + "\n", + "Nurmohamed, R., Naipal, S., & De Smedt, F. (2007). Modeling hydrological response of the Upper Suriname river basin to climate change. BYU ScholarsArchive. https://scholarsarchive.byu.edu/josh/vol7/iss1/6/?utm_source=scholarsarchive.byu.edu%2Fjosh%2Fvol7%2Fiss1%2F6&utm_medium=PDF&utm_campaign=PDFCoverPages\n", + "\n", + "Nurmohamed, R., & Peter, D. (2017). The Impact of Climate Change and Climate Variability on The Agricultural Sector in Nickerie District. Journal of Agriculture and Environmental Sciences. https://doi.org/10.15640/jaes.v6n1a6\n", + "\n", + "Palis, A. (2025). “SPCS hoort als dochteronderneming van Staatsolie op de hoogte te zijn van de effecten van klimaatverandering” - KEY NEWS SURINAME. KEY NEWS SURINAME. https://keynews.sr/abeleven-we-hebben-alles-gedaan-wat-we-kunnen/\n", + "\n", + "Republic of Suriname. (2019). Afobaka Dam Acquisition To Improve Efficiency of Suriname’s Energy Sector.\n", + "\n", + "Saaki, F. (2025, March 12). Parbode Xtra: Lage waterstand stuwmeer zorgt voor onrust bij autoriteiten; extra kosten kunnen oplopen tot 45 miljoen US-dollar - Parbode. Parbode. https://www.parbode.com/parbode-xtra-lage-waterstand-stuwmeer-zorgt-voor-onrust-bij-autoriteiten-extra-kosten-kunnen-oplopen-tot-45-miljoen-us-dollar/\n", + "\n", + "Sterl, S., Donk, P., Willems, P., & Thiery, W. (2020). Turbines of the Caribbean: Decarbonising Suriname’s electricity mix through hydro-supported integration of wind power. Renewable and Sustainable Energy Reviews, 134, 110352. https://doi.org/10.1016/j.rser.2020.110352\n", + "\n", + "TU Delft. (2017). Socioeconomic Pathways. TU Delft. https://www.tudelft.nl/sustainability/environmental-literacy/socioeconomic-pathways\n", + "Understand low-carbon energy in Suriname through Data. (2024). Lowcarbonpower.org. https://lowcarbonpower.org/region/Suriname\n", + "\n", + "Wikipedia. (2018, July 11). File:Brokopondo reservoir.jpg. Wikipedia; Wikimedia Foundation. https://en.wikipedia.org/wiki/File:Brokopondo_reservoir.jpg\n", + "\n", + "Wikipedia contributers. (2023, April 10). Bestand:Rivers of Suriname.png - Wikipedia. Wikipedia.org. https://nl.wikipedia.org/wiki/Bestand:Rivers_of_Suriname.png\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Afvoermodellen_2.png b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Afvoermodellen_2.png new file mode 100644 index 00000000..2dde7849 Binary files /dev/null and b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Afvoermodellen_2.png differ diff --git a/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Afvoermodellen_2.png.yml b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Afvoermodellen_2.png.yml new file mode 100644 index 00000000..eeec9b09 --- /dev/null +++ b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Afvoermodellen_2.png.yml @@ -0,0 +1,3 @@ +author: "Julian Steenhuisen" +license: "CC-BY-4.0" +date: "18-06-2026" \ No newline at end of file diff --git a/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Afvoermodellen_cumulatief_2.png b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Afvoermodellen_cumulatief_2.png new file mode 100644 index 00000000..2ba873ee Binary files /dev/null and b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Afvoermodellen_cumulatief_2.png differ diff --git a/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Afvoermodellen_cumulatief_2.png.yml b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Afvoermodellen_cumulatief_2.png.yml new file mode 100644 index 00000000..eeec9b09 --- /dev/null +++ b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Afvoermodellen_cumulatief_2.png.yml @@ -0,0 +1,3 @@ +author: "Julian Steenhuisen" +license: "CC-BY-4.0" +date: "18-06-2026" \ No newline at end of file diff --git a/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/CMIP_quantile_2.png b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/CMIP_quantile_2.png new file mode 100644 index 00000000..02694450 Binary files /dev/null and b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/CMIP_quantile_2.png differ diff --git a/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/CMIP_quantile_2.png.yml b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/CMIP_quantile_2.png.yml new file mode 100644 index 00000000..eeec9b09 --- /dev/null +++ b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/CMIP_quantile_2.png.yml @@ -0,0 +1,3 @@ +author: "Julian Steenhuisen" +license: "CC-BY-4.0" +date: "18-06-2026" \ No newline at end of file diff --git a/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/DAHITI_2.png b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/DAHITI_2.png new file mode 100644 index 00000000..6a4cd6a7 Binary files /dev/null and b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/DAHITI_2.png differ diff --git a/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/DAHITI_2.png.yml b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/DAHITI_2.png.yml new file mode 100644 index 00000000..eeec9b09 --- /dev/null +++ b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/DAHITI_2.png.yml @@ -0,0 +1,3 @@ +author: "Julian Steenhuisen" +license: "CC-BY-4.0" +date: "18-06-2026" \ No newline at end of file diff --git a/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Hoogte_resultaten_2.png b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Hoogte_resultaten_2.png new file mode 100644 index 00000000..ca2ca331 Binary files /dev/null and b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Hoogte_resultaten_2.png differ diff --git a/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Hoogte_resultaten_2.png.yml b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Hoogte_resultaten_2.png.yml new file mode 100644 index 00000000..eeec9b09 --- /dev/null +++ b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Hoogte_resultaten_2.png.yml @@ -0,0 +1,3 @@ +author: "Julian Steenhuisen" +license: "CC-BY-4.0" +date: "18-06-2026" \ No newline at end of file diff --git a/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Hoogtetekort_2.png b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Hoogtetekort_2.png new file mode 100644 index 00000000..cf19d3c6 Binary files /dev/null and b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Hoogtetekort_2.png differ diff --git a/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Hoogtetekort_2.png.yml b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Hoogtetekort_2.png.yml new file mode 100644 index 00000000..eeec9b09 --- /dev/null +++ b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Hoogtetekort_2.png.yml @@ -0,0 +1,3 @@ +author: "Julian Steenhuisen" +license: "CC-BY-4.0" +date: "18-06-2026" \ No newline at end of file diff --git a/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Hoogteverhouding_2.png b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Hoogteverhouding_2.png new file mode 100644 index 00000000..45f748a5 Binary files /dev/null and b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Hoogteverhouding_2.png differ diff --git a/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Hoogteverhouding_2.png.yml b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Hoogteverhouding_2.png.yml new file mode 100644 index 00000000..eeec9b09 --- /dev/null +++ b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Hoogteverhouding_2.png.yml @@ -0,0 +1,3 @@ +author: "Julian Steenhuisen" +license: "CC-BY-4.0" +date: "18-06-2026" \ No newline at end of file diff --git a/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Kritisch_hoogtetekort_2.png b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Kritisch_hoogtetekort_2.png new file mode 100644 index 00000000..366f3043 Binary files /dev/null and b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Kritisch_hoogtetekort_2.png differ diff --git a/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Kritisch_hoogtetekort_2.png.yml b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Kritisch_hoogtetekort_2.png.yml new file mode 100644 index 00000000..eeec9b09 --- /dev/null +++ b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Kritisch_hoogtetekort_2.png.yml @@ -0,0 +1,3 @@ +author: "Julian Steenhuisen" +license: "CC-BY-4.0" +date: "18-06-2026" \ No newline at end of file diff --git a/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Schematisering modellen.png b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Schematisering modellen.png new file mode 100644 index 00000000..44b61758 Binary files /dev/null and b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Schematisering modellen.png differ diff --git a/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Schematisering modellen.png.yml b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Schematisering modellen.png.yml new file mode 100644 index 00000000..eeec9b09 --- /dev/null +++ b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Schematisering modellen.png.yml @@ -0,0 +1,3 @@ +author: "Julian Steenhuisen" +license: "CC-BY-4.0" +date: "18-06-2026" \ No newline at end of file diff --git a/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Stappenplan.png b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Stappenplan.png new file mode 100644 index 00000000..621fa890 Binary files /dev/null and b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Stappenplan.png differ diff --git a/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Stappenplan.png.yml b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Stappenplan.png.yml new file mode 100644 index 00000000..eeec9b09 --- /dev/null +++ b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Stappenplan.png.yml @@ -0,0 +1,3 @@ +author: "Julian Steenhuisen" +license: "CC-BY-4.0" +date: "18-06-2026" \ No newline at end of file diff --git a/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Suriname_Kaart.png b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Suriname_Kaart.png new file mode 100644 index 00000000..d86231c3 Binary files /dev/null and b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Suriname_Kaart.png differ diff --git a/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Suriname_Kaart.png.yml b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Suriname_Kaart.png.yml new file mode 100644 index 00000000..6b6f74d3 --- /dev/null +++ b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Suriname_Kaart.png.yml @@ -0,0 +1,3 @@ +author: "Wikipedia contributers" +license: "CC-BY-4.0" +date: "20-05-2026" \ No newline at end of file diff --git a/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Suriname_stroomgebied.png b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Suriname_stroomgebied.png new file mode 100644 index 00000000..5a915254 Binary files /dev/null and b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Suriname_stroomgebied.png differ diff --git a/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Suriname_stroomgebied.png.yml b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Suriname_stroomgebied.png.yml new file mode 100644 index 00000000..c6725de5 --- /dev/null +++ b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Suriname_stroomgebied.png.yml @@ -0,0 +1,3 @@ +author: "Donk et al." +license: "CC-BY-4.0" +date: "19-05-2026" \ No newline at end of file diff --git a/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Zeer_kritisch_hoogtetekort_2.png b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Zeer_kritisch_hoogtetekort_2.png new file mode 100644 index 00000000..0acd90ad Binary files /dev/null and b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Zeer_kritisch_hoogtetekort_2.png differ diff --git a/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Zeer_kritisch_hoogtetekort_2.png.yml b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Zeer_kritisch_hoogtetekort_2.png.yml new file mode 100644 index 00000000..eeec9b09 --- /dev/null +++ b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Rapport/Figuren/Zeer_kritisch_hoogtetekort_2.png.yml @@ -0,0 +1,3 @@ +author: "Julian Steenhuisen" +license: "CC-BY-4.0" +date: "18-06-2026" \ No newline at end of file diff --git a/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Under_construction/Future_analysis_.ipynb b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Under_construction/Future_analysis_.ipynb new file mode 100644 index 00000000..2f018def --- /dev/null +++ b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Under_construction/Future_analysis_.ipynb @@ -0,0 +1,930 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "30966fee-6a27-4380-8325-a1299e23a57b", + "metadata": {}, + "outputs": [], + "source": [ + "plt.figure(figsize=(16, 7))\n", + "plt.plot(model_output_m3s_logNSE.index, a, label = \"Height [m]\")\n", + "\n", + "plt.xlabel(\"Date\")\n", + "plt.ylabel(\"Height (m)\")\n", + "plt.title(\"Height function\")\n", + "plt.legend()\n", + "plt.grid(True)\n", + "plt.show()\n", + "\n", + "np.set_printoptions(suppress=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2185f0d7-84ed-4d8a-8476-ce85fef66275", + "metadata": {}, + "outputs": [], + "source": [ + "import warnings\n", + "warnings.filterwarnings(\"ignore\", category=UserWarning)\n", + "import numpy as np\n", + "from pathlib import Path\n", + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "import xarray as xr\n", + "# import geopandas as gpd\n", + "import pandas as pd\n", + "import seaborn as sns\n", + "from scipy.stats import qmc\n", + "from ipywidgets import IntProgress\n", + "import math as math\n", + "\n", + "# importeren van ewatercycle\n", + "import ewatercycle\n", + "import ewatercycle.models\n", + "import ewatercycle.forcing\n", + "\n", + "from ewatercycle_discharge import DischargeLocal\n", + "\n", + "shape_file_area = 7.629080e+03 # in km^2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fa26b618-6476-4dda-9e42-94dd92dbadc5", + "metadata": {}, + "outputs": [], + "source": [ + "basin_name = \"boven_suriname\"\n", + "\n", + "historical_start_date = \"2019-01-01\"\n", + "historical_end_date = \"2024-12-31\"\n", + "future_start_data = \"2027-01-01\"\n", + "future_end_data = \"2099-12-31\"\n", + "\n", + "shapefile = Path.home() / \"BEP-Julian\" / \"BEP-Julian\" / \"Suriname_Model\" / \"boven_suriname.shp\"\n", + "\n", + "forcing_route_CMIP = Path.home() / \"BEP-Julian\" / \"BEP-Julian\" / \"Forcing\" / \"CMIP\"\n", + "\n", + "forcing_route = Path.home() / \"BEP-Julian\" / \"BEP-Julian\" / \"Forcing\" / \"ERA5_SUR_2019_2024\"/ \"work\" / \"diagnostic\" / \"script\" \n", + "\n", + "Eigen_model = Path.home() / \"BEP-Julian\" / \"BEP-Julian\" / \"Suriname_Model\" / \"discharge_bmi\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3c7d239b-e11b-4536-a2a9-871b3b124fa6", + "metadata": {}, + "outputs": [], + "source": [ + "# # Option one: Generate CMIP data\n", + "# cmip_dataset = {\n", + "# 'project': 'CMIP6',\n", + "# 'activity': 'ScenarioMIP',\n", + "# 'exp': 'ssp245', # veranderen per generatie CMIP data\n", + "# 'mip': 'day',\n", + "# 'dataset': 'MPI-ESM1-2-HR',\n", + "# 'ensemble': 'r1i1p1f1',\n", + "# 'institute': 'DKRZ',\n", + "# 'grid': 'gn'\n", + "# }\n", + "\n", + "# cmip_historical = {\n", + "# 'project': 'CMIP6',\n", + "# 'exp': 'historical',\n", + "# 'dataset': 'MPI-ESM1-2-HR',\n", + "# \"ensemble\": 'r1i1p1f1',\n", + "# 'grid': 'gn'\n", + "# }\n", + "\n", + "## verschillende datapunten. Historical is CMIP ssp245 voor 2019-2024.\n", + "# ssp126_dir = forcing_route_CMIP / \"SSP126_26-99\"\n", + "# ssp245_dir = forcing_route_CMIP / \"SSP245_26-99\"\n", + "# ssp585_dir = forcing_route_CMIP / \"SSP585_26-99\"\n", + "# historical = forcing_route_CMIP / \"historical\"\n", + "\n", + "# CMIP_forcing = ewatercycle.forcing.sources[\"LumpedMakkinkForcing\"].generate(\n", + "# dataset=cmip_dataset, # veranderen per generatie CMIP data\n", + "# start_time=historical_start_date+\"T00:00:00Z\",\n", + "# end_time=historical_end_date+\"T00:00:00Z\",\n", + "# shape=shapefile,\n", + "# directory=historical, # veranderen per generatie CMIP data\n", + "# )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b2af3044-9211-4f38-bd56-f4e07cc4126d", + "metadata": {}, + "outputs": [], + "source": [ + "# Option two: load generated data\n", + "# Load historical data\n", + "historic_location = forcing_route_CMIP / \"historical\" / \"work\" / \"diagnostic\" / \"script\" \n", + "HIST = ewatercycle.forcing.sources[\"LumpedMakkinkForcing\"].load(directory=historic_location)\n", + "\n", + "# Load SSP126 data\n", + "ssp126_location = forcing_route_CMIP / \"SSP126_26-99\" / \"work\" / \"diagnostic\" / \"script\" \n", + "SSP126 = ewatercycle.forcing.sources[\"LumpedMakkinkForcing\"].load(directory=ssp126_location)\n", + "\n", + "# Load SSP245 data\n", + "ssp245_location = forcing_route_CMIP / \"SSP245_26-99\" / \"work\" / \"diagnostic\" / \"script\" \n", + "SSP245 = ewatercycle.forcing.sources[\"LumpedMakkinkForcing\"].load(directory=ssp245_location)\n", + "\n", + "# Load SSP585 data\n", + "ssp585_location = forcing_route_CMIP / \"SSP585_26-99\" / \"work\" / \"diagnostic\" / \"script\" \n", + "SSP585 = ewatercycle.forcing.sources[\"LumpedMakkinkForcing\"].load(directory=ssp585_location)\n", + "\n", + "ERA5_forcing = ewatercycle.forcing.sources[\"LumpedMakkinkForcing\"].load(directory=forcing_route)\n", + "evap = ERA5_forcing.to_xarray()[\"evspsblpot\"] #units: kg m^-2 s^-1 = mm/s, gesampled per dag\n", + "prec = ERA5_forcing.to_xarray()[\"pr\"] #units: kg m^-2 s^-1 = mm/s, gesampled per dag" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f049f1cb-ff8b-415a-b491-4509ae691639", + "metadata": {}, + "outputs": [], + "source": [ + "def level(Qin, Qout, ERA5_forcing, A, L0):\n", + " # Qin is array met discharge van rivier in meer, gebaseerd op E en P en dagelijks [m^3/s]\n", + " # Qout is een standaard baseflow uit het meer [m^3/s]\n", + " # E is verdampingsdata van ERA5, dagelijks [mm/s]\n", + " # A is oppervlakte meer [km^2]\n", + " # L0 is een gegeven begin hoogte [m]\n", + " # L0 moet handmatig worden ingevoerd omdat in de toekomst niet zeker is hoe hoog het meer gaat staan op het beginpunt van de forcing data\n", + " \n", + " dt = 3600*24\n", + " E = ERA5_forcing.to_xarray()[\"evspsblpot\"] /1000 #* dt\n", + " L = np.zeros(len(Qin))\n", + " L[0] = L0\n", + " A = A * 10**6\n", + " \n", + " for i in range(len(Qin)-1):\n", + " dL = ((Qin.iloc[i] - Qout) / A) - E[i]\n", + " L[i+1] = L[i] + dL*dt \n", + " if L[i+1] > 48.5:\n", + " L[i+1] = 48.5\n", + " return L" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e49fbdbd-c66f-4048-9c83-b9bd211a1ad2", + "metadata": {}, + "outputs": [], + "source": [ + "model = DischargeLocal(forcing = ERA5_forcing)\n", + "params = [1.30978424, 0.39171679, 1.05045276]\n", + "config_file, _ = model.setup(parameters=params, cfg_dir=Eigen_model)\n", + "\n", + "model.initialize(config_file)\n", + "Q_m = []\n", + "time = []\n", + "\n", + "while model.time < model.end_time:\n", + " model.update()\n", + " Q_m.append(model.get_value(\"Q\")[0])\n", + " time.append(pd.Timestamp(model.time_as_datetime))\n", + "\n", + "model.finalize()\n", + "model_output_mmday = pd.Series(data=Q_m, name=\"Modelled discharge\", index=time)\n", + "# print(model_output_mmday.max())\n", + "model_output_m3s_test = model_output_mmday * shape_file_area * 1000 / 86400" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3247aa65-0dd0-48d1-876a-b50aece9fc8c", + "metadata": {}, + "outputs": [], + "source": [ + "forcing_list = [HIST, SSP126, SSP245, SSP585] \n", + "output = []\n", + "years = []\n", + "params = [1.30978424, 0.39171679, 1.05045276]\n", + "\n", + "for forcings in forcing_list:\n", + " model = DischargeLocal(forcing=forcings)\n", + " config_file, _ = model.setup(\n", + " parameters=params, \n", + " cfg_dir = Eigen_model,\n", + " )\n", + "\n", + " model.initialize(config_file)\n", + "\n", + " Q_m = []\n", + " time = []\n", + " \n", + " while model.time < model.end_time:\n", + " model.update()\n", + " Q_m.append(model.get_value(\"Q\")[0])\n", + " time.append(pd.Timestamp(model.time_as_datetime))\n", + " \n", + " output.append(Q_m)\n", + " years.append(time)\n", + " \n", + " del Q_m, time\n", + " model.finalize()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c2f5f1fa-0c0f-4026-a79a-5477e1c938de", + "metadata": {}, + "outputs": [], + "source": [ + "historical_output = pd.Series(data=output[0], name=\"Historical\", index=years[0])[\"2019-01-01\":]\n", + "SSP126_output = pd.Series(data=output[1], name=\"SSP126\", index=years[1])[\"2027-01-01\":]\n", + "SSP245_output = pd.Series(data=output[2], name=\"SSP245\", index=years[2])[\"2027-01-01\":]\n", + "SSP585_output = pd.Series(data=output[3], name=\"SSP585\", index=years[3])[\"2027-01-01\":]\n", + "\n", + "# Convert mm/d to m3/s\n", + "factor = shape_file_area / 86.4\n", + "historical_output *= factor\n", + "SSP126_output *= factor\n", + "SSP245_output *= factor\n", + "SSP585_output *= factor" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6beb147e-9162-4868-ae24-8e37bfe1a886", + "metadata": {}, + "outputs": [], + "source": [ + "parameter_test = [1.30978424, 0.39171679, 1.05045276]\n", + "model = DischargeLocal(forcing = ERA5_forcing)\n", + "config_file, _ = model.setup(parameters=parameter_test, cfg_dir=Eigen_model)\n", + "\n", + "model.initialize(config_file)\n", + "Q_m = []\n", + "time = []\n", + "\n", + "while model.time < model.end_time:\n", + " model.update()\n", + " Q_m.append(model.get_value(\"Q\")[0])\n", + " time.append(pd.Timestamp(model.time_as_datetime))\n", + "\n", + "model.finalize()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "03c168b4-c74d-45eb-ba98-8871fbc46750", + "metadata": {}, + "outputs": [], + "source": [ + "# plot historische data als test\n", + "\n", + "plt.figure(figsize=(16, 7))\n", + "evap_hist = HIST.to_xarray()[\"evspsblpot\"] #units: kg m^-2 s^-1 = mm/s, gesampled per dag\n", + "prec_hist = HIST.to_xarray()[\"pr\"] #units: kg m^-2 s^-1 = mm/s, gesampled per dag\n", + "# prec_hist.plot()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "76ee1482-3103-4496-8eea-2828696d88f3", + "metadata": {}, + "outputs": [], + "source": [ + "prec = prec.compute()\n", + "evap = evap.compute()\n", + "\n", + "prec_hist = prec_hist.compute()\n", + "evap_hist = evap_hist.compute()\n", + "thr = 1e-7\n", + "era_wet = prec.values[prec.values > thr]\n", + "\n", + "hist_wet = prec_hist.values[\n", + " prec_hist.values > thr\n", + "]\n", + "\n", + "q = np.linspace(0,1,1000)\n", + "\n", + "era_q_pr = np.quantile(era_wet, q)\n", + "\n", + "hist_q_pr = np.quantile(hist_wet, q)\n", + "\n", + "era_q_evap = np.quantile(evap.values, q)\n", + "\n", + "hist_q_evap = np.quantile(evap_hist.values,q)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "49c32a88-f0b7-474a-be1f-43b7ea88ebed", + "metadata": {}, + "outputs": [], + "source": [ + "pr = prec_hist.values.copy()\n", + "wet_frac_era = (prec.values > thr).mean()\n", + "# find CMIP threshold that yields same wet-day fraction\n", + "thr_cmip = np.quantile( prec_hist.values, 1 - wet_frac_era)\n", + "mask = prec_hist.values > thr_cmip\n", + "\n", + "pr_corr = np.zeros_like(pr)\n", + "\n", + "pr_corr[mask] = np.interp(pr[mask], hist_q_pr, era_q_pr, left=era_q_pr[0], right=era_q_pr[-1])\n", + "\n", + "prec_hist_corr = xr.DataArray(pr_corr, coords=prec_hist.coords, dims=prec_hist.dims, attrs=prec_hist.attrs,)\n", + "\n", + "scale = (prec.mean()/prec_hist_corr.mean())**0.5\n", + "\n", + "prec_hist_corr *= scale" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a991952f-9057-418d-8d91-a81d555c94f9", + "metadata": {}, + "outputs": [], + "source": [ + "ev = evap_hist.values.copy()\n", + "\n", + "ev_corr = np.interp(ev, hist_q_evap, era_q_evap, left=era_q_evap[0], right=era_q_evap[-1])\n", + "\n", + "evap_hist_corr = xr.DataArray(ev_corr, coords=evap_hist.coords, dims=evap_hist.dims, attrs=evap_hist.attrs,)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c4ecdd9f-8168-4fe6-aff3-babe65909e5f", + "metadata": {}, + "outputs": [], + "source": [ + "ssp126_ds = SSP126.to_xarray()\n", + "\n", + "pr126 = ssp126_ds[\"pr\"].compute()\n", + "evap126 = ssp126_ds[\"evspsblpot\"].compute()\n", + "\n", + "pr126_np = pr126.values.copy()\n", + "pr126_corr = np.zeros_like(pr126_np)\n", + "\n", + "# use historical wet-day threshold\n", + "mask = pr126_np > thr_cmip\n", + "\n", + "pr126_corr[mask] = np.interp(\n", + " pr126_np[mask],\n", + " hist_q_pr,\n", + " era_q_pr,\n", + " left=era_q_pr[0],\n", + " right=era_q_pr[-1]\n", + ")\n", + "\n", + "pr126_corr = xr.DataArray(\n", + " pr126_corr,\n", + " coords=pr126.coords,\n", + " dims=pr126.dims,\n", + " attrs=pr126.attrs,\n", + ")\n", + "\n", + "# apply same scaling as historical\n", + "pr126_corr *= scale\n", + "\n", + "evap126_corr = xr.DataArray(\n", + " np.interp(\n", + " evap126.values,\n", + " hist_q_evap,\n", + " era_q_evap,\n", + " left=era_q_evap[0],\n", + " right=era_q_evap[-1]\n", + " ),\n", + " coords=evap126.coords,\n", + " dims=evap126.dims,\n", + " attrs=evap126.attrs,\n", + ")\n", + "\n", + "ssp245_ds = SSP245.to_xarray()\n", + "\n", + "pr245 = ssp245_ds[\"pr\"].compute()\n", + "evap245 = ssp245_ds[\"evspsblpot\"].compute()\n", + "\n", + "pr245_np = pr245.values.copy()\n", + "pr245_corr = np.zeros_like(pr245_np)\n", + "\n", + "mask = pr245_np > thr_cmip\n", + "\n", + "pr245_corr[mask] = np.interp(\n", + " pr245_np[mask],\n", + " hist_q_pr,\n", + " era_q_pr,\n", + " left=era_q_pr[0],\n", + " right=era_q_pr[-1]\n", + ")\n", + "\n", + "pr245_corr = xr.DataArray(\n", + " pr245_corr,\n", + " coords=pr245.coords,\n", + " dims=pr245.dims,\n", + " attrs=pr245.attrs,\n", + ")\n", + "\n", + "pr245_corr *= scale\n", + "\n", + "evap245_corr = xr.DataArray(\n", + " np.interp(\n", + " evap245.values,\n", + " hist_q_evap,\n", + " era_q_evap,\n", + " left=era_q_evap[0],\n", + " right=era_q_evap[-1]\n", + " ),\n", + " coords=evap245.coords,\n", + " dims=evap245.dims,\n", + " attrs=evap245.attrs,\n", + ")\n", + "\n", + "ssp585_ds = SSP585.to_xarray()\n", + "\n", + "pr585 = ssp585_ds[\"pr\"].compute()\n", + "evap585 = ssp585_ds[\"evspsblpot\"].compute()\n", + "\n", + "pr585_np = pr585.values.copy()\n", + "pr585_corr = np.zeros_like(pr585_np)\n", + "\n", + "mask = pr585_np > thr_cmip\n", + "\n", + "pr585_corr[mask] = np.interp(\n", + " pr585_np[mask],\n", + " hist_q_pr,\n", + " era_q_pr,\n", + " left=era_q_pr[0],\n", + " right=era_q_pr[-1]\n", + ")\n", + "\n", + "pr585_corr = xr.DataArray(\n", + " pr585_corr,\n", + " coords=pr585.coords,\n", + " dims=pr585.dims,\n", + " attrs=pr585.attrs,\n", + ")\n", + "\n", + "pr585_corr *= scale\n", + "\n", + "evap585_corr = xr.DataArray(\n", + " np.interp(\n", + " evap585.values,\n", + " hist_q_evap,\n", + " era_q_evap,\n", + " left=era_q_evap[0],\n", + " right=era_q_evap[-1]\n", + " ),\n", + " coords=evap585.coords,\n", + " dims=evap585.dims,\n", + " attrs=evap585.attrs,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "377122e4-a74e-487a-8927-b6fd49f2ea03", + "metadata": {}, + "outputs": [], + "source": [ + "SSP126_corr_ds = SSP126.to_xarray().copy()\n", + "SSP126_corr_ds[\"pr\"] = xr.DataArray( pr126_corr, coords=pr126.coords, dims=pr126.dims, attrs=pr126.attrs, )\n", + "SSP126_corr_ds[\"evspsblpot\"] = xr.DataArray( evap126_corr, coords=evap126.coords, dims=evap126.dims, attrs=evap126.attrs,)\n", + "\n", + "SSP245_corr_ds = SSP245.to_xarray().copy()\n", + "SSP245_corr_ds[\"pr\"] = xr.DataArray( pr245_corr, coords=pr245.coords, dims=pr245.dims, attrs=pr245.attrs, )\n", + "SSP245_corr_ds[\"evspsblpot\"] = xr.DataArray( evap245_corr, coords=evap245.coords, dims=evap245.dims, attrs=evap245.attrs,)\n", + "\n", + "SSP585_corr_ds = SSP585.to_xarray().copy()\n", + "SSP585_corr_ds[\"pr\"] = xr.DataArray( pr585_corr, coords=pr585.coords, dims=pr585.dims, attrs=pr585.attrs, )\n", + "SSP585_corr_ds[\"evspsblpot\"] = xr.DataArray( evap585_corr, coords=evap585.coords, dims=evap585.dims, attrs=evap585.attrs,)\n", + "\n", + "HIST_corr_ds = HIST.to_xarray().copy()\n", + "HIST_corr_ds[\"pr\"] = xr.DataArray( prec_hist_corr, coords=prec_hist.coords, dims=prec_hist.dims, attrs=prec_hist.attrs, )\n", + "HIST_corr_ds[\"evspsblpot\"] = xr.DataArray( evap_hist_corr, coords=evap_hist.coords, dims=evap_hist.dims, attrs=evap_hist.attrs,)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fa61607e-9313-413c-bef1-13871ad28dfb", + "metadata": {}, + "outputs": [], + "source": [ + "HIST_corr_ds.to_netcdf(\n", + " historic_location / \"forcing_biascorr.nc\"\n", + ")\n", + "SSP126_corr_ds.to_netcdf(\n", + " ssp126_location / \"forcing_biascorr.nc\"\n", + ")\n", + "SSP245_corr_ds.to_netcdf(\n", + " ssp245_location / \"forcing_biascorr.nc\"\n", + ")\n", + "SSP585_corr_ds.to_netcdf(\n", + " ssp585_location / \"forcing_biascorr.nc\"\n", + ")\n", + "\n", + "HIST_corr = HIST.model_copy(deep=True)\n", + "\n", + "SSP126_corr = SSP126.model_copy(deep=True)\n", + "\n", + "SSP245_corr = SSP245.model_copy(deep=True)\n", + "\n", + "SSP585_corr = SSP585.model_copy(deep=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7846ffec-2207-4e76-93e6-2fc43f047c45", + "metadata": {}, + "outputs": [], + "source": [ + "HIST_corr.filenames[\"pr\"] = \"forcing_biascorr.nc\"\n", + "HIST_corr.filenames[\"evspsblpot\"] = \"forcing_biascorr.nc\"\n", + "\n", + "SSP126_corr.filenames[\"pr\"] = \"forcing_biascorr.nc\"\n", + "SSP126_corr.filenames[\"evspsblpot\"] = \"forcing_biascorr.nc\"\n", + "\n", + "SSP245_corr.filenames[\"pr\"] = \"forcing_biascorr.nc\"\n", + "SSP245_corr.filenames[\"evspsblpot\"] = \"forcing_biascorr.nc\"\n", + "\n", + "SSP585_corr.filenames[\"pr\"] = \"forcing_biascorr.nc\"\n", + "SSP585_corr.filenames[\"evspsblpot\"] = \"forcing_biascorr.nc\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0f19246a-899c-480e-b154-50d5fb706b64", + "metadata": {}, + "outputs": [], + "source": [ + "test = HIST_corr.to_xarray()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "947b6058-a2fa-43fb-92a2-668aa35aeb4d", + "metadata": {}, + "outputs": [], + "source": [ + "forcing_list = [HIST_corr, SSP126_corr, SSP245_corr, SSP585_corr] \n", + "output_corr = []\n", + "years_corr = []\n", + "params = [1.30978424, 0.39171679, 1.05045276]\n", + "\n", + "for forcings in forcing_list:\n", + " model = DischargeLocal(forcing=forcings)\n", + " config_file, _ = model.setup(\n", + " parameters=params, \n", + " cfg_dir = Eigen_model,\n", + " )\n", + "\n", + " model.initialize(config_file)\n", + "\n", + " Q_m = []\n", + " time = []\n", + " \n", + " while model.time < model.end_time:\n", + " model.update()\n", + " Q_m.append(model.get_value(\"Q\")[0])\n", + " time.append(pd.Timestamp(model.time_as_datetime))\n", + " \n", + " output_corr.append(Q_m)\n", + " years_corr.append(time)\n", + " \n", + " del Q_m, time\n", + " model.finalize()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ddb8336d-61e0-4cc4-8dee-029d9cfa8303", + "metadata": {}, + "outputs": [], + "source": [ + "historical_output = pd.Series(data=output_corr[0], name=\"Historical\", index=years[0])[\"2019-01-01\":]\n", + "SSP126_output = pd.Series(data=output_corr[1], name=\"SSP126\", index=years[1])[\"2027-01-01\":]\n", + "SSP245_output = pd.Series(data=output_corr[2], name=\"SSP245\", index=years[2])[\"2027-01-01\":]\n", + "SSP585_output = pd.Series(data=output_corr[3], name=\"SSP585\", index=years[3])[\"2027-01-01\":]\n", + "\n", + "# Convert mm/d to m3/s\n", + "factor = shape_file_area / 86.4\n", + "historical_output *= factor\n", + "SSP126_output *= factor\n", + "SSP245_output *= factor\n", + "SSP585_output *= factor" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "218a0ba7-fcbf-42cc-80e3-d5e8689aa85f", + "metadata": {}, + "outputs": [], + "source": [ + "# quantile mapped CMIP neerslag data vergelijken met ERA5 en oude CMIP\n", + "\n", + "def ecdf(x):\n", + " x = np.asarray(x)\n", + " x = x[np.isfinite(x)] # remove NaNs\n", + " x = np.sort(x)\n", + " y = np.arange(1, len(x)+1) / len(x)\n", + " return x, y\n", + "\n", + "# x_cmip, y_cmip = ecdf(historical_output)\n", + "x_cmip, y_cmip = ecdf(test[\"pr\"])\n", + "x_cmip_oud, y_cmip_oud = ecdf(prec_hist)\n", + "x_era5, y_era5 = ecdf(prec)\n", + "\n", + "# x_era5 *= 3600*24\n", + "\n", + "plt.figure(figsize=(16, 7))\n", + "\n", + "plt.plot(x_cmip * 86400, y_cmip, label='CMIP gecorrigeerd')\n", + "plt.plot(x_cmip_oud * 86400, y_cmip_oud, label='CMIP')\n", + "plt.plot(x_era5 * 86400, y_era5, label='ERA5')\n", + "\n", + "plt.xlabel('Neerslag [mm/d]')\n", + "plt.ylabel('Cumulatieve kans [-]')\n", + "plt.title(\"Regenval CMIP en ERA5\")\n", + "plt.legend()\n", + "plt.grid(alpha=0.3)\n", + "\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1548d827-f457-4150-b395-9a431ccc6886", + "metadata": {}, + "outputs": [], + "source": [ + "# quantile mapped CMIP verdamping data vergelijken met ERA5 en oude CMIP\n", + "x_cmipE, y_cmipE = ecdf(test[\"evspsblpot\"])\n", + "x_cmip_oudE, y_cmip_oudE = ecdf(evap_hist)\n", + "x_era5E, y_era5E = ecdf(evap)\n", + "\n", + "# x_era5 *= 3600*24\n", + "\n", + "plt.figure(figsize=(16, 7))\n", + "\n", + "plt.plot(x_cmipE, y_cmipE, label='CMIP gecorrigeerd')\n", + "plt.plot(x_cmip_oudE, y_cmip_oudE, label='CMIP')\n", + "plt.plot(x_era5E, y_era5E, label='ERA5')\n", + "\n", + "plt.xlabel('Verdamping [mm/s]')\n", + "plt.ylabel('Cumulatieve kans [-]')\n", + "plt.title(\"Regenval CMIP en ERA5\")\n", + "plt.legend()\n", + "plt.grid(alpha=0.3)\n", + "\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "130f7912-2ba8-49e5-973e-c94f545cbc94", + "metadata": {}, + "outputs": [], + "source": [ + "def droogte(level, L_crit, start_date):\n", + "\n", + " # Create daily dates\n", + " dates = pd.date_range(\n", + " start=start_date,\n", + " periods=len(level),\n", + " freq=\"D\"\n", + " )\n", + "\n", + " # Make Series\n", + " level = pd.Series(level, index=dates)\n", + "\n", + " # Determine drought days\n", + " drought = level < L_crit\n", + "\n", + " # Daily deficit (0 if level >= L_crit)\n", + " deficit = (L_crit - level).clip(lower=0)\n", + "\n", + " # Find consecutive drought periods\n", + " groups = (drought != drought.shift()).cumsum()\n", + "\n", + " events = []\n", + "\n", + " for _, group in drought.groupby(groups):\n", + "\n", + " if group.iloc[0]: # only drought groups\n", + "\n", + " start = group.index[0]\n", + " end = group.index[-1]\n", + "\n", + " duration = (end - start).days + 1\n", + "\n", + " # Deficit during this event\n", + " event_deficit = deficit.loc[start:end]\n", + "\n", + " max_deficit = event_deficit.max()\n", + " cum_deficit = event_deficit.sum()\n", + " mean_deficit = event_deficit.mean()\n", + "\n", + " events.append({\n", + " \"start\": start,\n", + " \"end\": end,\n", + " \"duration_days\": duration,\n", + " \"max_deficit\": max_deficit,\n", + " \"mean_deficit\": mean_deficit,\n", + " \"cum_deficit\": cum_deficit\n", + " })\n", + "\n", + " events = pd.DataFrame(events)\n", + "\n", + " return drought, deficit, events" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c824fb5d-0b47-4439-9752-d1801954892a", + "metadata": {}, + "outputs": [], + "source": [ + "Q_out = 200\n", + "A = 1020\n", + "L0 = 46.5\n", + "SSP126_level_200 = level(SSP126_output, Q_out, SSP126_corr, A, L0)\n", + "SSP245_level_200 = level(SSP245_output, Q_out, SSP245_corr, A, L0)\n", + "SSP585_level_200 = level(SSP585_output, Q_out, SSP585_corr, A, L0)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "df46f087-583d-4dbf-afe3-b99e4acc65fb", + "metadata": {}, + "outputs": [], + "source": [ + "# hoogte voorspellingen 3 klimaatscenario's\n", + "\n", + "import matplotlib.dates as mdates\n", + "plt.figure(figsize=(16, 7))\n", + "plt.axhline(42.92, color = \"r\", linestyle='--', label = \"Kritische hoogte; 42,92m\")\n", + "plt.axhline(40.5, color = \"r\", label = \"Zeer kritische hoogte; 40,5m\")\n", + "plt.plot(SSP126_output.index, SSP126_level_200, label = \"SSP126\")\n", + "plt.plot(SSP245_output.index, SSP245_level_200, label = \"SSP245\")\n", + "plt.plot(SSP585_output.index, SSP585_level_200, label = \"SSP585\")\n", + "plt.legend()\n", + "# plt.xlim(\"2025-01-01\", \"2060-01-01\")\n", + "plt.xlim(pd.Timestamp(\"2024-12-31\"),\n", + " pd.Timestamp(\"2060-01-01\"))\n", + "plt.xticks(pd.date_range(\"2025\", \"2060\", freq=\"5YS\"))\n", + "plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%Y'))\n", + "plt.ylim(25, 50)\n", + "plt.xlabel(\"Datum\")\n", + "plt.ylabel(\"Hoogte meer [m]\")\n", + "# plt.title(\"Klimaatscenario's met Qout = 200 m^3/s\")\n", + "plt.title(\"Hoogtevoorspellingen 3 klimaatscenario's\")\n", + "plt.grid()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "65696039-1eb5-4ff3-8fae-e04683e1126f", + "metadata": {}, + "outputs": [], + "source": [ + "drought_ssp126, deficit_ssp126, events_ssp126 = droogte(SSP126_level_200, L_crit=42.92, start_date=\"2027-01-01\")\n", + "drought_ssp245, deficit_ssp245, events_ssp245 = droogte(SSP245_level_200, L_crit=42.92, start_date=\"2027-01-01\")\n", + "drought_ssp585, deficit_ssp585, events_ssp585 = droogte(SSP585_level_200, L_crit=42.92, start_date=\"2027-01-01\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "08416c00-181e-47ba-9607-52f9524bcf12", + "metadata": {}, + "outputs": [], + "source": [ + "# hoogte tekort per jaar 3 klimaatscenario's\n", + "\n", + "plt.figure(figsize=(16, 7))\n", + "drought_ssp126, deficit_ssp126, events_ssp126 = droogte(SSP126_level_200, L_crit=42.92, start_date=\"2027-01-01\")\n", + "drought_ssp245, deficit_ssp245, events_ssp245 = droogte(SSP245_level_200, L_crit=42.92, start_date=\"2027-01-01\")\n", + "drought_ssp585, deficit_ssp585, events_ssp585 = droogte(SSP585_level_200, L_crit=42.92, start_date=\"2027-01-01\")\n", + "\n", + "year_deficit_ssp126 = deficit_ssp126.groupby(deficit_ssp126.index.year).sum()\n", + "year_deficit_ssp245 = deficit_ssp245.groupby(deficit_ssp245.index.year).sum()\n", + "year_deficit_ssp585 = deficit_ssp585.groupby(deficit_ssp585.index.year).sum()\n", + "\n", + "plt.plot(year_deficit_ssp126.index, year_deficit_ssp126, marker = \"o\", label = \"SSP126\")\n", + "plt.plot(year_deficit_ssp245.index, year_deficit_ssp245, marker = \"o\", label = \"SSP245\")\n", + "plt.plot(year_deficit_ssp585.index, year_deficit_ssp585, marker = \"o\", label = \"SSP585\")\n", + "# plt.axhline(1000, color = \"r\", linestyle='--', label = \"kritische hoogte\")\n", + "plt.xlim(2025, 2060)\n", + "plt.ylim(0, 25000)\n", + "plt.xlabel(\"Datum\")\n", + "plt.ylabel(\"Hoogte tekort [m]\")\n", + "plt.title(\"Hoogte tekort per jaar\")\n", + "plt.legend()\n", + "plt.grid();" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "85648c88-7b05-44ed-b4c8-c8fa29c08300", + "metadata": {}, + "outputs": [], + "source": [ + "# dagen onder kritische hoogte 3 klimaatscenario's\n", + "\n", + "plt.figure(figsize=(16, 4))\n", + "drought_ssp126, deficit_ssp126, events_ssp126 = droogte(SSP126_level_200, L_crit=42.92, start_date=\"2027-01-01\")\n", + "drought_ssp245, deficit_ssp245, events_ssp245 = droogte(SSP245_level_200, L_crit=42.92, start_date=\"2027-01-01\")\n", + "drought_ssp585, deficit_ssp585, events_ssp585 = droogte(SSP585_level_200, L_crit=42.92, start_date=\"2027-01-01\")\n", + "\n", + "year_drought_ssp126 = drought_ssp126.groupby(drought_ssp126.index.year).sum()\n", + "year_drought_ssp245 = drought_ssp245.groupby(drought_ssp245.index.year).sum()\n", + "year_drought_ssp585 = drought_ssp585.groupby(drought_ssp585.index.year).sum()\n", + "# print(year_deficit_ssp126)\n", + "plt.plot(year_drought_ssp126.index, year_drought_ssp126, marker = \"o\", label = \"SSP126\")\n", + "plt.plot(year_drought_ssp245.index, year_drought_ssp245, marker = \"o\", label = \"SSP245\")\n", + "plt.plot(year_drought_ssp585.index, year_drought_ssp585, marker = \"o\", label = \"SSP585\")\n", + "\n", + "plt.xlabel(\"Datum\")\n", + "plt.ylabel(\"Dagen kritische hoogte\")\n", + "plt.title(\"Dagen per jaar onder kritische hoogte 42,92m\")\n", + "plt.xlim(2025, 2060)\n", + "plt.legend()\n", + "plt.grid();" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "076fd119-6c8c-4e32-97dc-9182963b1b2c", + "metadata": {}, + "outputs": [], + "source": [ + "# dagen onder zeer kritische hoogte 3 klimaatscenario's\n", + "plt.figure(figsize=(16, 4))\n", + "drought_ssp126, deficit_ssp126, events_ssp126 = droogte(SSP126_level_200, L_crit=40.5, start_date=\"2027-01-01\")\n", + "drought_ssp245, deficit_ssp245, events_ssp245 = droogte(SSP245_level_200, L_crit=40.5, start_date=\"2027-01-01\")\n", + "drought_ssp585, deficit_ssp585, events_ssp585 = droogte(SSP585_level_200, L_crit=40.5, start_date=\"2027-01-01\")\n", + "\n", + "year_drought_ssp126 = drought_ssp126.groupby(drought_ssp126.index.year).sum()\n", + "year_drought_ssp245 = drought_ssp245.groupby(drought_ssp245.index.year).sum()\n", + "year_drought_ssp585 = drought_ssp585.groupby(drought_ssp585.index.year).sum()\n", + "# print(year_deficit_ssp126)\n", + "plt.plot(year_drought_ssp126.index, year_drought_ssp126, marker = \"o\", label = \"SSP126\")\n", + "plt.plot(year_drought_ssp245.index, year_drought_ssp245, marker = \"o\", label = \"SSP245\")\n", + "plt.plot(year_drought_ssp585.index, year_drought_ssp585, marker = \"o\", label = \"SSP585\")\n", + "\n", + "plt.xlabel(\"Datum\")\n", + "plt.ylabel(\"Dagen kritische hoogte\")\n", + "plt.title(\"Dagen per jaar onder zeer kritische hoogte 40,5m\")\n", + "plt.xlim(2025, 2060)\n", + "plt.legend()\n", + "plt.grid();" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Under_construction/Suriname_calibration_.ipynb b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Under_construction/Suriname_calibration_.ipynb new file mode 100644 index 00000000..c67da4d3 --- /dev/null +++ b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Under_construction/Suriname_calibration_.ipynb @@ -0,0 +1,1036 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "0a258582-9a94-4eb5-8574-34ba9cca73ab", + "metadata": {}, + "outputs": [], + "source": [ + "import warnings\n", + "warnings.filterwarnings(\"ignore\", category=UserWarning)\n", + "import numpy as np\n", + "from pathlib import Path\n", + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "import xarray as xr\n", + "# import geopandas as gpd\n", + "import pandas as pd\n", + "import seaborn as sns\n", + "from scipy.stats import qmc\n", + "from ipywidgets import IntProgress\n", + "import math as math\n", + "\n", + "# importeren van ewatercycle\n", + "import ewatercycle\n", + "import ewatercycle.models\n", + "import ewatercycle.forcing\n", + "\n", + "from ewatercycle_discharge import DischargeLocal\n", + "\n", + "shape_file_area = 7.629080e+03 # in km^2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b0805d7c-9c36-41da-acbd-99aafa8542a6", + "metadata": {}, + "outputs": [], + "source": [ + "basin_name = \"boven_suriname\"\n", + "\n", + "# tijdsinterval\n", + "start_datum = \"2019-01-01\"\n", + "eind_datum = \"2024-12-31\"\n", + "start_datum = pd.to_datetime(start_datum, utc=True)\n", + "end_datum = pd.to_datetime(eind_datum, utc=True)\n", + "start_pd = start_datum.strftime(\"%Y-%m-%dT%H:%M:%SZ\")\n", + "end_pd = end_datum.strftime(\"%Y-%m-%dT%H:%M:%SZ\")\n", + "start_datum = start_pd\n", + "eind_datum = end_pd\n", + "\n", + "start_calibration = start_pd\n", + "end_calibration = end_pd\n", + "start_calibration = pd.Timestamp(start_calibration).tz_localize(None)\n", + "end_calibration = pd.Timestamp(end_calibration).tz_localize(None)\n", + "\n", + "print(start_datum)\n", + "\n", + "# route naar shape file\n", + "shapefile = Path.home() / \"BEP-Julian\" / \"BEP-Julian\" / \"Suriname_Model\" / \"boven_suriname.shp\"\n", + "\n", + "Eigen_model = Path.home() / \"BEP-Julian\" / \"BEP-Julian\" / \"Suriname_Model\" / \"discharge_bmi\"\n", + "Eigen_model.mkdir(exist_ok=True)\n", + "\n", + "forcing_route = Path.home() / \"BEP-Julian\" / \"BEP-Julian\" / \"Forcing\" / \"ERA5_SUR_2019_2024\"/ \"work\" / \"diagnostic\" / \"script\" " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "262c5ba2-9cf4-4f9d-8462-dcbf0d1dde47", + "metadata": {}, + "outputs": [], + "source": [ + "# genereren\n", + "# ERA5_forcing = ewatercycle.forcing.sources['LumpedMakkinkForcing'].generate(\n", + "# dataset=\"ERA5\",\n", + "# start_time=start_datum,\n", + "# end_time=eind_datum,\n", + "# shape=shapefile,\n", + "# directory=forcing_route\n", + "# )\n", + "\n", + "# inladen\n", + "ERA5_forcing = ewatercycle.forcing.sources[\"LumpedMakkinkForcing\"].load(directory=forcing_route)\n", + "\n", + "print(f\"The forcing object you created: \\n {ERA5_forcing}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "70f828e9-359e-401b-ad0c-063aee4c2e51", + "metadata": {}, + "outputs": [], + "source": [ + "# forcing visualiseren als controle\n", + "evap = ERA5_forcing.to_xarray()[\"evspsblpot\"] #units: kg m^-2 s^-1 = mm/s, gesampled per dag\n", + "prec = ERA5_forcing.to_xarray()[\"pr\"] #units: kg m^-2 s^-1 = mm/s, gesampled per dag\n", + "print(evap)\n", + "# print(prec)\n", + "fig, ax = plt.subplots(figsize=(12,5))\n", + "\n", + "evap.plot(ax=ax, label='Potential evaporation')\n", + "prec.plot(ax=ax, label='Precipitation')\n", + "ax.set_ylabel('mm/s')\n", + "ax.set_xlabel(\"tijd\")\n", + "plt.title(\"E en P in mm/s, sampled per dag\")\n", + "ax.legend();" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6591b4f0-4998-4118-a47c-58022a678223", + "metadata": {}, + "outputs": [], + "source": [ + "# oppervlakte stuwmeer inladen\n", + "opp_file = Path.home() / \"BEP-Julian\" / \"BEP-Julian\" / \"Suriname_Model\" / \"GWSC_dams_mogwai_Brokopondo.csv\"\n", + "opp = pd.read_csv(opp_file, delimiter=',', skiprows = 1)\n", + "opp = opp.rename(columns={\"Time (UTC)\": \"Date\"})\n", + "opp[\"Date\"] = pd.to_datetime(opp[\"Date\"], utc = True)\n", + "# opp[\"Date\"] = opp[\"Date\"].dt.tz_localize(None)\n", + "opp = opp[(opp[\"Date\"] >= start_datum) &(opp[\"Date\"] <= eind_datum)].copy()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4a02b8a8-483f-4f63-966f-bf0ceb606ee0", + "metadata": {}, + "outputs": [], + "source": [ + "# hoogte stuwmeer inladen\n", + "height_file = Path.home() / \"BEP-Julian\" / \"BEP-Julian\" / \"Suriname_Model\" / \"Dahiti Brokopondo water height.xlsx\"\n", + "height = pd.read_excel(height_file)\n", + "height = height.iloc[:, 0].str.split(';', expand=True)\n", + "height.columns = [\"datetime\", \"wse\", \"wse_u\"]\n", + "height[\"datetime\"] = pd.to_datetime(height[\"datetime\"], utc=True)\n", + "height[\"wse\"] = height[\"wse\"].astype(float)\n", + "height[\"wse_u\"] = height[\"wse_u\"].astype(float)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c90cc20f-a51e-4cdc-8397-c1cc43531d65", + "metadata": {}, + "outputs": [], + "source": [ + "#Qin links van Suriname model inladen. Hierop moet discharge_bmi worden gekalibreerd\n", + "height[\"datetime_local_none_test\"] = height[\"datetime\"].dt.tz_localize(None)\n", + "fig, ax1 = plt.subplots(figsize=(16,5))\n", + "\n", + "opp[\"Date\"] = opp[\"Date\"].dt.tz_localize(None)\n", + "begin_datum = pd.to_datetime(start_datum).tz_localize(None)\n", + "eind_datum = pd.to_datetime(eind_datum).tz_localize(None)\n", + "evap = evap.sel(time=slice(begin_datum, eind_datum))\n", + "\n", + "height = height[\n", + " (height[\"datetime_local_none_test\"] >= begin_datum) &\n", + " (height[\"datetime_local_none_test\"] <= eind_datum)\n", + "].copy()\n", + "\n", + "height = height.reset_index(drop=True)\n", + "\n", + "area_interp = np.interp(height[\"datetime_local_none_test\"].astype(\"int64\"), opp[\"Date\"].astype(\"int64\"), opp[\"Value\"])\n", + "\n", + "H = height[\"wse\"].to_numpy()\n", + "V = np.exp((H - 8)/15) - 2\n", + "Vv = V * 10**9 # van km^3 naar m^3\n", + "delta_s = np.zeros(len(height[\"datetime_local_none_test\"]))\n", + "E = np.zeros(len(height[\"datetime_local_none_test\"]))\n", + "# opper = np.zeros(len(height[\"datetime_local_none_test\"]))\n", + "Q_in_L = np.zeros(len(height[\"datetime_local_none_test\"]))\n", + "E_v = np.zeros(len(height[\"datetime_local_none_test\"]))\n", + "Q_in_L_sum = np.zeros(len(height[\"datetime_local_none_test\"]))\n", + "Q_in_L_sum_test = np.zeros(len(height[\"datetime_local_none_test\"]))\n", + "Q_out = 200# m^3/s \n", + "\n", + "for i in range(len(height[\"datetime_local_none_test\"])-1):\n", + " \n", + " t0 = height[\"datetime_local_none_test\"].iloc[i]\n", + " t1 = height[\"datetime_local_none_test\"].iloc[i+1]\n", + "\n", + " dt_seconds = (t1 - t0).total_seconds()\n", + " delta_s[i+1] = (Vv[i+1] - Vv[i]) / dt_seconds\n", + " \n", + " evap_interval = evap.sel(time=slice(t0, t1))\n", + " E[i+1] = evap_interval.mean().values * 10**-3 #/dt_seconds # van mm/s naar m/s\n", + "\n", + " A_t = area_interp[i+1]\n", + " E_v[i+1] = A_t * 1e6 * E[i+1]\n", + "\n", + " Q_in_L[i+1] = delta_s[i+1] + E_v[i+1] + Q_out\n", + " Q_in_L[i+1] = np.nan_to_num(Q_in_L[i+1], nan=0.0)\n", + " Q_in_L_sum[i] = Q_in_L.sum()\n", + " Q_in_L_sum_test = np.cumsum(Q_in_L)\n", + "\n", + "plt.plot(height[\"datetime_local_none_test\"], Q_in_L, label = \"Afvoer\")\n", + "plt.plot(height[\"datetime_local_none_test\"], E_v, label = \"Neerslag\")\n", + "plt.legend()\n", + "plt.title(\"Afvoer Surinamerivier model 1\")\n", + "plt.xlabel(\"Datum\")\n", + "plt.ylabel(\"Afvoer Surinamerivier [m^3/s]\")\n", + "plt.grid();" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "528c369b-732f-4a1d-b939-43851f94c09f", + "metadata": {}, + "outputs": [], + "source": [ + "flow = pd.DataFrame(data=Q_in_L, index=height[\"datetime_local_none_test\"], columns=['Q'])\n", + "flow.index = pd.to_datetime(flow.index).tz_localize(None)\n", + "flow = flow[flow.index.notna()]" + ] + }, + { + "cell_type": "markdown", + "id": "8fcb5e2c-c601-424a-bd9b-4a292a96fedd", + "metadata": {}, + "source": [ + "## RMSE functie" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9f2647b7-01c0-4693-bd8b-4a9d4330154d", + "metadata": {}, + "outputs": [], + "source": [ + "def RMSE(output, observed, start, end):\n", + " start = pd.to_datetime(start)\n", + " end = pd.to_datetime(end)\n", + " \n", + " output.index = pd.to_datetime(output.index)\n", + " observed.index = pd.to_datetime(observed.index)\n", + "\n", + " hydro_data = pd.concat([output.reindex(observed.index, method='ffill'), observed], axis=1, keys=['model', 'observation'])\n", + " hydro_data = hydro_data.dropna()\n", + " \n", + " hydro_data = hydro_data[(hydro_data.index > start) & (hydro_data.index < end)]\n", + " \n", + " squarediff = (hydro_data['model'] - hydro_data['observation']) ** 2\n", + " rootMeanSquareDiff = np.sqrt(np.mean(squarediff))\n", + " \n", + " return rootMeanSquareDiff" + ] + }, + { + "cell_type": "markdown", + "id": "034c7958-1ca2-4a52-9425-8f47e8fb5a2d", + "metadata": {}, + "source": [ + "## NSE functie" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "da5b4752-bc73-4654-9aed-14a6646007c5", + "metadata": {}, + "outputs": [], + "source": [ + "def NSE(output, observed, start, end):\n", + " start = pd.to_datetime(start)\n", + " end = pd.to_datetime(end)\n", + " \n", + " output.index = pd.to_datetime(output.index)\n", + " observed.index = pd.to_datetime(observed.index)\n", + "\n", + " hydro_data = pd.concat([output.reindex(observed.index, method='ffill'), observed], axis=1, keys=['model', 'observation'])\n", + " hydro_data = hydro_data.dropna()\n", + " \n", + " hydro_data = hydro_data[(hydro_data.index > start) & (hydro_data.index < end)]\n", + "\n", + " #hier de formule van NSE invoegen\n", + " \n", + " top = np.sum((hydro_data['observation'] - hydro_data['model'])**2)\n", + "\n", + " bottom = np.sum((hydro_data['observation']- hydro_data['observation'].mean())**2)\n", + "\n", + " nse = 1 - (top / bottom)\n", + " \n", + " return nse" + ] + }, + { + "cell_type": "markdown", + "id": "0dac203b-5fe9-4127-9fd1-16062a3c24f8", + "metadata": {}, + "source": [ + "## log NSE functie" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a1e3cc35-b2a1-4acd-a531-bb56289c4993", + "metadata": {}, + "outputs": [], + "source": [ + "def logNSE(output, observed, start, end):\n", + " start = pd.to_datetime(start)\n", + " end = pd.to_datetime(end)\n", + " \n", + " output.index = pd.to_datetime(output.index)\n", + " observed.index = pd.to_datetime(observed.index)\n", + "\n", + " hydro_data = pd.concat([output.reindex(observed.index, method='ffill'), observed], axis=1, keys=['model', 'observation'])\n", + " hydro_data = hydro_data.dropna()\n", + " \n", + " hydro_data = hydro_data[(hydro_data.index > start) & (hydro_data.index < end)]\n", + "\n", + " #hier de formule van NSE invoegen\n", + " \n", + " top = np.sum((np.log10(hydro_data['observation']) - np.log10(hydro_data['model']))**2)\n", + "\n", + " bottom = np.sum((np.log10(hydro_data['observation']) - np.log10(hydro_data['observation']).mean())**2)\n", + "\n", + " lognse = 1 - (top / bottom)\n", + " \n", + " return lognse" + ] + }, + { + "cell_type": "markdown", + "id": "f1da12fa-dfb2-4c77-8d17-70a876286bd1", + "metadata": {}, + "source": [ + "## Parameters genereren" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "be52023b-048e-4122-943f-419e32f46e81", + "metadata": {}, + "outputs": [], + "source": [ + "N = 1 # 50 voor show, 200 voor test, 2000 voor kalibratie" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4837fe91-d2a5-4285-91dd-2202a8eb2738", + "metadata": {}, + "outputs": [], + "source": [ + "param_names = [\"Qgw\", \"alpha\", \"beta\"]\n", + "\n", + "# voor mock run\n", + "param_mins = np.array([1.29, 0.39, 1.049])\n", + "param_maxs = np.array([1.31, 0.41, 1.051])\n", + "\n", + "#Fill the parameters array with N random values between each minimum and maximum \n", + "sampler = qmc.LatinHypercube(d=len(param_names))\n", + "sample = sampler.random(n=N)\n", + "parameters = qmc.scale(sample, param_mins, param_maxs)\n", + "print(list(zip(param_names, np.round(parameters[0], decimals=3))))\n", + "# print(parameters)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9b2625f6-03a5-4ac5-a4ef-0d8263e710d8", + "metadata": {}, + "outputs": [], + "source": [ + "def mmday_to_m3s(Q_sim_mmday, frans_area):\n", + " return (Q_sim_mmday * shape_file_area) / 86.4" + ] + }, + { + "cell_type": "markdown", + "id": "4917be09-c018-4347-b485-0dfe5650e55f", + "metadata": {}, + "source": [ + "## RMSE " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b2addedf-1ee8-496e-8e94-3a3983739e9e", + "metadata": {}, + "outputs": [], + "source": [ + "ensemble = []\n", + "\n", + "for counter in range(N): \n", + " # print(counter, parameters[counter])\n", + " ensemble.append(DischargeLocal(forcing=ERA5_forcing))\n", + " config_file, _ = ensemble[counter].setup(parameters = parameters[counter], cfg_dir = Eigen_model)\n", + " ensemble[counter].initialize(config_file)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "59dcc25f-fbc4-4ec3-9124-ba502444a2a0", + "metadata": {}, + "outputs": [], + "source": [ + "f = IntProgress(min=0, max=N)\n", + "display(f)\n", + "\n", + "objectives_RMSE = []\n", + "obs_times = height[\"datetime_local_none_test\"]\n", + "\n", + "for ensembleMember in ensemble:\n", + " Q_m_RMSE = []\n", + " time_RMSE = []\n", + " while ensembleMember.time < ensembleMember.end_time:\n", + " ensembleMember.update()\n", + " discharge_this_timestep = ensembleMember.get_value(\"Q\")\n", + " Q_m_RMSE.append(discharge_this_timestep[0])\n", + " time_RMSE.append(ensembleMember.time_as_datetime)\n", + "\n", + " Q_m_RMSE = mmday_to_m3s(np.array(Q_m_RMSE), shape_file_area)\n", + "\n", + " discharge_dataframe = pd.DataFrame({'model output': Q_m_RMSE},index=pd.to_datetime(time_RMSE))\n", + "\n", + " model_interval_Q = []\n", + "\n", + " for i in range(len(obs_times)-1):\n", + "\n", + " t0 = obs_times.iloc[i]\n", + " t1 = obs_times.iloc[i+1]\n", + "\n", + " interval = discharge_dataframe.loc[t0:t1, \"model output\"]\n", + "\n", + " if len(interval) > 0:\n", + " model_interval_Q.append(interval.mean())\n", + " else:\n", + " model_interval_Q.append(np.nan)\n", + "\n", + " model_interval_Q = pd.Series( model_interval_Q, index=obs_times.iloc[1:])\n", + "\n", + " observed_Q = flow[\"Q\"].iloc[1:]\n", + "\n", + " fit_RMSE = RMSE(model_interval_Q, observed_Q, start_calibration, end_calibration) \n", + " objectives_RMSE.append(fit_RMSE)\n", + "\n", + " del Q_m_RMSE, time_RMSE, discharge_dataframe, fit_RMSE\n", + " f.value += 1\n", + "\n", + "for ensembleMember in ensemble:\n", + " ensembleMember.finalize()\n", + "\n", + "# kijkt naar gemiddelde tussen punten met zelfde waarde" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bece9217-c97d-4b8d-a9d0-e67c29c92361", + "metadata": {}, + "outputs": [], + "source": [ + "parameters_RMSE_index = np.argmin(np.array(objectives_RMSE))\n", + "if np.min(np.array(objectives_RMSE)) == np.inf:\n", + " print(\"No real parameter is chosen\")\n", + "\n", + "parameters_RMSE = parameters[parameters_RMSE_index]\n", + "\n", + "print(f'The best RMSE parameters are: {list(zip(param_names, np.round(parameters_RMSE, decimals=3)))}')\n", + "print(parameters_RMSE)\n", + "print(np.min(np.array(objectives_RMSE)))" + ] + }, + { + "cell_type": "markdown", + "id": "c010db09-c785-4828-ad94-0455f768dcfa", + "metadata": {}, + "source": [ + "## NSE" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dcbbb832-afa7-4816-97da-3d7009ef749e", + "metadata": {}, + "outputs": [], + "source": [ + "ensemble = []\n", + "\n", + "for counter in range(N): \n", + " ensemble.append(DischargeLocal(forcing=ERA5_forcing))\n", + " config_file, _ = ensemble[counter].setup(parameters = parameters[counter], cfg_dir = Eigen_model)\n", + " ensemble[counter].initialize(config_file)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8c5699e2-3ea0-4756-9307-f7552dd631b9", + "metadata": {}, + "outputs": [], + "source": [ + "f = IntProgress(min=0, max=N)\n", + "display(f)\n", + "\n", + "objectives_NSE = []\n", + "obs_times = height[\"datetime_local_none_test\"]\n", + "\n", + "for ensembleMember in ensemble:\n", + " Q_m_NSE = []\n", + " time_NSE = []\n", + " while ensembleMember.time < ensembleMember.end_time:\n", + " ensembleMember.update()\n", + " discharge_this_timestep = ensembleMember.get_value(\"Q\")\n", + " Q_m_NSE.append(discharge_this_timestep[0])\n", + " time_NSE.append(ensembleMember.time_as_datetime)\n", + "\n", + " Q_m_NSE = mmday_to_m3s(np.array(Q_m_NSE), shape_file_area)\n", + "\n", + " discharge_dataframe = pd.DataFrame({'model output': Q_m_NSE},index=pd.to_datetime(time_NSE))\n", + "\n", + " model_interval_Q = []\n", + "\n", + " for i in range(len(obs_times)-1):\n", + "\n", + " t0 = obs_times.iloc[i]\n", + " t1 = obs_times.iloc[i+1]\n", + "\n", + " interval = discharge_dataframe.loc[t0:t1, \"model output\"]\n", + "\n", + " if len(interval) > 0:\n", + " model_interval_Q.append(interval.mean())\n", + " else:\n", + " model_interval_Q.append(np.nan)\n", + "\n", + " model_interval_Q = pd.Series( model_interval_Q, index=obs_times.iloc[1:])\n", + "\n", + " observed_Q = flow[\"Q\"].iloc[1:]\n", + "\n", + " fit_NSE = NSE(model_interval_Q, observed_Q, start_calibration, end_calibration) \n", + " objectives_NSE.append(fit_NSE)\n", + "\n", + " del Q_m_NSE, time_NSE, discharge_dataframe, fit_NSE\n", + " f.value += 1\n", + "for ensembleMember in ensemble:\n", + " ensembleMember.finalize()\n", + "\n", + "# kijkt naar gemiddelde tussen punten met zelfde waarde" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8bff3fb6-d038-4386-b861-ad7c1169782f", + "metadata": {}, + "outputs": [], + "source": [ + "parameters_NSE_index = np.argmax(np.array(objectives_NSE))\n", + "if np.min(np.array(objectives_NSE)) == np.inf:\n", + " print(\"No real parameter is chosen\")\n", + "\n", + "parameters_NSE = parameters[parameters_NSE_index]\n", + "\n", + "print(f'The best NSE parameters are: {list(zip(param_names, np.round(parameters_NSE, decimals=3)))}')\n", + "print(parameters_NSE)\n", + "print(np.max(np.array(objectives_NSE)))" + ] + }, + { + "cell_type": "markdown", + "id": "ae811904-0969-4bb8-ac7d-916d4c49a714", + "metadata": {}, + "source": [ + "## log NSE" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "578fa720-af3c-4af5-adcf-0a67ad6d0180", + "metadata": {}, + "outputs": [], + "source": [ + "ensemble = []\n", + "\n", + "for counter in range(N): \n", + " ensemble.append(DischargeLocal(forcing=ERA5_forcing))\n", + " config_file, _ = ensemble[counter].setup(parameters = parameters[counter], cfg_dir = Eigen_model)\n", + " ensemble[counter].initialize(config_file)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "38b52f8d-eaaa-405e-b207-f04d622070b7", + "metadata": {}, + "outputs": [], + "source": [ + "f = IntProgress(min=0, max=N)\n", + "display(f)\n", + "\n", + "objectives_logNSE = []\n", + "obs_times = height[\"datetime_local_none_test\"]\n", + "\n", + "for ensembleMember in ensemble:\n", + " Q_m_logNSE = []\n", + " time_logNSE = []\n", + " while ensembleMember.time < ensembleMember.end_time:\n", + " ensembleMember.update()\n", + " discharge_this_timestep = ensembleMember.get_value(\"Q\")\n", + " Q_m_logNSE.append(discharge_this_timestep[0])\n", + " time_logNSE.append(ensembleMember.time_as_datetime)\n", + "\n", + " Q_m_logNSE = mmday_to_m3s(np.array(Q_m_logNSE), shape_file_area)\n", + "\n", + " discharge_dataframe = pd.DataFrame({'model output': Q_m_logNSE},index=pd.to_datetime(time_logNSE))\n", + "\n", + " model_interval_Q = []\n", + "\n", + " for i in range(len(obs_times)-1):\n", + "\n", + " t0 = obs_times.iloc[i]\n", + " t1 = obs_times.iloc[i+1]\n", + "\n", + " interval = discharge_dataframe.loc[t0:t1, \"model output\"]\n", + "\n", + " if len(interval) > 0:\n", + " model_interval_Q.append(interval.mean())\n", + " else:\n", + " model_interval_Q.append(np.nan)\n", + "\n", + " model_interval_Q = pd.Series( model_interval_Q, index=obs_times.iloc[1:])\n", + "\n", + " observed_Q = flow[\"Q\"].iloc[1:]\n", + "\n", + " fit_logNSE = logNSE(model_interval_Q, observed_Q, start_calibration, end_calibration) \n", + " objectives_logNSE.append(fit_logNSE)\n", + "\n", + " del Q_m_logNSE, time_logNSE, discharge_dataframe, fit_logNSE\n", + " f.value += 1\n", + "\n", + "for ensembleMember in ensemble:\n", + " ensembleMember.finalize()\n", + "\n", + "# kijkt naar gemiddelde tussen punten met zelfde waarde" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5df09f6a-c960-48c7-86cf-692805e13a66", + "metadata": {}, + "outputs": [], + "source": [ + "parameters_logNSE_index = np.argmax(np.array(objectives_logNSE))\n", + "if np.min(np.array(objectives_logNSE)) == np.inf:\n", + " print(\"No real parameter is chosen\")\n", + "\n", + "parameters_logNSE = parameters[parameters_logNSE_index]\n", + "\n", + "print(f'The best logNSE parameters are: {list(zip(param_names, np.round(parameters_logNSE, decimals=3)))}')\n", + "print(parameters_logNSE)\n", + "print(np.max(np.array(objectives_logNSE)))" + ] + }, + { + "cell_type": "markdown", + "id": "0849f2bf-e51d-4977-9603-ef22651be42e", + "metadata": {}, + "source": [ + "## Visualiseren" + ] + }, + { + "cell_type": "markdown", + "id": "770ef0b5-c632-421b-ad7b-f855cb6ffa50", + "metadata": {}, + "source": [ + "run rmse" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "543e1b9e-e200-46f8-822f-25339795a940", + "metadata": {}, + "outputs": [], + "source": [ + "# Voor test run zijn parameters overschreven met laatste kalibratie voor visualisatie\n", + "parameters_RMSE = [1.30978424, 0.39171679, 1.05045276]\n", + "\n", + "model = DischargeLocal(forcing = ERA5_forcing)\n", + "config_file, _ = model.setup(parameters=parameters_RMSE, cfg_dir=Eigen_model)\n", + "\n", + "model.initialize(config_file)\n", + "Q_m = []\n", + "time = []\n", + "\n", + "while model.time < model.end_time:\n", + " model.update()\n", + " Q_m.append(model.get_value(\"Q\")[0])\n", + " time.append(pd.Timestamp(model.time_as_datetime))\n", + "\n", + "model.finalize()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "780e30f5-2fd0-4a35-85d0-a47cea9a28db", + "metadata": {}, + "outputs": [], + "source": [ + "model_output_mmday = pd.Series(data=Q_m, name=\"Modelled discharge\", index=time)\n", + "model_output_m3s_RMSE = model_output_mmday * shape_file_area * 1000 / 86400" + ] + }, + { + "cell_type": "markdown", + "id": "333326b7-fca2-4bea-83c6-20da51dc730a", + "metadata": {}, + "source": [ + "run nse" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "668327a9-e4a3-4544-af6e-6bf0f4622cfc", + "metadata": {}, + "outputs": [], + "source": [ + "# Voor test run zijn parameters overschreven met laatste kalibratie voor visualisatie\n", + "parameters_NSE = [1.30978424, 0.39171679, 1.05045276]\n", + "\n", + "model = DischargeLocal(forcing = ERA5_forcing)\n", + "config_file, _ = model.setup(parameters=parameters_NSE, cfg_dir=Eigen_model)\n", + "\n", + "model.initialize(config_file)\n", + "Q_m = []\n", + "time = []\n", + "\n", + "while model.time < model.end_time:\n", + " model.update()\n", + " Q_m.append(model.get_value(\"Q\")[0])\n", + " time.append(pd.Timestamp(model.time_as_datetime))\n", + "\n", + "model.finalize()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "660d0f46-ab2a-4516-a7ea-a0e216c83bda", + "metadata": {}, + "outputs": [], + "source": [ + "model_output_mmday = pd.Series(data=Q_m, name=\"Modelled discharge\", index=time)\n", + "model_output_m3s_NSE = model_output_mmday * shape_file_area * 1000 / 86400" + ] + }, + { + "cell_type": "markdown", + "id": "bbfb9fc1-23a3-4d19-bb9d-b0d92a24faef", + "metadata": {}, + "source": [ + "run lognse" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f30ee664-e3f9-4b29-98b3-dcdc33c31602", + "metadata": {}, + "outputs": [], + "source": [ + "# Voor test run zijn parameters overschreven met laatste kalibratie voor visualisatie\n", + "parameters_logNSE = [1.30978424, 0.39171679, 1.05045276]\n", + "\n", + "model = DischargeLocal(forcing = ERA5_forcing)\n", + "config_file, _ = model.setup(parameters=parameters_logNSE, cfg_dir=Eigen_model)\n", + "\n", + "model.initialize(config_file)\n", + "Q_m = []\n", + "time = []\n", + "\n", + "while model.time < model.end_time:\n", + " model.update()\n", + " Q_m.append(model.get_value(\"Q\")[0])\n", + " time.append(pd.Timestamp(model.time_as_datetime))\n", + "\n", + "model.finalize()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "043cbf70-8ae5-47ab-9bc3-57ff9eb5495a", + "metadata": {}, + "outputs": [], + "source": [ + "model_output_mmday = pd.Series(data=Q_m, name=\"Modelled discharge\", index=time)\n", + "model_output_m3s_logNSE = model_output_mmday * shape_file_area * 1000 / 86400" + ] + }, + { + "cell_type": "markdown", + "id": "0be8a7e3-9d17-4691-b1d4-234073c60f91", + "metadata": {}, + "source": [ + "run test" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "73e07baa-7e1f-4c73-88ae-8451368e68d4", + "metadata": {}, + "outputs": [], + "source": [ + "# Voor test run zijn parameters overschreven met laatste kalibratie voor visualisatie\n", + "# test run is alleen maar om handmatig aanpassingen te kunnen maken aan parameters zonder andere dingen te overschrijven. \n", + "parameters_test = [1.30978424, 0.39171679, 1.05045276]\n", + "\n", + "model = DischargeLocal(forcing = ERA5_forcing)\n", + "config_file, _ = model.setup(parameters=parameters_test, cfg_dir=Eigen_model)\n", + "\n", + "model.initialize(config_file)\n", + "Q_m = []\n", + "time = []\n", + "\n", + "while model.time < model.end_time:\n", + " model.update()\n", + " Q_m.append(model.get_value(\"Q\")[0])\n", + " time.append(pd.Timestamp(model.time_as_datetime))\n", + "\n", + "model.finalize()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f57b2a71-d71e-41bf-8ee8-c9a212eda1f6", + "metadata": {}, + "outputs": [], + "source": [ + "model_output_mmday = pd.Series(data=Q_m, name=\"Modelled discharge\", index=time)\n", + "model_output_m3s_test = model_output_mmday * shape_file_area * 1000 / 86400" + ] + }, + { + "cell_type": "markdown", + "id": "98d1e08f-a7f0-4c4f-b363-dabd98b16b50", + "metadata": {}, + "source": [ + "## Grafiek" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "914e914d-334f-42cb-a46d-4c4d9498ce6c", + "metadata": {}, + "outputs": [], + "source": [ + "# plot grafiek met discharge model 1 en model 2\n", + "plt.figure(figsize=(16, 7))\n", + "\n", + "# model_output_m3s_RMSE = model_output_m3s_RMSE[(model_output_m3s_RMSE.index >= begin_datum) &(model_output_m3s_RMSE.index <= eind_datum)].copy()\n", + "# model_output_m3s_NSE = model_output_m3s_NSE[(model_output_m3s_NSE.index >= begin_datum) &(model_output_m3s_NSE.index <= eind_datum)].copy()\n", + "model_output_m3s_logNSE = model_output_m3s_logNSE[(model_output_m3s_logNSE.index >= begin_datum) &(model_output_m3s_logNSE.index <= eind_datum)].copy()\n", + "model_output_m3s_test = model_output_m3s_test[(model_output_m3s_test.index >= begin_datum) &(model_output_m3s_test.index <= eind_datum)].copy()\n", + "\n", + "# model_output_m3s_logNSE.plot(label=\"Modelled discharge_logNSE\")\n", + "# model_output_m3s_RMSE.plot(label=\"Modelled discharge_RMSE\")\n", + "# model_output_m3s_NSE.plot(label=\"Modelled discharge_NSE\")\n", + "\n", + "model_output_m3s_test.plot(label = \"Model 2\")\n", + "\n", + "plt.plot(height[\"datetime_local_none_test\"], Q_in_L, label = \"Model 1\")\n", + "\n", + "plt.xlabel(\"Datum\")\n", + "plt.ylabel(\"Afvoer [m^3/s]\")\n", + "plt.title(\"Vergelijking afvoer modellen Surinamerivier\")\n", + "plt.legend()\n", + "plt.grid(True)\n", + "plt.show()\n", + "np.set_printoptions(suppress=True)\n", + "\n", + "# print(f'The RMSE paramaters are: {parameters_RMSE}')\n", + "# print(f'The NSE paramters are: {parameters_NSE}')\n", + "# print(f'The logNSE paramters are: {parameters_logNSE}');" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a9baadb9-f3b9-4d5d-8e89-64127d57748b", + "metadata": {}, + "outputs": [], + "source": [ + "dt_days = np.diff(height[\"datetime_local_none_test\"]).astype('timedelta64[s]').astype(float) / (24 * 3600)\n", + "dt_days_full = np.zeros(len(Q_in_L))\n", + "dt_days_full[1:] = dt_days\n", + "Q_in_day_weighted = Q_in_L * dt_days_full\n", + "Q_in_day_weighted_sum = np.cumsum(Q_in_day_weighted)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "883432ba-6f60-463c-bd2e-62775ab7582e", + "metadata": {}, + "outputs": [], + "source": [ + "# plot cumulatieve discharge model 1 en model 2\n", + "plt.figure(figsize=(16, 7))\n", + "\n", + "model_output_m3s_RMSE_sum = np.cumsum(model_output_m3s_RMSE)\n", + "model_output_m3s_NSE_sum = np.cumsum(model_output_m3s_NSE)\n", + "model_output_m3s_logNSE_sum = np.cumsum(model_output_m3s_logNSE)\n", + "model_output_m3s_test_sum = np.cumsum(model_output_m3s_test)\n", + "\n", + "# model_output_m3s_logNSE_sum.plot(label=\"Modelled discharge_logNSE\")\n", + "# model_output_m3s_RMSE_sum.plot(label=\"Modelled discharge_RMSE\")\n", + "# model_output_m3s_NSE_sum.plot(label=\"Modelled discharge_NSE\")\n", + "model_output_m3s_test_sum.plot(label=\"Model 2\")\n", + "plt.plot(height[\"datetime_local_none_test\"], Q_in_day_weighted_sum, label = \"Model 1\")\n", + "\n", + "# plt.plot(height[\"datetime_local_none_test\"], Q_in_L, label = \"Q_in [m^3/s]\")\n", + "\n", + "plt.xlabel(\"Datum\")\n", + "plt.ylabel(\"Afvoer [m^3]\")\n", + "plt.title(\"Cumulatieve afvoer Surinamerivier van de modellen\")\n", + "plt.legend()\n", + "plt.grid(True)\n", + "plt.show()\n", + "\n", + "np.set_printoptions(suppress=True)\n", + "\n", + "print(f'The RMSE parameters are: {parameters_RMSE}')\n", + "print(f'The NSE parameters are: {parameters_NSE}')\n", + "print(f'The logNSE parameters are: {parameters_logNSE}');" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b4a61629-9d69-4575-8670-a9d72ebd29e6", + "metadata": {}, + "outputs": [], + "source": [ + "def level(Qin, Qout, ERA5_forcing, A, L0):\n", + " # Qin is array met discharge van rivier in meer, gebaseerd op E en P en dagelijks [m^3/s]\n", + " # Qout is een standaard baseflow uit het meer [m^3/s]\n", + " # E is verdampingsdata van ERA5, dagelijks [mm/s]\n", + " # A is oppervlakte meer [km^2]\n", + " # L0 is een gegeven begin hoogte [m]\n", + " # L0 moet handmatig worden ingevoerd omdat in de toekomst niet zeker is hoe hoog het meer gaat staan op het beginpunt van de forcing data\n", + " \n", + " dt = 3600*24\n", + " E = ERA5_forcing.to_xarray()[\"evspsblpot\"] /1000 #* dt\n", + " L = np.zeros(len(Qin))\n", + " L[0] = L0\n", + " A = A * 10**6\n", + " \n", + " for i in range(len(Qin)-1):\n", + " dL = ((Qin.iloc[i] - Qout) / A) - E[i]\n", + " L[i+1] = L[i] + dL*dt \n", + " if L[i+1] > 48.5:\n", + " L[i+1] = 48.5\n", + " return L" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "94e3f8bd-7697-423b-b102-a4013fd508ec", + "metadata": {}, + "outputs": [], + "source": [ + "# hoogte functie testen op ERA5 data\n", + "a = level(model_output_m3s_test, Q_out, ERA5_forcing, 1020, 46.5)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6c49f9cd-f534-4771-b657-666bf14c0e16", + "metadata": {}, + "outputs": [], + "source": [ + "# hoogte functie plotten voor ERA5 data\n", + "plt.figure(figsize=(16, 7))\n", + "plt.plot(model_output_m3s_logNSE.index, a, label = \"Height [m]\")\n", + "\n", + "plt.xlabel(\"Date\")\n", + "plt.ylabel(\"Height (m)\")\n", + "plt.title(\"Height function\")\n", + "plt.legend()\n", + "plt.grid(True)\n", + "plt.show()\n", + "\n", + "np.set_printoptions(suppress=True)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Under_construction/Suriname_model_.ipynb b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Under_construction/Suriname_model_.ipynb new file mode 100644 index 00000000..8bdf365a --- /dev/null +++ b/book/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/Under_construction/Suriname_model_.ipynb @@ -0,0 +1,477 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "4de0376e-67a9-4574-8972-afda650493dc", + "metadata": {}, + "outputs": [], + "source": [ + "# importeren om te kunnen werken\n", + "import warnings\n", + "warnings.filterwarnings(\"ignore\", category=UserWarning)\n", + "import numpy as np\n", + "from pathlib import Path\n", + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "import xarray as xr\n", + "import seaborn as sns\n", + "import math as math\n", + "import ewatercycle\n", + "import ewatercycle.models\n", + "import ewatercycle.forcing\n", + "\n", + "shape_file_area = 7.629080e+03 # in km^2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c76d2921-e37c-415b-966d-0a5103cf9b13", + "metadata": {}, + "outputs": [], + "source": [ + "#Route naar oppervlakte\n", + "\n", + "opp_file = Path.home() / \"BEP-Julian\" / \"BEP-Julian\" / \"Suriname_Model\" / \"GWSC_dams_mogwai_Brokopondo.csv\"\n", + "opp = pd.read_csv(opp_file, delimiter=',', skiprows = 1)\n", + "opp = opp.rename(columns={\"Time (UTC)\": \"Date\"})\n", + "opp[\"Date\"] = pd.to_datetime(opp[\"Date\"], utc = True) #opp werkt in \"Date\" en \"Value voor de datum en de km^2\n", + "\n", + "# plt.figure(figsize=(12, 5))\n", + "# plt.plot(opp[\"Date\"], opp[\"Value\"])\n", + "# plt.grid(); " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "89a3e133-26b7-4908-a72d-65333ec16d61", + "metadata": {}, + "outputs": [], + "source": [ + "# Hoogtemetingen plotten samen met kritische en zeer kritische hoogte\n", + "\n", + "plt.figure(figsize=(16, 7))\n", + "\n", + "height_file = Path.home() / \"BEP-Julian\" / \"BEP-Julian\" / \"Suriname_Model\" / \"Dahiti Brokopondo water height.xlsx\"\n", + "\n", + "# Read malformed Excel\n", + "height = pd.read_excel(height_file)\n", + "\n", + "# Split the single column into multiple columns\n", + "height = height.iloc[:, 0].str.split(';', expand=True)\n", + "\n", + "# Rename columns\n", + "height.columns = [\"datetime\", \"wse\", \"wse_u\"]\n", + "\n", + "# Convert data types\n", + "height[\"datetime\"] = pd.to_datetime(height[\"datetime\"], utc=True)\n", + "height[\"wse\"] = height[\"wse\"].astype(float)\n", + "height[\"wse_u\"] = height[\"wse_u\"].astype(float)\n", + "\n", + "# Plot\n", + "plt.figure(figsize=(12,5))\n", + "plt.plot(height[\"datetime\"], height[\"wse\"], label = \"Waterhoogte metingen\") #height werkt in \"datetime\" en \"wse\" voor datum en hoogte\n", + "plt.title(\"Historische waterhoogte Brokopondomeer\")\n", + "plt.xlabel(\"Datum\")\n", + "plt.ylabel(\"Waterhoogte [m]\")\n", + "plt.axhline(42.92, color = \"r\", linestyle='--', label = \"Kritische hoogte\")\n", + "plt.axhline(40.5, color = \"r\", label = \"Zeer kritische hoogte\")\n", + "plt.legend()\n", + "plt.grid()\n", + "plt.show();" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d695f4b7-0499-42e3-92a4-2cf4a5b93b2d", + "metadata": {}, + "outputs": [], + "source": [ + "#begin en eind datum van beide metingen samen bepalen. \n", + "start = max(opp[\"Date\"].min(), height[\"datetime\"].min())\n", + "end = min(opp[\"Date\"].max(), height[\"datetime\"].max())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "968a4e5e-2d51-41bf-8c9c-364050dd87fd", + "metadata": {}, + "outputs": [], + "source": [ + "# oppervlakte tussen de start en einddatum zetten. \n", + "opp = opp[\n", + " (opp[\"Date\"] >= start) &\n", + " (opp[\"Date\"] <= end)\n", + "].copy()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4581b4af-76d0-4c7a-840e-e3394e276578", + "metadata": {}, + "outputs": [], + "source": [ + "# hoogte en oppervlakte metingen plotten. \n", + "fig, ax1 = plt.subplots(figsize=(16,7))\n", + "ax1.plot(opp[\"Date\"], opp[\"Value\"], 'b', label = 'Oppervlakte')\n", + "ax1.set_xlabel(\"Datum\")\n", + "ax1.set_ylabel(\"Oppervlakte stuwmeer [m^2]\")\n", + "plt.legend(loc = 'lower left')\n", + "\n", + "# Right y-axis: water level\n", + "ax2 = ax1.twinx()\n", + "ax2.plot(height[\"datetime\"], height[\"wse\"], 'g', label = 'Hoogte')\n", + "ax2.set_ylabel(\"Waterhoogte [m]\")\n", + "\n", + "plt.title(\"Brokopondomeer metingen waterhoogte en oppervlakte\")\n", + "plt.legend(loc = 'lower right')\n", + "plt.grid()\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "95d9612d-b08f-44be-90ba-d98355cf4ed9", + "metadata": {}, + "outputs": [], + "source": [ + "# Forcing genereren\n", + "basin_name = \"Suriname\"\n", + "\n", + "# tijdsinterval\n", + "start_datum = \"2019-01-01\"\n", + "eind_datum = \"2024-12-31\"\n", + "start_datum = pd.to_datetime(start_datum, utc=True)\n", + "end_datum = pd.to_datetime(eind_datum, utc=True)\n", + "start_pd = start_datum.strftime(\"%Y-%m-%dT%H:%M:%SZ\")\n", + "end_pd = end_datum.strftime(\"%Y-%m-%dT%H:%M:%SZ\")\n", + "start_datum = start_pd\n", + "eind_datum = end_pd\n", + "\n", + "# route naar shape file\n", + "shapefile = Path.home() / \"BEP-Julian\" / \"BEP-Julian\" / \"Suriname_Model\" / \"boven_suriname.shp\"\n", + "\n", + "HBV_model = Path.home() / \"BEP-Julian\" / \"BEP-Julian\" / \"Suriname_Model\" / \"hbv_bmi\"\n", + "\n", + "forcing_route = Path.home() / \"BEP-Julian\" / \"BEP-Julian\" / \"Forcing\" / \"ERA5_SUR_2019_2024\"/ \"work\" / \"diagnostic\" / \"script\" " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "51bd5cd4-40f4-49e6-8cdc-5fd2b06ba500", + "metadata": {}, + "outputs": [], + "source": [ + "# forcing genereren\n", + "\n", + "# ERA5_forcing = ewatercycle.forcing.sources['LumpedMakkinkForcing'].generate(\n", + "# dataset=\"ERA5\",\n", + "# start_time=start_datum,\n", + "# end_time=eind_datum,\n", + "# shape=shapefile,\n", + "# directory=forcing_route\n", + "# )\n", + "\n", + "# forcing inladen\n", + "ERA5_forcing = ewatercycle.forcing.sources[\"LumpedMakkinkForcing\"].load(directory=forcing_route)\n", + "\n", + "print(f\"The forcing object you created: \\n {ERA5_forcing}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "eafb1da2-bcb9-4d06-afa0-920badb6adec", + "metadata": {}, + "outputs": [], + "source": [ + "# verdampingen en neerslag bruikbaar maken\n", + "evap = ERA5_forcing.to_xarray()[\"evspsblpot\"] #units: kg m^-2 s^-1 = mm/s, gesampled per dag\n", + "prec = ERA5_forcing.to_xarray()[\"pr\"] #units: kg m^-2 s^-1 = mm/s, gesampled per dag\n", + "fig, ax = plt.subplots(figsize=(12,5))\n", + "\n", + "# evap.plot(ax=ax, label='Potential evaporation')\n", + "# prec.plot(ax=ax, label='Precipitation')\n", + "# ax.set_ylabel('mm/s')\n", + "# ax.set_xlabel(\"tijd\")\n", + "# plt.title(\"E en P in mm/s, sampled per dag\")\n", + "# ax.legend();" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e3177704-8cc4-4c28-9d0a-8b5e26458130", + "metadata": {}, + "outputs": [], + "source": [ + "# neerslag bruikbaar maken en plotten in mm/seconde\n", + "evap = ERA5_forcing.to_xarray()[\"evspsblpot\"] #units: kg m^-2 s^-1 = mm/s, gesampled per dag\n", + "prec = ERA5_forcing.to_xarray()[\"pr\"] #units: kg m^-2 s^-1 = mm/s, gesampled per dag\n", + "fig, ax = plt.subplots(figsize=(12,5))\n", + "\n", + "# evap.plot(ax=ax, label='Potential evaporation')\n", + "# prec.plot(ax=ax, label='Precipitation')\n", + "# ax.set_ylabel('mm/s')\n", + "# ax.set_xlabel(\"tijd\")\n", + "# plt.title(\"E en P in mm/s, sampled per dag\")\n", + "# ax.legend();" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4f552d0c-966f-4ba6-90f4-9ad186503bca", + "metadata": {}, + "outputs": [], + "source": [ + "# neerslag bruikbaar maken en plotten in mm/dag\n", + "print(evap.min().values, evap.max().values)\n", + "print(prec.min().values, prec.max().values)\n", + "evap_dag = evap*3600*24\n", + "prec_dag = prec*3600*24\n", + "fig, ax = plt.subplots(figsize=(12,5))\n", + "evap_dag.plot(ax=ax, label=\"Evaporation [mm/day]\")\n", + "prec_dag.plot(ax=ax, label=\"Precipitation [mm/day]\")\n", + "\n", + "# ax.set_ylabel(\"mm/dag\")\n", + "# ax.set_xlabel(\"tijd\")\n", + "# ax.legend()\n", + "# plt.title(\"E en P in mm/dag, sampled per dag\")\n", + "# plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cb1d5f25-4fdf-48ca-84f6-bb16695182ee", + "metadata": {}, + "outputs": [], + "source": [ + "# hoogte-volume verhouding plotten\n", + "\n", + "fig, ax1 = plt.subplots(figsize=(5,6))\n", + "testH = np.arange(0, 55, 0.1)\n", + "testV = np.zeros(len(testH))\n", + "for i in range(len(testH)):\n", + " testV[i] = (testH[i] - 36.715)/0.9096\n", + "plt.plot(testV, testH, label = \"Rule curve\")\n", + "\n", + "testHh = np.arange(0, 55, 0.1)\n", + "testVv = np.zeros(len(testHh))\n", + "\n", + "testVvv = np.arange(0,20, 0.03)\n", + "testHhh = np.zeros(len(testVvv))\n", + "for i in range(len(testVvv)):\n", + " testHhh[i] = 8 + 15*np.log(testVvv[i]+2)\n", + "plt.plot(testVvv, testHhh, label = \"Verhouding H en V\")\n", + "\n", + "plt.xlim(0, 20)\n", + "plt.title(\"Bathymetrie Brokopondomeer\")\n", + "plt.legend(loc = 'lower right')\n", + "ax1.set_xlabel(\"Volume meer [km^3]\")\n", + "ax1.set_ylabel(\"Hoogte meer [m]\")\n", + "plt.grid();" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0173c4b8-bdb2-4209-b2a9-89a4ec2b03cf", + "metadata": {}, + "outputs": [], + "source": [ + "# hoogte-volume verhouding toepassen op hoogtemetingen\n", + "\n", + "fig, ax1 = plt.subplots(figsize=(12,5))\n", + "H = height[\"wse\"]\n", + "V = np.zeros(len(H))\n", + "# H = 8 + 15*np.log(V+2) met np.log = ln\n", + "# V = math.exp((H-8)/15)-2\n", + "for i in range(len(H)):\n", + " V[i] = math.exp((H[i]-8)/15)-2\n", + "plt.plot(height[\"datetime\"], V)\n", + "plt.title(\"V in km^3 according to (Sterl et al., 2020)\")\n", + "plt.grid();" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3311cb53-5cd2-4bbe-9b71-f4d4c4b121a5", + "metadata": {}, + "outputs": [], + "source": [ + "# tijd tussen metingen plotten in dagen\n", + "fig, ax1 = plt.subplots(figsize=(12,5))\n", + "height[\"time_diff\"] = height[\"datetime\"].diff()\n", + "height[\"time_diff_hours\"] = (\n", + " height[\"datetime\"].diff().dt.total_seconds() / (3600*24)\n", + ")\n", + "plt.plot(height[\"datetime\"], height[\"time_diff_hours\"])\n", + "plt.title(\"Tijd tussen hoogtemetingen Brokopondomeer in dagen\")\n", + "plt.xlabel(\"Datum\")\n", + "plt.ylabel(\"Dagen tussen metingen\")\n", + "plt.grid();" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "098c5edd-da13-4887-9706-423790b23db1", + "metadata": {}, + "outputs": [], + "source": [ + "# verdamping en instroom model 1 berekenen en plotten\n", + "\n", + "height[\"datetime_local_none_test\"] = height[\"datetime\"].dt.tz_localize(None)\n", + "fig, ax1 = plt.subplots(figsize=(16,5))\n", + "\n", + "opp[\"Date\"] = opp[\"Date\"].dt.tz_localize(None)\n", + "begin_datum = pd.to_datetime(start_datum).tz_localize(None)\n", + "eind_datum = pd.to_datetime(eind_datum).tz_localize(None)\n", + "evap = evap.sel(time=slice(begin_datum, eind_datum))\n", + "\n", + "height = height[\n", + " (height[\"datetime_local_none_test\"] >= begin_datum) &\n", + " (height[\"datetime_local_none_test\"] <= eind_datum)\n", + "].copy()\n", + "\n", + "height = height.reset_index(drop=True)\n", + "\n", + "height = height.reset_index(drop=True)\n", + "\n", + "area_interp = np.interp(height[\"datetime_local_none_test\"].astype(\"int64\"), opp[\"Date\"].astype(\"int64\"), opp[\"Value\"])\n", + "\n", + "H = height[\"wse\"].to_numpy()\n", + "V = np.exp((H - 8)/15) - 2\n", + "Vv = V * 10**9 # van km^3 naar m^3\n", + "delta_s = np.zeros(len(height[\"datetime_local_none_test\"]))\n", + "E = np.zeros(len(height[\"datetime_local_none_test\"]))\n", + "opper = np.zeros(len(height[\"datetime_local_none_test\"]))\n", + "Q_in_L = np.zeros(len(height[\"datetime_local_none_test\"]))\n", + "E_v = np.zeros(len(height[\"datetime_local_none_test\"]))\n", + "Q_in_L_sum = np.zeros(len(height[\"datetime_local_none_test\"]))\n", + "Q_in_L_sum_test = np.zeros(len(height[\"datetime_local_none_test\"]))\n", + "Q_out = 200\n", + "\n", + "for i in range(len(height[\"datetime_local_none_test\"])-1):\n", + " \n", + " t0 = height[\"datetime_local_none_test\"].iloc[i]\n", + " t1 = height[\"datetime_local_none_test\"].iloc[i+1]\n", + "\n", + " dt_seconds = (t1 - t0).total_seconds()\n", + " delta_s[i+1] = (Vv[i+1] - Vv[i]) / dt_seconds\n", + " \n", + " evap_interval = evap.sel(time=slice(t0, t1))\n", + " E[i+1] = evap_interval.mean().values * 10**-3 #/dt_seconds # van mm/s naar m/s\n", + "\n", + " A_t = area_interp[i+1]\n", + " E_v[i+1] = A_t * 1e6 * E[i+1]\n", + "\n", + " Q_in_L[i+1] = delta_s[i+1] + E_v[i+1] + Q_out\n", + " Q_in_L[i+1] = np.nan_to_num(Q_in_L[i+1], nan=0.0)\n", + " Q_in_L_sum[i] = Q_in_L.sum()\n", + " Q_in_L_sum_test = np.cumsum(Q_in_L)\n", + "\n", + "plt.plot(height[\"datetime_local_none_test\"], Q_in_L, label = \"Q_in model 1 \")\n", + "plt.plot(height[\"datetime_local_none_test\"], E_v, label = \"Verdamping model 1\")\n", + "plt.xlabel(\"Datum\")\n", + "plt.ylabel(\"Discharge [m^3/s]\")\n", + "plt.legend()\n", + "plt.title(\"Qin per dag m^3/s\")\n", + "plt.grid();" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a6f92c2e-f67d-4904-a45d-64ae457a1b44", + "metadata": {}, + "outputs": [], + "source": [ + "# functie om instroom meer naar hooogte om te zetten\n", + "\n", + "def level(Qin, Qout, ERA5_forcing, A):\n", + " #Qin is array met discharge van rivier in meer, gebaseerd op E en P en dagelijks\n", + " #Qout is een standaard baseflow uit het meer\n", + " #E is verdampingsdata van ERA5, dagelijks\n", + " #A is oppervlakte meer in m^2 \n", + " \n", + " dt = 3600*24\n", + " E = ERA5_forcing.to_xarray()[\"evspsblpot\"] * dt\n", + " L = np.zeros(len(E))\n", + " \n", + " for i in range(len(E)):\n", + " dL = (Qin[i] - Qout - E[i]) / A\n", + " L[i] = L[i-1] + dL*dt\n", + " return L" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c864c65e-b343-4896-8d99-f6612043fd1e", + "metadata": {}, + "outputs": [], + "source": [ + "# model 2 \n", + "\n", + "def discharge(parameters, forcing):\n", + " # parameters zijn;\n", + " # Qgw - ground water flow in eht meer\n", + " # alpha - neerslag/verdamping coefficient\n", + " # beta - neerslag/verdamping coefficient\n", + " ERA5_forcing = forcing\n", + "\n", + " E_da = ERA5_forcing.to_xarray()[\"evspsblpot\"] #units: kg m^-2 s^-1 = mm/s, gesampled per dag\n", + " P_da = ERA5_forcing.to_xarray()[\"pr\"] #units: kg m^-2 s^-1 = mm/s, gesampled per dag\n", + "\n", + " Qg, alpha, beta = parameters\n", + "\n", + " dt = 86400\n", + "\n", + " Qin = []\n", + "\n", + " for current_timestep in range(len(P_da)):\n", + "\n", + " P = P_da.isel(time=current_timestep).to_numpy() * dt\n", + " E = E_da.isel(time=current_timestep).to_numpy() * dt\n", + "\n", + " Q = Qg + alpha * (P - E)**beta\n", + "\n", + " Qin.append(Q)\n", + "\n", + " return Qin # in m^3/s" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/book/thesis_projects/BSc/2026_Q4_NielsEijer_CEG/BSc_NielsEijer.md b/book/thesis_projects/BSc/2026_Q4_NielsEijer_CEG/BSc_NielsEijer.md index 4c022649..9c9f2d65 100644 --- a/book/thesis_projects/BSc/2026_Q4_NielsEijer_CEG/BSc_NielsEijer.md +++ b/book/thesis_projects/BSc/2026_Q4_NielsEijer_CEG/BSc_NielsEijer.md @@ -1,4 +1,6 @@ -# Samenvatting +# Bevaarbaarheid van de IJssel: Een kwantitatieve analyse van de invloed van klimaatverandering onder low-flow conditions - Niels Eijer + +## Samenvatting Dit onderzoek analyseert hoe klimaatverandering de bevaarbaarheid van de IJssel onder lage afvoercondities kan beïnvloeden, met de afvoer bij Lobith als bovenstroomse hydrologische randvoorwaarde voor de Rijntakken. De centrale vraag is in welke mate toekomstige low-flow condities, veroorzaakt diff --git a/book/thesis_projects/BSc/overview_BSc_thesis_projects.md b/book/thesis_projects/BSc/overview_BSc_thesis_projects.md index ee84aeec..bff57624 100644 --- a/book/thesis_projects/BSc/overview_BSc_thesis_projects.md +++ b/book/thesis_projects/BSc/overview_BSc_thesis_projects.md @@ -24,7 +24,7 @@ The projects are listed in chronological order. - 2026 Q4 by Beau Buijtenhuijs: [Impact of Climate Change on the Okavango River: The impact of the future discharge on the water supply of Okavango Basin](https://www.ewatercycle.org/projects/main/thesis_projects/BSc/2026_Q4_BeauBuijtenhuijs_CEG/Report/00_Abstract.html) - [pdf version (ask us)] - taken from [Beau's GitHub page](https://github.com/BeauBuijtenhuijs/BEP-beau) -- 2026 Q4 by Julian Steenhuisen: [Droogte in het Brokopondomeer: De effecten van klimaatverandering op de Surinamerivier (Dutch report)](https://www.ewatercycle.org/projects/main/thesis_projects/BSc/) +- 2026 Q4 by Julian Steenhuisen: [Droogte in het Brokopondomeer: De effecten van klimaatverandering op de Surinamerivier (Dutch report)](https://www.ewatercycle.org/projects/main/thesis_projects/BSc/2026_Q4_JulianSteenhuisen_CEG/BSc_JulianSteenhuisen.html) - [pdf version (ask us)] - taken from [Julian's GitHub page](https://github.com/jlsteenhuisen/BEP-Julian/tree/BEP-Julian) - 2026 Q4 by Maxime de Bekker: [The influence of climate change on the river discharge of the Lower Athabasca River and its implications for navigation](https://www.ewatercycle.org/projects/main/thesis_projects/BSc/2026_Q4_MaximedeBekker_CEG/BSc_MaximedeBekker.html) diff --git a/test.txt b/test.txt deleted file mode 100644 index e69de29b..00000000