跳轉到

2026-W37 週報:binding 搬出設備的那一週

第七份週報,本週 5 張卡、5 個工作日(9/7 一 ~ 9/11 五),沒有空窗、沒有補寫、沒有重複卡片。冷卻鏈從冰機往下走完了泵、儲冷槽、熱交換器、末端空調——第二輪的骨幹在這一週接通了。

但這週真正該記的不是接通,是「擋住你的那個東西」一張一張搬離了設備本身

binding 是誰 它住在哪
dc-19 冰水泵 系統曲線與泵曲線的交點 管路(不是泵)
dc-19b NPSH NPSHa(Q) 與 NPSHr(Q)+margin 的交點 土建(泵在幾樓)
dc-20 儲冷槽 Fr 還是 Re——看你採哪套判準 一份文件的選擇
dc-21 板式 HX 門檻濕球 = f(冰水設定值) IT 部門(機櫃進風上限)
dc-22 CRAH 回風溫度 = f(封閉品質) 營運習慣

五張卡的 binding 依序是:管路 → 土建 → 判準 → 別的部門 → 營運習慣。沒有一個在銘牌上。

W36 的結論是「容量是在一組條件下解出來的值」。本週把那句話的後半段挖開了:那些條件的擁有者,多半不是設施工程師。

本週卡片

標題 這張卡最關鍵的一個事實
dc-19 一次側/二次側冰水泵 兩台泵並聯只給 1.14 倍流量(87.3 vs 相加的 152.9 L/s,高估 75%),而電多吃 37%。系統阻力隨流量平方爬,多開一台就把每台推回曲線左邊
dc-20 儲冷槽與 ride-through 存得下 400 kWh,卻只放得出 480 kW。 細高槽能量維度 100%、功率維度 334%——不是撐不到 15 分鐘,是撐 0 秒。kWh 與 kW 之間比大小沒有意義
dc-19b NPSH 與泵的擺放高度 同一顆泵、同一張單線圖,放地面層 vs 放屋頂,最大可運轉流量是 170.4% vs 100.5%。 前 20 張卡沒有一張需要知道設備在幾樓
dc-21 板式熱交換器與免費冷卻 free cooling 小時數不是氣候的函數,是冰水設定值的函數。 同一座台北機房:7 °C 冰水門檻濕球 1 °C(全年 0 小時)、18 °C 冰水門檻 12 °C
dc-22 CRAH 機房空調(冰水式) 回風 23.9 → 29.4 °C,同一台機顯熱 +42%(228 → 323 kW),零採購。 而型錄「75 °F 回風」那列的招牌數字,本身就是一間旁通 43% 的機房

串起來

一、把五張卡放回同一條水路上

        ┌──────────── dc-21 板式 HX(並聯在冰機旁,free 模式時取代它)
冰機 ───┴──→ dc-19 一次側泵 ──→ [共通管 / dc-20 儲冷槽] ──→ dc-19 二次側泵
 ↑                                                              │
 └─ 冷卻水泵(dc-19b 的主角:開放迴路、自由液面)                  ↓
                                                        dc-22 CRAH 盤管
                                                    高架地板 → 機櫃進風

dc-19b 不在這條鏈上,它是鏈上每一顆泵的安裝條件。這是本週第一個結構性的新東西:前 20 張卡的關係都是「誰接誰」,dc-19b 問的是「它在幾樓」。

二、本週最值得記的一件事:卡片開始互相餵數字

dc-18 上週解聯立算出「濕球 30 °C、水塔 2 格」時冷卻水會停在 35.8 °C,那個數字當時的用途是「超過冷凝器進水上限 35 °C → 高壓跳脫」。

四天後,dc-19b同一個 35.8 °C 當成輸入丟進 NPSHa 算式:

32.0 °C → Pv/ρg = 0.49 m      (正常運轉)
35.8 °C → Pv/ρg = 0.61 m      (dc-18 解出的擾動平衡點)
屋頂配置 NPSHa = 10.39 + (−1.2) − 1.5 − 0.61 = 7.08 m
margin = 7.08 − 6.0 = 1.08 m   ← 判準 max(1.0, 0.1×6.0) = 1.0 m,剛好擦邊

跳脫門檻與汽蝕門檻,共用同一個解出來的水溫。dc-18 寫那張表的時候,完全沒想到那個數字會變成泵的輸入。

這對模型的意涵比對知識的意涵更大:SiteEnvironment 之外,還有一層「解出來的中間狀態」需要被存下來並被多方消費(承 dc-17 立的站點級外生變數)。T_cw_equilibrium 不是遙測值、不是設定值,是計算結果——但它同時是冰機保護判定、泵的 NPSHa、水塔用率三處的輸入。算完就丟,第二個消費者只能再算一次;而兩次的前提不見得一樣。

三、掉一個會連鎖到哪:本週的主連鎖,橫跨五張卡

這是本週最該畫出來的一條線,它把五張卡全部串起來,而且每一節都有數字:

外界濕球回升,超過 exit_wb_c
  → 控制系統從 free 切回 mechanical            (dc-21:第一個帶記憶的約束)
    → 冰機重啟需要 10–15 分鐘                  (dc-18)
      → 這段時間靠 ride-through 撐
        → 環路熱慣量只有 5.2 分鐘 → 需要儲冷槽  (dc-20)
          → 但細高槽的功率維度是 334% → 撐 0 秒(dc-20:能量 ≠ 功率)
          → 且若昨天做過放電測試 → recovery_until 尚未到 → 容量是降級的
        → 水要流動才拿得到,泵必須在 UPS 上
          → UPS 負載 1600 → 1690 kW(+5.6%),runtime 10 → 9.5 分鐘(dc-19)
          → 而冷卻水泵若擺在屋頂,擾動水溫 35.8 °C 下 margin 只剩 1.08 m(dc-19b)
        → 就算冰水送到了,CRAH 風扇不在 UPS 上
          → 冷量交不到伺服器手上                (dc-22:最後一棒)

七個環節,沒有任何一個設備故障。 觸發它的只是外面的濕球回升了一度、而控制系統做了一個它被設定去做的動作。

三個各自獨立的觀察:

  1. dc-21 讓「切換」本身變成故障源。 前 20 張卡的故障都是設備壞掉或環境超標;模式切換是控制系統的正常行為,而它開了一個 10–15 分鐘的脆弱窗口。這也是為什麼 ModePolicyenter_wb_c ≠ exit_wb_c 不是效率優化,是可用性設計——濕球在門檻附近抖動一天切十次,就是一天開十次窗口。
  2. dc-20recovery_until 在這條鏈上第二次派上用場。 容量第一次是路徑的函數:昨天做了什麼會改變今天還剩多少。而放電測試——那個唯一能證明儲冷槽有效的動作——本身就製造一模一樣的窗口。dc-09 電池容量測試的悖論完全同構(見間隔複習)。
  3. 鏈的最後一節是 dc-22 而不是冰機。 前面四張卡把冷量一路送到盤管,dc-22 說:kW 到了不代表送得進機櫃。Uptime 的原話是被動排熱設備「不可能排掉比 CRAC 送來的冷風更多的熱」——風量是與 kW 完全獨立的第二條約束,而缺口會由伺服器吸自己的排氣補上,容量報表全綠。

四、「多一台」這週被打了三次,方向各不相同

這是本週橫向比較最乾淨的一組:

