r.solute.transport(1grass)
r.solute.transport π§β¨
okay bestie, this is the GRASS User's Manual page for r.solute.transport from the 1grass collection, and honestly? it's giving serious hydrogeology main character energy π₯
KEYWORDS: raster, hydrology, solute transport π
β¨ SYNOPSIS β¨
r.solute.transport
r.solute.transport --help
r.solute.transport [-fc] c=name phead=name hc_x=name hc_y=name
status=name diff_x=name diff_y=name [q=name] [cin=name] cs=name
rd=name nf=name top=name bottom=name output=name [vx=name] [vy=name]
dtime=float [maxit=integer] [error=float] [solver=name]
[relax=float] [al=float] [at=float] [loops=float] [stab=string]
[--overwrite] [--help] [--verbose] [--quiet] [--ui]
π Flags
-fβ use a full filled quadratic linear equation system. the default is a sparse linear equation system, jsyk π-cβ use the Courant-Friedrichs-Lewy criteria for time step calculation β±οΈ--overwriteβ let output files overwrite existing files, no hesitation, no fear π«Ά--helpβ print usage summary--verboseβ verbose module output (she's chatty π¬)--quietβ quiet module output (she's mysterious π€«)--uiβ force launching GUI dialog
πΈ Parameters
c=name[required] β the initial concentration in[kg/m^3]phead=name[required] β the piezometric head in[m]hc_x=name[required] β the x-part of the hydraulic conductivity tensor in[m/s]hc_y=name[required] β the y-part of the hydraulic conductivity tensor in[m/s]status=name[required] β the status for each cell,= 0β inactive cell,1β active cell,2β dirichlet- and3β transfer boundary conditiondiff_x=name[required] β the x-part of the diffusion tensor in[m^2/s]diff_y=name[required] β the y-part of the diffusion tensor in[m^2/s]q=nameβ groundwater sources and sinks in[m^3/s]cin=nameβ concentration sources and sinks bounded to a water source or sink in[kg/s]cs=name[required] β concentration of inner sources and inner sinks in[kg/s](i.e. a chemical reaction) π§ͺrd=name[required] β retardation factor[-]nf=name[required] β effective porosity[-]top=name[required] β top surface of the aquifer in[m]bottom=name[required] β bottom surface of the aquifer in[m]output=name[required] β the resulting concentration of the numerical solute transport calculation will be written to this map.[kg/m^3]vx=nameβ calculate and store the groundwater filter velocity vector part in x direction[m/s]vy=nameβ calculate and store the groundwater filter velocity vector part in y direction[m/s]dtime=float[required] β the calculation time in seconds Default:86400maxit=integerβ maximum number of iteration used to solve the linear equation system Default:10000error=floatβ error break criteria for iterative solver Default:0.000001solver=nameβ the type of solver which should solve the linear equation system Options:gauss,lu,jacobi,sor,bicgstabDefault:bicgstabrelax=floatβ the relaxation parameter used by thejacobiandsorsolver for speedup or stabilizing Default:1al=floatβ the longditudinal dispersivity length.[m]Default:0.0at=floatβ the transversal dispersivity length.[m]Default:0.0loops=floatβ use this number of time loops if the CFL flag is off. The timestep will becomedt/loops. Default:1stab=stringβ set the flow stabilizing scheme (full or exponential upwinding). Options:full,expDefault:full
π DESCRIPTION π
So this numerical program calculates numerical implicit transient and steady state solute transport in porous media in the saturated zone of an aquifer. The computation is based on raster maps and the current region settings, periodt. All initial- and boundary-conditions must be provided as raster maps. And the unit of the coordinate reference system must be meters β no vibe-checking in other units, bestie π
This module is sensitive to mask settings. All cells which are outside the mask are ignored and handled as no flow boundaries. π«
This module calculates the concentration of the solution and optional the velocity field, based on the hydraulic conductivity, the effective porosity and the initial piecometric heads. The vector components can be visualized with paraview if they are exported with r.out.vtk. Use r.gwflow to compute the piezometric heights of the aquifer. The piezometric heights and the hydraulic conductivity are used to compute the flow direction and the mean velocity of the groundwater. This is the base of the solute transport computation. π
The solute transport will always be calculated transient. For stady state computation set the timestep to a large number (billions of seconds) β like, billions, we're not joking around here π
To reduce the numerical dispersion, which is a consequence of the convection term and the finite volume discretization, you can use small time steps and choose between full and exponential upwinding. slay β¨
π¦ NOTES π¦
The solute transport calculation is based on a diffusion/convection partial differential equation and a numerical implicit finite volume discretization. Specific for this kind of differential equation is the combination of a diffusion/dispersion term and a convection term. The discretization results in an unsymmetric linear equation system in form of Ax = b, which must be solved. The solute transport partial differential equation is of the following form:
(dc/dt)*R = div ( D grad c - uc) + cs -q/nf(c - c_in)
cβ the concentration[kg/m^3]uβ vector of mean groundwater flow velocitydtβ the time step for transient calculation in seconds[s]Rβ the linear retardation coefficient[-]Dβ the diffusion and dispersion tensor[m^2/s]csβ inner concentration sources/sinks[kg/m^3]c_inβ the solute concentration of influent water[kg/m^3]qβ inner well sources/sinks[m^3/s]nfβ the effective porosity[-]
Three different boundary conditions are implemented, the Dirichlet, Transmission and Neumann conditions. The calculation and boundary status of single cells can be set with the status map. The following states are supported:
0 == inactiveβ the cell with status0will not be calculated, active cells will have a no flow boundary to an inactive cell1 == activeβ this cell is used for sloute transport calculation, inner sources can be defined for those cells2 == Dirichletβ cells of this type will have a fixed concentration value which do not change over time3 == Transmissionβ cells of this type should be placed on out-flow boundaries to assure the flow of the solute stream out
β οΈ Note that all required raster maps are read into main memory. Additionally the linear equation system will be allocated, so the memory consumption of this module rapidely grow with the size of the input maps. yikes π
The resulting linear equation system Ax = b can be solved with several solvers. Several iterative solvers with unsymmetric sparse and quadratic matrices support are implemented. The jacobi method, the Gauss-Seidel method and the biconjugate gradients-stabilized (bicgstab) method. Additionally a direct Gauss solver and LU solver are available.
π¨ Those direct solvers only work with quadratic matrices, so be careful using them with large maps (maps of size 10.000 cells will need more than one gigabyte of ram). Always prefer a sparse matrix solver. like, always. i'm begging π₯Ί
π EXAMPLE π
Use this small python script to create a working groundwater flow / solute transport area and data. Make sure you are not in a lat/lon projection. β οΈ
#!/usr/bin/env python3
# This is an example script how groundwater flow and solute transport are
# computed within GRASS
import sys
import os
import grass.script as gs
# Overwrite existing maps
gs.run_command("g.gisenv", set="OVERWRITE=1")
gs.message(_("Set the region"))
# The area is 200m x 100m with a cell size of 1m x 1m
gs.run_command("g.region", res=1, res3=1, t=10, b=0, n=100, s=0, w=0, e=200)
gs.run_command("r.mapcalc", expression="phead = if(col() == 1 , 50, 40)")
gs.run_command("r.mapcalc", expression="phead = if(col() ==200 , 45 + row()/40, phead)")
gs.run_command("r.mapcalc", expression="status = if(col() == 1 || col() == 200 , 2, 1)")
gs.run_command("r.mapcalc", expression="well = if((row() == 50 && col() == 175) || (row() == 10 && col() == 135) , -0.001, 0)")
gs.run_command("r.mapcalc", expression="hydcond = 0.00005")
gs.run_command("r.mapcalc", expression="recharge = 0")
gs.run_command("r.mapcalc", expression="top_conf = 20")
gs.run_command("r.mapcalc", expression="bottom = 0")
gs.run_command("r.mapcalc", expression="poros = 0.17")
gs.run_command("r.mapcalc", expression="syield = 0.0001")
gs.run_command("r.mapcalc", expression="null = 0.0")
gs.message(_("Compute a steady state groundwater flow"))
gs.run_command("r.gwflow", solver="cg", top="top_conf", bottom="bottom", phead="phead",\
status="status", hc_x="hydcond", hc_y="hydcond", q="well", s="syield",\
recharge="recharge", output="gwresult_conf", dt=8640000000000, type="confined")
gs.message(_("generate the transport data"))
gs.run_command("r.mapcalc", expression="c = if(col() == 15 && row() == 75 , 500.0, 0.0)")
gs.run_command("r.mapcalc", expression="cs = if(col() == 15 && row() == 75 , 0.0, 0.0)")
gs.run_command("r.mapcalc", expression="tstatus = if(col() == 1 || col() == 200 , 3, 1)")
gs.run_command("r.mapcalc", expression="diff = 0.0000001")
gs.run_command("r.mapcalc", expression="R = 1.0")
# Compute the initial state
gs.run_command("r.solute.transport", solver="bicgstab", top="top_conf",\
bottom="bottom", phead="gwresult_conf", status="tstatus", hc_x="hydcond", hc_y="hydcond",\
rd="R", cs="cs", q="well", nf="poros", output="stresult_conf_0", dt=3600, diff_x="diff",\
diff_y="diff", c="c", al=0.1, at=0.01)
# Compute the solute transport for 300 days in 10 day steps
for dt in range(30):
gs.run_command("r.solute.transport", solver="bicgstab", top="top_conf",\
bottom="bottom", phead="gwresult_conf", status="tstatus", hc_x="hydcond", hc_y="hydcond",\
rd="R", cs="cs", q="well", nf="poros", output="stresult_conf_" + str(dt + 1), dt=864000, diff_x="diff",\
diff_y="diff", c="stresult_conf_" + str(dt), al=0.1, at=0.01)
π SEE ALSO π
r.gwflowr3.gwflowr.out.vtk
π AUTHOR π
SΓΆren Gebbert
This work is based on the Diploma Thesis of SΓΆren Gebbert available here at Technical University Berlin in Germany. π
π SOURCE CODE π
okay bestie, you wanna see the actual source? say less. π
- Available at:
r.solute.transport source code (history)β yep, the whole glow-up is public, go peek π - Latest change:
Wednesday May 21 09:11:03 2025in commit:
45102055f4f205276ad5f85b5775b70c6583a26f
that's the exact commit, bestie β don't be out here paraphrasing a hash, that's a crime fr fr π«
and then the index tour, because the docs are literally built different:
- Main index | Raster index | Topics index | Keywords index | Graphical index | Full index
go browse, you'll find your fave πΈ
Β© 2003-2026 GRASS Development Team β and it lives in the GRASS 8.5.0 Reference Manual π
okay so that's the whole vibe-check, bestie β every flag, every default, every warning, kept 100% intact, just with way more sparkle β¨ and no cap. now go run it and be the main character of your own watershed πππ¦
GRASS 8.5.0 Β· r.solute.transport(1grass) β that's the signature, and honestly? it ate. π sign-off done, mwah π
π¦ where this page comes from
- alpine 3.24: grass-gis-doc 8.5.0-r1 Β· GPL-2.0-or-later
- ubuntu stonking: grass-doc 8.5.0-1ubuntu1 Β· GPL-2.0-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms