landlab.core.component_utils¶
- iter_adaptive_time_steps(duration, *, calc_dt, max_steps=None, rtol=1e-12)[source]¶
Yield adaptive time steps that advance up to a requested duration.
Repeatedly call calc_dt to obtain the next stable time-step size, capping each step so that the total does not exceed duration. Note that iteration may stop within the tolerance specified by rtol.
- Parameters:
duration (float) – Total amount of time to advance.
calc_dt (callable) – Called with no arguments before each substep to obtain the current stable time-step size. A return value of
Nonesignals that iteration should be stopped before duration is reached. A return value of inf advances to duration.max_steps (int, optional) – Maximum number of substeps to yield before raising a
RuntimeError.rtol (float, optional) – Stop once the remaining time is no greater than
rtol * duration. Consequently, the yielded time steps may sum to slightly less than duration.
- Yields:
float – The next time-step size.
- Raises:
ValueError – If duration or rtol are out of range.
RuntimeError – If max_steps is exceeded, or if a returned step is either invalid or is too small, relative to the elapsed time, to make further progress.
- Return type:
Examples
>>> from landlab.core.component_utils import iter_adaptive_time_steps
>>> steps = iter([2.0, 2.0, 2.0, 1.0]) >>> list(iter_adaptive_time_steps(7.0, calc_dt=lambda: next(steps))) [2.0, 2.0, 2.0, 1.0]
Return
Nonefrom calc_dt to stop before duration is reached.>>> steps = iter([2.0, 2.0, None]) >>> list(iter_adaptive_time_steps(10.0, calc_dt=lambda: next(steps))) [2.0, 2.0]
>>> list(iter_adaptive_time_steps(10.0, calc_dt=lambda: 3.0)) [3.0, 3.0, 3.0, 1.0]
- iter_time_steps(duration, *, dt=None)[source]¶
Yield fixed-size time steps that evenly span a requested duration.
Split duration into equally-sized substeps, so that no substeps are longer that dt.
- Parameters:
- Yields:
float – The next time-step size.
- Raises:
ValueError – If duration is negative, or if dt is not finite and positive.
- Return type:
Examples
>>> from landlab.core.component_utils import iter_time_steps
>>> list(iter_time_steps(10.0, dt=2.5)) [2.5, 2.5, 2.5, 2.5]
A duration that doesn’t divide evenly is split into equal substeps, each no longer than dt, rather than leaving a short final step.
>>> list(iter_time_steps(10.0, dt=3.0)) [2.5, 2.5, 2.5, 2.5]
If dt isn’t given, duration is used as a single time step.
>>> list(iter_time_steps(5.0)) [5.0]
- resolve_field(field, *, grid, at)[source]¶
Resolve a field name or array to an array of values.
If field is a field name, look up and return its current values on grid. If field is 0-dimensional, broadcast it to the number of at elements of grid. Otherwise, return field unchanged. Call this each time you need the values of a field previously validated with
validate_field, so that a field name always resolves to that field’s current values, even if they have changed since field was validated.- Parameters:
field (str or array_like) – A field name, or an array of values, as returned by
validate_field.grid (GraphFields) – Grid to look up field on, or broadcast it against, as needed.
at (str) – Name of the group (e.g. “node”, “link”) that field is defined on.
- Returns:
The current values of field. If field is 0-dimensional, this is a read-only, broadcast view rather than a newly allocated array. If field is already an numpy array, it is returned unchanged (not copied). Otherwise, a new array is created.
- Return type:
ndarray
- Raises:
landlab.field.errors.GroupError – If at is not a group on grid.
landlab.field.errors.FieldError – If field is a field name that does not exist in grid at at.
Examples
>>> from landlab.core.component_utils import resolve_field >>> from landlab import RasterModelGrid
>>> grid = RasterModelGrid((3, 4)) >>> foo = grid.add_ones("foo", at="node")
>>> resolve_field("foo", grid=grid, at="node") is foo True >>> resolve_field(range(12), grid=grid, at="node") array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]) >>> resolve_field(42, grid=grid, at="node") array([42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42])
- validate_field(value, *, grid=None, at=None)[source]¶
Validate a field name or array-like value.
Check that value is either the name of an existing field, or an array-like object that could represent values located on a grid. Unlike
resolve_field, a field name is not resolved to its values, so the returned value can be stored and later passed toresolve_fieldto pick up the field’s current values at the time it’s needed. value is converted to a numpy array, but, unlikeresolve_field, it is not broadcast.- Parameters:
value (str or array_like) – A field name, or an array of values.
grid (GraphFields, optional) – Grid used to validate value against. If not given, value is not checked against a grid (and, if a field name, is returned unchecked).
at (str, optional) – Name of the group (e.g. “node”, “link”) that value is defined on. Must be given if, and only if, grid is given.
- Returns:
value unchanged, if it is a field name, otherwise value as an array (not copied, if value is already an ndarray).
- Return type:
str or ndarray
- Raises:
ValueError – If only one of grid and at is given, or if value is array-like (and not a scalar) but its first dimension does not match the number of at elements of grid.
landlab.field.errors.FieldError – If value is a field name that does not exist in grid at at.
Examples
>>> from landlab.core.component_utils import validate_field >>> from landlab import RasterModelGrid
>>> grid = RasterModelGrid((3, 4)) >>> _ = grid.add_ones("foo", at="node")
>>> validate_field("foo", grid=grid, at="node") 'foo' >>> validate_field(range(12), grid=grid, at="node") array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]) >>> validate_field(42, grid=grid, at="node") array(42)