加什麼 結果 為什麼
dc-19 並聯第二台泵 流量 +14.2%、電 +37% 系統阻力 ∝ Q²,揚程從 30 爬到 36.1 m
dc-19b 並聯泵(NPSH 角度) NPSHa 一起變差 共用吸入母管流速上升,h_f 變大
dc-20 把槽做大一倍 冗餘完全沒增加 兩倍大的槽仍是單一容器
dc-22 加第五台 CRAH 每台容量下降 回風被混得更冷,limit 是回風溫度的函數

四種失敗方式,四種不同的物理。共通點是同一件事:把冗餘設備的銘牌值當成可加量。 這在電力側已經犯過一次(dc-16 記下的 NetBox 斷點:雙電源設備兩個 power port 各填 500 W,機櫃顯示 1000 W),本週在水側與風側又各犯一次。

→ 直接後果:Dimension.aggregation 從 W36 的 3 種(sum / vector_sum / parallel_pump)長到 5 種,而 dc-22 的第五種連名字都還沒取(共用靜壓箱耦合)。程式裡任何一處寫死 sum(...) 都是還沒被發現的 bug——這句話 dc-19 已經講過,本週它又多了兩個實例。

五、dc-22 立的那個分界值得單獨記:自變數的四級階梯

把 W36 到本週的四個容量自變數排在一起,會看到一條很清楚的階梯:

自變數 誰決定它 模型能拿它怎樣
dc-16 scenario(故障情境) 沒有人,是意外 只能枚舉
dc-17 env(濕球) 天氣 只能觀測 + 用設計值規劃
dc-21 mode(運轉模式) 控制系統 可以選,但要帶遲滯與駐留
dc-22 return_air_c(回風溫度) 營運習慣——封閉、盲板、地磚開孔率 規劃階段量不到,只能假設

最後一級是質變。前三個要嘛可以觀測、要嘛可以選擇;回風溫度在機房還沒蓋好時根本不存在,而全廠的 CRAH 容量表就建在它上面。

所以 CapacityReport.assumed_return_air_c 與它的 basismeasured / assumed_containment)不是可有可無的記錄欄位——沒有它,沒有人知道那張表是按哪種封閉品質算出來的。 而一張按 23.9 °C 選型的表,本身就內建了 43% 旁通的假設(見 dc-22 演算一:BP = (32.5 − 23.9)/20 = 0.43,從風量比 1.75 獨立驗算吻合)。

六、本週母題

週次 母題
W31 單一欄位裝不下一個事實(數字要帶著量測條件)
W32 有些事實根本不住在欄位裡
W33 上限是多候選取 min,裸數字丟掉了最有用的資訊
W34 判定不是事實的屬性,是事實 × 判準——而判準是版本化的資料
W35 「還剩多少」有多種型別,而鏈上要跨它們取 min
W36 容量是在一組條件與情境下解出來的值——而條件會被結果改變
W37 binding 不住在設備裡。「還剩多少」的答案,擁有者常常在別的部門、別的專業、別的文件裡

自我測驗

Q1(事實回憶). 設計流量 76.4 L/s 的冰水泵,並聯第二台。總流量是多少?順便說明為什麼「N+1 台泵」不等於「N+1 倍流量餘裕」。

答案

87.3 L/s,不是 152.9 L/s。

系統曲線 H = 10 + 0.003422 Q²、單台泵曲線 H = 39 − 0.001540 Q_p²,兩台並聯時 Q = 2Q_p

39 − 0.001540 Q_p² = 10 + 0.003422 × (2Q_p)²
29 = 0.015228 Q_p²   →   Q_p = 43.6 L/s
總流量 = 87.3 L/s(+14.2%),揚程從 30 爬到 36.1 m
每台功率 19.3 kW,兩台 38.6 kW(+37%)

流量 +14%、電 +37%。 相加銘牌值(152.9)高估實際 75%

機制:系統阻力隨流量平方上升,流量一多揚程就爬,把每台泵推回曲線左邊——每台只跑 57% 的設計流量,已經偏離最佳效率點(所以 38.6 kW 還是樂觀值)。

台數冗餘保的是「壞一台還有流量」,不是「流量加倍」。 這兩件事在電力側常常重合(兩台變壓器確實給兩倍 kVA),在水側完全不重合——而這正是把電力側直覺搬到水側最容易踩的坑。

順帶一提 dc-19b 補的那半:並聯還會讓共用吸入母管流速上升、h_f 變大,所以每台的 NPSHa 一起變差。加台數在水側同時傷害流量效率與吸入條件。

Q2(事實回憶). 老闆問:「隔壁機房 free cooling 一年跑 2000 小時,我們一小時都沒有,是不是水塔選小了?」你怎麼回?把公式和兩個數字寫出來。

答案

先問對方的冰水供水設定值,不要先談設備。

門檻濕球 = T_chws − a_tower − ΔT_load × (1−ε)/ε

取塔 approach 4 K、負載側 ΔT 6 K、HX 效能 ε = 0.75(第三項 = 2.0 K):

冰水設定 門檻濕球
7 °C(傳統) 1 °C ← 台北一年 0 小時
13 °C 7 °C
18 °C(高溫水) 12 °C ← 冬季可觀

塔加大只能把 a_tower 從 4 壓到 2,門檻往上 2 K;把冰水從 7 拉到 18 是 11 K。 差了五倍以上的槓桿,而且前者要花錢、後者只是改一個設定值。

但那個設定值不是設施能單方面改的:T_chws 由盤管選型決定,盤管選型由機櫃進風溫度上限決定,而進風上限的擁有者是 IT(ASHRAE class)。這是「設施 vs IT 管理平面」在本軌跡的第三次穿越(前兩次:dc-16 的 iDRAC psu_policydc-19 的 BMS 流量變化率)。

最刺的一句在 dc-21 對資料模型 #3:IT 把機櫃進風上限從 27 °C 收到 22 °C,會直接砍掉整年的 free cooling,而沒有任何一張設施表會顯示這件事發生過。

對模型free_cooling_hours 不能是站點屬性,它是 chws_setpoint 的函數;而 chws_setpoint 要帶 derived_from(ASHRAE class + 盤管選型)與 changed_by。順帶:髒污讓 ε 從 0.75 掉到 0.68,門檻就下修 0.8 K——在台北那條本來就很窄的窗口裡,0.8 K 可能就是整個一月

Q3(應用). 同一顆冷卻水泵、同一組型錄數字、同一張單線圖。放在地面層與放在屋頂跟水塔並排,最大可運轉流量各是多少?為什麼 dc-19 整張卡都沒提這件事?

答案

170.4% vs 100.5%。

NPSHa = Patm/ρg + Z_static − h_f − Pv/ρg
NPSHr(r) = 6.0 r²   ;   margin 判準 = max(1.0 m, 0.1 × NPSHr)

A 地面層  Z = +18.0 m、h_f(r=1) = 3.0 m、水 32 °C
          NPSHa(r=1) = 24.89 m,margin 18.9 m
          高流量時 0.1×NPSHr 反超 1.0 m → 判準換分支 → r ≤ 1.704

B 屋頂並排 Z = −1.2 m、h_f(r=1) = 1.5 m、水 35.8 °C(dc-18 解出的擾動點)
          NPSHa(r=1) = 7.08 m,margin 1.08 m
          r ≤ 1.005   ← 而 r = 1.1 時 margin = −0.50 m,直接汽蝕

