Processes
Processes: stocks of material in engineered flows.
GrainStoreElement(label, visual=None, *, stock=1000.0, on_order=10000.0, desired_stock=6000.0, release_fraction=0.025, receiving_delay=10.0, adjustment_delay=5.0)
Bases: Element
Retail grain store, whose stock is restocked from grain on order through a receiving delay.
Grain on order arrives in the stock at the receiving rate on_order / receiving_delay, and the stock releases the
fraction release_fraction of itself per unit time to the consumers. The procurement rate
(desired_stock - stock) / adjustment_delay adds grain on order, and it is negative when the stock exceeds the
desired stock, which cancels orders.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the store. |
required |
visual
|
VisualSpec | None
|
How the store is drawn, or |
None
|
stock
|
Annotated[float, StateSpec(quantity=grain)]
|
The initial grain stock. |
1000.0
|
on_order
|
Annotated[float, StateSpec(quantity=grain)]
|
The initial grain on order. |
10000.0
|
desired_stock
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The desired grain stock. |
6000.0
|
release_fraction
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The fraction of the stock released per unit time. |
0.025
|
receiving_delay
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The average time for grain on order to arrive. |
10.0
|
adjustment_delay
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The time to close the gap between the desired and the current stock. |
5.0
|
Examples:
>>> from skcomplex.systems.engineering.processes import GrainStoreElement
>>> GrainStoreElement('store').desired_stock
6000.0
Source code in src/skcomplex/systems/engineering/processes/_grain_storage.py
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | |
bathtub(water=50.0, *, inflow=5.0, outflow=5.0)
Return a bathtub, one stock of water with an inflow from the faucet and an outflow through the drain.
The drain empties the tub at outflow gallons per minute while there is water, and the faucet opens to inflow
gallons per minute after five minutes. With equal flows the level falls for five minutes and then stays constant.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
water
|
float
|
The initial water in the tub, in gallons. |
50.0
|
inflow
|
float
|
The inflow after five minutes, in gallons per minute. |
5.0
|
outflow
|
float
|
The outflow, in gallons per minute. |
5.0
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The system, with the water |
Examples:
>>> from skcomplex.systems.engineering.processes import bathtub
>>> bathtub(water=20.0).elements[0].water
20.0
Source code in src/skcomplex/systems/engineering/processes/_processes.py
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 | |
cascade_classifier(n_stages=10, *, k=0.6, feed_stage=None, feed=1.0)
Return a cascade classifier, a column of stages that separates a narrow size class of particles by an air flow.
Material leaves every stage at unit rate, a fraction k upwards and 1 - k downwards. The top stage releases
into the fine product and the bottom stage into the coarse product. Material of one size class is fed into one
stage at a constant rate. At steady state the share of the feed that ends in the fine product is
F_f = (1 - ((1 - k) / k)^(z + 1 - i)) / (1 - ((1 - k) / k)^(z + 1)) for z stages and feeding at stage i
counted from the top, Barsky's fractional extraction.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n_stages
|
int
|
The number of stages |
10
|
k
|
float
|
The distribution coefficient, the fraction of material moving up from a stage. |
0.6
|
feed_stage
|
int | None
|
The stage that receives the feed, counted from 1 at the top, or |
None
|
feed
|
float
|
The feed rate. |
1.0
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The system, with the material |
Examples:
>>> from skcomplex.systems.engineering.processes import cascade_classifier
>>> len(cascade_classifier(n_stages=4).interactions)
8
Source code in src/skcomplex/systems/engineering/processes/_processes.py
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 | |
food_relief(affected=100000.0, *, ration=0.0005, onset=10.0, shipping_delay=14.0, cover=7.0, stock_time=7.0)
Return a food relief system, a pipeline that ships food to a warehouse and distributes it to people in need.
A disaster at onset leaves affected people who need a daily ration. The relief agency ships food at the need
plus corrections that close the gaps between the warehouse stock and its desired cover of the need, and between
the food in transit and the need over the shipping delay. Shipped food enters the pipeline and arrives at the
warehouse through a third-order material delay. The warehouse distributes the need while its stock lasts. Food is
conserved, so almost nothing reaches the people in the first days after the disaster, and the gap closes as the
pipeline fills. The structure follows the relief food example of Bala, Arshad and Noh (2017, Section 4.11), with
illustrative parameters in tonnes and days.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
affected
|
float
|
The number of people in need after the disaster. |
100000.0
|
ration
|
float
|
The daily ration in tonnes per person. |
0.0005
|
onset
|
float
|
The day of the disaster. |
10.0
|
shipping_delay
|
float
|
The average time from shipping to arrival, in days. |
14.0
|
cover
|
float
|
The desired warehouse stock in days of need. |
7.0
|
stock_time
|
float
|
The time to correct the warehouse stock, in days. |
7.0
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The system, with the food stocks |
Examples:
>>> from skcomplex.systems.engineering.processes import food_relief
>>> food_relief(shipping_delay=7.0).elements[0].shipping_delay
7.0
Source code in src/skcomplex/systems/engineering/processes/_systems.py
524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 | |
grain_storage(stock=1000.0, on_order=10000.0, *, desired_stock=6000.0, release_fraction=0.025, receiving_delay=10.0, adjustment_delay=5.0)
Return a retail grain store, whose orders through a supply line make its stock oscillate.
The grain stock gains the receiving rate on_order / receiving_delay and loses the release rate
release_fraction stock, and the grain on order gains the procurement rate
(desired_stock - stock) / adjustment_delay and loses the receiving rate. The orders ignore the grain already on
order, so the supply line overshoots and the stock, the receiving rate, and the procurement oscillate in weeks
before they settle, with the stock below the desired one at
desired_stock / (1 + release_fraction adjustment_delay), 5333 tonnes for the defaults, where the release
balances the receiving. The defaults are those of the grain storage example of Bala, Arshad and Noh (2017), in
tonnes and weeks.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
stock
|
float
|
The initial grain stock. |
1000.0
|
on_order
|
float
|
The initial grain on order. |
10000.0
|
desired_stock
|
float
|
The desired grain stock. |
6000.0
|
release_fraction
|
float
|
The fraction of the stock released per week. |
0.025
|
receiving_delay
|
float
|
The average time for grain on order to arrive, in weeks. |
10.0
|
adjustment_delay
|
float
|
The time to close the gap between the desired and the current stock, in weeks. |
5.0
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The system, with the stocks |
Examples:
>>> from skcomplex.systems.engineering.processes import grain_storage
>>> grain_storage(receiving_delay=5.0).elements[0].receiving_delay
5.0
Source code in src/skcomplex/systems/engineering/processes/_grain_storage.py
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 | |
irrigation(*, river_inflow=0.5, seasonality=0.9, reservoir_capacity=80.0, potential_et=0.4, canal_loss=0.2, pump_capacity=0.2)
Return an irrigation system, a reservoir and an aquifer that keep the root zone of the crops supplied.
A river fills the reservoir with a yearly cycle, and the reservoir loses water to evaporation and spills above its capacity. The irrigation demand is the potential crop evapotranspiration plus the refill of the root zone towards a target fraction of its field capacity. The reservoir releases the demand grossed up for the canal losses, as far as its stock allows, and the losses seep into the aquifer. When the release falls short, the farmers pump the unmet demand from the aquifer up to the pump capacity. The crops draw water from the root zone at the potential rate scaled by a water-stress table, and the root zone percolates to the aquifer, which drains as baseflow. Water is conserved, so in the dry season the reservoir falls, the pumping rises, and the aquifer is drawn down. The structure follows the irrigation example of Bala, Arshad and Noh (2017, Section 4.11), with illustrative parameters in millions of cubic metres and days.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
river_inflow
|
float
|
The mean river inflow to the reservoir, per day. |
0.5
|
seasonality
|
float
|
The relative amplitude of the yearly inflow cycle. |
0.9
|
reservoir_capacity
|
float
|
The capacity of the reservoir. |
80.0
|
potential_et
|
float
|
The crop water requirement, the potential evapotranspiration of the irrigated area per day. |
0.4
|
canal_loss
|
float
|
The fraction of the release lost from the canals to the aquifer. |
0.2
|
pump_capacity
|
float
|
The largest groundwater pumping per day. |
0.2
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The system, with the water stocks |
Examples:
>>> from skcomplex.systems.engineering.processes import irrigation
>>> irrigation(pump_capacity=0.0).elements[0].pump_capacity
0.0
Source code in src/skcomplex/systems/engineering/processes/_systems.py
595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 | |
rice_milling(*, harvest=2000.0, seasonality=0.8, procurement_delay=1.0, outturn=0.65, capacity=2000.0, expansion_time=12.0)
Return a rice milling system, a mill that buys paddy, mills it into rice and by-products, and sells them.
Paddy arrives from the farms through a third-order procurement delay, at a rate that follows the harvest season around its mean. The mill processes its paddy stock in a month, as far as its milling capacity allows, and splits the milled paddy by mass into rice, the outturn, husk, bran, and milling losses. Rice, husk, and bran leave their inventories for the market at a fixed coverage. The capacity adjusts to the smoothed indicated milling rate, so in the harvest season the capacity lags and paddy accumulates, and in the lean season the capacity idles. Grain is conserved, every change of the paddy, rice, husk, and bran stocks is a flow, and over a year the milled paddy and the rice sales match the mean harvest and its outturn. The structure follows the rice milling case of Bala, Arshad and Noh (2017), with illustrative parameters in tonnes and months, since the case data are specific to their study.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
harvest
|
float
|
The mean paddy procurement in tonnes per month. |
2000.0
|
seasonality
|
float
|
The relative amplitude of the yearly harvest cycle. |
0.8
|
procurement_delay
|
float
|
The average time for purchased paddy to reach the mill, in months. |
1.0
|
outturn
|
float
|
The fraction of the milled paddy that becomes rice. |
0.65
|
capacity
|
float
|
The initial milling capacity in tonnes of paddy per month. |
2000.0
|
expansion_time
|
float
|
The time for the capacity to adjust to the perceived milling rate, in months. |
12.0
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The system, with the grain stocks |
Examples:
>>> from skcomplex.systems.engineering.processes import rice_milling
>>> rice_milling(capacity=1500.0).elements[0].capacity
1500.0
Source code in src/skcomplex/systems/engineering/processes/_systems.py
369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 | |
solid_waste(population=1000000.0, *, growth_rate=0.02, per_capita=0.2, recycling_share=0.2, composting_share=0.3, landfill_capacity=2000000.0)
Return a solid waste system, the waste of a growing city collected, recycled, composted, and landfilled.
The population grows exponentially and generates waste in proportion to its size. The waste waits uncollected until the collection, limited by a collection capacity that the city expands towards the generation with a delay, removes it. The collected waste is recycled, composted, or sent to the landfill in fixed shares. Recycled material and compost leave for industry and farms. The landfill accepts waste until it nears its capacity, and a table function then turns the residual waste to open dumping. Waste is conserved, so the landfill fills up to its capacity and dumping takes over. The structure follows the solid waste management case of Bala, Arshad and Noh (2017), with illustrative parameters in tonnes and years for a city of a million people.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
population
|
float
|
The initial population. |
1000000.0
|
growth_rate
|
float
|
The yearly growth rate of the population. |
0.02
|
per_capita
|
float
|
The waste generated per person, in tonnes per year. |
0.2
|
recycling_share
|
float
|
The share of the collected waste that is recycled. |
0.2
|
composting_share
|
float
|
The share of the collected waste that is composted. |
0.3
|
landfill_capacity
|
float
|
The capacity of the landfill in tonnes. |
2000000.0
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The system, with the population |
Examples:
>>> from skcomplex.systems.engineering.processes import solid_waste
>>> solid_waste(landfill_capacity=1e6).elements[0].landfill_capacity
1000000.0
Source code in src/skcomplex/systems/engineering/processes/_systems.py
449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 | |