Skip to content

Commit cd2eb16

Browse files
committed
Add crusher circuit example
1 parent 64adfa9 commit cd2eb16

4 files changed

Lines changed: 1529 additions & 0 deletions

File tree

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*.csv
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
"""Test the full circuit simulation with mass tracking + interpolated d80."""
2+
3+
import asyncio
4+
5+
from crusher_circuit import Conveyor, Crusher, FeedSource, PSD, ProductCollector, Screen
6+
from plugboard.connector import AsyncioConnector
7+
from plugboard.process import LocalProcess
8+
from plugboard.schemas import ConnectorSpec
9+
10+
SIZE_CLASSES = [150.0, 106.0, 75.0, 53.0, 37.5, 26.5, 19.0, 13.2, 9.5, 6.7, 4.75]
11+
FEED_FRACTIONS = [0.05, 0.10, 0.15, 0.20, 0.18, 0.12, 0.08, 0.05, 0.04, 0.02, 0.01]
12+
13+
connect = lambda src, tgt: AsyncioConnector(spec=ConnectorSpec(source=src, target=tgt))
14+
15+
process = LocalProcess(
16+
components=[
17+
FeedSource(
18+
name="feed",
19+
size_classes=SIZE_CLASSES,
20+
feed_fractions=FEED_FRACTIONS,
21+
feed_tonnes=100.0,
22+
total_steps=50,
23+
),
24+
Crusher(
25+
name="crusher",
26+
css=12.0,
27+
oss=30.0,
28+
k3=2.3,
29+
n_stages=2,
30+
initial_values={"recirc_psd": [None]},
31+
),
32+
Screen(name="screen", d50c=18.0, alpha=3.5, bypass=0.05),
33+
Conveyor(name="conveyor", delay_steps=3),
34+
ProductCollector(name="product", target_d80=20.0),
35+
],
36+
connectors=[
37+
connect("feed.feed_psd", "crusher.feed_psd"),
38+
connect("crusher.product_psd", "screen.crusher_product"),
39+
connect("screen.undersize", "product.product_psd"),
40+
connect("screen.oversize", "conveyor.input_psd"),
41+
connect("conveyor.output_psd", "crusher.recirc_psd"),
42+
],
43+
)
44+
45+
46+
async def main() -> None:
47+
async with process:
48+
await process.run()
49+
collector = process.components["product"]
50+
d80s = [PSD(**h).d80 for h in collector.psd_history]
51+
masses = [PSD(**h).mass_tonnes for h in collector.psd_history]
52+
print(f"Steps: {len(d80s)}")
53+
for i in [0, 1, 2, 3, 4, 5, 6, 7, 9, 14, 19, 29, 49]:
54+
if i < len(d80s):
55+
print(f" Step {i + 1:>2}: d80={d80s[i]:.2f} mm, mass={masses[i]:.1f} t")
56+
unique_d80s = len(set(round(d, 4) for d in d80s))
57+
unique_masses = len(set(round(m, 4) for m in masses))
58+
print(f"\nUnique d80 values: {unique_d80s}")
59+
print(f"Unique mass values: {unique_masses}")
60+
print(f"d80 range: {min(d80s):.2f} - {max(d80s):.2f} mm")
61+
print(f"Mass range: {min(masses):.1f} - {max(masses):.1f} t")
62+
ok = unique_d80s > 1 and unique_masses > 1
63+
print("PASS" if ok else "FAIL - no dynamics")
64+
65+
66+
asyncio.run(main())

0 commit comments

Comments
 (0)