為什麼 dc-19 沒提:那張卡講的是密閉冰水迴路。高程沿環路互相抵消,NPSHa 由膨脹水箱的定壓值決定——200 kPa g、7 °C 水 → 30.6 m,怎麼配都過。開放迴路(冷卻水塔的集水盤是自由液面)沒有這個保護,NPSHa 直接就是「水面比泵高多少」減掉摩擦。

密閉迴路唯一會出 NPSH 事故的方式是接錯邊:膨脹水箱接在出口側時,泵自身的揚程要從吸入壓力裡減掉——定壓 50 kPa g、揚程 30 m → 吸入絕對水頭 −14.6 m,物理上不可能,水在泵入口就閃蒸。

對模型,三件事

  1. Device.elevation_mdatum_ref——前 20 張卡沒有一張需要知道設備在幾樓。拓撲回答「誰接誰」,NPSH 回答「它在幾樓」。第三輪的空間層級(dc-28)被提前需要了。而且基準要定義清楚(泵中心線?底座?),冷水盤要記運轉水位不是溢流水位。
  2. max_flow 是解出來的,不是查出來的——Limit.basis = "npsh_crossover"solved=True。NPSHa(Q) 遞減、NPSHr(Q) 遞增,交點才是上限,而它同時依賴高程、h_f、水溫。dc-17limit(env)dc-19Limit.basis 在這裡第一次疊在同一個維度上,而且 margin 判準本身會換分支,所以 basis 要記到判準層級
  3. 搬泵的機會只有一次。 把 NPSHr 從 6.0 壓到 4.5(換泵)只把上限推到 1.12;把泵從屋頂搬到地面直接變 1.70。這是選型解決不了的土建問題。

Q4(應用). 一間機房的 CRAH 容量報表全綠,機櫃卻在過熱。你的模型少了哪一個維度?把 dc-22 情境 C 的判斷寫出來,並說明為什麼「加第五台 CRAH」會讓事情更糟。

答案

少了 resource = "air_flow"

dc-22 情境 C:回風 29.4 °C、一台機跑 45% 轉速。

  • heat 維度:limit 是查回風溫度得到的(29.4 °C → 323 kW),實際負載 228 kW → 仍在 limit 之內,綠燈
  • air_flow 維度:45% × 16.52 = 7.4 m³/s,而 228 kW 的 IT 負載在 20 K 溫升下需要 228/(1.21×20) = 9.42 m³/s → 風量比 0.79 < 1.0,違規

binding() 只回一個值,這間機房會是綠的。 而缺口不會消失,它由回流(recirculation)補上——伺服器吸自己的排氣。Uptime 講得很白:被動排熱設備「不可能排掉比 CRAC 送來的冷風更多的熱」。

為什麼加第五台會更糟:CRAH 的 limit 是回風溫度的函數。多一台機吹出來的冷風,在旁通 43% 的機房裡有很大一部分直接回到機組——回風被混得更冷 → 每台的 sensible_limit_kw 下降。總容量的增幅小於一台的銘牌值,這是 Dimension.aggregation 的第五種,不是 sum

反過來,正確的動作是把回風弄熱:封閉、盲板、堵地磚。同一台機從 23.9 → 29.4 °C 回風,顯熱 228 → 323 kW(+42%),零採購;而且封閉之後同樣 228 kW 只需要 0.71 台,風扇轉速降到 71%,功率約剩 36%。

兩個模型欄位

  • 房間層級的 AirBalance(bypass, recirculation, balance)——注意它推導不出任何設備的銘牌,只能從三個溫度算:BP = (T_exhaust − T_return)/(T_exhaust − T_supply)。這是第一個「不屬於任何設備」的容量實體。
  • MeasurementPoint.role = control | compliance——ASHRAE 明文規範只針對進入 IT 設備的空氣,機殼內、排氣、回風、送風靜壓箱的量測「與 IT 設備的運作與可靠度無關」。CRAH 回風全綠與某一櫃頂進風 38 °C 完全相容。 告警建在 CRAH 讀數上,會對熱點永遠沉默。

順帶一個本週最容易被誤用的數字:兩份型錄都寫 net sensible,意思不一樣。Vertiv 註腳明寫已扣風扇熱(可從水側獨立反推 14–15 kW,兩列吻合);Uptime 附錄 C 註記「reduced by 7.5 kW × 3 = 22.5 kW for fans」——標 90 kW 的機實際只有 67.5 kW,差 25%。capacity_basis 是第三個「不能是數字、要能指向一份文件」的欄位(前兩個:dc-12derating_basisdc-15accuracy)。

Q5(建模判斷). 本週五張卡的 binding 沒有一個住在設備裡。你的 CapacityReport 要多存什麼,才能回答「現在擋住我們的是誰、那個限制的擁有者在哪」?

答案

這是本週投報率最高的一項,而且它不是加欄位,是換問題。

目前 binding() 回答的是「哪一維最緊」。本週五張卡證明這個答案不可行動——知道 binding 是 max_flow 沒有用,要知道那個 max_flow誰定的、依據哪份文件、改它要動誰

把五張卡的 binding 攤開:

binding 維度 basis 擁有者 要改它得動什麼
dc-19 max_flow system_curve 機電設計 管路(改不動)
dc-19 min_flow 廠商文件 + 50% 地板 冰機廠商 查表,不能外推
dc-19b max_flow npsh_crossoversolved=True 土建 泵的標高(只有一次機會)
dc-20 功率 froude_0.5 reynolds_2000 判準的選擇 Fr 擋 → 加大開口 h;Re 擋 → 只能加長 L
dc-21 HX approach + 塔格數 mode=free 下的拓撲 控制系統 ModePolicy 的門檻
dc-22 air_flow assumed_containment 營運 盲板與地磚(不是採購)

dc-20 那一列是最刺的:同一個矮胖槽,Fr ≤ 1.0 時 binding 是 Re(1 116 kW,143%),Fr ≤ 0.5 時 binding 是 Fr(884 kW,181%)。兩者的處置方向相反——Fr 擋住可以加大開口(Fr ∝ h^−1.5),Re 擋住只能加長擴散器(Re 與 h 無關)。選錯 basis,錢會花在改不動的地方。

收斂建議(可直接貼;沿用 dc-19Limit 但補完三個欄位):

from dataclasses import dataclass
from typing import Literal

Owner = Literal[
    "facility_mep",      # 機電設計
    "civil",             # 土建(dc-19b:標高)
    "vendor",            # 廠商文件(dc-19 的 min_flow)
    "controls",          # BMS / 控制序列(dc-19 rate limiter、dc-21 ModePolicy)
    "it",                # IT 管理平面(dc-21 的 chws_setpoint、dc-16 的 psu_policy)
    "operations",        # 營運習慣(dc-22 的封閉品質)
    "criterion",         # 判準本身就是選擇(dc-20 的 Fr 0.5 vs 1.0)
]

@dataclass(frozen=True)
class Limit:
    value: float
    unit: str
    basis: str                  # "system_curve" | "npsh_crossover" | "froude_0.5" ...
    owner: Owner                # ★ 新增:擋住我們的是誰
    source: str                 # 文件編號 + 版本,或 "solved"
    solved: bool = False        # ★ dc-19b:這個值是算出來的不是查出來的
    remediation: str = ""       # ★ dc-20:要改它得做什麼(Fr → 加大 h;Re → 加長 L)

