2026-W36 週報:容量不再是一個數字的那一週¶
第六份週報,本週 5 張卡,5 個工作日,量與節奏都達標。而且這一週跨了兩件事:電力鏈在 9/2 走完最後一張(dc-16),9/3 冷卻鏈開工。
但真正該記的不是里程碑,是模型在這五天裡被連續改了五次,而且每一次都比前一次更根本:
| 卡 | 「容量」變成什麼 | 前一天的 code 還能不能用 |
|---|---|---|
dc-14 rack PDU |
四維取 min,而 binding 會跑 | 能,這是 W35 #1 的兌現 |
dc-15 電錶 |
實測維度帶誤差帶,要用保守端;失聯要降級 | 能,加一個 method |
dc-16 雙電源 |
多一個離散維度 scenario(3 值) |
能,但既有數字會變壞 |
dc-17 冷卻水塔 |
limit: float → limit(env);第二種資源(水) |
不能,binding() 簽章換了 |
dc-18 冰機 |
從沿樹求值變成解聯立(固定點迭代) | 不能,報表要多帶 converged |
一週之內,「還剩多少」從查表變成解方程。而最後一張卡做了這條軌跡從來沒發生過的事:dc-18 用 dc-17 自己的模型推翻了 dc-17 的結論。
本週卡片¶
| 卡 | 標題 | 這張卡最關鍵的一個事實 |
|---|---|---|
dc-14 |
機櫃電源 rack PDU | 線間負載的電流不能相加:10 A + 10 A 的共用相是 17.32 A(向量和),但 wye 接法就是直接相加——兩種算法都對,錯的是不知道自己在哪一種。而同一顆 CS8365C 插頭依內部斷路器數量有 35 A 與 40 A 兩個正確答案 |
dc-15 |
電力監測儀表與電錶 | 精度與取樣率正交:輪詢從 5 分鐘改 5 秒只是更頻繁地拿到同一個 ±1% 的錯值。而精度沿感測鏈累加(PMD 0.2 + CT 0.5 → 0.7%),在 2 MW 上是 14 kW——比兩個機櫃還多 |
dc-16 |
設備端雙電源與單電源 | 樹在最後一跳變成 DAG。而「每側 ≤ 50%」是推論不是規定:真正的約束是「單側扛得住全櫃」。10 kW 櫃日常 58.4% 全綠,failover 是 116.8%——斷路器跳,冗餘設計反而全損 |
dc-17 |
冷卻水塔 | 濕球升 2 °C,容量掉一半,一格設備都沒壞。 出水溫是「濕球 + approach」,濕球是天氣給的不是你設的。同時它是第一個同時掛在電力樹與冷卻樹上的設備 |
dc-18 |
冰水主機 | 跳機的是壓力不是容量。 WB 30 °C/2 格那格,水塔「排得掉」1 877 kW、容量報表不算超載,但平衡點解出 35.8 °C 超過冷凝器進水上限 → 高壓跳脫。容量報表全綠、機器照跳 |
串起來¶
一、五天,五次「容量」的定義被改寫¶
W35 的結論是「還剩多少有三種回傳型別」。本週把它一路推到底:
dc-14 capacity = min over 四個維度 ← 純量比大小
↓ binding 會跑(30A 機是進線,50A 機是斷路器)
dc-15 capacity = min over 維度,但實測維度是「區間」 ← 值變成 Bound
↓ 而且失聯時該維度是 stale 不是 0
dc-16 capacity = min over 維度 × scenario ← 多一個離散軸(3 值)
↓ 第一次讓既有數字「變壞」:58.4% 綠 → 116.8% 紅
dc-17 capacity = min over 維度 × scenario,limit 是 env 的函數 ← 軸變成連續
↓ 而且要 per-resource(kW 不能跟 L/min 比大小)
dc-18 capacity = 解聯立的結果 ← 不再是求值,是求解
每一步都不是加欄位,是換數學。 而且五步之間沒有任何一步是可逆的——dc-18 之後你不可能再退回「查一下表就知道還剩多少」。
值得單獨記一句:dc-16 是第一張讓既有數字變難看的卡。 前十五張卡都在增加模型的解析度,dc-16 第一次讓一個「本來是綠燈」的機櫃變成紅燈——而它並沒有新增任何量測,只是多算了一個情境。這是模型成熟的訊號,也是最容易被拒絕的那種改進。
二、本週最大的一件事:後一張卡推翻了前一張卡¶
dc-17 算出「濕球 30 °C 時 4 格水塔只剩 1 300 kW、用率 142%、紅燈」。dc-18 把水塔模型和冰機模型接起來解聯立,得到完全不同的答案:
Q_tower(T_cw) = 650 × 4 × (T_cw − WB) ← dc-17 的水塔
P_comp(T_cw) = 455 × 0.55 × (1 + 0.036 × (T_cw − 32)) ← dc-18 的冰機
Q_reject = 1600 + P_comp
令兩邊相等,WB = 30 °C:
640.99 · T_cw = 21061.96
T_cw = 32.86 °C ← 系統不會停,它停在這裡
驗證:approach 2.86 K → 水塔排 1859 kW;kW/ton 0.567 → 壓縮機 258 kW → 需排 1858 kW ✔
濕球 30 °C 時系統不會掛,它停在冷卻水 32.9 °C,代價是冰機多吃 8 kW。142% 是錯的。
錯在哪很重要:不是算術錯,是前提錯。 dc-17 假設冷卻水恆定 32 °C,然後問「這個溫度下水塔排得掉多少」。但真實系統的水溫會往上浮直到排得掉為止;水溫一浮,冰機更耗電、排更多熱——正回饋,只能解不能算。
而真正的紅燈條件也換了位置:
| 情境 | 平衡冷卻水溫 | 判定 |
|---|---|---|
| WB 28 °C、4 格 | 30.8 °C | 綠燈 |
| WB 30 °C、4 格 | 32.9 °C | 綠燈(dc-17 說紅燈) |
| WB 28 °C、2 格 | 33.7 °C | 黃燈 |
| WB 30 °C、2 格 | 35.8 °C | 紅燈——但不是容量不足,是超過 max_condenser_entering_c = 35 |
反推臨界濕球:4 格 32.1 °C/3 格 31.1 °C/2 格 29.2 °C。台北極端濕球就在 2 格那個數字附近——所以「兩格水塔同時不可用」在夏天真的會掉機房,四格全開則再熱都撐得住。 這三個數字是這座機房冷卻鏈的風險地圖,而且是算出來的,不是誰的經驗。
對這條學習軌跡本身的意涵:這是第一次「今天的卡證明昨天的卡是錯的」。這件事應該被視為正常而不是失誤——
dc-17在只有水塔知識時給出了那個前提下唯一能給的答案,dc-18帶來了缺的那一半。真正的教訓是卡片裡的數字必須帶著它的前提一起存(dc-17自己其實有標「這張表是一階近似,不是規格」,做對了);只有數字沒有前提的那些,才是未來會靜默出錯的地方。
三、電力鏈橫向回顧(W35 交代的作業)¶
第一輪 16 項在 9/2 走完,實際產出 22 張卡(六次拆卡)。回頭看整條鏈:
dc-01 市電 → dc-02 變壓器 → dc-03 MV盤 → dc-04 ATS → dc-05 發電機 → dc-06 油
→ dc-07 LV盤 → dc-08 UPS → dc-09 電池 → dc-10 STS → dc-11 PDU
→ dc-12 RPP → dc-13 busway → dc-14 rack PDU → dc-16 設備
(dc-15 電錶不在鏈上,是掛在鏈上的觀測器)
第一個發現:整條鏈上沒有任何兩段的容量單位可以直接相加。
| 段 | 容量單位 | 為什麼不能跟上一段相加 |
|---|---|---|
| dc-02 變壓器 | MVA + 阻抗% | 阻抗決定下游的 Icw 合法性,不是容量 |
| dc-07 LV 盤 | InA / Inc / Ing / RDF | 四個額定名字都叫「電流」但語意不同 |
| dc-11 PDU | kVA + 極數 | 極數用完了 kVA 還剩很多(擱置容量) |
| dc-13 busway | A + 位置(前綴和) | 同一條 run 上不同位置的剩餘量不同 |
| dc-14 rack PDU | 每相 A(向量和) | 線間負載不能算術相加 |
| dc-16 設備 | W × scenario | 沒有單一數字,只有一組情境下的數字 |
第二個發現,也是更有用的一個:六次拆卡全部發生在同一個交界上。
| 原卡(設備本體) | 拆出去的(關係/制度) |
|---|---|
| dc-03 MV 盤額定 | dc-03b LSC 分級與互鎖(制度) |
| dc-05 發電機額定 | dc-05b 起動時序、dc-05c NFPA 110 測試制度(時間軸/制度) |
| dc-07 LV 盤額定 | dc-07b 短路耐受與保護協調(設備之間的關係) |
| dc-09 電池額定 | dc-09b 測試制度、dc-09c 消防合規(時間軸/第二棵樹) |
| dc-10 STS 本體 | dc-10b 兩源拓撲關係、dc-10c 相位同步(邊與圖) |
規律很乾淨:設備本身寫得完,設備之間的關係與圍繞它的制度寫不完。 每一次拆卡都是「六格裝不下」的訊號,而裝不下的東西總是同三類:時間軸、第二棵樹、邊。
這對佇列排程有直接建議:冷卻鏈可以預期同樣的拆法。dc-18 已經冒出「冰機重啟時序」(時間軸)與「水處理/退伍軍人桿菌合規」(制度)兩條線,兩條都不在六格裡。
四、「真相不在設施側」本週出現三次,而且各寫了一次降級路徑¶
這是本週最該立刻收斂的一件事(見連貫性檢視 #1):
| 卡 | 欄位 | 真相在哪 | 過期時 |
|---|---|---|---|
dc-15 |
錶讀數 | 錶/BMS,會失聯 | Meter.last_seen + ttl → METER_STALE |
dc-16 |
psu_policy |
iDRAC/Redfish,伺服器管理員會改而不通知設施 | fetched_at + ttl → PSU_POLICY_STALE |
dc-17 |
濕球 | 氣象站/推導自乾球+RH | SiteEnvironment.valid → ENV_STALE |
三個形狀一模一樣:外部來源 + 取得時間 + 有效期 + 過期時退回保守值並吐一條降級 Finding。三張卡各實作了一次。
dc-16 那條特別值得記,因為它是第一個真相在別的部門手上的欄位:hot spare 開著時 A 側天天貼著 93.5% 跑,設施看到的「嚴重不平衡」完全是設計行為——而這個設定不在設施的任何一張表裡。這不只是技術問題,是組織介面問題。
五、掉一個會連鎖到哪:本週的兩條新連鎖¶
(a)電力側的故障域會投影成冷卻側的容量損失(dc-17 誤解 3):
A 側停電 → 幾格水塔風扇掉電 → in_service=False
→ 有效格數變少 → 平衡冷卻水溫上升(dc-18 解聯立)
→ 冰機 lift 上升、kW/ton 上升
→ 若超過 35 °C 進水上限 → 高壓跳脫 → 機房失冷
兩張表若互不知道,這條連鎖沒有人看得到。 W35 收斂的「兩棵樹橫向邊」在 dc-17 第一次有真實流量,而且是有方向的:電力側的 scenario 要能傳播成熱側的容量損失。
(b)冰機回頭咬發電機(dc-18 對資料模型 #5):
停電 → 冰機掉(不在 UPS 上)→ 熱慣量只撐 5.2 分鐘(20 m³ 環路)
→ 發電機起來 → 冰機重啟是 250 kW 的 step load
→ 回頭吃 dc-05b 的發電機暫態性能(頻率下陷)
→ 時序沒排好會連累別的負載
而 restart_time 本身是回水溫的函數(見來源分歧),回水太熱時重啟會二次跳脫。所以這條連鎖是時間軸上的,穩態的 CapacityReport 表達不了它——dc-18 因此要求一個 TransientScenario。這是本軌跡第一次需要模擬而不是計算。
六、本週母題¶
| 週次 | 母題 |
|---|---|
| W31 | 單一欄位裝不下一個事實(數字要帶著量測條件) |
| W32 | 有些事實根本不住在欄位裡(住在序列、存量、多對多裡) |
| W33 | 上限是多候選取 min,裸數字丟掉了最有用的資訊 |
| W34 | 判定不是事實的屬性,是事實 × 判準——而判準是版本化的資料 |
| W35 | 「還剩多少」有多種型別,而鏈上要跨它們取 min |
| W36 | 容量不是屬性,是在一組條件與情境下解出來的值——而條件會被結果改變 |
五張卡各自撞到它的不同層次:dc-14 是算法分岔(wiring 決定用哪條公式)、dc-16 是情境(離散)、dc-17 是環境(連續)、dc-18 是迴圈(互為因果)。dc-15 則從側面說了同一件事:連「量到的值」都不是一個數,是一個帶著出身的區間。
自我測驗¶
Q1(事實回憶). 一台 208 V delta 接法的 rack PDU,L1-L2 掛 12 A、L2-L3 掛 8 A、L3-L1 掛 0 A。三條線的電流各是多少?若同一批負載改接在台灣常見的 380Y/220V 機櫃上呢?
答案
delta:L1 = 12 A、L3 = 8 A、L2 = 17.44 A。
L1 與 L3 各只被一個負載使用,等於該負載本身。L2 被兩個線間負載共用,相位差 120°,走向量和:
注意 L2 比任何一個負載都大,也比它們的算術平均大很多,但小於 20 A。 直覺上「平均一下」與「加起來」都會給錯答案,而且錯的方向相反。
wye(380Y/220V):插座是相對中性的單相 220 V,電流直接相加。 同一批負載掛在同一相上就是 20 A。
這才是重點:兩種算法都對,錯的是不知道自己在哪一種。 所以 RackPdu.wiring 不是裝飾欄位,它是計算的前提——不存的話兩個分支都會給出看起來合理的數字,而且沒有任何遙測會告訴你選錯了(PDU 自己量到的永遠是對的,錯的是你的資料庫)。
Q2(事實回憶). 你把某條饋線的 Modbus 輪詢從 5 分鐘改成 5 秒。資料變準了嗎?如果沒有,什麼情況下這件事仍然值得做?
答案
沒有變準。精度與取樣率正交。
精度由 PMD 等級與 CT 等級決定(Eaton 的比喻:精度是樂手唱得準不準,取樣率是你用 HD 還是舊 VHS 錄他)。±1% 的錶輪詢再密還是 ±1%。這條對軟體工程師特別致命,因為「提高取樣頻率」是我們手上唯一能自己動的旋鈕。
而且精度沿感測鏈累加,不是只看錶:
class 0.2 的 PMD + class 0.5 的 CT
最壞(線性):0.2 + 0.5 = 0.7%
RSS: √(0.2² + 0.5²) ≈ 0.54%
2 MW × 0.7% = 14 kW ← 比兩個 6 kW 機櫃還多
更陰險的是同一顆錶在不同負載率下不是同一個精度:CT 的等級定義在額定附近,新機房第一年一條 400/5 CT 只跑 60 A = 15% 額定,誤差比銘牌差好幾倍——而新機房頭一年正是最需要準確資料做容量規劃的時候。
仍值得提高取樣率的情況:要抓的是短時事件而非穩態值——STS 切換暫態、發電機 起動時的電壓下陷、跨 demand block 邊界的真實尖峰(dc-15 第三節那個 750 vs 1000 kW,差 33%)。這些在 5 分鐘取樣下根本不存在。
一句話:取樣率決定你「看得到什麼事件」,精度決定你「數字有多可信」。 兩者都要,不能互相替代。
Q3(應用). 一個機櫃日常兩側各 58.4%,儀表板全綠。你的容量報表要多做哪一件事才會發現這是紅燈?把數字算出來。
答案
要在 failover 情境下重算,不能只算今天的讀數。
「每側 ≤ 50%」是推論不是規定。唯一的約束是「單側必須扛得住全機櫃」:
承 dc-14:兩條 208 V delta 30 A rack PDU,derated 24 A,
C_side = √3 × 208 × 24 = 8 646 VA
10 kW 機櫃(PF 0.99 → 10 101 VA):
⚠️
dc-16卡片的驗收表把normal那格寫成 50.5%,那是錯的。 分母誤用成 10 kVA 而非單側 derated 容量 8 646 VA。自我一致性檢查很簡單:平分政策下 failover 恰好是 normal 的兩倍,116.8 / 2 = 58.4。同卡的 8 kW 那列(46.7% / 93.5%)就是這個關係,只有 10 kW 這列破了。照那張驗收表寫測試會直接紅。 見連貫性檢視 #6。
冗餘設計反而造成全損,而日常儀表板永遠看不到這件事。
還有第二層陷阱:負載不會平均落回去。伺服器 PSU 的兩路輸入未必接在對側 PDU 的同一 bank,轉移後可能單一 bank 瞬間翻倍而其他兩個不變——總量還在 90%,但某一個 bank 已經跳了。所以 redundancy_ok() 不能比對總 kVA,要逐 bank 模擬對側失效後的重分佈。
對模型:CapacityReport 要多一個 scenario 維度(normal / lose_a / lose_b),binding() 取跨情境的最壞值。這是 dc-10b「枚舉配置取 max」從幾台 STS 推廣到每一個葉節點。
Q4(應用). 「容量用率 92%、綠燈」但冰機跳了。怎麼會這樣?順便說明為什麼這個數字不能沿著樹往上查就算出來。
答案
跳的是保護不是容量。
WB 30 °C、水塔只剩 2 格時,解聯立得到平衡冷卻水溫 35.8 °C,超過 max_condenser_entering_c = 35 → 高壓保護動作。熱量「排得掉」(水塔排 1 877 kW,數字上不算超載),但排得掉的那個溫度機器受不了。
為什麼不能沿樹查:冰機的 limit 依賴冷凝器進水溫,那個溫度由水塔決定;而水塔要排的熱包含冰機自己的壓縮機功——互為因果,形成正回饋。沿樹求值假設「下游不影響上游」,這個假設在這裡破了。
Q_tower(T_cw) = 650 × cells × (T_cw − WB)
Q_reject = 1600 + 455 × 0.55 × (1 + 0.036 × (T_cw − 32))
→ 固定點迭代求 T_cw
對模型的三個後果:
CapacityReport要記converged/iterations/residual_k——不收斂的報表要能明講自己不收斂,而不是吐一個看起來很正常的數字。- 保護設定值與容量維度要分開存。
Finding要有PROTECTION_TRIP_PREDICTED,與OVERLOADED並列而非合併——這兩件事的處置方向完全不同。 - 反推臨界濕球(二分搜尋讓
T_cw剛好 35 °C)得到 4 格 32.1 / 3 格 31.1 / 2 格 29.2 °C。這是可以算出來的風險地圖,不必等事故。
Q5(建模判斷). 本週三張卡各自實作了一次「外部真相過期就降級」:METER_STALE、PSU_POLICY_STALE、ENV_STALE。它們該合併嗎?合併成什麼?不合併會怎樣?
答案
該合併,而且這是本週投報率最高的一項。
三者的形狀完全相同——只差在來源與 TTL:
dc-15 錶 |
dc-16 PSU 政策 |
dc-17 濕球 |
|
|---|---|---|---|
| 來源 | 錶/BMS | Redfish/iDRAC | 氣象站/乾球+RH 推導 |
| 誰會改它 | 沒人,會失聯 | 伺服器管理員,且不通知設施 | 天氣 |
| 過期判準 | last_seen + ttl |
fetched_at + ttl |
valid 旗標 |
| 過期時 | 退回 nameplate 法 | 退回平分假設 | 退回設計濕球(保守端) |
| 吐什麼 | METER_STALE |
PSU_POLICY_STALE |
ENV_STALE |
收斂建議(可直接貼):
from dataclasses import dataclass
from datetime import datetime, timedelta
from typing import Generic, TypeVar, Literal
T = TypeVar("T")
@dataclass(frozen=True)
class Sourced(Generic[T]):
value: T
source: Literal["redfish", "modbus", "bacnet", "weather", "manual", "design"]
fetched_at: datetime
ttl: timedelta
fallback: T | None = None # 過期時退回的保守值
def is_stale(self, now: datetime) -> bool:
return now - self.fetched_at > self.ttl
def resolve(self, now: datetime) -> tuple[T, "Finding | None"]:
if not self.is_stale(now):
return self.value, None
if self.fallback is None:
raise ValueError(f"stale {self.source} and no fallback")
return self.fallback, Finding(
policy_id="SOURCE_STALE", severity="WARNING",
entity_ids=[], message=f"{self.source} stale, using fallback")
不合併的三個具體後果:
- 降級語意會漂。 三處各寫一次
if stale: ...,遲早有一處忘了設Dimension.valid=False,於是那一維被當成量到 0——dc-15已經點名這件事:回報 0 的系統會讓人以為機櫃是空的。 Finding的 code 會爆炸。 每多一個外部來源就多一個*_STALE,而它們的處置完全一樣。應該是同一條 policy 帶不同source,這樣「本站現在有幾個資料來源是過期的」才是一個查得出來的問題。- 最重要的一條:
Sourced逼你為每個外部欄位想清楚fallback是什麼。 三張卡的 fallback 都是保守端(設計濕球而不是今天的濕球、nameplate 而不是實測、平分而不是 hot spare 假設),但這件事目前只寫在散文裡。放進型別,它就變成建構時必須回答的問題。
反過來,不該塞進 Sourced 的:SiteEnvironment 本身。濕球是站點級外生變數(dc-17 對資料模型 #4),同時被水塔、冰機、free cooling 判斷、CRAH 除濕四個地方消費,掛在某台設備下面會被複製四份且互相不一致。Sourced 包的是欄位的取得方式,不是欄位的歸屬層級——這兩件事本週很容易混起來。
間隔複習¶
本週抽兩週前(W34)與四週前(W32)各一張。
| 週次 | 抽兩週前 | 抽四週前 |
|---|---|---|
| W34 | W32 ✅ | 尚無 |
| W35 | W33 的 dc-07b ✅ |
W31 的 dc-03b ✅ |
| W36(本週) | W34 的 dc-10 STS |
W32 的 dc-05b 發電機起動時序 |
| W37 | W35 的卡(dc-10b ~ dc-13) |
W33 的卡(dc-06 ~ dc-09) |
兩張都不是隨機抽的:本週有兩張卡分別把它們的結論推到了新的規模與新的領域。
抽 W34 的 dc-10 靜態切換開關 STS(2026-08-20,17 天前)¶
複習題. dc-10 說「有兩個源是宣稱,redundancy_effective() 才是事實」,並要求對 STS 跑 common-ancestor 測試。本週的 dc-16 對這個結論做了什麼?為什麼那是一個量級的差別?另外,dc-16 裡的「ATS」跟 dc-10 裡的 ATS 是同一種東西嗎?
答案
dc-16 把這個測試的對象從「幾台 STS」變成「每一台伺服器」。
dc-10 / dc-10b 的 common-ancestor 測試原本只要對設施級 STS 跑——一座機房大概幾台。dc-16 指出雙電源設備的兩條電源線就是兩個父節點,所以同一個測試要對每一台雙電源伺服器跑:
量級差別的實質後果:所有沿樹寫的容量演算法都得重寫。dc-13 立的前綴和要參數化成 prefix_sum(edge, scenario);load 不能是純量,PowerEdge 需要 share_normal 與 share_failover,而後者取決於「哪一側掛了」——所以它不是欄位,是情境函數 load(scenario)。
而 dc-16 的加分題把這件事變成一個可執行的清單:對整個機房跑一次 check_path_independence(),統計有多少台設備的獨立性只到 rack PDU 層。 那個數字就是進 commissioning 前最該修的清單——dc-10b 那三級 verdict(NO_INDEPENDENCE / SHALLOW_LCA / OK)在這裡第一次有了統計意義。
ATS 那半:不是同一種東西,而且差兩個數量級。
設施級 ATS(dc-04) |
機櫃級「rack ATS」(dc-16) |
|
|---|---|---|
| 切什麼 | 市電 vs 發電機(一邊通常是死的) | 兩條都活的 A/B 側 |
| 機構 | 接觸器/馬達操作斷路器 | 固態 |
| 轉換時間 | 100–500 ms(EPC) | 典型 8 ms(APC AP4423) |
EPC 直言「UPS 下游放(設施級)ATS 餵伺服器,不是保護它們,是重開它們」。兩邊都沒錯——是兩種不同的東西共用一個名字。
對模型的結論很硬:device_role == "ats" 推不出轉換時間,transfer_time_ms 必須是實測或型錄值。而且就算是 8 ms 也沒有帳面上那麼寬鬆:ITIC 的 20 ms hold-up 是滿載條件下標的,負載 90% 時可能只剩 12 ms,餘裕從 12 ms 縮到 4 ms——而 failover 發生的時刻正好是負載最高的時刻。這跟 dc-10 演算 1「餘裕從 13.83 ms 掉到 5.50 ms」是同一種陷阱的第二次現身:規格書上的餘裕都是在最好的條件下算的,而故障總是發生在最壞的條件下。
抽 W32 的 dc-05b 發電機起動時序與暫態性能(2026-08-05,32 天前)¶
複習題. dc-05b 講發電機承接階躍負載時的頻率/電壓下陷(ISO 8528-5)。本週的 dc-18 從冷卻側丟了一個新的階躍負載過來——是什麼?為什麼它比一般負載麻煩?這會讓資料模型長出什麼欄位?
答案
是冰機重啟:一台 455 RT 級的機器約 250 kW,而且它是整條鏈上唯一「掉了不會馬上回來」的設備。
先把時間尺度排一次,這是本軌跡最該記住的一張表:
UPS 毫秒 (dc-08)
STS 4–12 ms (dc-10)
rack ATS 8 ms (dc-16)
設施 ATS 100–500 ms(dc-04 / dc-16 的分歧)
發電機 ~10 秒 (dc-05b)
冰機 分鐘 (dc-18)← 慢了兩個數量級
為什麼比一般負載麻煩,三個理由:
- 它不在 UPS 上,所以停電時一定掉。 而熱慣量只撐得住 5.2 分鐘(20 m³ 環路、允許回水 12→18 °C、1600 kW 負載)——要撐 15 分鐘需要 57 m³,將近 3 倍,這就是
dc-20儲冷槽存在的理由。前提是泵在 UPS 上:水不流動時那 20 m³ 送不到機房,有儲量不等於送得到。 - 重啟本身是一個大階躍,正好落在
dc-05b講的 ISO 8528-5 暫態性能上。時序沒排好,頻率下陷會連累同一台發電機上的其他負載。 - 重啟時間不是常數(來源分歧)。 datacentre.solutions / Climaveneta 說典型 10–15 分鐘、新機種 4–5 分鐘;Cundall(2026-07,附 L4 實測,模型與實測差 0.2 °C 內)說重啟計時器根本不是重點——他們在雪梨看到的是回水溫爬太高,冰機重啟後蒸發器過壓、幾分鐘內二次跳脫。
會長出的欄位:
PowerLoad.startup_profile(步階大小、允許延遲、可否分批)——這份資料只有機械團隊有,設施電力側拿不到。這是本週第二個「真相在別的部門手上」的欄位(第一個是dc-16的psu_policy在伺服器團隊手上)。restart_time_s不能是設備欄位,要是restart(return_water_temp, attempt_n),而且必須能回傳「重啟會失敗」。這是「常數 vs 條件函數」的又一例,跟dc-10的transfer_time_ms同構。TransientScenario——ride_through是f(loop_volume, allowed_dt, load, pumps_on_ups, restart_time),橫跨冰機/泵/儲槽/UPS 四類設備,而restart_time自己又是回水溫的函數。穩態的CapacityReport表達不了它,這是模型第一次需要時間軸模擬。
兩張卡合起來的那句話:dc-05b 問「發電機承不承受得住這個階躍」,dc-18 問「這個階躍什麼時候來、來幾次、來的時候還有沒有用」。同一個事件的兩端,中間隔了 32 天和一整條鏈。
本週的 model code 連貫性檢視¶
先結算舊帳。本週是規律最清楚的一次:
| 來源 | 項目 | 狀態 |
|---|---|---|
| W35 #1 | 「還剩多少」三種回傳型別 | ✅ 兌現。dc-14 定義了統一的 Dimension / CapacityReport(dims: list[Dimension]),而 dc-15 / dc-16 / dc-17 / dc-18 四張卡全部長在同一份上(每張都明寫「不要開新檔案」) |
| W35 #2 | validate() -> list[str] vs audit() -> list[Finding] |
✅ 兌現。dc-14 定義了 Finding 本體(含「不得有 acked」的註解),本週五張卡一致回 list[Finding] |
| W35 #3 | _derated 命名漂了三次 |
🟡 部分。dc-14 用 input_derated_a + derating_basis,形狀對了;但 Rating(nameplate, derated, basis, authority) 這個值物件仍未抽出來 |
| W35 #4 | Breaker / Panelboard 各定義兩次 |
⚠️ 未動(本週沒碰) |
| W35 #5 | 約束的基數有四種 | 🟡 部分。dc-14 的 Outlet.legs: tuple[Leg,...](wiring 決定長度)是第一個把基數當一等公民的例子 |
| W34 #1 | dc-09 的 energy_kwh() 改名 |
🔴 連續第三週掛在第一順位卻沒做。 10 分鐘 |
| W34 #2 | Policy 本體 |
🔴 仍未定義。本週的 Finding.policy_id 已經指向 7 個不存在的 policy |
| W33 #1 / #2 | Assembly 碰撞 / EnergyStore |
⚠️ 仍未動(連續第四週) |
W34 立的那條規律第三次成立:具體到可以直接貼進 code 的建議會被採納,抽象的不會。 W35 的 #1 與 #2 都附了明確的目標 dataclass,兩項都在下一張卡就兌現了;#4 / #5 是描述性的,一項沒動。所以下面五項同樣全部寫成可貼的 code。
本週新增五處。
🔴 1. 三個 *_STALE 是同一件事(=自我測驗 Q5)¶
不重複展開。結論:抽出 Sourced[T]{value, source, fetched_at, ttl, fallback},resolve() 回 (值, Finding | None)。這是本週投報率最高的一項——三處已經各寫了一次,第四處(dc-19 泵的運轉狀態)下週就會來。
🔴 2. binding() 的簽章在本週被改了兩次,而前三張卡的驗收表全部失效¶
# dc-14 / dc-15 / dc-16 假設的
def binding(self) -> Dimension: ... # remaining 最小的那一維
# dc-17 要求的
def binding(self) -> dict[Resource, Dimension] # kW 不能跟 L/min 比大小
# dc-18 追加的前置條件
# converged=False 時 binding() 不得回報綠燈
dc-17 那一改是對的(跨資源比大小確實沒有意義),但它讓 dc-14、dc-15、dc-16 三張卡驗收表裡的 binding().name == "input_current" 這類斷言全部跑不過。
收斂建議(一次改到位,之後不用再動):
@dataclass(frozen=True)
class CapacityReport:
entity_id: str
dims: list[Dimension]
evaluated_at_env: SiteEnvironment | None = None # dc-17:沒有環境就不可複現
scenario: Scenario = "normal" # dc-16
converged: bool = True # dc-18
iterations: int = 0
residual_k: float | None = None
def binding(self) -> dict[Resource, Dimension]:
"""per-resource 取 remaining 最小者。跨 resource 不比較。"""
...
def worst(self, resource: Resource = "power_kw") -> Dimension:
"""舊行為的相容入口——dc-14~dc-16 的驗收表改呼叫這個。"""
return self.binding()[resource]
def status(self) -> Literal["green", "yellow", "red", "unknown"]:
if not self.converged:
return "unknown" # ★ dc-18:不收斂不得回綠
...
加 worst() 這個相容入口只要 3 行,而它讓前三張卡的驗收表繼續有效。 不做的話,下次回頭跑那些測試會以為是自己寫錯了。
🔴 3. Dimension 本週長了六個新欄位,但沒有一張卡回頭改前一張的建構子¶
逐卡累積:
| 卡 | 加了什麼 |
|---|---|
dc-14 |
name / remaining / used_pct / method / valid |
dc-15 |
method="measured";valid 第一次真的有用途(stale ≠ 0) |
dc-16 |
scenario |
dc-17 |
resource / unit;limit: float → limit(env) -> Bound |
dc-18 |
lower_limit(第一個下界維度) |
合併後的目標(可直接貼):
@dataclass(frozen=True)
class Dimension:
name: str # "input_current" | "bank" | "thermal" | "makeup_water" ...
resource: Resource # ★ dc-17
unit: str # ★ dc-17:"A" | "kW" | "L/min" | "U"
remaining: Bound | None # ★ dc-15/17:區間,不是點值;None = 這台沒有這一維
used_pct: float | None
method: Method # nameplate | measured | pole_count | prefix_sum
# | outlet_count | vector_sum | curve ← dc-17 新增
scenario: Scenario = "normal" # ★ dc-16
lower_limit: float | None = None # ★ dc-18:違反時 UNDERLOADED,處置方向相反
valid: bool = True # False = stale,不是 0
注意 lower_limit 不能塞進 remaining:上界違反要減少負載,下界違反要減少在線設備——處置方向相反,合併會讓自動化建議做出完全錯的事。
🟡 4. Bound 第三次被要求,而三處語意不同¶
| 出處 | 形狀 | 語意 |
|---|---|---|
W33 提出 → dc-10c 實作 |
Angle(deg, kind) |
同單位、不同 kind 禁止比較 |
dc-15 |
band() -> tuple[float, float] |
量測誤差帶 |
dc-17 |
capacity_kw() -> "Bound" |
一階近似的區間 |
三者都是「一個值加上它的不確定性」,但一個是值物件、一個是裸 tuple、一個只在型別註解裡出現過。
@dataclass(frozen=True)
class Bound:
lo: float
hi: float
unit: str
basis: str # "PMD0.2+CT0.5@15%" / "linear approx" / "vendor curve"
def conservative(self, direction: Literal["min","max"] = "min") -> float:
return self.lo if direction == "min" else self.hi
def __lt__(self, other: "Bound") -> bool:
if self.unit != other.unit:
raise TypeError(f"cannot compare {self.unit} with {other.unit}")
...
basis 那一欄是重點,它跟 derating_basis(dc-12)、accuracy chain(dc-15)、RatingPoint(dc-17)是同一個家族:「不能是列舉、要能指向來源」的欄位本週湊到第四個。 該考慮讓它們共用一個 Provenance 型別了。
🟡 5. 「模式欄位改變演算法」本週出現三次,形狀卻各不相同¶
| 卡 | 模式欄位 | 分岔了什麼 |
|---|---|---|
dc-14 |
wiring ∈ {delta_208, wye_380y220} |
line_currents():向量和 vs 直接相加 |
dc-16 |
psu_policy.hot_spare |
draw_on():平分 vs 全壓在 primary |
dc-17 |
mode ∈ {mechanical, free_cooling} |
排熱需求含不含壓縮機功 |
三處各寫一組 if。它們的共通點是這個欄位不是資料,是計算的前提——選錯不會報錯,兩個分支都會給出看起來合理的數字,而且沒有任何遙測會告訴你選錯了。
建議:不必立刻抽象成 Strategy(那是 W34 說的「抽象的不會被採納」那一類),但至少讓這類欄位在型別上可辨識,並強制它們有一條 validate() 規則:
# 最小可行版本:一個標記 + 一條共用規則
PREMISE_FIELDS = {"wiring", "hot_spare", "mode"} # 計算前提,不是資料
def check_premises(entity) -> list[Finding]:
"""前提欄位若來自預設值而非實際確認過的來源 → 吐 PREMISE_UNVERIFIED。"""
...
理由很實際:dc-14 的 wiring 答錯,整個機房的每相電流全錯;dc-16 的 hot_spare 答錯,A/B 平衡報表在報一個不存在的問題。這兩件事都不會有任何告警。
🔴 6. dc-16 的驗收表有一個算錯的數字(本週唯一「已經錯了」而非「待重構」的一項)¶
前面五項都是「型別該怎麼收斂」,這一項不同——它是一個現在就錯在卡片上的數字。
dc-16 驗收表寫:
10 kW / PF 0.99 = 10 101 VA
C_side = √3 × 208 × 24 = 8 646 VA
normal 每側 = 5 050 / 8 646 = 58.4% ← 不是 50.5%
failover = 10 101 / 8 646 = 116.8% ✔ 這個是對的
分母被誤用成 10 kVA 而非單側 derated 容量。照這張驗收表寫測試會直接紅,而它剛好落在最不該錯的地方——那一列的教學重點正是「normal 看起來還好」,58.4% 比 50.5% 更能撐住這個論點(它離 50% 更遠卻仍然綠燈)。
收斂建議(5 分鐘):改 dc-16 卡片那一格為 58.4%,並在測試裡加一條不變式而不是逐格核對:
# 平分政策下,failover 恰好是 normal 的兩倍。這條不變式能自動抓出整類分母錯誤。
assert used_pct(dev, "lose_b") == pytest.approx(2 * used_pct(dev, "normal"))
怎麼被抓到的值得記一筆:不是靠重算,是靠同卡內橫向核對——8 kW 那列是 46.7% / 93.5%(恰為兩倍),只有 10 kW 這列破了關係。W35 的自我修正(0.80 被修正兩次)與本週 dc-18 推翻 dc-17,都是下一張卡發現上一張卡;這是第一次由同一張卡內部的一致性抓到錯誤。
→ 建議把「同卡內數字的自我一致性檢查」加進 dc-daily-card SKILL 的收尾:凡是同一張表裡有兩列以上共用同一組公式的,收工前核對它們之間應該成立的比例關係。這比重算便宜,而且抓得到重算抓不到的東西(重算時你會用同一個錯誤的分母)。
優先序:
- #6 改掉
dc-16的 50.5% → 58.4% + 加不變式 — 5 分鐘。排第一不是因為它最重要,是因為它是本週唯一一個「已經錯在檔案裡」的東西,其餘五項都只是還沒做的重構。錯誤資訊留著會被後面的卡引用。- #2
binding()相容入口 — 3 行,讓三張卡的驗收表繼續有效。擋住其他任何改動的驗證。- #1
Sourced[T]— 三處合一,且dc-19下週就是第四處。投報率最高。- #3
Dimension合併 — 機械改寫,但要一次做完,否則dc-19會變成第六個版本。- W34 #1
energy_kwh()改名 — 連續第三週。10 分鐘。它是模型裡唯一會產生錯誤數字的項目,而且是靜默的。 若這週再不做,建議直接降級成「已知缺陷」寫進topic-01——一項連續三週排在前面卻不做的事,掛在清單上只會讓清單失去可信度。4
Bound/ #5 前提欄位標記 — 可以等,但Bound跟 #3 的remaining: Bound綁在一起,實際上會一起做。¶
本週該問 facility 的問題¶
五張卡共提出 15 個問題,去重後選 3 個下週真的拿去問人的。挑選標準沿用前五週:「現在問還來得及改,晚問就固化了」。本週三題的固化時點分別是——設計階段/隨時可能被改掉/採購規格。
Q1 — 問 機電設計單位 + 冰機/水塔廠商(⚠️ 設計階段,設備下單後就固化)¶
「設計濕球用的是哪個數字、哪一年的氣象資料、哪個百分位(0.4% / 1% / 2%)? 站址有沒有做過熱氣再循環修正? 水塔的廠商性能曲線(cold water temp vs 濕球 vs 水量)拿得到嗎? 冰機的冷凝器進水上限與蒸發器低溫保護設定值是多少?出廠值有沒有被現場改過? 最小負載多少?低負載靠變頻還是熱氣旁通?運轉策略是輪流開一台還是全部並聯?」
為什麼是這題,而且為什麼最急:dc-18 算出這座機房的臨界濕球是 4 格 32.1 °C/3 格 31.1 °C/2 格 29.2 °C——而台北的極端濕球就在 2 格那個數字附近。這三個數字的正確性完全取決於上面四個輸入:
- 設計濕球:卡片裡的 28 °C 是佔位符,明確標了「不要直接引用」。這個數字錯 1 °C,臨界濕球整條線跟著移。
- 性能曲線:拿不到就只能存一個銘牌數字,而那個數字一年裡大概只有幾小時是對的(
dc-17的線性近似自己標了「不可以拿去做設計或驗收」)。 - 35 °C 進水上限:
dc-18明寫這是「常見典型值,各機型不同,要跟廠商拿」。而紅燈判定完全建立在這個數字上——它是保護設定值,不是容量。 - 最小負載與運轉策略:
dc-18第 4 節指出三台並聯跑 136 RT 會讓每台只有 18%,低於離心機典型的 25–30% 最小負載 → surge 或熱氣旁通純燒電。這是前 17 張卡第一次出現「加冗餘反而讓事情變糟」,而它跟 N+1 的標準做法直接衝突。
這一題現在問還來得及影響選型與台數,設備進場後就只能接受。
Q2 — 問 伺服器團隊 + facility(要兩邊一起問)(⚠️ 隨時可能被改掉,而且改了不會有人通知)¶
「機櫃內的伺服器 PSU 冗餘政策是什麼?hot spare 開著嗎?primary PSU 是哪一顆? 現場有多少單電源設備?各接在哪裡?有沒有 rack ATS?型號與標稱轉換時間多少? A/B 兩側往上追,最近的共同祖先在哪一層?」
為什麼是這題:這是本軌跡第一個真相在別的部門手上的欄位,而且它會被改而設施完全不知情。
- Dell 的 hot spare 啟用時一顆 PSU 進睡眠、幾乎全部負載壓在 active 那顆。同一個 8 kW 機櫃,平分是兩側各 46.7%,hot spare +
Primary PSU = 1是 A 側 93.5%、B 側 ≈0。總量一樣,設施側看到的是完全不同的兩張圖。 - 若整櫃伺服器都用出廠預設
Primary PSU = 1,A 側天天貼著 93.5% 跑——而這個事實不在設施的任何一張表裡,它在 iDRAC。 - 單電源盤點越早越好:EPC 指出「Tier III 設計為了省錢砍掉 STS,後來才發現三分之一的機櫃是單電源」。而 rack ATS 不是等價替代——它只是把單點從電源路徑搬到 ATS 上,且 PSU 在 90% 負載時 hold-up 可能只剩 12 ms,餘裕縮到 4 ms。
- 第三問是 dc-10b 的老題目,但這次要對每一台伺服器跑(見間隔複習)。若答案是「同一台 UPS」,那機櫃裡所有雙電源設備的第二條線都只是裝飾。
這一題的答案有半衰期——問完要排定期輪詢,不是問一次就結案。
Q3 — 問 機電設計單位 + rack PDU 供應商(⚠️ 採購規格階段)¶
「機櫃內是 208 V line-to-line(delta)還是 220 V line-to-neutral(wye)?rack PDU 型錄給我。 rack PDU 的分路斷路器幾個、額定多少?進線導體線規多少? outlet-level 計量是哪一個 class(IEC 62053-21 class 1 還是只是「大概準」)?資料保存多久?」
為什麼是這題:
- 第一問答錯,整個機房的每相電流都是錯的,而且錯得看起來很合理(
dc-14誤解 1)。這是本週「前提欄位」問題最貴的一個實例。 - 第二問決定 binding 在哪,以及同一顆插頭是 35 A 還是 40 A。 同一個 CS8365C,3 個分路斷路器是 35 A、6 個是 40 A——差的是一個從外觀完全看不到的線規,而它值 1.1 kVA。型錄封面上不會有。
- 第三問延續 W35 Q3:沒有保存期就不能用實測法做容量規劃。順帶注意
dc-14記的那個坑:rack PDU 宣稱的 class 1(IEC 62053-21)與電錶的 class 0.2(ANSI C12.20)不可互相比較,兩套標準的 class 數字語意不同。
這週沒選上、但別忘記的¶
- 「對外報的 PUE 是 category 幾?量測點在哪顆錶上?用 ISO/IEC 30134-2 還是 Green Grid 的定義?」 後者綁量測頻率(Level 3 = 一年 ≥ 35 040 點),前者不綁(可以是 12 點)——對遙測儲存與輪詢設計差一個數量級。
- 「每顆錶的 CT 變比與精度等級表給我;初期負載下這些 CT 實際跑在額定的百分之幾?」 後半是殺手:CT 照滿載選,你讀它時機房是空的(60/400 = 15% 額定,誤差比銘牌差好幾倍)。
- 「Demand 用 fixed block 還是 rolling?區間幾分鐘?跟台電帳單對得上嗎?」 同一批原始資料,fixed 15 分鐘報 750 kW、rolling 報 1000 kW,差 33%。
- 「停電後冰機重啟時序是什麼?誰先起、間隔多久?回水太熱時會不會拒絕啟動或二次跳脫,實測過沒有?」 直接決定
dc-20儲冷槽要多大(5.2 分鐘 → 15 分鐘要 57 m³,近 3 倍)。順帶必問:泵在不在 UPS 上? 不在的話有儲量也送不到機房。 - 「補水從哪來?斷水時盆內存量撐幾分鐘?排污有沒有排放許可的水量/水質上限?」 這三問決定水這個資源的容量維度長什麼樣。
- 冷卻水塔清洗與檢驗頻率的地區差異(
dc-17分歧二):美規約每 90 天培養檢驗/每月清洗,台灣業界指引是每年至少一次、高風險半年一次、每季或每半年清洗消毒——頻率差一個數量級,不要把美規排程硬編進工單系統。 - W35 起就掛著、仍未問的:busway 吊裝位置環境溫度與廠商降載曲線、A/B 兩台 RPP 是否同櫃/同吊架、鋰電室樓板承重上限(W33 起)、STS 波形記錄保存期。
節奏¶
5 張卡 / 5 個工作日(8/31 一 ~ 9/4 五),本週是這條軌跡目前最平順的一週——沒有空窗、沒有補寫、沒有 lock 殘留、沒有重複卡片。W35 那條「拆卡當下必須同時往 backlog 插入新項目」的教訓本週沒有再被觸發(本週沒有拆卡,五張全部一次寫完,且四張落在 9457–9998 字元,貼著上限但都在範圍內)。
但這份週報本身遲到了。 排程的 datacenter-weekly-review(週日 10:00)在 9/6 沒有產出 2026-W36.md;本份是 datacenter-daily-card 在週日 21:20 執行時,依 SKILL 的「若今天是週日 → 改走週報流程」分支偵測到缺漏後補寫的。
建議(機制性的,跟 W34 的 lock 問題同一類):
dc-daily-card的週日分支目前是唯一的安全網,而它能運作純屬幸運——這條任務的 cron 設為週一至週五,9/6 這次執行是額外觸發的。應該在dc-weekly-review加一道自檢:開工先確認上週的週報檔案存在,不存在就先補上週的再寫本週的。 否則週報的斷鏈會安靜累積,而且沒有任何東西會通知你——這正是本週dc-14/dc-16反覆講的那種失敗模式(選錯前提不會報錯、儀表板全綠)。我們自己的基礎設施犯了跟卡片內容一模一樣的錯。
另外值得記一筆:本週五張卡有四張明寫「不要開新檔案,繼續長同一份 code」(dc-15 / dc-16 / dc-17 / dc-18)。這是 W35 連貫性檢視 #1、#2 產生的直接效果——一旦有了一份共同的 CapacityReport,後面的卡就會自動往上長。 這比任何抽象建議都有效,值得作為往後寫卡的預設做法。
下週¶
- 佇列下一張:
dc-19一次側/二次側冰水泵。dc-18已經先欠了它一個問題:「泵在不在 UPS 上」決定 ride-through 是 5.2 分鐘還是 0。而dc-19會是Sourced[T]的第四個使用者(泵的運轉狀態),所以連貫性檢視 #1 與 #2 請在動筆之前做完——現在是 20 + 3 分鐘,dc-19寫完再做就是六張卡一起改。 energy_kwh()改名連續第三週掛在第一順位卻沒做。 10 分鐘。它是模型裡唯一會產生錯誤數字的項目,而且是靜默的。若下週再沒做,建議直接從佇列裡撥半天出來清一次技術債,不要再往後推。- 冷卻鏈可以預期跟電力鏈一樣的拆法(見「串起來」第三節)。
dc-18已經冒出兩條不在六格裡的線:冰機重啟時序(時間軸,跟dc-05c的測試制度同類)與水處理/退伍軍人桿菌合規(制度,跟dc-09c的消防合規同類)。建議現在就在 backlog 預留位置,不要等到寫的時候才發現裝不下——這正是 W35 記取的教訓。 - ⚠️ commissioning 隨時可能開始。 本週為現場驗收單加了兩項:(a)rack PDU 的 wiring 與分路斷路器實地確認(
dc-14,錯了整個機房每相電流全錯)、(b)冰機停電重啟實測,含回水溫過高時的二次跳脫行為(dc-18,Cundall 的實測經驗指出這才是真正的失效模式)。連同 W32 Q3(ATS 五個計時器、NFPA 110 分段時序記錄)、W33 Q2(ZSI 注入電流測試、tie 閉合互鎖、arc flash 標籤)、W34 Q3(STS 演算法、抑制門檻、latched reset 權限)、W35 Q2(兩源實際相位差 + 手動轉換實測)——這六份清單合起來就是現場驗收單。W35 就建議整理成一頁帶去現場,本週再提一次。 - W37 的間隔複習:抽 W35 的卡(
dc-10b~dc-13)+ W33 的卡(dc-06~dc-09)。