Concentration Tracker#
ConcentrationTrackerForDiffusion: Track mass concentration of sediment properties based on flux from DepthDependentDiffuser or DepthDependentTaylorDiffuser#
Created on Wed May 31 11:41:20 2023
@author: LaurentRoberge
- class ConcentrationTrackerForDiffusion(*args, **kwds)[source]#
Bases:
Component
Track the concentration of any user-defined property.
This component tracks the concentration of any user-defined property of sediment using a mass balance approach in which the concentration \(C\) is calculated as:
\[∂CH / ∂t = [-(∂q_x C_x) / ∂x - (∂q_y C_y) / ∂y] + C_br * H_brw\]where \(H\) is sediment depth, \(q_x\) and \(q_y\) are sediment fluxed in the x and y directions, \(C_br\) is concentration in parent bedrock, and \(H_brw\) is the height of bedrock weathered into soil.
Note
This component requires a soil flux field calculated by a hillslope diffusion component and must be run after every diffusion step. Currently, this component WILL ONLY WORK IF COUPLED with the
DepthDependentDiffuser
or theDepthDependentTaylorDiffuser
(without the dynamic timestep option).In-situ production and decay of the material property are handled by the ConcentrationTrackerProductionDecay component.
Examples
A 1-D hillslope:
>>> import numpy as np >>> from landlab import NodeStatus, RasterModelGrid >>> from landlab.components import DepthDependentDiffuser >>> from landlab.components import ConcentrationTrackerForDiffusion
>>> mg = RasterModelGrid((3, 5), xy_spacing=2.0)
>>> mg.set_status_at_node_on_edges( ... right=NodeStatus.CLOSED, ... top=NodeStatus.CLOSED, ... left=NodeStatus.CLOSED, ... bottom=NodeStatus.CLOSED, ... ) >>> mg.status_at_node[5] = NodeStatus.FIXED_VALUE >>> mg.status_at_node.reshape(mg.shape) array([[4, 4, 4, 4, 4], [1, 0, 0, 0, 4], [4, 4, 4, 4, 4]], dtype=uint8)
>>> mg.at_node["sediment_property__concentration"] = [ ... [0.0, 0.0, 0.0, 0.0, 0.0], ... [0.0, 0.0, 0.0, 1.0, 0.0], ... [0.0, 0.0, 0.0, 0.0, 0.0], ... ] >>> mg.at_node["soil__depth"] = mg.node_x.copy() >>> mg.at_node["bedrock__elevation"] = mg.node_x.copy() >>> mg.at_node["topographic__elevation"] = ( ... mg.at_node["soil__depth"] + mg.at_node["bedrock__elevation"] ... ) >>> _ = mg.add_zeros("soil_production__rate", at="node")
>>> ddd = DepthDependentDiffuser(mg) >>> ct = ConcentrationTrackerForDiffusion(mg) >>> ddd.run_one_step(1.0) >>> ct.run_one_step(1.0)
>>> mg.at_node["topographic__elevation"].reshape(mg.shape) array([[ 0. , 4. , 8. , 12. , 16. ], [ 0. , 4.11701964, 8.01583689, 11.00247875, 16. ], [ 0. , 4. , 8. , 12. , 16. ]]) >>> mg.at_node["sediment_property__concentration"].reshape(mg.shape) array([[ 0. , 0. , 0. , 0. , 0. ], [ 0. , 0. , 0.24839685, 1. , 0. ], [ 0. , 0. , 0. , 0. , 0. ]])
Now, a 2-D pyramid-shaped hillslope.
>>> mg = RasterModelGrid((5, 5), xy_spacing=2.0)
>>> c = mg.add_zeros("sediment_property__concentration", at="node") >>> c[12] = 1.0 >>> h = mg.add_full("soil__depth", 2.0, at="node") >>> z_br = mg.add_field( ... "bedrock__elevation", ... 8.0 - abs(4.0 - mg.node_x) - abs(4.0 - mg.node_y), ... at="node", ... ) >>> z = mg.add_field("topographic__elevation", z_br + h, at="node") >>> _ = mg.add_zeros("soil_production__rate", at="node")
>>> ddd = DepthDependentDiffuser(mg) >>> ct = ConcentrationTrackerForDiffusion(mg) >>> ddd.run_one_step(1.0) >>> ct.run_one_step(1.0)
>>> mg.at_node["topographic__elevation"][mg.core_nodes].reshape((3, 3)) array([[ 6. , 7.13533528, 6. ], [ 7.13533528, 8.27067057, 7.13533528], [ 6. , 7.13533528, 6. ]]) >>> mg.at_node["sediment_property__concentration"][mg.core_nodes].reshape((3, 3)) array([[ 0. , 0.38079708, 0. ], [ 0.38079708, 1. , 0.38079708], [ 0. , 0.38079708, 0. ]])
And running one more step.
>>> ddd.run_one_step(1.0) >>> ct.run_one_step(1.0)
>>> mg.at_node["topographic__elevation"][mg.core_nodes].reshape((3, 3)) array([[ 5.52060315, 6.62473963, 5.52060315], [ 6.62473963, 8.00144598, 6.62473963], [ 5.52060315, 6.62473963, 5.52060315]]) >>> mg.at_node["sediment_property__concentration"][mg.core_nodes].reshape((3, 3)) array([[ 0.09648071, 0.44750673, 0.09648071], [ 0.44750673, 1. , 0.44750673], [ 0.09648071, 0.44750673, 0.09648071]])
Finally, the same 2D hillslope now using the DepthDependentTaylorDiffuser. Note that the timestep must be smaller than 1 to maintain stability in the diffusion calculation. Typically, one could use the dynamic timestepping option. However, here it will provide incorrect soil flux values to the ConcentrationTrackerForDiffusion, which cannot do sub-timestep calculations. Use the if_unstable=”warn” flag when instantiating the Taylor diffuser and pick a timestep that is stable.
>>> from landlab.components import DepthDependentTaylorDiffuser >>> mg = RasterModelGrid((5, 5), xy_spacing=2.0)
>>> c = mg.add_zeros("sediment_property__concentration", at="node") >>> c[12] = 1.0 >>> h = mg.add_full("soil__depth", 2.0, at="node") >>> z_br = mg.add_field( ... "bedrock__elevation", ... 8.0 - abs(4.0 - mg.node_x) - abs(4.0 - mg.node_y), ... at="node", ... ) >>> z = mg.add_field("topographic__elevation", z_br + h, at="node") >>> _ = mg.add_zeros("soil_production__rate", at="node")
>>> ddtd = DepthDependentTaylorDiffuser(mg, if_unstable="warn") >>> ct = ConcentrationTrackerForDiffusion(mg) >>> ddtd.run_one_step(0.4) >>> ct.run_one_step(0.4)
>>> mg.at_node["topographic__elevation"][mg.core_nodes].reshape((3, 3)) array([[ 6. , 7.30826823, 6. ], [ 7.30826823, 8.61653645, 7.30826823], [ 6. , 7.30826823, 6. ]]) >>> mg.at_node["sediment_property__concentration"][mg.core_nodes].reshape((3, 3)) array([[ 0. , 0.26436925, 0. ], [ 0.26436925, 1. , 0.26436925], [ 0. , 0.26436925, 0. ]])
References
Required Software Citation(s) Specific to this Component
CITATION
- Parameters:
grid (ModelGrid) – Landlab ModelGrid object
concentration_initial (float, array, or str, optional) – Initial concentration in soil/sediment as either a scalar, array, or the name of an existing node field, -/m^3.
concentration_in_bedrock (float, array, or str, optional) – Concentration in bedrock as either a scalar, array, or the name of an existing node field, -/m^3.
concentration_from_weathering (float or array, optional) – Concentration generated during the weathering process, -/m^3. Defaults to
None
, which causes all weathered bedrock to retain its original parent material concentration (concentration_in_bedrock
) as it weathers to soil. Use this parameter to differentiate between the concentration in weathered material compared to its parent bedrock.
- __init__(grid, concentration_initial=0, concentration_in_bedrock=0, concentration_from_weathering=None)[source]#
- Parameters:
grid (ModelGrid) – Landlab ModelGrid object
concentration_initial (float, array, or str, optional) – Initial concentration in soil/sediment as either a scalar, array, or the name of an existing node field, -/m^3.
concentration_in_bedrock (float, array, or str, optional) – Concentration in bedrock as either a scalar, array, or the name of an existing node field, -/m^3.
concentration_from_weathering (float or array, optional) – Concentration generated during the weathering process, -/m^3. Defaults to
None
, which causes all weathered bedrock to retain its original parent material concentration (concentration_in_bedrock
) as it weathers to soil. Use this parameter to differentiate between the concentration in weathered material compared to its parent bedrock.
- calc_concentration(dt)[source]#
Calculate change in concentration for a time period ‘dt’.
- Parameters:
dt (float (time)) – The imposed timestep.
- property conc_br#
Concentration in bedrock (kg/m^3).
- property conc_init#
Initial concentration in soil/sediment (kg/m^3).
- property conc_w#
Concentration from the weathering process (kg/m^3).