From 37912920384f460015b9839b00e7a4ce3078cf30 Mon Sep 17 00:00:00 2001 From: Corey White Date: Mon, 28 Sep 2026 23:42:54 -0400 Subject: [PATCH 1/3] r.sim: Add -p flag with format=json run summary and normalize history Add a -p flag and a format=plain|json option to r.sim.water and r.sim.sediment which print a summary of the run (walker counts, time step, iteration counts, mean velocity, mean Manning's n, mean source rate, early stop, and the names and simulated times of the written maps) to standard output. Without -p nothing is printed to standard output. Replace the three inconsistent history blocks in simlib with one helper whose labels are the same keys as the printed summary, and record the same values for every written map. Free the time series map names which were leaked before, and compute the simulated time of the final maps from the number of completed iterations rather than the loop counter. Convert stray printf calls in the walker loop to G_debug so standard output stays clean. Add pytest tests on the shared raster fixture, and document the keys and units in both manuals. Addresses #7923. Seeds are left to #7884. AI assisted. --- raster/r.sim/CMakeLists.txt | 17 +- raster/r.sim/r.sim.sediment/Makefile | 2 +- raster/r.sim/r.sim.sediment/main.c | 21 +- .../r.sim/r.sim.sediment/r.sim.sediment.html | 73 +++ raster/r.sim/r.sim.sediment/r.sim.sediment.md | 70 +++ .../tests/r_sim_sediment_summary_test.py | 173 ++++++ raster/r.sim/r.sim.water/Makefile | 2 +- raster/r.sim/r.sim.water/main.c | 21 +- raster/r.sim/r.sim.water/r.sim.water.html | 107 ++++ raster/r.sim/r.sim.water/r.sim.water.md | 103 ++++ .../tests/r_sim_water_summary_test.py | 215 ++++++++ raster/r.sim/simlib/Makefile | 2 +- raster/r.sim/simlib/hydro.c | 29 +- raster/r.sim/simlib/input.c | 8 +- raster/r.sim/simlib/output.c | 509 ++++++------------ raster/r.sim/simlib/simlib.h | 47 +- raster/r.sim/simlib/summary.c | 236 ++++++++ 17 files changed, 1256 insertions(+), 379 deletions(-) create mode 100644 raster/r.sim/r.sim.sediment/tests/r_sim_sediment_summary_test.py create mode 100644 raster/r.sim/r.sim.water/tests/r_sim_water_summary_test.py create mode 100644 raster/r.sim/simlib/summary.c diff --git a/raster/r.sim/CMakeLists.txt b/raster/r.sim/CMakeLists.txt index 13e0fdf3211..ac468cff5f2 100644 --- a/raster/r.sim/CMakeLists.txt +++ b/raster/r.sim/CMakeLists.txt @@ -6,6 +6,7 @@ build_library_in_subdir( grass_datetime grass_gis grass_gmath + grass_parson grass_raster grass_vector OPTIONAL_DEPENDS OpenMP::OpenMP_C @@ -14,14 +15,26 @@ build_library_in_subdir( build_program_in_subdir( r.sim.water - DEPENDS grass_gis grass_gmath grass_raster grass_sim grass_vector + DEPENDS + grass_gis + grass_gmath + grass_parson + grass_raster + grass_sim + grass_vector OPTIONAL_DEPENDS OpenMP::OpenMP_C INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}/../simlib" ) build_program_in_subdir( r.sim.sediment - DEPENDS grass_gis grass_gmath grass_raster grass_sim grass_vector + DEPENDS + grass_gis + grass_gmath + grass_parson + grass_raster + grass_sim + grass_vector OPTIONAL_DEPENDS OpenMP::OpenMP_C INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}/../simlib" ) diff --git a/raster/r.sim/r.sim.sediment/Makefile b/raster/r.sim/r.sim.sediment/Makefile index 13ca19d09dc..d66d55f57d5 100644 --- a/raster/r.sim/r.sim.sediment/Makefile +++ b/raster/r.sim/r.sim.sediment/Makefile @@ -4,7 +4,7 @@ PGM=r.sim.sediment EXTRA_CLEAN_DIRS=doxygenhtml -LIBES = $(SIMLIB) $(GMATHLIB) $(GISLIB) $(RASTERLIB) $(OPENMP_LIBPATH) $(OPENMP_LIB) +LIBES = $(SIMLIB) $(GMATHLIB) $(GISLIB) $(RASTERLIB) $(PARSONLIB) $(OPENMP_LIBPATH) $(OPENMP_LIB) DEPENDENCIES = $(SIMDEP) $(GMATHDEP) $(GISDEP) $(RASTERDEP) EXTRA_INC = $(OPENMP_INCPATH) $(VECT_INC) EXTRA_CFLAGS = -I ../simlib $(VECT_CFLAGS) $(OPENMP_CFLAGS) diff --git a/raster/r.sim/r.sim.sediment/main.c b/raster/r.sim/r.sim.sediment/main.c index b7987e5f3f3..8c6630d5181 100644 --- a/raster/r.sim/r.sim.sediment/main.c +++ b/raster/r.sim/r.sim.sediment/main.c @@ -59,6 +59,7 @@ /********************************/ #include #include +#include #include #include @@ -303,10 +304,24 @@ int main(int argc, char *argv[]) _("Number of threads which will be used for parallel computation."); parm.threads->guisection = _("Parameters"); + flag.print = G_define_flag(); + flag.print->key = 'p'; + flag.print->description = _("Print run summary to standard output"); + flag.print->guisection = _("Print"); + + parm.format = G_define_standard_option(G_OPT_F_FORMAT); + parm.format->guisection = _("Print"); + G_option_collective(parm.dxin, parm.dyin, NULL); if (G_parser(argc, argv)) exit(EXIT_FAILURE); + SummaryFormat summary_format = SUMMARY_NONE; + if (flag.print->answer) + summary_format = strcmp(parm.format->answer, "json") == 0 + ? SUMMARY_JSON + : SUMMARY_PLAIN; + if (flag.generateSeed->answer) { seed_value = G_srand48_auto(); G_verbose_message(_("Generated random seed (-s): %ld"), seed_value); @@ -334,6 +349,7 @@ int main(int argc, char *argv[]) Inputs inputs = {0}; Outputs outputs = {0}; Grids grids = {0}; + Summary summary = {0}; geometry.conv = G_database_units_to_meters_factor(); @@ -385,6 +401,7 @@ int main(int argc, char *argv[]) threads = 1; #endif G_message(_("Number of threads: %d"), threads); + summary.threads = threads; /* sscanf(parm.nwalk->answer, "%d", &wp.maxwa); */ sscanf(parm.niter->answer, "%d", &settings.timesec); @@ -435,7 +452,9 @@ int main(int argc, char *argv[]) init_grids_sediment(&setup, &geometry, &outputs, &grids); /* treba dat output pre topoerdep */ main_loop(&setup, &geometry, &settings, &sim, &points, &inputs, &outputs, - &grids); + &grids, &summary); + print_summary(summary_format, &setup, &settings, &sim, &inputs, &summary); + free_summary(&summary); free_walkers(&sim, outputs.outwalk); /* Exit with Success */ diff --git a/raster/r.sim/r.sim.sediment/r.sim.sediment.html b/raster/r.sim/r.sim.sediment/r.sim.sediment.html index e3caec941d5..9416e63a33e 100644 --- a/raster/r.sim/r.sim.sediment/r.sim.sediment.html +++ b/raster/r.sim/r.sim.sediment/r.sim.sediment.html @@ -45,6 +45,79 @@

DESCRIPTION

Increasing the number of threads with nprocs does not really speed up the simulation. +

NOTES

+ +

Run summary

+ +With the -p flag, a summary of the run is printed to standard output +after the maps are written. The format option selects plain text +(one key: value pair per line) or JSON. Without -p, nothing is +printed to standard output regardless of format. The values are also +stored in the history of the sediment_flux raster map under the same +keys (see r.info). + +

+The keys are the same as for r.sim.water with these +differences: + + + + + + + + + +
KeyMeaningUnit
time_step_sedimentTime step derived from the sediment transport parameters; time_step is the smaller of this and the water time steps
velocity_maxMaximum flow velocity over the defined cellsm/s
sigma_maxMaximum first order reaction coefficient (detachment to transport capacity ratio) over the defined cells1/m
mean_source_rateMean sediment source (detachment) ratekg/m^2s
mean_infiltrationNot reported
outputsA single entry with the simulated_time (s), timestamp and walkers_active at the time of writing, and the names of the transport_capacity, tlimit_erosion_deposition, sediment_concentration, sediment_flux, erosion_deposition and walkers maps, or null for maps which were not requested
+ +

+Summary of a run in JSON: + +

+r.sim.sediment elevation=elevation water_depth=water_depth detachment_coeff=detachment \
+    transport_coeff=transport shear_stress=shear_stress man_value=1 \
+    sediment_flux=flux erosion_deposition=erdep transport_capacity=tc \
+    duration=1 random_seed=1 -p format=json
+
+ +
+{
+    "walkers_requested": 60,
+    "walkers_generated": 78,
+    "walkers_active": 43,
+    "duration": 60,
+    "simulated_time": 54,
+    "time_step": 1.3722835778402895,
+    "time_step_sediment": 70.517234241515013,
+    "time_coefficient": 4,
+    "iterations_planned": 10,
+    "iterations_completed": 10,
+    "iterations_per_output": 21,
+    "stopped_early": false,
+    "elevation_min": 1,
+    "elevation_max": 5,
+    "mean_velocity": 0.1821780891624834,
+    "velocity_max": 0.21544346900318839,
+    "sigma_max": 0.052657639041437901,
+    "mean_mannings_n": 1,
+    "mean_source_rate": 0.56025284041612944,
+    "threads": 1,
+    "outputs": [
+        {
+            "simulated_time": 54,
+            "timestamp": "1 minutes",
+            "walkers_active": 43,
+            "transport_capacity": "tc",
+            "tlimit_erosion_deposition": null,
+            "sediment_concentration": null,
+            "sediment_flux": "flux",
+            "erosion_deposition": "erdep",
+            "walkers": null
+        }
+    ]
+}
+
+