Skip to content

Commit 33fb1ef

Browse files
authored
Merge pull request #5 from mt5555/copilot/create-plot-with-matplotlib
Add offset top x-axis to runtime layout plot
2 parents 50f0674 + c836e8e commit 33fb1ef

2 files changed

Lines changed: 131 additions & 0 deletions

File tree

pace/runtime_layout.py

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
"""
2+
Reproduce the PACE runtime processor layout plot.
3+
4+
The chart shows which MPI processor ranks are assigned to each component
5+
of a coupled climate model (e.g. E3SM/CESM). Each component is drawn as
6+
a filled rectangle whose y-extent gives the processor-rank range for that
7+
component. CPL (the coupler) spans all ranks; ATM shares the same rank
8+
range as CPL but is drawn with a narrower width to make it visible.
9+
10+
Processor layout for PACE run 224501
11+
-------------------------------------
12+
Component | color | ranks (y) | x-width
13+
-----------+--------------+-----------------+-----------
14+
ICE | cyan | 0 – 356 | full
15+
LND | lime green | 356 – 375 | full
16+
OCN | blue-purple | 1374 – 2312 | full
17+
CPL | orange | 2312 – 2419 | full
18+
ATM | light blue | 2312 – 2419 | 107 (narrow, drawn over CPL)
19+
"""
20+
21+
import matplotlib.pyplot as plt
22+
import matplotlib.patches as mpatches
23+
24+
# ---------------------------------------------------------------------------
25+
# Data: (label, face_color, x_start, x_end, y_start, y_end)
26+
# x / y values are MPI processor ranks (0-based).
27+
# CPL and ATM share the same rank range; ATM is drawn on top with a narrower
28+
# x-extent so both are visible simultaneously.
29+
# ---------------------------------------------------------------------------
30+
TOTAL_PROCS = 4096
31+
32+
t_ice1=0
33+
t_ice2=72.2
34+
35+
t_lnd1=t_ice2
36+
t_lnd2=t_lnd1 + 3.6
37+
38+
t_ocn1=t_lnd2
39+
t_ocn2=t_ocn1 + 199.7
40+
41+
t_atm1=t_lnd2
42+
t_atm2=t_atm1+187.6
43+
44+
t_cpl1 = max(t_atm2,t_ocn2)
45+
t_cpl2 = t_cpl1 + 106.3
46+
47+
total = 307.2
48+
if total > t_cpl2:
49+
print("Adding other overheads to CPL: original=",t_cpl2," new=",total)
50+
t_cpl2=total
51+
52+
53+
c_ocn1=0
54+
c_ocn2=TOTAL_PROCS-256
55+
c_atm1=c_ocn2
56+
c_atm2=c_atm1+256
57+
58+
59+
60+
61+
components = [
62+
# name color x0 x1 y0 y1
63+
("ICE", "cyan", 0, TOTAL_PROCS, t_ice1, t_ice2),
64+
("LND", "#00CC00", 0, TOTAL_PROCS, t_lnd1, t_lnd2),
65+
("OCN", "#8888FF", c_ocn1, c_ocn2, t_ocn1, t_ocn2),
66+
("CPL", "orange", 0, TOTAL_PROCS, t_cpl1, t_cpl2),
67+
# ATM shares the CPL rank range; its narrower x-width distinguishes it
68+
("ATM", "#87CEEB", c_atm1, c_atm2, t_atm1, t_atm2),
69+
]
70+
71+
# ---------------------------------------------------------------------------
72+
# Build figure
73+
# ---------------------------------------------------------------------------
74+
fig, ax = plt.subplots(figsize=(10, 7))
75+
76+
for name, color, x0, x1, y0, y1 in components:
77+
rect = mpatches.Rectangle(
78+
(x0, y0), x1 - x0, y1 - y0,
79+
linewidth=0.8,
80+
edgecolor="black",
81+
facecolor=color,
82+
zorder=2,
83+
)
84+
ax.add_patch(rect)
85+
86+
# Place the label at the visual centre of the rectangle
87+
cx = (x0 + x1) / 2
88+
cy = (y0 + y1) / 2
89+
ax.text(
90+
cx, cy, name,
91+
ha="center", va="center",
92+
fontsize=14, fontweight="bold",
93+
zorder=3,
94+
)
95+
96+
# ---------------------------------------------------------------------------
97+
# Axes formatting
98+
# ---------------------------------------------------------------------------
99+
ax.set_xlim(0, TOTAL_PROCS)
100+
ax.set_ylim(0, t_cpl2)
101+
102+
# Y-axis ticks match the component boundaries visible in the original plot
103+
yticks = [t_ice1, t_ocn1, t_cpl1, t_cpl2]
104+
ax.set_yticks(yticks)
105+
ax.set_yticklabels([f"{v:.1f}" for v in yticks])
106+
107+
xticks = [0, 1024, 2048, 3072, 4096]
108+
ax.set_xticks(xticks)
109+
ax.set_xticklabels([f"{v:.0f}" for v in xticks])
110+
111+
ax.set_xlabel("Processor Cores", fontsize=12)
112+
ax.set_ylabel("Seconds per Model Day", fontsize=12)
113+
114+
# Top x-axis in bottom-axis units, starting at 4096.
115+
ax_top = ax.secondary_xaxis(
116+
"top",
117+
functions=(
118+
lambda cores: cores + TOTAL_PROCS,
119+
lambda top_units: top_units - TOTAL_PROCS,
120+
),
121+
)
122+
top_ticks = [4096, 5120, 6144, 7168, 8192]
123+
ax_top.set_xticks(top_ticks)
124+
ax_top.set_xticklabels([f"{v:.0f}" for v in top_ticks])
125+
ax_top.set_xlabel("Processor Cores (+4096 offset)", fontsize=12)
126+
127+
ax.tick_params(axis="both", labelsize=10)
128+
129+
plt.tight_layout()
130+
plt.savefig("runtime_layout.png", dpi=100, bbox_inches="tight")
131+
plt.show()

runtime_layout.png

30.8 KB
Loading

0 commit comments

Comments
 (0)