三個具體後果,不加會怎樣:

  1. 沒有 owner,容量報表產不出工單。 本週六個 binding 分屬六個不同的單位,其中三個(IT、營運、判準)設施側完全無法單方面改動。一張說「binding 是 air_flow」的報表,工單只能派給設施;正確的收件人是負責裝盲板的人
  2. 沒有 remediationbasis 只是個字串。 dc-20 證明了 basis 改變的是改善動作而不只是數字——這是 Limit.basisdc-19 立的)第一次有這個性質,而目前的定義裡 basis 只是一個註記。
  3. 沒有 solved,你分不出「查出來的上限」與「解出來的上限」。 後者會隨環境漂移(dc-19bmax_flow 同時依賴高程、h_f、水溫),快取它等於快取一個會過期的值;前者不會。兩者長得一模一樣,都是一個 float。

不該做的一件事:不要把 owner 做成組織架構表的外鍵。它要回答的是「這個數字的真相住在哪個管理平面」,跟誰現在坐在哪個部門無關——組織會重整,而 chws_setpoint 的真正擁有者永遠是決定機櫃進風上限的那個人。

間隔複習

本週抽兩週前(W35)與四週前(W33)各一張。

週次 抽兩週前 抽四週前
W35 W33 的 dc-07b W31 的 dc-03b
W36 W34 的 dc-10 W32 的 dc-05b
W37(本週) W35 的 dc-10b STS 兩源拓撲獨立性 W33 的 dc-09 UPS 電池組
W38 W36 的卡(dc-14 ~ dc-18 W34 的卡(dc-09b ~ dc-10

兩張都不是隨機抽的:本週各有一張卡把它們的結論搬到了水側,而且搬過去之後才看得出原來的結論哪一部分是通用的、哪一部分只是電的性質。

抽 W35 的 dc-10b STS 兩源關係(一)拓撲獨立性與雙母線容量會計(2026-08-24,20 天前)

複習題. dc-10b 說「共同祖先永遠存在,問題只在它在第幾層」,並要求 lowest_common_ancestor() 在電力樹與空間樹上各跑一次。本週出現了第三棵樹嗎?另外,dc-10b 說「per-bus 上限是枚舉出來的不是查表查來的」——本週哪兩張卡在水側與風側犯了同一類錯?

答案

第三棵樹出現了,而且是 dc-19b 順手提到的一句話。

dc-19b 冗餘那一格寫:「備援泵放同一個吸入坑就是共同故障點。」 那就是水力樹上的 LCA,而且它跟空間樹的 LCA 一樣——在單線圖上完全看不見

電力樹 LCA(dc-10b)  → 意義:故障域邊界
空間樹 LCA(dc-09c)  → 意義:消防聚合範圍
水力樹 LCA(dc-19b)  → 意義:吸入條件的共同來源

第三次驗證了 dc-10b 對資料模型 #3 的那個要求:遍歷邏輯必須參數化「走哪一種邊」,不能把 upstream_id 寫死。 三棵樹、同一個演算法、三種不同的意義。

dc-21 還給了第四種形狀,而且更奇怪:HX 本體不在電力樹上(純被動、不吃電),但它的切換閥與致動器在。 所以 lose_a 傳不到設備本身、卻能讓它卡在錯誤的模式——fault_domain 要指向閥的電源而不是設備本身。這是「橫向邊」到目前為止最不直觀的一種。

第二半:「用數量冒充容量」本週犯了兩次。

dc-10b 的原話是 per-bus 上限不是常數 50%,是拓撲的函數,必須枚舉配置取 max。本週的兩個同類錯誤:

dc-10b(電) dc-19(水) dc-22(風)
天真做法 兩條母線各記 50% 兩台泵流量相加 五台 CRAH 容量相加
實際 152 kW 不是 140(dual-PSU 單邊 uplift 10%) 87.3 不是 152.9 L/s(高估 75%) 每台 limit 下降(回風變冷)
為什麼 冗餘動作本身改變了負載 冗餘動作本身改變了運轉點 冗餘動作本身改變了自變數

三者的形狀完全一樣:加上冗餘這個動作,改變了計算容量時的前提。 而三次的機制完全不同(PSU 效率曲線、系統阻力平方、回風混合),所以沒辦法用一個係數打折——只能是 aggregation 這個欄位

dc-10b 那句「is_redundant: bool 存下來就會在有人改接線那天靜默說謊」,在水側的對應版本是 dc-19 那句「程式裡任何一處寫死 sum(...) 都是還沒發現的 bug」。同一個教訓,兩種語言。

抽 W33 的 dc-09 UPS 電池組(VRLA vs 鋰電)(2026-08-14,30 天前)

複習題. dc-09 說「容量是一條曲線不是一個數字」。dc-20 的儲冷槽把同一件事又講了一次——但儲冷槽多了什麼是電池沒有的?這個差別會讓兩者的資料模型長得不一樣嗎?

答案

儲冷槽就是冷的電池——直到你問它的功率上限從哪來。

先看相同的地方,多到值得列表:

dc-09 電池 dc-20 儲冷槽
容量是曲線 discharge_rating: [(分鐘, W/cell)] usable_fraction 是幾何的函數(85% vs 62.5%)
高率打折 Peukert k ≈ 1.25 Fr 推高 → thermocline 變厚 → 下次能用的變少
沉默故障 浮充三年,斷電那秒才知道 穩態運轉毫無異狀,事故當天才發現
唯一的證明方式 容量放電測試 放電測試
測試悖論 那 30 分鐘是全年 UPS 最沒有保護的時候 充回要數小時,期間 ride-through 降級
冗餘的陷阱 三串並聯掉一串 ≠ 還有 2/3 槽做大一倍 ≠ 冗餘增加

測試悖論那一列是完全同構的——連「唯一能證明它有效的動作,本身就是它最脆弱的時候」這個句子都可以原封搬過去。dc-20 把它形式化成了 CapacityReport.recovery_untildc-09 當時沒有這個欄位。→ 回頭補:電池容量測試期間的 UPS CapacityReport 也該帶 recovery_until,這是本週對舊卡最便宜的一個回饋。

關鍵差別:兩個約束的來源。

電池的功率上限與能量上限同源——都從同一張恆功率放電表讀出來(w_per_cell_at(minutes))。查一次表同時得到「能放多大」與「能放多久」,所以一條 discharge_rating 曲線就夠了。

儲冷槽的兩者來自完全不同的物理

能量:E = V × ρ · c_p · ΔT × usable_fraction     ← 熱力學,看體積
功率:由入口 Froude 數與 Reynolds 數限制          ← 流體力學,看擴散器幾何

所以細高槽可以能量 100%、功率 334%:存得下 400 kWh_th,擴散器卻只放得出 480 kW。不是撐不到 15 分鐘,是撐 0 秒。 電池不會發生這種事——你不可能買到一顆「充得飽但放不出來」的電池,因為兩個數字是同一張表給的。

對模型的結論很硬dc-20 要求 Dimension 新增 kind = power | energy,而 binding() 在 per-resource(dc-17)之上再加 per-kind。kWh 與 kW 之間比大小沒有意義,硬壓成一個 capacity 欄位,細高槽那個案例會顯示綠燈。

而電池其實也需要這個欄位——只是因為它的兩個維度同源,用一條曲線混過去了。dc-09 對資料模型 #5 寫「energy_kwh 是衍生欄位但必須物化」,因為消防(NFPA 855 每防火區能量上限)、樓板承重、運輸法規全部用 kWh 計,而放電設計用 W/cell。那其實就是 kind 這一維的雛形,只是當時沒認出來。

回頭補的第二件事BatteryString 也該吐兩個 Dimensionkind=powerdeliverable_kwkind=energyenergy_kwh),而不是一個曲線加一堆衍生 method。這樣電池與儲冷槽在 binding() 眼裡就是同一種東西。

順帶dc-09energy_kwh() 改名這件事連續第四週掛在優先序上沒做(見下一節)。而上面這個「應該吐兩個 Dimension」的建議,如果先做了改名,只要 10 分鐘;現在要連同 kind 一起改。技術債的利息是複利的,這是實例。

本週的 model code 連貫性檢視

先結算 W36 的六項。本週的結算結果值得停下來看一下,因為它推翻了我們立了三週的那條規律。

來源 項目 W36 預估 狀態
W36 #1 改掉 dc-16 的 50.5% → 58.4% + 加不變式 5 分鐘,排第一 🔴 完全沒動。 dual-corded-equipment.md 四處仍是 50.5%(第 70、128、198、209 行)
W36 #2 binding() 相容入口 worst() 3 行 🔴 沒做,而且簽章本週又被改了兩次dc-20 的 per-kind、dc-21 的 per-mode)
W36 #3 Sourced[T] 三處合一 20 分鐘,「dc-19 就是第四處」 🔴 沒做。dc-19 果然是第四處,而且手寫了兩份不同形狀(見新增 #3)
W36 #4 Dimension 合併(8 欄位版) 機械改寫 🔴 比沒做更糟dc-20 重新定義了一個 6 欄位、欄位名不同的 Dimension(見新增 #1)
W34 #1 dc-09energy_kwh() 改名 10 分鐘 🔴 連續第四週
W36 #6 Bound / 前提欄位標記 可以等 ⚠️ 仍未動

六項全紅,包括那個 5 分鐘的。

而 W34 立、W35 與 W36 各驗證一次的那條規律——「具體到可以直接貼進 code 的建議會被採納,抽象的不會」——本週失效了。W36 六項全部寫成了可貼的 dataclass,六項全部沒被採納。

修正後的規律,證據在本週五張卡裡

可貼的 code 會被採納,但只被「下一張卡」採納,而下一張卡會再貼一份自己的。

本週五張卡的動手練習區塊全部寫著「接昨天的」:

dc-19  「繼續同一份 code」        → 接 dc-18
dc-20  「昨天 dc-19 做出了 …」    → 接 dc-19
dc-19b 「接昨天 dc-20 的 Dimension」→ 接 dc-20
dc-21  「接 dc-19b 的 Dimension / Limit」→ 接 dc-19b
dc-22  「延續 dc-21 的 per-mode binding()」→ 接 dc-21

五張卡形成了一條乾淨的繼承鏈,而週報不在那條鏈上。 W36 的收斂建議寫得再具體,也沒有任何一張卡引用它——因為每張卡引用的是前一張卡。W36 觀察到「四張卡明寫不要開新檔案」是有效的,那個觀察是對的;錯的是推論——有效的不是「寫成可貼的 code」,是「住在鏈上」。

本週最重要的建議,而且它是機制性的:把收斂結果寫進一張 datacenter/topics/model.md 主題卡,當成模型的單一真相來源,並在 dc-daily-card 的練習區塊模板裡把「接昨天那張卡」改成「topics/model.md,並在卡片末尾把今天的修改 append 回去」。

⚠️ 這會動到佇列topics/ 目前明寫「排在第五輪,等前四輪設備卡跑完,目前尚無」。但模型的不一致已經是現在就在擋路的東西(見下面新增 #1 與 #2),不是第五輪的問題。建議把 topic-01(容量語意)提前開,只寫 code 不寫散文,讓它當鏈的頭。這是取捨,不是自動可以做的決定——留給使用者裁決。


本週新增六處。

🔴 1. Dimension重新定義了,而不是被擴充——現在有兩個互不相容的版本

W36 給的收斂目標(8 個欄位):

@dataclass(frozen=True)
class Dimension:
    name: str; resource: Resource; unit: str
    remaining: Bound | None
    used_pct: float | None
    method: Method
    scenario: Scenario = "normal"
    lower_limit: float | None = None
    valid: bool = True

dc-20 動手練習實際貼出來的(6 個欄位,非 frozen):

@dataclass                      # ← 少了 frozen=True
class Dimension:
    name: str; resource: str
    kind: str                   # ← 新增(對的,這是 dc-20 的貢獻)
    unit: str
    value: float                # ← 取代了 remaining: Bound
    limits: list[Limit]         # ← 取代了 lower_limit,也吞掉了 method 的角色

remaining / used_pct / method / valid / scenario / lower_limit 六個欄位全部消失。 而它們分別是 dc-14 / dc-14 / dc-14 / dc-15 / dc-16 / dc-18 的貢獻——五張卡的成果被一次覆蓋掉,而且 dc-19bdc-21dc-22 三張卡接的都是這個新版本。

valid 的消失最危險,因為它正是 dc-15 那條「錶失聯是 stale 不是 0」的載體,而 dc-19b 本週又用同一個欄位承載了第二種語意(公式適用域失效)。兩種 invalid 現在都沒有地方住。

收斂建議(一次做完,dc-23 動筆之前——它會是第九個實作者):

@dataclass(frozen=True)
class Dimension:
    name: str
    resource: Resource                    # power_kw | water | air_flow | thermal
    kind: Literal["power", "energy"]      # ★ dc-20:kWh 不能跟 kW 比
    unit: str
    value: Bound                          # ★ dc-15/17:帶誤差帶的值
    limits: list[Limit]                   # ★ dc-19/20:多上界 + basis;下界用 sense 表達
    method: Method
    scenario: Scenario = "normal"
    mode: Mode = Mode.MECHANICAL          # ★ dc-21
    status: Check = Check.SATISFIED       # ★ dc-19b:三態,取代 valid: bool
    invalid_reason: str | None = None     # "meter_stale" | "formula_out_of_domain"

    def binding_limit(self) -> Limit: ...        # dc-19:多上界取最小
    def remaining(self) -> Bound | None: ...     # 衍生,不存

lower_limit 不併進 limits,要用 Limit.sense = "upper" | "lower"——dc-18 講得很清楚:上界違反要減少負載,下界違反要減少在線設備,處置方向相反,min(limits) 會直接算錯。

🔴 2. dc-22 沒有用 CapacityReport,它發明了 RoomReport——而這次是對的

@dataclass
class RoomReport:
    heat_used_pct: float
    air_used_pct: float
    binding: dict
    bypass: float
    fan_kw: float
    assumed_return_air_c: float
    basis: str

前七次型別分岔都是漂移,這一次不是。AirBalance(bypass, recirculation, balance) 推導不出任何設備的銘牌——它是三個溫度算出來的房間屬性,沒有任何設備擁有它。CapacityReportentity_id 在這裡指向什麼?沒有答案。

所以這是模型第一次真的需要第二個層級:房間。 但需要它不代表可以放著兩個型別互相抄欄位:

@dataclass(frozen=True)
class RoomReport:
    room_id: str
    units: list[CapacityReport]        # ★ 引用而非複製設備層的報表
    air_balance: AirBalance            # ★ 只住在這一層
    assumed_return_air_c: float
    basis: Literal["measured", "assumed_containment"]

    def binding(self) -> dict[Resource, Dimension]:
        """設備層取 min,再與房間層的 air_flow 一起 per-resource 回傳。
        ★ 不可以 sum 設備層的 limit——共用靜壓箱耦合(aggregation 第五種)"""

邊界規則寫清楚:凡是「從三個以上設備的讀數推導、且不對應任何設備銘牌」的量,住 RoomReport;其餘住 CapacityReport。目前符合前者的只有 AirBalance——但 dc-25 冷熱通道封閉幾乎確定會再加幾個。

🔴 3. 「值 + 出處」家族第五次現身,而這次是同一週、同一個名字、三個不同欄位集

出處 定義
dc-19 Limit(value, basis, source, fetched_at)
dc-20 Limit(value, basis, source) — 少了 fetched_at
dc-19b Limit.basis="npsh_crossover"solved=True — 多了 solved,而型別沒重新定義

三張卡連續三天,同一個型別名,三個形狀。dc-21 又加了 clean_baseline(dp_kpa, flow, water_temp, measured_at)dc-19 另外有 RateConstraint(max_pct_per_min, source, commissioned_at)

時間欄位現在有四個名字、三種語意

fetched_at      取得時間     (dc-16 psu_policy、dc-19 Limit)
commissioned_at 建立基準時間 (dc-19 RateConstraint)
measured_at     建立基準時間 (dc-21 clean_baseline)   ← 與上一個同義,不同名
recovery_until  有效期終點   (dc-20 CapacityReport)

commissioned_atmeasured_at 是同一件事(這個基準是什麼時候建立的),而 fetched_at 是另一件事(這份資料是什麼時候抓的)。混用會讓「哪些 baseline 過期了」查不出來。

這正是 W36 #3 的 Sourced[T] 要解決的問題,而它現在有五個未合併的實例。 建議不變,只是把 Q5ownerremediation 一併加進 Limit——一次改,五處收。

🟡 4. Constraint 三態與 Dimension.valid: bool 正面衝突

dc-19b 立的三態(satisfied / violated / not_applicable)只定義在它自己的練習裡:

class Check(Enum):
    SATISFIED = "satisfied"; VIOLATED = "violated"; NOT_APPLICABLE = "not_applicable"

dc-14 定義、dc-15 首次使用的 Dimension.valid: bool 是兩態。兩者現在各自表達 invalid 的一半

  • valid=Falsedc-15):感測器失聯 → 該維度是 stale,不是 0
  • NOT_APPLICABLEdc-19b):感測器好好的,是公式不成立(HI 9.8 只在 v > 0.61 m/s 有效,VFD 降到 41% 流量以下就出了適用域)

