Conveyor

BPTK API Documentation for the Conveyor class
Keywords

system dynamics, conveyor, agecount, bptk, bptk-py, python, business prototyping

Conveyor

Conveyor in a SD DSL model.

A conveyor is a stock that works like a conveyor belt: material put on at one end travels along it and comes off at the other end after the transit time - every unit stays exactly that long, where a stock with an outflow of stock / time lets some leave at once and others never. Leakage flows take a share of it on the way. The conveyor computes its outflow and its leakage itself, so those flows carry no equation of their own.

Create one through the model: model.conveyor("aged_20_to_40"). A conveyor is listed among the model’s stocks, and its value is the material on the belt.

turning_20 = model.flow("turning_20")
turning_20.equation = 100.0
turning_40 = model.flow("turning_40")      # no equation: the belt computes it
deaths = model.flow("deaths")              # no equation: the belt computes it

cohort = model.conveyor("aged_20_to_40")
cohort.transit_time = 20
cohort.initial_value = 1500.0
cohort.inflows = [turning_20]
cohort.outflows = [turning_40]
cohort.leaks = {deaths: 0.02}
cohort.exponential_leak = True

Conveyors run on the Python engine only for now; backend="rust" raises RustBackendError naming the conveyor.

Conveyor Constructor

Conveyor(model, name)

Create the conveyor.

Conveyor.equation

property equation

A conveyor has no equation: it reads None, and setting one raises ElementError. What enters comes from the inflows, what leaves from the belt itself.

Conveyor.exponential_leak

property exponential_leak

False, the default as in XMILE: linear leakage. The share is the part of each cohort that leaks out over its whole time on the belt, in equal amounts each timestep - 0.2 lets 20 % of what entered leak before the rest leaves. Several linear leaks are served in their order, and a later one may get less when the first ones take everything.

True: exponential leakage. The share is a rate per time unit taken from what is still on the belt - 0.02 takes 2 % of the remainder every year. Several exponential leaks add up.

Conveyor.fifo

property fifo

What a change of the transit time does. With a constant transit time both behave the same.

False, the default: material keeps the transit time it entered with. When the transit time shrinks, newer material can overtake older material and leave first.

True: first in, first out. The whole belt moves at the current transit time, so a shorter transit time speeds up everything on it - halving it doubles the outflow at once - and nothing overtakes.

Conveyor.inflows

property inflows

The flows that put material on the belt, as a list. They have to be flows: what enters a conveyor cannot be negative, so a biflow is refused.

Conveyor.initial_value

property initial_value

What lies on the belt at the start. A number, an element or an expression is the total, spread over the belt in the equilibrium its leakage implies - evenly, without leakage. A list gives one value per time unit, the first leaving first: [1, 2, 3] lets 1 leave in the first time unit, 2 in the second. A list with exactly as many values as the belt has slats fills the slats one by one; a shorter list repeats its last value, a longer one is cut.

Set on an arrayed conveyor, it is the start of every cell; a cell given its own afterwards keeps it.

Conveyor.leaks

property leaks

The leakage flows and the share each takes, as a dict: {deaths: mortality_rate}. The share is a number, an element or an expression, read anew every timestep. Like the outflow, a leakage flow carries no equation; the conveyor computes what it takes. The order of the dict is the priority when several linear leaks would take more than there is.

What the share means depends on exponential_leak.

Conveyor.non_negative

property non_negative

A conveyor is non-negative by construction - the outflow and the leakage take only what lies on the belt - so non_negative reads True, and setting it raises ElementError.

Conveyor.outflows

property outflows

The flow the belt empties into, as a list of one. The conveyor computes its value - what arrives at the front each timestep - so the flow must have no equation, and setting one while the conveyor drives it raises ElementError. Taken out of the list, it is an ordinary flow again.

Conveyor.transit_time

property transit_time

How long material stays on the belt, in time units: a number greater than zero, an element or an expression. It is read anew every timestep. The belt is divided into one slat per dt, so a transit time that is no whole number of timesteps is rounded to one - half away from zero - on a belt that is not FIFO.

AGECOUNT

sd.agecount(conveyor, minimum, maximum) is the material that has been on the belt for at least minimum and less than maximum time units. On an arrayed conveyor it is arrayed too.

aged_20_to_25 = model.converter("aged_20_to_25")
aged_20_to_25.equation = sd.agecount(cohort, 0, 5)

Inherited from Element

function_string, plot() and the arrayed-element API come from Element, where they are documented once for all element types.