From db81f84ac15627807ca36413ca52d5c3faa2e087 Mon Sep 17 00:00:00 2001 From: Anna Petrasova Date: Tue, 9 Jun 2026 16:22:41 -0400 Subject: [PATCH 1/2] update with soils --- .../parallelization/SIMWE_parallelization.qmd | 149 +++++++++++------- .../tutorials/parallelization/references.bib | 0 2 files changed, 93 insertions(+), 56 deletions(-) create mode 100644 content/tutorials/parallelization/references.bib diff --git a/content/tutorials/parallelization/SIMWE_parallelization.qmd b/content/tutorials/parallelization/SIMWE_parallelization.qmd index 6747649..4c8ad9a 100644 --- a/content/tutorials/parallelization/SIMWE_parallelization.qmd +++ b/content/tutorials/parallelization/SIMWE_parallelization.qmd @@ -9,6 +9,7 @@ description: > and erosion simulation (SIMWE) split by subwatersheds in parallel. image: SIMWE_images/thumbnail.webp +bibliography: references.bib format: ipynb: default html: @@ -265,7 +266,7 @@ The rest of the workflow will be done in a CRS used in North Carolina (EPSG 3358 Since we want our project to use a different CRS more suitable for our study area (EPSG:3358 for North Carolina), we will create it now: ```{python} -nc_project = path / "NC" +nc_project = Path(path) / "NC" gs.create_project(nc_project, epsg="3358") session = gj.init(nc_project) ``` @@ -369,7 +370,7 @@ tools.g_region(vector=f"basin_{huc12}") Display the NED data for that region: ```{python} -basin_map = gj.Map(current_region=True) +basin_map = gj.Map(use_region=True) basin_map.d_rast(map="ned") basin_map.d_vect(map=f"basin_{huc12}", fill_color="none") basin_map.show() @@ -392,7 +393,7 @@ MaskManager is new in GRASS version 8.5. Alternatively, you can use [r.mask](htt mask = gs.MaskManager(mask_name=f"basin_{huc12}") mask.activate() -basin_map = gj.Map(current_region=True) +basin_map = gj.Map(use_region=True) basin_map.d_rast(map="ned") basin_map.d_legend( raster="ned", @@ -418,60 +419,109 @@ basin_map.show() ![](SIMWE_images/basin_030401010402_nlcd.webp) -We will create a file `mannings.txt` to reclassify NLCD to manning's coefficients. The values are suggestions from the [r.sim.water](https://grass.osgeo.org/grass-devel/manuals/r.sim.water.html) documentation. The format is described in [r.recode](https://grass.osgeo.org/grass-devel/manuals/r.recode.html) documentation. +Next, we will estimate Manning's roughness coefficient from the NLCD landcover +using [r.manning](https://grass.osgeo.org/grass-stable/manuals/addons/r.manning.html) addon tool. +Specifically, we will use [@kalyanapu2009] lookup table that is more suitable for shallow flow. -```text -%%writefile mannings.txt -11:11:0.001 -21:21:0.0404 -22:23:0.0678 -24:24:0.0404 -31:31:0.0113 -41:41:0.36 -42:42:0.32 -43:52:0.4 -52:52:0.4 -71:71:0.368 -81:82:0.325 -90:90:0.086 -95:95:0.1825 +```{python} +tools.g_extension(extension="r.manning") +tools.r_manning(input=f"nlcd_{huc12}", output=f"mannings_{huc12}", landcover="nlcd", source="kalyanapu") + +basin_map = gj.Map() +basin_map.d_rast(map=f"mannings_{huc12}") +basin_map.d_legend( + raster=f"mannings_{huc12}", + flags="t", + at=[10, 15, 40, 95], + title="Roughness", + fontsize=12, +) +basin_map.show() ``` +Then we will estimate rainfall excess and to do that we will first process +soil data for our area using [r.in.ssurgo](https://grass.osgeo.org/grass-stable/manuals/addons/r.in.ssurgo.html) addon tool. +Since we need a fairly large area, we will first download the soil data itself for North Carolina +from [Gridded Soil Survey Geographic (gSSURGO) Database](https://www.nrcs.usda.gov/resources/data-and-reports/gridded-soil-survey-geographic-gssurgo-database) +and then have r.in.ssurgo extract Hydrologic Soil Group for our area. + +::: {.callout-note title="What is Hydrologic Soil Group?"} +Hydrologic Soil Group (HSG) classifies soils based on their minimum +infiltration rate and potential for rainfall runoff. +For smaller areas, r.in.ssurgo can download the data directly using the +[Soil Data Access (SDA) API](https://sdmdataaccess.nrcs.usda.gov/). +::: + ```{python} -tools.r_recode(input=f"nlcd_{huc12}", output=f"mannings_{huc12}", rules="mannings.txt") +tools.g_extension(extension="r.in.ssurgo") +tools.r_in_ssurgo(ssurgo_path=f"", soils=f"soils_{huc12}", hydgrp=f"hydgrp_{huc12}", nprocs=1) + +soil_map = gj.Map() +soil_map.d_rast(map=f"hydgrp_{huc12}") +soil_map.d_legend( + raster=f"hydgrp_{huc12}", + at=[10, 15, 40, 95], + title="HSG", + fontsize=12, +) +soil_map.show() ``` -Similarly, we will reclassify rainfall excess (rainfall minus infiltration). -These rainfall excess values were derived using the SCS Curve Number method for 50 mm/h of precipitation, assigning typical Curve Numbers based on common hydrologic soil groups for each NLCD land cover class; -they provide a rough estimate and should be refined with local soil and land management data when available. +With the soil and landcover data available, we will generate Curve Number, +which is an empirical parameter to estimate surface runoff. -```text -%%writefile runoff.txt -11:11:0.0 -21:21:3.3 # Developed Open Space (CN ~68, HSG B) -22:22:7.9 # Developed Low Intensity (CN ~81, HSG C) -23:23:19.8 # Developed Medium Intensity (CN ~90, HSG C) -24:24:27.9 # Developed High Intensity (CN ~94, HSG D) -31:31:6.1 # Barren (CN ~75, HSG B) -41:41:0.0 # Forest (CN ~55, HSG A) — P < 0.2S → Q = 0 -42:42:0.0 -43:43:0.0 -52:52:3.3 # Shrub/Scrub (CN ~68, HSG B) -71:71:2.0 # Grassland (CN ~61, HSG A) -81:81:5.1 # Pasture (CN ~74, HSG B) -82:82:14.7 # Cropland (CN ~82, HSG C) -90:90:0.0 # Woody Wetlands (CN ~70, HSG D) — often saturated, still low Q here -95:95:0.0 # Herbaceous Wetlands +```{python} +tools.g_extension(extension="r.curvenumber") +tools.r_curvenumber(landcover=f"nlcd_{huc12}", landcover_source="nlcd", soil=f"hydgrp_{huc12}", + output=f"curvenumber_{huc12}") + +cn_map = gj.Map() +cn_map.d_rast(map=f"curvenumber_{huc12}") +cn_map.d_legend( + raster=f"curvenumber_{huc12}", + at=[10, 15, 40, 95], + flags="t", + title="CN", + fontsize=12, +) +cn_map.show() ``` +We will model a 50-year storm event that lasts 3 hours, using data from +[NOAA Atlas 14](https://hdsc.nws.noaa.gov/pfds/) Precipitation Frequency Data Server. + ```{python} -tools.r_recode(input=f"nlcd_{huc12}", output=f"runoff_{huc12}", rules="runoff.txt") +tools.g_extension(extension="r.noaa.atlas14") +duration = 3 +depths = tools.r_noaa_atlas14(mode="point", statistic="depth", units="metric", format="json") +depth = [row["values"] for row in depth["table"]["rows"] if row["duration"] == f"{duration}-hr"]["50"] +print(depth) +``` + +We will then create an input rainfall depth raster: + +``` +tools.r_mapcalc(expression=f"rainfall_{huc12} = {depth}") ``` -Then, compute slope components (dx and dy) from the elevation raster to support hydrologic modeling. +With that we estimate runoff (rainfall excess): ```{python} -tools.r_slope_aspect(elevation="ned", dx=f"dx_{huc12}", dy=f"dy_{huc12}") +tools.g_extension(extension="r.runoff") +tools.r_runoff(rainfall=f"rainfall_{huc12}", duration=duration, curve_number=f"curvenumber_{huc12}", + runoff_depth=f"runoff_depth_{huc12}") +tools.r_mapcalc(expression=f"runoff_{huc12} = runoff_depth_{huc12} / {duration}") + +runoff_map = gj.Map() +runoff_map.d_rast(map=f"runoff_{huc12}") +runoff_map.d_legend( + raster=f"runoff_{huc12}", + at=[10, 15, 40, 95], + flags="t", + title="Runoff [mm/h]", + fontsize=12, +) +runoff_map.show() ``` Run hydrologic and sediment simulations for the selected subwatershed. @@ -483,8 +533,6 @@ Running the simulation may take a while. simulation_time = 180 tools.r_sim_water( elevation="ned", - dx=f"dx_{huc12}", - dy=f"dy_{huc12}", depth=f"depth_{huc12}", niterations=simulation_time, man=f"mannings_{huc12}", @@ -516,8 +564,6 @@ tools.r_mapcalc(expression=f"shear_stress_{huc12} = 0.01") tools.r_sim_sediment( elevation="ned", water_depth=f"depth_{huc12}", - dx=f"dx_{huc12}", - dy=f"dy_{huc12}", detachment_coeff=f"detachment_coef_{huc12}", transport_coeff=f"transport_capacity_{huc12}", shear_stress=f"shear_stress_{huc12}", @@ -665,15 +711,8 @@ def compute(huc12): output=f"runoff_{huc12}", rules="runoff.txt", ) - tools.r_slope_aspect( - elevation="ned", - dx=f"dx_{huc12}", - dy=f"dy_{huc12}", - ) tools.r_sim_water( elevation="ned", - dx=f"dx_{huc12}", - dy=f"dy_{huc12}", depth=f"depth_{huc12}", niterations=simulation_time, man=f"mannings_{huc12}", @@ -686,8 +725,6 @@ def compute(huc12): tools.r_sim_sediment( elevation="ned", water_depth=f"depth_{huc12}", - dx=f"dx_{huc12}", - dy=f"dy_{huc12}", detachment_coeff=f"detachment_coef_{huc12}", transport_coeff=f"transport_capacity_{huc12}", shear_stress=f"shear_stress_{huc12}", diff --git a/content/tutorials/parallelization/references.bib b/content/tutorials/parallelization/references.bib new file mode 100644 index 0000000..e69de29 From da53eca9f0ebad261dfdc239a211a01c0530469a Mon Sep 17 00:00:00 2001 From: Anna Petrasova Date: Thu, 11 Jun 2026 17:23:38 -0400 Subject: [PATCH 2/2] continued --- .../SIMWE_images/basin_030401010402.webp | Bin 16036 -> 0 bytes .../basin_030401010402_masked.webp | Bin 9536 -> 0 bytes .../parallelization/SIMWE_parallelization.qmd | 130 +++++++----------- 3 files changed, 50 insertions(+), 80 deletions(-) delete mode 100644 content/tutorials/parallelization/SIMWE_images/basin_030401010402.webp delete mode 100644 content/tutorials/parallelization/SIMWE_images/basin_030401010402_masked.webp diff --git a/content/tutorials/parallelization/SIMWE_images/basin_030401010402.webp b/content/tutorials/parallelization/SIMWE_images/basin_030401010402.webp deleted file mode 100644 index e9e07c53b277caea773ba478e93539f728255fe5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16036 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 diff --git a/content/tutorials/parallelization/SIMWE_images/basin_030401010402_masked.webp b/content/tutorials/parallelization/SIMWE_images/basin_030401010402_masked.webp deleted file mode 100644 index 2327880c96ceaf3c2d59830212d72054f8fa5426..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9536 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 diff --git a/content/tutorials/parallelization/SIMWE_parallelization.qmd b/content/tutorials/parallelization/SIMWE_parallelization.qmd index 4c8ad9a..8bc504c 100644 --- a/content/tutorials/parallelization/SIMWE_parallelization.qmd +++ b/content/tutorials/parallelization/SIMWE_parallelization.qmd @@ -42,9 +42,9 @@ subwatersheds, each approximately 100 km² in size) and run simulations independently for each unit. This approach demonstrates how to leverage new Python API features introduced -in GRASS 8.5—specifically, the [Tools API](https://grass.osgeo.org/grass-devel/manuals/libpython/grass.tools.html#) -and the [MaskManager](https://grass.osgeo.org/grass-devel/manuals/libpython/grass.script.html#grass.script.MaskManager) -and [RegionManager](https://grass.osgeo.org/grass-devel/manuals/libpython/grass.script.html#grass.script.RegionManager) +in GRASS 8.5—specifically, the [Tools API](https://grass.osgeo.org/grass-stable/manuals/libpython/grass.tools.html#) +and the [MaskManager](https://grass.osgeo.org/grass-stable/manuals/libpython/grass.script.html#grass.script.MaskManager) +and [RegionManager](https://grass.osgeo.org/grass-stable/manuals/libpython/grass.script.html#grass.script.RegionManager) context managers—which simplify region and mask handling and are especially useful in parallel workflows. @@ -137,7 +137,7 @@ gs.create_project(nlcd_project, filename=nlcd_filename) session = gj.init(nlcd_project) ``` -Link the NLCD raster with [r.external](https://grass.osgeo.org/grass-devel/manuals/r.external.html). This command creates a virtual raster without importing the full dataset, allowing us to work with just the small sections needed from the larger, nationwide NLCD file. +Link the NLCD raster with [r.external](https://grass.osgeo.org/grass-stable/manuals/r.external.html). This command creates a virtual raster without importing the full dataset, allowing us to work with just the small sections needed from the larger, nationwide NLCD file. ```{python} tools = Tools() @@ -220,7 +220,7 @@ tools.v_in_ogr( ``` Next, we want to extract the subwatersheds along the river. -If we simply overlap (with [v.select](https://grass.osgeo.org/grass-devel/manuals/v.select.html)) +If we simply overlap (with [v.select](https://grass.osgeo.org/grass-stable/manuals/v.select.html)) the river and the subwatersheds, we will miss some of them because the river data don't always overlap or touch the subwatersheds. @@ -240,7 +240,7 @@ basin_map.show() ![](SIMWE_images/basins.webp) -So instead we will [buffer](https://grass.osgeo.org/grass-devel/manuals/v.buffer.html) the river first: +So instead we will [buffer](https://grass.osgeo.org/grass-stable/manuals/v.buffer.html) the river first: ```{python} tools.v_buffer(input="river", output="river_buffer", distance=0.01) @@ -271,7 +271,7 @@ gs.create_project(nc_project, epsg="3358") session = gj.init(nc_project) ``` -We will reproject the river subwatersheds vector with [v.proj]((https://grass.osgeo.org/grass-devel/manuals/v.proj.html)): +We will reproject the river subwatersheds vector with [v.proj]((https://grass.osgeo.org/grass-stable/manuals/v.proj.html)): ```{python} tools.v_proj(input="river_basins", project="hydro") @@ -279,14 +279,15 @@ tools.v_proj(input="river_basins", project="hydro") ## Downloading NED elevation data -We will use GRASS addon [r.in.usgs](https://grass.osgeo.org/grass-devel/manuals/addons/r.in.usgs.html) to download and import NED layer using [USGS TNM Access API](https://apps.nationalmap.gov/tnmaccess/). +We will use GRASS addon [r.in.usgs](https://grass.osgeo.org/grass-stable/manuals/addons/r.in.usgs.html) to download and import NED layer using [USGS TNM Access API](https://apps.nationalmap.gov/tnmaccess/). ```{python} tools.g_extension(extension="r.in.usgs") ``` -First, we will set the computational region to match the river subwatersheds and then list available datasets -for that region (the output at the time of creating this tutorial, it may vary later on): +First, we will set the computational region to match the river subwatersheds +and then list the latest available datasets for that region +(the output at the time of creating this tutorial, it may vary later on): ```{python} tools.g_region(vector="river_basins") @@ -294,6 +295,7 @@ print( tools.r_in_usgs( product="ned", ned_dataset="ned13sec", + ned_release="current", flags="i", output_directory=os.getcwd(), ).text @@ -303,41 +305,33 @@ print( ```text USGS file(s) to download: ------------------------- -Total download size: 5.32 GB -Tile count: 17 +Total download size: 2.90 GB +Tile count: 6 USGS SRS: wgs84 USGS tile titles: -USGS 1/3 Arc Second n36w080 20240611 -USGS 1/3 Arc Second n36w081 20240611 -USGS 1/3 Arc Second n36w082 20220504 -USGS 1/3 Arc Second n36w082 20220512 -USGS 1/3 Arc Second n36w082 20240611 -USGS 1/3 Arc Second n37w080 20210305 -USGS 1/3 Arc Second n37w081 20210305 -USGS 1/3 Arc Second n37w081 20240611 -USGS 1/3 Arc Second n37w082 20210305 -USGS 1/3 Arc Second n37w082 20220512 -USGS 1/3 Arc Second n37w082 20240611 -USGS 13 arc-second n36w080 1 x 1 degree -USGS 13 arc-second n36w081 1 x 1 degree -USGS 13 arc-second n36w082 1 x 1 degree -USGS 13 arc-second n37w080 1 x 1 degree -USGS 13 arc-second n37w081 1 x 1 degree -USGS 13 arc-second n37w082 1 x 1 degree +USGS 1/3 Arc Second n36w080 20100929 +USGS 1/3 Arc Second n36w081 20100929 +USGS 1/3 Arc Second n36w082 20100929 +USGS 1/3 Arc Second n37w080 20100929 +USGS 1/3 Arc Second n37w081 20100929 +USGS 1/3 Arc Second n37w082 20100929 ------------------------- ``` -We will select the 2024 data and use the `title_filter` option to filter them. -We will download and import the datasets. +Now we will download and import the datasets. ```{python} tools.r_in_usgs( product="ned", ned_dataset="ned13sec", + ned_release="current", output_directory=os.getcwd(), - title_filter="20240611", output_name="ned", ) + +elevation_map = gj.Map() +elevation_map.d_rast(map="ned") +elevation_map.show() ``` Let's now compute the erosion/deposition for one of the subwatersheds. @@ -346,8 +340,8 @@ Let's now compute the erosion/deposition for one of the subwatersheds. We begin our analysis by selecting a single HUC12 subwatershed from the set of intersected basins. This subset will be used to test the erosion and deposition simulation workflow. For all outputs, we will use unique names with the subwatershed code as a prefix. That will help us with parallelization later on. -Use [v.db.select](https://grass.osgeo.org/grass-devel/manuals/v.db.select.html) to retrieve the list of HUC12 codes from the attribute table that has "areasqkm" and "huc12" attributes. -Extract the smallest HUC12 polygon using [v.extract](https://grass.osgeo.org/grass-devel/manuals/v.extract.html). +Use [v.db.select](https://grass.osgeo.org/grass-stable/manuals/v.db.select.html) to retrieve the list of HUC12 codes from the attribute table that has "areasqkm" and "huc12" attributes. +Extract the smallest HUC12 polygon using [v.extract](https://grass.osgeo.org/grass-stable/manuals/v.extract.html). ```{python} # Select for example the smallest huc12 @@ -361,60 +355,35 @@ tools.v_extract( ) ``` -Set the computational region with [g.region](https://grass.osgeo.org/grass-devel/manuals/g.region.html) to match the bounds of the selected subwatershed. - -```{python} -tools.g_region(vector=f"basin_{huc12}") -``` - -Display the NED data for that region: +Set the computational region with [g.region](https://grass.osgeo.org/grass-stable/manuals/g.region.html) to match the extent of the basin and align resolution with the elevation raster. ```{python} -basin_map = gj.Map(use_region=True) -basin_map.d_rast(map="ned") -basin_map.d_vect(map=f"basin_{huc12}", fill_color="none") -basin_map.show() +tools.g_region(raster="ned", vector=f"basin_{huc12}") ``` -![](SIMWE_images/basin_030401010402.webp) - -Set the region to match the extent of the basin and align resolution with the elevation raster. -Convert the selected vector to a raster using [v.to.rast](https://grass.osgeo.org/grass-devel/manuals/v.to.rast.html). +Convert the selected vector to a raster using [v.to.rast](https://grass.osgeo.org/grass-stable/manuals/v.to.rast.html). ```{python} -tools.g_region(raster="ned", vector=f"basin_{huc12}") tools.v_to_rast(input=f"basin_{huc12}", output=f"basin_{huc12}", use="val") ``` -Apply a raster mask with [MaskManager](https://grass.osgeo.org/grass-devel/manuals/libpython/grass.script.html#grass.script.MaskManager) to restrict all subsequent raster operations to this subwatershed. -MaskManager is new in GRASS version 8.5. Alternatively, you can use [r.mask](https://grass.osgeo.org/grass-devel/manuals/r.mask.html) to set a mask. +Apply a raster mask with [MaskManager](https://grass.osgeo.org/grass-stable/manuals/libpython/grass.script.html#grass.script.MaskManager) to restrict all subsequent raster operations to this subwatershed. +MaskManager is new in GRASS version 8.5. Alternatively, you can use [r.mask](https://grass.osgeo.org/grass-stable/manuals/r.mask.html) to set a mask. ```{python} mask = gs.MaskManager(mask_name=f"basin_{huc12}") mask.activate() - -basin_map = gj.Map(use_region=True) -basin_map.d_rast(map="ned") -basin_map.d_legend( - raster="ned", - flags="t", - at=[10, 15, 40, 95], - title="Elevation [m]", - fontsize=12, -) -basin_map.show() ``` -![](SIMWE_images/basin_030401010402_masked.webp) Reproject NLCD from a "nlcd" project to this project (see [NLCD legend](https://www.usgs.gov/media/images/annual-nlcd-land-cover-change-legend)): ```{python} tools.r_proj(project="nlcd", mapset="PERMANENT", input="nlcd", output=f"nlcd_{huc12}") -basin_map = gj.Map() -basin_map.d_rast(map=f"nlcd_{huc12}") -basin_map.show() +nlcd_map = gj.Map() +nlcd_map.d_rast(map=f"nlcd_{huc12}") +nlcd_map.show() ``` ![](SIMWE_images/basin_030401010402_nlcd.webp) @@ -427,16 +396,16 @@ Specifically, we will use [@kalyanapu2009] lookup table that is more suitable fo tools.g_extension(extension="r.manning") tools.r_manning(input=f"nlcd_{huc12}", output=f"mannings_{huc12}", landcover="nlcd", source="kalyanapu") -basin_map = gj.Map() -basin_map.d_rast(map=f"mannings_{huc12}") -basin_map.d_legend( +manning_map = gj.Map() +manning_map.d_rast(map=f"mannings_{huc12}") +manning_map.d_legend( raster=f"mannings_{huc12}", flags="t", at=[10, 15, 40, 95], title="Roughness", fontsize=12, ) -basin_map.show() +manning_map.show() ``` Then we will estimate rainfall excess and to do that we will first process @@ -454,15 +423,16 @@ For smaller areas, r.in.ssurgo can download the data directly using the ```{python} tools.g_extension(extension="r.in.ssurgo") -tools.r_in_ssurgo(ssurgo_path=f"", soils=f"soils_{huc12}", hydgrp=f"hydgrp_{huc12}", nprocs=1) +tools.r_in_ssurgo(ssurgo_path="gSSURGO_NC.zip", soils=f"soils_{huc12}", hydgrp=f"hydgrp_{huc12}", nprocs=1) soil_map = gj.Map() soil_map.d_rast(map=f"hydgrp_{huc12}") soil_map.d_legend( raster=f"hydgrp_{huc12}", - at=[10, 15, 40, 95], + at=[0, 30, 0, 10], title="HSG", fontsize=12, + flags="cn", ) soil_map.show() ``` @@ -494,7 +464,7 @@ We will model a 50-year storm event that lasts 3 hours, using data from tools.g_extension(extension="r.noaa.atlas14") duration = 3 depths = tools.r_noaa_atlas14(mode="point", statistic="depth", units="metric", format="json") -depth = [row["values"] for row in depth["table"]["rows"] if row["duration"] == f"{duration}-hr"]["50"] +depth = [row["values"] for row in depths["table"]["rows"] if row["duration"] == f"{duration}-hr"][0]["50"] print(depth) ``` @@ -525,7 +495,7 @@ runoff_map.show() ``` Run hydrologic and sediment simulations for the selected subwatershed. -First, simulate overland flow using [r.sim.water](https://grass.osgeo.org/grass-devel/manuals/r.sim.water.html) +First, simulate overland flow using [r.sim.water](https://grass.osgeo.org/grass-stable/manuals/r.sim.water.html) with inputs for topography, Manning’s coefficients, and rainfall intensity. Running the simulation may take a while. @@ -553,7 +523,7 @@ basin_map.show() ![](SIMWE_images/basin_030401010402_simwe.webp) -Then, define parameters for sediment transport and run [r.sim.sediment](https://grass.osgeo.org/grass-devel/manuals/r.sim.sediment.html) +Then, define parameters for sediment transport and run [r.sim.sediment](https://grass.osgeo.org/grass-stable/manuals/r.sim.sediment.html) to compute erosion and deposition patterns. We will trim the resulting raster's edges to avoid extreme values at the edge. The additional parameters for sediment erosion modeling are based on [WEPP](https://www.ars.usda.gov/midwest-area/west-lafayette-in/national-soil-erosion-research/docs/wepp/research/) model, here we use just a single-value estimate. @@ -590,9 +560,9 @@ basin_map.show() ![](SIMWE_images/basin_030401010402_erdep.webp) Calculate total erosion for the subwatershed. -Negative values from [r.sim.sediment](https://grass.osgeo.org/grass-devel/manuals/r.sim.sediment.html) +Negative values from [r.sim.sediment](https://grass.osgeo.org/grass-stable/manuals/r.sim.sediment.html) output are treated as erosion and converted to sediment mass. -Summary statistics are computed using [r.univar](https://grass.osgeo.org/grass-devel/manuals/r.univar.html). +Summary statistics are computed using [r.univar](https://grass.osgeo.org/grass-stable/manuals/r.univar.html). ```{python} # Erosion: extract negative values and convert to positive mass [kg/m^2] @@ -631,7 +601,7 @@ Each subwatershed needs to set different computational region and mask. However those setting are usually global for each mapset. So, to use different regions and masks for each parallel process, we will use the region and mask context managers. -* Computational region is handled using `RegionManager`, a [context manager for setting and managing computational region](https://grass.osgeo.org/grass-devel/manuals/libpython/grass.script.html#grass.script.RegionManager), +* Computational region is handled using `RegionManager`, a [context manager for setting and managing computational region](https://grass.osgeo.org/grass-stable/manuals/libpython/grass.script.html#grass.script.RegionManager), making it possible to have custom region for the current process. This feature is available only since GRASS 8.5. ```python @@ -640,7 +610,7 @@ making it possible to have custom region for the current process. This feature i tools.r_sim_water(...) ``` -* Masking is handled using `MaskManager`, a [context manager for setting and managing raster mask](https://grass.osgeo.org/grass-devel/manuals/libpython/grass.script.html#grass.script.MaskManager), +* Masking is handled using `MaskManager`, a [context manager for setting and managing raster mask](https://grass.osgeo.org/grass-stable/manuals/libpython/grass.script.html#grass.script.MaskManager), making it possible to have custom mask for the current process. This feature is available only since GRASS 8.5. ```python