壓成 bool 會在 VFD 低速時回報綠燈——而低流量正是實際運轉時間最長的工況。已在上面 #1 的 Dimension 收斂版裡合併成 status: Checkinvalid_reason

🟡 5. aggregation 從 3 種變 5 種,但仍是字串,且第五種沒有名字

sum            dc-12 分路
vector_sum     dc-14 delta 線間電流
parallel_pump  dc-19 並聯泵(系統曲線交點)
???            dc-20 多槽並聯?(卡片說「多容器」但沒定義聚合方式)
???            dc-22 共用靜壓箱(加機會拉低每台 limit)

dc-22 的加分題明寫這是「第五種,不是 sum」,但沒給名字也沒給實作。建議命名 shared_plenum,並且趁只有五種的時候把它從字串改成可註冊的策略

AGGREGATORS: dict[str, Callable[[list[Dimension], dict], Dimension]] = {}

def aggregator(name: str):
    def deco(fn): AGGREGATORS[name] = fn; return fn
    return deco

理由很實際:五種裡有三種parallel_pumpshared_plenum、以及 dc-20 尚未定義的那種)需要設備以外的上下文才算得出來(系統曲線、房間 AirBalance、槽的幾何)。純函數的 sum(...) 簽章裝不下它們,而現在改只要動五處。

