diff --git a/README.md b/README.md index 3f9aeea..aa8b930 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ ## 主な機能 -- 222項目の正規入力スキーマと方式別の表示・検証条件 +- 223項目の正規入力スキーマと方式別の表示・検証条件 - JSON入力とGradio Web UI - ダクト式セントラル空調、ルームエアコン、床下空調などの計算 - 暖冷房結果、8760時間系列、グラフ、計算ログの出力 diff --git a/apps/gradio/src/verification_app/form_model.py b/apps/gradio/src/verification_app/form_model.py index d3d7115..f539a8c 100644 --- a/apps/gradio/src/verification_app/form_model.py +++ b/apps/gradio/src/verification_app/form_model.py @@ -63,7 +63,7 @@ def visibility(self, values: Mapping[str, Any]) -> dict[str, bool]: def load_form_model( - version: str = "260809", + version: str = "260812", values: Mapping[str, Any] | None = None, ) -> FormModel: schema = load_input_schema(version) diff --git a/docs/calculation_differences.md b/docs/calculation_differences.md index d1e0591..0d14851 100644 --- a/docs/calculation_differences.md +++ b/docs/calculation_differences.md @@ -20,7 +20,7 @@ Verification Platform Nextは、建築研究所等の技術的協力のもと公 | --- | --- | | 建研本家 | `BRI-EES-House/pyhees` Ver.3.10、commit `d5224c4a01def00a8421bcd2fcc0d4b4a5b88644` | | 旧Verification Platform | Next移行時の基準commit `0f91ba8381df1b4960557b92b39339385cc9009f` | -| Verification Platform Next | ver.1.1.1、入力仕様 `260809` | +| Verification Platform Next | ver.1.1.1、入力仕様 `260812` | 建研本家の版は[`packages/pyhees-jjj/UPSTREAM.md`](../packages/pyhees-jjj/UPSTREAM.md)、 Nextの製品版は[`jjjexperiment/release.py`](../packages/pyhees-jjj/src/jjjexperiment/release.py) @@ -28,7 +28,7 @@ Nextの製品版は[`jjjexperiment/release.py`](../packages/pyhees-jjj/src/jjjex ## 3. 結論一覧 -| ID | 不具合候補・変更点 | 建研本家 | 旧Verification Platform | Next(入力仕様260809) | +| ID | 不具合候補・変更点 | 建研本家 | 旧Verification Platform | Next(入力仕様260812) | | --- | --- | --- | --- | --- | | BRI-01 | 冷房時の居室・非居室間の間仕切熱移動の符号 | `+Q_trs` | `+Q_trs` | 既定OFFは`+Q_trs`、①をONにすると全経路で`-Q_trs` | | BRI-02 | 全般換気なし時も区画別全般換気量を給気下限に使用 | 使用する | 使用する。最低風量直接入力時は過大値が拡大 | 既定OFFは建研式、②をONにすると換気下限と設備最低風量を分離 | @@ -95,7 +95,7 @@ L_{CS,i}+Q^{*}_{\mathrm{trs,prt},i}, ### 4.3 Nextの補正モード -新床下空調では、元の住宅負荷に含まれる断熱床経路を取り除くため、 +床下空調では、元の住宅負荷に含まれる断熱床経路を取り除くため、 床を通る符号付き熱流$\Delta L_{\mathrm{floor},i}$も同時に扱う。 ```math @@ -226,7 +226,7 @@ Nextでは、次の二つを別の物理量として扱う。 旧版との差は次のとおりである。 -| 項目 | 旧Verification Platform | Verification Platform Next(入力仕様260809) | +| 項目 | 旧Verification Platform | Verification Platform Next(入力仕様260812) | | --- | --- | --- | | 冷房時の間仕切熱移動 | 建研式の`+Q_trs` | ①OFFは同じ。ONは非床下・繰越・新床下すべて`-Q_trs` | | 全般換気なしの式(43)/(44)下限 | 区画別全般換気量を使用 | ②OFFは同じ。ONは区画別下限を0へ切替 | diff --git a/docs/underfloor_ac_input_guide.md b/docs/underfloor_ac_input_guide.md index eef5cc2..b313e62 100644 --- a/docs/underfloor_ac_input_guide.md +++ b/docs/underfloor_ac_input_guide.md @@ -1,93 +1,65 @@ -# 床下関連設定の入力ガイド +# 床下関連入力ガイド ## 1. この文書の目的 -この文書は、Verification Platform Next の「⑥ その他」にある床下関連項目を -入力する人のための操作ガイドである。計算式の設計根拠を説明する文書ではなく、 -次の判断を迷わず行えることを目的とする。 +この文書は、Verification Platform Next の「⑥ その他」にある床下関連項目について、 +どの設定がどの計算経路と数値に影響するかを説明する。 -- 床下を利用しない計算、建研方式の床下換気、新床下空調のどれを選ぶか -- 表示された入力値のうち、どれを変更する必要があるか -- 各入力がどの計算へ影響するか -- 同時に使用できない機能と、入力時の注意点 +詳細な計算式とExcel床下14との整合内容は、次の文書を参照する。 -数式、採用値、Excelとの比較結果は、次の資料を参照する。 - -- [床下を給気経路に用いる全館空調計算:7つの変更点](underfloor_ac_seven_changes.md) +- [床下空調の7つの変更点](underfloor_ac_seven_changes.md) - [床下計算とExcel床下14の整合結果](underfloor_ac_excel_alignment.md) - [床下空調7変更点の数式・採用値・設計検証台帳](underfloor_ac_seven_point_design_review.md) ## 2. 最初に選ぶ計算方式 -床下に関係する計算方式は、次の3通りである。 +床下に関係する計算方式は次の3通りである。 -| 計算したい内容 | 床下換気を評価 | 新床下空調を使用 | 備考 | +| 計算したい内容 | 「床下換気を評価する」 | 「床下空調を使用する」 | 計算経路 | |---|---:|---:|---| -| 床下を利用しない通常計算 | OFF | OFF | 床下関連の詳細入力は使用しない | +| 床下を利用しない通常計算 | OFF | OFF | 床下関連の補正を行わない | | 建研方式の床下換気 | ON | OFF | 外気を床下経由で導入することによる負荷補正 | -| 床下を給気経路に使う新床下空調 | OFF | ON | Excel床下14に対応するPass 1・Pass 2・地盤逐時計算 | +| 床下を空調給気経路として使用 | OFF | ON | Excel床下14に対応するPass 1・Pass 2・地盤逐時計算 | -「床下換気」と「新床下空調」は名前が似ているが、目的が異なる。 +「床下換気(建研方式)」と「床下空調(Verification Platform)」は別の計算である。 -- **床下換気(建研方式)**は、外気を床下空間経由で導入する換気方式を - 暖冷房負荷計算で評価する。 -- **新床下空調(Verification Platform)**は、熱源機からの空調空気を - 1階床下へ送り、床下から居室・非居室へ移動する熱を計算する。 +- 床下換気は、外気を床下経由で導入する換気方式を評価する。 +- 床下空調は、熱源機からの空調空気を1階床下へ送り、床下から居室・非居室へ + 移動する熱を評価する。 -新床下空調を使用する場合、内部では床下換気の面積割合を0%、床下空調の -利用面積割合を100%、床下空間を断熱区画内として扱う。したがって、 -床下換気側の面積割合と断熱チェックを新床下空調の条件設定には使用しない。 +床下空調をONにすると、内部では床下換気の利用面積を0%、床下空調の利用面積を +100%、床下空間を断熱区画内として扱う。したがって、床下換気側の面積割合と +断熱チェックは床下空調の条件設定には使用しない。 -## 3. 画面項目の関係 +## 3. 現在の画面構成 ```text ⑥ その他 ├─ 床下換気(建研方式) -│ ├─ 床下換気を評価する +│ ├─ 床下空間を経由して外気を導入する換気方式を評価する │ └─ ONのときだけ表示 -│ ├─ 外気が経由する床下の面積割合 -│ └─ 床下空間が断熱区画内にある +│ ├─ 外気が経由する床下の面積の割合 +│ └─ 床下空間の断熱 │ ├─ 全館空調の風量制御 │ └─ 熱源機の全体風量を設計風量に固定する │ -└─ 新床下空調(Verification Platform) - ├─ 新床下空調を使用する - └─ ONのときだけ表示 - ├─ 地盤表面熱伝達抵抗 R_g - └─ 補助定数を手動設定する - └─ ONのときだけ表示 - ├─ 地盤内の不易層温度 - ├─ 床板の熱貫流率 - └─ 基礎側面の線熱貫流率 φ - +├─ 床下空調(Verification Platform) +│ ├─ 床下空調を使用する +│ └─ ONのときだけ表示 +│ ├─ 床下空調の補助定数を手動設定する +│ └─ 手動設定ONのときだけ表示 +│ ├─ 地盤またはそれを覆う基礎の表面熱伝達抵抗 R_g +│ └─ 基礎側面の線熱貫流率 φ +│ (チェック項目の説明文に、不易層温度と床板熱貫流率の +│ 自動算定・固定採用方法を表示) +│ └─ 建研本家との比較設定 ├─ ① 冷房時の間仕切熱移動を物理的な符号に補正する └─ ② 全般換気なし時の給気風量下限を補正する ``` -親となるチェックをOFFにすると、その下の入力欄は非表示になる。入力欄が -見つからない場合は、先に親のチェック状態を確認する。 - -### 3.1 建研本家との比較設定 - -2つの項目はともに既定値がOFFであり、互いに独立している。 - -| 目的 | ① 間仕切熱移動 | ② 風量下限 | -|---|---:|---:| -| 建研本家と同じ入力で比較照合する | OFF | OFF | -| 物理的に正しいと判断した式と風量制御を使う | ON | ON | -| Excel床下14のGolden条件 | ON | 全般換気条件に応じて選択 | - -①は新床下専用ではない。ONにすると、非床下、過剰熱量持越し、新床下通常計算、 -新床下逐次計算のすべてで、冷房時の居室から非居室への熱流を冷房負荷から差し引く。 - -②は全般換気なしの場合だけ結果へ影響する。ONにすると、住宅の換気負荷は維持した -まま、式 (43)・式 (44)の熱源機側区画下限を0とし、暖冷房期の設備最低風量を -別に保証する。OFFでは建研本家と同じ区画別全般換気量下限を使用する。 - -数式と建研本家・旧Verification Platformとの差は -[建研本家・旧Verification Platformとの計算差分](calculation_differences.md)を参照する。 +親となるチェックがOFFのとき、その配下の入力欄は表示されない。 ## 4. 床下換気(建研方式) @@ -95,61 +67,64 @@ 建研付録D系の床下換気による暖冷房負荷補正を有効にする。 -- 通常の住宅計算で床下換気を評価しない場合:OFF -- 外気を床下経由で導入する換気方式を評価する場合:ON -- 新床下空調を使用する場合:OFF +- 通常計算:OFF +- 外気を床下経由で導入する換気方式:ON +- 床下空調:OFF -### 4.2 外気が経由する床下の面積割合 +### 4.2 外気が経由する床下の面積の割合 -床下換気を評価する場合に、外気が経由する床下部分の割合を百分率で入力する。 -入力値は0~100%の範囲として扱う。 +床下換気をONにした場合だけ使用する。入力範囲は0~100%である。 +床下空調の床下利用面積ではない。床下空調をONにした場合は内部で100%に固定する。 -- 初期値:100% -- 床下換気がOFFの場合:床下換気の負荷補正には使用しない -- 新床下空調の場合:この値ではなく、内部で床下空調利用面積100%を使用する - -### 4.3 床下空間が断熱区画内にある +### 4.3 床下空間の断熱 床下換気の負荷計算および助走時の床下温度条件に使用する。 - -- 断熱区画外:OFF -- 断熱区画内:ON -- 新床下空調:画面のチェックによらず、内部では断熱区画内に固定 +床下空調では画面の状態によらず、内部で断熱区画内に固定する。 ## 5. 全館空調の風量制御 -### 熱源機の全体風量を設計風量に固定する +「熱源機の全体風量を設計風量に固定する」は床下専用の設定ではない。 +ダクト式セントラル空調機全体の風量制御に影響する。 -この項目は床下専用ではない。ダクト式セントラル空調機全体の熱源機風量へ -影響する。 +- OFF:通常の風量制御 +- ON:暖房期は設計暖房風量、冷房期は設計冷房風量に固定し、中間期は0とする -- OFF:通常の風量制御を行う -- ON:暖房期は設計暖房風量、冷房期は設計冷房風量へ固定し、中間期は0とする +床下空調と同時に使用できるが、比較条件として固定する場合は、床下以外の +全館空調計算にも影響することに注意する。 -新床下空調と組み合わせることはできるが、床下だけでなく全館空調計算全体の -風量が変わるため、比較条件として意図的に固定する場合だけONにする。 +## 6. 床下空調(Verification Platform) -## 6. 新床下空調(Verification Platform) - -### 6.1 新床下空調を使用する +### 6.1 床下空調を使用する 床下を1階の給気経路として使用し、Excel床下14に対応する次の計算を有効にする。 1. 助走および地盤応答 -2. 元負荷に含まれる床損失の控除 +2. 元負荷に含まれる床熱損失の控除 3. 目標床下温度の算定 4. Pass 1による必要熱源出口温度の直接逆算 5. RAC能力・出口温度制約 6. Pass 2による実床下温度の順計算 7. 居室・非居室温度と地盤状態の更新 -反復計算や、床下温度の代わりに単純な前時刻値を使用する処理は行わない。 -地盤応答モデル内部で必要となる前時刻状態だけを逐次保持する。 +反復計算や、床下温度の代わりに単純な前時刻値を使う処理は行わない。 +地盤応答モデル内部で必要な前時刻状態だけを逐次保持する。 + +### 6.2 床下空調の補助定数を手動設定する + +このチェックは、ユーザーが直接変更できる2つの定数 $R_g$ と $\phi$ の採用方法を +切り替える。 + +| チェック | $R_g$ | $\phi$ | +|---|---|---| +| OFF(通常) | 既定値 0.15 (m²・K)/W | 地域区分と住宅の $Q$ 値から自動算定 | +| ON(検証用) | 表示されたUI入力値 | 表示されたUI入力値 | + +通常の計算ではOFFを推奨する。根拠のある試験条件やExcel床下14の固定条件を +再現する場合だけONにする。 -### 6.2 地盤またはそれを覆う基礎の表面熱伝達抵抗 +### 6.3 地盤またはそれを覆う基礎の表面熱伝達抵抗 $R_g$ -記号は $R_g$、単位は $\mathrm{(m^2\,K)/W}$ である。地盤応答と、床下から -地盤への熱移動に使用する。 +$R_g$ は、床下と地盤の熱移動および地盤応答に使用する。 $$ K_g @@ -157,129 +132,111 @@ K_g {1+\varphi_{A,0}/R_g} $$ -- 初期値:$0.15\ \mathrm{(m^2\,K)/W}$ -- 通常のExcel床下14条件:0.15のまま使用 -- 「補助定数を手動設定する」とは独立しており、新床下空調がONなら常に使用 +- 単位:$\mathrm{(m^2\,K)/W}$ +- 既定値:0.15 +- 手動設定OFF:既定値0.15を使用 +- 手動設定ON:UI入力値を使用 -根拠となる試験条件や別の仕様値がない限り、初期値から変更しない。 +### 6.4 基礎側面の線熱貫流率 $\phi$ -### 6.3 新床下空調の補助定数を手動設定する +$\phi$ は床下から外気への基礎側面熱損失に使用する。 -自動算定値ではなく、検証用の明示値を入力する場合にONにする。通常計算では -OFFを基本とする。Excel床下14の固定条件を明示的に再現する検証ではONとし、 -$\phi=0.846\ \mathrm{W/(m\,K)}$を使用する。 - -ただし、現行逐次計算で手入力値が実際に反映されるのは、基礎側面の -線熱貫流率$\phi$である。地盤内の不易層温度と床板の熱貫流率は、入力契約との -互換性のため表示を残しているが、現行逐次計算では自動値を使用する。 +$$ +K_{\mathrm{ex}}=\phi L_{\mathrm{uf}} +$$ -## 7. 補助定数の詳細 +- 単位:$\mathrm{W/(m\,K)}$ +- UIの初期表示値:0.846 +- 手動設定OFF:地域区分と住宅の $Q$ 値から自動算定 +- 手動設定ON:UI入力値を使用 -### 7.1 地盤内の不易層温度 +## 7. 画面から入力しない自動算定値・固定採用値 -記号は $\Theta_{g,\mathrm{avg}}$、単位は℃である。 +### 7.1 地盤内の不易層温度 $\Theta_{g,\mathrm{avg}}$ -- 画面初期値:15.7℃ -- 現行逐次計算:外気温度8760時間値の年間平均を自動算定して使用 -- 現在の画面入力値:計算結果には反映されない +不易層温度は、計算に使用する外気温8760時間値の年間平均として自動算定する。 +地域や気象ファイルと一体で決まるため、現在のUIには編集欄を設けない。 -15.7℃と自動算定値のどちらを正式仕様とするかは、計算仕様の変更として別途 -決定する。入力値を変えても結果が変わらないことは、現行仕様上の挙動である。 +内部JSONには後方互換のため `Theta_g_avg=15.7` が残るが、床下空調の逐次ソルバーは +この固定値を採用せず、実際の外気温系列から求めた年間平均を使用する。 ### 7.2 床板の熱貫流率 -床下計算では、目的の異なる2種類の値を使い分ける。 +床板の熱貫流率は目的により値が異なるため、単一のUI入力値を使用しない。 -| 用途 | 記号 | 現在の値・算定方法 | +| 用途 | 記号 | 採用方法 | |---|---|---| -| 元負荷に含まれる断熱床損失の控除 | $U_{s,\mathrm{vert}}$ | 地域区分と住宅の$Q$値から付録E式(4)で算定。基準ケースでは約0.542226 W/(m²・K) | -| 床下から室への実際の熱移動 | $U_s$ | 付録E式(1)の固定値2.223 W/(m²・K) | - -画面の初期値は2.223 W/(m²・K)だが、現行逐次計算ではこの入力欄を直接参照せず、 -上記2経路をコード側で分離している。したがって、画面値を変更しても計算結果は -変化しない。 - -### 7.3 基礎側面の線熱貫流率 +| 元負荷に含まれる断熱床経路の控除 | $U_{s,\mathrm{load}}$ | 地域区分と住宅の $Q$ 値から付録E式(4)により算定。標準条件では約0.542226 W/(m²・K) | +| 床下から室への実際の熱移動 | $U_{s,\mathrm{supply}}$ | 付録E式(1)の固定値 2.223 W/(m²・K) | -記号は $\phi$、単位は $\mathrm{W/(m\,K)}$ である。床下から外気への基礎側面 -熱損失に使用する。 +内部JSONには後方互換のため `U_s_vert=2.223` が残るが、床下空調の逐次ソルバーは +用途別の上記2値をコード内で明示的に使い分ける。現在のUIには編集欄を設けない。 -$$ -K_{\mathrm{ex}}=\phi L_{\mathrm{uf}} -$$ - -- 画面初期値:0.846 W/(m・K) -- 補助定数の手動設定がOFF:地域区分と住宅の$Q$値から自動算定 -- 補助定数の手動設定がON:画面入力値を使用 - -## 8. 代表的な入力例 +## 8. 代表的な設定例 ### 8.1 床下を利用しない通常計算 | 項目 | 設定 | |---|---:| | 床下換気を評価する | OFF | -| 新床下空調を使用する | OFF | -| 全体風量を設計風量に固定する | 検討条件に従う | +| 床下空調を使用する | OFF | -### 8.2 建研方式の床下換気を評価する +### 8.2 建研方式の床下換気 -| 項目 | 設定例 | +| 項目 | 設定 | |---|---:| | 床下換気を評価する | ON | -| 外気が経由する床下の面積割合 | 対象住宅の条件。全体なら100% | -| 床下空間が断熱区画内にある | 対象住宅の断熱区画に従う | -| 新床下空調を使用する | OFF | +| 外気が経由する床下の面積の割合 | 対象住宅の条件 | +| 床下空間の断熱 | 対象住宅の条件 | +| 床下空調を使用する | OFF | -### 8.3 Excel床下14の新床下空調条件 +### 8.3 Excel床下14の床下空調条件 | 項目 | 設定 | |---|---:| | 床下換気を評価する | OFF | -| 新床下空調を使用する | ON | -| ① 冷房時の間仕切熱移動を物理的な符号に補正する | ON | -| $R_g$ | 0.15 (m²・K)/W | +| 床下空調を使用する | ON | +| 冷房時の間仕切熱移動を物理的な符号に補正する | ON | | 補助定数を手動設定する | ON | -| 地盤内の不易層温度 | 15.7℃(現行逐次計算では自動算定値を使用) | -| 床板の熱貫流率 | 2.223 W/(m²・K)(現行逐次計算ではコード側で用途別に設定) | +| $R_g$ | 0.15 (m²・K)/W | | $\phi$ | 0.846 W/(m・K) | +| 不易層温度 | 外気温8760時間値から自動算定 | +| 元負荷控除用の床熱貫流率 | 地域区分と $Q$ 値から自動算定 | +| 床下から室への熱移動用の床熱貫流率 | 2.223 W/(m²・K) | -## 9. 同時使用できない設定 +## 9. 同時に使用できない設定 -新床下空調と「⑥-1. 過剰熱量持越し」の過剰熱量繰越計算は同時に使用できない。 -両方をONにすると、計算開始時に次の趣旨のエラーを表示する。 +床下空調と「過剰熱量持越し」の過剰熱量繰越計算は同時に使用できない。 +両方をONにすると、計算開始時に次のエラーを表示する。 ```text -新床下空調と過剰熱量繰越計算は同時に使用できません。 +床下空調と過剰熱量繰越計算は同時に使用できません。 どちらか一方を無効にしてください。 ``` -また、削除済みの旧入力`underfloor_air_conditioning_air_supply=2`をJSONから -直接指定することはできない。新床下空調は`change_underfloor_temperature=2` -に対応する画面チェックから選択する。 +削除済みの旧入力 `underfloor_air_conditioning_air_supply=2` をJSONから直接指定する +こともできない。床下空調は画面の「床下空調を使用する」から選択する。 -## 10. 計算実行後の確認 +## 10. 計算後の確認 計算後は次を確認する。 -1. 「計算入力」タブで、選択したチェックと数値が`input_data`へ入っていること -2. 「計算ログ」に「新・床下空調ロジックを使用」と表示されること -3. 暖房・冷房の年間結果と時系列出力が、比較対象の条件と一致していること -4. 設定を変えた比較では、計算条件名と出力マニフェストを保存すること +1. 「計算入力」タブに、選択したチェックと手動値が反映されていること +2. 「計算ログ」に「床下空調ロジックを使用」と表示されること +3. 暖房・冷房の年間結果と時系列出力が比較条件と一致していること +4. 手動設定した場合は、`R_g` と `phi` が保存された入力JSONに入っていること -`Theta_g_avg`または`U_s_vert`だけを変更して結果が変わらない場合は、異常ではなく -第7節に記載した現行の入力接続を確認する。$\phi$を変更した場合は、補助定数の -手動設定がONになっていることを確認する。 +不易層温度と床板熱貫流率はUI入力ではない。これらを確認するときは、気象ファイル、 +地域区分、$Q$ 値、および計算ログ・時系列出力を確認する。 ## 11. 入力判断に迷った場合 -通常は次の順に判断する。 +通常は次の順で判断する。 -1. 床下を給気経路として使用するか -2. 使用しない場合、建研方式の床下換気を評価するか -3. 新床下空調を使用する場合、$R_g$を初期値から変更する根拠があるか -4. $\phi$を自動算定ではなく固定値で検証する必要があるか -5. 全体風量を固定する比較条件か +1. 床下を空調給気経路として使うか +2. 使わない場合、建研方式の床下換気を評価するか +3. 床下空調を使う場合、$R_g$ と $\phi$ を既定・自動値から変更する根拠があるか +4. 全体風量を設計風量に固定する比較条件か -数式や採用値そのものを変更する必要がある場合は、この入力ガイドだけで判断せず、 -冒頭の設計・整合資料を参照し、数値回帰への影響を確認する。 +数式や採用値を変更する必要がある場合は、この入力ガイドだけで判断せず、 +床下空調の設計文書とExcel整合結果を参照し、数値回帰への影響を確認する。 diff --git "a/packages/pyhees-jjj/docs/\351\242\250\351\207\217\350\250\255\345\256\232_VAV_\350\250\210\347\256\227\343\203\253\343\203\274\343\203\210.md" "b/packages/pyhees-jjj/docs/\351\242\250\351\207\217\350\250\255\345\256\232_VAV_\350\250\210\347\256\227\343\203\253\343\203\274\343\203\210.md" index 49b1ba3..87f63c2 100644 --- "a/packages/pyhees-jjj/docs/\351\242\250\351\207\217\350\250\255\345\256\232_VAV_\350\250\210\347\256\227\343\203\253\343\203\274\343\203\210.md" +++ "b/packages/pyhees-jjj/docs/\351\242\250\351\207\217\350\250\255\345\256\232_VAV_\350\250\210\347\256\227\343\203\253\343\203\274\343\203\210.md" @@ -3,7 +3,7 @@ ## 1. この文書の目的 ダクト式セントラル空調の風量計算では、住宅の全般換気量、熱源機の設備最低風量、 -設計風量、VAV、風量上限、新床下空調が同じ計算系列へ入る。名称が似ていても +設計風量、VAV、風量上限、床下空調が同じ計算系列へ入る。名称が似ていても 意味は異なるため、本書では「どの設定が、どの計算ルートと出力に影響するか」を 表とフローで示す。 @@ -173,9 +173,9 @@ $$ 入力が正しければ、設備最低風量と設計風量の両方を満たす。最低風量が設計風量を 超える矛盾した入力は、上限を破って計算を続けず入力エラーとする。 -## 9. 新床下空調との関係 +## 9. 床下空調との関係 -新床下空調の逐次計算では、Excel床下14との数値契約に従い、区画別のVAV前配分を +床下空調の逐次計算では、Excel床下14との数値契約に従い、区画別のVAV前配分を 固定面積比で求める。通常経路の負荷依存配分 `change_supply_volume_before_vav_adjust` をそのまま渡すと、床下14 Goldenの年間値が 大きく変わることを確認している。 @@ -195,7 +195,7 @@ $$ | 全般換気なし・②ON・暖冷房期 | 合計風量が設備最低風量以上 | | 全般換気なし・②ON・中間期 | 合計風量・ファン電力とも0 | | 全般換気あり・中間期 | 熱源機が換気量を搬送 | -| 新床下空調 | Excel床下14に合わせ、固定面積比の配分を使用 | +| 床下空調 | Excel床下14に合わせ、固定面積比の配分を使用 | 関連資料は [最低風量・最低電力 直接入力](最低風量_最低電力_直接入力.md) と [風量設定・VAVの不具合修正メモ](風量設定_VAV_不具合修正メモ.md) を参照する。 diff --git a/packages/pyhees-jjj/src/jjjexperiment/inputs/climate_service.py b/packages/pyhees-jjj/src/jjjexperiment/inputs/climate_service.py index f5ee7fc..6be2950 100644 --- a/packages/pyhees-jjj/src/jjjexperiment/inputs/climate_service.py +++ b/packages/pyhees-jjj/src/jjjexperiment/inputs/climate_service.py @@ -33,10 +33,7 @@ def get_Theta_ex_d_t(self) -> Array8760: return Theta_ex_d_t def get_Theta_g_avg(self) -> float: - if (ufac := self._new_ufac) and ufac.explicit_constants: - return self._new_ufac.Theta_g_avg - else: - return algo.get_Theta_g_avg(self.get_Theta_ex_d_t()) + return algo.get_Theta_g_avg(self.get_Theta_ex_d_t()) def get_HCM_d_t(self) -> Array8760: H, C, M = dc.get_season_array_d_t(self.region) diff --git a/packages/pyhees-jjj/src/jjjexperiment/inputs/common.py b/packages/pyhees-jjj/src/jjjexperiment/inputs/common.py index 1bf341f..bbb13bd 100644 --- a/packages/pyhees-jjj/src/jjjexperiment/inputs/common.py +++ b/packages/pyhees-jjj/src/jjjexperiment/inputs/common.py @@ -79,7 +79,7 @@ class OuterSkin: # ▼ 床下空調利用時 r_A_ufac: Optional[float] = None """当該住戸において、床下空間全体の面積に対する 空調を供給する床下空間の面積の比 [-]""" - # NOTE: 新床下空調インプットによって決まる + # NOTE: 床下空調インプットによって決まる underfloor_insulation: bool = False """床下空間の断熱""" @@ -120,7 +120,7 @@ def from_dict(cls, data: dict) -> 'OuterSkin': if 'underfloor_insulation' in data: kwargs['underfloor_insulation'] = int(data['underfloor_insulation']) == 2 - # 新床下空調がオンの場合は、床下換気なし・床下断熱状態となります + # 床下空調がオンの場合は、床下換気なし・床下断熱状態となります if ( 'change_underfloor_temperature' in data and int(data['change_underfloor_temperature']) == 2 diff --git a/packages/pyhees-jjj/src/jjjexperiment/inputs/di_container.py b/packages/pyhees-jjj/src/jjjexperiment/inputs/di_container.py index e75973c..730ba4a 100644 --- a/packages/pyhees-jjj/src/jjjexperiment/inputs/di_container.py +++ b/packages/pyhees-jjj/src/jjjexperiment/inputs/di_container.py @@ -18,7 +18,7 @@ from jjjexperiment.v_supply_cap.inputs.v_supply_cap_dto import VSupplyCapDto # F24-04 過剰熱量繰越 from jjjexperiment.carryover_heat.inputs.carryover_heat_dto import CarryoverHeatDto -# F24-05 新床下空調 +# F24-05 床下空調 import jjjexperiment.underfloor_ac.inputs.common as ufac_input # F25-01 最小風量・最低電力 直接入力 import jjjexperiment.v_min_input.inputs.heating as v_min_heating_input @@ -102,7 +102,7 @@ def _validate_feature_inputs(self) -> tuple[bool, bool]: if removed_ufac_flg is not None and int(removed_ufac_flg) == 2: raise ValueError( 'underfloor_air_conditioning_air_supply=2 の旧床下空調計算は' - '削除されました。新床下空調を使用する場合は ' + '削除されました。床下空調を使用する場合は ' 'change_underfloor_temperature=2 を指定してください。' ) @@ -117,7 +117,7 @@ def _validate_feature_inputs(self) -> tuple[bool, bool]: ) if new_ufac_enabled and carry_over_enabled: raise ValueError( - '新床下空調と過剰熱量繰越計算は同時に使用できません。' + '床下空調と過剰熱量繰越計算は同時に使用できません。' 'どちらか一方を無効にしてください。' ) @@ -126,8 +126,8 @@ def _validate_feature_inputs(self) -> tuple[bool, bool]: def _update_underfloor_input(self, new_ufac_enabled: bool) -> None: """床下利用状態を入力辞書へ反映し、従来のログを出力する。""" if new_ufac_enabled: - print("新・床下空調ロジックを使用") - # 新床下空調 + print("床下空調ロジックを使用") + # 床下空調 self._input['r_A_ufac'] = 100.0 # [%] WG資料より print("r_A_ufac = 100.0 [%]") print("空調空気を床下を通して給気する") @@ -259,7 +259,7 @@ def provide_v_supply_cap_dto(self) -> VSupplyCapDto: def provide_carryover_heat_dto(self) -> CarryoverHeatDto: return CarryoverHeatDto.from_dict(self._get_root_input()) - # F24-05 新・床下空調 + # F24-05 床下空調 @singleton @provider def provide_underfloor_ac_input(self) -> ufac_input.UnderfloorAc: diff --git a/packages/pyhees-jjj/src/jjjexperiment/section4_2_jjj.py b/packages/pyhees-jjj/src/jjjexperiment/section4_2_jjj.py index 1795afc..1c1e6c9 100644 --- a/packages/pyhees-jjj/src/jjjexperiment/section4_2_jjj.py +++ b/packages/pyhees-jjj/src/jjjexperiment/section4_2_jjj.py @@ -47,7 +47,7 @@ # F24-4 過剰熱量繰越 from jjjexperiment.carryover_heat.inputs.carryover_heat_dto import CarryoverHeatDto import jjjexperiment.carryover_heat as jjj_carryover_heat -# F24-5 新床下空調 +# F24-5 床下空調 import jjjexperiment.underfloor_ac.section4_2_jjj as jjj_ufac_dc from jjjexperiment.underfloor_ac.section3_1_e_jjj import calc_Theta_uf_d_t_2023 @@ -2503,7 +2503,7 @@ def _get_new_underfloor_requested_temperatures(inputs: _NewUnderfloorRequestedTe Theta_uf_d_t_2023 = calc_Theta_uf_d_t_2023(*_ExpectedUnderfloorTemperatureInputs( L_star_H_d_t_i, L_star_CS_d_t_i, house.A_A, house.A_MR, house.A_OR, skin.r_A_ufac, V_dash_supply_d_t_i, Theta_ex_d_t, house.region)) - # 新床下空調-1st: θuf_supply を逆算(二分探索) + # 床下空調-1st: θuf_supply を逆算(二分探索) _, _, Theta_uf_supply_d_t = algo.calc_Theta( region=house.region, A_A=house.A_A, @@ -2569,7 +2569,7 @@ def _get_new_underfloor_supply_temperatures(inputs: _NewUnderfloorSupplyTemperat Theta_underfloor_supply_override_d_t = ( inputs.Theta_underfloor_supply_override_d_t ) - # 新床下空調-2nd: θuf の本計算 + # 床下空調-2nd: θuf の本計算 Theta_uf_d_t, Theta_g_surf_d_t, *others = algo.calc_Theta( region=house.region, A_A=house.A_A, diff --git a/packages/pyhees-jjj/src/jjjexperiment/underfloor_ac/inputs/common.py b/packages/pyhees-jjj/src/jjjexperiment/underfloor_ac/inputs/common.py index 19eb7e8..d222f93 100644 --- a/packages/pyhees-jjj/src/jjjexperiment/underfloor_ac/inputs/common.py +++ b/packages/pyhees-jjj/src/jjjexperiment/underfloor_ac/inputs/common.py @@ -12,7 +12,8 @@ class UnderfloorAc: new_ufac_flg: 床下空調ロジック = 床下空調ロジック.変更しない - # NOTE: 従来 pyhees では上書き対象でない定数たち + # NOTE: Theta_g_avg と U_s_vert は旧入力JSONとの互換保持用。 + # 現行計算ではそれぞれ気象系列からの自動算定値と用途別U値を使用する。 """床下空調ロジック""" Theta_g_avg: float = 15.7 """地盤内の不易層の温度 [℃]""" @@ -38,8 +39,6 @@ def from_dict(cls, data: dict) -> 'UnderfloorAc': # 実行条件: 明示的な上書き宣言が必要 if 'input_ufac_consts' in data and int(data['input_ufac_consts']) == 2: kwargs['explicit_constants'] = True - kwargs['Theta_g_avg'] = float(data['Theta_g_avg']) - kwargs['U_s_vert'] = float(data['U_s_vert']) kwargs['phi'] = float(data['phi']) return cls(**kwargs) diff --git a/packages/pyhees-jjj/src/jjjexperiment/underfloor_ac/section3_1_e_jjj.py b/packages/pyhees-jjj/src/jjjexperiment/underfloor_ac/section3_1_e_jjj.py index 2698fde..caab207 100644 --- a/packages/pyhees-jjj/src/jjjexperiment/underfloor_ac/section3_1_e_jjj.py +++ b/packages/pyhees-jjj/src/jjjexperiment/underfloor_ac/section3_1_e_jjj.py @@ -26,7 +26,7 @@ def calc_sum_Theta_dash_g_surf_A_m_runup( state.commit(Theta_uf_const, response) return float(np.sum(response)) -#260112 IGUCHI 新床下空調用固定値 +#260112 IGUCHI 床下空調用固定値 @jjj_cloning def get_Theta_uf_d_t_runup( underfloor_insulation: bool, diff --git a/packages/pyhees-jjj/src/jjjexperiment/underfloor_ac/section4_2_f46_f48_jjj.py b/packages/pyhees-jjj/src/jjjexperiment/underfloor_ac/section4_2_f46_f48_jjj.py index 66aa954..7ba80c9 100644 --- a/packages/pyhees-jjj/src/jjjexperiment/underfloor_ac/section4_2_f46_f48_jjj.py +++ b/packages/pyhees-jjj/src/jjjexperiment/underfloor_ac/section4_2_f46_f48_jjj.py @@ -22,7 +22,7 @@ def get_Theta_HBR_i( ) -> Array5x1: """単時点版 (46-1)(46-2)(46-3) の床下空調 補正 """ - # TODO: 事前条件: 新床下空調ロジック 有効時のみ + # TODO: 事前条件: 床下空調ロジック 有効時のみ assert V_supply_i.shape == (5, 1), '想定外の行列数' assert Theta_supply_i.shape == (5, 1), '想定外の行列数' @@ -84,7 +84,7 @@ def get_Theta_NR( ) -> float: """単時点版 (48a)(48b) 床下空調 補正アリ """ - # TODO: 事前条件: 新床下空調ロジック 有効時のみ + # TODO: 事前条件: 床下空調ロジック 有効時のみ assert Theta_HBR_i.shape == (5, 1), '想定外の行列数' assert V_dash_supply_i.shape == (5, 1), '想定外の行列数' diff --git a/packages/pyhees-jjj/src/jjjexperiment/underfloor_ac/section4_2_f52_jjj.py b/packages/pyhees-jjj/src/jjjexperiment/underfloor_ac/section4_2_f52_jjj.py index b90c025..b7937cd 100644 --- a/packages/pyhees-jjj/src/jjjexperiment/underfloor_ac/section4_2_f52_jjj.py +++ b/packages/pyhees-jjj/src/jjjexperiment/underfloor_ac/section4_2_f52_jjj.py @@ -69,7 +69,7 @@ def get_Theta_star_NR( Returns: Theta_star_NR: 単時点版 負荷バランス時の非居室の室温 [℃] """ - # NOTE: 新床下空調ロジックのみで使用可能 + # NOTE: 床下空調ロジックのみで使用可能 # vectorize可能 c_p_air, rho_air, U_s = _get_formula_52_properties() diff --git a/packages/pyhees-jjj/src/pyhees/section3_1_e.py b/packages/pyhees-jjj/src/pyhees/section3_1_e.py index 9585abf..369fdbc 100644 --- a/packages/pyhees-jjj/src/pyhees/section3_1_e.py +++ b/packages/pyhees-jjj/src/pyhees/section3_1_e.py @@ -503,7 +503,7 @@ def calc_Theta(region, A_A, A_MR, A_OR, Q, r_A_ufvnt, underfloor_insulation, The Theta_in_H = 20 Theta_in_C = 27 - # NOTE: 既存コードにあったものを、新床下空調時 目標 Theta_uf の実行可否の閾値に再利用しています + # NOTE: 既存コードにあったものを、床下空調時 目標 Theta_uf の実行可否の閾値に再利用しています # 指数項mにおける吸熱応答係数 phi_1_A_m = np.array([get_phi_1_A_m(m) for m in range(1, M + 1)]) diff --git a/packages/pyhees-jjj/src/tests/inputs/test_di_validation_effect_contract.py b/packages/pyhees-jjj/src/tests/inputs/test_di_validation_effect_contract.py index cdc7cee..c7e2a8b 100644 --- a/packages/pyhees-jjj/src/tests/inputs/test_di_validation_effect_contract.py +++ b/packages/pyhees-jjj/src/tests/inputs/test_di_validation_effect_contract.py @@ -39,7 +39,7 @@ def test_new_underfloor_updates_ratio_and_preserves_log_order(capsys): assert module._input["r_A_ufac"] == 100.0 assert capsys.readouterr().out == ( - "新・床下空調ロジックを使用\n" + "床下空調ロジックを使用\n" "r_A_ufac = 100.0 [%]\n" "空調空気を床下を通して給気する\n" ) @@ -93,7 +93,7 @@ def test_feature_conflict_error_precedes_logs_and_mutation(capsys): before = deepcopy(data) with pytest.raises( - ValueError, match="新床下空調と過剰熱量繰越計算は同時に使用できません" + ValueError, match="床下空調と過剰熱量繰越計算は同時に使用できません" ): JJJExperimentModule(data) diff --git a/packages/pyhees-jjj/src/tests/inputs/test_input.yaml b/packages/pyhees-jjj/src/tests/inputs/test_input.yaml index ac6f6e3..35e0d14 100644 --- a/packages/pyhees-jjj/src/tests/inputs/test_input.yaml +++ b/packages/pyhees-jjj/src/tests/inputs/test_input.yaml @@ -15,7 +15,7 @@ eta_A_H: 4.3 TS: False r_A_ufvnt: null # [%] hs_CAV: False -change_underfloor_temperature: 1 # 新床下空調なし +change_underfloor_temperature: 1 # 床下空調なし R_g: 0.15 H_A: type: 1 diff --git a/packages/pyhees-jjj/src/tests/inputs/test_input_climate.py b/packages/pyhees-jjj/src/tests/inputs/test_input_climate.py index 56330f2..04cd1eb 100644 --- a/packages/pyhees-jjj/src/tests/inputs/test_input_climate.py +++ b/packages/pyhees-jjj/src/tests/inputs/test_input_climate.py @@ -80,7 +80,7 @@ def test_underfloor_constants_are_derived_when_not_explicit(): ) -def test_explicit_underfloor_constants_do_not_override_load_floor_u_value(): +def test_explicit_underfloor_constants_only_override_foundation_phi(): q = 2.647962191872085 climate = ClimateService( 6, @@ -92,9 +92,27 @@ def test_explicit_underfloor_constants_do_not_override_load_floor_u_value(): ), ) - assert climate.get_Theta_g_avg() == 14.1 + assert climate.get_Theta_g_avg() == pytest.approx( + 15.686130136986295, + abs=1e-12, + ) assert climate.get_U_s_vert(q) == pytest.approx( 0.5422264459110593, abs=1e-12, ) assert climate.get_phi(2.6) == 0.91 + + +def test_underfloor_input_only_accepts_editable_ground_constants(): + underfloor = UnderfloorAc.from_dict({ + "change_underfloor_temperature": 2, + "input_ufac_consts": 2, + "Theta_g_avg": 14.1, + "U_s_vert": 9.9, + "phi": 0.91, + }) + + assert underfloor.explicit_constants + assert underfloor.Theta_g_avg == 15.7 + assert underfloor.U_s_vert == 2.223 + assert underfloor.phi == 0.91 diff --git a/packages/pyhees-jjj/src/tests/test_dicontainer.py b/packages/pyhees-jjj/src/tests/test_dicontainer.py index 1f534d6..4677570 100644 --- a/packages/pyhees-jjj/src/tests/test_dicontainer.py +++ b/packages/pyhees-jjj/src/tests/test_dicontainer.py @@ -46,7 +46,7 @@ def test_new_underfloor_input_sets_only_new_underfloor_state(): def test_new_underfloor_and_carryover_fail_instead_of_falling_back(): - with pytest.raises(ValueError, match="新床下空調と過剰熱量繰越計算は同時に使用できません"): + with pytest.raises(ValueError, match="床下空調と過剰熱量繰越計算は同時に使用できません"): JJJExperimentModule(_underfloor_inputs( change_underfloor_temperature=床下空調ロジック.変更する.value, carry_over_heat=過剰熱量繰越計算.行う.value, diff --git a/packages/verification-core/src/verification_core/bindings.py b/packages/verification-core/src/verification_core/bindings.py index 070d2ab..3bc03bc 100644 --- a/packages/verification-core/src/verification_core/bindings.py +++ b/packages/verification-core/src/verification_core/bindings.py @@ -108,7 +108,7 @@ def _binding_from_dict(item: Mapping[str, Any]) -> InputBinding: ) -def load_input_bindings(version: str = "260809") -> InputBindingCatalog: +def load_input_bindings(version: str = "260812") -> InputBindingCatalog: file_name = f"input_bindings_{version}.json" data_file = resources.files("verification_core.data").joinpath(file_name) with data_file.open(encoding="utf-8") as stream: diff --git a/packages/verification-core/src/verification_core/data/input_bindings_260812.json b/packages/verification-core/src/verification_core/data/input_bindings_260812.json new file mode 100644 index 0000000..9352250 --- /dev/null +++ b/packages/verification-core/src/verification_core/data/input_bindings_260812.json @@ -0,0 +1,19 @@ +{ + "version": "260812", + "base_version": "260809", + "binding_count": 270, + "binding_overrides": [ + { + "line": 138, + "target_path": ["Theta_g_avg"], + "expression": "15.7", + "source_ids": [] + }, + { + "line": 141, + "target_path": ["U_s_vert"], + "expression": "2.223", + "source_ids": [] + } + ] +} diff --git a/packages/verification-core/src/verification_core/data/input_fields_260812.json b/packages/verification-core/src/verification_core/data/input_fields_260812.json new file mode 100644 index 0000000..be58956 --- /dev/null +++ b/packages/verification-core/src/verification_core/data/input_fields_260812.json @@ -0,0 +1,41 @@ +{ + "version": "260812", + "base_version": "260809", + "field_count": 223, + "remove_field_ids": [ + "Theta_g_avg__0", + "U_s_vert__0" + ], + "field_overrides": { + "underfloor_ventilation__0": { + "description": "建研付録D系の床下換気による負荷補正です。床下空調とは別の計算です。" + }, + "r_A_ufvnt__0": { + "description": "床下換気を評価する場合だけ使用します。床下空調の床下利用面積ではありません。" + }, + "underfloor_insulation__0": { + "description": "床下換気の負荷計算に使用します。床下空調では断熱区画内に固定されます。" + }, + "change_underfloor_temperature__0": { + "group": "床下空調(Verification Platform)", + "label": "床下空調を使用する", + "description": "Excel床下14に合わせたPass 1・Pass 2・地盤逐時計算を使用します。床下利用面積は100%、床下断熱は断熱区画内に固定されます。" + }, + "input_ufac_consts__0": { + "group": "床下空調(Verification Platform)", + "label": "床下空調の補助定数を手動設定する", + "description": "OFFではR_gに既定値0.15を使い、基礎側面の線熱貫流率φを地域区分とQ値から算定します。ONでは表示されるR_gとφを使用します。不易層温度は外気温8760時間値の年間平均から自動算定します。床板熱貫流率は、元負荷控除用を地域区分とQ値から算定し、床下から室への熱移動用を2.223 W/(m²・K)に固定します。" + }, + "R_g__0": { + "group": "手動設定する補助定数", + "description": "地盤応答と床下から地盤への熱移動に使用します。手動設定しない場合は既定値0.15 (m²・K)/Wを使用します。" + }, + "phi__0": { + "group": "手動設定する補助定数", + "description": "床下から外気への基礎側面熱損失に使用します。手動設定しない場合は地域区分とQ値から自動算定します。" + }, + "carry_over_heat__0": { + "description": "床下空調とは同時に使用できません。両方を有効にすると計算開始時にエラーになります。" + } + } +} diff --git a/packages/verification-core/src/verification_core/declarative_builder.py b/packages/verification-core/src/verification_core/declarative_builder.py index eb04b82..3d607d0 100644 --- a/packages/verification-core/src/verification_core/declarative_builder.py +++ b/packages/verification-core/src/verification_core/declarative_builder.py @@ -14,7 +14,7 @@ def build_input_data( values: Mapping[str, Any], - version: str = "260809", + version: str = "260812", ) -> dict[str, Any]: """Build input_data by applying the declarative binding catalog in source order.""" diff --git a/packages/verification-core/src/verification_core/legacy.py b/packages/verification-core/src/verification_core/legacy.py index 6097855..c95c7fa 100644 --- a/packages/verification-core/src/verification_core/legacy.py +++ b/packages/verification-core/src/verification_core/legacy.py @@ -91,7 +91,7 @@ def _field_from_dict(item: dict[str, Any]) -> LegacyFieldDefinition: ) -def load_legacy_inventory(version: str = "260809") -> LegacyInputInventory: +def load_legacy_inventory(version: str = "260812") -> LegacyInputInventory: file_name = f"input_fields_{version}.json" data_file = resources.files("verification_core.data").joinpath(file_name) with data_file.open(encoding="utf-8") as stream: diff --git a/packages/verification-core/src/verification_core/schema_loader.py b/packages/verification-core/src/verification_core/schema_loader.py index 2d14871..8151e4e 100644 --- a/packages/verification-core/src/verification_core/schema_loader.py +++ b/packages/verification-core/src/verification_core/schema_loader.py @@ -9,7 +9,7 @@ } -def load_input_schema(version: str = "260809") -> InputSchema: +def load_input_schema(version: str = "260812") -> InputSchema: inventory = load_legacy_inventory(version) return InputSchema.from_fields( _field_definition(field, inventory) diff --git a/tests/test_declarative_builder.py b/tests/test_declarative_builder.py index 9558973..7845bf3 100644 --- a/tests/test_declarative_builder.py +++ b/tests/test_declarative_builder.py @@ -36,6 +36,30 @@ def test_removed_legacy_underfloor_input_is_always_disabled() -> None: assert data["change_underfloor_temperature"] == "2" +def test_underfloor_automatic_values_are_not_editable_from_the_ui() -> None: + data = build_input_data({ + "Theta_g_avg__0": 9.9, + "U_s_vert__0": 9.9, + }) + + assert data["Theta_g_avg"] == 15.7 + assert data["U_s_vert"] == 2.223 + + +def test_underfloor_manual_ground_constants_use_ui_values() -> None: + data = build_input_data({ + "change_underfloor_temperature__0": True, + "input_ufac_consts__0": True, + "R_g__0": 0.2, + "phi__0": 0.9, + }) + + assert data["change_underfloor_temperature"] == "2" + assert data["input_ufac_consts"] == 2 + assert data["R_g"] == 0.2 + assert data["phi"] == 0.9 + + def test_partial_values_use_inventory_defaults() -> None: data = build_input_data({"case_name__0": "partial"}) diff --git a/tests/test_form_model.py b/tests/test_form_model.py index 1145ba6..f43739d 100644 --- a/tests/test_form_model.py +++ b/tests/test_form_model.py @@ -7,7 +7,7 @@ def test_form_model_preserves_schema_order_and_groups() -> None: model = load_form_model() - assert len(model.fields) == 225 + assert len(model.fields) == 223 assert len(model.sections) == 16 assert model.keys == tuple(field.key for field in model.schema.fields) assert all(section.groups for section in model.sections) @@ -77,7 +77,7 @@ def test_underfloor_manual_constants_follow_their_control() -> None: main_group = next( group for group in underfloor.groups - if group.name == "新床下空調(Verification Platform)" + if group.name == "床下空調(Verification Platform)" ) constants_group = next( group for group in underfloor.groups if group.name == "手動設定する補助定数" @@ -89,10 +89,10 @@ def test_underfloor_manual_constants_follow_their_control() -> None: ) assert tuple(field.key for field in constants_group.fields) == ( "R_g__0", - "Theta_g_avg__0", - "U_s_vert__0", "phi__0", ) + assert "Theta_g_avg__0" not in model.keys + assert "U_s_vert__0" not in model.keys values = model.schema.defaults() values["change_underfloor_temperature__0"] = True @@ -199,8 +199,6 @@ def test_form_model_updates_nested_underfloor_visibility() -> None: assert not initial["r_A_ufvnt__0"] assert not initial["R_g__0"] assert not initial["input_ufac_consts__0"] - assert not initial["Theta_g_avg__0"] - assert not initial["U_s_vert__0"] assert not initial["phi__0"] values["underfloor_ventilation__0"] = True @@ -209,24 +207,19 @@ def test_form_model_updates_nested_underfloor_visibility() -> None: assert ventilation["underfloor_insulation__0"] values["change_underfloor_temperature__0"] = True - new_underfloor = model.visibility(values) - assert not new_underfloor["R_g__0"] - assert new_underfloor["input_ufac_consts__0"] - assert not new_underfloor["Theta_g_avg__0"] + underfloor = model.visibility(values) + assert not underfloor["R_g__0"] + assert underfloor["input_ufac_consts__0"] values["input_ufac_consts__0"] = True constants = model.visibility(values) assert constants["R_g__0"] - assert constants["Theta_g_avg__0"] - assert constants["U_s_vert__0"] assert constants["phi__0"] values["change_underfloor_temperature__0"] = False hidden_parent = model.visibility(values) assert not hidden_parent["input_ufac_consts__0"] assert not hidden_parent["R_g__0"] - assert not hidden_parent["Theta_g_avg__0"] - assert not hidden_parent["U_s_vert__0"] assert not hidden_parent["phi__0"] @@ -338,5 +331,5 @@ def test_form_values_are_mapped_by_schema_order() -> None: def test_form_value_count_is_validated() -> None: model = load_form_model() - with pytest.raises(ValueError, match="Expected 225 form values, found 1"): + with pytest.raises(ValueError, match="Expected 223 form values, found 1"): model.values_from_sequence(("only-one",)) diff --git a/tests/test_gradio_app.py b/tests/test_gradio_app.py index b74bb1b..496ded4 100644 --- a/tests/test_gradio_app.py +++ b/tests/test_gradio_app.py @@ -48,6 +48,11 @@ def test_gradio_app_builds_all_schema_inputs_and_events() -> None: for component in config["components"] if component["type"] == "button" } + components_by_key = { + component["props"].get("key"): component + for component in config["components"] + if isinstance(component["props"].get("key"), str) + } def equipment_section(prefix: str) -> dict[str, object]: return next( @@ -59,7 +64,7 @@ def equipment_section(prefix: str) -> dict[str, object]: assert gradio.__version__.startswith("6.") assert config["title"] == "Verification Platform Next ver.1.1.1" assert component_types["accordion"] == 16 - assert component_types["number"] == 158 + assert component_types["number"] == 156 assert component_types["dropdown"] == 54 assert component_types["checkbox"] == 10 assert component_types["textbox"] == 4 # three text inputs and the log output @@ -95,11 +100,18 @@ def equipment_section(prefix: str) -> dict[str, object]: for value in html_values ) assert "変更した項目は濃い緑色で表示されます。" in markdown_values + manual_constants = components_by_key["field:input_ufac_consts__0"] + assert "不易層温度は外気温8760時間値の年間平均から自動算定" in ( + manual_constants["props"]["info"] + ) + assert "床下から室への熱移動用を2.223" in manual_constants["props"]["info"] + assert "field:Theta_g_avg__0" not in components_by_key + assert "field:U_s_vert__0" not in components_by_key assert "↩ 入力をデフォルトに戻す" in buttons assert buttons["↩ 入力をデフォルトに戻す"]["props"]["variant"] == "secondary" assert origin_classes == { "input-origin-bri-web": 47, - "input-origin-verification-platform": 178, + "input-origin-verification-platform": 176, } assert equipment_section("⑦-1")["props"]["visible"] is True assert equipment_section("⑧-1")["props"]["visible"] is True @@ -115,7 +127,7 @@ def equipment_section(prefix: str) -> dict[str, object]: dependencies = config["dependencies"] calculation_started, calculation, graph_generation = dependencies[:3] reset_inputs = next( - dependency for dependency in dependencies if len(dependency["outputs"]) == 233 + dependency for dependency in dependencies if len(dependency["outputs"]) == 231 ) install_default_highlights = next( dependency @@ -130,17 +142,17 @@ def equipment_section(prefix: str) -> dict[str, object]: assert calculation_started["queue"] is False assert len(calculation_started["inputs"]) == 0 assert len(calculation_started["outputs"]) == 10 - assert len(calculation["inputs"]) == 225 + assert len(calculation["inputs"]) == 223 assert len(calculation["outputs"]) == 6 assert len(graph_generation["inputs"]) == 1 assert len(graph_generation["outputs"]) == 7 assert len(visibility_dependencies) >= 14 assert 2 in {len(dependency["outputs"]) for dependency in visibility_dependencies} - assert 5 in {len(dependency["outputs"]) for dependency in visibility_dependencies} + assert 3 in {len(dependency["outputs"]) for dependency in visibility_dependencies} assert 78 in {len(dependency["outputs"]) for dependency in visibility_dependencies} assert 83 in {len(dependency["outputs"]) for dependency in visibility_dependencies} assert len(reset_inputs["inputs"]) == 0 - assert len(reset_inputs["outputs"]) == 233 + assert len(reset_inputs["outputs"]) == 231 assert len(install_default_highlights["inputs"]) == 0 assert len(install_default_highlights["outputs"]) == 0 assert install_default_highlights["queue"] is False @@ -152,10 +164,10 @@ def equipment_section(prefix: str) -> dict[str, object]: ) reset_outputs = reset_function() model = form_app.load_form_model() - assert tuple(update["value"] for update in reset_outputs[:225]) == tuple( + assert tuple(update["value"] for update in reset_outputs[:223]) == tuple( field.default for field in model.schema.fields ) - assert tuple(update["visible"] for update in reset_outputs[:225]) == tuple( + assert tuple(update["visible"] for update in reset_outputs[:223]) == tuple( field.visible for field in model.fields ) assert [update["visible"] for update in reset_outputs[-8:]] == [ diff --git a/tests/test_input_bindings.py b/tests/test_input_bindings.py index 74bec3e..41ad25f 100644 --- a/tests/test_input_bindings.py +++ b/tests/test_input_bindings.py @@ -24,6 +24,17 @@ def test_removed_legacy_underfloor_binding_is_fixed_disabled() -> None: assert binding.evaluate(default_ui_values()) == "1" +def test_automatic_underfloor_values_have_no_ui_sources() -> None: + catalog = load_input_bindings() + (ground_temperature,) = catalog.for_target("Theta_g_avg") + (floor_u_value,) = catalog.for_target("U_s_vert") + + assert ground_temperature.source_ids == () + assert ground_temperature.evaluate(default_ui_values()) == 15.7 + assert floor_u_value.source_ids == () + assert floor_u_value.evaluate(default_ui_values()) == 2.223 + + def test_correction_checkboxes_are_bound_to_both_seasons() -> None: catalog = load_input_bindings() values = default_ui_values() diff --git a/tests/test_legacy_inventory.py b/tests/test_legacy_inventory.py index 03881a5..8d27068 100644 --- a/tests/test_legacy_inventory.py +++ b/tests/test_legacy_inventory.py @@ -3,19 +3,19 @@ from verification_core import FieldKind, FieldOrigin, load_legacy_inventory -def test_260809_active_inventory_adds_opt_in_calculation_corrections() -> None: +def test_260812_active_inventory_adds_opt_in_calculation_corrections() -> None: inventory = load_legacy_inventory() - assert inventory.version == "260809" - assert len(inventory.fields) == 225 + assert inventory.version == "260812" + assert len(inventory.fields) == 223 assert inventory.category_counts == { - "基本設定": 46, + "基本設定": 44, "暖房": 86, "冷房": 91, "換気": 2, } assert len(inventory.section_names) == 16 - assert len({item.id for item in inventory.fields}) == 225 + assert len({item.id for item in inventory.fields}) == 223 assert "underfloor_air_conditioning_air_supply__0" not in { item.id for item in inventory.fields } @@ -24,8 +24,8 @@ def test_260809_active_inventory_adds_opt_in_calculation_corrections() -> None: for item in inventory.fields if item.id == "change_underfloor_temperature__0" ) - assert new_underfloor.label == "新床下空調を使用する" - assert new_underfloor.group == "新床下空調(Verification Platform)" + assert new_underfloor.label == "床下空調を使用する" + assert new_underfloor.group == "床下空調(Verification Platform)" assert "床下利用面積は100%" in new_underfloor.description ventilation_area = next( @@ -55,7 +55,7 @@ def test_260809_active_inventory_adds_opt_in_calculation_corrections() -> None: assert all(item.default is False for item in corrections.values()) -def test_260809_consolidates_related_general_sections() -> None: +def test_260812_consolidates_related_general_sections() -> None: inventory = load_legacy_inventory() fields = {item.id: item for item in inventory.fields} @@ -85,7 +85,7 @@ def test_260809_consolidates_related_general_sections() -> None: assert "⑨ 熱交換型換気設備)" not in inventory.section_names -def test_260809_has_independent_heating_and_cooling_efficiency_classes() -> None: +def test_260812_has_independent_heating_and_cooling_efficiency_classes() -> None: inventory = load_legacy_inventory() fields = { item.id: item @@ -126,13 +126,13 @@ def test_260809_has_independent_heating_and_cooling_efficiency_classes() -> None assert fields["C_A_mode__0"].source_name == "C_A_mode" -def test_260809_classifies_bri_web_and_verification_platform_inputs() -> None: +def test_260812_classifies_bri_web_and_verification_platform_inputs() -> None: inventory = load_legacy_inventory() fields = {item.id: item for item in inventory.fields} assert Counter(item.origin for item in inventory.fields) == { FieldOrigin.BRI_WEB: 47, - FieldOrigin.VERIFICATION_PLATFORM: 178, + FieldOrigin.VERIFICATION_PLATFORM: 176, } assert fields["A_A__0"].origin is FieldOrigin.BRI_WEB assert fields["H_A_input_V_hs_dsgn_H__0"].origin is FieldOrigin.BRI_WEB @@ -145,6 +145,17 @@ def test_260809_classifies_bri_web_and_verification_platform_inputs() -> None: ) +def test_260809_historical_inventory_remains_frozen() -> None: + inventory = load_legacy_inventory("260809") + + assert inventory.version == "260809" + assert len(inventory.fields) == 225 + fields = {item.id: item for item in inventory.fields} + assert fields["change_underfloor_temperature__0"].label == "新床下空調を使用する" + assert "Theta_g_avg__0" in fields + assert "U_s_vert__0" in fields + + def test_260804_historical_inventory_remains_frozen() -> None: inventory = load_legacy_inventory("260804") diff --git a/tests/test_schema_loader.py b/tests/test_schema_loader.py index 668f32b..0a5cf08 100644 --- a/tests/test_schema_loader.py +++ b/tests/test_schema_loader.py @@ -9,7 +9,7 @@ def test_input_schema_contains_all_inventory_fields() -> None: inventory = load_legacy_inventory() schema = load_input_schema() - assert len(schema.fields) == 225 + assert len(schema.fields) == 223 assert schema.defaults() == default_ui_values(inventory) assert {field.key for field in schema.fields} == { field.id for field in inventory.fields