🟡 6. Method 已經 9 個值,而且混了兩件正交的事(W36 #5 的延續,本週惡化)

nameplate | measured | pole_count | prefix_sum | outlet_count
| vector_sum | curve | ???(dc-19 要的「解交點」) | ???(dc-19b 的 solved)

dc-19 對資料模型 #1 明寫:「Methodcurve 要分得出『查曲線』與『解交點』」,而 dc-19bLimit.solved=True 表達了同一件事——兩張卡用兩個不同的欄位表達同一個區別。

其實只有兩個正交軸:

資料從哪來 怎麼算出來
nameplate / measured / vendor_curve / bms direct / sum / vector_sum / prefix_sum / solved
誰立的 dc-11 ~ dc-15 dc-13 / dc-14 / dc-18 / dc-19b

pole_countoutlet_count 其實是 nameplatedirectvector_summeasuredvector_sum拆成兩個欄位,9 個值降到 4 + 5,而且每一個組合都有意義。 但這是跨八張卡的重構——依照本週修正後的規律,它不會被採納,除非先有 topics/model.md。誠實記下這一點,不要第四次把它排進優先序然後第四次跳票。


優先序(本週刻意只排三項,且全部小於 30 分鐘):

  1. 建立 datacenter/topics/model.md,把 #1 的 Dimension 與 #2 的 RoomReport 貼進去,然後改 dc-daily-card 的練習模板指向它。 25 分鐘。排第一不是因為它最重要,是因為沒有它,下面兩項會跟前六項一樣在下週變成紅字。 這是本週唯一一個機制性的改動。
  2. dc-16 的 50.5% → 58.4%。 5 分鐘,第二次排進來。四處要改(第 70、128、198、209 行),順帶第 212 行那句「50.5% × 2 = 101% 已經超過單側容量」——它跟同段結論的 116.8% 自相矛盾,正確是 58.4% × 2 = 116.8%。加上不變式 used_pct(lose_b) == 2 × used_pct(normal)
  3. dc-09energy_kwh() 改名。 10 分鐘,連續第四週。承間隔複習那一節:它現在不只是改名,還牽到「電池該吐兩個 Dimension」。若這週再不做,就照 W36 說的降級成「已知缺陷」寫進 topics/model.md,從優先序上拿掉。連續四週排在前面卻不做的事,掛著只會讓整份清單失去可信度——而這份清單正是我們用來管理模型的唯一工具。

3 到 #6 本週不排。理由寫在 #6 最後一段:跨卡重構在目前的機制下不會發生,排了就是第五次跳票。先修機制(項目 1),下週再排它們。

本週該問 facility 的問題

五張卡共提出 15 個問題,去重後選 3 個下週真的拿去問人的。挑選標準沿用前六週:「現在問還來得及改,晚問就固化了」。本週三題的固化時點特別分明——土建澆置前/設備採購前/commissioning 當下,而且三者的順序就是它們變得不可逆的順序。

Q1 — 問 機電設計單位 + 土建/結構(🔴 最不可逆的一題,基礎澆下去就補不回來)

冷卻水泵的中心線標高,和冷卻水塔集水盤的「運轉水位」標高,各是多少?(要運轉水位,不是溢流水位) 泵是放在地面層還是上屋頂跟塔並排?如果是屋頂,吸入側做了集水坑或獨立吸水槽嗎? 吸入端裝的是普通壓力錶還是 compound gauge?量程下限多少? 冰水側的膨脹水箱接在泵的吸入側還是出口側?補水定壓幾 kPa?迴路最高點標高多少?

為什麼是這題,而且為什麼排第一dc-19b 算出同一顆泵、同一組型錄數字,放地面層最大流量 170.4%、放屋頂 100.5%。而 dc-18 解出的擾動水溫 35.8 °C 一代進去,屋頂配置的 margin 只剩 1.08 m,流量拉到 110% 就是 −0.50 m,直接汽蝕

四問各有各的不可逆程度:

  • 標高dc-19b 說得很直白——把 NPSHr 從 6.0 換到 4.5(換泵)只把上限推到 1.12;把泵搬下樓直接變 1.70。搬泵的機會只有一次。
  • 集水坑:ANSI/HI 9.8 算出需要的淹沒深度 S = 1.00 m,而冷水盤有效水深常只有 0.3–0.5 m。「接在盤底」這個做法本身不成立,而且加大喇叭口從 0.35 到 0.45 m 只買回 10 cm。
  • compound gauge:這是 dc-15 「錶失聯是 stale 不是 0」的孿生錯誤——這次錶是好的,是量程說不出危險。吸入端負壓時普通壓力錶讀 0,BMS 收到「正常」。換錶便宜,但要先知道現在裝的是哪一種。
  • 膨脹水箱接哪邊:接錯邊的後果是吸入絕對水頭 −14.6 m,物理上不可能,水在泵入口就閃蒸。這是接管拓撲的錯,不是設備的錯,圖上改比現場改便宜一個數量級。

這一題也是本軌跡第一次需要問「幾樓」而不是「接誰」,而那個資訊不在任何型錄裡。

Q2 — 問 IT 團隊 + 機電設計(必須兩邊一起問,分開問會得到兩個不衝突但不相干的答案)(⚠️ 設備選型前,決定全廠容量表的分母)

冰水供水設定值是多少?誰有權改它?機櫃進風溫度上限對應 ASHRAE 哪一個 class(A1–A4)? CRAH 選型表是按幾度回風選的?如果是 24 °C,那張表內建了旁通 43% 的假設——那個封閉是誰的工單? 型錄上的 sensible capacity 扣過風扇熱了嗎?ESP 設幾 Pa? 水路圖上有沒有 free cooling 板式 HX?integrated(串回水預冷)還是 non-integrated(旁通冰機)?

為什麼是這題,也為什麼四問必須一起問:因為它們是同一條溫度鏈上的四個點,而分屬兩個部門。

機櫃進風上限(IT / ASHRAE class)
   → 決定盤管選型(dc-22)
     → 決定冰水供水設定值 T_chws
       → 決定 free cooling 門檻濕球(dc-21:7 °C → 1 °C/18 °C → 12 °C)
         → 決定全年 free cooling 小時數

四個數字,各有各的驚人之處:

  • chws_setpoint:7 vs 18 °C 是 11 K 的槓桿,而塔加大只買得到 2 K。台北在 7 °C 冰水下是一年 0 小時。 而這個設定值的真正擁有者在 IT 側——dc-21 明寫:IT 把進風上限從 27 收到 22 °C 會砍掉整年 free cooling,而沒有任何一張設施表會顯示這件事發生過。
  • CRAH 選型回風溫度:24 °C 選型 → 那張表的分母是一間旁通 43% 的機房;29 °C 選型 → 設計時已假設封閉會做到位。兩者差 42% 的容量,而分界線是誰去裝盲板。
  • 風扇熱扣了沒:兩份型錄同樣寫 net sensible,一份已扣(Vertiv,14–15 kW)、一份未扣(Uptime 附錄 C,7.5 × 3 = 22.5 kW)。標 90 kW 的機實際 67.5 kW。 這一問決定同一份容量表要不要再打 75 折。
  • integrated vs non-integrated:決定 mode 是三值還是兩值,也決定切換時冰機在不在線——直接連到本週那條主連鎖。

這一題現在問還來得及影響盤管選型與設備台數;設備下單後,能改的只剩封閉品質。

Q3 — 問 控制系統承包商 / BMS 整合商(⚠️ commissioning 當下,事後沒有紀錄就永遠問不到)

BMS 的冰水流量變化率限制器設多少 %/min?誰在 commissioning 時定的、有沒有寫進控制序列文件? 板式 HX 的 clean ΔP baseline 有沒有量?當時的流量與水溫是多少? 儲冷槽的擴散器用 Fr ≤ 1.0 還是 Fr ≤ 0.5 選的?有沒有 CFD 驗收報告?報告裡 thermocline 幾 mm?溫度感測是幾點、間距多少、有沒有量 tilt? 模式切換的 enter / exit 濕球門檻各是多少?最短駐留時間設幾分鐘?

為什麼是這題:這四個數字有一個共同性質——它們不在任何銘牌上、不在任何型錄上,只在 commissioning 那幾天存在,而如果沒人寫下來就永遠消失了。

dc-21 把這件事講成了一個類別:「沒有 commissioning 產出就沒有告警規則」的欄位,本週湊到第三個(前兩個是 dc-09b 的電池 baseline、dc-19 的 rate limiter)。

各自的代價:

  • 流量變化率:來源分歧 10%/min vs 30%/min(Trane 說 30 在「舒適空調」可以,資料中心算不算舒適空調沒人說;JCI 說 10% 或更少、60 秒內、且必須連續調變)。1 212 gpm 從 100% 降到 40%,10%/min 要 4.0 分鐘、30%/min 只要 1.3 分鐘。設錯的後果是泵幾秒內掉下去 → 冰機低流量跳脫 → 10–15 分鐘才回得來,而 ride-through 只有 5.2 分鐘。一個銘牌上完全看不到的參數,能把整座機房打掉。
  • clean ΔP baseline:沒有它,髒污告警寫不出來。而且它必須是曲線不是單點——ΔP ∝ Q^1.8,70% 流量時期望值是 23.7 kPa 不是 45。拿 45 去比 70% 流量下的讀數,會把節流看成變乾淨。
  • Fr 判準:這一個選擇決定 binding 是誰(Fr 884 kW vs Re 1 116 kW),而兩者的改善動作相反——Fr 擋住可以加大開口,Re 擋住只能加長擴散器。選錯 basis,錢會花在改不動的地方。 感測點數則決定 dc-20 那條「熱損讓容量掉 8% 而 thermocline 一格沒動」的告警寫不寫得出來(只有頂底兩點就寫不出來)。
  • 遲滯與駐留enter_wb_c == exit_wb_c 時濕球在門檻附近抖動會讓冰機反覆起停,而每一次切換都開一個 10–15 分鐘的窗口。dc-21 的加分題建議把實際濕球時間序列餵進去數切換次數——那個差值就是冰機壽命。

這週沒選上、但別忘記的

  • 「我們是 VPF 還是一次側/二次側?若是 VPF,旁通閥最小流量設定值是多少、依據哪張廠商表的哪一列?」 真正想知道的是有沒有人算過部分負載那一段——min_flow負載的函數(線性下降、50% 觸底),寫成線性外推會在 30% 負載時開太小 → 低壓跳脫 → 長期凍裂管束。這是一個寫錯會弄壞硬體的欄位。
  • 「冰水泵、冷卻水泵、CRAH 風扇,哪些在 UPS 上?UPS 的容量報表有沒有把它們算進負載?」 掛三台 30 kW 泵 = UPS 負載 +5.6%、runtime 10 → 9.5 分鐘。而只掛泵不夠——CRAH 風扇不在 UPS 上,水冷了也送不進機櫃。
  • 「ride-through 目標是幾分鐘,basis 是哪一種?」 三方講的不是同一件事:業界慣例 10–15 分、冰機實測重啟時間、ASHRAE 15 分鐘變溫率反推。ride_through_target_s 必須記 basis,否則審查時三方各講各的都「有出處」。
  • 「濕度走 RH 還是露點?加濕/除濕集中在 DOAS 還是每台 CRAH 自己來?」 後者保證會出現一台加濕、另一台同時除濕(RH 是相對量,各處回風溫度不同)。而 ASHRAE 建議濕度下限跨版本差約 15 K 露點,2021 版的數字兩個二手來源還對不上——EnvelopeRule 必須帶 standard + edition + class。
  • W36 起就掛著、仍未問的:設計濕球用哪一年氣象資料哪個百分位、水塔廠商性能曲線、冰機冷凝器進水上限與最小負載、伺服器 PSU hot spare 政策、rack PDU 是 delta 還是 wye、每顆錶的 CT 變比與初期負載下的實際額定百分比、demand 用 fixed block 還是 rolling。
  • W35 起就掛著、仍未問的:busway 吊裝位置環境溫度與廠商降載曲線、A/B 兩台 RPP 是否同櫃/同吊架、鋰電室樓板承重上限(W33 起)、STS 波形記錄保存期。

節奏

5 張卡 / 5 個工作日(9/7 一 ~ 9/11 五),與 W36 並列為這條軌跡最平順的兩週:沒有空窗、沒有補寫、沒有拆卡、沒有重複。dc-19b 是刻意回補第一輪拆出的欠項,插隊規則(dc-19b 自註「優先度低於 dc-20」)被正確執行了——W35 立的「拆卡當下必須同時往 backlog 插入新項目」這條教訓,本週第一次看到它的回報。

但基礎設施這週有兩件事要記,而且第二件比第一件嚴重。

(一)兩天的卡沒進版控,原因不是 lock 是磁碟

dc-21(9/10)與 dc-22(9/11)都寫進了本機資料夾,但兩天都沒有 commit。原因是排程沙箱的 workspace 自 9/10 安裝 mkdocs 後磁碟寫滿(no space left on device),9/11 重試三次同一錯誤。兩天都沒有執行任何 git 指令、沒有殘留 lock 檔(本次檢查 .git/*.lock 確認乾淨)。

本份週報遇到的是同一個問題的下一階段:本次排程執行時,沙箱連 workspace 都起不來(useradd failed: cannot create directory),重試四次皆同一錯誤。所以本週報是用檔案工具直接寫進資料夾的,mkdocs build --strictgit commit 兩者都沒能執行。

需要在 Mac 本機補的三件事(一次做完):

cd ~/Desktop/side-projects/github-learn-log

# 1. 驗證字數(dc-22 的字數目前是估算值,沙箱兩天都跑不了)
wc -m datacenter/devices/plate-hx-free-cooling.md \
      datacenter/devices/crah-chilled-water.md \
      datacenter/weekly/2026-W37.md

# 2. 確認無 warning、無殘留 [[
mkdocs build --strict -d /tmp/sitebuild

# 3. 一次補上三天的產出(dc-21、dc-22、本週報)
git add -A
git commit -m "docs(dc): weekly review 2026-W37 + cards dc-21, dc-22"

之後 launchd 的 30 分鐘輪詢會自動 push。不要在沙箱裡 push。

機制性建議(跟 W36 那條「週報自檢」同一類)dc-daily-carddc-weekly-review 開工時應該先確認上一次的產出有沒有進版控git log -1 --format=%cd 對照最新卡片的 written_at),不一致就在輸出裡標紅。目前這個斷鏈是靠人讀 index.md 的紅字列發現的——而那列是三天前寫的,沒有任何東西會主動提醒。 這已經是我們自己的基礎設施第三次犯下卡片內容裡反覆警告的那種錯:失敗是靜默的,儀表板全綠。

(二)mkdocs.yml$$ 問題還在,而且本週又多了一張卡

9/10 發現、至今未修:mkdocs.yml 沒有 pymdownx.arithmatex,而 pdu-floor / sts-two-source-relationship / npsh-and-pump-placement / lib-fire-compliance / plate-hx-free-cooling 共 5 張卡 6 處用了 $$...$$在 CF Pages 上會印出字面字串——與當初 wikilink 完全同一類的坑。

本週新增的那一處在 dc-19bnpsh-and-pump-placement.md 第 46、48、70 行),也就是說發現問題的那一天,同一批卡片又製造了一個新實例。

修法是 mkdocs.ymlpymdownx.arithmatex: {generic: true}extra_javascript 掛 MathJax,但需本機 build 驗證後再動。在修好之前,dc-daily-card 應該把「不要用 $$,改用程式碼區塊寫公式」列進收尾檢查——dc-22 已經刻意全程避開,本份週報也是(本文所有公式都在 code block 或行內反引號裡)。


下週

  • 佇列下一張:dc-23 CRAC 精密空調(直膨式)。 同一個位置、同一組六格,但容量的自變數從「回風溫度 + EWT」換成「回風溫度 + 冷凝溫度」,且故障域從共用冰水環路變成每台自己一套冷媒迴路——故障域變小,但 ride-through 歸零(沒有水可以當熱電池)。這會是本軌跡第一次「冗餘變好但韌性變差」的取捨,值得跟 dc-18 那個「加冗餘反而讓事情變糟」並排寫。
  • dc-23 會是 Dimension 的第九個實作者。 連貫性檢視 #1 的收斂請在它動筆之前做完——現在 25 分鐘,dc-23 寫完再做就是九張卡一起改。而且依本週修正後的規律,做法是建 topics/model.md 並改練習模板,不是再寫一次可貼的 dataclass。
  • 冷卻鏈的拆卡預期(W36 的推論本週繼續成立):dc-19b 已經是第一次拆(設備本體 vs 安裝條件),而 dc-20 冒出的「水處理/退伍軍人桿菌合規」(制度,同 dc-09c)與 dc-18 的「冰機重啟時序」(時間軸,同 dc-05c)兩條線仍未在 backlog 裡佔位。建議現在就預留,不要等到寫的時候才發現六格裝不下。
  • ⚠️ commissioning 隨時可能開始。 本週為現場驗收單加了三項:(a) 冷卻水泵標高與冷水盤運轉水位實測dc-19b,錯了補不回一層樓)、(b) 板式 HX 的 clean ΔP baseline 含當時流量與水溫dc-21,沒有它髒污告警寫不出來)、(c) BMS 流量變化率限制器的設定值與設定依據dc-19,一個銘牌上看不見的參數能打掉整座機房)。連同 W32 ~ W36 的五份清單,這八份合起來就是現場驗收單。W35 建議整理成一頁帶去現場,W36 再提一次,本週第三次提——這件事的優先級應該高於下一張卡。
  • W38 的間隔複習:抽 W36 的卡(dc-14 ~ dc-18)+ W34 的卡(dc-09b ~ dc-10)。
  • 單線圖對照盤點仍未做(承 dc-17 ~ dc-22 共六張卡的註記)。排程任務手上沒有公司的單線圖,無法自動執行。dc-19b 讓這件事多了一個新需求:盤點時順便記下每個設備的標高,不是只記拓撲。